Skip to content

Commit

Permalink
lib: Add i_realloc_type() for i_realloc() that checks for overflows
Browse files Browse the repository at this point in the history
  • Loading branch information
sirainen authored and GitLab committed Jun 8, 2017
1 parent d8ed8d5 commit 71b92ca
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib/Makefile.am
Expand Up @@ -331,6 +331,7 @@ test_lib_SOURCES = \
test-hash-method.c \
test-hmac.c \
test-hex-binary.c \
test-imem.c \
test-ioloop.c \
test-iso8601-date.c \
test-iostream-pump.c \
Expand Down
2 changes: 2 additions & 0 deletions src/lib/imem.h
Expand Up @@ -6,6 +6,8 @@
extern pool_t default_pool;

#define i_new(type, count) p_new(default_pool, type, count)
#define i_realloc_type(mem, type, old_count, new_count) \
p_realloc_type(default_pool, mem, type, old_count, new_count)

void *i_malloc(size_t size) ATTR_MALLOC ATTR_RETURNS_NONNULL;
void *i_realloc(void *mem, size_t old_size, size_t new_size)
Expand Down
9 changes: 9 additions & 0 deletions src/lib/mempool.h
Expand Up @@ -73,9 +73,18 @@ pool_t pool_datastack_create(void);
old_size + 1. */
size_t pool_get_exp_grown_size(pool_t pool, size_t old_size, size_t min_size);

/* We require sizeof(type) to be <= UINT_MAX. This allows compiler to optimize
away the entire MALLOC_MULTIPLY() call on 64bit systems. */
#define p_new(pool, type, count) \
((type *) p_malloc(pool, MALLOC_MULTIPLY((unsigned int)sizeof(type), (count))) + \
COMPILE_ERROR_IF_TRUE(sizeof(type) > UINT_MAX))

#define p_realloc_type(pool, mem, type, old_count, new_count) \
((type *) p_realloc(pool, mem, \
MALLOC_MULTIPLY((unsigned int)sizeof(type), (old_count)), \
MALLOC_MULTIPLY((unsigned int)sizeof(type), (new_count))) + \
COMPILE_ERROR_IF_TRUE(sizeof(type) > UINT_MAX))

static inline void * ATTR_MALLOC ATTR_RETURNS_NONNULL
p_malloc(pool_t pool, size_t size)
{
Expand Down
61 changes: 61 additions & 0 deletions src/lib/test-imem.c
@@ -0,0 +1,61 @@
/* Copyright (c) 2017 Dovecot authors, see the included COPYING file */

#include "test-lib.h"

struct test_struct {
uint32_t num[10];
};

static void test_imem_alloc(void)
{
struct test_struct ab, bc, cd, de;

test_begin("imem allocs");

memset(ab.num, 0xab, sizeof(ab.num));
memset(bc.num, 0xbc, sizeof(bc.num));
memset(cd.num, 0xcd, sizeof(cd.num));
memset(de.num, 0xde, sizeof(de.num));

/* regular alloc */
struct test_struct *s1 = i_new(struct test_struct, 2);
struct test_struct *s2 = i_malloc(sizeof(struct test_struct) * 2);
s1[0] = ab; s2[0] = ab;
s1[1] = bc; s2[1] = bc;
test_assert(memcmp(s1, s2, sizeof(struct test_struct) * 2) == 0);

/* realloc */
s1 = i_realloc_type(s1, struct test_struct, 2, 4);
s2 = i_realloc(s2, sizeof(struct test_struct) * 2,
sizeof(struct test_struct) * 4);
s1[2] = cd; s2[2] = cd;
s1[3] = de; s2[3] = de;
test_assert(memcmp(&s1[0], &ab, sizeof(ab)) == 0);
test_assert(memcmp(&s1[1], &bc, sizeof(bc)) == 0);
test_assert(memcmp(&s1[2], &cd, sizeof(cd)) == 0);
test_assert(memcmp(&s1[3], &de, sizeof(de)) == 0);
test_assert(memcmp(s1, s2, sizeof(struct test_struct) * 4) == 0);

/* freeing realloced memory */
i_free(s1);
i_free(s2);
test_assert(s1 == NULL);
test_assert(s2 == NULL);

/* allcating new memory with realloc */
s1 = i_realloc_type(NULL, struct test_struct, 0, 2);
s2 = i_realloc(NULL, 0, sizeof(struct test_struct) * 2);
s1[0] = ab; s2[0] = ab;
s1[1] = bc; s2[1] = bc;
test_assert(memcmp(s1, s2, sizeof(struct test_struct) * 2) == 0);

i_free(s1);
i_free(s2);

test_end();
}

void test_imem(void)
{
test_imem_alloc();
}
1 change: 1 addition & 0 deletions src/lib/test-lib.inc
Expand Up @@ -20,6 +20,7 @@ TEST(test_hash_format)
TEST(test_hash_method)
TEST(test_hmac)
TEST(test_hex_binary)
TEST(test_imem)
TEST(test_ioloop)
TEST(test_iso8601_date)
TEST(test_iostream_pump)
Expand Down

0 comments on commit 71b92ca

Please sign in to comment.