Skip to content

Commit ddf1de2

Browse files
authored
[hwasan] Fix rare false negative (zero tag) in stack-uar.c (#69374)
stack-uar.c is flaky (1 in 256 executions) because the random tag may be zero (#69221). This patch works around the issue in the same way as deep-recursion.c (aa4dfd3), by falling back to a neighboring object, which must have a different (non-zero) tag. This patch also does a minor cleanup of the aforementioned deep-recursion.c, for consistency with stack-uar.c. Co-authored-by: Thurston Dang <thurston@google.com>
1 parent 192d332 commit ddf1de2

File tree

2 files changed

+26
-9
lines changed

2 files changed

+26
-9
lines changed

compiler-rt/test/hwasan/TestCases/deep-recursion.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
// Stack histories are currently not recorded on x86.
1818
// XFAIL: target=x86_64{{.*}}
1919

20-
#include <stdint.h>
20+
#include <assert.h>
21+
#include <sanitizer/hwasan_interface.h>
2122
#include <stdlib.h>
2223

2324
// At least -O1 is needed for this function to not have a stack frame on
@@ -33,11 +34,12 @@ __attribute__((noinline)) void OOB() {
3334
int y[4];
3435

3536
// Tags for stack-allocated variables can occasionally be zero, resulting in
36-
// a false negative for this test. This is not easy to fix, hence we work
37-
// around it: if the tag is zero, we use the neighboring variable instead,
38-
// which must have a different (hence non-zero) tag.
39-
// This tag check assumes aarch64.
40-
if (((uintptr_t)&x) >> 56 == 0) {
37+
// a false negative for this test. The tag allocation algorithm is not easy
38+
// to fix, hence we work around it: if the tag is zero, we use the
39+
// neighboring variable instead, which must have a different (hence non-zero)
40+
// tag.
41+
if (__hwasan_tag_pointer(x, 0) == x) {
42+
assert(__hwasan_tag_pointer(y, 0) != y);
4143
y[four] = 0;
4244
} else {
4345
x[four] = 0;

compiler-rt/test/hwasan/TestCases/stack-uar.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,29 @@
99
// Stack histories currently are not recorded on x86.
1010
// XFAIL: target=x86_64{{.*}}
1111

12+
#include <assert.h>
13+
#include <sanitizer/hwasan_interface.h>
14+
1215
void USE(void *x) { // pretend_to_do_something(void *x)
1316
__asm__ __volatile__("" : : "r" (x) : "memory");
1417
}
1518

1619
__attribute__((noinline))
1720
char *buggy() {
18-
char zzz[0x1000];
19-
char *volatile p = zzz;
21+
char zzz[0x800];
22+
char yyy[0x800];
23+
// Tags for stack-allocated variables can occasionally be zero, resulting in
24+
// a false negative for this test. The tag allocation algorithm is not easy
25+
// to fix, hence we work around it: if the tag is zero, we use the
26+
// neighboring variable instead, which must have a different (hence non-zero)
27+
// tag.
28+
char *volatile p;
29+
if (__hwasan_tag_pointer(zzz, 0) == zzz) {
30+
assert(__hwasan_tag_pointer(yyy, 0) != yyy);
31+
p = yyy;
32+
} else {
33+
p = zzz;
34+
}
2035
return p;
2136
}
2237

@@ -35,7 +50,7 @@ int main() {
3550
// CHECK: Cause: stack tag-mismatch
3651
// CHECK: is located in stack of thread
3752
// CHECK: Potentially referenced stack objects:
38-
// CHECK-NEXT: zzz in buggy {{.*}}stack-uar.c:[[@LINE-20]]
53+
// CHECK-NEXT: {{zzz|yyy}} in buggy {{.*}}stack-uar.c:
3954
// CHECK-NEXT: Memory tags around the buggy address
4055

4156
// NOSYM: Previously allocated frames:

0 commit comments

Comments
 (0)