]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
global: Make sure *_malloc() calculations won't cause integer overflows.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 12 Dec 2016 05:28:00 +0000 (07:28 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 16 Dec 2016 21:41:29 +0000 (23:41 +0200)
24 files changed:
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

index dfb4e0f021b5e6f435f0a779ecdbf8c12ea35897..43ecd1ca2e7e7d1a3eaef5510133f691152077b9 100644 (file)
@@ -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;
 
index 2bab0134712864ce7316abc67e17085c6c46e669..a810cea52eccc9e04a1246e11a772bf6099670c7 100644 (file)
@@ -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;
index 1a5504a7ecbc56fe5ada3d213def9488991d7d6b..cdf892f21f15d8947add6dcfeb27abc1821e740f 100644 (file)
@@ -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, "&-");
index 7c01904b111ecb3b6f10dbbb84999cae67db1938..54736d5f0d5342ce13aabcb3371d2a8db481a0f7 100644 (file)
@@ -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);
index b93b839d2c5b97498f155fee43dbef911655a1bf..58a45aff8daa0249639e2b4825057d1c15cb3647 100644 (file)
@@ -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;
 
index 4056c99099029481a88cf89412a5f3c438e119ec..960078c6b08d4234d3efe49327875c9072ed5407 100644 (file)
@@ -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;
index 95acc0efba94a469da88ceade2de89906dc71851..b6f81aeda3fe6aa7ef8bf4f8f4b3e3e1cfe3f82e 100644 (file)
@@ -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",
index 4b6816cd2280c43168b61ec5841de40edec4ce27..dab0bb785aed199e011902c012ab98e8a5f3863c 100644 (file)
@@ -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;
index 011bbdb1086c61245a507e0140c5c0ef1ec62bf6..489253761d28d824cd54af0040406ee2d56a5389 100644 (file)
@@ -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);
index ad1a5ac2cf5d7b97483143c16b1217a9738c83bb..2f1d7f91a608d5892f7f2b6f7740b3497fb7b0d2 100644 (file)
@@ -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] =
index 913326d21878b097e8814b10e3ad9e12a5ab1da0..c8f331222a18c2b2692f40d247efaa4d44594bc7 100644 (file)
@@ -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
index 16f7868ec70fe9c99ed2ccc2c1c2adf578b3a66f..edb297c1fb5b646d5c2ec8d3c6c4cc95f1e9aa6c 100644 (file)
@@ -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';
index 44bf3c58a416f477fe3f34c09e316854198b0a8f..d8362b32b4008557d2208d105801791d712e111c 100644 (file)
@@ -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;
index 1e8d41c43d5fa8557430ad1201b140a8627ecbd4..d5d2b2ec2242ff7dbdf18226460791a446212e08 100644 (file)
@@ -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;
 
index 347a3f84c5b8b007c55e0ff1ea0b6769cb5f933c..7fdef9ff8f777a8f3f09f524bdbab5272c2113ad 100644 (file)
@@ -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);
index 420220c5def7e992c825f71fce39f1a6d5e23ac1..712b7d75a39b014a8e45aed70228afcc6f92fe51 100644 (file)
@@ -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;
index 396e9ddc8a92454d0a9d2d3c57424eff555d2729..6b71ed5760e5993fa7d7fab3ab49d551c0f41c76 100644 (file)
@@ -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);
index c437bf964998d79eddac1054c89853fcbe56cef1..ed4a115771a3c654738cfdc59ac8544061831731 100644 (file)
@@ -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. */
index e2149e7534663ed1f7d3531e42efa68cb27d4532..10b3cb6e60a3dfd8b7eacf03e27eee078ad448ea 100644 (file)
@@ -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];
index 80e9bbb447821cbd18a04ace71b6d8b2a6d9b183..5c77ced0c788e8957cca76ba6110c36ef940b276 100644 (file)
@@ -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;
index b55f1605e3ad2402b50ed513660694010c32ae9d..ec8523750387c0c176a25a6d21a647b63896474c 100644 (file)
@@ -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;
index e9c77d91ab1564cff8d0bf32e2e69e5cfd32f9ed..1b1915293d37b89a620e2c1a9114c49313481f45 100644 (file)
@@ -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;
index dc6f8ddc3f0908c720bfaa97d8c3f29571cdb316..9452d2819dd7ba1ffb3fd959e28f384d7fbe83bf 100644 (file)
@@ -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);
index 2b9e888c3ceadf927b31055c311b7c49669e00fc..a2a237d79196d49acc63a3a3b6af11aff17c452d 100644 (file)
@@ -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;