Skip to content

Commit 6682db9

Browse files
committed
[TySan] Fix struct access with different bases
1 parent 95eb49a commit 6682db9

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

compiler-rt/lib/tysan/tysan.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,17 @@ static bool isAliasingLegalUp(tysan_type_descriptor *TDA,
131131
break;
132132
}
133133

134+
// This offset can't be negative. Therefore we must be accessing something
135+
// before the current type (not legal) or partially inside the last type.
136+
// In the latter case, we adjust Idx.
137+
if (TDA->Struct.Members[Idx].Offset > OffsetA) {
138+
// Trying to access something before the current type.
139+
if (!Idx)
140+
return false;
141+
142+
Idx -= 1;
143+
}
144+
134145
OffsetA -= TDA->Struct.Members[Idx].Offset;
135146
TDA = TDA->Struct.Members[Idx].Type;
136147
} else {
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: %clangxx_tysan -O0 %s -o %t && %run %t >%t.out 2>&1
2+
// RUN: FileCheck %s --implicit-check-not ERROR < %t.out
3+
4+
// Modified reproducer from https://github.com/llvm/llvm-project/issues/105960
5+
6+
#include <stdio.h>
7+
8+
struct inner1 {
9+
char buffer;
10+
int i;
11+
};
12+
13+
struct inner2 {
14+
char buffer;
15+
int i;
16+
float endBuffer;
17+
};
18+
19+
void init_inner1(inner1 *iPtr) { iPtr->i = 200; }
20+
void init_inner2(inner2 *iPtr) {
21+
iPtr->i = 400;
22+
iPtr->endBuffer = 413.0f;
23+
}
24+
25+
struct outer {
26+
inner1 foo;
27+
inner2 bar;
28+
char buffer;
29+
};
30+
31+
int main(void) {
32+
outer *l = new outer();
33+
34+
init_inner1(&l->foo);
35+
init_inner2(&l->bar);
36+
37+
int access = l->foo.i;
38+
printf("Accessed value 1 is %d\n", access);
39+
access = l->bar.i;
40+
printf("Accessed value 2 is %d\n", access);
41+
float fAccess = l->bar.endBuffer;
42+
printf("Accessed value 3 is %f\n", fAccess);
43+
44+
return 0;
45+
}
46+
47+
// CHECK: Accessed value 1 is 200
48+
// CHECK: Accessed value 2 is 400
49+
// CHECK: Accessed value 3 is 413.0

0 commit comments

Comments
 (0)