diff mbox

Don't leak C_MAYBE_CONST_EXPRs into gimplifier from float-cast instrumentation (PR sanitizer/69099)

Message ID 20160105130315.GE31604@redhat.com
State New
Headers show

Commit Message

Marek Polacek Jan. 5, 2016, 1:03 p.m. UTC
The problem in this PR is that we were leaking C_MAYBE_CONST_EXPRs into the
gimplifier.  It was created in the float-cast instrumentation in convert().

Fixed by using the fully-folded EXPR only, thus without C_MAYBE_CONST_EXPR.
Which means that we can drop a parameter of ubsan_instrument_float_cast.
Seems that this doesn't hurt the diagnostics.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2016-01-05  Marek Polacek  <polacek@redhat.com>

	PR sanitizer/69099
	* c-convert.c (convert) [INTEGER_TYPE]: Drop ARG.  Don't pass ARG to
	ubsan_instrument_float_cast.  Fold EXPR.

	* convert.c (convert_to_integer_1): Adjust call to
	ubsan_instrument_float_cast.
	* ubsan.c (ubsan_instrument_float_cast): Drop the ARG parameter.  Use
	EXPR instead of ARG.
	* ubsan.h (ubsan_instrument_float_cast): Adjust declaration.

	* gcc.dg/ubsan/float-cast-overflow-atomic.c: New test.


	Marek

Comments

Jeff Law Jan. 5, 2016, 6:49 p.m. UTC | #1
On 01/05/2016 06:03 AM, Marek Polacek wrote:
> The problem in this PR is that we were leaking C_MAYBE_CONST_EXPRs into the
> gimplifier.  It was created in the float-cast instrumentation in convert().
>
> Fixed by using the fully-folded EXPR only, thus without C_MAYBE_CONST_EXPR.
> Which means that we can drop a parameter of ubsan_instrument_float_cast.
> Seems that this doesn't hurt the diagnostics.
>
> Bootstrapped/regtested on x86_64-linux, ok for trunk?
>
> 2016-01-05  Marek Polacek  <polacek@redhat.com>
>
> 	PR sanitizer/69099
> 	* c-convert.c (convert) [INTEGER_TYPE]: Drop ARG.  Don't pass ARG to
> 	ubsan_instrument_float_cast.  Fold EXPR.
>
> 	* convert.c (convert_to_integer_1): Adjust call to
> 	ubsan_instrument_float_cast.
> 	* ubsan.c (ubsan_instrument_float_cast): Drop the ARG parameter.  Use
> 	EXPR instead of ARG.
> 	* ubsan.h (ubsan_instrument_float_cast): Adjust declaration.
>
> 	* gcc.dg/ubsan/float-cast-overflow-atomic.c: New test.
OK.  You might want to mention the change from NULL to NULL_TREE in the 
ChangeLog as well.

jeff
diff mbox

Patch

diff --git gcc/c/c-convert.c gcc/c/c-convert.c
index 5ee52eb..4167c34 100644
--- gcc/c/c-convert.c
+++ gcc/c/c-convert.c
@@ -111,20 +111,16 @@  convert (tree type, tree expr)
 	  && COMPLETE_TYPE_P (type)
 	  && do_ubsan_in_current_function ())
 	{
-	  tree arg;
 	  if (in_late_binary_op)
-	    {
-	      expr = save_expr (expr);
-	      arg = expr;
-	    }
+	    expr = save_expr (expr);
 	  else
 	    {
 	      expr = c_save_expr (expr);
-	      arg = c_fully_fold (expr, false, NULL);
+	      expr = c_fully_fold (expr, false, NULL);
 	    }
-	  tree check = ubsan_instrument_float_cast (loc, type, expr, arg);
+	  tree check = ubsan_instrument_float_cast (loc, type, expr);
 	  expr = fold_build1 (FIX_TRUNC_EXPR, type, expr);
-	  if (check == NULL)
+	  if (check == NULL_TREE)
 	    return expr;
 	  return fold_build2 (COMPOUND_EXPR, TREE_TYPE (expr), check, expr);
 	}
