Mercurial > dovecot > original-hg > dovecot-1.2
changeset 3688:1e6af9a000e6 HEAD
mail_cache_delete(): Make sure we don't get to infinite loop if cache
records contain a loop.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 28 Oct 2005 13:52:02 +0300 |
parents | 629ffe1a3874 |
children | 8b68997d6e34 |
files | src/lib-index/mail-cache-transaction.c |
diffstat | 1 files changed, 35 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-index/mail-cache-transaction.c Thu Oct 27 18:57:28 2005 +0300 +++ b/src/lib-index/mail-cache-transaction.c Fri Oct 28 13:52:02 2005 +0300 @@ -773,9 +773,24 @@ return 0; } +static int find_offset(array_t *array, uint32_t offset) +{ + ARRAY_SET_TYPE(array, uint32_t); + const uint32_t *offsets; + unsigned int i, count; + + offsets = array_get(array, &count); + for (i = 0; i < count; i++) { + if (offsets[i] == offset) + return TRUE; + } + return FALSE; +} + int mail_cache_delete(struct mail_cache *cache, uint32_t offset) { const struct mail_cache_record *cache_rec; + array_t ARRAY_DEFINE(tmp_offsets, uint32_t); i_assert(cache->locked); @@ -789,12 +804,29 @@ the data. also it's actually useful as some index views are still able to ask cached data from messages that have already been expunged. */ - do { + t_push(); + ARRAY_CREATE(&tmp_offsets, pool_datastack_create(), uint32_t, 8); + array_append(&tmp_offsets, &offset, 1); + for (;;) { cache->hdr_copy.deleted_space += cache_rec->size; if (mail_cache_get_record(cache, cache_rec->prev_offset, - &cache_rec) < 0) + &cache_rec) < 0) { + t_pop(); return -1; - } while (cache_rec != NULL); + } + + if (cache_rec == NULL) + break; + + if (find_offset(&tmp_offsets, cache_rec->prev_offset)) { + mail_cache_set_corrupted(cache, + "record list is circular"); + t_pop(); + return -1; + } + array_append(&tmp_offsets, &cache_rec->prev_offset, 1); + } + t_pop(); cache->hdr_modified = TRUE; return 0;