]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
mail_index_update_header_ext(): Couldn't handle >=64k headers.
authorTimo Sirainen <tss@iki.fi>
Thu, 19 Nov 2009 23:45:21 +0000 (18:45 -0500)
committerTimo Sirainen <tss@iki.fi>
Thu, 19 Nov 2009 23:45:21 +0000 (18:45 -0500)
--HG--
branch : HEAD

src/doveadm/doveadm-dump-log.c
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
src/lib-index/mail-transaction-log.h

index a0a1135ccb54baa5477046bce8ee9a05547fd28c..bc84cace3cb419850240531a9675e4efdad013c7 100644 (file)
@@ -88,6 +88,9 @@ static const char *log_record_type(unsigned int type)
        case MAIL_TRANSACTION_EXT_HDR_UPDATE:
                name = "ext-hdr";
                break;
+       case MAIL_TRANSACTION_EXT_HDR_UPDATE32:
+               name = "ext-hdr32";
+               break;
        case MAIL_TRANSACTION_EXT_REC_UPDATE:
                name = "ext-rec";
                break;
@@ -323,6 +326,14 @@ static void log_record_print(const struct mail_transaction_header *hdr,
                printf("\n");
                break;
        }
+       case MAIL_TRANSACTION_EXT_HDR_UPDATE32: {
+               const struct mail_transaction_ext_hdr_update32 *u = data;
+
+               printf(" - offset = %u, size = %u: ", u->offset, u->size);
+               print_data(u + 1, u->size);
+               printf("\n");
+               break;
+       }
        case MAIL_TRANSACTION_EXT_REC_UPDATE: {
                const struct mail_transaction_ext_rec_update *rec = data, *end;
                size_t record_size;
index 0d9621f0914da35af1a8e253dd29c025fdbf1520..06d17f9e52427db0952e87d483cf3679e31449e4 100644 (file)
@@ -603,9 +603,9 @@ int mail_index_sync_ext_reset(struct mail_index_sync_map_ctx *ctx,
        return 1;
 }
 
-int
-mail_index_sync_ext_hdr_update(struct mail_index_sync_map_ctx *ctx,
-                              const struct mail_transaction_ext_hdr_update *u)
+int mail_index_sync_ext_hdr_update(struct mail_index_sync_map_ctx *ctx,
+                                  uint32_t offset, uint32_t size,
+                                  const void *data)
 {
        struct mail_index_map *map = ctx->view->map;
         const struct mail_index_ext *ext;
@@ -619,10 +619,9 @@ mail_index_sync_ext_hdr_update(struct mail_index_sync_map_ctx *ctx,
                return 1;
 
        ext = array_idx(&map->extensions, ctx->cur_ext_map_idx);
-       i_assert(ext->hdr_offset + u->offset + u->size <= map->hdr.header_size);
+       i_assert(ext->hdr_offset + offset + size <= map->hdr.header_size);
 
-       buffer_write(map->hdr_copy_buf, ext->hdr_offset + u->offset,
-                    u + 1, u->size);
+       buffer_write(map->hdr_copy_buf, ext->hdr_offset + offset, data, size);
        map->hdr_base = map->hdr_copy_buf->data;
 
        if (ext->index_idx == ctx->view->index->modseq_ext_id)
index 328fa34f749c0e2c85fb325d69ebdef827eb7542..147b421b10d532a7e54a97ed396bf8342c0f35f6 100644 (file)
@@ -76,9 +76,9 @@ int mail_index_sync_ext_intro(struct mail_index_sync_map_ctx *ctx,
                              const struct mail_transaction_ext_intro *u);
 int mail_index_sync_ext_reset(struct mail_index_sync_map_ctx *ctx,
                              const struct mail_transaction_ext_reset *u);
-int
-mail_index_sync_ext_hdr_update(struct mail_index_sync_map_ctx *ctx,
-                              const struct mail_transaction_ext_hdr_update *u);
+int mail_index_sync_ext_hdr_update(struct mail_index_sync_map_ctx *ctx,
+                                  uint32_t offset, uint32_t size,
+                                  const void *data);
 int
 mail_index_sync_ext_rec_update(struct mail_index_sync_map_ctx *ctx,
                               const struct mail_transaction_ext_rec_update *u);
index 0a9f07f174d5b338a29c141f942a4a07ad07e39f..dee6f6b9c0aef8db8159c225727c4f82a11f7ef2 100644 (file)
@@ -687,7 +687,34 @@ int mail_index_sync_record(struct mail_index_sync_map_ctx *ctx,
                                break;
                        }
 
-                       ret = mail_index_sync_ext_hdr_update(ctx, rec);
+                       ret = mail_index_sync_ext_hdr_update(ctx, rec->offset,
+                                                            rec->size, rec + 1);
+                       if (ret <= 0)
+                               break;
+
+                       i += sizeof(*rec) + rec->size;
+                       if ((i % 4) != 0)
+                               i += 4 - (i % 4);
+               }
+               break;
+       }
+       case MAIL_TRANSACTION_EXT_HDR_UPDATE32: {
+               const struct mail_transaction_ext_hdr_update32 *rec = data;
+               unsigned int i;
+
+               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->offset,
+                                                            rec->size, rec + 1);
                        if (ret <= 0)
                                break;
 
index 212e7bd7757cc3ab2d75a296626605bd1540afc6..5da8754fd82e09cf554390afb8651a1538738bd6 100644 (file)
@@ -130,10 +130,12 @@ log_append_ext_hdr_update(struct mail_index_export_context *ctx,
        buffer_t *buf;
        const unsigned char *data, *mask;
        struct mail_transaction_ext_hdr_update u;
-       uint16_t offset;
-       bool started = FALSE;
+       struct mail_transaction_ext_hdr_update32 u32;
+       size_t offset;
+       bool started = FALSE, use_32 = hdr->alloc_size >= 65536;
 
        memset(&u, 0, sizeof(u));
+       memset(&u32, 0, sizeof(u32));
 
        data = hdr->data;
        mask = hdr->mask;
@@ -142,21 +144,28 @@ log_append_ext_hdr_update(struct mail_index_export_context *ctx,
        for (offset = 0; offset <= hdr->alloc_size; offset++) {
                if (offset < hdr->alloc_size && mask[offset] != 0) {
                        if (!started) {
-                               u.offset = offset;
+                               u32.offset = offset;
                                started = TRUE;
                        }
                } else {
                        if (started) {
-                               u.size = offset - u.offset;
-                               buffer_append(buf, &u, sizeof(u));
-                               buffer_append(buf, data + u.offset, u.size);
+                               u32.size = offset - u32.offset;
+                               if (use_32)
+                                       buffer_append(buf, &u32, sizeof(u32));
+                               else {
+                                       u.offset = u32.offset;
+                                       u.size = u32.size;
+                                       buffer_append(buf, &u, sizeof(u));
+                               }
+                               buffer_append(buf, data + u32.offset, u32.size);
                                started = FALSE;
                        }
                }
        }
        if (buf->used % 4 != 0)
                buffer_append_zero(buf, 4 - buf->used % 4);
-       log_append_buffer(ctx, buf, MAIL_TRANSACTION_EXT_HDR_UPDATE);
+       log_append_buffer(ctx, buf, use_32 ? MAIL_TRANSACTION_EXT_HDR_UPDATE32 :
+                         MAIL_TRANSACTION_EXT_HDR_UPDATE);
 }
 
 static void
index 3f783fe3f8a32ae0db501d84415272dda166cd25..5c0e1d96fd1a5e2152d81f8bd5c5cdf72cf2f153 100644 (file)
@@ -41,6 +41,7 @@ enum mail_transaction_type {
        MAIL_TRANSACTION_EXPUNGE_GUID           = 0x00002000,
        MAIL_TRANSACTION_UID_UPDATE             = 0x00004000,
        MAIL_TRANSACTION_MODSEQ_UPDATE          = 0x00008000,
+       MAIL_TRANSACTION_EXT_HDR_UPDATE32       = 0x00010000,
 
        MAIL_TRANSACTION_TYPE_MASK              = 0x0000ffff,
 
@@ -141,6 +142,14 @@ struct mail_transaction_ext_hdr_update {
        uint16_t size;
        /* unsigned char data[]; */
 };
+/* this _update32 version should have been the only ext_hdr_update,
+   but since 16bit integers were originally used for now we'll just use this
+   only when actually needed to be backwards compatible. */
+struct mail_transaction_ext_hdr_update32 {
+       uint32_t offset;
+       uint32_t size;
+       /* unsigned char data[]; */
+};
 
 struct mail_transaction_ext_rec_update {
        uint32_t uid;