Skip to content

[asan] Add test case for alignment of FakeStack frames #152889

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Aug 11, 2025
68 changes: 68 additions & 0 deletions compiler-rt/test/asan/TestCases/fakestack_alignment.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Regression test 1:
// This deterministically fails: when the stack size is 1<<16, FakeStack's
// GetFrame() is out of alignment, because SizeRequiredForFlags(16) == 2K.
// 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

// Regression test 2:
// The FakeStack frame is not guaranteed to be aligned, but alignment can
// happen by chance, so try this on many threads.
// 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
// 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

// Extra tests:
// RUN: %clangxx_asan -fsanitize-address-use-after-return=always -O0 -DALIGNMENT=4096 -DTHREAD_COUNT=32 -DTHREAD_STACK_SIZE=65536 %s -o %t && %run %t 2>&1
// RUN: %clangxx_asan -fsanitize-address-use-after-return=always -O0 -DALIGNMENT=8192 -DTHREAD_COUNT=32 -DTHREAD_STACK_SIZE=65536 %s -o %t && %run %t 2>&1
// RUN: %clangxx_asan -fsanitize-address-use-after-return=always -O0 -DALIGNMENT=16384 -DTHREAD_COUNT=32 -DTHREAD_STACK_SIZE=65536 %s -o %t && %run %t 2>&1
// RUN: %clangxx_asan -fsanitize-address-use-after-return=always -O0 -DALIGNMENT=4096 -DTHREAD_COUNT=32 -DTHREAD_STACK_SIZE=131072 %s -o %t && %run %t 2>&1
// 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
// 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

// XFAIL: *

#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct alignas(ALIGNMENT) big_object {
int x;
};

bool misaligned = false;

// Check whether the FakeStack frame is sufficiently aligned. Alignment can
// happen by chance, so try this on many threads.
void *Thread(void *unused) {
big_object x;
uint alignment = (unsigned long)&x % alignof(big_object);

if (alignment != 0)
misaligned = true;

return NULL;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is C++, use nullptr

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}

int main(int argc, char **argv) {
pthread_attr_t attr;
pthread_attr_init(&attr);
#ifdef THREAD_STACK_SIZE
pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE);
#endif

pthread_t t[THREAD_COUNT];
for (int i = 0; i < THREAD_COUNT; i++)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

optionally, if you think it's an improvement: we can use range based for loops for all of these.

for (phtread_t& t : threads) {
  pthread_create(&t, ...)

etc

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

pthread_create(&t[i], &attr, Thread, 0);

pthread_attr_destroy(&attr);

for (int i = 0; i < THREAD_COUNT; i++)
pthread_join(t[i], 0);

if (misaligned) {
printf("Test failed: not perfectly aligned\n");
exit(1);
}

return 0;
}
Loading