Skip to content

Commit c996fde

Browse files
thurstondtomtor
authored andcommitted
[NFCI][msan] Show that shadow for partially undefined constant vectors is computed as fully initialized (llvm#143823)
This happens because `getShadow(Value *V)` has a special case for fully undefined/poisoned values, but partially undefined values fall-through and are given a clean shadow. This leads to false negatives (no false positives). Note: MSan correctly handles InsertElementInst, but the shadow of the initial constant vector may still be wrong and be propagated. Showing that the same approximation happens for other composite types is left as an exercise for the reader.
1 parent 00de79a commit c996fde

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2085,6 +2085,10 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
20852085
assert(ShadowPtr && "Could not find shadow for an argument");
20862086
return ShadowPtr;
20872087
}
2088+
2089+
// TODO: Partially undefined vectors are handled by the fall-through case
2090+
// below (see partial-poison.ll); this causes false negatives.
2091+
20882092
// For everything else the shadow is zero.
20892093
return getCleanShadow(V);
20902094
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
; 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
3+
;
4+
; Test case to show that MSan computes shadows for partially poisoned vectors
5+
; as fully initialized, resulting in false negatives.
6+
7+
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"
8+
target triple = "x86_64-unknown-linux-gnu"
9+
10+
define <2 x i64> @left_poison(ptr %add.ptr) sanitize_memory {
11+
; CHECK-LABEL: define <2 x i64> @left_poison(
12+
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0:[0-9]+]] {
13+
; CHECK-NEXT: call void @llvm.donothing()
14+
; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
15+
; CHECK-NEXT: ret <2 x i64> <i64 poison, i64 42>
16+
;
17+
ret <2 x i64> <i64 poison, i64 42>
18+
}
19+
20+
define <2 x i64> @right_poison(ptr %add.ptr) sanitize_memory {
21+
; CHECK-LABEL: define <2 x i64> @right_poison(
22+
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
23+
; CHECK-NEXT: call void @llvm.donothing()
24+
; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
25+
; CHECK-NEXT: ret <2 x i64> <i64 42, i64 poison>
26+
;
27+
ret <2 x i64> <i64 42, i64 poison>
28+
}
29+
30+
define <2 x i64> @full_poison(ptr %add.ptr) sanitize_memory {
31+
; CHECK-LABEL: define <2 x i64> @full_poison(
32+
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
33+
; CHECK-NEXT: call void @llvm.donothing()
34+
; CHECK-NEXT: store <2 x i64> splat (i64 -1), ptr @__msan_retval_tls, align 8
35+
; CHECK-NEXT: ret <2 x i64> poison
36+
;
37+
ret <2 x i64> <i64 poison, i64 poison>
38+
}
39+
40+
define <2 x i64> @no_poison_or_undef(ptr %add.ptr) sanitize_memory {
41+
; CHECK-LABEL: define <2 x i64> @no_poison_or_undef(
42+
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
43+
; CHECK-NEXT: call void @llvm.donothing()
44+
; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
45+
; CHECK-NEXT: ret <2 x i64> splat (i64 42)
46+
;
47+
ret <2 x i64> <i64 42, i64 42>
48+
}
49+
50+
define <2 x i64> @left_undef(ptr %add.ptr) sanitize_memory {
51+
; CHECK-LABEL: define <2 x i64> @left_undef(
52+
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
53+
; CHECK-NEXT: call void @llvm.donothing()
54+
; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
55+
; CHECK-NEXT: ret <2 x i64> <i64 undef, i64 42>
56+
;
57+
ret <2 x i64> <i64 undef, i64 42>
58+
}
59+
60+
define <2 x i64> @right_undef(ptr %add.ptr) sanitize_memory {
61+
; CHECK-LABEL: define <2 x i64> @right_undef(
62+
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
63+
; CHECK-NEXT: call void @llvm.donothing()
64+
; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
65+
; CHECK-NEXT: ret <2 x i64> <i64 42, i64 undef>
66+
;
67+
ret <2 x i64> <i64 42, i64 undef>
68+
}
69+
70+
define <2 x i64> @full_undef(ptr %add.ptr) sanitize_memory {
71+
; CHECK-LABEL: define <2 x i64> @full_undef(
72+
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
73+
; CHECK-NEXT: call void @llvm.donothing()
74+
; CHECK-NEXT: store <2 x i64> splat (i64 -1), ptr @__msan_retval_tls, align 8
75+
; CHECK-NEXT: ret <2 x i64> undef
76+
;
77+
ret <2 x i64> <i64 undef, i64 undef>
78+
}

0 commit comments

Comments
 (0)