blob: 4c8683c2200d8649c5b6b0d9a92e82c8895da02e [file] [log] [blame]
sewardj12412a22011-01-23 20:47:26 +00001
2// Simplified version of mempool.c, that is more oriented towards
3// checking that the description of invalid addresses is correct.
4
5#include <stdio.h>
6#include <unistd.h>
7#include "tests/sys_mman.h"
8#include <assert.h>
9#include <stdlib.h>
10
11#include "../memcheck.h"
12
13#define SUPERBLOCK_SIZE 100000
14#define REDZONE_SIZE 8
15
16typedef struct _level_list
17{
18 struct _level_list *next;
19 char *where;
20 // Padding ensures the struct is the same size on 32-bit and 64-bit
21 // machines.
22 char padding[16 - 2*sizeof(char*)];
23} level_list;
24
25typedef struct _pool {
26 char *mem;
27 char *where;
28 level_list *levels;
29 int size, left;
30 // Padding ensures the struct is the same size on 32-bit and 64-bit
31 // machines.
32 char padding[24 - 3*sizeof(char*)];
33} pool;
34
35pool *make_pool( int use_mmap )
36{
37 pool *p;
38
39 if (use_mmap) {
40 p = (pool *)mmap(0, sizeof(pool), PROT_READ|PROT_WRITE|PROT_EXEC,
41 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
42 p->where = p->mem = (char *)mmap(NULL, SUPERBLOCK_SIZE,
43 PROT_READ|PROT_WRITE|PROT_EXEC,
44 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
45 } else {
46 p = (pool *)malloc(sizeof(pool));
47 p->where = p->mem = (char *)malloc(SUPERBLOCK_SIZE);
48 }
49
50 p->size = p->left = SUPERBLOCK_SIZE;
51 p->levels = NULL;
florian06bc7222013-10-01 22:38:43 +000052 (void) VALGRIND_MAKE_MEM_NOACCESS(p->where, SUPERBLOCK_SIZE);
sewardj12412a22011-01-23 20:47:26 +000053 return p;
54}
55
56void push(pool *p, int use_mmap )
57{
58 level_list *l;
59
60 if (use_mmap)
61 l = (level_list *)mmap(0, sizeof(level_list),
62 PROT_READ|PROT_WRITE|PROT_EXEC,
63 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
64 else
65 l = (level_list *)malloc(sizeof(level_list));
66
67 l->next = p->levels;
68 l->where = p->where;
69 VALGRIND_CREATE_MEMPOOL(l->where, REDZONE_SIZE, 0);
70 p->levels = l;
71}
72
73void pop(pool *p, int use_mmap)
74{
75 level_list *l = p->levels;
76 p->levels = l->next;
77 VALGRIND_DESTROY_MEMPOOL(l->where);
florian06bc7222013-10-01 22:38:43 +000078 (void) VALGRIND_MAKE_MEM_NOACCESS(l->where, p->where-l->where);
sewardj12412a22011-01-23 20:47:26 +000079 p->where = l->where;
80 if (use_mmap)
81 munmap(l, sizeof(level_list));
82 else
83 free(l);
84}
85
86void destroy_pool(pool *p, int use_mmap)
87{
88 level_list *l = p->levels;
89
90 while(l) {
91 pop(p, use_mmap);
92 }
93 if (use_mmap) {
94 munmap(p->mem, SUPERBLOCK_SIZE);
95 munmap(p, sizeof(pool));
96 } else {
97 free(p->mem);
98 free(p);
99 }
100}
101
102char *allocate(pool *p, int size)
103{
104 char *where;
105 p->left -= size + (REDZONE_SIZE*2);
106 where = p->where + REDZONE_SIZE;
107 p->where += size + (REDZONE_SIZE*2);
108 VALGRIND_MEMPOOL_ALLOC(p->levels->where, where, size);
109 return where;
110}
111
112//-------------------------------------------------------------------------
113// Rest
114//-------------------------------------------------------------------------
115
116void test(void)
117{
118 char *x1, *x2;
119 char res = 0;
120
121 // p1 is a malloc-backed pool
122 pool *p1 = make_pool(0);
123
124 // p2 is a mmap-backed pool
125 pool *p2 = make_pool(1);
126
127 push(p1, 0);
128 push(p2, 1);
129
130 x1 = allocate(p1, 10);
131 x2 = allocate(p2, 20);
132
133 fprintf(stderr,
134 "\n------ out of range reads in malloc-backed pool ------\n\n");
135 res += x1[-1];
136 res += x1[10];
137
138 fprintf(stderr,
139 "\n------ out of range reads in mmap-backed pool ------\n\n");
140 res += x2[-1]; // invalid
141 res += x2[20]; // invalid
142
143 fprintf(stderr,
Elliott Hughesed398002017-06-21 14:41:24 -0700144 "\n------ Illegal memory pool address ------\n\n");
145 VALGRIND_MEMPOOL_FREE(p1, x1); // Should be p1->mem
146
147 fprintf(stderr,
sewardj12412a22011-01-23 20:47:26 +0000148 "\n------ read free in malloc-backed pool ------\n\n");
Elliott Hughesed398002017-06-21 14:41:24 -0700149 VALGRIND_MEMPOOL_FREE(p1->mem, x1);
sewardj12412a22011-01-23 20:47:26 +0000150 res += x1[5];
151
152 fprintf(stderr,
153 "\n------ read free in mmap-backed pool ------\n\n");
Elliott Hughesed398002017-06-21 14:41:24 -0700154 VALGRIND_MEMPOOL_FREE(p2->mem, x2);
sewardj12412a22011-01-23 20:47:26 +0000155 res += x2[11];
156
157 fprintf(stderr,
158 "\n------ double free in malloc-backed pool ------\n\n");
Elliott Hughesed398002017-06-21 14:41:24 -0700159 VALGRIND_MEMPOOL_FREE(p1->mem, x1);
sewardj12412a22011-01-23 20:47:26 +0000160
161 fprintf(stderr,
162 "\n------ double free in mmap-backed pool ------\n\n");
Elliott Hughesed398002017-06-21 14:41:24 -0700163 VALGRIND_MEMPOOL_FREE(p2->mem, x2);
sewardj12412a22011-01-23 20:47:26 +0000164
philippee529b872012-07-05 21:11:12 +0000165 {
166 // test that redzone are still protected even if the user forgets
167 // to mark the superblock noaccess.
168 char superblock[100];
169
170 VALGRIND_CREATE_MEMPOOL(superblock, REDZONE_SIZE, 0);
171 // User should mark the superblock no access to benefit
172 // from full Valgrind memcheck protection.
173 // VALGRIND_MEMPOOL_ALLOC will however still ensure the
174 // redzones are protected.
175 VALGRIND_MEMPOOL_ALLOC(superblock, superblock+30, 10);
176
177 res += superblock[30]; // valid
178 res += superblock[39]; // valid
179
180 fprintf(stderr,
181 "\n------ 2 invalid access in 'no no-access superblock' ---\n\n");
182 res += superblock[29]; // invalid
183 res += superblock[40]; // invalid
184
185 VALGRIND_DESTROY_MEMPOOL(superblock);
186 }
sewardj12412a22011-01-23 20:47:26 +0000187 // claim res is used, so gcc can't nuke this all
188 __asm__ __volatile__("" : : "r"(res));
189
190 fprintf(stderr,
191 "\n------ done ------\n\n");
192 pop(p1, 0);
193 pop(p2, 1);
194 destroy_pool(p1, 0);
195 destroy_pool(p2, 1);
196}
197
198int main(void)
199{
200 test();
201 return 0;
202}