1 #include <unistd.h>
2 #include "tests/sys_mman.h"
3 #include <assert.h>
4 #include <stdlib.h>
5
6 #include "../memcheck.h"
7
8 #define SUPERBLOCK_SIZE 100000
9
10 //-------------------------------------------------------------------------
11 // Allocator
12 //-------------------------------------------------------------------------
13
get_superblock(void)14 void* get_superblock(void)
15 {
16 void* p = mmap( 0, SUPERBLOCK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC,
17 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0 );
18
19 assert(p != ((void*)(-1)));
20
21 // Mark it no access; although it's addressible we don't want the
22 // program to be using it unless its handed out by custom_alloc()
23
24 // with redzones, better not to have it
25 VALGRIND_MAKE_MEM_NOACCESS(p, SUPERBLOCK_SIZE);
26
27 return p;
28 }
29
30 // has a redzone
custom_alloc(int size)31 static void* custom_alloc(int size)
32 {
33 #define RZ 8
34 static void* hp = 0; // current heap pointer
35 static void* hp_lim = 0; // maximum usable byte in current block
36 int size2 = size + RZ*2;
37 void* p;
38
39 if (hp + size2 > hp_lim) {
40 hp = get_superblock();
41 hp_lim = hp + SUPERBLOCK_SIZE - 1;
42 }
43
44 p = hp + RZ;
45 hp += size2;
46
47 VALGRIND_MALLOCLIKE_BLOCK( p, size, RZ, /*is_zeroed*/1 );
48 return (void*)p;
49 }
50
custom_free(void * p)51 static void custom_free(void* p)
52 {
53 // don't actually free any memory... but mark it as freed
54 VALGRIND_FREELIKE_BLOCK( p, RZ );
55 }
56 #undef RZ
57
58
59
60 //-------------------------------------------------------------------------
61 // Rest
62 //-------------------------------------------------------------------------
63
make_leak(void)64 void make_leak(void)
65 {
66 int* array2 = custom_alloc(sizeof(int) * 10);
67 array2 = 0; // leak
68 return;
69 }
70
main(void)71 int main(void)
72 {
73 int *array, *array3;
74 int x;
75
76 array = custom_alloc(sizeof(int) * 10);
77 array[8] = 8;
78 array[9] = 8;
79 array[10] = 10; // invalid write (ok w/o MALLOCLIKE -- in superblock)
80
81 custom_free(array); // ok
82
83 custom_free((void*)0x1); // invalid free
84
85 array3 = malloc(sizeof(int) * 10);
86 custom_free(array3); // mismatched free (ok without MALLOCLIKE)
87
88 make_leak();
89 x = array[0]; // use after free (ok without MALLOCLIKE/MAKE_MEM_NOACCESS)
90 // (nb: initialised because is_zeroed==1 above)
91 // unfortunately not identified as being in a free'd
92 // block because the freeing of the block and shadow
93 // chunk isn't postponed.
94
95 // Bug 137073: passing 0 to MALLOCLIKE_BLOCK was causing an assertion
96 // failure. Test for this (and likewise for FREELIKE_BLOCK).
97 VALGRIND_MALLOCLIKE_BLOCK(0,0,0,0);
98 VALGRIND_FREELIKE_BLOCK(0,0);
99
100 return x;
101
102 // leak from make_leak()
103 }
104