1/* Test different kinds of addressability and definedness */ 2#include "../memcheck.h" 3#include "tests/sys_mman.h" 4#include <stdio.h> 5#include <sys/resource.h> 6#include <unistd.h> 7#include <sys/wait.h> 8#include <assert.h> 9#include <errno.h> 10#include <string.h> 11#include <stdlib.h> 12 13static int pgsz; 14 15static char *mm(char *addr, int size, int prot) 16{ 17 int flags = MAP_PRIVATE | MAP_ANONYMOUS; 18 char *ret; 19 20 if (addr) 21 flags |= MAP_FIXED; 22 23 ret = mmap(addr, size, prot, flags, -1, 0); 24 if (ret == (char *)-1) { 25 perror("mmap failed"); 26 exit(1); 27 } 28 29 return ret; 30} 31 32/* Case 1 - mmaped memory is defined */ 33static void test1() 34{ 35 char *m = mm(0, pgsz * 5, PROT_READ); 36 37 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m, pgsz*5); /* all defined */ 38} 39 40/* Case 2 - unmapped memory is unaddressable+undefined */ 41static void test2() 42{ 43 char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE); 44 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m, pgsz*5); /* all OK */ 45 46 munmap(&m[pgsz*2], pgsz); 47 48 (void) VALGRIND_CHECK_MEM_IS_DEFINED(&m[pgsz*2], pgsz); /* undefined */ 49 50 /* XXX need a memcheck request to test addressability */ 51 m[pgsz*2] = 'x'; /* unmapped fault */ 52} 53 54/* Case 3 - memory definedness doesn't survive remapping */ 55static void test3() 56{ 57 char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE); 58 59 (void) VALGRIND_MAKE_MEM_UNDEFINED(&m[pgsz], pgsz); 60 mm(&m[pgsz], pgsz, PROT_READ); 61 (void) VALGRIND_CHECK_MEM_IS_DEFINED(&m[pgsz], pgsz); /* OK */ 62} 63 64/* Case 4 - mprotect doesn't affect addressability */ 65static void test4() 66{ 67 char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE); 68 69 mprotect(m, pgsz, PROT_WRITE); 70 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m, pgsz); /* OK */ 71 m[44] = 'y'; /* OK */ 72 73 mprotect(m, pgsz*5, PROT_NONE); 74 m[55] = 'x'; /* permission fault, but no tool complaint */ 75} 76 77/* Case 5 - mprotect doesn't affect definedness */ 78static void test5() 79{ 80 char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE); 81 82 (void) VALGRIND_MAKE_MEM_UNDEFINED(m, pgsz*5); 83 memset(m, 'x', 10); 84 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m, 10); /* OK */ 85 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m+10, 10); /* BAD */ 86 87 mprotect(m, pgsz*5, PROT_NONE); 88 mprotect(m, pgsz*5, PROT_READ); 89 90 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m, 10); /* still OK */ 91 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m+20, 10); /* BAD */ 92} 93 94static struct test { 95 void (*test)(void); 96 int faults; 97} tests[] = { 98 { test1, 0 }, 99 { test2, 1 }, 100 { test3, 0 }, 101 { test4, 1 }, 102 { test5, 0 }, 103}; 104static const int n_tests = sizeof(tests)/sizeof(*tests); 105 106int main() 107{ 108 static const struct rlimit zero = { 0, 0 }; 109 int i; 110 111 pgsz = getpagesize(); 112 setvbuf(stdout, NULL, _IOLBF, 0); 113 114 setrlimit(RLIMIT_CORE, &zero); 115 116 for(i = 0; i < n_tests; i++) { 117 int pid; 118 119 pid = fork(); 120 if (pid == -1) { 121 perror("fork"); 122 exit(1); 123 } 124 if (pid == 0) { 125 (*tests[i].test)(); 126 exit(0); 127 } else { 128 int status; 129 int ret; 130 131 printf("Test %d: ", i+1); 132 fflush(stdout); 133 134 while((ret = waitpid(pid, &status, 0)) != pid) { 135 if (errno != EINTR) { 136 perror("waitpid"); 137 exit(1); 138 } 139 } 140 if (WIFSIGNALED(status)) { 141 assert(WTERMSIG(status) != 0); 142 143 if (1 == tests[i].faults && 144 (WTERMSIG(status) == SIGSEGV || 145 WTERMSIG(status) == SIGBUS)) 146 printf("PASS\n"); 147 else 148 printf("died with unexpected signal %d\n", 149 WTERMSIG(status)); 150 } else if (WIFEXITED(status)) { 151 if (WEXITSTATUS(status) == 0) { 152 if (tests[i].faults == 0) 153 printf("PASS\n"); 154 else 155 printf("exited without expected SIGSEGV or SIGBUS signal\n"); 156 } else 157 printf("exited with unexpected status %d\n", 158 WEXITSTATUS(status)); 159 } else { 160 printf("strange status %x?\n", status); 161 } 162 } 163 } 164 exit(0); 165} 166