Skip to content

Commit 0a94da3

Browse files
committed
[TySan] Fix false positives with derrived classes
1 parent 025541d commit 0a94da3

File tree

3 files changed

+92
-18
lines changed

3 files changed

+92
-18
lines changed

compiler-rt/lib/tysan/tysan.cpp

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -102,20 +102,10 @@ static tysan_type_descriptor *getRootTD(tysan_type_descriptor *TD) {
102102
return RootTD;
103103
}
104104

105-
static bool isAliasingLegalUp(tysan_type_descriptor *TDA,
106-
tysan_type_descriptor *TDB, int TDAOffset) {
107-
// Walk up the tree starting with TDA to see if we reach TDB.
108-
uptr OffsetA = 0, OffsetB = 0;
109-
if (TDB->Tag == TYSAN_MEMBER_TD) {
110-
OffsetB = TDB->Member.Offset;
111-
TDB = TDB->Member.Base;
112-
}
113-
114-
if (TDA->Tag == TYSAN_MEMBER_TD) {
115-
OffsetA = TDA->Member.Offset - TDAOffset;
116-
TDA = TDA->Member.Base;
117-
}
118-
105+
bool walkAliasTree(
106+
tysan_type_descriptor* TDA, tysan_type_descriptor* TDB,
107+
uptr OffsetA, uptr OffsetB
108+
){
119109
do {
120110
if (TDA == TDB)
121111
return OffsetA == OffsetB;
@@ -153,8 +143,43 @@ static bool isAliasingLegalUp(tysan_type_descriptor *TDA,
153143
return false;
154144
}
155145

146+
static bool isAliasingLegalUp(tysan_type_descriptor *TDA,
147+
tysan_type_descriptor *TDB) {
148+
// Walk up the tree starting with TDA to see if we reach TDB.
149+
uptr OffsetA = 0, OffsetB = 0;
150+
if (TDB->Tag == TYSAN_MEMBER_TD) {
151+
OffsetB = TDB->Member.Offset;
152+
TDB = TDB->Member.Base;
153+
}
154+
155+
if (TDA->Tag == TYSAN_MEMBER_TD) {
156+
OffsetA = TDA->Member.Offset;
157+
TDA = TDA->Member.Base;
158+
}
159+
160+
return walkAliasTree(TDA, TDB, OffsetA, OffsetB);
161+
}
162+
163+
static bool isAliasingLegalWithOffset(tysan_type_descriptor *AccessTD, tysan_type_descriptor *ShadowTD, int OffsetInShadow){
164+
// This is handled in the other cases
165+
if(OffsetInShadow == 0)
166+
return false;
167+
168+
// You can't have an offset into a member
169+
if(ShadowTD->Tag == TYSAN_MEMBER_TD)
170+
return false;
171+
172+
int OffsetInAccess = 0;
173+
if(AccessTD->Tag == TYSAN_MEMBER_TD){
174+
OffsetInAccess = AccessTD->Member.Offset;
175+
AccessTD = AccessTD->Member.Base;
176+
}
177+
178+
return walkAliasTree(ShadowTD, AccessTD, OffsetInShadow, OffsetInAccess);
179+
}
180+
156181
static bool isAliasingLegal(tysan_type_descriptor *TDA,
157-
tysan_type_descriptor *TDB, int TDAOffset = 0) {
182+
tysan_type_descriptor *TDB) {
158183
if (TDA == TDB || !TDB || !TDA)
159184
return true;
160185

@@ -165,8 +190,7 @@ static bool isAliasingLegal(tysan_type_descriptor *TDA,
165190
// TDB may have been adjusted by offset TDAOffset in the caller to point to
166191
// the outer type. Check for aliasing with and without adjusting for this
167192
// offset.
168-
return isAliasingLegalUp(TDA, TDB, 0) || isAliasingLegalUp(TDB, TDA, 0) ||
169-
isAliasingLegalUp(TDA, TDB, TDAOffset);
193+
return isAliasingLegalUp(TDA, TDB) || isAliasingLegalUp(TDB, TDA);
170194
}
171195

172196
namespace __tysan {
@@ -243,7 +267,7 @@ __tysan_check(void *addr, int size, tysan_type_descriptor *td, int flags) {
243267
OldTDPtr -= i;
244268
OldTD = *OldTDPtr;
245269

246-
if (!isAliasingLegal(td, OldTD, i))
270+
if (!isAliasingLegal(td, OldTD) && !isAliasingLegalWithOffset(td, OldTD, i))
247271
reportError(addr, size, td, OldTD, AccessStr,
248272
"accesses part of an existing object", -i, pc, bp, sp);
249273

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %clangxx_tysan %s -o %t && %run %t 2>&1 | FileCheck --implicit-check-not ERROR %s
2+
3+
#include <stdio.h>
4+
5+
class Inner{
6+
public:
7+
void* ptr = nullptr;
8+
};
9+
10+
class Base{
11+
public:
12+
void* buffer1;
13+
Inner inside;
14+
void* buffer2;
15+
};
16+
17+
class Derrived : public Base{
18+
19+
};
20+
21+
Derrived derr;
22+
23+
int main(){
24+
printf("%p", derr.inside.ptr);
25+
26+
return 0;
27+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %clangxx_tysan %s -o %t && %run %t 2>&1 | FileCheck --implicit-check-not ERROR %s
2+
3+
#include <stdio.h>
4+
5+
class Base{
6+
public:
7+
void* first;
8+
void* second;
9+
void* third;
10+
};
11+
12+
class Derrived : public Base{
13+
14+
};
15+
16+
Derrived derr;
17+
18+
int main(){
19+
derr.second = nullptr;
20+
printf("%p", derr.second);
21+
22+
return 0;
23+
}

0 commit comments

Comments
 (0)