]> gcc.gnu.org Git - gcc.git/commit
c++: Fix get_member_function_from_ptrfunc with -fsanitize=bounds [PR116449]
authorJakub Jelinek <jakub@redhat.com>
Tue, 10 Sep 2024 16:32:58 +0000 (18:32 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 10 Sep 2024 16:42:32 +0000 (18:42 +0200)
commit0008050b9d6046ba4e811a03b406fb5d98707cae
tree814e1e9aa79d7786e54fd51b58b085ac6a96f1af
parent4e1e50458b2004d0f08ac8c64f89b85fc1a87057
c++: Fix get_member_function_from_ptrfunc with -fsanitize=bounds [PR116449]

The following testcase is miscompiled, because
get_member_function_from_ptrfunc
emits something like
(((FUNCTION.__pfn & 1) != 0)
 ? ptr + FUNCTION.__delta + FUNCTION.__pfn - 1
 : FUNCTION.__pfn) (ptr + FUNCTION.__delta, ...)
or so, so FUNCTION tree is used there 5 times.  There is
if (TREE_SIDE_EFFECTS (function)) function = save_expr (function);
but in this case function doesn't have side-effects, just nested ARRAY_REFs.
Now, if all the FUNCTION trees would be shared, it would work fine,
FUNCTION is evaluated in the first operand of COND_EXPR; but unfortunately
that isn't the case, both the BIT_AND_EXPR shortening and conversion to
bool done for build_conditional_expr actually unshare_expr that first
expression, but none of the other 4 are unshared.  With -fsanitize=bounds,
.UBSAN_BOUNDS calls are added to the ARRAY_REFs and use save_expr to avoid
evaluating the argument multiple times, but because that FUNCTION tree is
first used in the second argument of COND_EXPR (i.e. conditionally), the
SAVE_EXPR initialization is done just there and then the third argument
of COND_EXPR just uses the uninitialized temporary and so does the first
argument computation as well.

The following patch fixes that by doing save_expr even if !TREE_SIDE_EFFECTS,
but to avoid doing that too often only if !nonvirtual and if the expression
isn't a simple decl.

2024-09-10  Jakub Jelinek  <jakub@redhat.com>

PR c++/116449
* typeck.cc (get_member_function_from_ptrfunc): Use save_expr
on instance_ptr and function even if it doesn't have side-effects,
as long as it isn't a decl.

* g++.dg/ubsan/pr116449.C: New test.
gcc/cp/typeck.cc
gcc/testsuite/g++.dg/ubsan/pr116449.C [new file with mode: 0644]
This page took 0.055328 seconds and 5 git commands to generate.