From: Timo Sirainen Date: Fri, 6 Mar 2009 21:17:39 +0000 (-0500) Subject: mail_index_atomic_inc_ext(): Added error checking. X-Git-Tag: 2.0.alpha1~1038^2~64 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=28f0b21ee66fe5a5cb961f6b3ae598c88d2eb5d3;p=thirdparty%2Fdovecot%2Fcore.git mail_index_atomic_inc_ext(): Added error checking. --HG-- branch : HEAD --- diff --git a/src/lib-index/mail-index-sync-ext.c b/src/lib-index/mail-index-sync-ext.c index 57d18222fb..8ebb074cec 100644 --- a/src/lib-index/mail-index-sync-ext.c +++ b/src/lib-index/mail-index-sync-ext.c @@ -696,6 +696,7 @@ mail_index_sync_ext_atomic_inc(struct mail_index_sync_map_ctx *ctx, const struct mail_index_ext *ext; void *data; uint32_t seq; + uint64_t orig_num; i_assert(ctx->cur_ext_map_idx != (uint32_t)-1); i_assert(!ctx->cur_ext_ignore); @@ -719,21 +720,26 @@ mail_index_sync_ext_atomic_inc(struct mail_index_sync_map_ctx *ctx, switch (ext->record_size) { case 1: { uint8_t *num = data; + + orig_num = *num; *num += u->diff; break; } case 2: { uint16_t *num = data; + orig_num = *num; *num += u->diff; break; } case 4: { uint32_t *num = data; + orig_num = *num; *num += u->diff; break; } case 8: { uint64_t *num = data; + orig_num = *num; *num += u->diff; break; } @@ -743,6 +749,14 @@ mail_index_sync_ext_atomic_inc(struct mail_index_sync_map_ctx *ctx, ext->record_size); return -1; } + if (u->diff < 0 && (uint32_t)(-u->diff) > orig_num) { + mail_index_sync_set_corrupted(ctx, + "Extension record inc drops number below zero " + "(uid=%u, diff=%d, orig=%llu)", + u->uid, u->diff, (unsigned long long)orig_num); + return -1; + } + mail_index_sync_write_seq_update(ctx, seq, seq); return 1; } diff --git a/src/lib-index/mail-index-transaction.c b/src/lib-index/mail-index-transaction.c index 1f349ab3e9..3d8a2d67c4 100644 --- a/src/lib-index/mail-index-transaction.c +++ b/src/lib-index/mail-index-transaction.c @@ -1357,6 +1357,9 @@ void mail_index_atomic_inc_ext(struct mail_index_transaction *t, uint32_t seq, (seq <= mail_index_view_get_messages_count(t->view) || seq <= t->last_new_seq)); i_assert(ext_id < array_count(&t->view->index->extensions)); + /* currently non-external transactions can be applied multiple times, + causing multiple increments. */ + i_assert((t->flags & MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL) != 0); t->log_ext_updates = TRUE; if (!array_is_created(&t->ext_rec_atomics))