https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88835
Martin Sebor <msebor at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW See Also| |https://gcc.gnu.org/bugzill | |a/show_bug.cgi?id=88844 Summary|[9 Regression] Maybe |overly aggressive |misleading |-Werror=format-overflow for |-Werror=format-overflow |printf since r265648 |since r265648 | Ever confirmed|0 |1 --- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> --- The warning can be reproduced in the (over)simplified test case below. There, it isn't strictly incorrect -- the upper bound of the width does allow the output to exceed INT_MAX. But it arguably is overly pedantic. The root cause in the readelf.i test case is the same: the width the warning sees is unbounded. But the warning there is a false positive because the width is clearly bounded. The width is computed in a loop like the one in pr88844 where GCC should be but is unable to determine the maximum number of iterations (bounded by the size of the integer argument). As a result of the width's upper bound being unknown it is taken as INT_MAX. Short of examining the loop and computing the range itself there isn't much the warning code can do to compensate for the poor range info it relies on. What it could and maybe should do is avoid using the upper bound at level 1 and instead use the lower bound. GCC 8 issues the same warning for calls to sprintf. It doesn't check printf and fprintf, so it doesn't diagnose the Binutils test case. r265648 extended the checking to those functions and exposed the underlying issues. As a result, even though I agree that the warning is overly aggressive, I don't consider this bug a regression. Let me look into relaxing it. $ cat pr88835.c && gcc -O2 -S -Wall -fdump-tree-printf-return-value=/dev/stdout pr88835.c void f (int n, int i) { if (n < 4) n = 4; if (i < 4) i = 4; __builtin_printf (" %*i", n, i); } ;; Function f (f, funcdef_no=0, decl_uid=1907, cgraph_uid=1, symbol_order=0) pr88835.c:8: __builtin_printf: objsize = 18446744073709551615, fmtstr = " %*i" Directive 1 at offset 0: " ", length = 1 Result: 1, 1, 1, 1 (1, 1, 1, 1) Directive 2 at offset 1: "%*i", width in range [4, 2147483647] pr88835.c: In function ‘f’: pr88835.c:8:23: warning: ‘%*i’ directive output between 4 and 2147483647 bytes may cause result to exceed ‘INT_MAX’ [-Wformat-overflow=] 8 | __builtin_printf (" %*i", n, i); | ^~~ pr88835.c:8:21: note: directive argument in the range [4, 2147483647] 8 | __builtin_printf (" %*i", n, i); | ^~~~~~ Result: 4, 2147483647, 2147483647, 2147483647 (5, 2147483648, 2147483648, 2147483648) Directive 3 at offset 4: "", length = 1 f (int n, int i) { <bb 2> [local count: 1073741824]: n_4 = MAX_EXPR <n_1(D), 4>; i_2 = MAX_EXPR <i_3(D), 4>; __builtin_printf (" %*i", n_4, i_2); return; }