Skip to content

Commit 620ee82

Browse files
Matthew NagygbMattN
Matthew Nagy
authored andcommitted
[TySan] Fixed false positive when accessing global object's member variables
1 parent 8e6e62d commit 620ee82

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

compiler-rt/lib/tysan/tysan.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,24 @@ __tysan_check(void *addr, int size, tysan_type_descriptor *td, int flags) {
226226
OldTDPtr -= i;
227227
OldTD = *OldTDPtr;
228228

229-
if (!isAliasingLegal(td, OldTD, i))
229+
// When shadow memory is set for global objects, the entire object is tagged with the struct type
230+
// This means that when you access a member variable, tysan reads that as you accessing a struct midway
231+
// through, with 'i' being the offset
232+
// Therefore, if you are accessing a struct, we need to find the member type. We can go through the
233+
// members of the struct type and see if there is a member at the offset you are accessing the struct by.
234+
// If there is indeed a member starting at offset 'i' in the struct, we should check aliasing legality
235+
// with that type. If there isn't, we run alias checking on the struct with will give us the correct error.
236+
tysan_type_descriptor *InternalMember = OldTD;
237+
if (OldTD->Tag == TYSAN_STRUCT_TD) {
238+
for (int j = 0; j < OldTD->Struct.MemberCount; j++) {
239+
if (OldTD->Struct.Members[j].Offset == i) {
240+
InternalMember = OldTD->Struct.Members[j].Type;
241+
break;
242+
}
243+
}
244+
}
245+
246+
if (!isAliasingLegal(td, InternalMember, i))
230247
reportError(addr, size, td, OldTD, AccessStr,
231248
"accesses part of an existing object", -i, pc, bp, sp);
232249

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1
2+
// RUN: FileCheck %s < %t.out
3+
4+
#include <stdio.h>
5+
6+
struct X {
7+
int a, b, c;
8+
} x;
9+
10+
static struct X xArray[2];
11+
12+
int main() {
13+
x.a = 1;
14+
x.b = 2;
15+
x.c = 3;
16+
17+
printf("%d %d %d\n", x.a, x.b, x.c);
18+
// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation
19+
20+
for (size_t i = 0; i < 2; i++) {
21+
xArray[i].a = 1;
22+
xArray[i].b = 1;
23+
xArray[i].c = 1;
24+
}
25+
26+
struct X *xPtr = (struct X *)&(xArray[0].c);
27+
xPtr->a = 1;
28+
// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
29+
// CHECK: WRITE of size 4 at {{.*}} with type int (in X at offset 0) accesses an existing object of type int (in X at offset 8)
30+
// CHECK: {{#0 0x.* in main .*struct-members.c:}}[[@LINE-3]]
31+
}

0 commit comments

Comments
 (0)