diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index c2315d5de7041..d3c6a7151ec37 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -2085,6 +2085,10 @@ struct MemorySanitizerVisitor : public InstVisitor { assert(ShadowPtr && "Could not find shadow for an argument"); return ShadowPtr; } + + // TODO: Partially undefined vectors are handled by the fall-through case + // below (see partial-poison.ll); this causes false negatives. + // For everything else the shadow is zero. return getCleanShadow(V); } diff --git a/llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll b/llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll new file mode 100644 index 0000000000000..5164441c17e10 --- /dev/null +++ b/llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll @@ -0,0 +1,78 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt < %s -S -passes='msan' 2>&1 | FileCheck %s +; +; Test case to show that MSan computes shadows for partially poisoned vectors +; as fully initialized, resulting in false negatives. + +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" +target triple = "x86_64-unknown-linux-gnu" + +define <2 x i64> @left_poison(ptr %add.ptr) sanitize_memory { +; CHECK-LABEL: define <2 x i64> @left_poison( +; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: call void @llvm.donothing() +; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8 +; CHECK-NEXT: ret <2 x i64> +; + ret <2 x i64> +} + +define <2 x i64> @right_poison(ptr %add.ptr) sanitize_memory { +; CHECK-LABEL: define <2 x i64> @right_poison( +; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: call void @llvm.donothing() +; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8 +; CHECK-NEXT: ret <2 x i64> +; + ret <2 x i64> +} + +define <2 x i64> @full_poison(ptr %add.ptr) sanitize_memory { +; CHECK-LABEL: define <2 x i64> @full_poison( +; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: call void @llvm.donothing() +; CHECK-NEXT: store <2 x i64> splat (i64 -1), ptr @__msan_retval_tls, align 8 +; CHECK-NEXT: ret <2 x i64> poison +; + ret <2 x i64> +} + +define <2 x i64> @no_poison_or_undef(ptr %add.ptr) sanitize_memory { +; CHECK-LABEL: define <2 x i64> @no_poison_or_undef( +; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: call void @llvm.donothing() +; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8 +; CHECK-NEXT: ret <2 x i64> splat (i64 42) +; + ret <2 x i64> +} + +define <2 x i64> @left_undef(ptr %add.ptr) sanitize_memory { +; CHECK-LABEL: define <2 x i64> @left_undef( +; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: call void @llvm.donothing() +; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8 +; CHECK-NEXT: ret <2 x i64> +; + ret <2 x i64> +} + +define <2 x i64> @right_undef(ptr %add.ptr) sanitize_memory { +; CHECK-LABEL: define <2 x i64> @right_undef( +; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: call void @llvm.donothing() +; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8 +; CHECK-NEXT: ret <2 x i64> +; + ret <2 x i64> +} + +define <2 x i64> @full_undef(ptr %add.ptr) sanitize_memory { +; CHECK-LABEL: define <2 x i64> @full_undef( +; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: call void @llvm.donothing() +; CHECK-NEXT: store <2 x i64> splat (i64 -1), ptr @__msan_retval_tls, align 8 +; CHECK-NEXT: ret <2 x i64> undef +; + ret <2 x i64> +}