Hi!

This makes c_strlen avoid an unsafe strlen folding of const arguments
with non-const offset.  Currently a negative out of bounds offset
makes the strlen function return an extremely large number, and
at the same time, prevents the VRP machinery, to determine the correct
range if the strlen function in this case.

Fixed by doing the whole computation in size_t and casting the
result back to ssize_t.


Bootstrapped and reg-tested on x86_64-pc-linux-gnu.
Is it OK for trunk?


Thanks
Bernd.
gcc:
2018-10-22  Bernd Edlinger  <bernd.edlin...@hotmail.de>

	PR tree-optimization/86572
	* builtins.c (c_strlen): Handle negative offsets in a safe way.

testsuite:
2018-10-22  Bernd Edlinger  <bernd.edlin...@hotmail.de>

	PR tree-optimization/86572
	* gcc.dg/pr86572.c: New test.

diff -Npur gcc/builtins.c gcc/builtins.c
--- gcc/builtins.c	2018-10-21 10:41:08.000000000 +0200
+++ gcc/builtins.c	2018-10-22 10:45:25.846236006 +0200
@@ -734,11 +734,14 @@ c_strlen (tree src, int only_value, c_st
 	 of the string subtract the offset from the length of the string,
 	 and return that.  Otherwise the length is zero.  Take care to
 	 use SAVE_EXPR in case the OFFSET has side-effects.  */
-      tree offsave = TREE_SIDE_EFFECTS (byteoff) ? save_expr (byteoff) : byteoff;
-      offsave = fold_convert (ssizetype, offsave);
+      tree offsave = TREE_SIDE_EFFECTS (byteoff) ? save_expr (byteoff)
+						 : byteoff;
+      offsave = fold_convert_loc (loc, sizetype, offsave);
       tree condexp = fold_build2_loc (loc, LE_EXPR, boolean_type_node, offsave,
-				      build_int_cst (ssizetype, len));
-      tree lenexp = size_diffop_loc (loc, ssize_int (len), offsave);
+				      size_int (len));
+      tree lenexp = fold_build2_loc (loc, MINUS_EXPR, sizetype, size_int (len),
+				     offsave);
+      lenexp = fold_convert_loc (loc, ssizetype, lenexp);
       return fold_build3_loc (loc, COND_EXPR, ssizetype, condexp, lenexp,
 			      build_zero_cst (ssizetype));
     }
diff -Npur gcc/testsuite/gcc.dg/pr86572.c gcc/testsuite/gcc.dg/pr86572.c
--- gcc/testsuite/gcc.dg/pr86572.c	1970-01-01 01:00:00.000000000 +0100
+++ gcc/testsuite/gcc.dg/pr86572.c	2018-10-22 12:35:25.771640418 +0200
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+const char buf[40] = "test";
+void test (int x)
+{
+  if (__builtin_strlen (buf + x) > 4)
+    __builtin_abort ();
+}
+
+/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */

Reply via email to