]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Fixed crashes related to struct mail_index_map_modseq handling.
authorTimo Sirainen <tss@iki.fi>
Sun, 31 Aug 2008 08:02:13 +0000 (11:02 +0300)
committerTimo Sirainen <tss@iki.fi>
Sun, 31 Aug 2008 08:02:13 +0000 (11:02 +0300)
--HG--
branch : HEAD

src/lib-index/mail-index-map.c
src/lib-index/mail-index-modseq.c
src/lib-index/mail-index-modseq.h
src/lib-index/mail-index-sync-update.c
src/lib-index/mail-index-view-sync.c

index 27a231448ac8aba0880b9146f298e42b611f0ad2..891d1131c67bc0772911c94908d3258a51ad95da 100644 (file)
@@ -978,7 +978,7 @@ static void mail_index_record_map_free(struct mail_index_map *map,
        }
        array_free(&rec_map->maps);
        if (rec_map->modseq != NULL)
-               mail_index_map_modseq_free(rec_map->modseq);
+               mail_index_map_modseq_free(&rec_map->modseq);
        i_free(rec_map);
 }
 
@@ -991,8 +991,10 @@ static void mail_index_record_map_unlink(struct mail_index_map *map)
        for (i = 0; i < count; i++) {
                if (maps[i] == map) {
                        array_delete(&map->rec_map->maps, i, 1);
-                       if (i == 0 && count == 1)
+                       if (i == 0 && count == 1) {
                                mail_index_record_map_free(map, map->rec_map);
+                               map->rec_map = NULL;
+                       }
                        return;
                }
        }
@@ -1145,6 +1147,10 @@ void mail_index_record_map_move_to_private(struct mail_index_map *map)
        } else {
                new_map = map->rec_map;
        }
+       if (map->rec_map->modseq != NULL) {
+               new_map->modseq =
+                       mail_index_map_modseq_clone(map->rec_map->modseq);
+       }
 
        if (new_map->records_count != map->hdr.messages_count) {
                new_map->records_count = map->hdr.messages_count;
@@ -1168,8 +1174,13 @@ void mail_index_map_move_to_memory(struct mail_index_map *map)
 
        i_assert(map->rec_map->lock_id != 0);
 
-       new_map = array_count(&map->rec_map->maps) == 1 ? map->rec_map :
-               mail_index_record_map_alloc(map);
+       if (array_count(&map->rec_map->maps) == 1)
+               new_map = map->rec_map;
+       else {
+               new_map = mail_index_record_map_alloc(map);
+               new_map->modseq = map->rec_map->modseq == NULL ? NULL :
+                       mail_index_map_modseq_clone(map->rec_map->modseq);
+       }
 
        mail_index_map_copy_records(new_map, map->rec_map,
                                    map->hdr.record_size);
index d91f5438d083647035938207066ff61f507bc756..ecf66da76616011e03e0f1d52a8e0214cda1f4a1 100644 (file)
@@ -494,11 +494,18 @@ void mail_index_modseq_sync_end(struct mail_index_modseq_sync **_ctx)
        struct mail_index_modseq_sync *ctx = *_ctx;
 
        *_ctx = NULL;
-       if (ctx->mmap != NULL)
+       if (ctx->mmap != NULL) {
+               i_assert(ctx->mmap == ctx->view->map->rec_map->modseq);
                mail_index_modseq_update_header(ctx);
+       }
        i_free(ctx);
 }
 
