From: Timo Sirainen Date: Thu, 8 Sep 2016 18:31:37 +0000 (+0300) Subject: lib: Allow static analyzers to check for t_pop() leaks. X-Git-Tag: 2.3.0.rc1~3065 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e90d9eaa3ef3486c2da76b86ffd83b779f45d9cd;p=thirdparty%2Fdovecot%2Fcore.git lib: Allow static analyzers to check for t_pop() leaks. They should be able to detect the missing free() call from code paths missing a t_pop(). --- diff --git a/src/lib/data-stack.c b/src/lib/data-stack.c index 88939ed7a2..ba3d04e31a 100644 --- a/src/lib/data-stack.c +++ b/src/lib/data-stack.c @@ -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); diff --git a/src/lib/data-stack.h b/src/lib/data-stack.h index b15b12dbfc..fa3f32dc01 100644 --- a/src/lib/data-stack.h +++ b/src/lib/data-stack.h @@ -31,13 +31,13 @@ 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 diff --git a/src/lib/mempool-datastack.c b/src/lib/mempool-datastack.c index 83578c6694..8304db67a5 100644 --- a/src/lib/mempool-datastack.c +++ b/src/lib/mempool-datastack.c @@ -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)