changeset 22138:54260e47d2e1

lib: Add i_realloc_type() for i_realloc() that checks for overflows
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Wed, 07 Jun 2017 11:24:03 +0300
parents d02fc7312081
children df6a5fba9405
files src/lib/Makefile.am src/lib/imem.h src/lib/mempool.h src/lib/test-imem.c src/lib/test-lib.c src/lib/test-lib.h
diffstat 6 files changed, 75 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib/Makefile.am	Thu May 12 05:40:29 2016 -0400
+++ b/src/lib/Makefile.am	Wed Jun 07 11:24:03 2017 +0300
@@ -325,6 +325,7 @@
 	test-hash-format.c \
 	test-hash-method.c \
 	test-hex-binary.c \
+	test-imem.c \
 	test-ioloop.c \
 	test-iso8601-date.c \
 	test-iostream-temp.c \
--- a/src/lib/imem.h	Thu May 12 05:40:29 2016 -0400
+++ b/src/lib/imem.h	Wed Jun 07 11:24:03 2017 +0300
@@ -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)
--- a/src/lib/mempool.h	Thu May 12 05:40:29 2016 -0400
+++ b/src/lib/mempool.h	Wed Jun 07 11:24:03 2017 +0300
@@ -73,9 +73,18 @@
    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)
 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/test-imem.c	Wed Jun 07 11:24:03 2017 +0300
@@ -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();
+}
--- a/src/lib/test-lib.c	Thu May 12 05:40:29 2016 -0400
+++ b/src/lib/test-lib.c	Wed Jun 07 11:24:03 2017 +0300
@@ -20,6 +20,7 @@
 		test_hash_format,
 		test_hash_method,
 		test_hex_binary,
+		test_imem,
 		test_ioloop,
 		test_iso8601_date,
 		test_iostream_temp,
--- a/src/lib/test-lib.h	Thu May 12 05:40:29 2016 -0400
+++ b/src/lib/test-lib.h	Wed Jun 07 11:24:03 2017 +0300
@@ -21,6 +21,7 @@
 void test_hash_format(void);
 void test_hash_method(void);
 void test_hex_binary(void);
+void test_imem(void);
 void test_ioloop(void);
 void test_iso8601_date(void);
 void test_iostream_temp(void);