fortify-headers

standalone fortify-source implementation
git clone git://git.2f30.org/fortify-headers
Log | Files | Refs | README | LICENSE

commit cb1ce9e1815a492de0f13c2b046b8472024b9f6d
parent 58168afc8b2328c24137820c5fbe7c9775901944
Author: jvoisin <julien.voisin@dustri.org>
Date:   Wed, 14 Jun 2023 14:59:11 +0200

Add tests for strncpy and handle overlapping buffers there

Diffstat:
Minclude/string.h | 7++++++-
Mtests/Makefile | 33++++++++++++++++++---------------
Atests/test_strncpy_overwrite_over.c | 15+++++++++++++++
Atests/test_strncpy_overwrite_under.c | 15+++++++++++++++
Atests/test_strncpy_static_write.c | 16++++++++++++++++
5 files changed, 70 insertions(+), 16 deletions(-)

diff --git a/include/string.h b/include/string.h @@ -156,8 +156,13 @@ __access (write_only, 1) __access (read_only, 2, 3) _FORTIFY_FN(strncpy) char *strncpy(char *__d, const char *__s, size_t __n) { - size_t __b = __bos(__d, 0); + /* 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 (__n > __b) __builtin_trap(); return __orig_strncpy(__d, __s, __n); diff --git a/tests/Makefile b/tests/Makefile @@ -2,21 +2,24 @@ CC=../x86_64-linux-musl-native/bin/gcc GCOV=../x86_64-linux-musl-native/bin/gcov CFLAGS=-I../include/ -D_FORTIFY_SOURCE=3 -static -O2 -TARGETS=test_memcpy_static_write \ - test_memcpy_dynamic_write \ - test_memcpy_static_read \ - test_memcpy_dynamic_read \ - test_memmove_static_write \ - test_memmove_dynamic_write \ - test_memmove_static_read \ - test_memmove_dynamic_read \ - test_memset_static_write \ - test_memset_dynamic_write \ - test_strcpy_static_write \ - test_strcat_static_write \ - test_strcpy_overwrite_over \ - test_strcpy_overwrite_under\ - test_getcwd \ +TARGETS=test_memcpy_static_write \ + test_memcpy_dynamic_write \ + test_memcpy_static_read \ + test_memcpy_dynamic_read \ + test_memmove_static_write \ + test_memmove_dynamic_write \ + test_memmove_static_read \ + test_memmove_dynamic_read \ + test_memset_static_write \ + test_memset_dynamic_write \ + test_strcpy_static_write \ + test_strcat_static_write \ + test_strcpy_overwrite_over \ + test_strcpy_overwrite_under \ + test_strncpy_static_write \ + test_strncpy_overwrite_over \ + test_strncpy_overwrite_under \ + test_getcwd \ .SILENT: diff --git a/tests/test_strncpy_overwrite_over.c b/tests/test_strncpy_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 + strncpy(buffer+1, buffer, 5); + CHK_FAIL_END + + puts(buffer); + return ret; +} diff --git a/tests/test_strncpy_overwrite_under.c b/tests/test_strncpy_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 + strncpy(buffer-1, buffer, 5); + CHK_FAIL_END + + puts(buffer); + return ret; +} diff --git a/tests/test_strncpy_static_write.c b/tests/test_strncpy_static_write.c @@ -0,0 +1,16 @@ +#include "common.h" + +#include <string.h> + +int main(int argc, char** argv) { + char buffer[8] = {0}; + strncpy(buffer, "1234567", 5); + puts(buffer); + + CHK_FAIL_START + strncpy(buffer, "1234567890", 10); + CHK_FAIL_END + + puts(buffer); + return ret; +}