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

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Severity|normal                      |enhancement

--- Comment #2 from Martin Sebor <msebor at gcc dot gnu.org> ---
This is true and as Richard explained in comment #1, the inconsistency is
unavoidable in general.  It is also documented in the manual:

When the exact number of bytes written by a format directive cannot be
determined at compile-time it is estimated based on heuristics that depend on
the level argument and on optimization. While enabling optimization will in
most cases improve the accuracy of the warning, it may also result in false
positives.

It's not possible to detect the exact same set of conditions at all
optimization levels by a warning that depends on optimization.

It may, however,  be possible to suppress the warnings at -O0 when the
directives' argument values are indeterminate and their ranges are unavailable,
and issue the warnings only for certain truncation.  That might be an
enhancement worth considering for GCC 8 (it's too late for GCC 7), perhaps
under a new level.

Until then (but even with this possible enhancement) the recommended solution
is to defensively allocate buffers that are sufficiently large for even the
largest argument values, or for %s, use precision, and for integer directives,
use the appropriate length modifiers to constrain the number of bytes output by
individual directives.  This holds true for both -Wformat-overflow and
-Wformat-truncation.  For the latter (and snprintf) specifically, the warnings
can also be avoided by checking the return value.  Calls to snprintf that don't
check their return value are often hidden bugs because subsequent code is
rarely prepared to deal with the truncation.

So for example, the first call to snprintf could be constrained to 4 bytes
(including the terminating NUL) like so:

  snprintf(buffer, 4, "%2hhd", val % 100);

This is 1 byte more than can actually be output by the call.  If that is
unacceptable then I would recommend disabling the warning at -O0 by specifying
-Wno-format-truncation.

Reply via email to