diff mbox

Fix not caught use-after-scope with -O1 (PR sanitize/78106)

Message ID 8fb63eca-0d92-efc1-8497-d3e2c8e14e07@suse.cz
State New
Headers show

Commit Message

Martin Liška Oct. 25, 2016, 11:40 a.m. UTC
Hello.

While reading and trying to understand sanopt code, I've noticed that we can possibly
optimize out a ASAN_CHECK when there's a BB in between DOM(BB) and BB which can
call a freeing function.

Ready to be installed after it survives regression tests?
Martin

Comments

Jakub Jelinek Oct. 25, 2016, 11:52 a.m. UTC | #1
On Tue, Oct 25, 2016 at 01:40:03PM +0200, Martin Liška wrote:
> While reading and trying to understand sanopt code, I've noticed that we can possibly
> optimize out a ASAN_CHECK when there's a BB in between DOM(BB) and BB which can
> call a freeing function.
> 
> Ready to be installed after it survives regression tests?
> Martin

> >From d8ed43c1f8e29cfe63ebd7c40a76715c9c644522 Mon Sep 17 00:00:00 2001
> From: marxin <mliska@suse.cz>
> Date: Tue, 25 Oct 2016 13:29:47 +0200
> Subject: [PATCH] Fix not caught use-after-scope with -O1 (PR sanitize/78106)
> 
> gcc/ChangeLog:
> 
> 2016-10-25  Martin Liska  <mliska@suse.cz>
> 
> 	PR sanitizer/78106
> 	* sanopt.c (imm_dom_path_with_freeing_call): Handle gasm
> 	statements as they can also contain possibly a freeing call.

Other places use something like
      if ((gimple_code (stmt) == GIMPLE_ASM && gimple_vdef (stmt))
          || (is_gimple_call (stmt)
              && (!nonfreeing_call_p (stmt) || !nonbarrier_call_p (stmt))))
though what you added matches more what ipa-pure-const.c does, ok.

> gcc/testsuite/ChangeLog:
> 
> 2016-10-25  Martin Liska  <mliska@suse.cz>
> 
> 	PR sanitizer/78106
> 	* gcc.dg/asan/pr78106.c: New test.

The test is bad.  1) asan is supported on various architectures, call release
is x86 specific, and even there on some OSes the syntax might be different
(_release, etc.?) 2) you aren't trying to maintain required stack alignment

So, I think it would be better to just use dg-do compile and just scan some
dump.

	Jakub
diff mbox

Patch

From d8ed43c1f8e29cfe63ebd7c40a76715c9c644522 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Tue, 25 Oct 2016 13:29:47 +0200
Subject: [PATCH] Fix not caught use-after-scope with -O1 (PR sanitize/78106)

gcc/ChangeLog:

2016-10-25  Martin Liska  <mliska@suse.cz>

	PR sanitizer/78106
	* sanopt.c (imm_dom_path_with_freeing_call): Handle gasm
	statements as they can also contain possibly a freeing call.

gcc/testsuite/ChangeLog:

2016-10-25  Martin Liska  <mliska@suse.cz>

	PR sanitizer/78106
	* gcc.dg/asan/pr78106.c: New test.
---
 gcc/sanopt.c                        |  6 +++++-
 gcc/testsuite/gcc.dg/asan/pr78106.c | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/asan/pr78106.c

diff --git a/gcc/sanopt.c b/gcc/sanopt.c
index 27c43da..8a6fbe9 100644
--- a/gcc/sanopt.c
+++ b/gcc/sanopt.c
@@ -211,8 +211,12 @@  imm_dom_path_with_freeing_call (basic_block bb, basic_block dom)
       for (gsi = gsi_start_bb (e->src); !gsi_end_p (gsi); gsi_next (&gsi))
 	{
 	  gimple *stmt = gsi_stmt (gsi);
+	  gasm *asm_stmt;
 
-	  if (is_gimple_call (stmt) && !nonfreeing_call_p (stmt))
+	  if ((is_gimple_call (stmt) && !nonfreeing_call_p (stmt))
+	      || ((asm_stmt = dyn_cast <gasm *> (stmt))
+		  && (gimple_asm_clobbers_memory_p (asm_stmt)
+		      || gimple_asm_volatile_p (asm_stmt))))
 	    {
 	      pred_info->has_freeing_call_p = true;
 	      break;
diff --git a/gcc/testsuite/gcc.dg/asan/pr78106.c b/gcc/testsuite/gcc.dg/asan/pr78106.c
new file mode 100644
index 0000000..7c0e05e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asan/pr78106.c
@@ -0,0 +1,34 @@ 
+/* PR sanitizer/78106 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=address" } */
+/* { dg-shouldfail "asan" } */
+
+int *variable;
+
+void __attribute__((used)) release()
+{
+  __builtin_free (variable);
+}
+
+int main2(int argc)
+{
+  *variable = 2;
+
+  if (argc <= 5)
+    asm volatile ("call release");
+
+  *variable = 2;
+  __builtin_abort ();
+
+  return 0;
+}
+
+int main(int argc, char **argv)
+{
+  variable = __builtin_malloc (sizeof(int));
+  return main2(argc);
+}
+
+/* { dg-output "ERROR: AddressSanitizer:? heap-use-after-free on address.*(\n|\r\n|\r)" } */
+/* { dg-output "WRITE of size 4 at.*" } */
+/* { dg-output "    #0 0x\[0-9a-f\]+ +in _*main2 .*" } */
-- 
2.10.1