1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Make sure that leak-check's pointer tracing avoids traps, i.e. tricky 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown memory areas where it could crash if not careful. 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h> 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "memcheck/memcheck.h" 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "tests/sys_mman.h" 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdlib.h> 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <fcntl.h> 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <unistd.h> 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if !defined(MAP_NORESERVE) 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define MAP_NORESERVE 0 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main() 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char **volatile ptrs; 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int i; 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int fd; 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char *map; 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* I _think_ the point of this is to fill ptrs with a pointer 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to every 4th page in the entire address space, hence 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown guaranteeing that at least one of them points into one of 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the below traps, and so checks that the leak checker 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown doesn't bomb when following them. That's fine on 32-bit 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown platforms, but hopeless for a 64-bit system. So the 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown following settings do achieve that on a 32-bit target but 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown merely make a 64-bit target give the same output without 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown properly testing it. */ 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ptrbits, stepbits, stepsize, nptrs; 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sizeof(void*) == 8) { 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 64-bit machine */ 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ptrbits = 32; //bogus 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stepbits = 14+1; //bogus 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stepsize = (1 << stepbits); 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nptrs = 1 << (ptrbits - stepbits); 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 32-bit machine */ 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ptrbits = 32; 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stepbits = 14; 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stepsize = (1 << stepbits); 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nptrs = 1 << (ptrbits - stepbits); 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ptrs = malloc(nptrs * sizeof(char *)); 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < nptrs; i++) 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ptrs[i] = (char *)((long)i << stepbits); 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* lay some traps */ 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* non-RWX memory, and MAP_NORESERVE if present */ 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown map = mmap(0, stepsize * 2, PROT_NONE, MAP_PRIVATE|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0); 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (map == (char *)-1) 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown perror("trap 1 failed"); 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* write-only memory, and MAP_NORESERVE if supported */ 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown map = mmap(0, stepsize * 2, PROT_WRITE, MAP_PRIVATE|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0); 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (map == (char *)-1) 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown perror("trap 2 failed"); 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* non-zero mmap of a zero-length file -> SIGBUS */ 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fd = open("./pointer-trace-test-file", O_RDWR | O_CREAT | O_EXCL, 0600); 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unlink("./pointer-trace-test-file"); 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown map = mmap(0, stepsize * 2, PROT_WRITE|PROT_READ, MAP_PRIVATE, fd, 0); 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (map == (char *)-1) 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown perror("trap 3 failed"); 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //printf("trap 3 = %p-%p\n", map, map+stepsize*2); 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* unmapped memory that's marked as defined */ 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown map = mmap(0, 256*1024, PROT_NONE, MAP_PRIVATE|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0); 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (map == (char *)-1) 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown perror("trap 4 failed"); 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown munmap(map, 256*1024); 77436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (void)VALGRIND_MAKE_MEM_DEFINED(map, 256*1024); /* great big fat lie */ 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_DO_LEAK_CHECK; 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown free(ptrs); 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // We deliberately make a leak, it'll be obvious if something went 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // wrong because the message won't be printed. 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ptrs = malloc(1000); 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 90