Skip to content

Commit 2f1c4b5

Browse files
committed
[msan] Fix shadow computation for partially undefined constant fixed-length vectors
For each element of the vector, the shadow is initialized iff the element is not undefined/poisoned. Previously, partially undefined constant fixed-length vectors always had fully initialized shadows, which leads to false negatives. Updates the tests from llvm#143823 Note: since this patch corrects a false negative, MSan can now detect more bugs (corollary: code/tests that passed MSan may start failing).
1 parent 2efff47 commit 2f1c4b5

File tree

2 files changed

+26
-8
lines changed

2 files changed

+26
-8
lines changed

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1989,6 +1989,8 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
19891989
}
19901990
return Shadow;
19911991
}
1992+
// Handle fully undefined values
1993+
// (partially undefined constant vectors are handled later)
19921994
if (UndefValue *U = dyn_cast<UndefValue>(V)) {
19931995
Value *AllOnes = (PropagateShadow && PoisonUndef) ? getPoisonedShadow(V)
19941996
: getCleanShadow(V);
@@ -2086,8 +2088,25 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
20862088
return ShadowPtr;
20872089
}
20882090

2089-
// TODO: Partially undefined vectors are handled by the fall-through case
2090-
// below (see partial-poison.ll); this causes false negatives.
2091+
// Check for partially undefined constant vectors
2092+
// TODO: scalable vectors (this is hard because we do not have IRBuilder)
2093+
if ( isa<FixedVectorType>(V->getType())
2094+
&& isa<Constant>(V)
2095+
&& (cast<Constant>(V))->containsUndefOrPoisonElement()
2096+
&& PropagateShadow
2097+
&& PoisonUndef) {
2098+
unsigned NumElems = (cast<FixedVectorType>(V->getType()))->getNumElements();
2099+
SmallVector<Constant *, 32> ShadowVector(NumElems);
2100+
for (unsigned i = 0; i != NumElems; ++i) {
2101+
Constant *Elem = (cast<Constant>(V))->getAggregateElement(i);
2102+
ShadowVector[i] = isa<UndefValue>(Elem) ? getPoisonedShadow(Elem) : getCleanShadow(Elem);
2103+
}
2104+
2105+
Value *ShadowConstant = ConstantVector::get(ShadowVector);
2106+
LLVM_DEBUG(dbgs() << "Partial undef constant vector: " << *V << " ==> " << *ShadowConstant << "\n");
2107+
2108+
return ShadowConstant;
2109+
}
20912110

20922111
// For everything else the shadow is zero.
20932112
return getCleanShadow(V);

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

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
22
; RUN: opt < %s -S -passes='msan' 2>&1 | FileCheck %s
33
;
4-
; Test case to show that MSan computes shadows for partially poisoned vectors
5-
; as fully initialized, resulting in false negatives.
4+
; Regression test case for computing shadows of partially poisoned vectors
65

76
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"
87
target triple = "x86_64-unknown-linux-gnu"
@@ -11,7 +10,7 @@ define <2 x i64> @left_poison(ptr %add.ptr) sanitize_memory {
1110
; CHECK-LABEL: define <2 x i64> @left_poison(
1211
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0:[0-9]+]] {
1312
; CHECK-NEXT: call void @llvm.donothing()
14-
; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
13+
; CHECK-NEXT: store <2 x i64> <i64 -1, i64 0>, ptr @__msan_retval_tls, align 8
1514
; CHECK-NEXT: ret <2 x i64> <i64 poison, i64 42>
1615
;
1716
ret <2 x i64> <i64 poison, i64 42>
@@ -21,7 +20,7 @@ define <2 x i64> @right_poison(ptr %add.ptr) sanitize_memory {
2120
; CHECK-LABEL: define <2 x i64> @right_poison(
2221
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
2322
; CHECK-NEXT: call void @llvm.donothing()
24-
; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
23+
; CHECK-NEXT: store <2 x i64> <i64 0, i64 -1>, ptr @__msan_retval_tls, align 8
2524
; CHECK-NEXT: ret <2 x i64> <i64 42, i64 poison>
2625
;
2726
ret <2 x i64> <i64 42, i64 poison>
@@ -51,7 +50,7 @@ define <2 x i64> @left_undef(ptr %add.ptr) sanitize_memory {
5150
; CHECK-LABEL: define <2 x i64> @left_undef(
5251
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
5352
; CHECK-NEXT: call void @llvm.donothing()
54-
; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
53+
; CHECK-NEXT: store <2 x i64> <i64 -1, i64 0>, ptr @__msan_retval_tls, align 8
5554
; CHECK-NEXT: ret <2 x i64> <i64 undef, i64 42>
5655
;
5756
ret <2 x i64> <i64 undef, i64 42>
@@ -61,7 +60,7 @@ define <2 x i64> @right_undef(ptr %add.ptr) sanitize_memory {
6160
; CHECK-LABEL: define <2 x i64> @right_undef(
6261
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
6362
; CHECK-NEXT: call void @llvm.donothing()
64-
; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
63+
; CHECK-NEXT: store <2 x i64> <i64 0, i64 -1>, ptr @__msan_retval_tls, align 8
6564
; CHECK-NEXT: ret <2 x i64> <i64 42, i64 undef>
6665
;
6766
ret <2 x i64> <i64 42, i64 undef>

0 commit comments

Comments
 (0)