https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103835
Martin Sebor <msebor at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Summary|Bogus sprintf warnings |bogus sprintf warnings due | |to missing strlen | |propagation Blocks| |83819 --- Comment #3 from Martin Sebor <msebor at gcc dot gnu.org> --- The warnings in comment #0 are caused by a limitation of the strlen/sprintf passes: their less than perfect integration with the range (or constant) propagation machinery. The issue can be seen in the simplified test case below. In f() the constant strlen() result isn't propagated into the addition in d_5 = &a + n_4; at the time the warning runs (within the strlen pass), and so it triggers as expected. In g() it is propagated and the warning doesn't trigger. To avoid the warnings the strlen pass needs to set the range of strlen results and propagate them through the IL so they can be determined in computations in subsequent statements (like sprintf). $ cat pr103835.c && gcc -O2 -S -Wall -fdump-tree-strlen=/dev/stdout pr103835.c char a[8]; int f (void) { __builtin_strcpy (a, "f"); __SIZE_TYPE__ n = __builtin_strlen (a) + 1; char *d = a + n; __builtin_sprintf (d, "%s", a); return n; } int g (void) { __builtin_strcpy (a, "g"); __SIZE_TYPE__ n = __builtin_strlen ("g") + 1; char *d = a + n; __builtin_sprintf (d, "%s", a); return n; } ;; Function f (f, funcdef_no=0, decl_uid=1980, cgraph_uid=1, symbol_order=1) ;; 1 loops found ;; ;; Loop 0 ;; header 0, latch 1 ;; depth 0, outer -1 ;; nodes: 0 1 2 ;; 2 succs { 1 } pr103835.c:11: __builtin_sprintf: objsize = 6, fmtstr = "%s" Directive 1 at offset 0: "%s" Result: 1, 1, 1, 1 (1, 1, 1, 1) Directive 2 at offset 2: "", length = 1 pr103835.c: In function ‘f’: pr103835.c:11:2: warning: ‘__builtin_sprintf’ argument 3 may overlap destination object ‘a’ [-Wrestrict] 11 | __builtin_sprintf (d, "%s", a); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pr103835.c:1:6: note: destination object referenced by ‘restrict’-qualified argument 1 was declared here 1 | char a[8]; | ^ int f () { char * d; long unsigned int n; long unsigned int _1; int _7; <bb 2> [local count: 1073741824]: __builtin_memcpy (&a, "f", 2); _1 = 1; n_4 = _1 + 1; d_5 = &a + n_4; __builtin_strcpy (d_5, &a); _7 = (int) n_4; return _7; } ;; Function g (g, funcdef_no=1, decl_uid=1985, cgraph_uid=2, symbol_order=2) ;; 1 loops found ;; ;; Loop 0 ;; header 0, latch 1 ;; depth 0, outer -1 ;; nodes: 0 1 2 ;; 2 succs { 1 } pr103835.c:24: __builtin_sprintf: objsize = 6, fmtstr = "%s" Directive 1 at offset 0: "%s" Result: 1, 1, 1, 1 (1, 1, 1, 1) Directive 2 at offset 2: "", length = 1 Substituting 1 for return value. int g () { <bb 2> [local count: 1073741824]: __builtin_memcpy (&a, "g", 2); __builtin_strcpy (&MEM <char[8]> [(void *)&a + 2B], &a); return 2; } Referenced Bugs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83819 [Bug 83819] [meta-bug] missing strlen optimizations