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;

}

Reply via email to