]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Add i_realloc_type() for i_realloc() that checks for overflows
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 7 Jun 2017 08:24:03 +0000 (11:24 +0300)
committerGitLab <gitlab@git.dovecot.net>
Thu, 8 Jun 2017 10:50:13 +0000 (13:50 +0300)
src/lib/Makefile.am
src/lib/imem.h
src/lib/mempool.h
src/lib/test-imem.c [new file with mode: 0644]
src/lib/test-lib.inc

index ee72da3a4ef1dc580e77f90c5fc562002cd7bef1..5e9ebebae7c974bf1426296e74b0446f1fe3d5c3 100644 (file)
@@ -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 \
index 0d35ffcc6e70f6e021d534d9c98928132e5f9fed..4065b6e6f530226e0aaab10297c40338f3ba8cba 100644 (file)
@@ -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)
index da7583d9ef125ed2d4f55cf2b5c3cc5aa08cfce7..fefac79ebe750622a395212d1aa430e538af34bc 100644 (file)
@@ -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)
 {
diff --git a/src/lib/test-imem.c b/src/lib/test-imem.c
new file mode 100644 (file)
index 0000000..01570ad
--- /dev/null
@@ -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();
+}
index 571a74a402b4fa7335ad6262ca3c66fc6377b024..8d54e3a220b90b370996c1952252d6dd27f238d2 100644 (file)
@@ -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)