sanopt.c (sanopt_optimize_walker): Limit removal of the checks.
authorMarek Polacek <polacek@redhat.com>
Thu, 6 Nov 2014 11:22:59 +0000 (11:22 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Thu, 6 Nov 2014 11:22:59 +0000 (11:22 +0000)
* sanopt.c (sanopt_optimize_walker): Limit removal of the checks.
Remove vector limit.
testsuite/
* c-c++-common/ubsan/align-2.c: Add dg-output.
* c-c++-common/ubsan/align-4.c: Likewise.
* c-c++-common/ubsan/align-6.c: New test.
* c-c++-common/ubsan/align-7.c: New test.
* c-c++-common/ubsan/align-8.c: New test.
* g++.dg/ubsan/null-1.C: Add dg-output.
* g++.dg/ubsan/null-2.C: Likewise.
* g++.dg/ubsan/null-3.C: New test.
* g++.dg/ubsan/null-4.C: New test.
* g++.dg/ubsan/null-5.C: New test.

From-SVN: r217189

13 files changed:
gcc/ChangeLog
gcc/sanopt.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/ubsan/align-2.c
gcc/testsuite/c-c++-common/ubsan/align-4.c
gcc/testsuite/c-c++-common/ubsan/align-6.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/ubsan/align-7.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/ubsan/align-8.c [new file with mode: 0644]
gcc/testsuite/g++.dg/ubsan/null-1.C
gcc/testsuite/g++.dg/ubsan/null-2.C
gcc/testsuite/g++.dg/ubsan/null-3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ubsan/null-4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ubsan/null-5.C [new file with mode: 0644]

index 88eb6d9ff1639451ed56ed2e1a45cff4af5412ce..f362e2ebaf2b29420cce064d5aec7a4e730304e6 100644 (file)
@@ -1,3 +1,8 @@
+2014-11-06  Marek Polacek  <polacek@redhat.com>
+
+       * sanopt.c (sanopt_optimize_walker): Limit removal of the checks.
+       Remove vector limit.
+
 2014-11-06  Richard Biener  <rguenther@suse.de>
 
        * match.pd: Implement bitwise binary and unary simplifications
index 4483ff75cba7cfc4e216adb73a3f7ddc266cd4b6..0fc032a7a3057d7003f192f1ff38a35cf5e3e43d 100644 (file)
@@ -130,7 +130,30 @@ sanopt_optimize_walker (basic_block bb, struct sanopt_ctx *ctx)
                          /* At this point we shouldn't have any statements
                             that aren't dominating the current BB.  */
                          tree align = gimple_call_arg (g, 2);
-                         remove = tree_int_cst_le (cur_align, align);
+                         int kind = tree_to_shwi (gimple_call_arg (g, 1));
+                         /* If this is a NULL pointer check where we had segv
+                            anyway, we can remove it.  */
+                         if (integer_zerop (align)
+                             && (kind == UBSAN_LOAD_OF
+                                 || kind == UBSAN_STORE_OF
+                                 || kind == UBSAN_MEMBER_ACCESS))
+                           remove = true;
+                         /* Otherwise remove the check in non-recovering
+                            mode, or if the stmts have same location.  */
+                         else if (integer_zerop (align))
+                           remove = !(flag_sanitize_recover & SANITIZE_NULL)
+                                    || flag_sanitize_undefined_trap_on_error
+                                    || gimple_location (g)
+                                       == gimple_location (stmt);
+                         else if (tree_int_cst_le (cur_align, align))
+                           remove = !(flag_sanitize_recover
+                                      & SANITIZE_ALIGNMENT)
+                                    || flag_sanitize_undefined_trap_on_error
+                                    || gimple_location (g)
+                                       == gimple_location (stmt);
+                         if (!remove && gimple_bb (g) == gimple_bb (stmt)
+                             && tree_int_cst_compare (cur_align, align) == 0)
+                           v.pop ();
                          break;
                        }
                    }
@@ -147,7 +170,7 @@ sanopt_optimize_walker (basic_block bb, struct sanopt_ctx *ctx)
                        }
                      gsi_remove (&gsi, true);
                    }
-                 else if (v.length () < 30)
+                 else
                    v.safe_push (stmt);
                  }
            }
index 80f9bff275d5d64e426077d1720e902a8364d025..003a044eec64948b5733cf27bc6a3f9f34f99bf0 100644 (file)
@@ -1,3 +1,16 @@
+2014-11-06  Marek Polacek  <polacek@redhat.com>
+
+       * c-c++-common/ubsan/align-2.c: Add dg-output.
+       * c-c++-common/ubsan/align-4.c: Likewise.
+       * c-c++-common/ubsan/align-6.c: New test.
+       * c-c++-common/ubsan/align-7.c: New test.
+       * c-c++-common/ubsan/align-8.c: New test.
+       * g++.dg/ubsan/null-1.C: Add dg-output.
+       * g++.dg/ubsan/null-2.C: Likewise.
+       * g++.dg/ubsan/null-3.C: New test.
+       * g++.dg/ubsan/null-4.C: New test.
+       * g++.dg/ubsan/null-5.C: New test.
+
 2014-11-06  Ilya Tocar  <ilya.tocar@intel.com>
 
        * gcc.target/i386/avx512vl-vandnpd-2.c: Fix
