This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix ubsan shift instrumentation


The issue here was that we were diagnosing an artificial check
that we created within the scope of shift instrumentation.  In
other words, for shifts we create something like
(unsigned) A >> (B - C) and signed-integer-overflow triggered
on that subtraction.  Fixed by making the subtraction work on
unsigned types.  This only happened in C99/C++11 mode.
Middle end seems to cope well with RSHIFT_EXPR whose second op
has an unsigned type.

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

2014-10-23  Marek Polacek  <polacek@redhat.com>

	* c-ubsan.c (ubsan_instrument_shift): Perform the MINUS_EXPR
	in unsigned type.

	* c-c++-common/ubsan/undefined-2.c: New test.

diff --git gcc/c-family/c-ubsan.c gcc/c-family/c-ubsan.c
index 5a42303..7f4dc25 100644
--- gcc/c-family/c-ubsan.c
+++ gcc/c-family/c-ubsan.c
@@ -128,19 +128,19 @@ ubsan_instrument_shift (location_t loc, enum tree_code code,
   tree op1_utype = unsigned_type_for (type1);
   HOST_WIDE_INT op0_prec = TYPE_PRECISION (type0);
   tree uprecm1 = build_int_cst (op1_utype, op0_prec - 1);
-  tree precm1 = build_int_cst (type1, op0_prec - 1);
 
   t = fold_convert_loc (loc, op1_utype, op1);
   t = fold_build2 (GT_EXPR, boolean_type_node, t, uprecm1);
 
   /* For signed x << y, in C99/C11, the following:
-     (unsigned) x >> (precm1 - y)
+     (unsigned) x >> (uprecm1 - y)
      if non-zero, is undefined.  */
   if (code == LSHIFT_EXPR
       && !TYPE_UNSIGNED (type0)
       && flag_isoc99)
     {
-      tree x = fold_build2 (MINUS_EXPR, integer_type_node, precm1, op1);
+      tree x = fold_build2 (MINUS_EXPR, unsigned_type_node, uprecm1,
+			    fold_convert (op1_utype, op1));
       tt = fold_convert_loc (loc, unsigned_type_for (type0), op0);
       tt = fold_build2 (RSHIFT_EXPR, TREE_TYPE (tt), tt, x);
       tt = fold_build2 (NE_EXPR, boolean_type_node, tt,
@@ -148,13 +148,14 @@ ubsan_instrument_shift (location_t loc, enum tree_code code,
     }
 
   /* For signed x << y, in C++11 and later, the following:
-     x < 0 || ((unsigned) x >> (precm1 - y))
+     x < 0 || ((unsigned) x >> (uprecm1 - y))
      if > 1, is undefined.  */
   if (code == LSHIFT_EXPR
       && !TYPE_UNSIGNED (TREE_TYPE (op0))
       && (cxx_dialect >= cxx11))
     {
-      tree x = fold_build2 (MINUS_EXPR, integer_type_node, precm1, op1);
+      tree x = fold_build2 (MINUS_EXPR, unsigned_type_node, uprecm1,
+			    fold_convert (op1_utype, op1));
       tt = fold_convert_loc (loc, unsigned_type_for (type0), op0);
       tt = fold_build2 (RSHIFT_EXPR, TREE_TYPE (tt), tt, x);
       tt = fold_build2 (GT_EXPR, boolean_type_node, tt,
diff --git gcc/testsuite/c-c++-common/ubsan/undefined-2.c gcc/testsuite/c-c++-common/ubsan/undefined-2.c
index e69de29..7b06709 100644
--- gcc/testsuite/c-c++-common/ubsan/undefined-2.c
+++ gcc/testsuite/c-c++-common/ubsan/undefined-2.c
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover=signed-integer-overflow" } */
+/* { dg-additional-options "-std=gnu11" { target c } } */
+/* { dg-additional-options "-std=c++11" { target c++ } } */
+
+volatile int w, z;
+
+__attribute__ ((noinline, noclone)) int
+foo (int x, int y)
+{
+  z++;
+  return x << y;
+}
+
+int
+main ()
+{
+  w = foo (0, -__INT_MAX__);
+  return 0;
+}
+
+/* { dg-output "shift exponent -\[^\n\r]* is negative\[^\n\r]*(\n|\r\n|\r)" } */

	Marek


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]