Mercurial > dovecot > core-2.2
changeset 5721:18d7a680ffae HEAD
Added more corruption detection code.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 13 Jun 2007 21:35:14 +0300 |
parents | 5f4a7e932c4f |
children | 9c53047d3b2c |
files | src/lib-index/mail-index-sync-update.c src/lib-index/mail-transaction-log-view.c |
diffstat | 2 files changed, 54 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-index/mail-index-sync-update.c Wed Jun 13 21:34:16 2007 +0300 +++ b/src/lib-index/mail-index-sync-update.c Wed Jun 13 21:35:14 2007 +0300 @@ -593,7 +593,7 @@ rec = CONST_PTR_OFFSET(data, i); if (i + sizeof(*rec) + rec->name_size > hdr->size) { mail_index_sync_set_corrupted(ctx, - "extension intro: name_size too large"); + "ext intro: name_size too large"); ret = -1; break; } @@ -610,6 +610,13 @@ } case MAIL_TRANSACTION_EXT_RESET: { const struct mail_transaction_ext_reset *rec = data; + + if (hdr->size != sizeof(*rec)) { + mail_index_sync_set_corrupted(ctx, + "ext reset: invalid record size"); + ret = -1; + break; + } ret = mail_index_sync_ext_reset(ctx, rec); break; } @@ -619,6 +626,15 @@ for (i = 0; i < hdr->size; ) { rec = CONST_PTR_OFFSET(data, i); + + if (i + sizeof(*rec) > hdr->size || + i + sizeof(*rec) + rec->size > hdr->size) { + mail_index_sync_set_corrupted(ctx, + "ext hdr update: invalid record size"); + ret = -1; + break; + } + ret = mail_index_sync_ext_hdr_update(ctx, rec); if (ret <= 0) break; @@ -630,9 +646,9 @@ break; } case MAIL_TRANSACTION_EXT_REC_UPDATE: { - const struct mail_transaction_ext_rec_update *rec, *end; + const struct mail_transaction_ext_rec_update *rec; const struct mail_index_ext *ext; - unsigned int record_size; + unsigned int i, record_size; if (ctx->cur_ext_id == (uint32_t)-1) { mail_index_sync_set_corrupted(ctx, @@ -651,14 +667,19 @@ /* the record is padded to 32bits in the transaction log */ record_size = (sizeof(*rec) + ext->record_size + 3) & ~3; - rec = data; - end = CONST_PTR_OFFSET(data, hdr->size); - while (rec < end) { + for (i = 0; i < hdr->size; i += record_size) { + rec = CONST_PTR_OFFSET(data, i); + + if (i + record_size > hdr->size) { + mail_index_sync_set_corrupted(ctx, + "ext rec update: invalid record size"); + ret = -1; + break; + } + ret = mail_index_sync_ext_rec_update(ctx, rec); if (ret <= 0) break; - - rec = CONST_PTR_OFFSET(rec, record_size); } break; }
--- a/src/lib-index/mail-transaction-log-view.c Wed Jun 13 21:34:16 2007 +0300 +++ b/src/lib-index/mail-transaction-log-view.c Wed Jun 13 21:35:14 2007 +0300 @@ -349,12 +349,25 @@ return FALSE; } + if (rec_size == 0) { + mail_transaction_log_file_set_corrupted(file, + "Empty record contents (type=0x%x)", rec_type); + return FALSE; + } + /* records that are exported by syncing and view syncing will be checked here so that we don't have to implement the same validation multiple times. other records are checked internally by mail_index_sync_record(). */ t_push(); switch (rec_type) { + case MAIL_TRANSACTION_APPEND: + if ((rec_size % sizeof(struct mail_index_record)) != 0) { + mail_transaction_log_file_set_corrupted(file, + "Invalid append record size"); + ret = FALSE; + } + break; case MAIL_TRANSACTION_EXPUNGE: uid_buf = buffer_create_const_data(pool_datastack_create(), data, rec_size); @@ -375,8 +388,7 @@ if ((seqset_offset % 4) != 0) seqset_offset += 4 - (seqset_offset % 4); - if (seqset_offset >= rec_size || - ((rec_size - seqset_offset) % (sizeof(uint32_t)*2)) != 0) { + if (seqset_offset > rec_size) { mail_transaction_log_file_set_corrupted(file, "Invalid keyword update record size"); ret = FALSE; @@ -403,6 +415,17 @@ const struct seq_range *rec, *prev = NULL; unsigned int i, count = array_count(&uids); + if ((uid_buf->used % uids.arr.element_size) != 0) { + mail_transaction_log_file_set_corrupted(file, + "Invalid record size (type=0x%x)", rec_type); + ret = FALSE; + count = 0; + } else if (count == 0) { + mail_transaction_log_file_set_corrupted(file, + "No UID ranges (type=0x%x)", rec_type); + ret = FALSE; + } + for (i = 0; i < count; i++, prev = rec) { rec = array_idx(&uids, i); if (rec->seq1 > rec->seq2 || rec->seq1 == 0) {