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 #define REDZONE_SIZE 8
10 
11 static const int USE_MMAP = 0;
12 
13 typedef struct _level_list
14 {
15    struct _level_list *next;
16    char *where;
17    // Padding ensures the struct is the same size on 32-bit and 64-bit
18    // machines.
19    char padding[16 - 2*sizeof(char*)];
20 } level_list;
21 
22 typedef struct _pool {
23    char *mem;
24    char *where;
25    level_list *levels;
26    int size, left;
27    // Padding ensures the struct is the same size on 32-bit and 64-bit
28    // machines.
29    char padding[24 - 3*sizeof(char*)];
30 } pool;
31 
make_pool()32 pool *make_pool()
33 {
34    pool *p;
35 
36    if(USE_MMAP) {
37       p = (pool *)mmap(0, sizeof(pool), PROT_READ|PROT_WRITE|PROT_EXEC,
38                        MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
39       p->where = p->mem = (char *)mmap(NULL, SUPERBLOCK_SIZE,
40                                        PROT_READ|PROT_WRITE|PROT_EXEC,
41                                        MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
42    } else {
43       p = (pool *)malloc(sizeof(pool));
44       p->where = p->mem = (char *)malloc(SUPERBLOCK_SIZE);
45    }
46 
47    p->size = p->left = SUPERBLOCK_SIZE;
48    p->levels = NULL;
49    (void) VALGRIND_MAKE_MEM_NOACCESS(p->where, SUPERBLOCK_SIZE);
50    return p;
51 }
52 
push(pool * p)53 void push(pool *p)
54 {
55    level_list *l;
56 
57    if(USE_MMAP)
58       l = (level_list *)mmap(0, sizeof(level_list),
59                              PROT_READ|PROT_WRITE|PROT_EXEC,
60                              MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
61    else
62       l = (level_list *)malloc(sizeof(level_list));
63 
64    l->next = p->levels;
65    l->where = p->where;
66    VALGRIND_CREATE_MEMPOOL(l->where, REDZONE_SIZE, 0);
67    p->levels = l;
68 }
69 
pop(pool * p)70 void pop(pool *p)
71 {
72    level_list *l = p->levels;
73    p->levels = l->next;
74    VALGRIND_DESTROY_MEMPOOL(l->where);
75    (void) VALGRIND_MAKE_MEM_NOACCESS(l->where, p->where-l->where);
76    p->where = l->where;
77    if(USE_MMAP)
78       munmap(l, sizeof(level_list));
79    else
80       free(l);
81 }
82 
destroy_pool(pool * p)83 void destroy_pool(pool *p)
84 {
85    level_list *l = p->levels;
86 
87    while(l) {
88       pop(p);
89    }
90    if(USE_MMAP) {
91       munmap(p->mem, SUPERBLOCK_SIZE);
92       munmap(p, sizeof(pool));
93    } else {
94       free(p->mem);
95       free(p);
96    }
97 }
98 
allocate(pool * p,int size)99 char *allocate(pool *p, int size)
100 {
101    char *where;
102    p->left -= size + (REDZONE_SIZE*2);
103    where = p->where + REDZONE_SIZE;
104    p->where += size + (REDZONE_SIZE*2);
105    VALGRIND_MEMPOOL_ALLOC(p->levels->where, where, size);
106    return where;
107 }
108 
109 //-------------------------------------------------------------------------
110 // Rest
111 //-------------------------------------------------------------------------
112 
test(void)113 void test(void)
114 {
115    char *x1, *x2, *x3, *x4, *x5;
116 
117    pool *p = make_pool();
118 
119    push(p);
120 
121    x1 = allocate(p, 10);
122    x2 = allocate(p, 20);
123    push(p);
124    x3 = allocate(p, 10);
125    x4 = allocate(p, 20);
126 
127    *x1 = 'a';  // valid
128    *x2 = 'b';  // valid
129 
130    x1[-1] = 'h'; // invalid
131    x1[10] = 'i'; // invalid
132 
133    pop(p);
134 
135    *x3 = 'c';  // invalid
136    *x4 = 'd';  // invalid
137 
138    *x1 = 'e';  // valid
139    *x2 = 'f';  // valid
140 
141    x5 = allocate(p, 10);
142 
143    *x5 = 'g';  // valid
144 
145    // pop(p);
146 
147    // *x5 = 'g';  // invalid
148 
149    // destroy_pool(p);
150 }
151 
main(void)152 int main(void)
153 {
154    test();
155    return 0;
156 }
157