https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94021
Martin Sebor <msebor at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|UNCONFIRMED |NEW
Keywords| |diagnostic
Last reconfirmed| |2020-03-03
Component|c |tree-optimization
CC| |msebor at gcc dot gnu.org
Blocks| |85741
Ever confirmed|0 |1
Summary|-Werror=format-truncation= |-Wformat-truncation false
|seems to cause incorrect |positive due to excessive
|warning, thus error. |integer range
Known to fail| |10.0, 9.2.0
--- Comment #4 from Martin Sebor <msebor at gcc dot gnu.org> ---
Confirmed with the small test case below. The warning code works correctly but
the integer conditionals are somehow confusing EVRP into thinking h's range is
[0, 596523], which causes the warning to trigger. The dump shows that the
warning thinks the result of the first %02i directive is between 2 and 6
characters:
Directive 2 at offset 2: "%02i"
Result: 2, 6, 6, 6 (3, 7, 7, 7)
$ cat pr94021.c && gcc -O2 -S -Wall -fdump-tree-strlen=/dev/stdout pr94021.c
char a[8];
void format_utc_offset (int x)
{
if (x < 0)
x = -x;
int h = x / 3600, m = (x % 3600) / 60;
if (h < 0 || h >= 24 || m < 0 || m >= 60)
__builtin_puts ("");
if (0 <= m && m <= 60 && 0 <= h && h <= 24)
__builtin_snprintf (a, sizeof a, "%s%02i%02i", "+", h, m);
}
;; Function format_utc_offset (format_utc_offset, funcdef_no=0, decl_uid=1931,
cgraph_uid=1, symbol_order=1)
;; 1 loops found
;;
;; Loop 0
;; header 0, latch 1
;; depth 0, outer -1
;; nodes: 0 1 2 3 4 5 6
;; 2 succs { 3 6 }
;; 3 succs { 6 }
;; 4 succs { 5 }
;; 5 succs { 1 }
;; 6 succs { 4 5 }
pr94021.c:14: __builtin_snprintf: objsize = 8, fmtstr = "%s%02i%02i"
Directive 1 at offset 0: "%s"
Result: 1, 1, 1, 1 (1, 1, 1, 1)
Directive 2 at offset 2: "%02i"
Result: 2, 6, 6, 6 (3, 7, 7, 7)
Directive 3 at offset 6: "%02i"
pr94021.c: In function ‘format_utc_offset’:
pr94021.c:14:45: warning: ‘%02i’ directive output may be truncated writing 2
bytes into a region of size between 1 and 5 [-Wformat-truncation=]
14 | __builtin_snprintf (a, sizeof a, "%s%02i%02i", "+", h, m);
| ^~~~
pr94021.c:14:38: note: directive argument in the range [0, 59]
14 | __builtin_snprintf (a, sizeof a, "%s%02i%02i", "+", h, m);
| ^~~~~~~~~~~~
Result: 2, 2, 2, 2 (5, 9, 9, 9)
Directive 4 at offset 10: "", length = 1
pr94021.c:14:5: note: ‘__builtin_snprintf’ output between 6 and 10 bytes into a
destination of size 8
14 | __builtin_snprintf (a, sizeof a, "%s%02i%02i", "+", h, m);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Moving the test for hours etc. being out-of-bounds after the test for them
being in-bounds avoids the warning (and streamlines the code so it seems like
an overall improvement).
Referenced Bugs:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85741
[Bug 85741] [meta-bug] bogus/missing -Wformat-overflow