[libcxx-commits] [llvm] [compiler-rt] [libcxx] [clang] [mlir] [asan] Enable StackSafetyAnalysis by default (PR #77210)

Fangrui Song via libcxx-commits libcxx-commits at lists.llvm.org
Sun Jan 7 09:43:17 PST 2024


https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/77210

>From af33fcdf5a46c5bd34db89615a037e5eca421ef9 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Fri, 5 Jan 2024 23:50:40 -0800
Subject: [PATCH] [asan] Enable StackSafetyAnalysis by default

StackSafetyAnalysis determines whether stack-allocated variables are
safe from memory access bugs and allows removing certain unneeded
instrumentations.
(hwasan enables StackSafetyAnalysis in https://reviews.llvm.org/D108381)

Test updates:

* asan-stack-safety.ll: test the -asan-use-stack-safety=1 default
* lifetime-uar-uas.ll: switch to an indexed store to prevent
  StackSafetyAnalysis from optimizing out instrumentation for %c
* alloca_vla_interact.cpp: add a load to prevent StackSafetyAnalysis
  from optimizing out `__asan_alloca_poison` for the VLA `array`
* scariness_score_test.cpp: add -asan-use-stack-safety=0 to make a load
  of a `__asan_poison_memory_region`-poisoned local variable fail as
  intended.
* other .ll tests: add -asan-use-stack-safety=0

Pull Request: https://github.com/llvm/llvm-project/pull/77210
---
 .../test/asan/TestCases/alloca_vla_interact.cpp     |  2 ++
 .../test/asan/TestCases/scariness_score_test.cpp    |  6 ++++--
 .../Transforms/Instrumentation/AddressSanitizer.cpp |  2 +-
 .../AddressSanitizer/asan-stack-safety.ll           |  2 +-
 .../Instrumentation/AddressSanitizer/debug_info.ll  |  2 +-
 .../AddressSanitizer/lifetime-uar-uas.ll            | 13 ++++++++-----
 .../Instrumentation/AddressSanitizer/lifetime.ll    |  4 ++--
 .../AddressSanitizer/local_stack_base.ll            |  2 +-
 .../AddressSanitizer/stack_dynamic_alloca.ll        |  8 ++++----
 .../AddressSanitizer/stack_layout.ll                |  4 ++--
 10 files changed, 26 insertions(+), 19 deletions(-)

diff --git a/compiler-rt/test/asan/TestCases/alloca_vla_interact.cpp b/compiler-rt/test/asan/TestCases/alloca_vla_interact.cpp
index 92b0afafc8db77..96ac4c7db291a0 100644
--- a/compiler-rt/test/asan/TestCases/alloca_vla_interact.cpp
+++ b/compiler-rt/test/asan/TestCases/alloca_vla_interact.cpp
@@ -33,6 +33,8 @@ __attribute__((noinline)) void foo(int len) {
     if (i) assert(!__asan_region_is_poisoned(bot, 96));
     // VLA is unpoisoned at the end of iteration.
     volatile char array[i];
+    // Ensure that asan-use-stack-safety does not optimize out the poisoning.
+    if (i) array[0] = 0;
     assert(!(reinterpret_cast<uintptr_t>(array) & 31L));
     // Alloca is unpoisoned at the end of iteration,
     // because dominated by VLA.
diff --git a/compiler-rt/test/asan/TestCases/scariness_score_test.cpp b/compiler-rt/test/asan/TestCases/scariness_score_test.cpp
index d73975feb6873b..9e55e33675fde3 100644
--- a/compiler-rt/test/asan/TestCases/scariness_score_test.cpp
+++ b/compiler-rt/test/asan/TestCases/scariness_score_test.cpp
@@ -1,7 +1,9 @@
 // Test how we produce the scariness score.
 
 // UAR Mode: runtime
-// RUN: %clangxx_asan -O0 %s -o %t
+// Case 26 loads a __asan_poison_memory_region-poisoned local variable, which is
+// only instrumented when StackSafetyAnalysis is disabled.
+// RUN: %clangxx_asan -O0 -mllvm -asan-use-stack-safety=0 %s -o %t
 // On OSX and Windows, alloc_dealloc_mismatch=1 isn't 100% reliable, so it's
 // off by default. It's safe for these tests, though, so we turn it on.
 // RUN: export %env_asan_opts=symbolize=0:detect_stack_use_after_return=1:handle_abort=1:print_scariness=1:alloc_dealloc_mismatch=1
@@ -36,7 +38,7 @@
 // RUN: not %run %t 27 2>&1 | FileCheck %s --check-prefix=CHECK27
 //
 // UAR Mode: always
-// RUN: %clangxx_asan -O0 %s -o %t -fsanitize-address-use-after-return=always
+// RUN: %clangxx_asan -O0 %s -o %t -fsanitize-address-use-after-return=always -mllvm -asan-use-stack-safety=0
 // On OSX and Windows, alloc_dealloc_mismatch=1 isn't 100% reliable, so it's
 // off by default. It's safe for these tests, though, so we turn it on.
 // RUN: export %env_asan_opts=symbolize=0:handle_abort=1:print_scariness=1:alloc_dealloc_mismatch=1
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index e3deafa49bd91e..5e7e08eaa9978d 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -216,7 +216,7 @@ static cl::opt<bool> ClInstrumentWrites(
     cl::Hidden, cl::init(true));
 
 static cl::opt<bool>
-    ClUseStackSafety("asan-use-stack-safety", cl::Hidden, cl::init(false),
+    ClUseStackSafety("asan-use-stack-safety", cl::Hidden, cl::init(true),
                      cl::Hidden, cl::desc("Use Stack Safety analysis results"),
                      cl::Optional);
 
diff --git a/llvm/test/Instrumentation/AddressSanitizer/asan-stack-safety.ll b/llvm/test/Instrumentation/AddressSanitizer/asan-stack-safety.ll
index 02c58a1f492261..8210970aaaeb4b 100644
--- a/llvm/test/Instrumentation/AddressSanitizer/asan-stack-safety.ll
+++ b/llvm/test/Instrumentation/AddressSanitizer/asan-stack-safety.ll
@@ -1,7 +1,7 @@
 ; REQUIRES: x86-registered-target
 
 ; RUN: opt < %s -S -asan-instrumentation-with-call-threshold=0 -passes=asan -asan-use-stack-safety=0 -o - | FileCheck %s --implicit-check-not="call {{.*}} @__asan_{{load|store|stack}}" --check-prefixes=CHECK,NOSAFETY
-; RUN: opt < %s -S -asan-instrumentation-with-call-threshold=0 -passes=asan -asan-use-stack-safety=1 -o - | FileCheck %s --implicit-check-not="call {{.*}} @__asan_{{load|store|stack}}"
+; RUN: opt < %s -S -asan-instrumentation-with-call-threshold=0 -passes=asan | FileCheck %s --implicit-check-not="call {{.*}} @__asan_{{load|store|stack}}"
 
 ; CHECK-LABEL: define i32 @load
 define i32 @load() sanitize_address {
diff --git a/llvm/test/Instrumentation/AddressSanitizer/debug_info.ll b/llvm/test/Instrumentation/AddressSanitizer/debug_info.ll
index 4c678f984864ae..edd63c614857fe 100644
--- a/llvm/test/Instrumentation/AddressSanitizer/debug_info.ll
+++ b/llvm/test/Instrumentation/AddressSanitizer/debug_info.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -passes=asan -asan-use-after-return=never -S | FileCheck %s
+; RUN: opt < %s -passes=asan -asan-use-after-return=never -asan-use-stack-safety=0 -S | FileCheck %s
 
 ; Checks that llvm.dbg.declare instructions are updated
 ; accordingly as we merge allocas.
diff --git a/llvm/test/Instrumentation/AddressSanitizer/lifetime-uar-uas.ll b/llvm/test/Instrumentation/AddressSanitizer/lifetime-uar-uas.ll
index 302205c4f6cad0..a40dad526a14dc 100644
--- a/llvm/test/Instrumentation/AddressSanitizer/lifetime-uar-uas.ll
+++ b/llvm/test/Instrumentation/AddressSanitizer/lifetime-uar-uas.ll
@@ -11,26 +11,29 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3
 declare void @llvm.lifetime.start.p0(i64, ptr nocapture) nounwind
 declare void @llvm.lifetime.end.p0(i64, ptr nocapture) nounwind
 
-define i32 @basic_test() sanitize_address {
-  ; CHECK-LABEL: define i32 @basic_test()
+define i32 @basic_test(i64 %i) sanitize_address {
+  ; CHECK-LABEL: define i32 @basic_test(
 
 entry:
   %retval = alloca i32, align 4
-  %c = alloca i8, align 1
+  %c = alloca [2 x i8], align 1
 
   ; Memory is poisoned in prologue: F1F1F1F104F3F8F2
   ; CHECK-UAS: store i64 -866676825215864335, ptr %{{[0-9]+}}
+  ; CHECK-UAS-SS-NOT: store i64
 
   call void @llvm.lifetime.start.p0(i64 1, ptr %c)
   ; Memory is unpoisoned at llvm.lifetime.start: 01
-  ; CHECK-UAS: store i8 1, ptr %{{[0-9]+}}
+  ; CHECK-UAS: store i8 2, ptr %{{[0-9]+}}
 
+  %ci = getelementptr inbounds [2 x i8], ptr %c, i64 0, i64 %i
   store volatile i32 0, ptr %retval
-  store volatile i8 0, ptr %c, align 1
+  store volatile i8 0, ptr %ci, align 1
 
   call void @llvm.lifetime.end.p0(i64 1, ptr %c)
   ; Memory is poisoned at llvm.lifetime.end: F8
   ; CHECK-UAS: store i8 -8, ptr %{{[0-9]+}}
+  ; CHECK-UAS-SS-NOT: store i8 -8,
 
   ; Unpoison memory at function exit in UAS mode.
   ; CHECK-UAS: store i64 0, ptr %{{[0-9]+}}
diff --git a/llvm/test/Instrumentation/AddressSanitizer/lifetime.ll b/llvm/test/Instrumentation/AddressSanitizer/lifetime.ll
index 7f158487a47a15..1d073cdc3bdb92 100644
--- a/llvm/test/Instrumentation/AddressSanitizer/lifetime.ll
+++ b/llvm/test/Instrumentation/AddressSanitizer/lifetime.ll
@@ -1,6 +1,6 @@
 ; Test handling of llvm.lifetime intrinsics.
-; RUN: opt < %s -passes=asan -asan-use-after-scope -asan-use-after-return=never -S | FileCheck %s --check-prefixes=CHECK,CHECK-DEFAULT
-; RUN: opt < %s -passes=asan -asan-use-after-scope -asan-use-after-return=never -asan-instrument-dynamic-allocas=0 -S | FileCheck %s --check-prefixes=CHECK,CHECK-NO-DYNAMIC
+; RUN: opt < %s -passes=asan -asan-use-after-scope -asan-use-after-return=never -asan-use-stack-safety=0 -S | FileCheck %s --check-prefixes=CHECK,CHECK-DEFAULT
+; RUN: opt < %s -passes=asan -asan-use-after-scope -asan-use-after-return=never -asan-use-stack-safety=0 -asan-instrument-dynamic-allocas=0 -S | FileCheck %s --check-prefixes=CHECK,CHECK-NO-DYNAMIC
 
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
diff --git a/llvm/test/Instrumentation/AddressSanitizer/local_stack_base.ll b/llvm/test/Instrumentation/AddressSanitizer/local_stack_base.ll
index 43b402e1b166f2..4e8466b685689b 100644
--- a/llvm/test/Instrumentation/AddressSanitizer/local_stack_base.ll
+++ b/llvm/test/Instrumentation/AddressSanitizer/local_stack_base.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -passes=asan -asan-skip-promotable-allocas=0 %s -o - | FileCheck %s
+; RUN: opt -S -passes=asan -asan-use-stack-safety=0 -asan-skip-promotable-allocas=0 %s -o - | FileCheck %s
 ; Generated from:
 ; int bar(int y) {
 ;   return y + 2;
diff --git a/llvm/test/Instrumentation/AddressSanitizer/stack_dynamic_alloca.ll b/llvm/test/Instrumentation/AddressSanitizer/stack_dynamic_alloca.ll
index 98851b871393c5..cbb2001c45e651 100644
--- a/llvm/test/Instrumentation/AddressSanitizer/stack_dynamic_alloca.ll
+++ b/llvm/test/Instrumentation/AddressSanitizer/stack_dynamic_alloca.ll
@@ -1,14 +1,14 @@
-; RUN: opt < %s -passes=asan -asan-stack-dynamic-alloca \
+; RUN: opt < %s -passes=asan -asan-stack-dynamic-alloca -asan-use-stack-safety=0 \
 ; RUN:       -asan-use-after-return=runtime -S | FileCheck %s \
 ; RUN:       --check-prefixes=CHECK,CHECK-RUNTIME
-; RUN: opt < %s -passes=asan -asan-stack-dynamic-alloca -asan-mapping-scale=5 \
+; RUN: opt < %s -passes=asan -asan-stack-dynamic-alloca -asan-mapping-scale=5 -asan-use-stack-safety=0 \
 ; RUN:       -asan-use-after-return=runtime -S | FileCheck %s \
 ; RUN:       --check-prefixes=CHECK,CHECK-RUNTIME
-; RUN: opt < %s -passes=asan  -asan-stack-dynamic-alloca \
+; RUN: opt < %s -passes=asan  -asan-stack-dynamic-alloca -asan-use-stack-safety=0 \
 ; RUN:       -asan-use-after-return=always -S | FileCheck %s \
 ; RUN:       --check-prefixes=CHECK,CHECK-ALWAYS \
 ; RUN:       --implicit-check-not=__asan_option_detect_stack_use_after_return
-; RUN: opt < %s -passes=asan -asan-stack-dynamic-alloca \
+; RUN: opt < %s -passes=asan -asan-stack-dynamic-alloca -asan-use-stack-safety=0 \
 ; RUN:       -asan-use-after-return=always -S | FileCheck %s \
 ; RUN:       --check-prefixes=CHECK,CHECK-ALWAYS \
 ; RUN:       --implicit-check-not=__asan_option_detect_stack_use_after_return
diff --git a/llvm/test/Instrumentation/AddressSanitizer/stack_layout.ll b/llvm/test/Instrumentation/AddressSanitizer/stack_layout.ll
index 726f628607dae1..48465be36789d6 100644
--- a/llvm/test/Instrumentation/AddressSanitizer/stack_layout.ll
+++ b/llvm/test/Instrumentation/AddressSanitizer/stack_layout.ll
@@ -1,8 +1,8 @@
 ; Test the ASan's stack layout.
 ; More tests in tests/Transforms/Utils/ASanStackFrameLayoutTest.cpp
-; RUN: opt < %s -passes=asan -asan-stack-dynamic-alloca=0 -asan-use-after-scope -S \
+; RUN: opt < %s -passes=asan -asan-use-stack-safety=0 -asan-stack-dynamic-alloca=0 -asan-use-after-scope -S \
 ; RUN:     | FileCheck %s --check-prefixes=CHECK,CHECK-STATIC
-; RUN: opt < %s -passes=asan -asan-stack-dynamic-alloca=1 -asan-use-after-scope -S \
+; RUN: opt < %s -passes=asan -asan-use-stack-safety=0 -asan-stack-dynamic-alloca=1 -asan-use-after-scope -S \
 ; RUN:     | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC
 
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"



More information about the libcxx-commits mailing list