]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
backport: re PR sanitizer/89869 (-fsanitize=undefined miscompilation)
authorJakub Jelinek <jakub@redhat.com>
Fri, 30 Aug 2019 12:34:19 +0000 (14:34 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 30 Aug 2019 12:34:19 +0000 (14:34 +0200)
Backported from mainline
2019-03-29  Jakub Jelinek  <jakub@redhat.com>

PR sanitizer/89869
* typeck.c: Include gimplify.h.
(cp_build_modify_expr) <case COND_EXPR>: Unshare rhs before using it
for second time.  Formatting fixes.

* g++.dg/ubsan/vptr-14.C: New test.

From-SVN: r275145

gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ubsan/vptr-14.C [new file with mode: 0644]

index b4ebbebe9a1b0fc8dd4d89e406cc9b0598557e5b..300eca80f259a054779927bc322c94155e7cc3e3 100644 (file)
@@ -1,6 +1,13 @@
 2019-08-30  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from mainline
+       2019-03-29  Jakub Jelinek  <jakub@redhat.com>
+
+       PR sanitizer/89869
+       * typeck.c: Include gimplify.h.
+       (cp_build_modify_expr) <case COND_EXPR>: Unshare rhs before using it
+       for second time.  Formatting fixes.
+
        2019-03-26  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/89796
index 305444b2d93f03e1dff6519e29fed6aea734002e..ac45316b31272fb975977645cac0c1e2f270fd88 100644 (file)
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "c-family/c-ubsan.h"
 #include "params.h"
 #include "gcc-rich-location.h"
+#include "gimplify.h"
 
 static tree cp_build_addr_expr_strict (tree, tsubst_flags_t);
 static tree cp_build_function_call (tree, tree, tsubst_flags_t);
@@ -7676,8 +7677,6 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
        /* Produce (a ? (b = rhs) : (c = rhs))
           except that the RHS goes through a save-expr
           so the code to compute it is only emitted once.  */
-       tree cond;
-
        if (VOID_TYPE_P (TREE_TYPE (rhs)))
          {
            if (complain & tf_error)
@@ -7692,13 +7691,20 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
        if (!lvalue_or_else (lhs, lv_assign, complain))
          return error_mark_node;
 
-       cond = build_conditional_expr
-         (input_location, TREE_OPERAND (lhs, 0),
-          cp_build_modify_expr (loc, TREE_OPERAND (lhs, 1),
-                                modifycode, rhs, complain),
-          cp_build_modify_expr (loc, TREE_OPERAND (lhs, 2),
-                                modifycode, rhs, complain),
-           complain);
+       tree op1 = cp_build_modify_expr (loc, TREE_OPERAND (lhs, 1),
+                                        modifycode, rhs, complain);
+       /* When sanitizing undefined behavior, even when rhs doesn't need
+          stabilization at this point, the sanitization might add extra
+          SAVE_EXPRs in there and so make sure there is no tree sharing
+          in the rhs, otherwise those SAVE_EXPRs will have initialization
+          only in one of the two branches.  */
+       if (flag_sanitize & (SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT))
+         rhs = unshare_expr (rhs);
+       tree op2 = cp_build_modify_expr (loc, TREE_OPERAND (lhs, 2),
+                                        modifycode, rhs, complain);
+       tree cond = build_conditional_expr (input_location,
+                                           TREE_OPERAND (lhs, 0), op1, op2,
+                                           complain);
 
        if (cond == error_mark_node)
          return cond;
index 0f6129a4ba2349f1b377c4d09c7675f6944178e1..458115358c34eb6c0bae248561c0bd742a5574a0 100644 (file)
@@ -3,6 +3,9 @@
        Backported from mainline
        2019-03-29  Jakub Jelinek  <jakub@redhat.com>
 
+       PR sanitizer/89869
+       * g++.dg/ubsan/vptr-14.C: New test.
+
        PR c/89872
        * gcc.dg/tree-ssa/pr89872.c: New test.
 
diff --git a/gcc/testsuite/g++.dg/ubsan/vptr-14.C b/gcc/testsuite/g++.dg/ubsan/vptr-14.C
new file mode 100644 (file)
index 0000000..2247ad9
--- /dev/null
@@ -0,0 +1,18 @@
+// PR sanitizer/89869
+// { dg-do run }
+// { dg-options "-fsanitize=vptr -fno-sanitize-recover=vptr" }
+
+struct S { S *s = 0; virtual ~S () {} };
+
+void
+foo (S *x, S *y)
+{
+  (x->s ? y : x) = x->s;
+}
+
+int
+main ()
+{
+  S a;
+  foo (&a, 0);
+}