https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82867
Bug ID: 82867 Summary: missing warning on buffer overflow assigning to the result of mempcpy Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: msebor at gcc dot gnu.org Target Milestone: --- This test case was inspired by Glibc bug https://sourceware.org/bugzilla/show_bug.cgi?id=22332. Although the mempcpy call in it doesn't overflow, the assignment via the pointer returned by it does. It seems that it should be possible to enhance the -Wstringop-overflow warning to detect this case (perhaps in tree-ssa-strlen.c?) even though the value of n is unknown, by saving the alloca/malloc argument for each allocated block. checking it against the mempcpy byte counter in assignments through the returned pointer, and diagnosing it if it's the same. $ cat c.c && gcc -O2 -S -Wall -Wextra -fdump-tree-strlen=/dev/stdout c.c void* f (const char *s0, const char *s1) { void *d = __builtin_malloc (s1 - s0); *(char*)__builtin_mempcpy (d, s0, s1 - s0) = '\0'; return d; } void sink (void*); void g (const char *s0, const char *s1) { void *d = __builtin_alloca (s1 - s0); *(char*)__builtin_mempcpy (d, s0, s1 - s0) = '\0'; sink (d); } ;; Function f (f, funcdef_no=0, decl_uid=1888, cgraph_uid=0, symbol_order=0) f (const char * s0, const char * s1) { void * d; long int s1.0_1; long int s0.1_2; long int _3; long unsigned int _4; void * _5; <bb 2> [100.00%] [count: INV]: s1.0_1 = (long int) s1_6(D); s0.1_2 = (long int) s0_7(D); _3 = s1.0_1 - s0.1_2; _4 = (long unsigned int) _3; d_10 = __builtin_malloc (_4); _5 = __builtin_mempcpy (d_10, s0_7(D), _4); MEM[(char *)_5] = 0; return d_10; } ;; Function g (g, funcdef_no=1, decl_uid=1895, cgraph_uid=1, symbol_order=1) g (const char * s0, const char * s1) { void * d; long int s1.4_1; long int s0.5_2; long int _3; long unsigned int _4; void * _5; <bb 2> [100.00%] [count: INV]: s1.4_1 = (long int) s1_6(D); s0.5_2 = (long int) s0_7(D); _3 = s1.4_1 - s0.5_2; _4 = (long unsigned int) _3; d_10 = __builtin_alloca (_4); _5 = __builtin_mempcpy (d_10, s0_7(D), _4); MEM[(char *)_5] = 0; sink (d_10); return; }