Home | History | Annotate | Download | only in tests
      1 /*
      2    Make sure that leak-check's pointer tracing avoids traps, i.e. tricky
      3    memory areas where it could crash if not careful.
      4  */
      5 
      6 #include <stdio.h>
      7 #include "memcheck/memcheck.h"
      8 #include "tests/sys_mman.h"
      9 #include <stdlib.h>
     10 #include <fcntl.h>
     11 #include <unistd.h>
     12 
     13 #if !defined(MAP_NORESERVE)
     14 #  define MAP_NORESERVE 0
     15 #endif
     16 
     17 int main()
     18 {
     19 	char **volatile ptrs;
     20 	int i;
     21 	int fd;
     22 	char *map;
     23 
     24 	/* I _think_ the point of this is to fill ptrs with a pointer
     25 	   to every 4th page in the entire address space, hence
     26 	   guaranteeing that at least one of them points into one of
     27 	   the below traps, and so checks that the leak checker
     28 	   doesn't bomb when following them.  That's fine on 32-bit
     29 	   platforms, but hopeless for a 64-bit system.  So the
     30 	   following settings do achieve that on a 32-bit target but
     31 	   merely make a 64-bit target give the same output without
     32 	   properly testing it. */
     33         int ptrbits, stepbits, stepsize, nptrs;
     34 	if (sizeof(void*) == 8) {
     35            /* 64-bit machine */
     36 	   ptrbits = 32;   //bogus
     37            stepbits = 14+1;  //bogus
     38 	   stepsize = (1 << stepbits);
     39 	   nptrs = 1 << (ptrbits - stepbits);
     40 	} else {
     41            /* 32-bit machine */
     42 	   ptrbits = 32;
     43            stepbits = 14;
     44 	   stepsize = (1 << stepbits);
     45 	   nptrs = 1 << (ptrbits - stepbits);
     46 	}
     47 
     48 	ptrs = malloc(nptrs * sizeof(char *));
     49 	for (i = 0; i < nptrs; i++)
     50 		ptrs[i] = (char *)((long)i << stepbits);
     51 
     52 	/* lay some traps */
     53         /* non-RWX memory, and MAP_NORESERVE if present */
     54 	map = mmap(0, stepsize * 2, PROT_NONE, MAP_PRIVATE|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0);
     55 	if (map == (char *)-1)
     56 		perror("trap 1 failed");
     57 
     58         /* write-only memory, and MAP_NORESERVE if supported */
     59 	map = mmap(0, stepsize * 2, PROT_WRITE, MAP_PRIVATE|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0);
     60 	if (map == (char *)-1)
     61 		perror("trap 2 failed");
     62 
     63 	/* non-zero mmap of a zero-length file -> SIGBUS */
     64 	fd = open("./pointer-trace-test-file", O_RDWR | O_CREAT | O_EXCL, 0600);
     65 	unlink("./pointer-trace-test-file");
     66 	map = mmap(0, stepsize * 2, PROT_WRITE|PROT_READ, MAP_PRIVATE, fd, 0);
     67 	if (map == (char *)-1)
     68 		perror("trap 3 failed");
     69 	//printf("trap 3 = %p-%p\n", map, map+stepsize*2);
     70 
     71         /* unmapped memory that's marked as defined */
     72 	map = mmap(0, 256*1024, PROT_NONE, MAP_PRIVATE|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0);
     73 	if (map == (char *)-1)
     74 		perror("trap 4 failed");
     75 	else {
     76 		munmap(map, 256*1024);
     77 		(void)VALGRIND_MAKE_MEM_DEFINED(map, 256*1024); /* great big fat lie */
     78 	}
     79 
     80 	VALGRIND_DO_LEAK_CHECK;
     81 
     82 	free(ptrs);
     83 
     84         // We deliberately make a leak, it'll be obvious if something went
     85         // wrong because the message won't be printed.
     86         ptrs = malloc(1000);
     87 
     88 	return 0;
     89 }
     90