+void mail_index_modseq_sync_map_replaced(struct mail_index_modseq_sync *ctx)
+{
+       ctx->mmap = mail_index_map_modseq(ctx->view);
+}
+
 void mail_index_modseq_hdr_update(struct mail_index_modseq_sync *ctx)
 {
        if (ctx->mmap == NULL) {
@@ -601,11 +608,27 @@ void mail_index_modseq_reset_keywords(struct mail_index_modseq_sync *ctx,
                modseqs_idx_update(ctx, i, seq1, seq2);
 }
 
-void mail_index_map_modseq_free(struct mail_index_map_modseq *mmap)
+struct mail_index_map_modseq *
+mail_index_map_modseq_clone(const struct mail_index_map_modseq *mmap)
 {
+       struct mail_index_map_modseq *new_mmap;
+
+       new_mmap = i_new(struct mail_index_map_modseq, 1);
+       i_array_init(&new_mmap->metadata_modseqs,
+                    array_count(&mmap->metadata_modseqs) + 16);
+       array_append_array(&new_mmap->metadata_modseqs,
+                          &mmap->metadata_modseqs);
+       return new_mmap;
+}
+
+void mail_index_map_modseq_free(struct mail_index_map_modseq **_mmap)
+{
+       struct mail_index_map_modseq *mmap = *_mmap;
        struct metadata_modseqs *metadata;
        unsigned int i, count;
 
+       *_mmap = NULL;
+
        metadata = array_get_modifiable(&mmap->metadata_modseqs, &count);
        for (i = 0; i < count; i++) {
                if (array_is_created(&metadata[i].modseqs))
index 58151171067838344d3eed6d7743ad2e938d7c30..98116b71d40ba1f0b1346db638348c3e81ec80ae 100644 (file)
@@ -40,6 +40,7 @@ struct mail_index_modseq_sync *
 mail_index_modseq_sync_begin(struct mail_index_sync_map_ctx *sync_map_ctx);
 void mail_index_modseq_sync_end(struct mail_index_modseq_sync **ctx);
 
+void mail_index_modseq_sync_map_replaced(struct mail_index_modseq_sync *ctx);
 void mail_index_modseq_hdr_update(struct mail_index_modseq_sync *ctx);
 void mail_index_modseq_append(struct mail_index_modseq_sync *ctx, uint32_t seq);
 void mail_index_modseq_expunge(struct mail_index_modseq_sync *ctx,
@@ -53,7 +54,9 @@ void mail_index_modseq_update_keyword(struct mail_index_modseq_sync *ctx,
 void mail_index_modseq_reset_keywords(struct mail_index_modseq_sync *ctx,
                                      uint32_t seq1, uint32_t seq2);
 
-void mail_index_map_modseq_free(struct mail_index_map_modseq *mmap);
+struct mail_index_map_modseq *
+mail_index_map_modseq_clone(const struct mail_index_map_modseq *mmap);
+void mail_index_map_modseq_free(struct mail_index_map_modseq **mmap);
 
 bool mail_index_modseq_get_next_log_offset(struct mail_index_view *view,
                                           uint64_t modseq, uint32_t *log_seq_r,
index 78298055c8480546dc8b94818e63f42241574ec1..b2f3156d0183293bd60021de69a30ff34ecab80d 100644 (file)
@@ -65,6 +65,8 @@ static void mail_index_sync_replace_map(struct mail_index_sync_map_ctx *ctx,
 
        if (ctx->type != MAIL_INDEX_SYNC_HANDLER_VIEW)
                view->index->map = map;
+
+       mail_index_modseq_sync_map_replaced(ctx->modseq_ctx);
 }
 
 static void
@@ -82,6 +84,7 @@ mail_index_sync_move_to_private_memory(struct mail_index_sync_map_ctx *ctx)
 
        if (!MAIL_INDEX_MAP_IS_IN_MEMORY(ctx->view->map))
                mail_index_map_move_to_memory(ctx->view->map);
+       mail_index_modseq_sync_map_replaced(ctx->modseq_ctx);
 }
 
 struct mail_index_map *
@@ -89,6 +92,7 @@ mail_index_sync_get_atomic_map(struct mail_index_sync_map_ctx *ctx)
 {
        mail_index_sync_move_to_private_memory(ctx);
        mail_index_record_map_move_to_private(ctx->view->map);
+       mail_index_modseq_sync_map_replaced(ctx->modseq_ctx);
        ctx->view->map->write_atomic = TRUE;
        return ctx->view->map;
 }
index ac1e60039224692461a6a838a229f0405f09e56f..b2ccc4ccb448fba1847f40682a62ec9fe615467f 100644 (file)
@@ -559,8 +559,6 @@ mail_index_view_sync_begin(struct mail_index_view *view,
                return ctx;
        }
 
-       mail_index_sync_map_init(&ctx->sync_map_ctx, view,
-                                MAIL_INDEX_SYNC_HANDLER_VIEW);
        if (ret == 0) {
                ctx->log_was_lost = TRUE;
                if (!sync_expunges)
@@ -629,6 +627,8 @@ mail_index_view_sync_begin(struct mail_index_view *view,
                        ctx->sync_new_map->refcount++;
                }
        }
+       mail_index_sync_map_init(&ctx->sync_map_ctx, view,
+                                MAIL_INDEX_SYNC_HANDLER_VIEW);
 
 #ifdef DEBUG
        mail_index_map_check(view->map);