index 02a26e2d301a04478cfc9c4f8223f2abdc4a8588..071de8c202a782b7bf363edd196b9ce15ce3f9f3 100644 (file)
@@ -51,4 +51,6 @@ main ()
 /* { dg-output "\.c:(13|16):\[0-9]*: \[^\n\r]*store to misaligned address 0x\[0-9a-fA-F]* for type 'int', which requires 4 byte alignment.*" } */
 /* { dg-output "\.c:23:\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
 /* { dg-output "\.c:(29|30):\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
+/* { dg-output "\.c:30:\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
+/* { dg-output "\.c:31:\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
 /* { dg-output "\.c:37:\[0-9]*: \[^\n\r]*load of misaligned address 0x\[0-9a-fA-F]* for type 'long long int', which requires \[48] byte alignment" } */
index f010589d18891b1410d2edfe83ac3e5e645a86cc..3252595d33014311345cd66362897bd584425d7f 100644 (file)
@@ -9,4 +9,6 @@
 /* { dg-output "\[^\n\r]*\.c:(13|16):\[0-9]*: \[^\n\r]*store to misaligned address 0x\[0-9a-fA-F]* for type 'int', which requires 4 byte alignment.*" } */
 /* { dg-output "\[^\n\r]*\.c:23:\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
 /* { dg-output "\[^\n\r]*\.c:(29|30):\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
+/* { dg-output "\[^\n\r]*\.c:30:\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
+/* { dg-output "\[^\n\r]*\.c:31:\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
 /* { dg-output "\[^\n\r]*\.c:37:\[0-9]*: \[^\n\r]*load of misaligned address 0x\[0-9a-fA-F]* for type 'long long int', which requires \[48] byte alignment" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/align-6.c b/gcc/testsuite/c-c++-common/ubsan/align-6.c
new file mode 100644 (file)
index 0000000..5521292
--- /dev/null
@@ -0,0 +1,33 @@
+/* Limit this to known non-strict alignment targets.  */
+/* { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } } */
+/* { dg-options "-O -fsanitize=alignment -fsanitize-recover=alignment" } */
+
+struct S { int a; char b; long long c; short d[10]; };
+struct T { char a; long long b; };
+struct U { char a; int b; int c; long long d; struct S e; struct T f; } __attribute__((packed));
+struct V { long long a; struct S b; struct T c; struct U u; } v;
+
+__attribute__((noinline, noclone)) int
+foo (struct S *p)
+{
+  volatile int i;
+  i = p->a;
+  i = p->a;
+  i = p->a;
+  i = p->a;
+  return p->a;
+}
+
+int
+main ()
+{
+  if (foo (&v.u.e))
+    __builtin_abort ();
+  return 0;
+}
+
+/* { dg-output "\.c:14:\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
+/* { dg-output "\.c:15:\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
+/* { dg-output "\.c:16:\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
+/* { dg-output "\.c:17:\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
+/* { dg-output "\.c:18:\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/align-7.c b/gcc/testsuite/c-c++-common/ubsan/align-7.c
new file mode 100644 (file)
index 0000000..4a18d8d
--- /dev/null
@@ -0,0 +1,32 @@
+/* Limit this to known non-strict alignment targets.  */
+/* { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } } */
+/* { dg-options "-O -fsanitize=alignment -fno-sanitize-recover=alignment -fdump-tree-sanopt-details" } */
+/* { dg-shouldfail "ubsan" } */
+
+struct S { int a; char b; long long c; short d[10]; };
+struct T { char a; long long b; };
+struct U { char a; int b; int c; long long d; struct S e; struct T f; } __attribute__((packed));
+struct V { long long a; struct S b; struct T c; struct U u; } v;
+
+__attribute__((noinline, noclone)) int
+foo (struct S *p)
+{
+  volatile int i;
+  i = p->a;
+  i = p->a;
+  i = p->a;
+  i = p->a;
+  return p->a;
+}
+
+int
+main ()
+{
+  if (foo (&v.u.e))
+    __builtin_abort ();
+  return 0;
+}
+
+/* { dg-output "\.c:15:\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
+/* { dg-final { scan-tree-dump-times "Optimizing" 4 "sanopt"} } */
+/* { dg-final { cleanup-tree-dump "sanopt" } } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/align-8.c b/gcc/testsuite/c-c++-common/ubsan/align-8.c
new file mode 100644 (file)
index 0000000..b930162
--- /dev/null
@@ -0,0 +1,31 @@
+/* Limit this to known non-strict alignment targets.  */
+/* { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } } */
+/* { dg-options "-O -fsanitize=alignment -fsanitize-undefined-trap-on-error -fdump-tree-sanopt-details" } */
+/* { dg-shouldfail "ubsan" } */
+
+struct S { int a; char b; long long c; short d[10]; };
+struct T { char a; long long b; };
+struct U { char a; int b; int c; long long d; struct S e; struct T f; } __attribute__((packed));
+struct V { long long a; struct S b; struct T c; struct U u; } v;
+
+__attribute__((noinline, noclone)) int
+foo (struct S *p)
+{
+  volatile int i;
+  i = p->a;
+  i = p->a;
+  i = p->a;
+  i = p->a;
+  return p->a;
+}
+
+int
+main ()
+{
+  if (foo (&v.u.e))
+    __builtin_abort ();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "Optimizing" 4 "sanopt"} } */
+/* { dg-final { cleanup-tree-dump "sanopt" } } */
index 83b3033b614900a49ab85d772f0e1292bc2ae336..e1524b1f922e277cf3065ed48738976fb5012513 100644 (file)
@@ -25,4 +25,6 @@ main (void)
 }
 
 // { dg-output "reference binding to null pointer of type 'int'(\n|\r\n|\r)" }
