Hi.

As always Jakub provided my very nice hint how to fix the issue.
It's about adding representative of a stack partitioning into
asan_handled_variables when another variable of the partition
lies in asan_handled_variables.

Patch survives testing on ppc64le-linux-gnu.
Ready for trunk?

gcc/ChangeLog:

2018-09-21  Martin Liska  <mli...@suse.cz>

        PR sanitizer/85774
        * asan.c: Make asan_handled_variables extern.
        * asan.h: Likewise.
        * cfgexpand.c (expand_stack_vars): Make sure
        a representative is unpoison if another
        variable in the partition is handled by
        use-after-scope sanitization.

gcc/testsuite/ChangeLog:

2018-09-21  Martin Liska  <mli...@suse.cz>

        PR sanitizer/85774
        * g++.dg/asan/pr85774.C: New test.
---
 gcc/asan.c                          |  2 +-
 gcc/asan.h                          |  2 ++
 gcc/cfgexpand.c                     | 14 ++++++++
 gcc/testsuite/g++.dg/asan/pr85774.C | 51 +++++++++++++++++++++++++++++
 4 files changed, 68 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/asan/pr85774.C


diff --git a/gcc/asan.c b/gcc/asan.c
index e71ab2cc710..235e219479d 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -253,7 +253,7 @@ static tree last_alloca_addr;
 /* Set of variable declarations that are going to be guarded by
    use-after-scope sanitizer.  */
 
-static hash_set<tree> *asan_handled_variables = NULL;
+hash_set<tree> *asan_handled_variables = NULL;
 
 hash_set <tree> *asan_used_labels = NULL;
 
diff --git a/gcc/asan.h b/gcc/asan.h
index 412af220597..2f431b4f938 100644
--- a/gcc/asan.h
+++ b/gcc/asan.h
@@ -110,6 +110,8 @@ extern bool asan_sanitize_stack_p (void);
 
 extern bool asan_sanitize_allocas_p (void);
 
+extern hash_set<tree> *asan_handled_variables;
+
 /* Return TRUE if builtin with given FCODE will be intercepted by
    libasan.  */
 
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index c8d7805308c..35ca276e4ad 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -1155,6 +1155,20 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data)
 	      if (repr_decl == NULL_TREE)
 		repr_decl = stack_vars[i].decl;
 	      data->asan_decl_vec.safe_push (repr_decl);
+
+	      /* Make sure a representative is unpoison if another
+		 variable in the partition is handled by
+		 use-after-scope sanitization.  */
+	      if (asan_handled_variables != NULL
+		  && !asan_handled_variables->contains (repr_decl))
+		{
+		  for (j = i; j != EOC; j = stack_vars[j].next)
+		    if (asan_handled_variables->contains (stack_vars[j].decl))
+		      break;
+		  if (j != EOC)
+		    asan_handled_variables->add (repr_decl);
+		}
+
 	      data->asan_alignb = MAX (data->asan_alignb, alignb);
 	      if (data->asan_base == NULL)
 		data->asan_base = gen_reg_rtx (Pmode);
diff --git a/gcc/testsuite/g++.dg/asan/pr85774.C b/gcc/testsuite/g++.dg/asan/pr85774.C
new file mode 100644
index 00000000000..c033abfd69b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/pr85774.C
@@ -0,0 +1,51 @@
+/* PR sanitizer/85774 */
+/* { dg-do run } */
+
+#include <functional>
+
+void
+DoSomething ()
+{
+}
+
+void
+DoFunc (const std::function<void(void)> &func)
+{
+  func ();
+}
+
+void
+Setup ()
+{
+  switch (1)
+    {
+    case 1:
+      {
+	DoFunc ([]() {});
+	break;
+      }
+    case 2:
+      {
+	DoFunc ([]() {});
+	break;
+      }
+    default:
+      break;
+    }
+
+  DoSomething ();
+}
+
+void
+DemostrateBadPoisoning ()
+{
+  DoFunc ([]() {});
+}
+
+int
+main ()
+{
+  Setup ();
+  DemostrateBadPoisoning ();
+  return 0;
+}

Reply via email to