https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81437
Bug ID: 81437 Summary: missing -Wstringop-overflow reading past the end of a string Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: msebor at gcc dot gnu.org Target Milestone: --- GCC 8 diagnoses some non-trivial instances of reading past the end of an array but misses some of the most basic ones. For example, while it diagnoses past the end reads in memcpy when the size is a variable in a range whose lower bound causes the invalid access it fails to issue the same diagnostic when the variable is has a known value with the same effect. Similarly, no warning is issued for calls to strcpy whose where the source argument points past the terminating NUL of a string. $ cat a.c && gcc -O2 -S -Wall -Wextra -Wpedantic -fdump-tree-optimized=/dev/stdout a.c void f (char *d, unsigned n) { const char a[] = "123"; if (n < 1) n = 1; __builtin_memcpy (d, a + 4, n); // warning (ok) } void g (char *d, unsigned n) { const char a[] = "123"; n = 1; __builtin_memcpy (d, a + 4, n); // missing warning } void h (char *d) { const char a[] = "123"; __builtin_strcpy (d, a + 4); // missing warning } ;; Function f (f, funcdef_no=0, decl_uid=1816, cgraph_uid=0, symbol_order=0) Removing basic block 3 f (char * d, unsigned int n) { const char a[4]; unsigned int _2; long unsigned int prephitmp_9; <bb 2> [100.00%] [count: INV]: if (n_4(D) == 0) goto <bb 3>; [50.00%] [count: INV] else goto <bb 4>; [50.00%] [count: INV] <bb 3> [50.00%] [count: INV]: <bb 4> [100.00%] [count: INV]: # _2 = PHI <n_4(D)(2), 1(3)> prephitmp_9 = (long unsigned int) _2; __builtin_memcpy (d_5(D), &MEM[(void *)&a + 4B], prephitmp_9); [tail call] a ={v} {CLOBBER}; return; } a.c: In function ‘f’: a.c:5:3: warning: ‘__builtin_memcpy’ reading between 1 and 4294967295 bytes from a region of size 0 [-Wstringop-overflow=] __builtin_memcpy (d, a + 4, n); // warning (ok) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;; Function g (g, funcdef_no=1, decl_uid=1821, cgraph_uid=1, symbol_order=1) g (char * d, unsigned int n) { const char a[4]; unsigned char _5; <bb 2> [100.00%] [count: INV]: _5 = MEM[(char * {ref-all})&a + 4B]; MEM[(char * {ref-all})d_2(D)] = _5; a ={v} {CLOBBER}; return; } ;; Function h (h, funcdef_no=2, decl_uid=1825, cgraph_uid=2, symbol_order=2) h (char * d) { const char a[4]; <bb 2> [100.00%] [count: INV]: __builtin_strcpy (d_2(D), &MEM[(void *)&a + 4B]); [tail call] a ={v} {CLOBBER}; return; }