public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug tree-optimization/109350] New: FAIL: g++.dg/warn/Wstringop-overflow-4.C
@ 2023-03-31 6:09 rguenth at gcc dot gnu.org
2023-03-31 6:35 ` [Bug tree-optimization/109350] " rguenth at gcc dot gnu.org
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: rguenth at gcc dot gnu.org @ 2023-03-31 6:09 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109350
Bug ID: 109350
Summary: FAIL: g++.dg/warn/Wstringop-overflow-4.C
Product: gcc
Version: 13.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: rguenth at gcc dot gnu.org
Target Milestone: ---
The
T (S (2), new int16_t[r_imin_imax + 1]); // { dg-bogus "into a region of
size" "pr106120" { xfail { ilp32 && c++98_only } } }
subtest now FAILs.
Reduced testcase:
#include "../../gcc.dg/range.h"
#define INT_MAX __INT_MAX__
#define INT_MIN (-INT_MAX - 1)
extern "C" char* strcpy (char*, const char*);
void sink (void*);
#define S36 "0123456789abcdefghijklmnopqrstuvwxyz"
#define S(N) (S36 + sizeof S36 - N - 1)
#define T(src, alloc) do { \
const char *s = src; \
char *d = (char*)alloc; \
strcpy (d, s); \
sink (d); \
} while (0)
#ifdef __INT16_TYPE__
// Hack around PR 92829.
#define XUR(min, max) \
(++idx, (vals[idx] < min || max < vals[idx] ? min : vals[idx]))
typedef __INT16_TYPE__ int16_t;
void test_strcpy_new_int16_t (size_t n, const size_t vals[])
{
size_t idx = 0;
int r_imin_imax = SR (INT_MIN, INT_MAX);
T (S (1), new int16_t[r_imin_imax]);
T (S (2), new int16_t[r_imin_imax + 1]); // { dg-bogus "into a region of
size" "pr106120" { xfail { ilp32 && c++98_only } } }
T (S (9), new int16_t[r_imin_imax * 2 + 1]);
}
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Bug tree-optimization/109350] FAIL: g++.dg/warn/Wstringop-overflow-4.C
2023-03-31 6:09 [Bug tree-optimization/109350] New: FAIL: g++.dg/warn/Wstringop-overflow-4.C rguenth at gcc dot gnu.org
@ 2023-03-31 6:35 ` rguenth at gcc dot gnu.org
2023-03-31 7:17 ` rguenth at gcc dot gnu.org
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: rguenth at gcc dot gnu.org @ 2023-03-31 6:35 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109350
Richard Biener <rguenth at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Keywords| |diagnostic
Blocks| |88443
--- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> ---
We have
<bb 2> [local count: 1073741824]:
_28 ={v} signed_value_source;
_4 = (unsigned long) _28;
_9 = _4 + 2147483648;
if (_9 > 4294967295)
goto <bb 8>; [50.00%]
else
goto <bb 3>; [50.00%]
<bb 3> [local count: 536870913]:
r_imin_imax_8 = (int) _28;
_31 = r_imin_imax_8 + 1;
_29 = (sizetype) _31;
if (_4 <= 4611686018427387900)
goto <bb 4>; [50.00%]
else
goto <bb 5>; [50.00%]
<bb 5> [local count: 268435458]:
_13 = operator new [] (18446744073709551615);
__builtin_memcpy (_13, &MEM <const char[37]> [(void
*)"0123456789abcdefghijklmnopqrstuvwxyz" + 35B], 2);
sink (_13);
if (_29 <= 4611686018427387900)
goto <bb 9>; [100.00%]
else
goto <bb 7>; [0.00%]
<bb 9> [local count: 0]:
iftmp.1_38 = _29 * 2;
_40 = operator new [] (iftmp.1_38);
__builtin_memcpy (_40, &MEM <const char[37]> [(void
*)"0123456789abcdefghijklmnopqrstuvwxyz" + 34B], 3);
and we're again down into get_size_range of the operator new[] argument
iftmp.1_38:
pointer-query.cc:507
/* Determine the largest valid range size, including zero. */
if (!get_size_range (qry, size, stmt, r, SR_ALLOW_ZERO | SR_USE_LARGEST))
return NULL_TREE;
where we compute
[irange] long unsigned int [0, 0] NONZERO 0x0$27 = void
for the range. I have to make up my mind if that's correct, but ranger
debug prints the same conclusion so it doesn't seem to be an artifact of
using legacy value_range.
Referenced Bugs:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88443
[Bug 88443] [meta-bug] bogus/missing -Wstringop-overflow warnings
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Bug tree-optimization/109350] FAIL: g++.dg/warn/Wstringop-overflow-4.C
2023-03-31 6:09 [Bug tree-optimization/109350] New: FAIL: g++.dg/warn/Wstringop-overflow-4.C rguenth at gcc dot gnu.org
2023-03-31 6:35 ` [Bug tree-optimization/109350] " rguenth at gcc dot gnu.org
@ 2023-03-31 7:17 ` rguenth at gcc dot gnu.org
2023-03-31 14:30 ` amacleod at redhat dot com
2023-03-31 20:47 ` amacleod at redhat dot com
3 siblings, 0 replies; 5+ messages in thread
From: rguenth at gcc dot gnu.org @ 2023-03-31 7:17 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109350
Richard Biener <rguenth at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |amacleod at redhat dot com
--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> ---
Hmm, the same reproduces with r_imin_imax as ptrdiff_t but the IL is a bit
more obvious:
<bb 2> [local count: 1073741824]:
_27 ={v} signed_value_source;
_4 = (unsigned long) _27;
_8 = _4 + 2147483648;
if (_8 > 4294967295)
goto <bb 8>; [50.00%]
else
goto <bb 3>; [50.00%]
<bb 3> [local count: 536870913]:
_30 = _27 + 1;
_28 = (sizetype) _30;
if (_4 <= 4611686018427387900)
goto <bb 4>; [50.00%]
else
goto <bb 5>; [50.00%]
<bb 5> [local count: 268435458]:
_12 = operator new [] (18446744073709551615);
__builtin_memcpy (_12, &MEM <const char[37]> [(void
*)"0123456789abcdefghijklmnopqrstuvwxyz" + 35B], 2);
sink (_12);
if (_28 <= 4611686018427387900)
goto <bb 9>; [100.00%]
else
goto <bb 7>; [0.00%]
<bb 9> [local count: 0]:
iftmp.2_37 = _28 * 2;
_39 = operator new [] (iftmp.2_37);
__builtin_memcpy (_39, &MEM <const char[37]> [(void
*)"0123456789abcdefghijklmnopqrstuvwxyz" + 34B], 3);
so we have (unsigned long)[int_min, int_max] > 4611686018427387900
&& (unsigned long)[int_min+1, int_max+1] <= 4611686018427387900 to
constrain _4. I don't see how we can arrive at [0,0] for iftmp.2_37.
In fact if I put this into a separate testcase like
void __attribute__((noipa))
foo (long signed_value_source)
{
unsigned long temu = signed_value_source;
if (temu + 2147483648 > 4294967295)
;
else
{
long tems = signed_value_source + 1;
unsigned long temu2 = tems;
if (temu > 4611686018427387900)
if (temu2 <= 4611686018427387900)
{
unsigned long iftmp = temu2 * 2;
if (iftmp == 0)
__builtin_abort ();
}
}
}
then we optimize this to
<bb 2> [local count: 1073741824]:
temu_3 = (long unsigned int) signed_value_source_2(D);
_1 = temu_3 + 2147483648;
if (_1 > 4294967295)
goto <bb 5>; [50.00%]
else
goto <bb 3>; [50.00%]
<bb 3> [local count: 536870913]:
if (signed_value_source_2(D) == -1)
goto <bb 4>; [0.00%]
else
goto <bb 5>; [100.00%]
<bb 4> [count: 0]:
__builtin_abort ();
and the outer if doesn't change the inner range result.
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Bug tree-optimization/109350] FAIL: g++.dg/warn/Wstringop-overflow-4.C
2023-03-31 6:09 [Bug tree-optimization/109350] New: FAIL: g++.dg/warn/Wstringop-overflow-4.C rguenth at gcc dot gnu.org
2023-03-31 6:35 ` [Bug tree-optimization/109350] " rguenth at gcc dot gnu.org
2023-03-31 7:17 ` rguenth at gcc dot gnu.org
@ 2023-03-31 14:30 ` amacleod at redhat dot com
2023-03-31 20:47 ` amacleod at redhat dot com
3 siblings, 0 replies; 5+ messages in thread
From: amacleod at redhat dot com @ 2023-03-31 14:30 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109350
--- Comment #3 from Andrew Macleod <amacleod at redhat dot com> ---
On 3/31/23 03:17, rguenth at gcc dot gnu.org wrote:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109350
>
> Richard Biener <rguenth at gcc dot gnu.org> changed:
>
> What |Removed |Added
> ----------------------------------------------------------------------------
> CC| |amacleod at redhat dot com
>
> --- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> ---
> Hmm, the same reproduces with r_imin_imax as ptrdiff_t but the IL is a bit
> more obvious:
>
> <bb 2> [local count: 1073741824]:
> _27 ={v} signed_value_source;
> _4 = (unsigned long) _27;
> _8 = _4 + 2147483648;
> if (_8 > 4294967295)
> goto <bb 8>; [50.00%]
> else
> goto <bb 3>; [50.00%]
>
> <bb 3> [local count: 536870913]:
> _30 = _27 + 1;
> _28 = (sizetype) _30;
> if (_4 <= 4611686018427387900)
> goto <bb 4>; [50.00%]
> else
> goto <bb 5>; [50.00%]
>
> <bb 5> [local count: 268435458]:
> _12 = operator new [] (18446744073709551615);
> __builtin_memcpy (_12, &MEM <const char[37]> [(void
> *)"0123456789abcdefghijklmnopqrstuvwxyz" + 35B], 2);
> sink (_12);
> if (_28 <= 4611686018427387900)
> goto <bb 9>; [100.00%]
> else
> goto <bb 7>; [0.00%]
>
> <bb 9> [local count: 0]:
> iftmp.2_37 = _28 * 2;
> _39 = operator new [] (iftmp.2_37);
> __builtin_memcpy (_39, &MEM <const char[37]> [(void
> *)"0123456789abcdefghijklmnopqrstuvwxyz" + 34B], 3);
>
> so we have (unsigned long)[int_min, int_max] > 4611686018427387900
> && (unsigned long)[int_min+1, int_max+1] <= 4611686018427387900 to
> constrain _4. I don't see how we can arrive at [0,0] for iftmp.2_37.
Looking at what ranger produces for vrp2 (same code just a few passes
later):
=========== BB 2 ============
Imports: _28
Exports: _4 _10 _28
_4 : _28(I)
_10 : _4 _28(I)
Partial equiv (_4 pe64 _28)
Relational : (_10 != _4)
<bb 2> [local count: 1073741824]:
_28 ={v} signed_value_source;
_4 = (unsigned long) _28;
_10 = _4 + 2147483648;
if (_10 > 4294967295)
goto <bb 8>; [50.00%]
else
goto <bb 3>; [50.00%]
2->3 (F) _4 : [irange] unsigned long [0,
2147483647][18446744071562067968, +INF]
2->3 (F) _10 : [irange] unsigned long [0, 4294967295] NONZERO
0xffffffff
2->3 (F) _28 : [irange] long int [-2147483648, 2147483647]
on entry top BB3 , _28 has the full range of a signed int in a long int
body.
=========== BB 3 ============
_4 [irange] unsigned long [0, 2147483647][18446744071562067968, +INF]
_28 [irange] long int [-2147483648, 2147483647]
Partial equiv (r_imin_imax_8 pe32 _28)
Relational : (_31 > r_imin_imax_8)
<bb 3> [local count: 536870913]:
r_imin_imax_8 = (int) _28; << THIs is
varying, which is why it isnt printed anywhere
_31 = r_imin_imax_8 + 1; << signed traps on overflowt, so
this would be [min+1, +INF]
_29 = (sizetype) _31; << sizetype is a larger unsigned
object,so the possible values for it are [0,
2147483647][18446744071562067969, +INF]
if (_4 <= 4611686018427387900) << this leaves _4 with
possible values of [18446744071562067968, +INF] on the FALSE branch.
goto <bb 4>; [50.00%]
else
goto <bb 5>; [50.00%]
_29 : [irange] sizetype [0, 2147483647][18446744071562067969, +INF]
_31 : [irange] int [-2147483647, +INF]
When we recalculate values based on the range of _4 on the false
branch, intersected with their knowns ranges, it comes up with this
3->5 (F) _4 : [irange] unsigned long [18446744071562067968, +INF]
3->5 (F) r_imin_imax_8 : [irange] int [-INF, -1]
3->5 (F) _28 : [irange] long int [-2147483648, -1]
3->5 (F) _29 : [irange] sizetype [0, 0][18446744071562067969, +INF]
3->5 (F) _31 : [irange] int [-2147483647, 0]
when we feed that value of _4 into
[18446744071562067968, +INF] = (unsigned long)28
in BB2, we discover the only possible valiues of _28 are [-2147483648,
-1] on this branch.
We now go an recalculate r_imin_imax_8, _31 and _29 based on this new
value of _28 and come up with those ranges
that means when we get to bb5, and see
if (_29 <= 4611686018427387900)
goto <bb 9>; [100.00%]
the only possible value of _29 on this branch is a [0,0] And thats a
direct result of _31 = [-INF, -1] + 1 before _20 is created with the cast.
yikes. talk about convoluted...
>
> In fact if I put this into a separate testcase like
>
> void __attribute__((noipa))
> foo (long signed_value_source)
> {
> unsigned long temu = signed_value_source;
> if (temu + 2147483648 > 4294967295)
> ;
> else
> {
> long tems = signed_value_source + 1;
> unsigned long temu2 = tems;
> if (temu > 4611686018427387900)
> if (temu2 <= 4611686018427387900)
> {
> unsigned long iftmp = temu2 * 2;
> if (iftmp == 0)
> __builtin_abort ();
> }
> }
> }
>
> then we optimize this to
>
> <bb 2> [local count: 1073741824]:
> temu_3 = (long unsigned int) signed_value_source_2(D);
> _1 = temu_3 + 2147483648;
> if (_1 > 4294967295)
> goto <bb 5>; [50.00%]
> else
> goto <bb 3>; [50.00%]
>
> <bb 3> [local count: 536870913]:
> if (signed_value_source_2(D) == -1)
> goto <bb 4>; [0.00%]
> else
> goto <bb 5>; [100.00%]
>
> <bb 4> [count: 0]:
> __builtin_abort ();
>
> and the outer if doesn't change the inner range result.
>
I bet if we used temu_3 at the abort point it would. I changed it to
bar (temu) from the abort:
if (iftmp == 0)
bar (temu);
From EVRP:
temu_5 = (long unsigned int) signed_value_source_4(D);
_1 = temu_5 + 2147483648;
if (_1 > 4294967295)
goto <bb 6>; [INV]
else
goto <bb 3>; [INV]
<bb 3> :
tems_7 = signed_value_source_4(D) + 1;
temu2_8 = (long unsigned int) tems_7;
if (temu_5 > 4611686018427387900)
goto <bb 4>; [INV]
else
goto <bb 6>; [INV]
<bb 4> :
if (temu2_8 <= 4611686018427387900)
goto <bb 5>; [INV]
else
goto <bb 6>; [INV]
<bb 5> :
bar (-1);
Andrew
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Bug tree-optimization/109350] FAIL: g++.dg/warn/Wstringop-overflow-4.C
2023-03-31 6:09 [Bug tree-optimization/109350] New: FAIL: g++.dg/warn/Wstringop-overflow-4.C rguenth at gcc dot gnu.org
` (2 preceding siblings ...)
2023-03-31 14:30 ` amacleod at redhat dot com
@ 2023-03-31 20:47 ` amacleod at redhat dot com
3 siblings, 0 replies; 5+ messages in thread
From: amacleod at redhat dot com @ 2023-03-31 20:47 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109350
--- Comment #4 from Andrew Macleod <amacleod at redhat dot com> ---
Perhaps its clearer (HA!) if I turn the IL into a C program:
This is what the code sequence we are seeing effectively does:
int need_beer(int value);
int need_big_beer(unsigned long value);
int beer(int value)
{
unsigned long x = value;
unsigned long y = x + 0x80000000;
if (y < 0xFFFFFFFF)
{
int r = x;
int t = r + 1;
unsigned long z = t;
if (x > 0x3FFFFFFFFFFFFFFC)
{
need_beer (r);
if (z <= 0x3FFFFFFFFFFFFFFC)
need_big_beer (z);
}
}
}
and with relevant outgoing edges:
<bb 2> :
x_3 = (long unsigned int) value_2(D);
y_4 = x_3 + 2147483648;
if (y_4 != 4294967295)
goto <bb 3>; [INV]
else
goto <bb 6>; [INV]
x_3 : [irange] long unsigned int [0, 2147483647][18446744071562067968, +INF]
y_4 : [irange] long unsigned int [0, 4294967295] NONZERO 0xffffffff
2->3 (T) value_2(D) : [irange] int [-INF, 2147483646]
2->3 (T) x_3 : [irange] long unsigned int [0,
2147483646][18446744071562067968, +INF]
2->3 (T) y_4 : [irange] long unsigned int [0, 4294967294] NONZERO
0xffffffff
<bb 3> :
t_7 = value_2(D) + 1;
z_8 = (long unsigned int) t_7;
if (x_3 > 4611686018427387900)
goto <bb 4>; [INV]
else
goto <bb 6>; [INV]
t_7 : [irange] int [-2147483647, +INF]
z_8 : [irange] long unsigned int [0, 2147483647][18446744071562067969, +INF]
3->4 (T) value_2(D) : [irange] int [-INF, -1]
3->4 (T) x_3 : [irange] long unsigned int [18446744071562067968, +INF]
3->4 (T) t_7 : [irange] int [-2147483647, 0]
3->4 (T) z_8 : [irange] long unsigned int [0, 0][18446744071562067969,
+INF]
<bb 4> :
need_beer (value_2(D));
if (z_8 <= 4611686018427387900)
goto <bb 5>; [INV]
else
goto <bb 6>; [INV]
4->5 (T) value_2(D) : [irange] int [-1, -1]
4->5 (T) z_8 : [irange] long unsigned int [0, 0] NONZERO 0x0
<bb 5> :
need_big_beer (0);
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2023-03-31 20:47 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-31 6:09 [Bug tree-optimization/109350] New: FAIL: g++.dg/warn/Wstringop-overflow-4.C rguenth at gcc dot gnu.org
2023-03-31 6:35 ` [Bug tree-optimization/109350] " rguenth at gcc dot gnu.org
2023-03-31 7:17 ` rguenth at gcc dot gnu.org
2023-03-31 14:30 ` amacleod at redhat dot com
2023-03-31 20:47 ` amacleod at redhat dot com
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).