aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorBernd Edlinger <bernd.edlinger@hotmail.de>2018-08-29 22:16:09 +0000
committerJeff Law <law@gcc.gnu.org>2018-08-29 16:16:09 -0600
commit1ebf0641a5201939cbaa1cc4f008bb8eda68895c (patch)
treedb468a623870c89e111e941c934472e18869fe46 /gcc
parentd66ab7d12bb632c3de947f535d189275209a3915 (diff)
downloadgcc-1ebf0641a5201939cbaa1cc4f008bb8eda68895c.zip
gcc-1ebf0641a5201939cbaa1cc4f008bb8eda68895c.tar.gz
gcc-1ebf0641a5201939cbaa1cc4f008bb8eda68895c.tar.bz2
re PR middle-end/87053 (wrong code with c_strlen)
gcc: 2018-08-22 Bernd Edlinger <bernd.edlinger@hotmail.de> PR middle-end/87053 * builtins.c (c_strlen): Improve range checks. testsuite: 2018-08-22 Bernd Edlinger <bernd.edlinger@hotmail.de> PR middle-end/87053 * gcc.c-torture/execute/pr87053.c: New test. From-SVN: r263968
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/builtins.c11
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr87053.c17
4 files changed, 35 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3cf10ca..8865f31 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2018-08-29 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR middle-end/87053
+ * builtins.c (c_strlen): Improve range checks.
+
2018-08-29 Martin Sebor <msebor@redhat.com>
Jeff Law <law@redhat.com>
diff --git a/gcc/builtins.c b/gcc/builtins.c
index c9de1e6..58ea747 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -567,7 +567,7 @@ string_length (const void *ptr, unsigned eltsize, unsigned maxelts)
tree
c_strlen (tree src, int only_value, unsigned eltsize)
{
- gcc_assert (eltsize == 1 || eltsize == 2 || eltsize == 4);
+ gcc_checking_assert (eltsize == 1 || eltsize == 2 || eltsize == 4);
STRIP_NOPS (src);
if (TREE_CODE (src) == COND_EXPR
&& (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
@@ -656,10 +656,10 @@ c_strlen (tree src, int only_value, unsigned eltsize)
a null character if we can represent it as a single HOST_WIDE_INT. */
if (byteoff == 0)
eltoff = 0;
- else if (! tree_fits_shwi_p (byteoff))
+ else if (! tree_fits_uhwi_p (byteoff) || tree_to_uhwi (byteoff) % eltsize)
eltoff = -1;
else
- eltoff = tree_to_shwi (byteoff) / eltsize;
+ eltoff = tree_to_uhwi (byteoff) / eltsize;
/* If the offset is known to be out of bounds, warn, and call strlen at
runtime. */
@@ -691,6 +691,11 @@ c_strlen (tree src, int only_value, unsigned eltsize)
unsigned len = string_length (ptr + eltoff * eltsize, eltsize,
strelts - eltoff);
+ /* Don't know what to return if there was no zero termination.
+ Ideally this would turn into a gcc_checking_assert over time. */
+ if (len > maxelts - eltoff)
+ return NULL_TREE;
+
return ssize_int (len);
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e38dab2..317cb47 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2018-08-29 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR middle-end/87053
+ * gcc.c-torture/execute/pr87053.c: New test.
+
2018-08-29 Jakub Jelinek <jakub@redhat.com>
PR c++/87095
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr87053.c b/gcc/testsuite/gcc.c-torture/execute/pr87053.c
new file mode 100644
index 0000000..0170731
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr87053.c
@@ -0,0 +1,17 @@
+/* PR middle-end/87053 */
+
+const union
+{ struct {
+ char x[4];
+ char y[4];
+ };
+ struct {
+ char z[8];
+ };
+} u = {{"1234", "567"}};
+
+int main ()
+{
+ if (__builtin_strlen (u.z) != 7)
+ __builtin_abort ();
+}