re PR middle-end/87053 (wrong code with c_strlen)
authorBernd Edlinger <bernd.edlinger@hotmail.de>
Wed, 29 Aug 2018 22:16:09 +0000 (22:16 +0000)
committerJeff Law <law@gcc.gnu.org>
Wed, 29 Aug 2018 22:16:09 +0000 (16:16 -0600)
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

gcc/ChangeLog
gcc/builtins.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr87053.c [new file with mode: 0644]

index 3cf10ca500e588ce239ce9e3f10041ead0fc0af0..8865f31a43c817248291ba65a89cdf6915287f0c 100644 (file)
@@ -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>
 
index c9de1e6f1f34a422eadd5f8d537296d78bba91ee..58ea7475ef7bb2a8abad2463b896efaa8fd79650 100644 (file)
@@ -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);
 }
 
index e38dab2f8abffe7a404f84555db655eb0930fb98..317cb47957546abd923d35456b749d1140e6daf9 100644 (file)
@@ -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 (file)
index 0000000..0170731
--- /dev/null
@@ -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 ();
+}