Add 469782 to NEWS
[valgrind.git] / memcheck / tests / addressable.c
blob568fbb45ed66d133e600c566fcc9d8ba0da4c85a
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 #if defined(VGO_freebsd)
13 #include <signal.h>
14 #endif
16 static int pgsz;
18 static char *mm(char *addr, int size, int prot)
20 int flags = MAP_PRIVATE | MAP_ANONYMOUS;
21 char *ret;
23 if (addr)
24 flags |= MAP_FIXED;
26 ret = mmap(addr, size, prot, flags, -1, 0);
27 if (ret == (char *)-1) {
28 perror("mmap failed");
29 exit(1);
32 return ret;
35 /* Case 1 - mmaped memory is defined */
36 static void test1()
38 char *m = mm(0, pgsz * 5, PROT_READ);
40 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m, pgsz*5); /* all defined */
43 /* Case 2 - unmapped memory is unaddressable+undefined */
44 static void test2()
46 char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE);
47 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m, pgsz*5); /* all OK */
49 munmap(&m[pgsz*2], pgsz);
51 (void) VALGRIND_CHECK_MEM_IS_DEFINED(&m[pgsz*2], pgsz); /* undefined */
53 /* XXX need a memcheck request to test addressability */
54 m[pgsz*2] = 'x'; /* unmapped fault */
57 /* Case 3 - memory definedness doesn't survive remapping */
58 static void test3()
60 char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE);
62 (void) VALGRIND_MAKE_MEM_UNDEFINED(&m[pgsz], pgsz);
63 mm(&m[pgsz], pgsz, PROT_READ);
64 (void) VALGRIND_CHECK_MEM_IS_DEFINED(&m[pgsz], pgsz); /* OK */
67 /* Case 4 - mprotect doesn't affect addressability */
68 static void test4()
70 char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE);
72 mprotect(m, pgsz, PROT_WRITE);
73 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m, pgsz); /* OK */
74 m[44] = 'y'; /* OK */
76 mprotect(m, pgsz*5, PROT_NONE);
77 m[55] = 'x'; /* permission fault, but no tool complaint */
80 /* Case 5 - mprotect doesn't affect definedness */
81 static void test5()
83 char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE);
85 (void) VALGRIND_MAKE_MEM_UNDEFINED(m, pgsz*5);
86 memset(m, 'x', 10);
87 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m, 10); /* OK */
88 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m+10, 10); /* BAD */
90 mprotect(m, pgsz*5, PROT_NONE);
91 mprotect(m, pgsz*5, PROT_READ);
93 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m, 10); /* still OK */
94 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m+20, 10); /* BAD */
97 static struct test {
98 void (*test)(void);
99 int faults;
100 } tests[] = {
101 { test1, 0 },
102 { test2, 1 },
103 { test3, 0 },
104 { test4, 1 },
105 { test5, 0 },
107 static const int n_tests = sizeof(tests)/sizeof(*tests);
109 int main()
111 static const struct rlimit zero = { 0, 0 };
112 int i;
114 pgsz = getpagesize();
115 setvbuf(stdout, NULL, _IOLBF, 0);
117 setrlimit(RLIMIT_CORE, &zero);
119 for(i = 0; i < n_tests; i++) {
120 int pid;
122 pid = fork();
123 if (pid == -1) {
124 perror("fork");
125 exit(1);
127 if (pid == 0) {
128 (*tests[i].test)();
129 exit(0);
130 } else {
131 int status;
132 int ret;
134 printf("Test %d: ", i+1);
135 fflush(stdout);
137 while((ret = waitpid(pid, &status, 0)) != pid) {
138 if (errno != EINTR) {
139 perror("waitpid");
140 exit(1);
143 if (WIFSIGNALED(status)) {
144 assert(WTERMSIG(status) != 0);
146 if (1 == tests[i].faults &&
147 (WTERMSIG(status) == SIGSEGV ||
148 WTERMSIG(status) == SIGBUS))
149 printf("PASS\n");
150 else
151 printf("died with unexpected signal %d\n",
152 WTERMSIG(status));
153 } else if (WIFEXITED(status)) {
154 if (WEXITSTATUS(status) == 0) {
155 if (tests[i].faults == 0)
156 printf("PASS\n");
157 else
158 printf("exited without expected SIGSEGV or SIGBUS signal\n");
159 } else
160 printf("exited with unexpected status %d\n",
161 WEXITSTATUS(status));
162 } else {
163 printf("strange status %x?\n", status);
167 exit(0);