blob: 5f3c2e182ef0e47b4e821d884f16141005d85b9a [file] [log] [blame]
sewardjcbdddcf2005-03-10 23:23:45 +00001/* Test different kinds of addressability and definedness */
2#include "../memcheck.h"
njn83b62cb2009-04-15 03:12:43 +00003#include "tests/sys_mman.h"
sewardjcbdddcf2005-03-10 23:23:45 +00004#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
florian06bc7222013-10-01 22:38:43 +000037 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m, pgsz*5); /* all defined */
sewardjcbdddcf2005-03-10 23:23:45 +000038}
39
40/* Case 2 - unmapped memory is unaddressable+undefined */
41static void test2()
42{
43 char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE);
florian06bc7222013-10-01 22:38:43 +000044 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m, pgsz*5); /* all OK */
sewardjcbdddcf2005-03-10 23:23:45 +000045
46 munmap(&m[pgsz*2], pgsz);
47
florian06bc7222013-10-01 22:38:43 +000048 (void) VALGRIND_CHECK_MEM_IS_DEFINED(&m[pgsz*2], pgsz); /* undefined */
sewardjcbdddcf2005-03-10 23:23:45 +000049
njn1d0825f2006-03-27 11:37:07 +000050 /* XXX need a memcheck request to test addressability */
sewardjcbdddcf2005-03-10 23:23:45 +000051 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
florian06bc7222013-10-01 22:38:43 +000059 (void) VALGRIND_MAKE_MEM_UNDEFINED(&m[pgsz], pgsz);
sewardjcbdddcf2005-03-10 23:23:45 +000060 mm(&m[pgsz], pgsz, PROT_READ);
florian06bc7222013-10-01 22:38:43 +000061 (void) VALGRIND_CHECK_MEM_IS_DEFINED(&m[pgsz], pgsz); /* OK */
sewardjcbdddcf2005-03-10 23:23:45 +000062}
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);
florian06bc7222013-10-01 22:38:43 +000070 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m, pgsz); /* OK */
sewardjcbdddcf2005-03-10 23:23:45 +000071 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
florian06bc7222013-10-01 22:38:43 +000082 (void) VALGRIND_MAKE_MEM_UNDEFINED(m, pgsz*5);
sewardjcbdddcf2005-03-10 23:23:45 +000083 memset(m, 'x', 10);
florian06bc7222013-10-01 22:38:43 +000084 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m, 10); /* OK */
85 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m+10, 10); /* BAD */
sewardjcbdddcf2005-03-10 23:23:45 +000086
87 mprotect(m, pgsz*5, PROT_NONE);
88 mprotect(m, pgsz*5, PROT_READ);
89
florian06bc7222013-10-01 22:38:43 +000090 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m, 10); /* still OK */
91 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m+20, 10); /* BAD */
sewardjcbdddcf2005-03-10 23:23:45 +000092}
93
94static struct test {
95 void (*test)(void);
njn36fce1b2009-04-28 01:55:01 +000096 int faults;
sewardjcbdddcf2005-03-10 23:23:45 +000097} tests[] = {
98 { test1, 0 },
njn36fce1b2009-04-28 01:55:01 +000099 { test2, 1 },
sewardjcbdddcf2005-03-10 23:23:45 +0000100 { test3, 0 },
njn36fce1b2009-04-28 01:55:01 +0000101 { test4, 1 },
sewardjcbdddcf2005-03-10 23:23:45 +0000102 { 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
njn36fce1b2009-04-28 01:55:01 +0000143 if (1 == tests[i].faults &&
144 (WTERMSIG(status) == SIGSEGV ||
145 WTERMSIG(status) == SIGBUS))
sewardjcbdddcf2005-03-10 23:23:45 +0000146 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) {
njn36fce1b2009-04-28 01:55:01 +0000152 if (tests[i].faults == 0)
sewardjcbdddcf2005-03-10 23:23:45 +0000153 printf("PASS\n");
154 else
njn36fce1b2009-04-28 01:55:01 +0000155 printf("exited without expected SIGSEGV or SIGBUS signal\n");
sewardjcbdddcf2005-03-10 23:23:45 +0000156 } 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}