dovecot-2.2: lib: data-stack - enable tighter sanity checks on s...
dovecot at dovecot.org
dovecot at dovecot.org
Mon Jul 28 13:54:27 UTC 2014
details: http://hg.dovecot.org/dovecot-2.2/rev/b4eec0a20bba
changeset: 17639:b4eec0a20bba
user: Phil Carmody <phil at dovecot.fi>
date: Mon Jul 28 16:45:33 2014 +0300
description:
lib: data-stack - enable tighter sanity checks on stack_block allocations
The canary doesn't have to be NULL. That's only effective if it will be read
and dereferenced as a pointer. If used as an integer, it's a perfectly boring
one, and not likely to draw attention to itself.
Once the canary is in place, at least in debug mode, we can check it in
every function as a sanity check.
Make our poison stand out from other poison used elsewhere in the code.
Signed-off-by: Phil Carmody <phil at dovecot.fi>
diffstat:
src/lib/data-stack.c | 18 ++++++++++++++----
1 files changed, 14 insertions(+), 4 deletions(-)
diffs (87 lines):
diff -r a5f479be46b9 -r b4eec0a20bba src/lib/data-stack.c
--- a/src/lib/data-stack.c Mon Jul 28 16:45:33 2014 +0300
+++ b/src/lib/data-stack.c Mon Jul 28 16:45:33 2014 +0300
@@ -22,19 +22,23 @@
#endif
#ifdef DEBUG
-# define CLEAR_CHR 0xde
+# define CLEAR_CHR 0xD5 /* D5 is mnemonic for "Data 5tack" */
# define SENTRY_COUNT (4*8)
+# define BLOCK_CANARY ((void *)0xBADBADD5BADBADD5) /* contains 'D5' */
+# define BLOCK_CANARY_CHECK(block) i_assert((block)->canary == BLOCK_CANARY)
#else
# define CLEAR_CHR 0
+# define BLOCK_CANARY NULL
+# define BLOCK_CANARY_CHECK(block) do { ; } while(0)
#endif
struct stack_block {
struct stack_block *next;
size_t size, left, lowwater;
- /* always NULL and here just in case something accesses
+ /* NULL or a poison value, just in case something accesses
the memory in front of an allocated area */
- char *nullpad;
+ void *canary;
/* unsigned char data[]; */
};
@@ -192,6 +196,7 @@
/* free all the blocks, except if any of them is bigger than
unused_block, replace it */
while (block != NULL) {
+ BLOCK_CANARY_CHECK(block);
next = block->next;
if (clean_after_pop)
@@ -223,6 +228,7 @@
block = current_frame_block->block[frame_pos];
pos = block->size - current_frame_block->block_space_used[frame_pos];
while (block != NULL) {
+ BLOCK_CANARY_CHECK(block);
used_size = block->size - block->left;
p = STACK_BLOCK_DATA(block);
while (pos < used_size) {
@@ -264,6 +270,7 @@
/* update the current block */
current_block = current_frame_block->block[frame_pos];
+ BLOCK_CANARY_CHECK(current_block);
if (clean_after_pop) {
size_t pos, used_size;
@@ -332,7 +339,7 @@
block->left = 0;
block->lowwater = block->size;
block->next = NULL;
- block->nullpad = NULL;
+ block->canary = BLOCK_CANARY;
#ifdef DEBUG
memset(STACK_BLOCK_DATA(block), CLEAR_CHR, alloc_size);
@@ -357,6 +364,7 @@
/* kludgy, but allow this before initialization */
data_stack_init();
}
+ BLOCK_CANARY_CHECK(current_block);
/* allocate only aligned amount of memory so alignment comes
always properly */
@@ -456,6 +464,7 @@
if (unlikely(size == 0 || size > SSIZE_T_MAX))
i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
+ BLOCK_CANARY_CHECK(current_block);
last_alloc_size = current_frame_block->last_alloc_size[frame_pos];
@@ -484,6 +493,7 @@
const unsigned int extra = MEM_ALIGN_SIZE-1 + SENTRY_COUNT +
MEM_ALIGN(sizeof(size_t));
#endif
+ BLOCK_CANARY_CHECK(current_block);
return current_block->left < extra ? current_block->left :
current_block->left - extra;
}
More information about the dovecot-cvs
mailing list