Skip to content

Commit 29ad073

Browse files
authored
Revert "[asan] Fix misalignment of variables in fake stack frames" (llvm#153139)
Reverts llvm#152819 due to buildbot failures
1 parent 927e19f commit 29ad073

File tree

4 files changed

+16
-61
lines changed

4 files changed

+16
-61
lines changed

compiler-rt/lib/asan/asan_fake_stack.cpp

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -54,34 +54,18 @@ FakeStack *FakeStack::Create(uptr stack_size_log) {
5454
stack_size_log = kMinStackSizeLog;
5555
if (stack_size_log > kMaxStackSizeLog)
5656
stack_size_log = kMaxStackSizeLog;
57-
CHECK_LE(kMaxStackFrameSizeLog, stack_size_log);
5857
uptr size = RequiredSize(stack_size_log);
59-
uptr padded_size = size + kMaxStackFrameSize;
60-
void *true_res = reinterpret_cast<void *>(
61-
flags()->uar_noreserve ? MmapNoReserveOrDie(padded_size, "FakeStack")
62-
: MmapOrDie(padded_size, "FakeStack"));
63-
// GetFrame() requires the property that
64-
// (res + kFlagsOffset + SizeRequiredForFlags(stack_size_log)) is aligned to
65-
// kMaxStackFrameSize.
66-
// We didn't use MmapAlignedOrDieOnFatalError, because it requires that the
67-
// *size* is a power of 2, which is an overly strong condition.
68-
static_assert(alignof(FakeStack) <= kMaxStackFrameSize);
6958
FakeStack *res = reinterpret_cast<FakeStack *>(
70-
RoundUpTo(
71-
(uptr)true_res + kFlagsOffset + SizeRequiredForFlags(stack_size_log),
72-
kMaxStackFrameSize) -
73-
kFlagsOffset - SizeRequiredForFlags(stack_size_log));
74-
res->true_start = true_res;
59+
flags()->uar_noreserve ? MmapNoReserveOrDie(size, "FakeStack")
60+
: MmapOrDie(size, "FakeStack"));
7561
res->stack_size_log_ = stack_size_log;
7662
u8 *p = reinterpret_cast<u8 *>(res);
7763
VReport(1,
7864
"T%d: FakeStack created: %p -- %p stack_size_log: %zd; "
79-
"mmapped %zdK, noreserve=%d, true_start: %p, start of first frame: "
80-
"0x%zx\n",
65+
"mmapped %zdK, noreserve=%d \n",
8166
GetCurrentTidOrInvalid(), (void *)p,
8267
(void *)(p + FakeStack::RequiredSize(stack_size_log)), stack_size_log,
83-
size >> 10, flags()->uar_noreserve, res->true_start,
84-
res->GetFrame(stack_size_log, /*class_id*/ 0, /*pos*/ 0));
68+
size >> 10, flags()->uar_noreserve);
8569
return res;
8670
}
8771

@@ -95,10 +79,8 @@ void FakeStack::Destroy(int tid) {
9579
Report("T%d: FakeStack destroyed: %s\n", tid, str.data());
9680
}
9781
uptr size = RequiredSize(stack_size_log_);
98-
uptr padded_size = size + kMaxStackFrameSize;
99-
FlushUnneededASanShadowMemory(reinterpret_cast<uptr>(true_start),
100-
padded_size);
101-
UnmapOrDie(true_start, padded_size);
82+
FlushUnneededASanShadowMemory(reinterpret_cast<uptr>(this), size);
83+
UnmapOrDie(this, size);
10284
}
10385

