Skip to content
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