From: Timo Sirainen Date: Mon, 12 Dec 2016 05:28:00 +0000 (+0200) Subject: global: Make sure *_malloc() calculations won't cause integer overflows. X-Git-Tag: 2.3.0.rc1~2409 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e7d0bea63a08b08c47c4b5c187d2cb7127859657;p=thirdparty%2Fdovecot%2Fcore.git global: Make sure *_malloc() calculations won't cause integer overflows. --- diff --git a/src/auth/auth-request-var-expand.c b/src/auth/auth-request-var-expand.c index dfb4e0f021..43ecd1ca2e 100644 --- a/src/auth/auth-request-var-expand.c +++ b/src/auth/auth-request-var-expand.c @@ -79,7 +79,8 @@ auth_request_get_var_expand_table_full(const struct auth_request *auth_request, /* keep the extra fields at the beginning. the last static_tab field contains the ending NULL-fields. */ - tab = ret_tab = t_new(struct var_expand_table, *count + auth_count); + tab = ret_tab = t_new(struct var_expand_table, + MALLOC_ADD(*count, auth_count)); tab += *count; *count += auth_count; diff --git a/src/doveadm/doveadm-dump-index.c b/src/doveadm/doveadm-dump-index.c index 2bab013471..a810cea52e 100644 --- a/src/doveadm/doveadm-dump-index.c +++ b/src/doveadm/doveadm-dump-index.c @@ -212,7 +212,7 @@ static void dump_extension_header(struct mail_index *index, /* 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; diff --git a/src/lib-imap/imap-utf7.c b/src/lib-imap/imap-utf7.c index 1a5504a7ec..cdf892f21f 100644 --- a/src/lib-imap/imap-utf7.c +++ b/src/lib-imap/imap-utf7.c @@ -82,7 +82,7 @@ int imap_utf8_to_utf7(const char *src, string_t *dest) /* at least one encoded character */ str_append_n(dest, src, p-src); - utf16 = t_malloc0(strlen(p)*2); + utf16 = t_malloc0(MALLOC_MULTIPLY(strlen(p), 2)); while (*p != '\0') { if (*p == '&') { str_append(dest, "&-"); diff --git a/src/lib-index/mail-index-transaction-view.c b/src/lib-index/mail-index-transaction-view.c index 7c01904b11..54736d5f0d 100644 --- a/src/lib-index/mail-index-transaction-view.c +++ b/src/lib-index/mail-index-transaction-view.c @@ -113,8 +113,8 @@ tview_apply_flag_updates(struct mail_index_view_transaction *tview, 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); diff --git a/src/lib-index/mail-index.c b/src/lib-index/mail-index.c index b93b839d2c..58a45aff8d 100644 --- a/src/lib-index/mail-index.c +++ b/src/lib-index/mail-index.c @@ -347,8 +347,8 @@ mail_index_keywords_create(struct mail_index *index, } /* @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 @@ mail_index_keywords_create_from_indexes(struct mail_index *index, } /* @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; diff --git a/src/lib-master/master-login.c b/src/lib-master/master-login.c index 4056c99099..960078c6b0 100644 --- a/src/lib-master/master-login.c +++ b/src/lib-master/master-login.c @@ -420,7 +420,7 @@ static void master_login_conn_input(struct master_login_connection *conn) /* @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; diff --git a/src/lib-program-client/program-client-local.c b/src/lib-program-client/program-client-local.c index 95acc0efba..b6f81aeda3 100644 --- a/src/lib-program-client/program-client-local.c +++ b/src/lib-program-client/program-client-local.c @@ -170,9 +170,9 @@ int program_client_local_connect(struct program_client *pclient) 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", diff --git a/src/lib-storage/index/maildir/maildir-save.c b/src/lib-storage/index/maildir/maildir-save.c index 4b6816cd22..dab0bb785a 100644 --- a/src/lib-storage/index/maildir/maildir-save.c +++ b/src/lib-storage/index/maildir/maildir-save.c @@ -167,8 +167,8 @@ maildir_save_add(struct mail_save_context *_ctx, const char *tmp_fname, 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; diff --git a/src/lib-storage/index/pop3c/pop3c-sync.c b/src/lib-storage/index/pop3c/pop3c-sync.c index 011bbdb108..489253761d 100644 --- a/src/lib-storage/index/pop3c/pop3c-sync.c +++ b/src/lib-storage/index/pop3c/pop3c-sync.c @@ -217,8 +217,10 @@ pop3c_sync_messages(struct pop3c_mailbox *mbox, 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); diff --git a/src/lib-storage/mailbox-list.c b/src/lib-storage/mailbox-list.c index ad1a5ac2cf..2f1d7f91a6 100644 --- a/src/lib-storage/mailbox-list.c +++ b/src/lib-storage/mailbox-list.c @@ -737,7 +737,7 @@ const char *mailbox_list_default_get_vname(struct mailbox_list *list, if (list_sep != ns_sep || prefix_len > 0) { /* @UNSAFE */ name_len = strlen(vname); - ret = t_malloc_no0(prefix_len + name_len + 1); + ret = t_malloc_no0(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] = diff --git a/src/lib/data-stack.c b/src/lib/data-stack.c index 913326d218..c8f331222a 100644 --- a/src/lib/data-stack.c +++ b/src/lib/data-stack.c @@ -344,8 +344,10 @@ static struct stack_block *mem_block_alloc(size_t min_size) 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 diff --git a/src/lib/hex-binary.c b/src/lib/hex-binary.c index 16f7868ec7..edb297c1fb 100644 --- a/src/lib/hex-binary.c +++ b/src/lib/hex-binary.c @@ -28,7 +28,7 @@ binary_to_hex_case(unsigned char *dest, const unsigned char *data, const char *binary_to_hex(const unsigned char *data, size_t size) { - unsigned char *dest = t_malloc_no0(size * 2 + 1); + unsigned char *dest = t_malloc_no0(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(const unsigned char *data, size_t size) const char *binary_to_hex_ucase(const unsigned char *data, size_t size) { - unsigned char *dest = t_malloc_no0(size * 2 + 1); + unsigned char *dest = t_malloc_no0(MALLOC_MULTIPLY(size, 2) + 1); binary_to_hex_case(dest, data, size, TRUE); dest[size*2] = '\0'; diff --git a/src/lib/str-find.c b/src/lib/str-find.c index 44bf3c58a4..d8362b32b4 100644 --- a/src/lib/str-find.c +++ b/src/lib/str-find.c @@ -83,8 +83,8 @@ struct str_find_context *str_find_init(pool_t pool, const char *key) 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; diff --git a/src/lib/strfuncs.c b/src/lib/strfuncs.c index 1e8d41c43d..d5d2b2ec22 100644 --- a/src/lib/strfuncs.c +++ b/src/lib/strfuncs.c @@ -690,6 +690,7 @@ const char **p_strarray_dup(pool_t pool, const char *const *arr) 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; diff --git a/src/log/log-error-buffer.c b/src/log/log-error-buffer.c index 347a3f84c5..7fdef9ff8f 100644 --- a/src/log/log-error-buffer.c +++ b/src/log/log-error-buffer.c @@ -59,7 +59,8 @@ void log_error_buffer_add(struct log_error_buffer *buf, 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); diff --git a/src/plugins/acl/acl-cache.c b/src/plugins/acl/acl-cache.c index 420220c5de..712b7d75a3 100644 --- a/src/plugins/acl/acl-cache.c +++ b/src/plugins/acl/acl-cache.c @@ -274,8 +274,8 @@ acl_cache_object_get(struct acl_cache *cache, const char *objname, 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; diff --git a/src/plugins/acl/acl-cache.h b/src/plugins/acl/acl-cache.h index 396e9ddc8a..6b71ed5760 100644 --- a/src/plugins/acl/acl-cache.h +++ b/src/plugins/acl/acl-cache.h @@ -14,7 +14,7 @@ struct acl_mask { 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); diff --git a/src/pop3/pop3-client.h b/src/pop3/pop3-client.h index c437bf9649..ed4a115771 100644 --- a/src/pop3/pop3-client.h +++ b/src/pop3/pop3-client.h @@ -10,7 +10,7 @@ struct mail_storage_service_ctx; 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. */ diff --git a/src/pop3/pop3-commands.c b/src/pop3/pop3-commands.c index e2149e7534..10b3cb6e60 100644 --- a/src/pop3/pop3-commands.c +++ b/src/pop3/pop3-commands.c @@ -830,7 +830,7 @@ static void client_uidls_save(struct client *client) } /* 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]; diff --git a/src/stats/mail-command.c b/src/stats/mail-command.c index 80e9bbb447..5c77ced0c7 100644 --- a/src/stats/mail-command.c +++ b/src/stats/mail-command.c @@ -47,7 +47,7 @@ mail_command_add(struct mail_session *session, const char *name, { 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; diff --git a/src/stats/mail-domain.c b/src/stats/mail-domain.c index b55f1605e3..ec85237503 100644 --- a/src/stats/mail-domain.c +++ b/src/stats/mail-domain.c @@ -28,7 +28,7 @@ struct mail_domain *mail_domain_login_create(const char *name) 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; diff --git a/src/stats/mail-ip.c b/src/stats/mail-ip.c index e9c77d91ab..1b1915293d 100644 --- a/src/stats/mail-ip.c +++ b/src/stats/mail-ip.c @@ -31,7 +31,7 @@ struct mail_ip *mail_ip_login(const struct ip_addr *ip_addr) 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; diff --git a/src/stats/mail-session.c b/src/stats/mail-session.c index dc6f8ddc3f..9452d2819d 100644 --- a/src/stats/mail-session.c +++ b/src/stats/mail-session.c @@ -97,7 +97,7 @@ int mail_session_connect_parse(const char *const *args, const char **error_r) 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); diff --git a/src/stats/mail-user.c b/src/stats/mail-user.c index 2b9e888c3c..a2a237d791 100644 --- a/src/stats/mail-user.c +++ b/src/stats/mail-user.c @@ -37,7 +37,7 @@ struct mail_user *mail_user_login(const char *username) if (domain == NULL) 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;