Skip to content

Commit

Permalink
lib: Allow static analyzers to check for t_pop() leaks.
Browse files Browse the repository at this point in the history
They should be able to detect the missing free() call from code paths
missing a t_pop().
  • Loading branch information
sirainen committed Sep 8, 2016
1 parent f2ed47f commit e90d9ea
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 15 deletions.
26 changes: 20 additions & 6 deletions src/lib/data-stack.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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, ...)
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions src/lib/data-stack.h
Expand Up @@ -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
Expand Down
14 changes: 7 additions & 7 deletions src/lib/mempool-datastack.c
Expand Up @@ -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)
Expand All @@ -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;
}

Expand All @@ -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++;
Expand All @@ -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--;
Expand All @@ -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);
Expand All @@ -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");
}

Expand All @@ -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)
Expand Down

0 comments on commit e90d9ea

Please sign in to comment.