]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-index, global: mail_cache_register_get_list() - Allocate results from a new pool
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 27 Dec 2022 13:35:23 +0000 (08:35 -0500)
committerTimo Sirainen <timo.sirainen@open-xchange.com>
Wed, 11 Jan 2023 21:50:37 +0000 (23:50 +0200)
The memory allocations can get large enough that it causes data stack to be
grown.

src/doveadm/doveadm-dump-index.c
src/lib-index/mail-cache-decisions.c
src/lib-index/mail-cache-fields.c
src/lib-index/mail-cache.h
src/lib-storage/index/index-mail-headers.c
src/lib-storage/index/index-status.c
src/lib-storage/index/index-storage.c
src/lib-storage/index/maildir/maildir-mail.c

index 2f2e1b9fbce10854dba898abe671d9f196d57db0..dada1817d3476dff69afebe201fb4bbbbb773517 100644 (file)
@@ -431,6 +431,7 @@ static void dump_cache_hdr(struct mail_cache *cache)
        const struct mail_cache_header *hdr;
        const struct mail_cache_field *fields, *field;
        unsigned int i, count, cache_idx;
+       pool_t pool;
 
        (void)mail_cache_open_and_verify(cache);
        if (MAIL_CACHE_IS_UNUSABLE(cache)) {
@@ -454,8 +455,7 @@ static void dump_cache_hdr(struct mail_cache *cache)
               hdr->field_header_offset);
 
        printf("-- Cache fields --\n");
-       fields = mail_cache_register_get_list(cache, pool_datastack_create(),
-                                             &count);
+       fields = mail_cache_register_get_list(cache, &pool, &count);
        printf(
 " #  Name                                         Type Size Dec  Last used\n");
        for (i = 0; i < cache->file_fields_count; i++) {
@@ -473,6 +473,7 @@ static void dump_cache_hdr(struct mail_cache *cache)
                       cache_decision2str(field->decision),
                       unixdate2str(field->last_used));
        }
+       pool_unref(&pool);
 }
 
 static void dump_message_part(string_t *str, const struct message_part *part)
index a725ff640de1a4c6d282085ad357fe6054199c9a..67ed14303434c90ffb573e683fc58e47aad4eb49 100644 (file)
@@ -274,9 +274,10 @@ int mail_cache_decisions_copy(struct mail_cache *src, struct mail_cache *dst)
        if (MAIL_CACHE_IS_UNUSABLE(src))
                return 0; /* no caching decisions */
 
+       pool_t pool;
        unsigned int count = 0;
        struct mail_cache_field *fields =
-               mail_cache_register_get_list(src, pool_datastack_create(), &count);
+               mail_cache_register_get_list(src, &pool, &count);
        i_assert(fields != NULL || count == 0);
        if (count > 0)
                mail_cache_register_fields(dst, fields, count,
@@ -287,5 +288,6 @@ int mail_cache_decisions_copy(struct mail_cache *src, struct mail_cache *dst)
           that the fields are updated even if the cache was already created
           and no purging was done. */
        dst->field_header_write_pending = TRUE;
+       pool_unref(&pool);
        return mail_cache_purge(dst, 0, "copy cache decisions");
 }
index 5080bdef9a5576d954ab9e6224fc9c975eee2441..5a2e166795f0f1ad69ea622c522afc4b46c8f621 100644 (file)
@@ -223,7 +223,7 @@ mail_cache_register_get_field(struct mail_cache *cache, unsigned int field_idx)
 }
 
 struct mail_cache_field *
