[Bug tree-optimization/94021] -Wformat-truncation false positive due to excessive integer range

2023-06-20 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94021

Andrew Pinski  changed:

   What|Removed |Added

 Status|NEW |RESOLVED
 Resolution|--- |FIXED
   Target Milestone|--- |13.0

--- Comment #11 from Andrew Pinski  ---
GCC 13:
  # RANGE [irange] int [0, 59] NONZERO 0x3f
  m_10 = _1 / 60;
  # RANGE [irange] int [0, 24] NONZERO 0x1f
  h_9 = _5 / 3600;

GCC 12:
  # RANGE [0, 59] NONZERO 63
  m_10 = _1 / 60;
  # RANGE [0, 596523] NONZERO 1048575
  h_9 = _5 / 3600;

And the warning is gone in GCC 13 too.

And produces:
/app/example.cpp:14: snprintfD.1756: 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, 2, 2, 2 (3, 3, 3, 3)
  Directive 3 at offset 6: "%02i"
Result: 2, 2, 2, 2 (5, 5, 5, 5)
  Directive 4 at offset 10: "", length = 1
  Substituting 5 for return value.

[Bug tree-optimization/94021] -Wformat-truncation false positive due to excessive integer range

2023-04-13 Thread ishikawa at yk dot rim.or.jp via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94021

--- Comment #10 from ishikawa,chiaki  ---
It would be great if the problem is fixed in later versions.
I observe the error with gcc-12 on my computer yet.

*BUT* compiling with -O instead of -O2 succeeds !?

gcc-12 version.

gcc-12 (Debian 12.2.0-14) 12.2.0
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

No error with -O !?

ishikawa@ip030:/NREF-COMM-CENTRAL/mozilla$ gcc-12 -c -O -Wall /tmp/pr94021.c

Error with -O2 as before.

ishikawa@ip030:/NREF-COMM-CENTRAL/mozilla$ gcc-12 -c -O2 -Wall /tmp/pr94021.c
/tmp/pr94021.c: In function ‘format_utc_offset’:
/tmp/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);
  | ^~~~
/tmp/pr94021.c:14:38: note: directive argument in the range [0, 59]
   14 | __builtin_snprintf (a, sizeof a, "%s%02i%02i", "+", h, m);
  |  ^~~~
/tmp/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);
  | ^
ishikawa@ip030:/NREF-COMM-CENTRAL/mozilla$

[Bug tree-optimization/94021] -Wformat-truncation false positive due to excessive integer range

2021-01-04 Thread amacleod at redhat dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94021

--- Comment #9 from Andrew Macleod  ---
(In reply to Jakub Jelinek from comment #6)
> CCing Andrew and Aldy to see what the ranger does or can do, talking about
>  I mean, if we have:
>   h_1 = x_2 / 3600;
>   if (x_2 <= -3599 && x_2 <= 8)
> use (h_1);
> figure out that h_1 is set to x_2 / 3600 and even when that
> SSA_NAME_DEF_STMT is not in a guarded block, its use is in one and so from
> the [-3599, 8] range of x_2 at the point of use derive that h_1 there is
> [0, 24]?
> Surely if it is like:
>   if (x_2 <= -3599 && x_2 <= 8)
> {
>   h_1 = x_2 / 3600;
>   use (h_1);
> }
> I'd expect it to handle it that way.


Certainly we get the latter case.  The earlier case is currently...
inconsistent.  Something I hope to address in the next release.

if we have precisely:
   h_1 = x_2 / 3600;
   if (x_2 <= -3599 && x_2 <= 8)
 use (h_1);
and if that is calculated in such a way that all of the conditions are
evaluated in a single basic block, then the GORI engine well mark h1 and x_2
both as exports and the evaluator will calculate the desired value for h_1.

Once we start to pull them further apart, the current implementation loses the
ability to recalculate h_1 when we get new ranges for x_2.

I have plans to segregate the def chains from the export lists in blocks, and
allow for greater ability to recalculate things like this.

When I look at #c4 in EVRP, I see:
=== BB 4 
 :
# x_10 = PHI 
h_15 = x_10 / 3600;
_1 = x_10 % 3600;
m_16 = _1 / 60;
h.0_2 = (unsigned int) h_15;
_3 = h.0_2 > 23;
_5 = _3;
if (_5 != 0)
  goto ; [INV]
else
  goto ; [INV]

_1 : int [0, 3599]
h.0_2 : unsigned int [0, 596523]
x_10 : int [0, +INF]
h_15 : int [0, 596523]
m_16 : int [0, 59]
4->6  (T) h.0_2 :   unsigned int [0, 596523]
4->6  (T) _5 :  _Bool [1, 1]
4->6  (T) x_10 :int [0, +INF]
4->6  (T) h_15 :int [0, 596523]
4->5  (F) h.0_2 :   unsigned int [0, 596523]
4->5  (F) _5 :  _Bool [0, 0]
4->5  (F) x_10 :int [0, +INF]
4->5  (F) h_15 :int [0, 596523]

and then later on:
=== BB 8 
x_10int [0, +INF]
 :
if (x_10 <= 8)
  goto ; [INV]
else
  goto ; [INV]

8->9  (T) x_10 :int [0, 8]
8->10  (F) x_10 :   int [9, +INF]

=== BB 9 
 :
__builtin_snprintf (, 8, "%s%02i%02i", "+", h_15, m_16);


The defchains already indicate that h_15 is dependant on the value of x_10, and
I am hoping to enable recalculation of h_15 when a dependant range has
changed.. and not just when they are exported from the same block.

 so in this case, when we ask for the range of h_15 in BB_9, we should be able
to see that x_10 has a range of int [0, 8] and trigger a recalculation of
h_15 using "current" values. and come up with h_15 = [0,24] 

The pieces are all there, but they need to be assembled in a non time consuming
way :-)

