Skip to content

Commit 9ad2e87

Browse files
authored
[DeviceMSAN] Check use-of-uninitialized value on private memory (#17309)
Support check use-of-uninitialized value on private memory
1 parent 20f9b53 commit 9ad2e87

File tree

15 files changed

+503
-151
lines changed

15 files changed

+503
-151
lines changed

clang/lib/Driver/SanitizerArgs.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,6 +1278,9 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
12781278

12791279
CmdArgs.push_back("-mllvm");
12801280
CmdArgs.push_back("-msan-eager-checks=1");
1281+
1282+
CmdArgs.push_back("-mllvm");
1283+
CmdArgs.push_back("-msan-poison-stack-with-call=1");
12811284
} else if (Sanitizers.has(SanitizerKind::Thread)) {
12821285
CmdArgs.push_back("-fsanitize=thread");
12831286
// The tsan function entry/exit builtins are used to record stack

libdevice/sanitizer/asan_rtl.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,8 @@ static __SYCL_CONSTANT__ const char __mem_set_shadow_private_end[] =
881881
static __SYCL_CONSTANT__ const char __mem_set_shadow_private[] =
882882
"[kernel] set_shadow_private(beg=%p, end=%p, val:%02X)\n";
883883

884+
// We outline the function of setting shadow memory of private memory, because
885+
// it may allocate failed on UR
884886
DEVICE_EXTERN_C_NOINLINE void __asan_set_shadow_private(uptr begin, uptr size,
885887
char val) {
886888
if (!__AsanLaunchInfo)

libdevice/sanitizer/msan_rtl.cpp

Lines changed: 121 additions & 35 deletions
Large diffs are not rendered by default.

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Lines changed: 214 additions & 81 deletions
Large diffs are not rendered by default.

llvm/test/Instrumentation/MemorySanitizer/SPIRV/check_large_access_size.ll

Lines changed: 0 additions & 19 deletions
This file was deleted.

llvm/test/Instrumentation/MemorySanitizer/SPIRV/check_unsupported_access.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: opt < %s -passes=msan -msan-instrumentation-with-call-threshold=0 -msan-eager-checks=1 -S | FileCheck %s
1+
; RUN: opt < %s -passes=msan -msan-instrumentation-with-call-threshold=0 -msan-eager-checks=1 -msan-spir-privates=0 -S | FileCheck %s
22
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
33
target triple = "spir64-unknown-unknown"
44

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
; RUN: opt < %s -passes=msan -msan-instrumentation-with-call-threshold=0 -msan-eager-checks=1 -msan-spir-privates=1 -msan-poison-stack-with-call=1 -S | FileCheck %s
2+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
3+
target triple = "spir64-unknown-unknown"
4+
5+
define spir_kernel void @MyKernel() sanitize_memory {
6+
; CHECK-LABEL: @MyKernel
7+
entry:
8+
%array = alloca [4 x i32], align 4
9+
; CHECK: call void @__msan_poison_stack(ptr %array, i64 16)
10+
ret void
11+
}
12+
13+
%"class.sycl::_V1::range" = type { %"class.sycl::_V1::detail::array" }
14+
%"class.sycl::_V1::detail::array" = type { [1 x i64] }
15+
16+
define spir_func void @ByValFunc(ptr noundef byval(%"class.sycl::_V1::range") align 8 %_arg_array12) sanitize_memory {
17+
; CHECK-LABEL: @ByValFunc
18+
entry:
19+
; CHECK: %0 = ptrtoint ptr %_arg_array12 to i64
20+
; CHECK: %1 = call i64 @__msan_get_shadow(i64 %0, i32 0, ptr addrspace(2) null)
21+
; CHECK: %2 = inttoptr i64 %1 to ptr addrspace(1)
22+
; CHECK: call void @llvm.memset.p1.i64(ptr addrspace(1) align 8 %2, i8 0, i64 8, i1 false)
23+
%_arg_array12.ascast = addrspacecast ptr %_arg_array12 to ptr addrspace(4)
24+
ret void
25+
}
26+
27+
define spir_kernel void @ByValKernel(ptr noundef byval(%"class.sycl::_V1::range") align 8 %_arg_array12) sanitize_memory {
28+
; CHECK-LABEL: @ByValKernel
29+
entry:
30+
; CHECK: %_arg_array12.byval = alloca %"class.sycl::_V1::range", align 8
31+
; CHECK: call void @__msan_unpoison_stack(ptr %_arg_array12.byval, i64 8), !nosanitize
32+
; CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %_arg_array12.byval, ptr align 8 %_arg_array12, i64 8, i1 false), !nosanitize
33+
call void @ByValFunc(ptr %_arg_array12)
34+
ret void
35+
}

llvm/test/Instrumentation/MemorySanitizer/SPIRV/instrument_static_local_mem.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: opt < %s -passes=msan -msan-instrumentation-with-call-threshold=0 -msan-eager-checks=1 -msan-spir-locals=1 -S | FileCheck %s
1+
; RUN: opt < %s -passes=msan -msan-instrumentation-with-call-threshold=0 -msan-eager-checks=1 -msan-spir-locals=1 -msan-spir-privates=0 -S | FileCheck %s
22
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
33
target triple = "spir64-unknown-unknown"
44

sycl/test-e2e/MemorySanitizer/check_buffer.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,17 @@
88

99
#include <sycl/detail/core.hpp>
1010

11-
__attribute__((noinline)) long long foo(int data1, long long data2) {
11+
__attribute__((noinline)) int foo(int data1, int data2) {
1212
return data1 + data2;
1313
}
1414

1515
int main() {
1616
sycl::queue q;
1717

1818
sycl::buffer<int, 1> buf1(sycl::range<1>(1));
19-
sycl::buffer<long long, 1> buf2(sycl::range<1>(1));
2019
q.submit([&](sycl::handler &h) {
2120
auto array1 = buf1.get_access<sycl::access::mode::read_write>(h);
22-
auto array2 = buf2.get_access<sycl::access::mode::read_write>(h);
23-
h.single_task<class MyKernel>(
24-
[=]() { array1[0] = foo(array1[0], array2[0]); });
21+
h.single_task<class MyKernel>([=]() { foo(array1[0], array1[0]); });
2522
}).wait();
2623
// CHECK: use-of-uninitialized-value
2724
// CHECK: kernel <{{.*MyKernel}}>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// REQUIRES: linux, cpu || (gpu && level_zero)
2+
// RUN: %{build} %device_msan_flags -O0 -g -o %t1.out
3+
// RUN: %{run} not %t1.out 2>&1 | FileCheck %s
4+
// RUN: %{build} %device_msan_flags -O1 -g -o %t2.out
5+
// RUN: %{run} not %t2.out 2>&1 | FileCheck %s
6+
// RUN: %{build} %device_msan_flags -O2 -g -o %t3.out
7+
// RUN: %{run} not %t3.out 2>&1 | FileCheck %s
8+
9+
#include <sycl/detail/core.hpp>
10+
#include <sycl/usm.hpp>
11+
12+
__attribute__((noinline)) int check(int p) { return p; }
13+
__attribute__((noinline)) int foo(int *p) { return check(*p); }
14+
// CHECK-NOT: [kernel]
15+
// CHECK: DeviceSanitizer: use-of-uninitialized-value
16+
// CHECK: #0 {{foo.*}} {{.*single_private.cpp}}:[[@LINE-3]]
17+
18+
int main() {
19+
sycl::queue Q;
20+
auto *array = sycl::malloc_device<int>(1, Q);
21+
22+
Q.submit([&](sycl::handler &h) {
23+
h.single_task<class MyKernel>([=]() {
24+
int p[4];
25+
*array += foo(p);
26+
});
27+
});
28+
Q.wait();
29+
30+
sycl::free(array, Q);
31+
return 0;
32+
}

0 commit comments

Comments
 (0)