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
mm(char * addr,int size,int prot)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 */
test1()33 static void test1()
34 {
35 char *m = mm(0, pgsz * 5, PROT_READ);
36
37 VALGRIND_CHECK_MEM_IS_DEFINED(m, pgsz*5); /* all defined */
38 }
39
40 /* Case 2 - unmapped memory is unaddressable+undefined */
test2()41 static void test2()
42 {
43 char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE);
44 VALGRIND_CHECK_MEM_IS_DEFINED(m, pgsz*5); /* all OK */
45
46 munmap(&m[pgsz*2], pgsz);
47
48 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 */
test3()55 static void test3()
56 {
57 char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE);
58
59 VALGRIND_MAKE_MEM_UNDEFINED(&m[pgsz], pgsz);
60 mm(&m[pgsz], pgsz, PROT_READ);
61 VALGRIND_CHECK_MEM_IS_DEFINED(&m[pgsz], pgsz); /* OK */
62 }
63
64 /* Case 4 - mprotect doesn't affect addressability */
test4()65 static void test4()
66 {
67 char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE);
68
69 mprotect(m, pgsz, PROT_WRITE);
70 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 */
test5()78 static void test5()
79 {
80 char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE);
81
82 VALGRIND_MAKE_MEM_UNDEFINED(m, pgsz*5);
83 memset(m, 'x', 10);
84 VALGRIND_CHECK_MEM_IS_DEFINED(m, 10); /* OK */
85 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 VALGRIND_CHECK_MEM_IS_DEFINED(m, 10); /* still OK */
91 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
main()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