1 /* wmem_allocator_strict.c
2 * Wireshark Memory Manager Strict Allocator
3 * Copyright 2012, Evan Huus <eapache@gmail.com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32 #include "wmem_core.h"
33 #include "wmem_allocator.h"
35 /* In this allocator, we do everything we can to catch invalid memory accesses.
36 * This includes using canaries (what Valgrind calls redzones) and
37 * filling allocated and freed memory with garbage. Valgrind is still the
38 * better tool on the platforms where it is available - use it instead if
42 #define WMEM_CANARY_SIZE 4 /* in bytes */
43 #define WMEM_CANARY_VALUE 0x9E
45 #define WMEM_PREFILL 0xA1
46 #define WMEM_POSTFILL 0x1A
48 typedef struct _wmem_strict_allocator_block_t
{
49 /* Just the length of real_data, not counting the canaries */
52 guint8
*leading_canary
;
54 guint8
*trailing_canary
;
55 } wmem_strict_allocator_block_t
;
57 typedef struct _wmem_strict_allocator_t
{
58 GHashTable
*block_table
;
59 } wmem_strict_allocator_t
;
62 * some internal helper functions
65 wmem_strict_block_check_canaries(wmem_strict_allocator_block_t
*block
)
69 for (i
=0; i
<WMEM_CANARY_SIZE
; i
++) {
70 g_assert(block
->leading_canary
[i
] == WMEM_CANARY_VALUE
);
71 g_assert(block
->trailing_canary
[i
] == WMEM_CANARY_VALUE
);
75 /* wrapper for use with g_hash_table_foreach() */
77 wmem_strict_ghash_check_canaries(gpointer key _U_
, gpointer value
,
78 gpointer user_data _U_
)
80 wmem_strict_block_check_canaries((wmem_strict_allocator_block_t
*)value
);
84 wmem_strict_block_free(wmem_strict_allocator_block_t
*block
)
86 memset(block
->real_data
, WMEM_POSTFILL
, block
->data_len
);
88 wmem_free(NULL
, block
->leading_canary
);
89 wmem_free(NULL
, block
);
92 /* wrapper for use with g_hash_table_new_full() */
94 wmem_strict_ghash_block_free(gpointer data
)
96 wmem_strict_block_free((wmem_strict_allocator_block_t
*)data
);
99 static wmem_strict_allocator_block_t
*
100 wmem_strict_block_new(const size_t size
)
102 wmem_strict_allocator_block_t
*block
;
105 block
= wmem_new(NULL
, wmem_strict_allocator_block_t
);
107 block
->data_len
= size
;
108 block
->leading_canary
= (guint8
*)wmem_alloc(NULL
, block
->data_len
+ (2 * WMEM_CANARY_SIZE
));
109 block
->real_data
= block
->leading_canary
+ WMEM_CANARY_SIZE
;
110 block
->trailing_canary
= block
->real_data
+ block
->data_len
;
112 memset(block
->real_data
, WMEM_PREFILL
, block
->data_len
);
113 for (i
=0; i
<WMEM_CANARY_SIZE
; i
++) {
114 block
->leading_canary
[i
] = WMEM_CANARY_VALUE
;
115 block
->trailing_canary
[i
] = WMEM_CANARY_VALUE
;
122 * public API functions
125 wmem_strict_alloc(void *private_data
, const size_t size
)
127 wmem_strict_allocator_t
*allocator
;
128 wmem_strict_allocator_block_t
*block
;
130 allocator
= (wmem_strict_allocator_t
*) private_data
;
132 block
= wmem_strict_block_new(size
);
134 /* we store a pointer to our header, keyed by a pointer to the actual
135 * block we return to the user */
136 g_hash_table_insert(allocator
->block_table
, block
->real_data
, block
);
138 return block
->real_data
;
142 wmem_strict_free(void *private_data
, void *ptr
)
144 wmem_strict_allocator_t
*allocator
;
145 wmem_strict_allocator_block_t
*block
;
147 allocator
= (wmem_strict_allocator_t
*) private_data
;
149 block
= (wmem_strict_allocator_block_t
*)g_hash_table_lookup(allocator
->block_table
, ptr
);
153 wmem_strict_block_check_canaries(block
);
155 g_hash_table_remove(allocator
->block_table
, ptr
);
159 wmem_strict_realloc(void *private_data
, void *ptr
, const size_t size
)
162 wmem_strict_allocator_t
*allocator
;
163 wmem_strict_allocator_block_t
*block
, *newblock
;
165 allocator
= (wmem_strict_allocator_t
*) private_data
;
167 /* retrieve and check the old block */
168 block
= (wmem_strict_allocator_block_t
*)g_hash_table_lookup(allocator
->block_table
, ptr
);
170 wmem_strict_block_check_canaries(block
);
172 /* create a new block */
173 newblock
= wmem_strict_block_new(size
);
175 /* copy from the old block to the new */
176 if (block
->data_len
> newblock
->data_len
) {
177 copy_len
= newblock
->data_len
;
180 copy_len
= block
->data_len
;
183 memcpy(newblock
->real_data
, block
->real_data
, copy_len
);
185 /* update the hash table */
186 g_hash_table_remove(allocator
->block_table
, ptr
);
187 g_hash_table_insert(allocator
->block_table
, newblock
->real_data
, newblock
);
189 return newblock
->real_data
;
193 wmem_strict_check_canaries(wmem_allocator_t
*allocator
)
195 wmem_strict_allocator_t
*private_allocator
;
197 if (allocator
->type
!= WMEM_ALLOCATOR_STRICT
) {
201 private_allocator
= (wmem_strict_allocator_t
*) allocator
->private_data
;
203 g_hash_table_foreach(private_allocator
->block_table
,
204 &wmem_strict_ghash_check_canaries
, NULL
);
208 wmem_strict_free_all(void *private_data
)
210 wmem_strict_allocator_t
*allocator
;
212 allocator
= (wmem_strict_allocator_t
*) private_data
;
214 g_hash_table_foreach(allocator
->block_table
,
215 &wmem_strict_ghash_check_canaries
, NULL
);
217 g_hash_table_remove_all(allocator
->block_table
);
221 wmem_strict_gc(void *private_data _U_
)
223 /* We don't really have anything to garbage-collect, but it might be worth
224 * checking our canaries at this point? */
228 wmem_strict_allocator_cleanup(void *private_data
)
230 wmem_strict_allocator_t
*allocator
;
232 allocator
= (wmem_strict_allocator_t
*) private_data
;
234 g_hash_table_destroy(allocator
->block_table
);
235 wmem_free(NULL
, allocator
);
239 wmem_strict_allocator_init(wmem_allocator_t
*allocator
)
241 wmem_strict_allocator_t
*strict_allocator
;
243 strict_allocator
= wmem_new(NULL
, wmem_strict_allocator_t
);
245 allocator
->alloc
= &wmem_strict_alloc
;
246 allocator
->realloc
= &wmem_strict_realloc
;
247 allocator
->free
= &wmem_strict_free
;
249 allocator
->free_all
= &wmem_strict_free_all
;
250 allocator
->gc
= &wmem_strict_gc
;
251 allocator
->cleanup
= &wmem_strict_allocator_cleanup
;
253 allocator
->private_data
= (void*) strict_allocator
;
255 strict_allocator
->block_table
= g_hash_table_new_full(
256 &g_direct_hash
, &g_direct_equal
,
257 NULL
, &wmem_strict_ghash_block_free
);
261 * Editor modelines - http://www.wireshark.org/tools/modelines.html
266 * indent-tabs-mode: nil
269 * vi: set shiftwidth=4 tabstop=8 expandtab:
270 * :indentSize=4:tabSize=8:noTabs=true: