[Bug tree-optimization/104746] False positive for -Wformat-overflow=2 since r12-7033-g3c9f762ad02f398c

msebor at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Fri Mar 4 00:24:07 GMT 2022


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104746

--- Comment #8 from Martin Sebor <msebor at gcc dot gnu.org> ---
Andrew, quoting from the documentation for the warning:

  Unknown string arguments whose length cannot be assumed to be bounded either
by the directive’s precision, or by a finite set of string literals they may
evaluate to, or the character array they may point to, are assumed to be 1
character long. 

The length of the second string argument to the second sprintf call is assumed
to be bounded by the size of the array allocated by the first call to malloc. 
The malloc argument is at most 2147483654 (INT_MAX + strlen (".mount") + 1), so
the maximum length of the string is 2147483653.  That's also what the warning
prints.  The ability to determine and use the maximum length was added in
r12-7033 to avoid the warning reported in PR 104119.  Because GCC 11 doesn't
have this ability, it assumes the length of the string argument is 1, and so
the warning doesn't trigger there.  That could be considered a bug or
limitation in GCC 11.

The instance of the warning in the test case in comment #3 is designed point
out directives whose output may exceed the environmental limit of 4095 bytes
(the minimum the C standard requires implementations to support).  It's working
as designed and as intended.  If you don't like the design and want to propose
a change I suggest you submit a concrete proposal and we can discuss it.

As for my integer test from comment #7, you're right that if each argument was
in the range [0, 9] that the warning would be avoided.  I didn't get the limits
quite right.  A test case that should better illustrate the point I was making
about the constraints derived from relationships might go something like this:

char a[4];

void f (int i, int j)
{
  if (i < 0 || j < 0 || i + j > 19)
    return;

  __builtin_sprintf (a, "%u%u", i, j);
}

Here, setting the range of each of i and j on its own to [0, 19] isn't enough
to rule out a possible overflow; we also need to capture the constraint that if
one is two digits the other must be just one.  At the moment there is no logic
to determine that.  I think the corresponding test case for a possible
optimization is this:

void f (int i, int j)
{
  if (i < 0 || j < 0 || i + j > 19)
    return;

  if (i * j > 90)   // fold to false
    __builtin_abort ();
}


More information about the Gcc-bugs mailing list