Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/lib-index/mail-index-sync-ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ int 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);
if (offset + size > ext->hdr_size) {
if (offset > ext->hdr_size || size > ext->hdr_size - offset) {
mail_index_sync_set_corrupted(ctx,
"Extension header update points outside header size");
return -1;
Expand Down
46 changes: 46 additions & 0 deletions src/lib-index/test-mail-index-sync-ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,56 @@ static void test_mail_index_sync_ext_atomic_inc(void)
test_end();
}

static void test_mail_index_sync_ext_hdr_update(void)
{
struct mail_index_sync_map_ctx ctx;
struct mail_index_ext *ext;
unsigned char data[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };

test_begin("mail index sync ext hdr update");

i_zero(&ctx);
ctx.view = t_new(struct mail_index_view, 1);
ctx.view->log_view = t_new(struct mail_transaction_log_view, 1);
ctx.view->index = t_new(struct mail_index, 1);
ctx.view->index->fsck_log_head_file_seq = 10; /* silence errors */
ctx.view->map = t_new(struct mail_index_map, 1);
ctx.view->map->hdr.header_size = 64;
ctx.view->map->hdr_copy_buf = buffer_create_dynamic(default_pool, 64);
buffer_append_zero(ctx.view->map->hdr_copy_buf, 64);

t_array_init(&ctx.view->map->extensions, 4);
ext = array_append_space(&ctx.view->map->extensions);
ext->index_idx = 5; /* != modseq_ext_id (0), skip modseq handling */
ext->hdr_offset = 16;
ext->hdr_size = 8;

ctx.cur_ext_map_idx = 0;

/* valid updates within the extension header */
test_assert(mail_index_sync_ext_hdr_update(&ctx, 0, 8, data) == 1);
test_assert(mail_index_sync_ext_hdr_update(&ctx, 4, 4, data) == 1);

/* ordinary out-of-range update is rejected */
test_assert(mail_index_sync_ext_hdr_update(&ctx, 4, 8, data) == -1);

/* offset+size wraps around 2^32 and must not pass the bounds check:
0xfffffff8 + 8 == 0, which is <= hdr_size */
test_assert(mail_index_sync_ext_hdr_update(&ctx, 0xfffffff8, 8,
data) == -1);
test_assert(mail_index_sync_ext_hdr_update(&ctx, 0xffffffff, 1,
data) == -1);

buffer_free(&ctx.view->map->hdr_copy_buf);
i_free(ctx.view->index->need_recreate);
test_end();
}

int main(void)
{
static void (*const test_functions[])(void) = {
test_mail_index_sync_ext_atomic_inc,
test_mail_index_sync_ext_hdr_update,
NULL
};
return test_run(test_functions);
Expand Down