Skip to content

Commit b8cc320

Browse files
committed
[InstCombine][asan] Don't speculate loads before select ptr
Even if memory is valid from `llvm` point of view, e.g. local alloca, sanitizers have API for user specific memory annotations. This annotations can be used to track size of the local object, e.g. inline vector like may prevent accessed beyond the current vector size. So valid programs should not access those parts of alloca before checking preconditions. Fixes #100639. Pull Request: #100773
1 parent 403561b commit b8cc320

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed

llvm/lib/Analysis/Loads.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,9 @@ bool llvm::isSafeToLoadUnconditionally(Value *V, Align Alignment, const APInt &S
375375
AssumptionCache *AC,
376376
const DominatorTree *DT,
377377
const TargetLibraryInfo *TLI) {
378+
if (ScanFrom && suppressSpeculativeLoadForSanitizers(*ScanFrom))
379+
return false;
380+
378381
// If DT is not specified we can't make context-sensitive query
379382
const Instruction* CtxI = DT ? ScanFrom : nullptr;
380383
if (isDereferenceableAndAlignedPointer(V, Alignment, Size, DL, CtxI, AC, DT,
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -passes=instcombine -S < %s | FileCheck %s
3+
4+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
5+
target triple = "x86_64-grtev4-linux-gnu"
6+
7+
define i32 @test_plain(i1 %f) {
8+
; CHECK-LABEL: @test_plain(
9+
; CHECK-NEXT: entry:
10+
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 8
11+
; CHECK-NEXT: [[B:%.*]] = alloca i32, align 8
12+
; CHECK-NEXT: [[A_VAL:%.*]] = load i32, ptr [[A]], align 8
13+
; CHECK-NEXT: [[B_VAL:%.*]] = load i32, ptr [[B]], align 8
14+
; CHECK-NEXT: [[L:%.*]] = select i1 [[F:%.*]], i32 [[A_VAL]], i32 [[B_VAL]]
15+
; CHECK-NEXT: ret i32 [[L]]
16+
;
17+
entry:
18+
%a = alloca i32, align 8
19+
%b = alloca i32, align 8
20+
%sel = select i1 %f, ptr %a, ptr %b
21+
%l = load i32, ptr %sel, align 8
22+
ret i32 %l
23+
}
24+
25+
; Don't speculate as the condition may control which memory is valid from
26+
; sanitizer perspective.
27+
define i32 @test_asan(i1 %f) sanitize_address {
28+
; CHECK-LABEL: @test_asan(
29+
; CHECK-NEXT: entry:
30+
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 8
31+
; CHECK-NEXT: [[B:%.*]] = alloca i32, align 8
32+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[F:%.*]], ptr [[A]], ptr [[B]]
33+
; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[SEL]], align 8
34+
; CHECK-NEXT: ret i32 [[L]]
35+
;
36+
entry:
37+
%a = alloca i32, align 8
38+
%b = alloca i32, align 8
39+
%sel = select i1 %f, ptr %a, ptr %b
40+
%l = load i32, ptr %sel, align 8
41+
ret i32 %l
42+
}
43+
44+
45+
; Don't speculate as the condition may control which memory is valid from
46+
; sanitizer perspective.
47+
define i32 @test_hwasan(i1 %f) sanitize_hwaddress {
48+
; CHECK-LABEL: @test_hwasan(
49+
; CHECK-NEXT: entry:
50+
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 8
51+
; CHECK-NEXT: [[B:%.*]] = alloca i32, align 8
52+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[F:%.*]], ptr [[A]], ptr [[B]]
53+
; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[SEL]], align 8
54+
; CHECK-NEXT: ret i32 [[L]]
55+
;
56+
entry:
57+
%a = alloca i32, align 8
58+
%b = alloca i32, align 8
59+
%sel = select i1 %f, ptr %a, ptr %b
60+
%l = load i32, ptr %sel, align 8
61+
ret i32 %l
62+
}
63+
64+
; Don't speculate as the condition may control which memory is valid from
65+
; sanitizer perspective.
66+
define i32 @test_tsan(i1 %f) sanitize_thread {
67+
; CHECK-LABEL: @test_tsan(
68+
; CHECK-NEXT: entry:
69+
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 8
70+
; CHECK-NEXT: [[B:%.*]] = alloca i32, align 8
71+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[F:%.*]], ptr [[A]], ptr [[B]]
72+
; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[SEL]], align 8
73+
; CHECK-NEXT: ret i32 [[L]]
74+
;
75+
entry:
76+
%a = alloca i32, align 8
77+
%b = alloca i32, align 8
78+
%sel = select i1 %f, ptr %a, ptr %b
79+
%l = load i32, ptr %sel, align 8
80+
ret i32 %l
81+
}
82+
83+
; Msan just propagates shadow, even if speculated load accesses uninitialized
84+
; value, instrumentation will select shadow of the desired value anyway.
85+
define i32 @test_msan(i1 %f) sanitize_memory {
86+
; CHECK-LABEL: @test_msan(
87+
; CHECK-NEXT: entry:
88+
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 8
89+
; CHECK-NEXT: [[B:%.*]] = alloca i32, align 8
90+
; CHECK-NEXT: [[A_VAL:%.*]] = load i32, ptr [[A]], align 8
91+
; CHECK-NEXT: [[B_VAL:%.*]] = load i32, ptr [[B]], align 8
92+
; CHECK-NEXT: [[L:%.*]] = select i1 [[F:%.*]], i32 [[A_VAL]], i32 [[B_VAL]]
93+
; CHECK-NEXT: ret i32 [[L]]
94+
;
95+
entry:
96+
%a = alloca i32, align 8
97+
%b = alloca i32, align 8
98+
%sel = select i1 %f, ptr %a, ptr %b
99+
%l = load i32, ptr %sel, align 8
100+
ret i32 %l
101+
}

0 commit comments

Comments
 (0)