summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjvoisin2023-06-14 14:59:11 +0200
committerjvoisin2023-06-14 14:59:11 +0200
commitcb1ce9e1815a492de0f13c2b046b8472024b9f6d (patch)
tree77b3a8268151533ad4dc7acec73d25d2144cd991
parent58168afc8b2328c24137820c5fbe7c9775901944 (diff)
Add tests for strncpy and handle overlapping buffers there
-rw-r--r--include/string.h7
-rw-r--r--tests/Makefile33
-rw-r--r--tests/test_strncpy_overwrite_over.c15
-rw-r--r--tests/test_strncpy_overwrite_under.c15
-rw-r--r--tests/test_strncpy_static_write.c16
5 files changed, 70 insertions, 16 deletions
diff --git a/include/string.h b/include/string.h
index 9b6e601..f416a51 100644
--- a/include/string.h
+++ b/include/string.h
@@ -156,8 +156,13 @@ __access (write_only, 1)
156__access (read_only, 2, 3) 156__access (read_only, 2, 3)
157_FORTIFY_FN(strncpy) char *strncpy(char *__d, const char *__s, size_t __n) 157_FORTIFY_FN(strncpy) char *strncpy(char *__d, const char *__s, size_t __n)
158{ 158{
159 size_t __b = __bos(__d, 0); 159 /* trap if pointers are overlapping but not if dst == src.
160 * gcc seems to like to generate code that relies on dst == src */
161 if ((__d < __s && __d + __n > __s) ||
162 (__s < __d && __s + __n > __d))
163 __builtin_trap();
160 164
165 size_t __b = __bos(__d, 0);
161 if (__n > __b) 166 if (__n > __b)
162 __builtin_trap(); 167 __builtin_trap();
163 return __orig_strncpy(__d, __s, __n); 168 return __orig_strncpy(__d, __s, __n);
diff --git a/tests/Makefile b/tests/Makefile
index 2c4e067..80a4626 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -2,21 +2,24 @@ CC=../x86_64-linux-musl-native/bin/gcc
2GCOV=../x86_64-linux-musl-native/bin/gcov 2GCOV=../x86_64-linux-musl-native/bin/gcov
3CFLAGS=-I../include/ -D_FORTIFY_SOURCE=3 -static -O2 3CFLAGS=-I../include/ -D_FORTIFY_SOURCE=3 -static -O2
4 4
5TARGETS=test_memcpy_static_write \ 5TARGETS=test_memcpy_static_write \
6 test_memcpy_dynamic_write \ 6 test_memcpy_dynamic_write \
7 test_memcpy_static_read \ 7 test_memcpy_static_read \
8 test_memcpy_dynamic_read \ 8 test_memcpy_dynamic_read \
9 test_memmove_static_write \ 9 test_memmove_static_write \
10 test_memmove_dynamic_write \ 10 test_memmove_dynamic_write \
11 test_memmove_static_read \ 11 test_memmove_static_read \
12 test_memmove_dynamic_read \ 12 test_memmove_dynamic_read \
13 test_memset_static_write \ 13 test_memset_static_write \
14 test_memset_dynamic_write \ 14 test_memset_dynamic_write \
15 test_strcpy_static_write \ 15 test_strcpy_static_write \
16 test_strcat_static_write \ 16 test_strcat_static_write \
17 test_strcpy_overwrite_over \ 17 test_strcpy_overwrite_over \
18 test_strcpy_overwrite_under\ 18 test_strcpy_overwrite_under \
19 test_getcwd \ 19 test_strncpy_static_write \
20 test_strncpy_overwrite_over \
21 test_strncpy_overwrite_under \
22 test_getcwd \
20 23
21.SILENT: 24.SILENT:
22 25
diff --git a/tests/test_strncpy_overwrite_over.c b/tests/test_strncpy_overwrite_over.c
new file mode 100644
index 0000000..d584bcc
--- /dev/null
+++ b/tests/test_strncpy_overwrite_over.c
@@ -0,0 +1,15 @@
1#include "common.h"
2
3#include <string.h>
4
5int 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 strncpy(buffer+1, buffer, 5);
11 CHK_FAIL_END
12
13 puts(buffer);
14 return ret;
15}
diff --git a/tests/test_strncpy_overwrite_under.c b/tests/test_strncpy_overwrite_under.c
new file mode 100644
index 0000000..f554b28
--- /dev/null
+++ b/tests/test_strncpy_overwrite_under.c
@@ -0,0 +1,15 @@
1#include "common.h"
2
3#include <string.h>
4
5int 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 strncpy(buffer-1, buffer, 5);
11 CHK_FAIL_END
12
13 puts(buffer);
14 return ret;
15}
diff --git a/tests/test_strncpy_static_write.c b/tests/test_strncpy_static_write.c
new file mode 100644
index 0000000..e619288
--- /dev/null
+++ b/tests/test_strncpy_static_write.c
@@ -0,0 +1,16 @@
1#include "common.h"
2
3#include <string.h>
4
5int main(int argc, char** argv) {
6 char buffer[8] = {0};
7 strncpy(buffer, "1234567", 5);
8 puts(buffer);
9
10 CHK_FAIL_START
11 strncpy(buffer, "1234567890", 10);
12 CHK_FAIL_END
13
14 puts(buffer);
15 return ret;
16}