-mail_cache_register_get_list(struct mail_cache *cache, pool_t pool,
+mail_cache_register_get_list(struct mail_cache *cache, pool_t *pool_r,
                             unsigned int *count_r)
 {
         struct mail_cache_field *list;
@@ -232,11 +232,12 @@ mail_cache_register_get_list(struct mail_cache *cache, pool_t pool,
        if (!cache->opened)
                (void)mail_cache_open_and_verify(cache);
 
+       *pool_r = pool_alloconly_create("mail cache register fields", 1024);
        list = cache->fields_count == 0 ? NULL :
-               p_new(pool, struct mail_cache_field, cache->fields_count);
+               p_new(*pool_r, struct mail_cache_field, cache->fields_count);
        for (i = 0; i < cache->fields_count; i++) {
                list[i] = cache->fields[i].field;
-               list[i].name = p_strdup(pool, list[i].name);
+               list[i].name = p_strdup(*pool_r, list[i].name);
        }
 
        *count_r = cache->fields_count;
index 9adc9f5d56afe87b64eacd2845ffd0492819c7ae..795e0bcad5b9a3f1644c367adacf94d39a0b27b5 100644 (file)
@@ -86,9 +86,9 @@ mail_cache_register_lookup(struct mail_cache *cache, const char *name);
 /* Returns specified field */
 const struct mail_cache_field *
 mail_cache_register_get_field(struct mail_cache *cache, unsigned int field_idx);
-/* Returns a list of all registered fields */
+/* Returns a list of all registered fields. The returned pool must be freed. */
 struct mail_cache_field *
-mail_cache_register_get_list(struct mail_cache *cache, pool_t pool,
+mail_cache_register_get_list(struct mail_cache *cache, pool_t *pool_r,
                             unsigned int *count_r);
 
 /* Returns TRUE if cache should be purged. */
index a39392d5de93a953c68058c9106cf9cf37f6d439..4c7bcdd8d99a934fcbc5401124665ae34c746251 100644 (file)
@@ -180,10 +180,10 @@ static void index_mail_parse_header_register_all_wanted(struct index_mail *mail)
        struct mail *_mail = &mail->mail.mail;
        const struct mail_cache_field *all_cache_fields;
        unsigned int i, count;
+       pool_t pool;
 
        all_cache_fields =
-               mail_cache_register_get_list(_mail->box->cache,
-                                            pool_datastack_create(), &count);
+               mail_cache_register_get_list(_mail->box->cache, &pool, &count);
        for (i = 0; i < count; i++) {
                if (!str_begins_icase_with(all_cache_fields[i].name, "hdr."))
                        continue;
@@ -194,6 +194,7 @@ static void index_mail_parse_header_register_all_wanted(struct index_mail *mail)
                array_idx_set(&mail->header_match, all_cache_fields[i].idx,
                              &mail->header_match_value);
        }
+       pool_unref(&pool);
 }
 
 void index_mail_parse_header_init(struct index_mail *mail,
index b8a89dfa998d78308307cdc009d7a49faede3f9f..1685339ca79e8560ffe46696e01b0fb8a34351b4 100644 (file)
@@ -198,9 +198,9 @@ get_metadata_cache_fields(struct mailbox *box,
        ARRAY_TYPE(mailbox_cache_field) *cache_fields;
        struct mailbox_cache_field *cf;
        unsigned int i, count;
+       pool_t pool;
 
-       fields = mail_cache_register_get_list(box->cache,
-                                             pool_datastack_create(), &count);
+       fields = mail_cache_register_get_list(box->cache, &pool, &count);
 
        cache_fields = t_new(ARRAY_TYPE(mailbox_cache_field), 1);
        t_array_init(cache_fields, count);
@@ -208,12 +208,13 @@ get_metadata_cache_fields(struct mailbox *box,
                dec = fields[i].decision & ENUM_NEGATE(MAIL_CACHE_DECISION_FORCED);
                if (dec != MAIL_CACHE_DECISION_NO) {
                        cf = array_append_space(cache_fields);
-                       cf->name = fields[i].name;
+                       cf->name = t_strdup(fields[i].name);
                        cf->decision = fields[i].decision;
                        cf->last_used = fields[i].last_used;
                }
        }
        metadata_r->cache_fields = cache_fields;
+       pool_unref(&pool);
 }
 
 static void get_metadata_precache_fields(struct mailbox *box,
@@ -222,9 +223,9 @@ static void get_metadata_precache_fields(struct mailbox *box,
        const struct mail_cache_field *fields;
        unsigned int i, count;
        enum mail_fetch_field cache = 0;
+       pool_t pool;
 
-       fields = mail_cache_register_get_list(box->cache,
-                                             pool_datastack_create(), &count);
+       fields = mail_cache_register_get_list(box->cache, &pool, &count);
        for (i = 0; i < count; i++) {
                const char *name = fields[i].name;
 
@@ -259,6 +260,7 @@ static void get_metadata_precache_fields(struct mailbox *box,
                                "Ignoring unknown cache field: %s", name);
        }
        metadata_r->precache_fields = cache;
+       pool_unref(&pool);
 }
 
 static int
index 7590394b635075b41686224ff69b55ebba965eba..ac96d89c7d64eafbfe770c2bcc5784907babc0a1 100644 (file)
@@ -488,9 +488,9 @@ index_storage_mailbox_update_cache(struct mailbox *box,
        const struct mail_cache_field *old_fields;
        struct mail_cache_field field;
        unsigned int i, j, old_count;
+       pool_t pool;
 
-       old_fields = mail_cache_register_get_list(box->cache,
-                                                 pool_datastack_create(),
+       old_fields = mail_cache_register_get_list(box->cache, &pool,
                                                  &old_count);
 
        /* There shouldn't be many fields, so don't worry about O(n^2). */
@@ -524,6 +524,7 @@ index_storage_mailbox_update_cache(struct mailbox *box,
                                           array_count(&new_fields),
                                           unsafe_data_stack_pool);
        }
+       pool_unref(&pool);
 }
 
 static int
index a12f885143bee81ae5c2b23f3552e62c32546ee2..2217bf1bbb7476dd44545983596bd0f983896a9a 100644 (file)
@@ -223,6 +223,7 @@ static int maildir_get_pop3_state(struct index_mail *mail)
        enum mail_cache_decision_type dec, vsize_dec;
        enum mail_fetch_field allowed_pop3_fields;
        bool not_pop3_only = FALSE;
+       pool_t pool;
 
        if (mail->pop3_state_set)
                return mail->pop3_state;
@@ -247,8 +248,7 @@ static int maildir_get_pop3_state(struct index_mail *mail)
        } else {
                /* also check if there are any non-[pv]size cached fields */
                vsize_dec = MAIL_CACHE_DECISION_NO;
-               fields = mail_cache_register_get_list(box->cache,
-                                                     pool_datastack_create(),
+               fields = mail_cache_register_get_list(box->cache, &pool,
                                                      &count);
                for (i = 0; i < count; i++) {
                        dec = fields[i].decision & ENUM_NEGATE(MAIL_CACHE_DECISION_FORCED);
@@ -258,6 +258,7 @@ static int maildir_get_pop3_state(struct index_mail *mail)
                                 fields[i].idx != psize_idx)
                                not_pop3_only = TRUE;
                }
+               pool_unref(&pool);
        }
 
        if (index_mail_get_vsize_extension(&mail->mail.mail) != NULL) {