changeset 21323:d223fad9767f

global: Make sure *_malloc() calculations won't cause integer overflows.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Mon, 12 Dec 2016 07:28:00 +0200
parents 5ab8dc1a4a6f
children ce210ada8bc2
files src/auth/auth-request-var-expand.c src/doveadm/doveadm-dump-index.c src/lib-imap/imap-utf7.c src/lib-index/mail-index-transaction-view.c src/lib-index/mail-index.c src/lib-master/master-login.c src/lib-program-client/program-client-local.c src/lib-storage/index/maildir/maildir-save.c src/lib-storage/index/pop3c/pop3c-sync.c src/lib-storage/mailbox-list.c src/lib/data-stack.c src/lib/hex-binary.c src/lib/str-find.c src/lib/strfuncs.c src/log/log-error-buffer.c src/plugins/acl/acl-cache.c src/plugins/acl/acl-cache.h src/pop3/pop3-client.h src/pop3/pop3-commands.c src/stats/mail-command.c src/stats/mail-domain.c src/stats/mail-ip.c src/stats/mail-session.c src/stats/mail-user.c
diffstat 24 files changed, 41 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/src/auth/auth-request-var-expand.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/auth/auth-request-var-expand.c	Mon Dec 12 07:28:00 2016 +0200
@@ -79,8 +79,8 @@
 
 	/* keep the extra fields at the beginning. the last static_tab field
 	   contains the ending NULL-fields. */
-	tab = ret_tab = t_malloc((*count + auth_count) * sizeof(*tab));
-	memset(tab, 0, *count * sizeof(*tab));
+	tab = ret_tab = t_new(struct var_expand_table,
+			      MALLOC_ADD(*count, auth_count));
 	tab += *count;
 	*count += auth_count;
 
--- a/src/doveadm/doveadm-dump-index.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/doveadm/doveadm-dump-index.c	Mon Dec 12 07:28:00 2016 +0200
@@ -212,7 +212,7 @@
 
 	/* add some padding, since we don't bother to handle undersized
 	   headers correctly */
-	buf = t_malloc0(ext->hdr_size + 128);
+	buf = t_malloc0(MALLOC_ADD(ext->hdr_size, 128));
 	data = CONST_PTR_OFFSET(index->map->hdr_base, ext->hdr_offset);
 	memcpy(buf, data, ext->hdr_size);
 	data = buf;
--- a/src/lib-imap/imap-utf7.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/lib-imap/imap-utf7.c	Mon Dec 12 07:28:00 2016 +0200
@@ -82,7 +82,7 @@
 
 	/* at least one encoded character */
 	str_append_n(dest, src, p-src);
-	utf16 = t_malloc(strlen(p)*2);
+	utf16 = t_malloc0(MALLOC_MULTIPLY(strlen(p), 2));
 	while (*p != '\0') {
 		if (*p == '&') {
 			str_append(dest, "&-");
--- a/src/lib-index/mail-index-transaction-view.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/lib-index/mail-index-transaction-view.c	Mon Dec 12 07:28:00 2016 +0200
@@ -113,8 +113,8 @@
 		tview->recs_count = t->first_new_seq;
 		tview->record_size = I_MAX(map->hdr.record_size,
 					   tview->view.map->hdr.record_size);
-		tview->recs = i_malloc(tview->record_size *
-				       tview->recs_count);
+		tview->recs = i_malloc(MALLOC_MULTIPLY(tview->record_size,
+						       tview->recs_count));
 		array_append(&tview->all_recs, &tview->recs, 1);
 	}
 	i_assert(tview->recs_count == t->first_new_seq);
--- a/src/lib-index/mail-index.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/lib-index/mail-index.c	Mon Dec 12 07:28:00 2016 +0200
@@ -347,8 +347,8 @@
 	}
 
 	/* @UNSAFE */
-	k = i_malloc(sizeof(struct mail_keywords) +
-		     (sizeof(k->idx) * (count-1)));
+	k = i_malloc(MALLOC_ADD(sizeof(struct mail_keywords),
+				MALLOC_MULTIPLY(sizeof(k->idx), (count-1))));
 	k->index = index;
 	k->refcount = 1;
 
@@ -387,8 +387,8 @@
 	}
 
 	/* @UNSAFE */
