From 4f182777356ff5a040d9a3ed8bf28da93375cbaa Mon Sep 17 00:00:00 2001 From: Enno Boland Date: Fri, 18 Aug 2023 12:33:44 +0200 Subject: [PATCH] reader: fix handling of when growing a reader When growing a reader that is in buffered mode, the offset was not updated correctly. This caused the reader to append overlapping data twice and therefore corrupting the data. This commit contains the fix as well as a test case for the metablock reader. Generalizing the test for the generic reader is left for later. --- lib/reader/reader.c | 5 +++- test/metablock/metablock_reader.c | 45 +++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/lib/reader/reader.c b/lib/reader/reader.c index 3d719957f..7a09d548b 100644 --- a/lib/reader/reader.c +++ b/lib/reader/reader.c @@ -156,7 +156,8 @@ handle_buffered(struct SqshReader *reader, sqsh_index_t offset, size_t size) { struct SqshBuffer *buffer = &reader->buffer; const uint8_t *buffer_data = sqsh__buffer_data(buffer); - const size_t copy_size = iterator_offset - offset; + size_t buffer_size = sqsh__buffer_size(buffer); + const size_t copy_size = buffer_size - offset; if (offset != 0) { rv = sqsh__buffer_init(&new_buffer); @@ -172,6 +173,8 @@ handle_buffered(struct SqshReader *reader, sqsh_index_t offset, size_t size) { goto out; } } + + reader->offset = buffer_size - iterator_offset; rv = reader_fill_buffer(reader, size); out: diff --git a/test/metablock/metablock_reader.c b/test/metablock/metablock_reader.c index 710695303..8b3e0fb7e 100644 --- a/test/metablock/metablock_reader.c +++ b/test/metablock/metablock_reader.c @@ -197,6 +197,50 @@ advance_overlapping_2(void) { sqsh__archive_cleanup(&sqsh); } +static void +advance_overlapping_3(void) { + int rv; + struct SqshArchive sqsh = {0}; + struct SqshMetablockReader cursor; + uint8_t payload[] = { + /* clang-format off */ + SQSH_HEADER, + [1024] = METABLOCK_HEADER(0, 8192), + [1024 + SQSH_SIZEOF_METABLOCK+8180] = + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + [1024 + SQSH_SIZEOF_METABLOCK + 8192] = METABLOCK_HEADER(0, 32 - 12), + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + /* clang-format on */ + }; + uint8_t expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}; + const uint8_t *data; + mk_stub(&sqsh, payload, sizeof(payload)); + + rv = sqsh__metablock_reader_init(&cursor, &sqsh, 1024, sizeof(payload)); + assert(rv == 0); + + rv = sqsh__metablock_reader_advance(&cursor, 8180, 16); + assert(rv == 0); + assert(sqsh__metablock_reader_size(&cursor) == 16); + data = sqsh__metablock_reader_data(&cursor); + assert(data != NULL); + assert(memcmp(data, expected, 16) == 0); + + rv = sqsh__metablock_reader_advance(&cursor, 0, 32); + assert(rv == 0); + assert(sqsh__metablock_reader_size(&cursor) == 32); + data = sqsh__metablock_reader_data(&cursor); + assert(data != NULL); + assert(memcmp(data, expected, 32) == 0); + + rv = sqsh__metablock_reader_cleanup(&cursor); + assert(rv == 0); + + sqsh__archive_cleanup(&sqsh); +} + static void advance_skip(void) { int rv; @@ -308,6 +352,7 @@ TEST(advance_once) TEST(advance_twice) TEST(advance_overlapping) TEST(advance_overlapping_2) +TEST(advance_overlapping_3) TEST(advance_skip) TEST(advance_skip_2) TEST(advance_overflow)