It is on the radar for next release.

[Bug tree-optimization/94021] -Wformat-truncation false positive due to excessive integer range

2020-12-17 Thread msebor at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94021

--- Comment #8 from Martin Sebor  ---
*** Bug 98281 has been marked as a duplicate of this bug. ***

[Bug tree-optimization/94021] -Wformat-truncation false positive due to excessive integer range

2020-03-04 Thread msebor at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94021

--- Comment #7 from Martin Sebor  ---
Since the merge with the sprintf pass, the strlen pass has an instance of EVRP
that it passes to sprintf to get range info from (it also uses it itself in
places).

[Bug tree-optimization/94021] -Wformat-truncation false positive due to excessive integer range

2020-03-04 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94021

Jakub Jelinek  changed:

   What|Removed |Added

 CC||aldyh at gcc dot gnu.org,
   ||amacleod at redhat dot com

--- Comment #6 from Jakub Jelinek  ---
CCing Andrew and Aldy to see what the ranger does or can do, talking about #c4.
So, we could:
--- gcc/match.pd.jj 2020-02-15 12:52:27.800034587 +0100
+++ gcc/match.pd2020-03-04 12:25:12.744289050 +0100
@@ -1551,11 +1551,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 /* X / C1 op C2 into a simple range test.  */
 (for cmp (simple_comparison)
  (simplify
-  (cmp (trunc_div:s @0 INTEGER_CST@1) INTEGER_CST@2)
+  (cmp (trunc_div@3 @0 INTEGER_CST@1) INTEGER_CST@2)
   (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
&& integer_nonzerop (@1)
&& !TREE_OVERFLOW (@1)
-   && !TREE_OVERFLOW (@2))
+   && !TREE_OVERFLOW (@2)
+   && single_use (@3))
(with { tree lo, hi; bool neg_overflow;
   enum tree_code code = fold_div_compare (cmp, @1, @2, , ,
   _overflow); }
and thus not optimize those
  h_1 = x_2 / 3600;
  h_1 <= 24;
and
  h_1 >= 0;
into
  x_2 <= 8;
and
  x_2 >= -3599;
because we have another h_1 use.  But, unfortunately that would pessimize the
case where there are multiple uses, but all of them can be optimized this way
(e.g. like that h_1 <= 24 and h_1 >= 0 uses), we'd keep a useless division.

I'd hope that with this optimization disabled or on #c5 ranger can handle the
testcase right (assuming the warning uses the ranger APIs), but the question is
can or could ranger handle even the case after this fold div compare
optimization?  I mean, if we have:
  h_1 = x_2 / 3600;
  if (x_2 <= -3599 && x_2 <= 8)
use (h_1);
figure out that h_1 is set to x_2 / 3600 and even when that SSA_NAME_DEF_STMT
is not in a guarded block, its use is in one and so from the [-3599, 8]
range of x_2 at the point of use derive that h_1 there is [0, 24]?
Surely if it is like:
  if (x_2 <= -3599 && x_2 <= 8)
{
  h_1 = x_2 / 3600;
  use (h_1);
}
I'd expect it to handle it that way.

[Bug tree-optimization/94021] -Wformat-truncation false positive due to excessive integer range

2020-03-04 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94021

Jakub Jelinek  changed:

   What|Removed |Added

 CC||jakub at gcc dot gnu.org

--- Comment #5 from Jakub Jelinek  ---
I don't understand why EVRP would be relevant, strlen pass runs after VRP1.
Anyway, I see two issues.  One general problem with SSA_NAME_RANGE_INFO
applying to SSA_NAME and thus it needs to cover ranges in all possible spots
the SSA_NAME is set or used, where during VRP where we have ASSERT_EXPRs we
find the right range but as it is just used in the bb guarded by the
conditional, there is nothing to stick it on (as compared to e.g. if the
sprintf was using h + 1 instead of h, where on the SSA_NAME holding h + 1 we
could add SSA_NAME_RANGE_INFO).  For this consider e.g.
 char a[8];

 void format_utc_offset (int x, int h)
 {
   if (x < 0)
 x = -x;

   int 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);
 }
where it warns too.  This is something that the value ranger work by
Andrew/Aldy could help with.
The other, on the #c4 case, is that match.pd seems to optimize e.g. the h <= 24
into x <= 24 * 3600 + 3599.  And that is really weird, because:
/* X / C1 op C2 into a simple range test.  */
(for cmp (simple_comparison)
 (simplify
  (cmp (trunc_div:s @0 INTEGER_CST@1) INTEGER_CST@2)
as it uses :s and so in my understanding shouldn't match because the h SSA_NAME
has multiple uses (e.g. is also used in the snprintf call).
And I bet this problem is what would prevent even the ranger for determining
something useful in this case.

[Bug tree-optimization/94021] -Wformat-truncation false positive due to excessive integer range

2020-03-03 Thread msebor at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94021

Martin Sebor  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  ---
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