Skip to content

Commit 97bfb34

Browse files
committed
Add 'msan-poison-undef-vectors' for shitty compilers
Also update tests and TODOs
1 parent 2f3fa0b commit 97bfb34

File tree

2 files changed

+47
-9
lines changed

2 files changed

+47
-9
lines changed

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,14 @@ static cl::opt<bool> ClPoisonUndef("msan-poison-undef",
269269
cl::desc("poison undef temps"), cl::Hidden,
270270
cl::init(true));
271271

272+
static cl::opt<bool> ClPoisonUndefVectors(
273+
"msan-poison-undef-vectors",
274+
cl::desc("Precisely poison partially undefined constant vectors. "
275+
"If false (legacy behavior), the entire vector is "
276+
"considered fully initialized, which may lead to false "
277+
"negatives."),
278+
cl::Hidden, cl::init(true));
279+
272280
static cl::opt<bool>
273281
ClHandleICmp("msan-handle-icmp",
274282
cl::desc("propagate shadow through ICmpEQ and ICmpNE"),
@@ -1181,6 +1189,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
11811189
bool PropagateShadow;
11821190
bool PoisonStack;
11831191
bool PoisonUndef;
1192+
bool PoisonUndefVectors;
11841193

11851194
struct ShadowOriginAndInsertPoint {
11861195
Value *Shadow;
@@ -1207,6 +1216,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
12071216
PropagateShadow = SanitizeFunction;
12081217
PoisonStack = SanitizeFunction && ClPoisonStack;
12091218
PoisonUndef = SanitizeFunction && ClPoisonUndef;
1219+
PoisonUndefVectors = SanitizeFunction && ClPoisonUndefVectors;
12101220

12111221
// In the presence of unreachable blocks, we may see Phi nodes with
12121222
// incoming nodes from such blocks. Since InstVisitor skips unreachable
@@ -2088,11 +2098,11 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
20882098
return ShadowPtr;
20892099
}
20902100

2091-
// Check for partially undefined constant vectors
2101+
// Check for partially-undefined constant vectors
20922102
// TODO: scalable vectors (this is hard because we do not have IRBuilder)
20932103
if (isa<FixedVectorType>(V->getType()) && isa<Constant>(V) &&
20942104
(cast<Constant>(V))->containsUndefOrPoisonElement() &&
2095-
PropagateShadow && PoisonUndef) {
2105+
PropagateShadow && PoisonUndefVectors) {
20962106
unsigned NumElems =
20972107
(cast<FixedVectorType>(V->getType()))->getNumElements();
20982108
SmallVector<Constant *, 32> ShadowVector(NumElems);
@@ -2109,6 +2119,8 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
21092119
return ShadowConstant;
21102120
}
21112121

2122+
// TODO: partially-undefined constant arrays, structures, and nested types
2123+
21122124
// For everything else the shadow is zero.
21132125
return getCleanShadow(V);
21142126
}

llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2-
; RUN: opt < %s -S -passes='msan' 2>&1 | FileCheck %s
2+
; RUN: opt < %s -S -passes='msan' 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-PRECISE
3+
; RUN: opt < %s -S -passes='msan' -msan-poison-undef-vectors=false 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-IMPRECISE
34
;
4-
; Regression test case for computing shadows of partially poisoned vectors
5+
; Regression test case for computing shadows of partially poisoned vectors.
6+
; Partially poisoned structs and arrays are not correctly implemented.
57

