From 089a6536d9830d90d39f3e9e36105c6b514c0f5c Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Fri, 20 Oct 2023 10:27:57 -0400 Subject: [PATCH 92/98] FIXME: more on c-c++-common/analyzer/strncat-1.c --- .../c-c++-common/analyzer/strncat-1.c | 137 +++++++++++++++++- 1 file changed, 134 insertions(+), 3 deletions(-) diff --git a/gcc/testsuite/c-c++-common/analyzer/strncat-1.c b/gcc/testsuite/c-c++-common/analyzer/strncat-1.c index 3db9383bfd72..82f25433ca1a 100644 --- a/gcc/testsuite/c-c++-common/analyzer/strncat-1.c +++ b/gcc/testsuite/c-c++-common/analyzer/strncat-1.c @@ -1,11 +1,142 @@ /* See e.g. https://en.cppreference.com/w/c/string/byte/strncat */ -extern char *strncat (char *dest, const char *src, size_t count); +/* { dg-additional-options "-Wno-stringop-overflow" } */ +/* { dg-additional-options "-fpermissive" { target c++ } } */ + +#include "../../gcc.dg/analyzer/analyzer-decls.h" + +typedef __SIZE_TYPE__ size_t; + +extern char *strncat (char *dst, const char *src, size_t count); extern char * -test_passthrough (char *dest, const char *src, size_t count) +test_passthrough (char *dst, const char *src, size_t count) +{ + char *result = strncpy (dst, src, count); + __analyzer_eval (result == dst); /* { dg-warning "TRUE" } */ + return result; +} + +char * +test_null_dst (const char *src, size_t count) +{ + return strncat (NULL, src, count); /* { dg-warning "use of NULL where non-null expected" } */ +} + +char * +test_null_src (char *dst, size_t count) +{ + return strncat (dst, NULL, count); /* { dg-warning "use of NULL where non-null expected" } */ +} + +char *test_unterminated_concrete_a (char *dst) +{ + char buf[3] = "abc"; /* { dg-warning "initializer-string for '\[^\n\]*' is too long" "" { target c++ } } */ + /* Should be OK to copy nothing. */ + return strncat (dst, buf, 0); /* { dg-bogus "" } */ +} + +char *test_unterminated_concrete_b (char *dst) +{ + char buf[3] = "abc"; /* { dg-warning "initializer-string for '\[^\n\]*' is too long" "" { target c++ } } */ + /* Should be OK as the count limits the accesses to valid + locations within src buf. */ + return strncat (dst, buf, 3); /* { dg-bogus "" } */ +} + +char *test_unterminated_concrete_c (char *dst) +{ + char buf[3] = "abc"; /* { dg-warning "initializer-string for '\[^\n\]*' is too long" "" { target c++ } } */ + /* Should warn: the count is one too high to limit the accesses + to within src buf. */ + return strncat (dst, buf, 4); /* { dg-warning "stack-based buffer over-read" } */ +} + +char *test_terminated_concrete_d (char *dst) +{ + char buf[6]; + __builtin_memset (buf, 'a', 3); + __builtin_memset (buf + 3, 'b', 3); + + /* Shouldn't warn. */ + return strncat (dst, buf, 6); /* { dg-bogus "" } */ +} + +char *test_unterminated_concrete_e (char *dst) +{ + char buf[6]; + __builtin_memset (buf, 'a', 3); + __builtin_memset (buf + 3, 'b', 3); + + /* Should warn. */ + return strncat (dst, buf, 7); /* { dg-warning "stack-based buffer over-read" } */ +} + +char *test_unterminated_symbolic (char *dst, size_t count) +{ + char buf[3] = "abc"; /* { dg-warning "initializer-string for '\[^\n\]*' is too long" "" { target c++ } } */ + return strncat (dst, buf, count); +} + +char *test_terminated_symbolic (char *dst, size_t count) +{ + const char *src = "abc"; + return strncat (dst, src, count); /* { dg-bogus "" } */ +} + +char *test_uninitialized_concrete_a (char *dst) +{ + char buf[16]; + return strncat (dst, buf, 0); /* { dg-bogus "" } */ +} + +char *test_uninitialized_concrete_b (char *dst) +{ + char buf[16]; + return strncat (dst, buf, 1); /* { dg-warning "use of uninitialized value" } */ +} + +char *test_initialized_concrete_c (char *dst) +{ + char buf[16]; + buf[0] = 'a'; + return strncat (dst, buf, 1); /* { dg-bogus "" } */ +} + +char *test_uninitialized_symbolic (char *dst, size_t count) +{ + char buf[16]; + return strncat (dst, buf, count); /* { dg-warning "use of uninitialized value" } */ +} + +// FIXME: from here, taken from strcpy-1.c and might need changing/removing + +void test_truncation_1 (const char *src) +{ + char buf[16]; + strncat (buf, src, 16); + /* buf might not be terminated (when strlen(src) > 16). */ + __analyzer_get_strlen (buf); /* { dg-warning "stack-based buffer over-read" "" { xfail *-*-* } } */ +} + +void test_truncation_2 (size_t count) +{ + char buf[16]; + strncat (buf, "abc", count); + /* buf might not be terminated (when count <= 3). */ + __analyzer_get_strlen (buf); /* { dg-warning "stack-based buffer over-read" "" { xfail *-*-* } } */ +} + +void test_too_big_concrete (void) +{ + char buf[10]; + strncat (buf, "abc", 128); /* { dg-warning "stack-based buffer overflow" } */ +} + +void test_too_big_symbolic (const char *src) { - return strncat (dest, src, count); + char buf[10]; + strncat (buf, src, 128); /* { dg-warning "stack-based buffer overflow" } */ } /* TODO: -- 2.49.0