diff --git gcc/convert.c gcc/convert.c
index 4b1e1f1..dd7d818 100644
--- gcc/convert.c
+++ gcc/convert.c
@@ -920,9 +920,9 @@  convert_to_integer_1 (tree type, tree expr, bool dofold)
 	  && do_ubsan_in_current_function ())
 	{
 	  expr = save_expr (expr);
-	  tree check = ubsan_instrument_float_cast (loc, type, expr, expr);
+	  tree check = ubsan_instrument_float_cast (loc, type, expr);
 	  expr = build1 (FIX_TRUNC_EXPR, type, expr);
-	  if (check == NULL)
+	  if (check == NULL_TREE)
 	    return expr;
 	  return maybe_fold_build2_loc (dofold, loc, COMPOUND_EXPR,
 					TREE_TYPE (expr), check, expr);
diff --git gcc/testsuite/gcc.dg/ubsan/float-cast-overflow-atomic.c gcc/testsuite/gcc.dg/ubsan/float-cast-overflow-atomic.c
index e69de29..0a4fa01 100644
--- gcc/testsuite/gcc.dg/ubsan/float-cast-overflow-atomic.c
+++ gcc/testsuite/gcc.dg/ubsan/float-cast-overflow-atomic.c
@@ -0,0 +1,171 @@ 
+/* PR sanitizer/69099 */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors -fsanitize=float-cast-overflow" } */
+/* This is gcc.dg/atomic/c11-atomic-exec-2.c.  */
+
+extern void abort (void);
+extern void exit (int);
+
+#define CMPLX(X, Y) __builtin_complex ((X), (Y))
+
+#define TEST_COMPOUND(TYPE, LHSVAL, RHSVAL, OP)				\
+  do									\
+    {									\
+      static volatile _Atomic (TYPE) a = (TYPE) (LHSVAL);		\
+      if ((a OP##= (RHSVAL)) != (TYPE) ((TYPE) (LHSVAL) OP (RHSVAL)))	\
+	abort ();							\
+      if (a != (TYPE) ((TYPE) (LHSVAL) OP (RHSVAL)))			\
+	abort ();							\
+    }									\
+  while (0)
+
+#define TEST_COMPOUND_ARITH(LHSVAL, RHSVAL, OP)				\
+  do									\
+    {									\
+      TEST_COMPOUND (_Bool, (LHSVAL), (RHSVAL), OP);			\
+      TEST_COMPOUND (char, (LHSVAL), (RHSVAL), OP);			\
+      TEST_COMPOUND (signed char, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (unsigned char, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (signed short, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (unsigned short, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (signed int, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (unsigned int, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (signed long, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (unsigned long, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (signed long long, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (unsigned long long, (LHSVAL), (RHSVAL), OP);	\
+      TEST_COMPOUND (float, (LHSVAL), (RHSVAL), OP);			\
+      TEST_COMPOUND (double, (LHSVAL), (RHSVAL), OP);			\
+      TEST_COMPOUND (long double, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (_Complex float, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (_Complex double, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (_Complex long double, (LHSVAL), (RHSVAL), OP);	\
+    }									\
+  while (0)
+
+#define TEST_COMPOUND_INT(LHSVAL, RHSVAL, OP)				\
+  do									\
+    {									\
+      TEST_COMPOUND (_Bool, (LHSVAL), (RHSVAL), OP);			\
+      TEST_COMPOUND (char, (LHSVAL), (RHSVAL), OP);			\
+      TEST_COMPOUND (signed char, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (unsigned char, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (signed short, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (unsigned short, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (signed int, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (unsigned int, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (signed long, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (unsigned long, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (signed long long, (LHSVAL), (RHSVAL), OP);		\
+      TEST_COMPOUND (unsigned long long, (LHSVAL), (RHSVAL), OP);	\
+    }									\
+  while (0)
+
+static void
+test_mult (void)
+{
+  TEST_COMPOUND_ARITH (1, 2, *);
+  TEST_COMPOUND_ARITH (-3, 5, *);
+  TEST_COMPOUND_ARITH (-7, -20, *);
+  TEST_COMPOUND_ARITH (1.25, 3.5, *);
+  TEST_COMPOUND_ARITH (CMPLX (1.5, 2.5), CMPLX (3.5, 4.5), *);
+  TEST_COMPOUND_ARITH (CMPLX (1.5, 2.5), 2, *);
+}
+
+static void
+test_div (void)
+{
+  TEST_COMPOUND_ARITH (1, 2, /);
+  TEST_COMPOUND_ARITH (-6, 3, /);
+  TEST_COMPOUND_ARITH (-70, -10, /);
+  TEST_COMPOUND_ARITH (1.25, 2.5, /);
+  TEST_COMPOUND_ARITH (CMPLX (1.0, 1.0), CMPLX (0.5, 0.5), /);
+  TEST_COMPOUND_ARITH (CMPLX (1.5, 2.5), 2, /);
+}
+
+static void
+test_mod (void)
+{
+  TEST_COMPOUND_INT (1, 2, %);
+  TEST_COMPOUND_INT (-3, 5, %);
+  TEST_COMPOUND_INT (-7, -2, %);
+}
+
+static void
+test_plus (void)
+{
+  TEST_COMPOUND_ARITH (1, 2, +);
+  TEST_COMPOUND_ARITH (-3, 5, +);
+  TEST_COMPOUND_ARITH (-7, -20, +);
+  TEST_COMPOUND_ARITH (1.25, 3.5, +);
+  TEST_COMPOUND_ARITH (CMPLX (1.5, 2.5), CMPLX (3.5, 4.5), +);
+  TEST_COMPOUND_ARITH (CMPLX (1.5, 2.5), 2, +);
+  static int ia[2];
+  TEST_COMPOUND (int *, &ia[1], 1, +);
+  TEST_COMPOUND (int *, &ia[1], -1, +);
+}
+
+static void
+test_minus (void)
+{
+  TEST_COMPOUND_ARITH (1, 2, -);
+  TEST_COMPOUND_ARITH (-3, 5, -);
+  TEST_COMPOUND_ARITH (-7, -20, -);
+  TEST_COMPOUND_ARITH (3.5, 1.25, -);
+  TEST_COMPOUND_ARITH (CMPLX (3.5, 4.5), CMPLX (1.5, 2.5), -);
+  TEST_COMPOUND_ARITH (CMPLX (3.5, 2.5), 2, -);
+  static int ia[2];
+  TEST_COMPOUND (int *, &ia[1], 1, -);
+  TEST_COMPOUND (int *, &ia[1], -1, -);
+}
+
+static void
+test_lshift (void)
+{
+  TEST_COMPOUND_INT (1, 7, <<);
+  TEST_COMPOUND_INT (15, 3, <<);
+}
+
+static void
+test_rshift (void)
+{
+  TEST_COMPOUND_INT (1, 1, >>);
+  TEST_COMPOUND_INT (127, 4, >>);
+}
+
+static void
+test_and (void)
+{
+  TEST_COMPOUND_INT (0x1234, 0x7856, &);
+  TEST_COMPOUND_INT (-1, 0x12345678, &);
+}
+
+static void
+test_xor (void)
+{
+  TEST_COMPOUND_INT (0x1234, 0x7856, ^);
+  TEST_COMPOUND_INT (-1, 0x12345678, ^);
+}
+
+static void
+test_or (void)
+{
+  TEST_COMPOUND_INT (0x1234, 0x7856, |);
+  TEST_COMPOUND_INT (-12345, 0x12345678, |);
+}
+
+int
+main (void)
+{
+  test_mult ();
+  test_div ();
+  test_mod ();
+  test_plus ();
+  test_minus ();
+  test_lshift ();
+  test_rshift ();
+  test_and ();
+  test_xor ();
+  test_or ();
+  exit (0);
+}
diff --git gcc/ubsan.c gcc/ubsan.c
index e5b49b2..d3fbfd1 100644
--- gcc/ubsan.c
+++ gcc/ubsan.c
@@ -1478,18 +1478,18 @@  ubsan_use_new_style_p (location_t loc)
 }
 
 /* Instrument float point-to-integer conversion.  TYPE is an integer type of
-   destination, EXPR is floating-point expression.  ARG is what to pass
-   the libubsan call as value, often EXPR itself.  */
+   destination, EXPR is floating-point expression.  */
 
 tree
-ubsan_instrument_float_cast (location_t loc, tree type, tree expr, tree arg)
+ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
 {
   tree expr_type = TREE_TYPE (expr);
   tree t, tt, fn, min, max;
   machine_mode mode = TYPE_MODE (expr_type);
   int prec = TYPE_PRECISION (type);
   bool uns_p = TYPE_UNSIGNED (type);
-  if (!loc) loc = input_location;
+  if (loc == UNKNOWN_LOCATION)
+    loc = input_location;
 
   /* Float to integer conversion first truncates toward zero, so
      even signed char c = 127.875f; is not problematic.
@@ -1609,7 +1609,7 @@  ubsan_instrument_float_cast (location_t loc, tree type, tree expr, tree arg)
       fn = builtin_decl_explicit (bcode);
       fn = build_call_expr_loc (loc, fn, 2,
 				build_fold_addr_expr_loc (loc, data),
-				ubsan_encode_value (arg, false));
+				ubsan_encode_value (expr, false));
     }
 
   return fold_build3 (COND_EXPR, void_type_node, t, fn, integer_zero_node);
diff --git gcc/ubsan.h gcc/ubsan.h
index d272d62..c66d0af 100644
--- gcc/ubsan.h
+++ gcc/ubsan.h
@@ -53,7 +53,7 @@  extern tree ubsan_type_descriptor (tree, enum ubsan_print_style = UBSAN_PRINT_NO
 extern tree ubsan_encode_value (tree, bool = false);
 extern bool is_ubsan_builtin_p (tree);
 extern tree ubsan_build_overflow_builtin (tree_code, location_t, tree, tree, tree);
-extern tree ubsan_instrument_float_cast (location_t, tree, tree, tree);
+extern tree ubsan_instrument_float_cast (location_t, tree, tree);
 extern tree ubsan_get_source_location_type (void);
 
 #endif  /* GCC_UBSAN_H  */