diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -773,6 +773,24 @@ if (Ptr->isSwiftError()) return true; + if (!InstrumentStack) { + // If we don't instrument the stack, don't instrument any reads that come + // from an alloca. We don't set OffsetZero to true, which means GEP might + // be out of range, but as we don't instrument any values on the stack, it + // would have to be very out of range (e.g. reaching the heap), to cause + // a fault. + if (findAllocaForValue(Ptr)) + return true; + } else { + // If we instrument the stack, do not instrument any reads that we can be + // certain are within range of an uninteresting alloca. We set OffsetZero + // to make sure no GEP can be out of range. + // TODO(fmayer): we could make use of some of the information we have in + // the stack safety analysis to determine whether the GEP is within range + // even if it does not have zero offset. + auto *StrictAI = findAllocaForValue(Ptr, /*OffsetZero=*/true); + if (StrictAI && !isInterestingAlloca(*StrictAI)) return true; + } return false; } diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/stack-safety-analysis.ll b/llvm/test/Instrumentation/HWAddressSanitizer/stack-safety-analysis.ll --- a/llvm/test/Instrumentation/HWAddressSanitizer/stack-safety-analysis.ll +++ b/llvm/test/Instrumentation/HWAddressSanitizer/stack-safety-analysis.ll @@ -1,6 +1,7 @@ -; RUN: opt -hwasan -hwasan-use-stack-safety=1 -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=SAFETY -; RUN: opt -hwasan -hwasan-use-stack-safety=0 -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=NOSAFETY -; RUN: opt -hwasan -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=SAFETY +; RUN: opt -hwasan -hwasan-instrument-with-calls -hwasan-use-stack-safety=1 -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=SAFETY +; RUN: opt -hwasan -hwasan-instrument-with-calls -hwasan-use-stack-safety=0 -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=NOSAFETY +; RUN: opt -hwasan -hwasan-instrument-with-calls -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=SAFETY +; RUN: opt -hwasan -hwasan-instrument-with-calls -hwasan-instrument-stack=0 -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=NOSTACK target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" target triple = "aarch64-unknown-linux-gnu" @@ -9,7 +10,11 @@ define i32 @test_load(i32* %a) sanitize_hwaddress { entry: ; NOSAFETY: call {{.*}}__hwasan_generate_tag + ; NOSAFETY: call {{.*}}__hwasan_store ; SAFETY-NOT: call {{.*}}__hwasan_generate_tag + ; SAFETY-NOT: call {{.*}}__hwasan_store + ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag + ; NOSTACK-NOT: call {{.*}}__hwasan_store %buf.sroa.0 = alloca i8, align 4 call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %buf.sroa.0) store volatile i8 0, i8* %buf.sroa.0, align 4, !tbaa !8 @@ -21,7 +26,11 @@ define i32 @test_use(i32* %a) sanitize_hwaddress { entry: ; NOSAFETY: call {{.*}}__hwasan_generate_tag + ; NOSAFETY: call {{.*}}__hwasan_store ; SAFETY: call {{.*}}__hwasan_generate_tag + ; SAFETY: call {{.*}}__hwasan_store + ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag + ; NOSTACK-NOT: call {{.*}}__hwasan_store %buf.sroa.0 = alloca i8, align 4 call void @use(i8* nonnull %buf.sroa.0) call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %buf.sroa.0) @@ -30,6 +39,24 @@ ret i32 0 } +; Check an alloca with out of range GEP to ensure it gets a tag. +define i32 @test_out_of_range(i32* %a) sanitize_hwaddress { +entry: + ; NOSAFETY: call {{.*}}__hwasan_generate_tag + ; NOSAFETY: call {{.*}}__hwasan_store + ; SAFETY: call {{.*}}__hwasan_generate_tag + ; SAFETY: call {{.*}}__hwasan_store + ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag + ; NOSTACK-NOT: call {{.*}}__hwasan_store + %buf.sroa.0 = alloca [10 x i8], align 4 + %off = call i32 @getoffset() + %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 %off + call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %ptr) + store volatile i8 0, i8* %ptr, align 4, !tbaa !8 + call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %ptr) + ret i32 0 +} + ; Function Attrs: argmemonly mustprogress nofree nosync nounwind willreturn declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) @@ -37,6 +64,7 @@ declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) declare void @use(i8* nocapture) +declare i32 @getoffset() !8 = !{!9, !9, i64 0} !9 = !{!"omnipotent char", !10, i64 0}