-	k = i_malloc(sizeof(struct mail_keywords) +
-		     (sizeof(k->idx) * (count-1)));
+	k = i_malloc(MALLOC_ADD(sizeof(struct mail_keywords),
+				MALLOC_MULTIPLY(sizeof(k->idx), (count-1))));
 	k->index = index;
 	k->refcount = 1;
 
--- a/src/lib-master/master-login.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/lib-master/master-login.c	Mon Dec 12 07:28:00 2016 +0200
@@ -423,7 +423,7 @@
 
 	/* @UNSAFE: we have a request. do userdb lookup for it. */
 	req.data_size -= i;
-	client = i_malloc(sizeof(struct master_login_client) + req.data_size);
+	client = i_malloc(MALLOC_ADD(sizeof(struct master_login_client), req.data_size));
 	client->conn = conn;
 	client->fd = client_fd;
 	client->auth_req = req;
--- a/src/lib-program-client/program-client-local.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/lib-program-client/program-client-local.c	Mon Dec 12 07:28:00 2016 +0200
@@ -167,9 +167,9 @@
 
 		efds = array_get_modifiable(&pclient->extra_fds, &xfd_count);
 		if (xfd_count > 0) {
-			parent_extra_fds = t_malloc0(sizeof(int) * xfd_count);
-			child_extra_fds =
-				t_malloc0(sizeof(int) * xfd_count * 2 + 1);
+			i_assert(xfd_count < INT_MAX);
+			parent_extra_fds = t_new(int, xfd_count);
+			child_extra_fds = t_new(int, xfd_count * 2 + 1);
 			for(i = 0; i < xfd_count; i++) {
 				if (pipe(extra_fd) < 0) {
 					i_error("pipe(extra=%d) failed: %m",
--- a/src/lib-storage/index/maildir/maildir-save.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/lib-storage/index/maildir/maildir-save.c	Mon Dec 12 07:28:00 2016 +0200
@@ -166,8 +166,8 @@
 	   into new/ or cur/. */
 	/* @UNSAFE */
 	keyword_count = mdata->keywords == NULL ? 0 : mdata->keywords->count;
-	mf = p_malloc(ctx->pool, sizeof(*mf) +
-		      sizeof(unsigned int) * keyword_count);
+	mf = p_malloc(ctx->pool, MALLOC_ADD(sizeof(*mf),
+		MALLOC_MULTIPLY(sizeof(unsigned int), keyword_count)));
 	mf->tmp_name = mf->dest_basename = p_strdup(ctx->pool, tmp_fname);
 	mf->flags = mdata->flags;
 	mf->size = (uoff_t)-1;
--- a/src/lib-storage/index/pop3c/pop3c-sync.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/lib-storage/index/pop3c/pop3c-sync.c	Mon Dec 12 07:28:00 2016 +0200
@@ -215,8 +215,10 @@
 	array_sort(&remote_msgs, pop3c_sync_msg_uidl_cmp);
 
 	/* skip over existing messages with matching UIDLs and expunge the ones
-	   that no longer exist in remote. (+1 to avoid malloc(0) assert) */
-	mbox->msg_uids = i_new(uint32_t, mbox->msg_count + 1);
+	   that no longer exist in remote. */
+	mbox->msg_uids = mbox->msg_count == 0 ?
+		i_new(uint32_t, 1) : /* avoid malloc(0) assert */
+		i_new(uint32_t, mbox->msg_count);
 	cache_trans = mail_cache_get_transaction(cache_view, sync_trans);
 
 	lmsg = array_get(&local_msgs, &lcount);
--- a/src/lib-storage/mailbox-list.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/lib-storage/mailbox-list.c	Mon Dec 12 07:28:00 2016 +0200
@@ -737,7 +737,7 @@
 	if (list_sep != ns_sep || prefix_len > 0) {
 		/* @UNSAFE */
 		name_len = strlen(vname);
-		ret = t_malloc(prefix_len + name_len + 1);
+		ret = t_malloc(MALLOC_ADD(prefix_len, name_len) + 1);
 		memcpy(ret, list->ns->prefix, prefix_len);
 		for (i = 0; i < name_len; i++) {
 			ret[i + prefix_len] =
--- a/src/lib/data-stack.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/lib/data-stack.c	Mon Dec 12 07:28:00 2016 +0200
@@ -322,8 +322,10 @@
 	size_t prev_size, alloc_size;
 
 	prev_size = current_block == NULL ? 0 : current_block->size;
-	alloc_size = nearest_power(prev_size + min_size);
+	alloc_size = nearest_power(MALLOC_ADD(prev_size, min_size));
 
+	/* nearest_power() returns 2^n values, so alloc_size can't be
+	   anywhere close to SIZE_MAX */
 #ifndef USE_GC
 	block = malloc(SIZEOF_MEMBLOCK + alloc_size);
 #else
--- a/src/lib/hex-binary.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/lib/hex-binary.c	Mon Dec 12 07:28:00 2016 +0200
@@ -28,7 +28,7 @@
 
 const char *binary_to_hex(const unsigned char *data, size_t size)
 {
-	unsigned char *dest = t_malloc(size * 2 + 1);
+	unsigned char *dest = t_malloc(MALLOC_MULTIPLY(size, 2) + 1);
 
 	binary_to_hex_case(dest, data, size, FALSE);
 	dest[size*2] = '\0';
@@ -37,7 +37,7 @@
 
 const char *binary_to_hex_ucase(const unsigned char *data, size_t size)
 {
-	unsigned char *dest = t_malloc(size * 2 + 1);
+	unsigned char *dest = t_malloc(MALLOC_MULTIPLY(size, 2) + 1);
 
 	binary_to_hex_case(dest, data, size, TRUE);
 	dest[size*2] = '\0';
--- a/src/lib/str-find.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/lib/str-find.c	Mon Dec 12 07:28:00 2016 +0200
@@ -83,8 +83,8 @@
 	i_assert(key_len > 0);
 	i_assert(key_len < INT_MAX);
 
-	ctx = p_malloc(pool, sizeof(struct str_find_context) +
-		       sizeof(ctx->goodtab[0]) * key_len);
+	ctx = p_malloc(pool, MALLOC_ADD(sizeof(struct str_find_context),
+		MALLOC_MULTIPLY(sizeof(ctx->goodtab[0]), key_len)));
 	ctx->pool = pool;
 	ctx->matches = p_new(pool, unsigned int, key_len);
 	ctx->key_len = key_len;
--- a/src/lib/strfuncs.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/lib/strfuncs.c	Mon Dec 12 07:28:00 2016 +0200
@@ -698,6 +698,7 @@
 	char *p;
 	size_t len, size = sizeof(const char *);
 
+	/* @UNSAFE: integer overflow checks are missing */
 	for (i = 0; arr[i] != NULL; i++)
 		size += sizeof(const char *) + strlen(arr[i]) + 1;
 
--- a/src/log/log-error-buffer.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/log/log-error-buffer.c	Mon Dec 12 07:28:00 2016 +0200
@@ -59,7 +59,8 @@
 		log_error_buffer_delete_head(buf);
 
 	/* @UNSAFE */
-	data = i_malloc(sizeof(*data) + prefix_size + text_size);
+	data = i_malloc(MALLOC_ADD(sizeof(*data),
+				   MALLOC_ADD(prefix_size, text_size)));
 	data->type = error->type;
 	data->timestamp = error->timestamp;
 	memcpy(data->prefix_text, error->prefix, prefix_size);
--- a/src/plugins/acl/acl-cache.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/plugins/acl/acl-cache.c	Mon Dec 12 07:28:00 2016 +0200
@@ -274,8 +274,8 @@
 
 	obj_cache = hash_table_lookup(cache->objects, objname);
 	if (obj_cache == NULL) {
-		obj_cache = i_malloc(sizeof(struct acl_object_cache) +
-				     cache->validity_rec_size);
+		obj_cache = i_malloc(MALLOC_ADD(sizeof(struct acl_object_cache),
+						cache->validity_rec_size));
 		obj_cache->name = i_strdup(objname);
 		hash_table_insert(cache->objects, obj_cache->name, obj_cache);
 		*created_r = TRUE;
--- a/src/plugins/acl/acl-cache.h	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/plugins/acl/acl-cache.h	Mon Dec 12 07:28:00 2016 +0200
@@ -14,7 +14,7 @@
 	unsigned char mask[1];
 };
 #define SIZEOF_ACL_MASK(bitmask_size) \
-	(sizeof(pool_t) + sizeof(unsigned int) + (bitmask_size))
+	(MALLOC_ADD(sizeof(pool_t) + sizeof(unsigned int), (bitmask_size)))
 
 struct acl_cache *acl_cache_init(struct acl_backend *backend,
 				 size_t validity_rec_size);
--- a/src/pop3/pop3-client.h	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/pop3/pop3-client.h	Mon Dec 12 07:28:00 2016 +0200
@@ -10,7 +10,7 @@
 typedef void command_func_t(struct client *client);
 
 #define MSGS_BITMASK_SIZE(client) \
-	(((client)->messages_count + (CHAR_BIT-1)) / CHAR_BIT)
+	(MALLOC_ADD((client)->messages_count, (CHAR_BIT-1)) / CHAR_BIT)
 
 /* Stop reading input when output buffer has this many bytes. Once the buffer
    size has dropped to half of it, start reading input again. */
--- a/src/pop3/pop3-commands.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/pop3/pop3-commands.c	Mon Dec 12 07:28:00 2016 +0200
@@ -827,7 +827,7 @@
 	}
 	/* map UIDLs to msgnums (in case POP3 sort ordering is different) */
 	client->message_uidls = p_new(client->uidl_pool, const char *,
-				      client->messages_count+1);
+				      MALLOC_ADD(client->messages_count, 1));
 	for (msgnum = 0; msgnum < client->messages_count; msgnum++) {
 		client->message_uidls[msgnum] =
 			seq_uidls[msgnum_to_seq(client, msgnum) - 1];
--- a/src/stats/mail-command.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/stats/mail-command.c	Mon Dec 12 07:28:00 2016 +0200
@@ -47,7 +47,7 @@
 {
 	struct mail_command *cmd;
 
-	cmd = i_malloc(sizeof(struct mail_command) + stats_alloc_size());
+	cmd = i_malloc(MALLOC_ADD(sizeof(struct mail_command), stats_alloc_size()));
 	cmd->stats = (void *)(cmd + 1);
 	cmd->refcount = 1; /* unrefed at "done" */
 	cmd->session = session;
--- a/src/stats/mail-domain.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/stats/mail-domain.c	Mon Dec 12 07:28:00 2016 +0200
@@ -28,7 +28,7 @@
 		return domain;
 	}
 
-	domain = i_malloc(sizeof(struct mail_domain) + stats_alloc_size());
+	domain = i_malloc(MALLOC_ADD(sizeof(struct mail_domain), stats_alloc_size()));
 	domain->stats = (void *)(domain + 1);
 	domain->name = i_strdup(name);
 	domain->reset_timestamp = ioloop_time;
--- a/src/stats/mail-ip.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/stats/mail-ip.c	Mon Dec 12 07:28:00 2016 +0200
@@ -31,7 +31,7 @@
 		return ip;
 	}
 
-	ip = i_malloc(sizeof(struct mail_ip) + stats_alloc_size());
+	ip = i_malloc(MALLOC_ADD(sizeof(struct mail_ip), stats_alloc_size()));
 	ip->stats = (void *)(ip + 1);
 	ip->ip = *ip_addr;
 	ip->reset_timestamp = ioloop_time;
--- a/src/stats/mail-session.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/stats/mail-session.c	Mon Dec 12 07:28:00 2016 +0200
@@ -97,7 +97,7 @@
 			session_id, args[1], args[2], (long)session->pid, (long)pid);
 		return -1;
 	}
-	session = i_malloc(sizeof(struct mail_session) + stats_alloc_size());
+	session = i_malloc(MALLOC_ADD(sizeof(struct mail_session), stats_alloc_size()));
 	session->stats = (void *)(session + 1);
 	session->refcount = 1; /* unrefed at disconnect */
 	session->id = i_strdup(session_id);
--- a/src/stats/mail-user.c	Mon Dec 12 07:19:55 2016 +0200
+++ b/src/stats/mail-user.c	Mon Dec 12 07:28:00 2016 +0200
@@ -39,7 +39,7 @@
 	else
 		domain = "";
 
-	user = i_malloc(sizeof(struct mail_user) + stats_alloc_size());
+	user = i_malloc(MALLOC_ADD(sizeof(struct mail_user), stats_alloc_size()));
 	user->stats = (void *)(user + 1);
 	user->name = i_strdup(username);
 	user->reset_timestamp = ioloop_time;