[Bug tree-optimization/103835] bogus sprintf warnings due to missing strlen propagation

msebor at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Thu Jan 6 23:24:35 GMT 2022


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

--- Comment #5 from Martin Sebor <msebor at gcc dot gnu.org> ---
It's the same cause.  When the -Wformat-overflow and -truncation warnings are
unable to compute the exact length of a string argument to a directive like %s
they use the size of the array the string is stored in as a worst case estimate
(if they can determine the size of the array).  In other words, they assume the
string is as long as fits in the array (minus 1 for the terminating nul).  See
the example below.  In simple cases specifying a precision (e.g., "%.4s") to
constrain the amount of output can be used to avoid the potential overflow and
suppress the warning.  This is difficult to do with multiple string directives;
with those, using snprintf is the preferred alternative.  To avoid the
-Wformat-truncation warning for the equivalent snprintf calls it's necessary to
check the function's return value.

The sprintf pass keeps a running total of the ranges of the bytes formatted by
each directive, and the warning tries to strike a balance between providing too
little and too much detail to understand why it triggers.  This is tricky as
the range of total bytes on output includes the sum of more and more
directives.  We discussed various approaches to improve this some time ago (see
pr77696) but didn't converge on one that made everyone happy.

$ cat a.c && gcc -O2 -S -Wall a.c
char a[8], b[8];

void f (void)
{
  __builtin_sprintf (a, "%s%i", b, 123);
}
a.c: In function ‘f’:
a.c:5:28: warning: ‘%i’ directive writing 3 bytes into a region of size between
1 and 8 [-Wformat-overflow=]
    5 |   __builtin_sprintf (a, "%s%i", b, 123);
      |                            ^~
a.c:5:3: note: ‘__builtin_sprintf’ output between 4 and 11 bytes into a
destination of size 8
    5 |   __builtin_sprintf (a, "%s%i", b, 123);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The decision when to warn and when not is difficult.  All these warnings depend
on various optimizations, and those are never perfect.  The warnings make a few
basic assumptions (e.g., unreachable code is eliminated) and sometimes apply
heuristics like the string length above.  Both of these can lead to false
positives in addition to false negatives.


More information about the Gcc-bugs mailing list