[clang] c059ede - [msan] Add more specific messages for use-after-destroy
Vitaly Buka via cfe-commits
cfe-commits at lists.llvm.org
Tue Aug 30 19:52:49 PDT 2022
Author: Vitaly Buka
Date: 2022-08-30T19:52:32-07:00
New Revision: c059ede28ea8faf0540cedad74bc5698ec59e744
URL: https://github.com/llvm/llvm-project/commit/c059ede28ea8faf0540cedad74bc5698ec59e744
DIFF: https://github.com/llvm/llvm-project/commit/c059ede28ea8faf0540cedad74bc5698ec59e744.diff
LOG: [msan] Add more specific messages for use-after-destroy
Reviewed By: kda, kstoimenov
Differential Revision: https://reviews.llvm.org/D132907
Added:
Modified:
clang/lib/CodeGen/CGClass.cpp
clang/test/CodeGenCXX/sanitize-dtor-bit-field.cpp
clang/test/CodeGenCXX/sanitize-dtor-callback.cpp
clang/test/CodeGenCXX/sanitize-dtor-derived-class.cpp
clang/test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp
clang/test/CodeGenCXX/sanitize-dtor-tail-call.cpp
clang/test/CodeGenCXX/sanitize-dtor-trivial-base.cpp
clang/test/CodeGenCXX/sanitize-dtor-trivial.cpp
clang/test/CodeGenCXX/sanitize-dtor-vtable.cpp
clang/test/CodeGenCXX/sanitize-dtor-zero-size-field.cpp
compiler-rt/include/sanitizer/msan_interface.h
compiler-rt/lib/msan/msan.h
compiler-rt/lib/msan/msan_interceptors.cpp
compiler-rt/lib/msan/msan_interface_internal.h
compiler-rt/lib/msan/msan_report.cpp
compiler-rt/test/msan/dtor-base-access.cpp
compiler-rt/test/msan/dtor-vtable-multiple-inheritance.cpp
compiler-rt/test/msan/use-after-dtor.cpp
Removed:
################################################################################
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 703eff8ac54c5..ec4d8e50a3560 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -1649,23 +1649,35 @@ namespace {
}
};
- static void EmitSanitizerDtorCallback(CodeGenFunction &CGF, llvm::Value *Ptr,
- CharUnits::QuantityType PoisonSize) {
+ static void EmitSanitizerDtorCallback(
+ CodeGenFunction &CGF, StringRef Name, llvm::Value *Ptr,
+ llvm::Optional<CharUnits::QuantityType> PoisonSize = {}) {
CodeGenFunction::SanitizerScope SanScope(&CGF);
// Pass in void pointer and size of region as arguments to runtime
// function
- llvm::Value *Args[] = {CGF.Builder.CreateBitCast(Ptr, CGF.VoidPtrTy),
- llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)};
+ SmallVector<llvm::Value *, 2> Args = {
+ CGF.Builder.CreateBitCast(Ptr, CGF.VoidPtrTy)};
+ SmallVector<llvm::Type *, 2> ArgTypes = {CGF.VoidPtrTy};
- llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy};
+ if (PoisonSize.has_value()) {
+ Args.emplace_back(llvm::ConstantInt::get(CGF.SizeTy, *PoisonSize));
+ ArgTypes.emplace_back(CGF.SizeTy);
+ }
llvm::FunctionType *FnType =
llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false);
- llvm::FunctionCallee Fn =
- CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback");
+ llvm::FunctionCallee Fn = CGF.CGM.CreateRuntimeFunction(FnType, Name);
+
CGF.EmitNounwindRuntimeCall(Fn, Args);
}
+ static void
+ EmitSanitizerDtorFieldsCallback(CodeGenFunction &CGF, llvm::Value *Ptr,
+ CharUnits::QuantityType PoisonSize) {
+ EmitSanitizerDtorCallback(CGF, "__sanitizer_dtor_callback_fields", Ptr,
+ PoisonSize);
+ }
+
/// Poison base class with a trivial destructor.
struct SanitizeDtorTrivialBase final : EHScopeStack::Cleanup {
const CXXRecordDecl *BaseClass;
@@ -1687,7 +1699,8 @@ namespace {
if (!BaseSize.isPositive())
return;
- EmitSanitizerDtorCallback(CGF, Addr.getPointer(), BaseSize.getQuantity());
+ EmitSanitizerDtorFieldsCallback(CGF, Addr.getPointer(),
+ BaseSize.getQuantity());
// Prevent the current stack frame from disappearing from the stack trace.
CGF.CurFn->addFnAttr("disable-tail-calls", "true");
@@ -1735,7 +1748,7 @@ namespace {
if (!PoisonSize.isPositive())
return;
- EmitSanitizerDtorCallback(CGF, OffsetPtr, PoisonSize.getQuantity());
+ EmitSanitizerDtorFieldsCallback(CGF, OffsetPtr, PoisonSize.getQuantity());
// Prevent the current stack frame from disappearing from the stack trace.
CGF.CurFn->addFnAttr("disable-tail-calls", "true");
@@ -1752,15 +1765,13 @@ namespace {
void Emit(CodeGenFunction &CGF, Flags flags) override {
assert(Dtor->getParent()->isDynamicClass());
(void)Dtor;
- ASTContext &Context = CGF.getContext();
// Poison vtable and vtable ptr if they exist for this class.
llvm::Value *VTablePtr = CGF.LoadCXXThis();
- CharUnits::QuantityType PoisonSize =
- Context.toCharUnitsFromBits(CGF.PointerWidthInBits).getQuantity();
// Pass in void pointer and size of region as arguments to runtime
// function
- EmitSanitizerDtorCallback(CGF, VTablePtr, PoisonSize);
+ EmitSanitizerDtorCallback(CGF, "__sanitizer_dtor_callback_vptr",
+ VTablePtr);
}
};
diff --git a/clang/test/CodeGenCXX/sanitize-dtor-bit-field.cpp b/clang/test/CodeGenCXX/sanitize-dtor-bit-field.cpp
index 6629cd8b274ea..94571d449380d 100644
--- a/clang/test/CodeGenCXX/sanitize-dtor-bit-field.cpp
+++ b/clang/test/CodeGenCXX/sanitize-dtor-bit-field.cpp
@@ -63,22 +63,22 @@ struct Adjacent {
Adjacent ad;
// CHECK-LABEL: define {{.*}}PackedD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}i64 17{{.*}}, !dbg ![[DI1:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}i64 17{{.*}}, !dbg ![[DI1:[0-9]+]]
// CHECK: ret void
// CHECK-LABEL: define {{.*}}EmptyD2Ev
// CHECK: ret void
// CHECK-LABEL: define {{.*}}SimpleD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}i64 1{{.*}}, !dbg ![[DI2:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}i64 1{{.*}}, !dbg ![[DI2:[0-9]+]]
// CHECK: ret void
// CHECK-LABEL: define {{.*}}AnonD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}i64 5{{.*}}, !dbg ![[DI3:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}i64 5{{.*}}, !dbg ![[DI3:[0-9]+]]
// CHECK: ret void
// CHECK-LABEL: define {{.*}}AdjacentD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}i64 1{{.*}}, !dbg ![[DI4:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}i64 1{{.*}}, !dbg ![[DI4:[0-9]+]]
// CHECK: ret void
// CHECK-LABEL: !DIFile{{.*}}cpp
diff --git a/clang/test/CodeGenCXX/sanitize-dtor-callback.cpp b/clang/test/CodeGenCXX/sanitize-dtor-callback.cpp
index d42008a7ad79c..18c6417001fd9 100644
--- a/clang/test/CodeGenCXX/sanitize-dtor-callback.cpp
+++ b/clang/test/CodeGenCXX/sanitize-dtor-callback.cpp
@@ -56,16 +56,16 @@ Defaulted_Non_Trivial def_non_trivial;
// instrumentation inserted.
// CHECK-LABEL: define {{.*}}SimpleD2Ev
// CHECK-NOT: store i{{[0-9]+}} 0, {{.*}}@__msan_param_tls
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, !dbg ![[DI1:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, !dbg ![[DI1:[0-9]+]]
// CHECK: ret void
// CHECK-LABEL: define {{.*}}InlinedD2Ev
// CHECK-NOT: store i{{[0-9]+}} 0, {{.*}}@__msan_param_tls
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, !dbg ![[DI2:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, !dbg ![[DI2:[0-9]+]]
// CHECK: ret void
// CHECK-LABEL: define {{.*}}Defaulted_Non_TrivialD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, !dbg ![[DI3:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, !dbg ![[DI3:[0-9]+]]
// CHECK: ret void
// CHECK-LABEL: !DIFile{{.*}}cpp
diff --git a/clang/test/CodeGenCXX/sanitize-dtor-derived-class.cpp b/clang/test/CodeGenCXX/sanitize-dtor-derived-class.cpp
index 1a6aa9ed1cdbf..1d5accb8bfd06 100644
--- a/clang/test/CodeGenCXX/sanitize-dtor-derived-class.cpp
+++ b/clang/test/CodeGenCXX/sanitize-dtor-derived-class.cpp
@@ -49,15 +49,15 @@ Derived d;
// Poison members and vtable ptr.
// CHECK-LABEL: define {{.*}}BaseD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, !dbg ![[DI1:[0-9]+]]
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}i64 8{{.*}}, !dbg ![[DI1]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, !dbg ![[DI1:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_vptr({{.*}}){{.*}}, !dbg ![[DI1]]
// CHECK: ret void
// Poison members and destroy non-virtual base.
// CHECK-LABEL: define {{.*}}DerivedD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, !dbg ![[DI3:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, !dbg ![[DI3:[0-9]+]]
// CHECK: call void {{.*}}BaseD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}i64 8{{.*}}, !dbg ![[DI3]]
+// CHECK: call void @__sanitizer_dtor_callback_vptr({{.*}}){{.*}}, !dbg ![[DI3]]
// CHECK: ret void
// CHECK-LABEL: !DIFile{{.*}}cpp
diff --git a/clang/test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp b/clang/test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp
index d30bd3ade7495..adbe77fc659bd 100644
--- a/clang/test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp
+++ b/clang/test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp
@@ -47,7 +47,7 @@ Derived d;
// CHECK-LABEL: define {{.*}}ZN7DerivedD1Ev
// CHECK: call void {{.*}}ZN11VirtualBaseD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}){{.*}}, !dbg ![[DI0:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_vptr({{.*}}){{.*}}, !dbg ![[DI0:[0-9]+]]
// CHECK: ret void
// CHECK-LABEL: define {{.*}}ZN7DerivedD0Ev
@@ -61,27 +61,27 @@ Derived d;
// poison 2 ints
// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, i64 8){{.*}}, !dbg ![[DI1:[0-9]+]]
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, i64 8)
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, i64 8){{.*}}, !dbg ![[DI1:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_vptr({{.*}}){{.*}}, !dbg ![[DI1]]
// CHECK: ret void
// poison int and double
// CHECK-LABEL: define {{.*}}ZN4BaseD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}{{.*}}, !dbg ![[DI2:[0-9]+]]
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, i64 8)
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, i64 16){{.*}}, !dbg ![[DI2:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_vptr({{.*}}{{.*}}, !dbg ![[DI2]]
// CHECK: ret void
// poison int, ignore vector, poison int
// CHECK-LABEL: define {{.*}}ZN7DerivedD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, i64 4){{.*}}, !dbg ![[DI3:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, i64 4){{.*}}, !dbg ![[DI3:[0-9]+]]
// CHECK: call void {{.*}}ZN6VectorIiED1Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, i64 4){{.*}}, !dbg ![[DI3]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, i64 4){{.*}}, !dbg ![[DI3]]
// CHECK: call void {{.*}}ZN4BaseD2Ev
// CHECK: ret void
// poison int
// CHECK-LABEL: define {{.*}}ZN6VectorIiED2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, i64 4){{.*}}, !dbg ![[DI5:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, i64 4){{.*}}, !dbg ![[DI5:[0-9]+]]
// CHECK: ret void
// CHECK-LABEL: !DIFile{{.*}}.cpp
diff --git a/clang/test/CodeGenCXX/sanitize-dtor-tail-call.cpp b/clang/test/CodeGenCXX/sanitize-dtor-tail-call.cpp
index 3d52e725cc556..5cdf69edb9d04 100644
--- a/clang/test/CodeGenCXX/sanitize-dtor-tail-call.cpp
+++ b/clang/test/CodeGenCXX/sanitize-dtor-tail-call.cpp
@@ -15,7 +15,7 @@ struct Simple {
Simple s;
// Simple internal member is poisoned by compiler-generated dtor
// CHECK: define {{.*}}SimpleD2Ev{{.*}} [[ATTRIBUTE:#[0-9]+]]
-// CHECK: {{^ *}}call void @__sanitizer_dtor_callback(
+// CHECK: call void @__sanitizer_dtor_callback_fields(
// CHECK: ret void
// Destructor does not emit any tail calls
diff --git a/clang/test/CodeGenCXX/sanitize-dtor-trivial-base.cpp b/clang/test/CodeGenCXX/sanitize-dtor-trivial-base.cpp
index 5da9405b74067..cfb80f8dbd6cb 100644
--- a/clang/test/CodeGenCXX/sanitize-dtor-trivial-base.cpp
+++ b/clang/test/CodeGenCXX/sanitize-dtor-trivial-base.cpp
@@ -20,8 +20,8 @@ Derived d;
// Poison members, then poison the trivial base class.
// CHECK-LABEL: define {{.*}}DerivedD2Ev
// CHECK: %[[GEP:[0-9a-z]+]] = getelementptr i8, i8* {{.*}}, i64 16
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}%[[GEP]], i64 4{{.*}}, !dbg ![[DI:[0-9]+]]
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, i64 16{{.*}}, !dbg ![[DI]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}%[[GEP]], i64 4{{.*}}, !dbg ![[DI:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, i64 16{{.*}}, !dbg ![[DI]]
// CHECK: ret void
// CHECK-LABEL: !DIFile{{.*}}cpp
diff --git a/clang/test/CodeGenCXX/sanitize-dtor-trivial.cpp b/clang/test/CodeGenCXX/sanitize-dtor-trivial.cpp
index eb60f7fa46eb0..e2b19424542bb 100644
--- a/clang/test/CodeGenCXX/sanitize-dtor-trivial.cpp
+++ b/clang/test/CodeGenCXX/sanitize-dtor-trivial.cpp
@@ -14,7 +14,6 @@ Trivial t;
// CHECK: call void @__sanitizer_dtor_callback({{.*}}, !dbg ![[DI:[0-9]+]]
+// CHECK-LABEL: !DIFile{{.*}}.cpp
-// CHECK-LABEL: !DIFile{{.*}}cpp
-
-// CHECK-DAG: ![[DI]] = {{.*}}line: [[@LINE-28]]
+// CHECK-DAG: ![[DI]] = {{.*}}line: [[@LINE-371]]
diff --git a/clang/test/CodeGenCXX/sanitize-dtor-vtable.cpp b/clang/test/CodeGenCXX/sanitize-dtor-vtable.cpp
index 063ff7ffdb081..49de930ce84ad 100644
--- a/clang/test/CodeGenCXX/sanitize-dtor-vtable.cpp
+++ b/clang/test/CodeGenCXX/sanitize-dtor-vtable.cpp
@@ -25,18 +25,18 @@ B b;
// CHECK-LABEL: define {{.*}}BD1Ev
// CHECK: call void {{.*}}BD2Ev
// CHECK: call void {{.*}}AD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, !dbg ![[DI1:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_vptr({{.*}}, !dbg ![[DI1:[0-9]+]]
// CHECK: ret void
// Since no virtual bases, poison vtable ptr here.
// CHECK-LABEL: define {{.*}}AD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, !dbg ![[DI2:[0-9]+]]
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, !dbg ![[DI2]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, !dbg ![[DI2:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_vptr({{.*}}, !dbg ![[DI2]]
// CHECK: ret void
// Poison members
// CHECK-LABEL: define {{.*}}BD2Ev
-// CHECK: call void @__sanitizer_dtor_callback({{.*}}, !dbg ![[DI4:[0-9]+]]
+// CHECK: call void @__sanitizer_dtor_callback_fields({{.*}}, !dbg ![[DI4:[0-9]+]]
// CHECK: ret void
// CHECK-LABEL: !DIFile{{.*}}cpp
diff --git a/clang/test/CodeGenCXX/sanitize-dtor-zero-size-field.cpp b/clang/test/CodeGenCXX/sanitize-dtor-zero-size-field.cpp
index a0b0631b952b5..7aba27e6b8d19 100644
--- a/clang/test/CodeGenCXX/sanitize-dtor-zero-size-field.cpp
+++ b/clang/test/CodeGenCXX/sanitize-dtor-zero-size-field.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -no-opaque-pointers -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++20 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s --implicit-check-not "call void @__sanitizer_dtor_callback"
-// RUN: %clang_cc1 -no-opaque-pointers -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++20 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s --implicit-check-not "call void @__sanitizer_dtor_callback"
+// RUN: %clang_cc1 -no-opaque-pointers -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++20 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s --implicit-check-not "call void @__sanitizer_dtor_callback_fields"
+// RUN: %clang_cc1 -no-opaque-pointers -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++20 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s --implicit-check-not "call void @__sanitizer_dtor_callback_fields"
struct Empty {};
@@ -30,7 +30,7 @@ struct Struct {
static_assert(sizeof(Struct) == 16);
} // namespace T0
// CHECK-LABEL: define {{.*}} @_ZN2T06StructD2Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 13)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 13)
// CHECK-NEXT: ret void
namespace empty {
@@ -45,7 +45,7 @@ static_assert(sizeof(Struct) == 24);
} // namespace T1
// CHECK-LABEL: define {{.*}} @_ZN5empty2T16StructD2Ev(
// CHECK: [[GEP:%.+]] = getelementptr i8, {{.*}}, i64 8{{$}}
-// CHECK: call void @__sanitizer_dtor_callback(i8* [[GEP]], i64 13)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* [[GEP]], i64 13)
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK-NEXT: ret void
@@ -60,10 +60,10 @@ static_assert(sizeof(Struct) == 24);
} // namespace T2
// CHECK-LABEL: define {{.*}} @_ZN5empty2T26StructD2Ev(
// CHECK: [[GEP1:%.+]] = getelementptr i8, {{.*}}, i64 16{{$}}
-// CHECK: call void @__sanitizer_dtor_callback(i8* [[GEP1]], i64 5)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* [[GEP1]], i64 5)
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK: [[GEP2:%.+]] = getelementptr i8, {{.*}}, i64 0{{$}}
-// CHECK: call void @__sanitizer_dtor_callback(i8* [[GEP2]], i64 8)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* [[GEP2]], i64 8)
// CHECK-NEXT: ret void
namespace T3 {
@@ -77,10 +77,10 @@ static_assert(sizeof(Struct) == 24);
} // namespace T3
// CHECK-LABEL: define {{.*}} @_ZN5empty2T36StructD2Ev(
// CHECK: [[GEP1:%.+]] = getelementptr i8, {{.*}}, i64 20{{$}}
-// CHECK: call void @__sanitizer_dtor_callback(i8* [[GEP1]], i64 1)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* [[GEP1]], i64 1)
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK: [[GEP2:%.+]] = getelementptr i8, {{.*}}, i64 0{{$}}
-// CHECK: call void @__sanitizer_dtor_callback(i8* [[GEP2]], i64 12)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* [[GEP2]], i64 12)
// CHECK-NEXT: ret void
namespace T4 {
@@ -93,7 +93,7 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T4
// CHECK-LABEL: define {{.*}} @_ZN5empty2T46StructD2Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 16)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 16)
// CHECK-NEXT: ret void
namespace T5 {
@@ -107,7 +107,7 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T5
// CHECK-LABEL: define {{.*}} @_ZN5empty2T56StructD2Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 13)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 13)
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK-NEXT: ret void
@@ -122,7 +122,7 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T6
// CHECK-LABEL: define {{.*}} @_ZN5empty2T66StructD2Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 13)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 13)
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK-NEXT: ret void
@@ -137,9 +137,9 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T7
// CHECK-LABEL: define {{.*}} @_ZN5empty2T76StructD2Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 5)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 5)
// CHECK: call void @_ZN10NonTrivialD1Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 8)
// CHECK-NEXT: ret void
namespace T8 {
@@ -153,8 +153,8 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T8
// CHECK-LABEL: define {{.*}} @_ZN5empty2T86StructD2Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 5)
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 5)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 8)
// CHECK-NEXT: ret void
namespace T9 {
@@ -168,8 +168,8 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T9
// CHECK-LABEL: define {{.*}} @_ZN5empty2T96StructD2Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 1)
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 1)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 12)
// CHECK-NEXT: ret void
namespace T10 {
@@ -183,8 +183,8 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T10
// CHECK-LABEL: define {{.*}} @_ZN5empty3T106StructD2Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 1)
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 1)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 12)
// CHECK-NEXT: ret void
namespace T11 {
@@ -198,7 +198,7 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T11
// CHECK-LABEL: define {{.*}} @_ZN5empty3T116StructD2Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 16)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 16)
// CHECK-NEXT: ret void
namespace T12 {
@@ -214,7 +214,7 @@ static_assert(sizeof(Struct) == 24);
} // namespace empty
// CHECK-LABEL: define {{.*}} @_ZN5empty3T126StructD2Ev(
// CHECK: call void @_ZN10NonTrivialD1Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 16)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 16)
// CHECK-NEXT: ret void
namespace empty_non_trivial {
@@ -228,7 +228,7 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T1
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T16StructD2Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 13)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 13)
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK-NEXT: ret void
@@ -242,8 +242,8 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T2
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T26StructD2Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 5)
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 5)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 8)
// CHECK-NEXT: ret void
namespace T3 {
@@ -256,8 +256,8 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T3
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T36StructD2Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 1)
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 1)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 12)
// CHECK-NEXT: ret void
namespace T4 {
@@ -270,7 +270,7 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T4
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T46StructD2Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 16)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 16)
// CHECK-NEXT: ret void
namespace T5 {
@@ -284,7 +284,7 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T5
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T56StructD2Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 13)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 13)
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK: call void @_ZN15EmptyNonTrivialD1Ev(
// CHECK-NEXT: ret void
@@ -300,7 +300,7 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T6
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T66StructD2Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 13)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 13)
// CHECK: call void @_ZN15EmptyNonTrivialD1Ev(
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK-NEXT: ret void
@@ -316,10 +316,10 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T7
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T76StructD2Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 5)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 5)
// CHECK: call void @_ZN15EmptyNonTrivialD1Ev(
// CHECK: call void @_ZN10NonTrivialD1Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 8)
// CHECK-NEXT: ret void
namespace T8 {
@@ -333,9 +333,9 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T8
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T86StructD2Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 5)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 5)
// CHECK: call void @_ZN10NonTrivialD1Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 8)
// CHECK: call void @_ZN15EmptyNonTrivialD1Ev(
// CHECK-NEXT: ret void
@@ -350,10 +350,10 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T9
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T96StructD2Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 1)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 1)
// CHECK: call void @_ZN15EmptyNonTrivialD1Ev(
// CHECK: call void @_ZN10NonTrivialD1Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 12)
// CHECK-NEXT: ret void
namespace T10 {
@@ -367,9 +367,9 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T10
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial3T106StructD2Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 1)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 1)
// CHECK: call void @_ZN10NonTrivialD1Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 12)
// CHECK: call void @_ZN15EmptyNonTrivialD1Ev(
// CHECK-NEXT: ret void
@@ -386,7 +386,7 @@ static_assert(sizeof(Struct) == 24);
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial3T116StructD2Ev(
// CHECK: call void @_ZN15EmptyNonTrivialD1Ev(
// CHECK: call void @_ZN10NonTrivialD1Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 16)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 16)
// CHECK-NEXT: ret void
namespace T12 {
@@ -402,6 +402,6 @@ static_assert(sizeof(Struct) == 24);
} // namespace empty_non_trivial
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial3T126StructD2Ev(
// CHECK: call void @_ZN10NonTrivialD1Ev(
-// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 16)
+// CHECK: call void @__sanitizer_dtor_callback_fields(i8* {{.*}}, i64 16)
// CHECK: call void @_ZN15EmptyNonTrivialD1Ev(
// CHECK: ret void
diff --git a/compiler-rt/include/sanitizer/msan_interface.h b/compiler-rt/include/sanitizer/msan_interface.h
index eeb39fbed8b49..854b12cda36ec 100644
--- a/compiler-rt/include/sanitizer/msan_interface.h
+++ b/compiler-rt/include/sanitizer/msan_interface.h
@@ -92,6 +92,8 @@ extern "C" {
/* Tell MSan about newly destroyed memory. Mark memory as uninitialized. */
void __sanitizer_dtor_callback(const volatile void* data, size_t size);
+ void __sanitizer_dtor_callback_fields(const volatile void *data, size_t size);
+ void __sanitizer_dtor_callback_vptr(const volatile void *data);
/* This function may be optionally provided by user and should return
a string containing Msan runtime options. See msan_flags.h for details. */
diff --git a/compiler-rt/lib/msan/msan.h b/compiler-rt/lib/msan/msan.h
index 1a4cc8c0c9756..5dc57fdd22be0 100644
--- a/compiler-rt/lib/msan/msan.h
+++ b/compiler-rt/lib/msan/msan.h
@@ -349,6 +349,8 @@ void UnpoisonThreadLocalState();
u32 ChainOrigin(u32 id, StackTrace *stack);
const int STACK_TRACE_TAG_POISON = StackTrace::TAG_CUSTOM + 1;
+const int STACK_TRACE_TAG_FIELDS = STACK_TRACE_TAG_POISON + 1;
+const int STACK_TRACE_TAG_VPTR = STACK_TRACE_TAG_FIELDS + 1;
#define GET_MALLOC_STACK_TRACE \
BufferedStackTrace stack; \
diff --git a/compiler-rt/lib/msan/msan_interceptors.cpp b/compiler-rt/lib/msan/msan_interceptors.cpp
index c4a9e88655fe0..b3d5484c70a35 100644
--- a/compiler-rt/lib/msan/msan_interceptors.cpp
+++ b/compiler-rt/lib/msan/msan_interceptors.cpp
@@ -944,6 +944,22 @@ void __sanitizer_dtor_callback(const void *data, uptr size) {
}
}
+void __sanitizer_dtor_callback_fields(const void *data, uptr size) {
+ if (flags()->poison_in_dtor) {
+ GET_MALLOC_STACK_TRACE;
+ stack.tag = STACK_TRACE_TAG_FIELDS;
+ PoisonMemory(data, size, &stack);
+ }
+}
+
+void __sanitizer_dtor_callback_vptr(const void *data) {
+ if (flags()->poison_in_dtor) {
+ GET_MALLOC_STACK_TRACE;
+ stack.tag = STACK_TRACE_TAG_VPTR;
+ PoisonMemory(data, sizeof(void *), &stack);
+ }
+}
+
template <class Mmap>
static void *mmap_interceptor(Mmap real_mmap, void *addr, SIZE_T length,
int prot, int flags, int fd, OFF64_T offset) {
diff --git a/compiler-rt/lib/msan/msan_interface_internal.h b/compiler-rt/lib/msan/msan_interface_internal.h
index 535c3fca8b24d..c2eead13c20cf 100644
--- a/compiler-rt/lib/msan/msan_interface_internal.h
+++ b/compiler-rt/lib/msan/msan_interface_internal.h
@@ -162,6 +162,10 @@ void __msan_allocated_memory(const void* data, uptr size);
// uninitialized.
SANITIZER_INTERFACE_ATTRIBUTE
void __sanitizer_dtor_callback(const void* data, uptr size);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_dtor_callback_fields(const void *data, uptr size);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_dtor_callback_vptr(const void *data);
SANITIZER_INTERFACE_ATTRIBUTE
u16 __sanitizer_unaligned_load16(const uu16 *p);
diff --git a/compiler-rt/lib/msan/msan_report.cpp b/compiler-rt/lib/msan/msan_report.cpp
index c8fc286c782df..d1ef36d9a322a 100644
--- a/compiler-rt/lib/msan/msan_report.cpp
+++ b/compiler-rt/lib/msan/msan_report.cpp
@@ -81,6 +81,13 @@ static void DescribeOrigin(u32 id) {
Printf(" %sMemory was marked as uninitialized%s\n", d.Origin(),
d.Default());
break;
+ case STACK_TRACE_TAG_FIELDS:
+ Printf(" %sMember fields were destroyed%s\n", d.Origin(), d.Default());
+ break;
+ case STACK_TRACE_TAG_VPTR:
+ Printf(" %sVirtual table ptr was destroyed%s\n", d.Origin(),
+ d.Default());
+ break;
default:
Printf(" %sUninitialized value was created%s\n", d.Origin(),
d.Default());
diff --git a/compiler-rt/test/msan/dtor-base-access.cpp b/compiler-rt/test/msan/dtor-base-access.cpp
index 1e141d5afdb26..e182af280150e 100644
--- a/compiler-rt/test/msan/dtor-base-access.cpp
+++ b/compiler-rt/test/msan/dtor-base-access.cpp
@@ -66,17 +66,17 @@ int main() {
assert(__msan_test_shadow(&g->d, sizeof(g->d)) == 0);
__msan_print_shadow(&g->tb0, sizeof(g->tb0));
- // CHECK: Memory was marked as uninitialized
+ // CHECK: Member fields were destroyed
// CHECK: {{#0 0x.* in __sanitizer_dtor_callback}}
// CHECK: {{#1 0x.* in .*~Derived.*cpp:}}[[@LINE-20]]:
__msan_print_shadow(&g->b, sizeof(g->b));
- // CHECK: Memory was marked as uninitialized
+ // CHECK: Member fields were destroyed
// CHECK: {{#0 0x.* in __sanitizer_dtor_callback}}
// CHECK: {{#1 0x.* in .*~Base.*cpp:}}[[@LINE-33]]:
__msan_print_shadow(&g->tb1, sizeof(g->tb1));
- // CHECK: Memory was marked as uninitialized
+ // CHECK: Member fields were destroyed
// CHECK: {{#0 0x.* in __sanitizer_dtor_callback}}
// CHECK: {{#1 0x.* in .*~Derived.*cpp:}}[[@LINE-30]]:
diff --git a/compiler-rt/test/msan/dtor-vtable-multiple-inheritance.cpp b/compiler-rt/test/msan/dtor-vtable-multiple-inheritance.cpp
index 7e50c49928e6a..600102cd53a73 100644
--- a/compiler-rt/test/msan/dtor-vtable-multiple-inheritance.cpp
+++ b/compiler-rt/test/msan/dtor-vtable-multiple-inheritance.cpp
@@ -51,8 +51,8 @@ int main() {
// This fails
#ifdef CVPTR
c->A_Foo();
-// CVPTR: Memory was marked as uninitialized
-// CVPTR: {{#0 0x.* in __sanitizer_dtor_callback}}
+// CVPTR: Virtual table ptr was destroyed
+// CVPTR: {{#0 0x.* in __sanitizer_dtor_callback_vptr}}
// CVPTR: {{#1 0x.* in ~C .*cpp:}}[[@LINE-28]]:
// CVPTR: {{#2 0x.* in main .*cpp:}}[[@LINE-7]]:
#endif
@@ -63,16 +63,16 @@ int main() {
// Both of these fail
#ifdef EAVPTR
e->A_Foo();
-// EAVPTR: Memory was marked as uninitialized
-// EAVPTR: {{#0 0x.* in __sanitizer_dtor_callback}}
+// EAVPTR: Virtual table ptr was destroyed
+// EAVPTR: {{#0 0x.* in __sanitizer_dtor_callback_vptr}}
// EAVPTR: {{#1 0x.* in ~E .*cpp:}}[[@LINE-25]]:
// EAVPTR: {{#2 0x.* in main .*cpp:}}[[@LINE-7]]:
#endif
#ifdef EDVPTR
e->D_Foo();
-// EDVPTR: Memory was marked as uninitialized
-// EDVPTR: {{#0 0x.* in __sanitizer_dtor_callback}}
+// EDVPTR: Virtual table ptr was destroyed
+// EDVPTR: {{#0 0x.* in __sanitizer_dtor_callback_vptr}}
// EDVPTR: {{#1 0x.* in ~E .*cpp:}}[[@LINE-33]]:
// EDVPTR: {{#2 0x.* in main .*cpp:}}[[@LINE-15]]:
#endif
diff --git a/compiler-rt/test/msan/use-after-dtor.cpp b/compiler-rt/test/msan/use-after-dtor.cpp
index 67582c18bc931..385dc349f4d5c 100644
--- a/compiler-rt/test/msan/use-after-dtor.cpp
+++ b/compiler-rt/test/msan/use-after-dtor.cpp
@@ -32,7 +32,7 @@ int main() {
// CHECK-UAD: WARNING: MemorySanitizer: use-of-uninitialized-value
// CHECK-UAD: {{#0 0x.* in main.*use-after-dtor.cpp:}}[[@LINE-3]]
- // CHECK-ORIGINS: Memory was marked as uninitialized
+ // CHECK-ORIGINS: Member fields were destroyed
// CHECK-ORIGINS: {{#0 0x.* in __sanitizer_dtor_callback}}
// CHECK-ORIGINS: {{#1 0x.* in .*~Simple.*cpp:}}[[@LINE-18]]:
More information about the cfe-commits
mailing list