Changeset View
Changeset View
Standalone View
Standalone View
test/scudo/secondary.c
// RUN: %clang_scudo %s -o %t | // RUN: %clang_scudo %s -o %t | ||||
// RUN: %run %t after 2>&1 | FileCheck %s | // RUN: %run %t after 2>&1 | FileCheck %s | ||||
// RUN: %run %t before 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 | // 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. | // allocated by the Secondary allocator, or writing too far in front of it. | ||||
#include <assert.h> | #include <assert.h> | ||||
#include <malloc.h> | |||||
#include <signal.h> | |||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <stdio.h> | |||||
#ifdef _WIN32 | |||||
# include <windows.h> | |||||
#else | |||||
# include <signal.h> | |||||
#include <unistd.h> | # include <unistd.h> | ||||
#endif | |||||
#ifdef _WIN32 | |||||
DWORD getpagesize() { | |||||
SYSTEM_INFO si; | |||||
GetSystemInfo(&si); | |||||
return si.dwPageSize; | |||||
} | |||||
LONG WINAPI handler(EXCEPTION_POINTERS *ExceptionInfo) | |||||
{ | |||||
fprintf(stderr, "AccessViolation\n"); | |||||
ExitProcess(0); | |||||
} | |||||
#else | |||||
void handler(int signo, siginfo_t *info, void *uctx) { | void handler(int signo, siginfo_t *info, void *uctx) { | ||||
if (info->si_code == SEGV_ACCERR) { | if (info->si_code == SEGV_ACCERR) { | ||||
fprintf(stderr, "SCUDO SIGSEGV\n"); | fprintf(stderr, "AccessViolation\n"); | ||||
exit(0); | exit(0); | ||||
} | } | ||||
exit(1); | exit(1); | ||||
} | } | ||||
long getpagesize() { | |||||
return sysconf(_SC_PAGESIZE); | |||||
} | |||||
#endif | |||||
int main(int argc, char **argv) | int main(int argc, char **argv) | ||||
{ | { | ||||
// The size must be large enough to be serviced by the secondary allocator. | // The size must be large enough to be serviced by the secondary allocator. | ||||
long page_size = sysconf(_SC_PAGESIZE); | long page_size = getpagesize(); | ||||
size_t size = (1U << 17) + page_size; | size_t size = (1U << 19) + page_size; | ||||
struct sigaction a; | |||||
assert(argc == 2); | assert(argc == 2); | ||||
memset(&a, 0, sizeof(a)); | |||||
#ifdef _WIN32 | |||||
SetUnhandledExceptionFilter(handler); | |||||
#else | |||||
struct sigaction a = {0}; | |||||
a.sa_sigaction = handler; | a.sa_sigaction = handler; | ||||
a.sa_flags = SA_SIGINFO; | a.sa_flags = SA_SIGINFO; | ||||
sigaction(SIGSEGV, &a, NULL); | |||||
#endif | |||||
char *p = (char *)malloc(size); | char *p = (char *)malloc(size); | ||||
assert(p); | assert(p); | ||||
memset(p, 'A', size); // This should not trigger anything. | memset(p, 'A', size); | ||||
// Set up the SIGSEGV handler now, as the rest should trigger an AV. | |||||
sigaction(SIGSEGV, &a, NULL); | |||||
if (!strcmp(argv[1], "after")) { | if (!strcmp(argv[1], "after")) { | ||||
for (int i = 0; i < page_size; i++) | for (int i = 0; i < page_size; i++) | ||||
p[size + i] = 'A'; | p[size + i] = 'A'; | ||||
} | } | ||||
if (!strcmp(argv[1], "before")) { | if (!strcmp(argv[1], "before")) { | ||||
for (int i = 1; i < page_size; i++) | for (int i = 1; i < page_size; i++) | ||||
p[-i] = 'A'; | p[-i] = 'A'; | ||||
} | } | ||||
free(p); | free(p); | ||||
return 1; // A successful test means we shouldn't reach this. | return 1; // A successful test means we shouldn't reach this. | ||||
} | } | ||||
// CHECK: SCUDO SIGSEGV | // CHECK: AccessViolation |