TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags
[wireshark-sm.git] / wsutil / wmem / wmem_allocator_strict.c
blob87ef01e2973dbf86491d74ddafca089e975ad280
1 /* wmem_allocator_strict.c
2 * Wireshark Memory Manager Strict Allocator
3 * Copyright 2012, Evan Huus <eapache@gmail.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #include <string.h>
16 #include <glib.h>
18 #include "wmem_core.h"
19 #include "wmem_allocator.h"
20 #include "wmem_allocator_strict.h"
22 /* In this allocator, we do everything we can to catch invalid memory accesses.
23 * This includes using canaries (what Valgrind calls redzones) and
24 * filling allocated and freed memory with garbage. Valgrind is still the
25 * better tool on the platforms where it is available - use it instead if
26 * possible.
29 #define WMEM_CANARY_SIZE 8 /* in bytes */
30 #define WMEM_CANARY_VALUE 0x9E
32 #define WMEM_PREFILL 0xA1
33 #define WMEM_POSTFILL 0x1A
35 typedef struct _wmem_strict_allocator_block_t {
36 struct _wmem_strict_allocator_block_t *prev, *next;
38 /* Just the length of real_data, not counting the canaries */
39 size_t data_len;
40 } wmem_strict_allocator_block_t;
42 #define WMEM_DATA_TO_BLOCK(DATA) ((wmem_strict_allocator_block_t*)((uint8_t*)(DATA) - WMEM_CANARY_SIZE - sizeof(wmem_strict_allocator_block_t)))
43 #define WMEM_BLOCK_TO_DATA(BLOCK) ((void*)((uint8_t*)(BLOCK) + WMEM_CANARY_SIZE + sizeof(wmem_strict_allocator_block_t)))
44 #define WMEM_BLOCK_TO_PRE_CANARY(BLOCK) ((uint8_t*)(BLOCK) + sizeof(wmem_strict_allocator_block_t))
45 #define WMEM_BLOCK_TO_POST_CANARY(BLOCK) ((uint8_t*)(BLOCK) + WMEM_CANARY_SIZE + sizeof(wmem_strict_allocator_block_t) + (BLOCK)->data_len)
46 #define WMEM_FULL_SIZE(SIZE) ((SIZE) + sizeof(wmem_strict_allocator_block_t) + (2*WMEM_CANARY_SIZE))
48 typedef struct _wmem_strict_allocator_t {
49 wmem_strict_allocator_block_t *blocks;
50 } wmem_strict_allocator_t;
53 * some internal helper functions
55 static inline void
56 wmem_strict_block_check_canaries(wmem_strict_allocator_block_t *block)
58 unsigned i;
59 uint8_t *canary;
61 canary = WMEM_BLOCK_TO_PRE_CANARY(block);
62 for (i=0; i<WMEM_CANARY_SIZE; i++) g_assert_true(canary[i] == WMEM_CANARY_VALUE);
64 canary = WMEM_BLOCK_TO_POST_CANARY(block);
65 for (i=0; i<WMEM_CANARY_SIZE; i++) g_assert_true(canary[i] == WMEM_CANARY_VALUE);
69 * public API functions
71 static void *
72 wmem_strict_alloc(void *private_data, const size_t size)
74 wmem_strict_allocator_t *allocator;
75 wmem_strict_allocator_block_t *block;
76 unsigned i;
77 uint8_t *canary;
79 allocator = (wmem_strict_allocator_t*) private_data;
81 block = (wmem_strict_allocator_block_t *)wmem_alloc(NULL, WMEM_FULL_SIZE(size));
82 block->data_len = size;
84 memset(WMEM_BLOCK_TO_DATA(block), WMEM_PREFILL, block->data_len);
86 canary = WMEM_BLOCK_TO_PRE_CANARY(block);
87 for (i=0; i<WMEM_CANARY_SIZE; i++) canary[i] = WMEM_CANARY_VALUE;
89 canary = WMEM_BLOCK_TO_POST_CANARY(block);
90 for (i=0; i<WMEM_CANARY_SIZE; i++) canary[i] = WMEM_CANARY_VALUE;
92 if (allocator->blocks) {
93 allocator->blocks->prev = block;
95 block->next = allocator->blocks;
96 block->prev = NULL;
97 allocator->blocks = block;
99 return WMEM_BLOCK_TO_DATA(block);
102 static void
103 wmem_strict_free(void *private_data, void *ptr)
105 wmem_strict_allocator_t *allocator;
106 wmem_strict_allocator_block_t *block;
108 allocator = (wmem_strict_allocator_t*) private_data;
110 block = WMEM_DATA_TO_BLOCK(ptr);
112 wmem_strict_block_check_canaries(block);
114 if (block->next) {
115 block->next->prev = block->prev;
118 if (block->prev) {
119 block->prev->next = block->next;
121 else {
122 allocator->blocks = block->next;
125 memset(block, WMEM_POSTFILL, WMEM_FULL_SIZE(block->data_len));
127 wmem_free(NULL, block);
130 static void *
131 wmem_strict_realloc(void *private_data, void *ptr, const size_t size)
133 wmem_strict_allocator_block_t *block;
134 void *new_ptr;
136 block = WMEM_DATA_TO_BLOCK(ptr);
138 /* create a new block */
139 new_ptr = wmem_strict_alloc(private_data, size);
141 /* copy from the old block to the new */
142 if (block->data_len > size) {
143 memcpy(new_ptr, ptr, size);
145 else {
146 memcpy(new_ptr, ptr, block->data_len);
149 /* free the old block */
150 wmem_strict_free(private_data, ptr);
152 return new_ptr;
155 void
156 wmem_strict_check_canaries(wmem_allocator_t *allocator)
158 wmem_strict_allocator_t *private_allocator;
159 wmem_strict_allocator_block_t *block;
161 if (allocator->type != WMEM_ALLOCATOR_STRICT) {
162 return;
165 private_allocator = (wmem_strict_allocator_t*) allocator->private_data;
167 block = private_allocator->blocks;
168 while (block) {
169 wmem_strict_block_check_canaries(block);
170 block = block->next;
174 static void
175 wmem_strict_free_all(void *private_data)
177 wmem_strict_allocator_t *allocator;
179 allocator = (wmem_strict_allocator_t*) private_data;
181 while (allocator->blocks) {
182 wmem_strict_free(private_data, WMEM_BLOCK_TO_DATA(allocator->blocks));
186 static void
187 wmem_strict_gc(void *private_data _U_)
189 /* We don't really have anything to garbage-collect, but it might be worth
190 * checking our canaries at this point? */
193 static void
194 wmem_strict_allocator_cleanup(void *private_data)
196 wmem_free(NULL, private_data);
199 void
200 wmem_strict_allocator_init(wmem_allocator_t *allocator)
202 wmem_strict_allocator_t *strict_allocator;
204 strict_allocator = wmem_new(NULL, wmem_strict_allocator_t);
206 allocator->walloc = &wmem_strict_alloc;
207 allocator->wrealloc = &wmem_strict_realloc;
208 allocator->wfree = &wmem_strict_free;
210 allocator->free_all = &wmem_strict_free_all;
211 allocator->gc = &wmem_strict_gc;
212 allocator->cleanup = &wmem_strict_allocator_cleanup;
214 allocator->private_data = (void*) strict_allocator;
216 strict_allocator->blocks = NULL;
220 * Editor modelines - https://www.wireshark.org/tools/modelines.html
222 * Local variables:
223 * c-basic-offset: 4
224 * tab-width: 8
225 * indent-tabs-mode: nil
226 * End:
228 * vi: set shiftwidth=4 tabstop=8 expandtab:
229 * :indentSize=4:tabSize=8:noTabs=true: