diff options
| author | jvoisin | 2023-05-30 20:46:14 +0200 |
|---|---|---|
| committer | jvoisin | 2023-05-30 20:46:14 +0200 |
| commit | 1ace027335c9ca0ae400958aded936d04505ec86 (patch) | |
| tree | cedfb24733bffe35d070688ef5baee94ce90d997 | |
| parent | b40f6d87482f20e968b27470baca042e50cd6792 (diff) | |
Add a check for overlapping copies in strcpy
| -rw-r--r-- | include/string.h | 9 | ||||
| -rw-r--r-- | tests/Makefile | 2 | ||||
| -rw-r--r-- | tests/test_strcpy_overwrite_over.c | 15 | ||||
| -rw-r--r-- | tests/test_strcpy_overwrite_under.c | 15 |
4 files changed, 40 insertions, 1 deletions
diff --git a/include/string.h b/include/string.h index f08eb4c..8685bb7 100644 --- a/include/string.h +++ b/include/string.h | |||
| @@ -107,8 +107,15 @@ _FORTIFY_FN(strcat) char *strcat(char *__d, const char *__s) | |||
| 107 | 107 | ||
| 108 | _FORTIFY_FN(strcpy) char *strcpy(char *__d, const char *__s) | 108 | _FORTIFY_FN(strcpy) char *strcpy(char *__d, const char *__s) |
| 109 | { | 109 | { |
| 110 | size_t __b = __bos(__d, 0); | 110 | size_t __n = strlen(__s) + 1; |
| 111 | |||
| 112 | /* trap if pointers are overlapping but not if dst == src. | ||
| 113 | * gcc seems to like to generate code that relies on dst == src */ | ||
| 114 | if ((__d < __s && __d + __n > __s) || | ||
| 115 | (__s < __d && __s + __n > __d)) | ||
| 116 | __builtin_trap(); | ||
| 111 | 117 | ||
| 118 | size_t __b = __bos(__d, 0); | ||
| 112 | if (strlen(__s) + 1 > __b) | 119 | if (strlen(__s) + 1 > __b) |
| 113 | __builtin_trap(); | 120 | __builtin_trap(); |
| 114 | return __orig_strcpy(__d, __s); | 121 | return __orig_strcpy(__d, __s); |
diff --git a/tests/Makefile b/tests/Makefile index 9cca6f5..18f55fe 100644 --- a/tests/Makefile +++ b/tests/Makefile | |||
| @@ -13,6 +13,8 @@ TARGETS=test_memcpy_static_write \ | |||
| 13 | test_memset_dynamic_write \ | 13 | test_memset_dynamic_write \ |
| 14 | test_strcpy_static_write \ | 14 | test_strcpy_static_write \ |
| 15 | test_strcat_static_write \ | 15 | test_strcat_static_write \ |
| 16 | test_strcpy_overwrite_over \ | ||
| 17 | test_strcpy_overwrite_under\ | ||
| 16 | 18 | ||
| 17 | .SILENT: | 19 | .SILENT: |
| 18 | 20 | ||
diff --git a/tests/test_strcpy_overwrite_over.c b/tests/test_strcpy_overwrite_over.c new file mode 100644 index 0000000..924b346 --- /dev/null +++ b/tests/test_strcpy_overwrite_over.c | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | #include "common.h" | ||
| 2 | |||
| 3 | #include <string.h> | ||
| 4 | |||
| 5 | int main(int argc, char** argv) { | ||
| 6 | char buffer[9] = {'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', '\0'}; | ||
| 7 | puts(buffer); | ||
| 8 | |||
| 9 | CHK_FAIL_START | ||
| 10 | strcpy(buffer+1, buffer); | ||
| 11 | CHK_FAIL_END | ||
| 12 | |||
| 13 | puts(buffer); | ||
| 14 | return ret; | ||
| 15 | } | ||
diff --git a/tests/test_strcpy_overwrite_under.c b/tests/test_strcpy_overwrite_under.c new file mode 100644 index 0000000..2442470 --- /dev/null +++ b/tests/test_strcpy_overwrite_under.c | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | #include "common.h" | ||
| 2 | |||
| 3 | #include <string.h> | ||
| 4 | |||
| 5 | int main(int argc, char** argv) { | ||
| 6 | char buffer[9] = {'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', '\0'}; | ||
| 7 | puts(buffer); | ||
| 8 | |||
| 9 | CHK_FAIL_START | ||
| 10 | strcpy(buffer-1, buffer); | ||
| 11 | CHK_FAIL_END | ||
| 12 | |||
| 13 | puts(buffer); | ||
| 14 | return ret; | ||
| 15 | } | ||