10486
void FakeStack::PoisonAll(u8 magic) {

compiler-rt/lib/asan/asan_fake_stack.h

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ struct FakeFrame {
3232
// is not popped but remains there for quite some time until gets used again.
3333
// So, we poison the objects on the fake stack when function returns.
3434
// It helps us find use-after-return bugs.
35+
//
3536
// The FakeStack objects is allocated by a single mmap call and has no other
3637
// pointers. The size of the fake stack depends on the actual thread stack size
3738
// and thus can not be a constant.
3839
// stack_size is a power of two greater or equal to the thread's stack size;
3940
// we store it as its logarithm (stack_size_log).
40-
// FakeStack is padded such that GetFrame() is aligned to BytesInSizeClass().
4141
// FakeStack has kNumberOfSizeClasses (11) size classes, each size class
4242
// is a power of two, starting from 64 bytes. Each size class occupies
4343
// stack_size bytes and thus can allocate
@@ -56,9 +56,6 @@ struct FakeFrame {
5656
class FakeStack {
5757
static const uptr kMinStackFrameSizeLog = 6; // Min frame is 64B.
5858
static const uptr kMaxStackFrameSizeLog = 16; // Max stack frame is 64K.
59-
static_assert(kMaxStackFrameSizeLog >= kMinStackFrameSizeLog);
60-
61-
static const u64 kMaxStackFrameSize = 1 << kMaxStackFrameSizeLog;
6259

6360
public:
6461
static const uptr kNumberOfSizeClasses =
@@ -69,7 +66,7 @@ class FakeStack {
6966

7067
void Destroy(int tid);
7168

72-
// min_uar_stack_size_log is 16 (stack_size >= 64KB)
69+
// stack_size_log is at least 15 (stack_size >= 32K).
7370
static uptr SizeRequiredForFlags(uptr stack_size_log) {
7471
return ((uptr)1) << (stack_size_log + 1 - kMinStackFrameSizeLog);
7572
}
@@ -113,28 +110,6 @@ class FakeStack {
113110
}
114111

115112
// Get frame by class_id and pos.
116-
// Return values are guaranteed to be aligned to BytesInSizeClass(class_id),
117-
// which is useful in combination with
118-
// ASanStackFrameLayout::ComputeASanStackFrameLayout().
119-
//
120-
// Note that alignment to 1<<kMaxStackFrameSizeLog (aka
121-
// BytesInSizeClass(max_class_id)) implies alignment to BytesInSizeClass()
122-
// for any class_id, since the class sizes are increasing powers of 2.
123-
//
124-
// 1) (this + kFlagsOffset + SizeRequiredForFlags())) is aligned to
125-
// 1<<kMaxStackFrameSizeLog (see FakeStack::Create)
126-
//
127-
// Note that SizeRequiredForFlags(16) == 2048. If FakeStack::Create() had
128-
// merely returned an address from mmap (4K-aligned), the addition would
129-
// not be 4K-aligned.
130-
// 2) We know that stack_size_log >= kMaxStackFrameSizeLog (otherwise you
131-
// couldn't store a single frame of that size in the entire stack)
132-
// hence (1<<stack_size_log) is aligned to 1<<kMaxStackFrameSizeLog
133-
// and ((1<<stack_size_log) * class_id) is aligned to
134-
// 1<<kMaxStackFrameSizeLog
135-
// 3) BytesInSizeClass(class_id) * pos is aligned to
136-
// BytesInSizeClass(class_id)
137-
// The sum of these is aligned to BytesInSizeClass(class_id).
138113
u8 *GetFrame(uptr stack_size_log, uptr class_id, uptr pos) {
139114
return reinterpret_cast<u8 *>(this) + kFlagsOffset +
140115
SizeRequiredForFlags(stack_size_log) +
@@ -181,18 +156,15 @@ class FakeStack {
181156

182157
private:
183158
FakeStack() { }
184-
static const uptr kFlagsOffset = 4096; // This is where the flags begin.
159+
static const uptr kFlagsOffset = 4096; // This is were the flags begin.
185160
// Must match the number of uses of DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID
186161
COMPILER_CHECK(kNumberOfSizeClasses == 11);
187162
static const uptr kMaxStackMallocSize = ((uptr)1) << kMaxStackFrameSizeLog;
188163

189164
uptr hint_position_[kNumberOfSizeClasses];
190165
uptr stack_size_log_;
166+
// a bit is set if something was allocated from the corresponding size class.
191167
bool needs_gc_;
192-
// We allocated more memory than needed to ensure the FakeStack (and, by
193-
// extension, each of the fake stack frames) is aligned. We keep track of the
194-
// true start so that we can unmap it.
195-
void *true_start;
196168
};
197169

198170
FakeStack *GetTLSFakeStack();

compiler-rt/lib/asan/tests/asan_fake_stack_test.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ TEST(FakeStack, Allocate) {
113113
uptr bytes_in_class = FakeStack::BytesInSizeClass(cid);
114114
for (uptr j = 0; j < n; j++) {
115115
FakeFrame *ff = fs->Allocate(stack_size_log, cid, 0);
116-
EXPECT_EQ(reinterpret_cast<uptr>(ff) % bytes_in_class, 0U);
117116
uptr x = reinterpret_cast<uptr>(ff);
118117
EXPECT_TRUE(s.insert(std::make_pair(ff, cid)).second);
119118
EXPECT_EQ(x, fs->AddrIsInFakeStack(x));

compiler-rt/test/asan/TestCases/fakestack_alignment.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
// Regression test 1:
2-
// When the stack size is 1<<16, SizeRequiredForFlags(16) == 2KB. This forces
3-
// FakeStack's GetFrame() out of alignment if the FakeStack isn't padded.
2+
// This deterministically fails: when the stack size is 1<<16, FakeStack's
3+
// GetFrame() is out of alignment, because SizeRequiredForFlags(16) == 2K.
44
// RUN: %clangxx_asan -fsanitize-address-use-after-return=always -O0 -DALIGNMENT=4096 -DTHREAD_COUNT=1 -DTHREAD_STACK_SIZE=65536 %s -o %t && %run %t 2>&1
55

66
// Regression test 2:
7-
// Check that the FakeStack frame is aligned, beyond the typical 4KB page
8-
// alignment. Alignment can happen by chance, so try this on many threads.
7+
// The FakeStack frame is not guaranteed to be aligned, but alignment can
8+
// happen by chance, so try this on many threads.
99
// RUN: %clangxx_asan -fsanitize-address-use-after-return=always -O0 -DALIGNMENT=8192 -DTHREAD_COUNT=32 -DTHREAD_STACK_SIZE=131072 %s -o %t && %run %t 2>&1
1010
// RUN: %clangxx_asan -fsanitize-address-use-after-return=always -O0 -DALIGNMENT=16384 -DTHREAD_COUNT=32 -DTHREAD_STACK_SIZE=131072 %s -o %t && %run %t 2>&1
1111

@@ -17,6 +17,8 @@
1717
// RUN: %clangxx_asan -fsanitize-address-use-after-return=always -O0 -DALIGNMENT=8192 -DTHREAD_COUNT=32 -DTHREAD_STACK_SIZE=131072 %s -o %t && %run %t 2>&1
1818
// RUN: %clangxx_asan -fsanitize-address-use-after-return=always -O0 -DALIGNMENT=16384 -DTHREAD_COUNT=32 -DTHREAD_STACK_SIZE=131072 %s -o %t && %run %t 2>&1
1919

20+
// XFAIL: *
21+
2022
#include <assert.h>
2123
#include <pthread.h>
2224
#include <stdio.h>

0 commit comments

Comments
 (0)