tests/vg_regtest: Always evaluate prerequisite expressions with sh
[valgrind.git] / memcheck / tests / addressable.c
blob5f3c2e182ef0e47b4e821d884f16141005d85b9a
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>
13 static int pgsz;
15 static char *mm(char *addr, int size, int prot)
17 int flags = MAP_PRIVATE | MAP_ANONYMOUS;
18 char *ret;
20 if (addr)
21 flags |= MAP_FIXED;
23 ret = mmap(addr, size, prot, flags, -1, 0);
24 if (ret == (char *)-1) {
25 perror("mmap failed");
26 exit(1);
29 return ret;
32 /* Case 1 - mmaped memory is defined */
33 static void test1()
35 char *m = mm(0, pgsz * 5, PROT_READ);
37 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m, pgsz*5); /* all defined */
40 /* Case 2 - unmapped memory is unaddressable+undefined */
41 static void test2()
43 char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE);
44 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m, pgsz*5); /* all OK */
46 munmap(&m[pgsz*2], pgsz);
48 (void) VALGRIND_CHECK_MEM_IS_DEFINED(&m[pgsz*2], pgsz); /* undefined */
50 /* XXX need a memcheck request to test addressability */
51 m[pgsz*2] = 'x'; /* unmapped fault */
54 /* Case 3 - memory definedness doesn't survive remapping */
55 static void test3()
57 char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE);
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 */
64 /* Case 4 - mprotect doesn't affect addressability */
65 static void test4()
67 char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE);
69 mprotect(m, pgsz, PROT_WRITE);
70 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m, pgsz); /* OK */
71 m[44] = 'y'; /* OK */
73 mprotect(m, pgsz*5, PROT_NONE);
74 m[55] = 'x'; /* permission fault, but no tool complaint */
77 /* Case 5 - mprotect doesn't affect definedness */
78 static void test5()
80 char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE);
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 */
87 mprotect(m, pgsz*5, PROT_NONE);
88 mprotect(m, pgsz*5, PROT_READ);
90 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m, 10); /* still OK */
91 (void) VALGRIND_CHECK_MEM_IS_DEFINED(m+20, 10); /* BAD */
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 },
104 static const int n_tests = sizeof(tests)/sizeof(*tests);
106 int main()
108 static const struct rlimit zero = { 0, 0 };
109 int i;
111 pgsz = getpagesize();
112 setvbuf(stdout, NULL, _IOLBF, 0);
114 setrlimit(RLIMIT_CORE, &zero);
116 for(i = 0; i < n_tests; i++) {
117 int pid;
119 pid = fork();
120 if (pid == -1) {
121 perror("fork");
122 exit(1);
124 if (pid == 0) {
125 (*tests[i].test)();
126 exit(0);
127 } else {
128 int status;
129 int ret;
131 printf("Test %d: ", i+1);
132 fflush(stdout);
134 while((ret = waitpid(pid, &status, 0)) != pid) {
135 if (errno != EINTR) {
136 perror("waitpid");
137 exit(1);
140 if (WIFSIGNALED(status)) {
141 assert(WTERMSIG(status) != 0);
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);
164 exit(0);