68
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"
79
target triple = "x86_64-unknown-linux-gnu"
@@ -10,7 +12,8 @@ define <2 x i64> @left_poison(ptr %add.ptr) sanitize_memory {
1012
; CHECK-LABEL: define <2 x i64> @left_poison(
1113
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0:[0-9]+]] {
1214
; CHECK-NEXT: call void @llvm.donothing()
13-
; CHECK-NEXT: store <2 x i64> <i64 -1, i64 0>, ptr @__msan_retval_tls, align 8
15+
; CHECK-PRECISE: store <2 x i64> <i64 -1, i64 0>, ptr @__msan_retval_tls, align 8
16+
; CHECK-IMPRECISE: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
1417
; CHECK-NEXT: ret <2 x i64> <i64 poison, i64 42>
1518
;
1619
ret <2 x i64> <i64 poison, i64 42>
@@ -20,7 +23,8 @@ define <2 x i64> @right_poison(ptr %add.ptr) sanitize_memory {
2023
; CHECK-LABEL: define <2 x i64> @right_poison(
2124
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
2225
; CHECK-NEXT: call void @llvm.donothing()
23-
; CHECK-NEXT: store <2 x i64> <i64 0, i64 -1>, ptr @__msan_retval_tls, align 8
26+
; CHECK-PRECISE: store <2 x i64> <i64 0, i64 -1>, ptr @__msan_retval_tls, align 8
27+
; CHECK-IMPRECISE: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
2428
; CHECK-NEXT: ret <2 x i64> <i64 42, i64 poison>
2529
;
2630
ret <2 x i64> <i64 42, i64 poison>
@@ -50,7 +54,8 @@ define <2 x i64> @left_undef(ptr %add.ptr) sanitize_memory {
5054
; CHECK-LABEL: define <2 x i64> @left_undef(
5155
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
5256
; CHECK-NEXT: call void @llvm.donothing()
53-
; CHECK-NEXT: store <2 x i64> <i64 -1, i64 0>, ptr @__msan_retval_tls, align 8
57+
; CHECK-PRECISE: store <2 x i64> <i64 -1, i64 0>, ptr @__msan_retval_tls, align 8
58+
; CHECK-IMPRECISE: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
5459
; CHECK-NEXT: ret <2 x i64> <i64 undef, i64 42>
5560
;
5661
ret <2 x i64> <i64 undef, i64 42>
@@ -60,7 +65,8 @@ define <2 x i64> @right_undef(ptr %add.ptr) sanitize_memory {
6065
; CHECK-LABEL: define <2 x i64> @right_undef(
6166
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
6267
; CHECK-NEXT: call void @llvm.donothing()
63-
; CHECK-NEXT: store <2 x i64> <i64 0, i64 -1>, ptr @__msan_retval_tls, align 8
68+
; CHECK-PRECISE: store <2 x i64> <i64 0, i64 -1>, ptr @__msan_retval_tls, align 8
69+
; CHECK-IMPRECISE: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
6470
; CHECK-NEXT: ret <2 x i64> <i64 42, i64 undef>
6571
;
6672
ret <2 x i64> <i64 42, i64 undef>
@@ -70,8 +76,28 @@ define <2 x i64> @full_undef(ptr %add.ptr) sanitize_memory {
7076
; CHECK-LABEL: define <2 x i64> @full_undef(
7177
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
7278
; CHECK-NEXT: call void @llvm.donothing()
73-
; CHECK-NEXT: store <2 x i64> splat (i64 -1), ptr @__msan_retval_tls, align 8
79+
; CHECK: store <2 x i64> splat (i64 -1), ptr @__msan_retval_tls, align 8
7480
; CHECK-NEXT: ret <2 x i64> undef
7581
;
7682
ret <2 x i64> <i64 undef, i64 undef>
7783
}
84+
85+
define {i64, i64} @struct_left_undef() sanitize_memory {
86+
; CHECK-LABEL: define { i64, i64 } @struct_left_undef(
87+
; CHECK-SAME: ) #[[ATTR0]] {
88+
; CHECK-NEXT: call void @llvm.donothing()
89+
; CHECK-NEXT: store { i64, i64 } zeroinitializer, ptr @__msan_retval_tls, align 8
90+
; CHECK-NEXT: ret { i64, i64 } { i64 undef, i64 42 }
91+
;
92+
ret {i64, i64} { i64 undef, i64 42 }
93+
}
94+
95+
define [2x i64] @array_right_undef() sanitize_memory {
96+
; CHECK-LABEL: define [2 x i64] @array_right_undef(
97+
; CHECK-SAME: ) #[[ATTR0]] {
98+
; CHECK-NEXT: call void @llvm.donothing()
99+
; CHECK-NEXT: store [2 x i64] zeroinitializer, ptr @__msan_retval_tls, align 8
100+
; CHECK-NEXT: ret [2 x i64] [i64 42, i64 undef]
101+
;
102+
ret [2x i64] [ i64 42, i64 undef ]
103+
}

0 commit comments

Comments
 (0)