]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-index: Fixes to handling resized records.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 13 Jun 2016 22:14:13 +0000 (01:14 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 14 Jun 2016 09:34:09 +0000 (12:34 +0300)
src/lib-index/mail-index-sync-ext.c
src/lib-index/mail-index-sync-private.h
src/lib-index/mail-index-sync-update.c
src/lib-index/mail-index-transaction-export.c

index e758e53df3081cd0a0d85311546c93f39e8aa4a7..e6d475ba8b880e8b471c1a0488198999e12d7477 100644 (file)
@@ -478,6 +478,7 @@ int mail_index_sync_ext_intro(struct mail_index_sync_map_ctx *ctx,
           intro is corrupted */
        ctx->cur_ext_map_idx = (uint32_t)-2;
        ctx->cur_ext_ignore = TRUE;
+       ctx->cur_ext_record_size = 0;
 
        if (u->ext_id != (uint32_t)-1 &&
            (!array_is_created(&map->extensions) ||
@@ -537,6 +538,7 @@ int mail_index_sync_ext_intro(struct mail_index_sync_map_ctx *ctx,
                return -1;
        }
 
+       ctx->cur_ext_record_size = u->record_size;
        if (ext != NULL) {
                /* exists already */
                if (u->reset_id == ext->reset_id) {
@@ -675,7 +677,7 @@ mail_index_sync_ext_rec_update(struct mail_index_sync_map_ctx *ctx,
                return 1;
 
        ext = array_idx(&view->map->extensions, ctx->cur_ext_map_idx);
-       i_assert(ext->record_offset + ext->record_size <=
+       i_assert(ext->record_offset + ctx->cur_ext_record_size <=
                 view->map->hdr.record_size);
 
        rec = MAIL_INDEX_REC_AT_SEQ(view->map, seq);
@@ -696,7 +698,11 @@ mail_index_sync_ext_rec_update(struct mail_index_sync_map_ctx *ctx,
        }
 
        /* @UNSAFE */
-       memcpy(old_data, u + 1, ext->record_size);
+       memcpy(old_data, u + 1, ctx->cur_ext_record_size);
+       if (ctx->cur_ext_record_size < ext->record_size) {
+               memset(PTR_OFFSET(old_data, ctx->cur_ext_record_size), 0,
+                      ext->record_size - ctx->cur_ext_record_size);
+       }
        return 1;
 }
 
@@ -724,7 +730,7 @@ mail_index_sync_ext_atomic_inc(struct mail_index_sync_map_ctx *ctx,
                return 1;
 
        ext = array_idx(&view->map->extensions, ctx->cur_ext_map_idx);
-       i_assert(ext->record_offset + ext->record_size <=
+       i_assert(ext->record_offset + ctx->cur_ext_record_size <=
                 view->map->hdr.record_size);
 
        rec = MAIL_INDEX_REC_AT_SEQ(view->map, seq);
@@ -732,8 +738,8 @@ mail_index_sync_ext_atomic_inc(struct mail_index_sync_map_ctx *ctx,
 
        min_value = u->diff >= 0 ? 0 : (uint64_t)(-(int64_t)u->diff);
 
-       max_value = ext->record_size == 8 ? (uint64_t)-1 :
-               ((uint64_t)1 << (ext->record_size*8)) - 1;
+       max_value = ctx->cur_ext_record_size == 8 ? (uint64_t)-1 :
+               ((uint64_t)1 << (ctx->cur_ext_record_size*8)) - 1;
        if (u->diff <= 0) {
                /* skip */
        } else if (max_value >= (uint32_t)u->diff) {
@@ -745,7 +751,7 @@ mail_index_sync_ext_atomic_inc(struct mail_index_sync_map_ctx *ctx,
                return -1;
        }
 
-       switch (ext->record_size) {
+       switch (ctx->cur_ext_record_size) {
        case 1: {
                uint8_t *num = data;
 
@@ -778,7 +784,7 @@ mail_index_sync_ext_atomic_inc(struct mail_index_sync_map_ctx *ctx,
        default:
                mail_index_sync_set_corrupted(ctx,
                        "Extension record inc with invalid size=%u",
-                       ext->record_size);
+                       ctx->cur_ext_record_size);
                return -1;
        }
        if (orig_num < min_value) {
index 5ef8293208faeb3def548fe943643cdda1862da3..985c8da2b776766097c1edb901db75456f19c618 100644 (file)
@@ -27,6 +27,7 @@ struct mail_index_sync_map_ctx {
        struct mail_index_view *view;
        struct mail_index_modseq_sync *modseq_ctx;
        uint32_t cur_ext_map_idx;
+       uint32_t cur_ext_record_size;
 
        uint32_t ext_intro_seq;
        uoff_t ext_intro_offset, ext_intro_end_offset;
index 0e0edee624fb79783ba91f43c50d669e89b73d72..05d33bc2bbc1ef00988c279816adc121c960d36b 100644 (file)
@@ -712,7 +712,6 @@ mail_index_sync_record_real(struct mail_index_sync_map_ctx *ctx,
        }
        case MAIL_TRANSACTION_EXT_REC_UPDATE: {
                const struct mail_transaction_ext_rec_update *rec;
-               const struct mail_index_ext *ext;
                unsigned int i, record_size;
 
                if (ctx->cur_ext_map_idx == (uint32_t)-1) {
@@ -728,10 +727,8 @@ mail_index_sync_record_real(struct mail_index_sync_map_ctx *ctx,
                        break;
                }
 
-               ext = array_idx(&ctx->view->map->extensions,
-                               ctx->cur_ext_map_idx);
                /* the record is padded to 32bits in the transaction log */
-               record_size = (sizeof(*rec) + ext->record_size + 3) & ~3;
+               record_size = (sizeof(*rec) + ctx->cur_ext_record_size + 3) & ~3;
 
                for (i = 0; i < hdr->size; i += record_size) {
                        rec = CONST_PTR_OFFSET(data, i);
index 1996c80c900fc73b110f92d4a3a790809786a4e6..f846c891f1c00c79cc291a3d0aeeecde43a63af9 100644 (file)
@@ -138,16 +138,14 @@ static void log_append_ext_intro(struct mail_index_export_context *ctx,
                /* generate a new intro structure */
                intro = buffer_append_space_unsafe(buf, sizeof(*intro));
                intro->ext_id = idx;
+               intro->record_size = rext->record_size;
+               intro->record_align = rext->record_align;
                if (idx == (uint32_t)-1) {
                        intro->hdr_size = rext->hdr_size;
-                       intro->record_size = rext->record_size;
-                       intro->record_align = rext->record_align;
                        intro->name_size = strlen(rext->name);
                } else {
                        ext = array_idx(&t->view->index->map->extensions, idx);
                        intro->hdr_size = ext->hdr_size;
-                       intro->record_size = ext->record_size;
-                       intro->record_align = ext->record_align;
                        intro->name_size = 0;
                }
                intro->flags = MAIL_TRANSACTION_EXT_INTRO_FLAG_NO_SHRINK;