From: Jakub Jelinek Date: Fri, 30 Aug 2019 12:34:19 +0000 (+0200) Subject: backport: re PR sanitizer/89869 (-fsanitize=undefined miscompilation) X-Git-Tag: releases/gcc-7.5.0~218 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8247363d9ad45f945d5145968d286bd23ba8080d;p=thirdparty%2Fgcc.git backport: re PR sanitizer/89869 (-fsanitize=undefined miscompilation) Backported from mainline 2019-03-29 Jakub Jelinek PR sanitizer/89869 * typeck.c: Include gimplify.h. (cp_build_modify_expr) : Unshare rhs before using it for second time. Formatting fixes. * g++.dg/ubsan/vptr-14.C: New test. From-SVN: r275145 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b4ebbebe9a1b..300eca80f259 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,6 +1,13 @@ 2019-08-30 Jakub Jelinek Backported from mainline + 2019-03-29 Jakub Jelinek + + PR sanitizer/89869 + * typeck.c: Include gimplify.h. + (cp_build_modify_expr) : Unshare rhs before using it + for second time. Formatting fixes. + 2019-03-26 Jakub Jelinek PR c++/89796 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 305444b2d93f..ac45316b3127 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0f6129a4ba23..458115358c34 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -3,6 +3,9 @@ Backported from mainline 2019-03-29 Jakub Jelinek + 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 index 000000000000..2247ad99fccf --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/vptr-14.C @@ -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); +}