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
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
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 */
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
56 wmem_strict_block_check_canaries(wmem_strict_allocator_block_t
*block
)
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
72 wmem_strict_alloc(void *private_data
, const size_t size
)
74 wmem_strict_allocator_t
*allocator
;
75 wmem_strict_allocator_block_t
*block
;
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
;
97 allocator
->blocks
= block
;
99 return WMEM_BLOCK_TO_DATA(block
);
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
);
115 block
->next
->prev
= block
->prev
;
119 block
->prev
->next
= block
->next
;
122 allocator
->blocks
= block
->next
;
125 memset(block
, WMEM_POSTFILL
, WMEM_FULL_SIZE(block
->data_len
));
127 wmem_free(NULL
, block
);
131 wmem_strict_realloc(void *private_data
, void *ptr
, const size_t size
)
133 wmem_strict_allocator_block_t
*block
;
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
);
146 memcpy(new_ptr
, ptr
, block
->data_len
);
149 /* free the old block */
150 wmem_strict_free(private_data
, ptr
);
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
) {
165 private_allocator
= (wmem_strict_allocator_t
*) allocator
->private_data
;
167 block
= private_allocator
->blocks
;
169 wmem_strict_block_check_canaries(block
);
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
));
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? */
194 wmem_strict_allocator_cleanup(void *private_data
)
196 wmem_free(NULL
, private_data
);
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
225 * indent-tabs-mode: nil
228 * vi: set shiftwidth=4 tabstop=8 expandtab:
229 * :indentSize=4:tabSize=8:noTabs=true: