Mercurial > hg > CbC > CbC_gcc
diff gcc/testsuite/c-c++-common/Wstringop-overflow.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gcc/testsuite/c-c++-common/Wstringop-overflow.c Thu Oct 25 07:37:49 2018 +0900 @@ -0,0 +1,158 @@ +/* PR middle-end/81117 - Improve buffer overflow checking in strncpy + { dg-do compile } + { dg-options "-O2 -Wstringop-overflow -Wno-stringop-truncation -ftrack-macro-expansion=0" } */ + +typedef __SIZE_TYPE__ size_t; + +#if __cplusplus +extern "C" { +#endif + +size_t strlen (const char*); +char* strncat (char*, const char*, size_t); +char* strncpy (char*, const char*, size_t); +#if __cplusplus +} +#endif + +const char ar[] = "123"; + +void test_strncat (char **d, const char* s, int i) +{ + /* Use a fresh pointer for each test to prevent the optimizer from + eliminating redundant writes into the same destination. Avoid + calling functions like sink() on the result that would have to + be assumed to change the source string by the alias oracle. */ +#define T(d, s, len) strncat (*d++, (s), (len)) + + T (d, "", 0); + T (d, "", 1); + T (d, "", 2); + T (d, "", 3); + T (d, "123", 0); + /* The following two calls truncate the copy and are diagnosed + by -Wstringop-truncation but there is evidence of overflow so + they're not diagnosed by -Wstringop-overflow. */ + T (d, "123", 1); + T (d, "123", 2); + + T (d, "123", 3); /* { dg-warning ".strncat\[^\n\r\]* specified bound 3 equals source length" } */ + T (d, "123", 4); + T (d, "123", 9); + + T (d, s, strlen (s)); /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */ + T (d, s, strlen (s) + 1); /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */ + /* The following could also be diagnosed by -Wstringop-truncation + (with some effort to distinguish the pattern from others like + the one above. */ + T (d, s, strlen (s) - 1); /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */ + T (d, s, strlen (s) - i); /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */ + + /* The following is dubious but not necessarily a smoking gun. */ + T (d, s, strlen (s) - strlen (s)); + + { + signed char n = strlen (s); /* { dg-message "length computed here" } */ + T (d, s, n); /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */ + } + + { + short n = strlen (s); /* { dg-message "length computed here" } */ + T (d, s, n); /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */ + } + + { + int n = strlen (s); /* { dg-message "length computed here" } */ + T (d, s, n); /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */ + } + + { + unsigned n = strlen (s); /* { dg-message "length computed here" } */ + T (d, s, n); /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */ + } + + { + size_t n; + n = strlen (s); /* { dg-message "length computed here" } */ + T (d, s, n); /* { dg-warning ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */ + } + + { + size_t n; + n = strlen (s) - 1; /* { dg-message "length computed here" } */ + T (d, s, n); /* { dg-message ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */ + } + + { + /* This doesn't overflow so iit should not be diagnosed. */ + size_t n = strlen (s) - strlen (s); + T (d, s, n); + } + + { + size_t n = i < strlen (s) ? i : strlen (s); /* { dg-message "length computed here" } */ + T (d, s, n); /* { dg-message ".strncat\[^\n\r\]* specified bound depends on the length of the source argument" } */ + } +} + + +void test_strncpy (char **d, const char* s, int i) +{ +#undef T +#define T(d, s, len) strncpy (*d++, (s), (len)) + + T (d, "", 0); + T (d, "", 1); + T (d, "", 2); + T (d, "", 3); + T (d, "123", 0); + T (d, "123", 1); + T (d, "123", 2); + T (d, "123", 3); + T (d, "123", 4); + T (d, "123", 9); + + T (d, "123", sizeof "123"); + T (d, ar, sizeof ar); + + T (d, s, strlen (s)); /* { dg-warning "\\\[-Wstringop-overflow=]" } */ + + { + int n = strlen (s); /* { dg-message "length computed here" } */ + T (d, s, n); /* { dg-warning "\\\[-Wstringop-overflow=]" } */ + } + + { + unsigned n = strlen (s); /* { dg-message "length computed here" } */ + T (d, s, n); /* { dg-warning "\\\[-Wstringop-overflow=]" } */ + } + + { + size_t n; + n = strlen (s); /* { dg-message "length computed here" } */ + T (d, s, n); /* { dg-warning "\\\[-Wstringop-overflow=]" } */ + } + + { + size_t n; + n = strlen (s) - 1; /* { dg-message "length computed here" } */ + T (d, s, n); /* { dg-warning "\\\[-Wstringop-overflow=]" } */ + } + + { + /* This is diagnosed by -Wstringop-truncation. Verify that it isn't + also diagnosed by -Wstringop-overflow. */ + size_t n = strlen (s) - strlen (s); + T (d, s, n); + } + + { + /* This use of strncpy is certainly dubious and it could well be + diagnosed by -Wstringop-truncation but it isn't. That it is + diagnosed with -Wstringop-overflow is more by accident than + by design. -Wstringop-overflow considers any dependency of + the bound on strlen(s) a potential bug. */ + size_t n = i < strlen (s) ? i : strlen (s); /* { dg-message "length computed here" } */ + T (d, s, n); /* { dg-message ".strncpy\[^\n\r]* specified bound depends on the length of the source argument" } */ + } +}