+// { dg-output "\[^\n\r]*reference binding to null pointer of type 'int'(\n|\r\n|\r)" }
 // { dg-output "\[^\n\r]*reference binding to null pointer of type 'const L'(\n|\r\n|\r)" }
+// { dg-output "\[^\n\r]*reference binding to null pointer of type 'int'(\n|\r\n|\r)" }
index 0230c7ca79c98553114934b96c70e39a919c0ff9..88f387e17c917d274e6bc0dabef63b2e3e53a382 100644 (file)
@@ -35,3 +35,5 @@ main (void)
 
 // { dg-output "\.C:26:\[0-9]*:\[\^\n\r]*member call on null pointer of type 'struct U'.*" }
 // { dg-output "\.C:29:\[0-9]*:\[\^\n\r]*member call on null pointer of type 'struct V'.*" }
+// { dg-output "\.C:31:\[0-9]*:\[\^\n\r]*member call on null pointer of type 'struct V'.*" }
+// { dg-output "\.C:33:\[0-9]*:\[\^\n\r]*member call on null pointer of type 'struct V'" }
diff --git a/gcc/testsuite/g++.dg/ubsan/null-3.C b/gcc/testsuite/g++.dg/ubsan/null-3.C
new file mode 100644 (file)
index 0000000..cd3716b
--- /dev/null
@@ -0,0 +1,20 @@
+// { dg-do run }
+// { dg-options "-fsanitize=null" }
+
+int
+main (void)
+{
+  int *p = 0;
+
+  int &r1 = *p;
+  int &r2 = *p;
+  int &r3 = *p;
+  int &r4 = *p;
+  int &r5 = *p;
+}
+
+// { dg-output "reference binding to null pointer of type 'int'(\n|\r\n|\r)" }
+// { dg-output "\[^\n\r]*reference binding to null pointer of type 'int'(\n|\r\n|\r)" }
+// { dg-output "\[^\n\r]*reference binding to null pointer of type 'int'(\n|\r\n|\r)" }
+// { dg-output "\[^\n\r]*reference binding to null pointer of type 'int'(\n|\r\n|\r)" }
+// { dg-output "\[^\n\r]*reference binding to null pointer of type 'int'(\n|\r\n|\r)" }
diff --git a/gcc/testsuite/g++.dg/ubsan/null-4.C b/gcc/testsuite/g++.dg/ubsan/null-4.C
new file mode 100644 (file)
index 0000000..9cb04ef
--- /dev/null
@@ -0,0 +1,19 @@
+// { dg-do run }
+// { dg-options "-O -fsanitize=null -fno-sanitize-recover=null -fdump-tree-sanopt-details" }
+// { dg-shouldfail "ubsan" }
+
+int
+main (void)
+{
+  int *p = 0;
+
+  int &r1 = *p;
+  int &r2 = *p;
+  int &r3 = *p;
+  int &r4 = *p;
+  int &r5 = *p;
+}
+
+// { dg-output "reference binding to null pointer of type 'int'(\n|\r\n|\r)" }
+// { dg-final { scan-tree-dump-times "Optimizing" 4 "sanopt"} }
+// { dg-final { cleanup-tree-dump "sanopt" } }
diff --git a/gcc/testsuite/g++.dg/ubsan/null-5.C b/gcc/testsuite/g++.dg/ubsan/null-5.C
new file mode 100644 (file)
index 0000000..d8e4a68
--- /dev/null
@@ -0,0 +1,18 @@
+// { dg-do run }
+// { dg-options "-O -fsanitize=null -fsanitize-undefined-trap-on-error -fdump-tree-sanopt-details" }
+// { dg-shouldfail "ubsan" }
+
+int
+main (void)
+{
+  int *p = 0;
+
+  int &r1 = *p;
+  int &r2 = *p;
+  int &r3 = *p;
+  int &r4 = *p;
+  int &r5 = *p;
+}
+
+// { dg-final { scan-tree-dump-times "Optimizing" 4 "sanopt"} }
+// { dg-final { cleanup-tree-dump "sanopt" } }