commit 1ace027335c9ca0ae400958aded936d04505ec86
parent b40f6d87482f20e968b27470baca042e50cd6792
Author: jvoisin <julien.voisin@dustri.org>
Date: Tue, 30 May 2023 20:46:14 +0200
Add a check for overlapping copies in strcpy
Diffstat:
4 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/include/string.h b/include/string.h
@@ -107,8 +107,15 @@ _FORTIFY_FN(strcat) char *strcat(char *__d, const char *__s)
_FORTIFY_FN(strcpy) char *strcpy(char *__d, const char *__s)
{
- size_t __b = __bos(__d, 0);
+ size_t __n = strlen(__s) + 1;
+
+ /* trap if pointers are overlapping but not if dst == src.
+ * gcc seems to like to generate code that relies on dst == src */
+ if ((__d < __s && __d + __n > __s) ||
+ (__s < __d && __s + __n > __d))
+ __builtin_trap();
+ size_t __b = __bos(__d, 0);
if (strlen(__s) + 1 > __b)
__builtin_trap();
return __orig_strcpy(__d, __s);
diff --git a/tests/Makefile b/tests/Makefile
@@ -13,6 +13,8 @@ TARGETS=test_memcpy_static_write \
test_memset_dynamic_write \
test_strcpy_static_write \
test_strcat_static_write \
+ test_strcpy_overwrite_over \
+ test_strcpy_overwrite_under\
.SILENT:
diff --git a/tests/test_strcpy_overwrite_over.c b/tests/test_strcpy_overwrite_over.c
@@ -0,0 +1,15 @@
+#include "common.h"
+
+#include <string.h>
+
+int main(int argc, char** argv) {
+ char buffer[9] = {'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', '\0'};
+ puts(buffer);
+
+ CHK_FAIL_START
+ strcpy(buffer+1, buffer);
+ CHK_FAIL_END
+
+ puts(buffer);
+ return ret;
+}
diff --git a/tests/test_strcpy_overwrite_under.c b/tests/test_strcpy_overwrite_under.c
@@ -0,0 +1,15 @@
+#include "common.h"
+
+#include <string.h>
+
+int main(int argc, char** argv) {
+ char buffer[9] = {'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', '\0'};
+ puts(buffer);
+
+ CHK_FAIL_START
+ strcpy(buffer-1, buffer);
+ CHK_FAIL_END
+
+ puts(buffer);
+ return ret;
+}