With -fstrong-eval-order=all we evaluate the function address before the
arguments. But this caused trouble with virtual functions and
-fsanitize=vptr; we would do vptr sanitization as part of calculating the
'this' argument, and separately look at the vptr in order to find the
function address. Without -fstrong-eval-order=all 'this' is evaluated
first, but with that flag the function address is evaluated first, so we
would access the null vptr before sanitizing it.
Fixed by instrumenting the OBJ_TYPE_REF of a virtual function call instead
of the 'this' argument.
This issue suggests that we should be running the ubsan tests in multiple
standard modes like the rest of the G++ testsuite, so I've made that change
as well. The testcase changes are all to accommodate that.
gcc/cp/ChangeLog:
* cp-ubsan.c (cp_ubsan_maybe_instrument_member_call): For a virtual
call, instrument the OBJ_TYPE_REF.
gcc/testsuite/ChangeLog:
* g++.dg/ubsan/ubsan.exp: Use g++-dg-runtest.
* c-c++-common/ubsan/bounds-13.c: Adjust.
* c-c++-common/ubsan/bounds-2.c: Adjust.
* c-c++-common/ubsan/div-by-zero-1.c: Adjust.
* c-c++-common/ubsan/div-by-zero-6.c: Adjust.
* c-c++-common/ubsan/div-by-zero-7.c: Adjust.
* c-c++-common/ubsan/overflow-add-1.c: Adjust.
* c-c++-common/ubsan/overflow-add-2.c: Adjust.
* c-c++-common/ubsan/overflow-int128.c: Adjust.
* c-c++-common/ubsan/overflow-sub-1.c: Adjust.
* c-c++-common/ubsan/overflow-sub-2.c: Adjust.
* g++.dg/ubsan/pr85029.C: Adjust.
* g++.dg/ubsan/vptr-14.C: Adjust.
---
gcc/cp/cp-ubsan.c | 33 +++++++++++++++----
gcc/testsuite/c-c++-common/ubsan/bounds-13.c | 1 +
gcc/testsuite/c-c++-common/ubsan/bounds-2.c | 1 +
.../c-c++-common/ubsan/div-by-zero-1.c | 1 +
.../c-c++-common/ubsan/div-by-zero-6.c | 1 +
.../c-c++-common/ubsan/div-by-zero-7.c | 1 +
.../c-c++-common/ubsan/overflow-add-1.c | 1 +
.../c-c++-common/ubsan/overflow-add-2.c | 1 +
.../c-c++-common/ubsan/overflow-int128.c | 1 +
.../c-c++-common/ubsan/overflow-sub-1.c | 1 +
.../c-c++-common/ubsan/overflow-sub-2.c | 1 +
gcc/testsuite/g++.dg/ubsan/pr85029.C | 2 +-
gcc/testsuite/g++.dg/ubsan/vptr-14.C | 2 +-
gcc/testsuite/g++.dg/ubsan/ubsan.exp | 2 +-
14 files changed, 39 insertions(+), 10 deletions(-)
diff --git a/gcc/cp/cp-ubsan.c b/gcc/cp/cp-ubsan.c
index b064a98202a..c40dac72b42 100644
--- a/gcc/cp/cp-ubsan.c
+++ b/gcc/cp/cp-ubsan.c
@@ -118,14 +118,33 @@ cp_ubsan_maybe_instrument_member_call (tree stmt)
{
if (call_expr_nargs (stmt) == 0)
return;
- tree *opp = &CALL_EXPR_ARG (stmt, 0);
- tree op = *opp;
- if (op == error_mark_node
- || !INDIRECT_TYPE_P (TREE_TYPE (op)))
- return;
- while (TREE_CODE (op) == COMPOUND_EXPR)
+ tree op, *opp;
+
+ tree fn = CALL_EXPR_FN (stmt);
+ if (fn && TREE_CODE (fn) == OBJ_TYPE_REF)
{
- opp = &TREE_OPERAND (op, 1);
+ /* Virtual function call: Sanitize the use of the object pointer in the
+ OBJ_TYPE_REF, since the vtable reference will SEGV otherwise (95221).
+ OBJ_TYPE_REF_EXPR is ptr->vptr[N] and OBJ_TYPE_REF_OBJECT is ptr. */
+ opp = &OBJ_TYPE_REF_EXPR (fn);
+ op = OBJ_TYPE_REF_OBJECT (fn);
+ while (*opp != op)
+ {
+ if (TREE_CODE (*opp) == COMPOUND_EXPR)
+ opp = &TREE_OPERAND (*opp, 1);
+ else
+ opp = &TREE_OPERAND (*opp, 0);
+ }
+ }
+ else
+ {
+ /* Non-virtual call: Sanitize the 'this' argument. */
+ opp = &CALL_EXPR_ARG (stmt, 0);
+ if (*opp == error_mark_node
+ || !INDIRECT_TYPE_P (TREE_TYPE (*opp)))
+ return;
+ while (TREE_CODE (*opp) == COMPOUND_EXPR)
+ opp = &TREE_OPERAND (*opp, 1);
op = *opp;
}
op = cp_ubsan_maybe_instrument_vptr (EXPR_LOCATION (stmt), op,
diff --git a/gcc/testsuite/c-c++-common/ubsan/bounds-13.c
b/gcc/testsuite/c-c++-common/ubsan/bounds-13.c
index 25b0467ec67..a8bce370f8f 100644
--- a/gcc/testsuite/c-c++-common/ubsan/bounds-13.c
+++ b/gcc/testsuite/c-c++-common/ubsan/bounds-13.c
@@ -1,6 +1,7 @@
/* PR sanitizer/71498 */
/* { dg-do run } */
/* { dg-options "-fsanitize=bounds -Wno-array-bounds" } */
+/* { dg-options "-fsanitize=bounds -Wno-array-bounds -Wno-volatile" { target
c++ } } */
struct S { int a[100]; int b, c; } s;
diff --git a/gcc/testsuite/c-c++-common/ubsan/bounds-2.c
b/gcc/testsuite/c-c++-common/ubsan/bounds-2.c
index 56654486f65..ec4ef7eed20 100644
--- a/gcc/testsuite/c-c++-common/ubsan/bounds-2.c
+++ b/gcc/testsuite/c-c++-common/ubsan/bounds-2.c
@@ -1,5 +1,6 @@
/* { dg-do run } */
/* { dg-options "-fsanitize=bounds -Wall -Wextra -Wno-unused -Wno-array-bounds
-Wno-uninitialized" } */
+/* { dg-options "-fsanitize=bounds -Wall -Wextra -Wno-unused -Wno-array-bounds
-Wno-uninitialized -Wno-volatile" { target c++ } } */
/* Test runtime errors. */
diff --git a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-1.c
b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-1.c
index 479ced038fb..8b62ae743d8 100644
--- a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-1.c
@@ -1,5 +1,6 @@
/* { dg-do run } */
/* { dg-options "-fsanitize=integer-divide-by-zero -Wno-div-by-zero" } */
+/* { dg-options "-fsanitize=integer-divide-by-zero -Wno-div-by-zero
-Wno-volatile" { target c++ } } */
int
main (void)
diff --git a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-6.c
b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-6.c
index 27a18bb096e..be017ad8179 100644
--- a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-6.c
+++ b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-6.c
@@ -1,5 +1,6 @@
/* { dg-do run } */
/* { dg-options "-fsanitize=integer-divide-by-zero -Wno-div-by-zero" } */
+/* { dg-options "-fsanitize=integer-divide-by-zero -Wno-div-by-zero
-Wno-volatile" { target c++ } } */
#include <stdio.h>
diff --git a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-7.c
b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-7.c
index 5f53bef74ea..643b76af143 100644
--- a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-7.c
+++ b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-7.c
@@ -1,5 +1,6 @@
/* { dg-do run } */
/* { dg-options "-fsanitize=integer-divide-by-zero -Wno-div-by-zero
-fno-sanitize-recover=integer-divide-by-zero" } */
+/* { dg-options "-fsanitize=integer-divide-by-zero -Wno-div-by-zero
-fno-sanitize-recover=integer-divide-by-zero -Wno-volatile" { target c++ } } */
/* { dg-shouldfail "ubsan" } */
#include <stdio.h>
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-add-1.c
b/gcc/testsuite/c-c++-common/ubsan/overflow-add-1.c
index 960f1b0afaf..3c0a17edb85 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-add-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-add-1.c
@@ -1,5 +1,6 @@
/* { dg-do run } */
/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable
-fno-sanitize-recover=signed-integer-overflow" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable
-fno-sanitize-recover=signed-integer-overflow -Wno-volatile" { target c++ } } */
#define SCHAR_MAX __SCHAR_MAX__
#define SHRT_MAX __SHRT_MAX__
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-add-2.c
b/gcc/testsuite/c-c++-common/ubsan/overflow-add-2.c
index b104d6158fe..8fa9074647a 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-add-2.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-add-2.c
@@ -1,5 +1,6 @@
/* { dg-do run } */
/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable
-Wno-volatile" { target c++ } } */
#define INT_MAX __INT_MAX__
#define INT_MIN (-__INT_MAX__ - 1)
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-int128.c
b/gcc/testsuite/c-c++-common/ubsan/overflow-int128.c
index 400f25b01e1..10ccc79d0fe 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-int128.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-int128.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-require-effective-target int128 } */
/* { dg-options "-fsanitize=signed-integer-overflow" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-volatile" { target
c++ } } */
/* 2^127 - 1 */
#define INT128_MAX (__int128) (((unsigned __int128) 1 << ((__SIZEOF_INT128__ *
__CHAR_BIT__) - 1)) - 1)
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-sub-1.c
b/gcc/testsuite/c-c++-common/ubsan/overflow-sub-1.c
index e92aaf4ce33..7ceb4ec60a7 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-sub-1.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-sub-1.c
@@ -1,5 +1,6 @@
/* { dg-do run } */
/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable
-fno-sanitize-recover=signed-integer-overflow" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable
-fno-sanitize-recover=signed-integer-overflow -Wno-volatile" { target c++ } } */
#define SCHAR_MAX __SCHAR_MAX__
#define SCHAR_MIN (-__SCHAR_MAX__ - 1)
diff --git a/gcc/testsuite/c-c++-common/ubsan/overflow-sub-2.c
b/gcc/testsuite/c-c++-common/ubsan/overflow-sub-2.c
index cc94061634e..92a2ea28af2 100644
--- a/gcc/testsuite/c-c++-common/ubsan/overflow-sub-2.c
+++ b/gcc/testsuite/c-c++-common/ubsan/overflow-sub-2.c
@@ -1,5 +1,6 @@
/* { dg-do run } */
/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable
-Wno-volatile" { target c++ } } */
#define INT_MAX __INT_MAX__
#define INT_MIN (-__INT_MAX__ - 1)
diff --git a/gcc/testsuite/g++.dg/ubsan/pr85029.C
b/gcc/testsuite/g++.dg/ubsan/pr85029.C
index 07472af16a5..836ce69cc15 100644
--- a/gcc/testsuite/g++.dg/ubsan/pr85029.C
+++ b/gcc/testsuite/g++.dg/ubsan/pr85029.C
@@ -1,7 +1,7 @@
// PR sanitizer/85029
// { dg-do compile }
// { dg-skip-if "" { *-*-* } { "-flto -fno-fat-lto-objects" } }
-// { dg-options "-fsanitize=undefined" }
+// { dg-options "-fsanitize=undefined -Wno-register" }
struct B {
virtual B bar ();
diff --git a/gcc/testsuite/g++.dg/ubsan/vptr-14.C
b/gcc/testsuite/g++.dg/ubsan/vptr-14.C
index 2247ad99fcc..06cd66347d4 100644
--- a/gcc/testsuite/g++.dg/ubsan/vptr-14.C
+++ b/gcc/testsuite/g++.dg/ubsan/vptr-14.C
@@ -1,5 +1,5 @@
// PR sanitizer/89869
-// { dg-do run }
+// { dg-do run { target c++11 } }
// { dg-options "-fsanitize=vptr -fno-sanitize-recover=vptr" }
struct S { S *s = 0; virtual ~S () {} };
diff --git a/gcc/testsuite/g++.dg/ubsan/ubsan.exp
b/gcc/testsuite/g++.dg/ubsan/ubsan.exp
index 11b92bff980..2bc98831d2e 100644
--- a/gcc/testsuite/g++.dg/ubsan/ubsan.exp
+++ b/gcc/testsuite/g++.dg/ubsan/ubsan.exp
@@ -26,7 +26,7 @@ ubsan_init
# Main loop.
if [check_effective_target_fsanitize_undefined] {
- gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C
$srcdir/c-c++-common/ubsan/*.c]] "" ""
+ g++-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C
$srcdir/c-c++-common/ubsan/*.c]] "" ""
}
# All done.
base-commit: 2221fb6f668a7edc8b8aad69772907aeabbbb0be
--
2.18.1