]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: data-stack - Move frame memory allocation inside data stack block
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Wed, 31 Mar 2021 13:04:47 +0000 (16:04 +0300)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Tue, 4 May 2021 07:02:35 +0000 (07:02 +0000)
src/lib/data-stack.c
src/lib/test-data-stack.c

index 1839d04236c9096b6f63d67869c0bd46563043e6..d7b9de07021ff830a269be4754243e238273e74d 100644 (file)
@@ -149,20 +149,18 @@ data_stack_frame_t t_push(const char *marker)
        }
 
        /* allocate new block */
-       frame = calloc(sizeof(*frame), 1);
-       if (frame == NULL)
-               i_fatal_status(FATAL_OUTOFMEM, "t_push(): Out of memory");
+       frame = t_buffer_get(sizeof(*frame));
        frame->prev = current_frame;
        current_frame = frame;
 
-       data_stack_last_buffer_reset(FALSE);
-
        /* mark our current position */
        current_frame->block = current_block;
        current_frame->block_space_left = current_block->left;
        current_frame->last_alloc_size = 0;
        current_frame->marker = marker;
 
+       t_buffer_alloc(sizeof(*frame));
+
 #ifndef STATIC_CHECKER
        return data_stack_frame_id++;
 #else
@@ -257,7 +255,7 @@ static void t_pop_verify(void)
 
 void t_pop_last_unsafe(void)
 {
-       struct stack_frame *frame;
+       size_t block_space_left;
 
        if (unlikely(current_frame == NULL))
                i_panic("t_pop() called with empty stack");
@@ -270,17 +268,22 @@ void t_pop_last_unsafe(void)
        /* update the current block */
        current_block = current_frame->block;
        block_canary_check(current_block);
+
+       /* current_frame points inside the stack frame that will be freed.
+          make sure it's not accessed after it's already freed/cleaned. */
+       block_space_left = current_frame->block_space_left;
+       current_frame = current_frame->prev;
+
        if (clean_after_pop) {
                size_t start_pos, end_pos;
 
-               start_pos = current_block->size -
-                       current_frame->block_space_left;
+               start_pos = current_block->size - block_space_left;
                end_pos = current_block->size - current_block->left_lowwater;
                i_assert(end_pos >= start_pos);
                memset(STACK_BLOCK_DATA(current_block) + start_pos, CLEAR_CHR,
                       end_pos - start_pos);
        }
-       current_block->left = current_frame->block_space_left;
+       current_block->left = block_space_left;
        current_block->left_lowwater = current_block->left;
 
        if (current_block->next != NULL) {
@@ -289,10 +292,6 @@ void t_pop_last_unsafe(void)
                current_block->next = NULL;
        }
 
-       frame = current_frame;
-       current_frame = frame->prev;
-       free(frame);
-
        data_stack_frame_id--;
 }
 
@@ -435,8 +434,10 @@ static void *t_malloc_real(size_t size, bool permanent)
 #endif
        data_stack_last_buffer_reset(TRUE);
 
-       /* used for t_try_realloc() */
-       current_frame->last_alloc_size = alloc_size;
+       if (permanent) {
+               /* used for t_try_realloc() */
+               current_frame->last_alloc_size = alloc_size;
+       }
 
        if (current_block->left < alloc_size) {
                struct stack_block *block;
index f437c2ddf5748ad600068a9596816750d47042cb..fa703b0d86d3d99bba762e0828350612060a6ca3 100644 (file)
@@ -134,7 +134,10 @@ static void test_ds_buffers(void)
        T_BEGIN {
                size_t bigleft = t_get_bytes_available();
                size_t i;
-               for (i = 1; i < bigleft-64; i += i_rand_limit(32)) T_BEGIN {
+               /* with DEBUG: the stack frame allocation takes 96 bytes
+                  and malloc takes extra 40 bytes + alignment, so don't let
+                  "i" be too high. */
+               for (i = 1; i < bigleft-96-40-16; i += i_rand_limit(32)) T_BEGIN {
                        unsigned char *p, *p2;
                        size_t left;
                        t_malloc_no0(i);