]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Allow static analyzers to check for t_pop() leaks.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 8 Sep 2016 18:31:37 +0000 (21:31 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 8 Sep 2016 18:31:37 +0000 (21:31 +0300)
They should be able to detect the missing free() call from code paths
missing a t_pop().

src/lib/data-stack.c
src/lib/data-stack.h
src/lib/mempool-datastack.c

index 88939ed7a2cf98cde454043e682ecc8e79c0b5a4..ba3d04e31a7ea6f93d20aed60b82249fe396463b 100644 (file)
@@ -67,13 +67,13 @@ struct stack_frame_block {
 #endif
 };
 
-#ifdef DEBUG
+#ifdef STATIC_CHECKER
 struct data_stack_frame {
-       int dummy;
+       unsigned int id;
 };
 #endif
 
-data_stack_frame_t data_stack_frame = 0;
+unsigned int data_stack_frame_id = 0;
 
 static bool data_stack_initialized = FALSE;
 static data_stack_frame_t root_frame_id;
@@ -184,7 +184,13 @@ data_stack_frame_t t_push(const char *marker)
        (void)marker; /* only used for debugging */
 #endif
 
-       return data_stack_frame++;
+#ifndef STATIC_CHECKER
+       return data_stack_frame_id++;
+#else
+       struct data_stack_frame *frame = i_new(struct data_stack_frame, 1);
+       frame->id = data_stack_frame_id++;
+       return frame;
+#endif
 }
 
 data_stack_frame_t t_push_named(const char *format, ...)
@@ -314,9 +320,17 @@ bool t_pop(data_stack_frame_t *id)
                frame_block->prev = unused_frame_blocks;
                unused_frame_blocks = frame_block;
        }
-       if (unlikely(--data_stack_frame != *id))
+#ifndef STATIC_CHECKER
+       if (unlikely(--data_stack_frame_id != *id))
                return FALSE;
        *id = 0;
+#else
+       unsigned int frame_id = (*id)->id;
+       i_free_and_null(*id);
+
+       if (unlikely(--data_stack_frame_id != frame_id))
+               return FALSE;
+#endif
        return TRUE;
 }
 
@@ -577,7 +591,7 @@ void data_stack_init(void)
                return;
        }
        data_stack_initialized = TRUE;
-       data_stack_frame = (data_stack_frame_t)1;
+       data_stack_frame_id = 1;
 
        outofmem_area.block.size = outofmem_area.block.left =
                sizeof(outofmem_area) - sizeof(outofmem_area.block);
index b15b12dbfce3d45a07ffe7daf0ab1ed635c4bc16..fa3f32dc016c3395d3a65a48e5e4e8085df1454e 100644 (file)
       overflows.
 */
 
-#ifndef DEBUG
+#ifndef STATIC_CHECKER
 typedef unsigned int data_stack_frame_t;
 #else
 typedef struct data_stack_frame *data_stack_frame_t;
 #endif
 
-extern data_stack_frame_t data_stack_frame;
+extern unsigned int data_stack_frame_id;
 
 /* All t_..() allocations between t_push*() and t_pop() are freed after t_pop()
    is called. Returns the current stack frame number, which can be used
index 83578c669489ee7beadc244d04e8dc2fd2911cf3..8304db67a5952cddfa78c6d303e8ab3797cd9b6c 100644 (file)
@@ -40,7 +40,7 @@ struct datastack_pool {
        struct pool pool;
        int refcount;
 
-       data_stack_frame_t data_stack_frame;
+       unsigned int data_stack_frame;
 };
 
 pool_t pool_datastack_create(void)
@@ -50,7 +50,7 @@ pool_t pool_datastack_create(void)
        dpool = t_new(struct datastack_pool, 1);
        dpool->pool = static_data_stack_pool;
        dpool->refcount = 1;
-       dpool->data_stack_frame = data_stack_frame;
+       dpool->data_stack_frame = data_stack_frame_id;
        return &dpool->pool;
 }
 
@@ -63,7 +63,7 @@ static void pool_data_stack_ref(pool_t pool)
 {
        struct datastack_pool *dpool = (struct datastack_pool *) pool;
 
-       if (unlikely(dpool->data_stack_frame != data_stack_frame))
+       if (unlikely(dpool->data_stack_frame != data_stack_frame_id))
                i_panic("pool_data_stack_ref(): stack frame changed");
 
        dpool->refcount++;
@@ -73,7 +73,7 @@ static void pool_data_stack_unref(pool_t *pool)
 {
        struct datastack_pool *dpool = (struct datastack_pool *)*pool;
 
-       if (unlikely(dpool->data_stack_frame != data_stack_frame))
+       if (unlikely(dpool->data_stack_frame != data_stack_frame_id))
                i_panic("pool_data_stack_unref(): stack frame changed");
 
        dpool->refcount--;
@@ -89,7 +89,7 @@ static void *pool_data_stack_malloc(pool_t pool ATTR_UNUSED, size_t size)
        if (unlikely(size == 0 || size > SSIZE_T_MAX))
                i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
 
-       if (unlikely(dpool->data_stack_frame != data_stack_frame))
+       if (unlikely(dpool->data_stack_frame != data_stack_frame_id))
                i_panic("pool_data_stack_malloc(): stack frame changed");
 
        return t_malloc0(size);
@@ -99,7 +99,7 @@ static void pool_data_stack_free(pool_t pool, void *mem ATTR_UNUSED)
 {
        struct datastack_pool *dpool = (struct datastack_pool *) pool;
 
-       if (unlikely(dpool->data_stack_frame != data_stack_frame))
+       if (unlikely(dpool->data_stack_frame != data_stack_frame_id))
                i_panic("pool_data_stack_free(): stack frame changed");
 }
 
@@ -113,7 +113,7 @@ static void *pool_data_stack_realloc(pool_t pool, void *mem,
        if (unlikely(new_size == 0 || new_size > SSIZE_T_MAX))
                i_panic("Trying to allocate %"PRIuSIZE_T" bytes", new_size);
 
-       if (unlikely(dpool->data_stack_frame != data_stack_frame))
+       if (unlikely(dpool->data_stack_frame != data_stack_frame_id))
                i_panic("pool_data_stack_realloc(): stack frame changed");
 
        if (mem == NULL)