Home | History | Annotate | Download | only in tests
      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 	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 	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 */
     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 */
     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 */
     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 
    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