On 12/05/2016 08:43 PM, Martin Sebor wrote:
Martin
$ cat b.c && /build/gcc-78622/gcc/xgcc -B /build/gcc-78622/gcc -O2 -S
-Wall -Wextra -Wpedantic b.c
char d[1];
void f (int i)
{
if (i < 1024 || 1033 < i) i = 1024;
__builtin_sprintf (d + 1, "%hhi", i);
}
void g (int i)
{
if (i < 1024 || 3456 < i) i = 1024;
__builtin_sprintf (d + 1, "%hhi", i);
}
b.c: In function ‘f’:
b.c:7:30: warning: ‘%hhi’ directive writing 1 byte into a region of size
0 [-Wformat-length=]
__builtin_sprintf (d + 1, "%hhi", i);
^~~~
b.c:7:29: note: directive argument in the range [1024, 1033]
__builtin_sprintf (d + 1, "%hhi", i);
^~~~~~
b.c:7:3: note: format output 2 bytes into a destination of size 0
__builtin_sprintf (d + 1, "%hhi", i);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
b.c: In function ‘g’:
b.c:14:30: warning: ‘%hhi’ directive writing between 1 and 4 bytes into
a region of size 0 [-Wformat-length=]
__builtin_sprintf (d + 1, "%hhi", i);
^~~~
b.c:14:29: note: using the range [0, -128] for directive argument
__builtin_sprintf (d + 1, "%hhi", i);
^~~~~~
b.c:14:3: note: format output between 2 and 5 bytes into a destination
of size 0
__builtin_sprintf (d + 1, "%hhi", i);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gcc-78622.diff
PR middle-end/78622 - [7 Regression] -Wformat-length/-fprintf-return-value
incorrect with overflow/wrapping
gcc/ChangeLog:
PR middle-end/78622
* gimple-ssa-sprintf.c (min_bytes_remaining): Use res.knownrange
rather than res.bounded.
(adjust_range_for_overflow): New function.
(format_integer): Always set res.bounded to true unless either
precision or width is specified and unknown.
Call adjust_range_for_overflow.
(format_directive): Remove vestigial quoting. Always inform of
argument value or range when it's available.
(add_bytes): Correct the computation of boundrange used to
decide whether a warning is of a "maybe" or "defnitely" kind.
gcc/testsuite/ChangeLog:
PR middle-end/78622
* gcc.c-torture/execute/pr78622.c: New test.
* gcc.dg/tree-ssa/builtin-sprintf-2.c: Remove "benign" undefined
behavior inadvertently introduced in a previous commit. Tighten
up final checking.
* gcc.dg/tree-ssa/builtin-sprintf-5.c: Rename macros for clarity.
Add test cases.
* gcc.dg/tree-ssa/builtin-sprintf-6.c: Add test cases.
* gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Same.
* gcc.dg/tree-ssa/builtin-sprintf-warn-5.c: Same.
* gcc.dg/tree-ssa/builtin-sprintf-warn-6.c: Remove xfails and
add a final optimization check.
* gcc.dg/tree-ssa/builtin-sprintf.c: Add test cases.
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index 99a635a..a888f55 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -795,6 +795,59 @@ get_width_and_precision (const conversion_spec &spec,
*pprec = prec;
}
+/* With the range [*ARGMIN, *ARGMAX] of an integer directive's actual
+ argument, due to the conversion from either *ARGMIN or *ARGMAX to
+ the type of the directive's formal argument it's possible for both
+ to result in the same number of bytes or a range of bytes that's
+ less than the number of bytes that would result from formatting
+ some other value in the range [*ARGMIN, *ARGMAX]. This can be
+ determined by checking for the actual argument being in the range
+ of the type of the directive. If it isn't it must be assumed to
+ take on the full range of the directive's type.
+ Return true when the range has been adjusted to the range of
+ DIRTYPE, false otherwise. */
So I think the return value needs a bit of clarification here. Take
guidance from our discussion on this thread.
OK with that fixed.
jeff