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 13 static int pgsz; 14 15 static 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 */ 33 static 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 */ 41 static 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 */ 55 static 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 */ 65 static 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 */ 78 static 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 94 static 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 }; 104 static const int n_tests = sizeof(tests)/sizeof(*tests); 105 106 int 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