summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2020-09-01 16:02:19 -0600
committerMartin Sebor <msebor@redhat.com>2020-09-01 16:03:25 -0600
commit0c344a649d803a83ed35f629d292b98143935ffa (patch)
tree069c12b4eb9f1263b68f13d0a2027908cb58204f
parentb1c59b31ef7adc832405209e9e2a77212284abd7 (diff)
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.
-rw-r--r--gcc/builtins.c9
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-42.c58
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow.c12
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overread-4.c58
4 files changed, 129 insertions, 8 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index bc35b071f02..97f1a184dc6 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -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];
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-42.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-42.c
new file mode 100644
index 00000000000..21a675ab7c7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-42.c
@@ -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);
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow.c b/gcc/testsuite/gcc.dg/Wstringop-overflow.c
index 2c5f4f05254..c615dae03fc 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow.c
@@ -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" } */
}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overread-4.c b/gcc/testsuite/gcc.dg/Wstringop-overread-4.c
new file mode 100644
index 00000000000..8248dad213b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overread-4.c
@@ -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);
+}