Skip to content

Commit 3e1cb0d

Browse files
committed
[CodeGen][MSan] Don't use offsets of zero-sized fields
Such fields will likely have offset zero making __sanitizer_dtor_callback poisoning wrong regions. E.g. it can poison base class member from derived class constructor. Differential Revision: https://reviews.llvm.org/D92727
1 parent c102c78 commit 3e1cb0d

File tree

2 files changed

+19
-8
lines changed

2 files changed

+19
-8
lines changed

clang/lib/CodeGen/CGClass.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1700,12 +1700,23 @@ namespace {
17001700
return FieldHasTrivialDestructorBody(Context, F);
17011701
};
17021702

1703+
auto IsZeroSize = [&](const FieldDecl *F) {
1704+
return F->isZeroSize(Context);
1705+
};
1706+
1707+
// Poison blocks of fields with trivial destructors making sure that block
1708+
// begin and end do not point to zero-sized fields. They don't have
1709+
// correct offsets so can't be used to calculate poisoning range.
17031710
for (auto It = Fields.begin(); It != Fields.end();) {
1704-
It = std::find_if(It, Fields.end(), IsTrivial);
1711+
It = std::find_if(It, Fields.end(), [&](const FieldDecl *F) {
1712+
return IsTrivial(F) && !IsZeroSize(F);
1713+
});
17051714
if (It == Fields.end())
17061715
break;
17071716
auto Start = It++;
1708-
It = std::find_if_not(It, Fields.end(), IsTrivial);
1717+
It = std::find_if(It, Fields.end(), [&](const FieldDecl *F) {
1718+
return !IsTrivial(F) && !IsZeroSize(F);
1719+
});
17091720

17101721
PoisonMembers(CGF, (*Start)->getFieldIndex(),
17111722
It == Fields.end() ? -1 : (*It)->getFieldIndex());

clang/test/CodeGenCXX/sanitize-dtor-zero-size-field.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// RUN: %clang_cc1 -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"
22
// RUN: %clang_cc1 -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"
33

4-
// This test convers invalid behaviour which will be fixed in followup patches.
5-
64
struct Empty {};
75

86
struct EmptyNonTrivial {
@@ -115,7 +113,7 @@ struct Struct {
115113
static_assert(sizeof(Struct) == 24);
116114
} // namespace T6
117115
// CHECK-LABEL: define {{.*}} @_ZN5empty2T66StructD2Ev(
118-
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 21)
116+
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 13)
119117
// CHECK-NEXT: ret void
120118

121119
namespace T7 {
@@ -130,7 +128,7 @@ static_assert(sizeof(Struct) == 24);
130128
} // namespace T7
131129
// CHECK-LABEL: define {{.*}} @_ZN5empty2T76StructD2Ev(
132130
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
133-
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 21)
131+
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 5)
134132
// CHECK-NEXT: ret void
135133

136134
namespace T8 {
@@ -160,7 +158,7 @@ static_assert(sizeof(Struct) == 24);
160158
} // namespace T9
161159
// CHECK-LABEL: define {{.*}} @_ZN5empty2T96StructD2Ev(
162160
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
163-
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 21)
161+
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 1)
164162
// CHECK-NEXT: ret void
165163

166164
namespace T10 {
@@ -190,7 +188,6 @@ static_assert(sizeof(Struct) == 24);
190188
} // namespace T11
191189
// CHECK-LABEL: define {{.*}} @_ZN5empty3T116StructD2Ev(
192190
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 16)
193-
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 24)
194191
// CHECK-NEXT: ret void
195192

196193
namespace T12 {
@@ -317,6 +314,7 @@ struct Struct {
317314
static_assert(sizeof(Struct) == 24);
318315
} // namespace T8
319316
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T86StructD2Ev(
317+
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
320318
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 5)
321319
// CHECK-NEXT: ret void
322320

@@ -346,6 +344,7 @@ struct Struct {
346344
static_assert(sizeof(Struct) == 24);
347345
} // namespace T10
348346
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial3T106StructD2Ev(
347+
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
349348
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 1)
350349
// CHECK-NEXT: ret void
351350

@@ -375,4 +374,5 @@ static_assert(sizeof(Struct) == 24);
375374
} // namespace T12
376375
} // namespace empty_non_trivial
377376
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial3T126StructD2Ev(
377+
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 16)
378378
// CHECK: ret void

0 commit comments

Comments
 (0)