Use the determined lower bound of the range of offsets in a PLUS_EXPR.
gcc/ChangeLog: * builtins.c (compute_objsize): Only replace the upper bound of a POINTER_PLUS offset when it's less than the lower bound. gcc/testsuite/ChangeLog: * gcc.dg/Wstringop-overflow.c: Remove xfails. * gcc.dg/Wstringop-overflow-42.c: New test. * gcc.dg/Wstringop-overread-4.c: New test.
This commit is contained in:
parent
b1c59b31ef
commit
0c344a649d
4 changed files with 129 additions and 8 deletions
|
@ -4367,12 +4367,17 @@ compute_objsize (tree ptr, int ostype, access_ref *pref,
|
|||
offset to the maximum. */
|
||||
offset_int orng[2];
|
||||
tree off = gimple_assign_rhs2 (stmt);
|
||||
if (!get_range (off, SIGNED, orng, rvals)
|
||||
|| !wi::les_p (orng[0], orng[1]))
|
||||
if (!get_range (off, SIGNED, orng, rvals))
|
||||
{
|
||||
orng[0] = wi::to_offset (TYPE_MIN_VALUE (ptrdiff_type_node));
|
||||
orng[1] = wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node));
|
||||
}
|
||||
else if (wi::lts_p (orng[1], orng[0]))
|
||||
/* The upper bound is less than the lower bound when the integer
|
||||
operand is the result of signed integer conversion to sizetype,
|
||||
as in P + OFF + CST where OFF > 0.
|
||||
Correct just the upper bound. */
|
||||
orng[1] = wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node));
|
||||
|
||||
pref->offrng[0] += orng[0];
|
||||
pref->offrng[1] += orng[1];
|
||||
|
|
58
gcc/testsuite/gcc.dg/Wstringop-overflow-42.c
Normal file
58
gcc/testsuite/gcc.dg/Wstringop-overflow-42.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* Verify -Wstringop-overflow a with destination pointer pointing either
|
||||
before the beginning or past the end of an object.
|
||||
{ dg-do compile }
|
||||
{ dg-options "-O -Wall -Wno-array-bounds -Wno-restrict" } */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
char* strcpy (char *, const char *);
|
||||
|
||||
|
||||
extern char a[1];
|
||||
|
||||
volatile char *d;
|
||||
|
||||
void cpy_si_1_max (int i, const char *s)
|
||||
{
|
||||
if (i < 1) i = 1;
|
||||
d = strcpy (a + i, s); // { dg-warning "writing 1 or more bytes into a region of size 0" }
|
||||
d = strcpy (a + i + 1, s); // { dg-warning "writing 1 or more bytes into a region of size 0" }
|
||||
}
|
||||
|
||||
void cpy_ui_1_max (unsigned i, const char *s)
|
||||
{
|
||||
if (i < 1) i = 1;
|
||||
d = strcpy (a + i, s); // { dg-warning "writing 1 or more bytes into a region of size 0" }
|
||||
d = strcpy (a + i + 1, s); // { dg-warning "writing 1 or more bytes into a region of size 0" "" { xfail ilp32 } }
|
||||
}
|
||||
|
||||
void cpy_sl_1_max (long i, const char *s)
|
||||
{
|
||||
if (i < 1) i = 1;
|
||||
d = strcpy (a + i, s); // { dg-warning "writing 1 or more bytes into a region of size 0" }
|
||||
d = strcpy (a + i + 1, s); // { dg-warning "writing 1 or more bytes into a region of size 0" }
|
||||
}
|
||||
|
||||
void cpy_ul_1_max (unsigned long i, const char *s)
|
||||
{
|
||||
if (i < 1) i = 1;
|
||||
d = strcpy (a + i, s); // { dg-warning "writing 1 or more bytes into a region of size 0" }
|
||||
d = strcpy (a + i + 1, s); // { dg-warning "writing 1 or more bytes into a region of size 0" "" { xfail *-*-* } }
|
||||
}
|
||||
|
||||
|
||||
void cpy_si_min_m1 (int i, const char *s)
|
||||
{
|
||||
if (i > -1) i = -1;
|
||||
d = strcpy (a + i - 1, s); // { dg-warning "writing 1 or more bytes into a region of size 0" }
|
||||
d = strcpy (a + i, s); // { dg-warning "writing 1 or more bytes into a region of size 0" }
|
||||
d = strcpy (a + i + 2, s);
|
||||
}
|
||||
|
||||
void cpy_sl_min_m1 (long i, const char *s)
|
||||
{
|
||||
if (i > -1) i = -1;
|
||||
d = strcpy (a + i - 1, s); // { dg-warning "writing 1 or more bytes into a region of size 0" }
|
||||
d = strcpy (a + i, s); // { dg-warning "writing 1 or more bytes into a region of size 0" }
|
||||
d = strcpy (a + i + 2, s);
|
||||
}
|
|
@ -51,8 +51,8 @@ void test_memcpy_array (const void *s)
|
|||
T (a7 + UR (8, 9), s, 7); /* { dg-warning "writing 7 bytes into a region of size 0" } */
|
||||
|
||||
T (a7 + UR (9, 10), s, 7); /* { dg-warning "writing 7 bytes into a region of size 0" } */
|
||||
T (a7 + UR (DIFF_MAX, DIFF_MAX + (size_t)1), s, 7); /* { dg-warning "writing 7 bytes into a region of size 0" "pr85350" { xfail *-*-* } } */
|
||||
T (a7 + UR (DIFF_MAX, SIZE_MAX), s, 7); /* { dg-warning "writing 7 bytes into a region of size 0" "pr85350" { xfail *-*-*} } */
|
||||
T (a7 + UR (DIFF_MAX, DIFF_MAX + (size_t)1), s, 7); /* { dg-warning "writing 7 bytes into a region of size 0" } */
|
||||
T (a7 + UR (DIFF_MAX, SIZE_MAX), s, 7); /* { dg-warning "writing 7 bytes into a region of size 0" } */
|
||||
|
||||
/* This is valid. */
|
||||
char *d = a7 + 7;
|
||||
|
@ -102,8 +102,8 @@ void test_strcpy_array (void)
|
|||
T (a7 + UR (8, 9), "012345"); /* { dg-warning "writing 7 bytes into a region of size 0" } */
|
||||
|
||||
T (a7 + UR (9, 10), "012345"); /* { dg-warning "writing 7 bytes into a region of size 0" } */
|
||||
T (a7 + UR (DIFF_MAX, DIFF_MAX + (size_t)1), "012345"); /* { dg-warning "writing 7 bytes into a region of size 0" "pr85350" { xfail *-*-* } } */
|
||||
T (a7 + UR (DIFF_MAX, SIZE_MAX), "012345"); /* { dg-warning "writing 7 bytes into a region of size 0" "pr85350" { xfail *-*-* } } */
|
||||
T (a7 + UR (DIFF_MAX, DIFF_MAX + (size_t)1), "012345"); /* { dg-warning "writing 7 bytes into a region of size 0" } */
|
||||
T (a7 + UR (DIFF_MAX, SIZE_MAX), "012345"); /* { dg-warning "writing 7 bytes into a region of size 0" } */
|
||||
|
||||
char *d = a7 + 7;
|
||||
|
||||
|
@ -127,6 +127,6 @@ void test_strncpy_memarray (struct MemArray *p, const void *s)
|
|||
T (p->a9 + UR (9, 10), s, 9); /* { dg-warning "writing 9 bytes into a region of size 0" } */
|
||||
T (p->a9 + UR (10, 11), s, 9); /* { dg-warning "writing 9 bytes into a region of size 0" } */
|
||||
|
||||
T (p->a9 + UR (DIFF_MAX, DIFF_MAX + (size_t)1), s, 1); /* { dg-warning "writing 1 byte into a region of size 0" "pr85350" { xfail *-*-* } } */
|
||||
T (p->a9 + UR (DIFF_MAX, SIZE_MAX), s, 3); /* { dg-warning "writing 3 bytes into a region of size 0" "pr85350" { xfail *-*-* } } */
|
||||
T (p->a9 + UR (DIFF_MAX, DIFF_MAX + (size_t)1), s, 1); /* { dg-warning "writing 1 byte into a region of size 0" } */
|
||||
T (p->a9 + UR (DIFF_MAX, SIZE_MAX), s, 3); /* { dg-warning "writing 3 bytes into a region of size 0" } */
|
||||
}
|
||||
|
|
58
gcc/testsuite/gcc.dg/Wstringop-overread-4.c
Normal file
58
gcc/testsuite/gcc.dg/Wstringop-overread-4.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* Verify -Wstringop-overread with a source pointer pointing either
|
||||
before the beginning or past the end of an object.
|
||||
{ dg-do compile }
|
||||
{ dg-options "-O -Wall" } */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
size_t strlen (const char *);
|
||||
|
||||
|
||||
extern char a[1];
|
||||
|
||||
volatile size_t n;
|
||||
|
||||
void len_si_1_max (int i)
|
||||
{
|
||||
if (i < 1) i = 1;
|
||||
n = strlen (a + i); // { dg-warning "reading 1 or more bytes from a region of size 0" }
|
||||
n = strlen (a + i + 1); // { dg-warning "reading 1 or more bytes from a region of size 0" }
|
||||
}
|
||||
|
||||
void len_ui_1_max (unsigned i)
|
||||
{
|
||||
if (i < 1) i = 1;
|
||||
n = strlen (a + i); // { dg-warning "reading 1 or more bytes from a region of size 0" }
|
||||
n = strlen (a + i + 1); // { dg-warning "reading 1 or more bytes from a region of size 0" "" { xfail ilp32 } }
|
||||
}
|
||||
|
||||
void len_sl_1_max (long i)
|
||||
{
|
||||
if (i < 1) i = 1;
|
||||
n = strlen (a + i); // { dg-warning "reading 1 or more bytes from a region of size 0" }
|
||||
n = strlen (a + i + 1); // { dg-warning "reading 1 or more bytes from a region of size 0" }
|
||||
}
|
||||
|
||||
void len_ul_1_max (unsigned long i)
|
||||
{
|
||||
if (i < 1) i = 1;
|
||||
n = strlen (a + i); // { dg-warning "reading 1 or more bytes from a region of size 0" }
|
||||
n = strlen (a + i + 1); // { dg-warning "reading 1 or more bytes from a region of size 0" "" { xfail *-*-* } }
|
||||
}
|
||||
|
||||
|
||||
void len_si_min_m1 (int i)
|
||||
{
|
||||
if (i > -1) i = -1;
|
||||
n = strlen (a + i - 1); // { dg-warning "reading 1 or more bytes from a region of size 0" "" { xfail lp64 } }
|
||||
n = strlen (a + i); // { dg-warning "reading 1 or more bytes from a region of size 0" "" { xfail *-*-* } }
|
||||
n = strlen (a + i + 2);
|
||||
}
|
||||
|
||||
void len_sl_min_m1 (long i)
|
||||
{
|
||||
if (i > -1) i = -1;
|
||||
n = strlen (a + i - 1); // { dg-warning "reading 1 or more bytes from a region of size 0" }
|
||||
n = strlen (a + i); // { dg-warning "reading 1 or more bytes from a region of size 0" "" { xfail *-*-* } }
|
||||
n = strlen (a + i + 2);
|
||||
}
|
Loading…
Add table
Reference in a new issue