diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -2931,6 +2931,8 @@ size_t Begin, size_t End, IRBuilder<> &IRB, Value *ShadowBase) { assert(ShadowMask.size() == ShadowBytes.size()); + const size_t MaxHoleSize = + std::min(sizeof(uint64_t), ASan.LongSize / 8); size_t Done = Begin; for (size_t i = Begin, j = Begin + 1; i < End; i = j++) { if (!ShadowMask[i]) { @@ -2945,6 +2947,20 @@ for (; j < End && ShadowMask[j] && Val == ShadowBytes[j]; ++j) { } + // Special case for zero value: allow a few consecutive zeros in the middle + // of the mask. It avoids splitting the buffer into many inlined chunks. + if (!Val) { + size_t HoleSize = 0; + for (; j < End && !ShadowBytes[j] && HoleSize <= MaxHoleSize; ++j) { + if (!ShadowMask[j]) + HoleSize++; + else + HoleSize = 0; + } + // Ignore trailing zeros in the mask. + j -= HoleSize; + } + if (j - i >= ClMaxInlinePoisoningSize) { copyToShadowInline(ShadowMask, ShadowBytes, Done, i, IRB, ShadowBase); IRB.CreateCall(AsanSetShadowFunc[Val], diff --git a/llvm/test/Instrumentation/AddressSanitizer/asan-optimize-inline-poisoning.ll b/llvm/test/Instrumentation/AddressSanitizer/asan-optimize-inline-poisoning.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Instrumentation/AddressSanitizer/asan-optimize-inline-poisoning.ll @@ -0,0 +1,63 @@ +; RUN: opt < %s -passes=asan -asan-max-inline-poisoning-size=8 -S | FileCheck %s --check-prefix=CHECK + +target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc19.20.0" + +%struct.S = type { ptr, ptr } + +define void @allocas() sanitize_address { +; CHECK-LABEL: void @allocas() +entry: + %agg.tmp = alloca %struct.S, align 8 + %agg.tmp1 = alloca %struct.S, align 8 + %agg.tmp2 = alloca %struct.S, align 8 + %agg.tmp3 = alloca %struct.S, align 8 + %agg.tmp4 = alloca %struct.S, align 8 + %agg.tmp5 = alloca %struct.S, align 8 + %agg.tmp6 = alloca %struct.S, align 8 + %agg.tmp7 = alloca %struct.S, align 8 + %agg.tmp8 = alloca %struct.S, align 8 + %agg.tmp9 = alloca %struct.S, align 8 + %agg.tmp10 = alloca %struct.S, align 8 + %agg.tmp11 = alloca %struct.S, align 8 + %agg.tmp12 = alloca %struct.S, align 8 + %agg.tmp13 = alloca %struct.S, align 8 + call void @get(ptr nonnull sret(%struct.S) align 8 %agg.tmp) + call void @use_copy(ptr noundef nonnull %agg.tmp) + call void @get(ptr nonnull sret(%struct.S) align 8 %agg.tmp1) + call void @use_copy(ptr noundef nonnull %agg.tmp1) + call void @get(ptr nonnull sret(%struct.S) align 8 %agg.tmp2) + call void @use_copy(ptr noundef nonnull %agg.tmp2) + call void @get(ptr nonnull sret(%struct.S) align 8 %agg.tmp3) + call void @use_copy(ptr noundef nonnull %agg.tmp3) + call void @get(ptr nonnull sret(%struct.S) align 8 %agg.tmp4) + call void @use_copy(ptr noundef nonnull %agg.tmp4) + call void @get(ptr nonnull sret(%struct.S) align 8 %agg.tmp5) + call void @use_copy(ptr noundef nonnull %agg.tmp5) + call void @get(ptr nonnull sret(%struct.S) align 8 %agg.tmp6) + call void @use_copy(ptr noundef nonnull %agg.tmp6) + call void @get(ptr nonnull sret(%struct.S) align 8 %agg.tmp7) + call void @use_copy(ptr noundef nonnull %agg.tmp7) + call void @get(ptr nonnull sret(%struct.S) align 8 %agg.tmp8) + call void @use_copy(ptr noundef nonnull %agg.tmp8) + call void @get(ptr nonnull sret(%struct.S) align 8 %agg.tmp9) + call void @use_copy(ptr noundef nonnull %agg.tmp9) + call void @get(ptr nonnull sret(%struct.S) align 8 %agg.tmp10) + call void @use_copy(ptr noundef nonnull %agg.tmp10) + call void @get(ptr nonnull sret(%struct.S) align 8 %agg.tmp11) + call void @use_copy(ptr noundef nonnull %agg.tmp11) + call void @get(ptr nonnull sret(%struct.S) align 8 %agg.tmp12) + call void @use_copy(ptr noundef nonnull %agg.tmp12) + call void @get(ptr nonnull sret(%struct.S) align 8 %agg.tmp13) + call void @use_copy(ptr noundef nonnull %agg.tmp13) + br label %return +return: +; CHECK: return: +; CHECK: call void @__asan_set_shadow_f5(i64 %{{.*}}, i64 64) +; CHECK: call void @__asan_set_shadow_00(i64 %{{.*}}, i64 60) +; CHECK: ret void + ret void +} + +declare void @use_copy(ptr noundef) +declare void @get(ptr sret(%struct.S) align 8, ...)