Skip to content

Commit c940317

Browse files
authored
[msan] Add test cases for vector shadow track origins bug (#97611)
These test cases demonstrate a bug in MSan (vector shadow is not always converted to scalar before zext) that will shortly be fixed in #96722 The bug is not architecture-specific; we provide both x86 and Arm NEON test cases. Since the test cases will crash the compiler (unless it is a release build), they are marked as UNSUPPORTED. The buggy codepath is nested inside 'if (instrumentWithCalls(ConvertedShadow)'. To keep the test cases small, we set -msan-instrumentation-with-call-threshold=0, though we have observed this bug in the real world with default settings.
1 parent c0d1d04 commit c940317

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --tool build-release/bin/opt --version 5
2+
; RUN: opt < %s -S -passes="msan<eager-checks;track-origins=2>" -msan-instrumentation-with-call-threshold=0 -disable-verify | FileCheck %s
3+
;
4+
; UNSUPPORTED: target={{.*}}
5+
;
6+
; This test illustrates a bug in MemorySanitizer that will shortly be fixed
7+
; (https://github.com/llvm/llvm-project/pull/96722).
8+
;
9+
; '-msan-instrumentation-with-call-threshold=0' makes it possible to detect the
10+
; bug with a short test case.
11+
;
12+
; '-disable-verify' with a release build is needed to avoid a compiler crash
13+
; (e.g., to autogenerate the assertions).
14+
;
15+
16+
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
17+
target triple = "aarch64-grtev4-linux-gnu"
18+
19+
; Function Attrs: mustprogress noreturn nounwind sanitize_memory
20+
define dso_local void @_Z1cv() local_unnamed_addr #0 {
21+
; CHECK-LABEL: define dso_local void @_Z1cv(
22+
; CHECK-SAME: ) local_unnamed_addr #[[ATTR0:[0-9]+]] {
23+
; CHECK-NEXT: [[ENTRY:.*]]:
24+
; CHECK-NEXT: call void @llvm.donothing()
25+
; CHECK-NEXT: [[DOTPRE:%.*]] = load <4 x i16>, ptr @_Z1cv, align 8, !tbaa [[TBAA0:![0-9]+]]
26+
; CHECK-NEXT: [[_MSLD:%.*]] = load <4 x i16>, ptr inttoptr (i64 xor (i64 ptrtoint (ptr @_Z1cv to i64), i64 193514046488576) to ptr), align 8
27+
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr inttoptr (i64 add (i64 xor (i64 ptrtoint (ptr @_Z1cv to i64), i64 193514046488576), i64 35184372088832) to ptr), align 8
28+
; CHECK-NEXT: br label %[[FOR_COND:.*]]
29+
; CHECK: [[FOR_COND]]:
30+
; CHECK-NEXT: [[_MSPHI_S:%.*]] = phi <4 x i16> [ [[_MSLD]], %[[ENTRY]] ], [ [[_MSLD3:%.*]], %[[FOR_COND]] ]
31+
; CHECK-NEXT: [[_MSPHI_O:%.*]] = phi i32 [ [[TMP0]], %[[ENTRY]] ], [ [[TMP15:%.*]], %[[FOR_COND]] ]
32+
; CHECK-NEXT: [[TMP1:%.*]] = phi <4 x i16> [ [[DOTPRE]], %[[ENTRY]] ], [ [[TMP5:%.*]], %[[FOR_COND]] ]
33+
; CHECK-NEXT: [[_MSPHI_S1:%.*]] = phi <4 x i16> [ <i16 -1, i16 -1, i16 -1, i16 -1>, %[[ENTRY]] ], [ [[_MSLD3]], %[[FOR_COND]] ]
34+
; CHECK-NEXT: [[_MSPHI_O2:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[TMP15]], %[[FOR_COND]] ]
35+
; CHECK-NEXT: [[E_0:%.*]] = phi <4 x i16> [ undef, %[[ENTRY]] ], [ [[TMP5]], %[[FOR_COND]] ]
36+
; CHECK-NEXT: [[_MSPROP:%.*]] = shufflevector <4 x i16> [[_MSPHI_S1]], <4 x i16> <i16 -1, i16 -1, i16 -1, i16 -1>, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
37+
; CHECK-NEXT: [[LANE:%.*]] = shufflevector <4 x i16> [[E_0]], <4 x i16> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
38+
;
39+
; Editor's note: the following zext instructions are invalid
40+
; ('zext source and destination must both be a vector or neither')
41+
;
42+
; CHECK-NEXT: [[TMP2:%.*]] = zext <4 x i16> [[_MSPHI_S]] to i64
43+
; CHECK-NEXT: call void @__msan_maybe_warning_8(i64 zeroext [[TMP2]], i32 zeroext [[_MSPHI_O]])
44+
; CHECK-NEXT: [[TMP3:%.*]] = zext <4 x i16> [[_MSPROP]] to i64
45+
;
46+
; CHECK-NEXT: call void @__msan_maybe_warning_8(i64 zeroext [[TMP3]], i32 zeroext [[_MSPHI_O2]])
47+
; CHECK-NEXT: [[CALL:%.*]] = tail call noundef i32 @_Z1b11__Int16x4_tS_(<4 x i16> noundef [[TMP1]], <4 x i16> noundef [[LANE]])
48+
; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[CALL]] to i64
49+
; CHECK-NEXT: [[TMP8:%.*]] = inttoptr i64 [[CONV]] to ptr
50+
; CHECK-NEXT: [[TMP5]] = load <4 x i16>, ptr [[TMP8]], align 8, !tbaa [[TBAA0]]
51+
; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[TMP8]] to i64
52+
; CHECK-NEXT: [[TMP11:%.*]] = xor i64 [[TMP10]], 193514046488576
53+
; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr
54+
; CHECK-NEXT: [[TMP13:%.*]] = add i64 [[TMP11]], 35184372088832
55+
; CHECK-NEXT: [[TMP14:%.*]] = inttoptr i64 [[TMP13]] to ptr
56+
; CHECK-NEXT: [[_MSLD3]] = load <4 x i16>, ptr [[TMP12]], align 8
57+
; CHECK-NEXT: [[TMP15]] = load i32, ptr [[TMP14]], align 8
58+
; CHECK-NEXT: store <4 x i16> [[_MSLD3]], ptr inttoptr (i64 xor (i64 ptrtoint (ptr @_Z1cv to i64), i64 193514046488576) to ptr), align 8
59+
; CHECK-NEXT: [[TMP16:%.*]] = bitcast <4 x i16> [[_MSLD3]] to i64
60+
; CHECK-NEXT: call void @__msan_maybe_store_origin_8(i64 zeroext [[TMP16]], ptr @_Z1cv, i32 zeroext [[TMP15]])
61+
; CHECK-NEXT: store <4 x i16> [[TMP5]], ptr @_Z1cv, align 8, !tbaa [[TBAA0]]
62+
; CHECK-NEXT: br label %[[FOR_COND]], !llvm.loop [[LOOP3:![0-9]+]]
63+
;
64+
entry:
65+
%.pre = load <4 x i16>, ptr @_Z1cv, align 8, !tbaa !2
66+
br label %for.cond
67+
68+
for.cond: ; preds = %for.cond, %entry
69+
%0 = phi <4 x i16> [ %.pre, %entry ], [ %2, %for.cond ]
70+
%e.0 = phi <4 x i16> [ undef, %entry ], [ %2, %for.cond ]
71+
%lane = shufflevector <4 x i16> %e.0, <4 x i16> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
72+
%call = tail call noundef i32 @_Z1b11__Int16x4_tS_(<4 x i16> noundef %0, <4 x i16> noundef %lane) #2
73+
%conv = sext i32 %call to i64
74+
%1 = inttoptr i64 %conv to ptr
75+
%2 = load <4 x i16>, ptr %1, align 8, !tbaa !2
76+
store <4 x i16> %2, ptr @_Z1cv, align 8, !tbaa !2
77+
br label %for.cond, !llvm.loop !5
78+
}
79+
80+
declare noundef i32 @_Z1b11__Int16x4_tS_(<4 x i16> noundef, <4 x i16> noundef) local_unnamed_addr #1
81+
82+
attributes #0 = { mustprogress noreturn nounwind sanitize_memory "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon" }
83+
84+
!2 = !{!3, !3, i64 0}
85+
!3 = !{!"omnipotent char", !4, i64 0}
86+
!4 = !{!"Simple C++ TBAA"}
87+
!5 = distinct !{!5, !6}
88+
!6 = !{!"llvm.loop.mustprogress"}
89+
;.
90+
; CHECK: [[TBAA0]] = !{[[META1:![0-9]+]], [[META1]], i64 0}
91+
; CHECK: [[META1]] = !{!"omnipotent char", [[META2:![0-9]+]], i64 0}
92+
; CHECK: [[META2]] = !{!"Simple C++ TBAA"}
93+
; CHECK: [[LOOP3]] = distinct !{[[LOOP3]], [[META4:![0-9]+]]}
94+
; CHECK: [[META4]] = !{!"llvm.loop.mustprogress"}
95+
;.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --tool build-release/bin/opt --version 5
2+
; RUN: opt < %s -S -passes="msan<eager-checks;track-origins=2>" -msan-instrumentation-with-call-threshold=0 -disable-verify | FileCheck %s
3+
;
4+
; UNSUPPORTED: target={{.*}}
5+
;
6+
; This test illustrates a bug in MemorySanitizer that will shortly be fixed
7+
; (https://github.com/llvm/llvm-project/pull/96722).
8+
;
9+
; '-msan-instrumentation-with-call-threshold=0' makes it possible to detect the
10+
; bug with a short test case.
11+
;
12+
; '-disable-verify' with a release build is needed to avoid a compiler crash
13+
; (e.g., to autogenerate the assertions).
14+
;
15+
; This is based on check-struct.ll.
16+
17+
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"
18+
target triple = "x86_64-unknown-linux-gnu"
19+
20+
define { i32, i8 } @main() sanitize_memory {
21+
; CHECK-LABEL: define { i32, i8 } @main(
22+
; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
23+
; CHECK-NEXT: call void @llvm.donothing()
24+
; CHECK-NEXT: [[P:%.*]] = inttoptr i64 0 to ptr
25+
; CHECK-NEXT: [[O:%.*]] = load { i32, i8 }, ptr [[P]], align 4
26+
; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P]] to i64
27+
; CHECK-NEXT: [[TMP2:%.*]] = xor i64 [[TMP1]], 87960930222080
28+
; CHECK-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr
29+
; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[TMP2]], 17592186044416
30+
; CHECK-NEXT: [[TMP5:%.*]] = inttoptr i64 [[TMP4]] to ptr
31+
; CHECK-NEXT: [[_MSLD:%.*]] = load { i32, i8 }, ptr [[TMP3]], align 4
32+
; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[TMP5]], align 4
33+
; CHECK-NEXT: store { i32, i8 } zeroinitializer, ptr @__msan_retval_tls, align 8
34+
;
35+
; Editor's note: the following zext instruction is invalid
36+
; ('ZExt only operates on integer')
37+
;
38+
; CHECK-NEXT: [[TMP7:%.*]] = zext { i32, i8 } [[_MSLD]] to i64
39+
;
40+
; CHECK-NEXT: call void @__msan_maybe_warning_8(i64 zeroext [[TMP7]], i32 zeroext [[TMP6]])
41+
; CHECK-NEXT: ret { i32, i8 } [[O]]
42+
;
43+
%p = inttoptr i64 0 to ptr
44+
%o = load { i32, i8 }, ptr %p
45+
ret { i32, i8 } %o
46+
}

0 commit comments

Comments
 (0)