With pr78245 resolved, GCC diagnoses the buffer overflow in function f() below. The overflow in g() is also detected but only after the sprintf pass has transformed the call to memcpy, and not by the pass itself. The overflow in h() is not detected at all, (presumably) because the detection relies on the objsize pass which is limited to constant sizes. $ cat a.c && gcc -O2 -S -Wall a.c void* f (void) { char *p = __builtin_malloc (4); __builtin_sprintf (p, "%i", 12345); // overflow detected return p; } void* g (unsigned n) { if (4 < n) n = 4; char *p = __builtin_malloc (n); __builtin_sprintf (p, "%s", "12345"); // overflow detected return p; } void* h (unsigned n) { if (4 < n) n = 4; char *p = __builtin_malloc (n); __builtin_sprintf (p, "%i", 12345); // overflow not detected return p; } a.c: In function ‘f’: a.c:4:26: warning: ‘%i’ directive writing 5 bytes into a region of size 4 [-Wformat-overflow=] 4 | __builtin_sprintf (p, "%i", 12345); // overflow detected | ^~ a.c:4:3: note: ‘__builtin_sprintf’ output 6 bytes into a destination of size 4 4 | __builtin_sprintf (p, "%i", 12345); // overflow detected | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ a.c: In function ‘g’: a.c:13:3: warning: ‘__builtin_memcpy’ forming offset [4, 5] is out of the bounds [0, 4] [-Warray-bounds] 13 | __builtin_sprintf (p, "%s", "12345"); // overflow detected | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This seems fixed in GCC 11+: <source>: In function 'h': <source>:23:26: warning: '%i' directive writing 5 bytes into a region of size 4 [-Wformat-overflow=] 23 | __builtin_sprintf (p, "%i", 12345); // overflow not detected | ^~ <source>:23:3: note: '__builtin_sprintf' output 6 bytes into a destination of size 4 23 | __builtin_sprintf (p, "%i", 12345); // overflow not detected | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Fixed by r11-5622 (AKA PR middle-end/97373).