From 163a9f4552bea71b2d53126a5f74f9a1b47d2865 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Tue, 12 Apr 2022 13:45:53 -0700 Subject: [PATCH] [MSan] Ensure argument shadow initialized on memcpy We need to explicitly query the shadow here, because it is lazily initialized for byval arguments. Without opaque pointers this used to mostly work out, because there would be a bitcast to `i8*` present, and that would query, and copy in case of byval, the argument shadow. Reviewed By: vitalybuka, eugenis Differential Revision: https://reviews.llvm.org/D123602 --- .../Transforms/Instrumentation/MemorySanitizer.cpp | 2 ++ .../Instrumentation/MemorySanitizer/opaque-ptr.ll | 35 ++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 llvm/test/Instrumentation/MemorySanitizer/opaque-ptr.ll diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index 8315af3..034d97f 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -2570,6 +2570,7 @@ struct MemorySanitizerVisitor : public InstVisitor { /// /// Similar situation exists for memcpy and memset. void visitMemMoveInst(MemMoveInst &I) { + getShadow(I.getArgOperand(1)); // Ensure shadow initialized IRBuilder<> IRB(&I); IRB.CreateCall( MS.MemmoveFn, @@ -2584,6 +2585,7 @@ struct MemorySanitizerVisitor : public InstVisitor { // FIXME: consider doing manual inline for small constant sizes and proper // alignment. void visitMemCpyInst(MemCpyInst &I) { + getShadow(I.getArgOperand(1)); // Ensure shadow initialized IRBuilder<> IRB(&I); IRB.CreateCall( MS.MemcpyFn, diff --git a/llvm/test/Instrumentation/MemorySanitizer/opaque-ptr.ll b/llvm/test/Instrumentation/MemorySanitizer/opaque-ptr.ll new file mode 100644 index 0000000..07ee832 --- /dev/null +++ b/llvm/test/Instrumentation/MemorySanitizer/opaque-ptr.ll @@ -0,0 +1,35 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -passes=msan < %s | FileCheck %s + +target triple = "x86_64-unknown-linux-gnu" + +define void @test_memcpy(ptr %p, ptr byval(i32) %p2) sanitize_memory { +; CHECK-LABEL: @test_memcpy( +; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P2:%.*]] to i64 +; CHECK-NEXT: [[TMP2:%.*]] = xor i64 [[TMP1]], 87960930222080 +; CHECK-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP3]], ptr align 4 inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 8) to ptr), i64 4, i1 false) +; CHECK-NEXT: call void @llvm.donothing() +; CHECK-NEXT: [[TMP4:%.*]] = call ptr @__msan_memcpy(ptr [[P:%.*]], ptr [[P2]], i64 4) +; CHECK-NEXT: ret void +; + call void @llvm.memcpy.p0.p0.i64(i8* %p, i8* %p2, i64 4, i1 false) + ret void +} + +define void @test_memmove(ptr %p, ptr byval(i32) %p2) sanitize_memory { +; CHECK-LABEL: @test_memmove( +; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P2:%.*]] to i64 +; CHECK-NEXT: [[TMP2:%.*]] = xor i64 [[TMP1]], 87960930222080 +; CHECK-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP3]], ptr align 4 inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 8) to ptr), i64 4, i1 false) +; CHECK-NEXT: call void @llvm.donothing() +; CHECK-NEXT: [[TMP4:%.*]] = call ptr @__msan_memmove(ptr [[P:%.*]], ptr [[P2]], i64 4) +; CHECK-NEXT: ret void +; + call void @llvm.memmove.p0.p0.i64(i8* %p, i8* %p2, i64 4, i1 false) + ret void +} + +declare void @llvm.memcpy.p0.p0.i64(i8*, i8*, i64, i1) +declare void @llvm.memmove.p0.p0.i64(i8*, i8*, i64, i1) -- 2.7.4