aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2022-02-12 19:17:44 +0100
committerJakub Jelinek <jakub@redhat.com>2022-02-12 19:17:44 +0100
commitf0c7367b8802c47efaad87b1f2126fe6350d8b47 (patch)
treedf53385c4613bae236711f681d0289f74be4ffa5
parent5c4258d7c78a92ab17c14dec1163d87fc42ff019 (diff)
downloadgcc-f0c7367b8802c47efaad87b1f2126fe6350d8b47.zip
gcc-f0c7367b8802c47efaad87b1f2126fe6350d8b47.tar.gz
gcc-f0c7367b8802c47efaad87b1f2126fe6350d8b47.tar.bz2
asan: Fix up address sanitizer instrumentation of __builtin_alloca* if it can throw [PR104449]
With -fstack-check* __builtin_alloca* can throw and the asan instrumentation of this builtin wasn't prepared for that case. The following patch fixes that by replacing the builtin with the replacement builtin and emitting any further insns on the fallthru edge. I haven't touched the hwasan code which most likely suffers from the same problem. 2022-02-12 Jakub Jelinek <jakub@redhat.com> PR sanitizer/104449 * asan.cc: Include tree-eh.h. (handle_builtin_alloca): Handle the case when __builtin_alloca or __builtin_alloca_with_align can throw. * gcc.dg/asan/pr104449.c: New test. * g++.dg/asan/pr104449.C: New test.
-rw-r--r--gcc/asan.cc50
-rw-r--r--gcc/testsuite/g++.dg/asan/pr104449.C16
-rw-r--r--gcc/testsuite/gcc.dg/asan/pr104449.c12
3 files changed, 71 insertions, 7 deletions
diff --git a/gcc/asan.cc b/gcc/asan.cc
index b347173..6046b80 100644
--- a/gcc/asan.cc
+++ b/gcc/asan.cc
@@ -63,6 +63,7 @@ along with GCC; see the file COPYING3. If not see
#include "fnmatch.h"
#include "tree-inline.h"
#include "tree-ssa.h"
+#include "tree-eh.h"
/* AddressSanitizer finds out-of-bounds and use-after-free bugs
with <2x slowdown on average.
@@ -726,14 +727,24 @@ handle_builtin_alloca (gcall *call, gimple_stmt_iterator *iter)
gassign *g;
gcall *gg;
tree callee = gimple_call_fndecl (call);
+ tree lhs = gimple_call_lhs (call);
tree old_size = gimple_call_arg (call, 0);
- tree ptr_type = gimple_call_lhs (call) ? TREE_TYPE (gimple_call_lhs (call))
- : ptr_type_node;
+ tree ptr_type = lhs ? TREE_TYPE (lhs) : ptr_type_node;
tree partial_size = NULL_TREE;
unsigned int align
= DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA
? 0 : tree_to_uhwi (gimple_call_arg (call, 1));
+ bool throws = false;
+ edge e = NULL;
+ if (stmt_can_throw_internal (cfun, call))
+ {
+ if (!lhs)
+ return;
+ throws = true;
+ e = find_fallthru_edge (gsi_bb (*iter)->succs);
+ }
+
if (hwasan_sanitize_allocas_p ())
{
gimple_seq stmts = NULL;
@@ -852,29 +863,54 @@ handle_builtin_alloca (gcall *call, gimple_stmt_iterator *iter)
build_int_cst (size_type_node, align));
tree new_alloca_with_rz = make_ssa_name (ptr_type, gg);
gimple_call_set_lhs (gg, new_alloca_with_rz);
- gsi_insert_before (iter, gg, GSI_SAME_STMT);
+ if (throws)
+ {
+ gimple_call_set_lhs (call, NULL);
+ gsi_replace (iter, gg, true);
+ }
+ else
+ gsi_insert_before (iter, gg, GSI_SAME_STMT);
/* new_alloca = new_alloca_with_rz + align. */
g = gimple_build_assign (make_ssa_name (ptr_type), POINTER_PLUS_EXPR,
new_alloca_with_rz,
build_int_cst (size_type_node,
align / BITS_PER_UNIT));
- gsi_insert_before (iter, g, GSI_SAME_STMT);
+ gimple_stmt_iterator gsi = gsi_none ();
+ if (throws)
+ {
+ gsi_insert_on_edge_immediate (e, g);
+ gsi = gsi_for_stmt (g);
+ }
+ else
+ gsi_insert_before (iter, g, GSI_SAME_STMT);
tree new_alloca = gimple_assign_lhs (g);
/* Poison newly created alloca redzones:
__asan_alloca_poison (new_alloca, old_size). */
fn = builtin_decl_implicit (BUILT_IN_ASAN_ALLOCA_POISON);
gg = gimple_build_call (fn, 2, new_alloca, old_size);
- gsi_insert_before (iter, gg, GSI_SAME_STMT);
+ if (throws)
+ gsi_insert_after (&gsi, gg, GSI_NEW_STMT);
+ else
+ gsi_insert_before (iter, gg, GSI_SAME_STMT);
/* Save new_alloca_with_rz value into last_alloca to use it during
allocas unpoisoning. */
g = gimple_build_assign (last_alloca, new_alloca_with_rz);
- gsi_insert_before (iter, g, GSI_SAME_STMT);
+ if (throws)
+ gsi_insert_after (&gsi, g, GSI_NEW_STMT);
+ else
+ gsi_insert_before (iter, g, GSI_SAME_STMT);
/* Finally, replace old alloca ptr with NEW_ALLOCA. */
- replace_call_with_value (iter, new_alloca);
+ if (throws)
+ {
+ g = gimple_build_assign (lhs, new_alloca);
+ gsi_insert_after (&gsi, g, GSI_NEW_STMT);
+ }
+ else
+ replace_call_with_value (iter, new_alloca);
}
/* Return the memory references contained in a gimple statement
diff --git a/gcc/testsuite/g++.dg/asan/pr104449.C b/gcc/testsuite/g++.dg/asan/pr104449.C
new file mode 100644
index 0000000..166ed8d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/pr104449.C
@@ -0,0 +1,16 @@
+// PR sanitizer/104449
+// { dg-do compile }
+// { dg-options "-fexceptions -fsanitize=address -fstack-check=generic" }
+
+void bar (int *);
+struct A { A (); ~A (); };
+
+void
+foo (int n)
+{
+ A b;
+ {
+ int a[n];
+ bar (a);
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/asan/pr104449.c b/gcc/testsuite/gcc.dg/asan/pr104449.c
new file mode 100644
index 0000000..5054027
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asan/pr104449.c
@@ -0,0 +1,12 @@
+/* PR sanitizer/104449 */
+/* { dg-do compile } */
+/* { dg-options "-fexceptions -fsanitize=address -fstack-check=generic" } */
+
+void bar (int *);
+
+void
+foo (void)
+{
+ int a[16];
+ bar (a);
+}