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:
Martin Sebor 2020-09-01 16:02:19 -06:00
parent b1c59b31ef
commit 0c344a649d
4 changed files with 129 additions and 8 deletions

View File

@ -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];

View 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);
}

View File

@ -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" } */
}

View 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);
}