From: Timo Sirainen Date: Tue, 27 Dec 2022 13:35:23 +0000 (-0500) Subject: lib-index, global: mail_cache_register_get_list() - Allocate results from a new pool X-Git-Tag: 2.4.0~3224 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7de50e217daa15476d208a050180a1cb26a11d9c;p=thirdparty%2Fdovecot%2Fcore.git lib-index, global: mail_cache_register_get_list() - Allocate results from a new pool The memory allocations can get large enough that it causes data stack to be grown. --- diff --git a/src/doveadm/doveadm-dump-index.c b/src/doveadm/doveadm-dump-index.c index 2f2e1b9fbc..dada1817d3 100644 --- a/src/doveadm/doveadm-dump-index.c +++ b/src/doveadm/doveadm-dump-index.c @@ -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) diff --git a/src/lib-index/mail-cache-decisions.c b/src/lib-index/mail-cache-decisions.c index a725ff640d..67ed143034 100644 --- a/src/lib-index/mail-cache-decisions.c +++ b/src/lib-index/mail-cache-decisions.c @@ -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"); } diff --git a/src/lib-index/mail-cache-fields.c b/src/lib-index/mail-cache-fields.c index 5080bdef9a..5a2e166795 100644 --- a/src/lib-index/mail-cache-fields.c +++ b/src/lib-index/mail-cache-fields.c @@ -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; diff --git a/src/lib-index/mail-cache.h b/src/lib-index/mail-cache.h index 9adc9f5d56..795e0bcad5 100644 --- a/src/lib-index/mail-cache.h +++ b/src/lib-index/mail-cache.h @@ -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. */ diff --git a/src/lib-storage/index/index-mail-headers.c b/src/lib-storage/index/index-mail-headers.c index a39392d5de..4c7bcdd8d9 100644 --- a/src/lib-storage/index/index-mail-headers.c +++ b/src/lib-storage/index/index-mail-headers.c @@ -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, diff --git a/src/lib-storage/index/index-status.c b/src/lib-storage/index/index-status.c index b8a89dfa99..1685339ca7 100644 --- a/src/lib-storage/index/index-status.c +++ b/src/lib-storage/index/index-status.c @@ -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 diff --git a/src/lib-storage/index/index-storage.c b/src/lib-storage/index/index-storage.c index 7590394b63..ac96d89c7d 100644 --- a/src/lib-storage/index/index-storage.c +++ b/src/lib-storage/index/index-storage.c @@ -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 diff --git a/src/lib-storage/index/maildir/maildir-mail.c b/src/lib-storage/index/maildir/maildir-mail.c index a12f885143..2217bf1bbb 100644 --- a/src/lib-storage/index/maildir/maildir-mail.c +++ b/src/lib-storage/index/maildir/maildir-mail.c @@ -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) {