diff options
Diffstat (limited to 'test/scudo/secondary.c')
-rw-r--r-- | test/scudo/secondary.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/test/scudo/secondary.c b/test/scudo/secondary.c new file mode 100644 index 000000000..b770ca076 --- /dev/null +++ b/test/scudo/secondary.c @@ -0,0 +1,53 @@ +// RUN: %clang_scudo %s -o %t +// RUN: %run %t after 2>&1 | FileCheck %s +// RUN: %run %t before 2>&1 | FileCheck %s + +// Test that we hit a guard page when writing past the end of a chunk +// allocated by the Secondary allocator, or writing too far in front of it. + +#include <assert.h> +#include <malloc.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +void handler(int signo, siginfo_t *info, void *uctx) { + if (info->si_code == SEGV_ACCERR) { + fprintf(stderr, "SCUDO SIGSEGV\n"); + exit(0); + } + exit(1); +} + +int main(int argc, char **argv) +{ + // The size must be large enough to be serviced by the secondary allocator. + long page_size = sysconf(_SC_PAGESIZE); + size_t size = (1U << 17) + page_size; + struct sigaction a; + + assert(argc == 2); + memset(&a, 0, sizeof(a)); + a.sa_sigaction = handler; + a.sa_flags = SA_SIGINFO; + + char *p = (char *)malloc(size); + assert(p); + memset(p, 'A', size); // This should not trigger anything. + // Set up the SIGSEGV handler now, as the rest should trigger an AV. + sigaction(SIGSEGV, &a, NULL); + if (!strcmp(argv[1], "after")) { + for (int i = 0; i < page_size; i++) + p[size + i] = 'A'; + } + if (!strcmp(argv[1], "before")) { + for (int i = 1; i < page_size; i++) + p[-i] = 'A'; + } + free(p); + + return 1; // A successful test means we shouldn't reach this. +} + +// CHECK: SCUDO SIGSEGV |