From 17099d7323c795315689623f05ee870714441d63 Mon Sep 17 00:00:00 2001 From: Enno Boland Date: Mon, 12 Aug 2024 17:33:20 +0200 Subject: [PATCH] reader: make offset uint64_t instead of platform dependend sqsh_index_t --- common/include/sqsh_reader_private.h | 6 +-- common/src/reader/reader.c | 13 +++-- doc/guide.md | 2 +- fuzzer/simple.c | 2 +- include/sqsh_file.h | 62 +++++++++++++++++++++- libsqsh/include/sqsh_mapper_private.h | 4 +- libsqsh/include/sqsh_metablock_private.h | 4 +- libsqsh/src/file/file_iterator.c | 12 ++++- libsqsh/src/file/file_reader.c | 10 +++- libsqsh/src/mapper/map_iterator.c | 12 +++-- libsqsh/src/mapper/map_reader.c | 4 +- libsqsh/src/metablock/metablock_iterator.c | 2 +- libsqsh/src/metablock/metablock_reader.c | 5 +- test/libsqsh/reader/reader.c | 2 +- tools/src/fs-common.c | 2 +- 15 files changed, 108 insertions(+), 34 deletions(-) diff --git a/common/include/sqsh_reader_private.h b/common/include/sqsh_reader_private.h index cc8a67d7..304ddd99 100644 --- a/common/include/sqsh_reader_private.h +++ b/common/include/sqsh_reader_private.h @@ -48,7 +48,7 @@ extern "C" { struct SqshReaderIteratorImpl { bool (*next)(void *iterator, size_t desired_size, int *err); - int (*skip)(void *iterator, sqsh_index_t *offset, size_t desired_size); + int (*skip)(void *iterator, uint64_t *offset, size_t desired_size); const uint8_t *(*data)(const void *iterator); size_t (*size)(const void *iterator); }; @@ -151,8 +151,8 @@ SQSH_NO_EXPORT SQSH_NO_UNUSED int sqsh__reader_init( * * @return 0 on success, less than zero on error. */ -SQSH_NO_EXPORT SQSH_NO_UNUSED int sqsh__reader_advance( - struct SqshReader *reader, sqsh_index_t offset, size_t size); +SQSH_NO_EXPORT SQSH_NO_UNUSED int +sqsh__reader_advance(struct SqshReader *reader, uint64_t offset, size_t size); /** * @internal diff --git a/common/src/reader/reader.c b/common/src/reader/reader.c index 3ec16f21..91ed56cf 100644 --- a/common/src/reader/reader.c +++ b/common/src/reader/reader.c @@ -119,7 +119,7 @@ reader_fill_buffer(struct SqshReader *reader, size_t size) { } static int -handle_buffered(struct SqshReader *reader, sqsh_index_t offset, size_t size) { +handle_buffered(struct SqshReader *reader, uint64_t offset, size_t size) { int rv = 0; struct CxBuffer new_buffer = {0}; sqsh_index_t iterator_offset = reader->iterator_offset; @@ -127,7 +127,7 @@ handle_buffered(struct SqshReader *reader, sqsh_index_t offset, size_t size) { struct CxBuffer *buffer = &reader->buffer; const uint8_t *buffer_data = cx_buffer_data(buffer); size_t buffer_size = cx_buffer_size(buffer); - const size_t copy_size = buffer_size - offset; + const size_t copy_size = buffer_size - (size_t)offset; if (offset != 0) { rv = cx_buffer_init(&new_buffer); @@ -152,7 +152,7 @@ handle_buffered(struct SqshReader *reader, sqsh_index_t offset, size_t size) { } static int -handle_mapped(struct SqshReader *reader, sqsh_index_t offset, size_t size) { +handle_mapped(struct SqshReader *reader, uint64_t offset, size_t size) { int rv = 0; void *iterator = reader->iterator; const struct SqshReaderIteratorImpl *impl = reader->iterator_impl; @@ -168,8 +168,8 @@ handle_mapped(struct SqshReader *reader, sqsh_index_t offset, size_t size) { } reader->iterator_size = impl->size(iterator); - reader->offset = offset; - sqsh_index_t end_offset; + reader->offset = (size_t)offset; + size_t end_offset; if (SQSH_ADD_OVERFLOW(offset, size, &end_offset)) { rv = -SQSH_ERROR_INTEGER_OVERFLOW; goto out; @@ -189,8 +189,7 @@ handle_mapped(struct SqshReader *reader, sqsh_index_t offset, size_t size) { } int -sqsh__reader_advance( - struct SqshReader *reader, sqsh_index_t offset, size_t size) { +sqsh__reader_advance(struct SqshReader *reader, uint64_t offset, size_t size) { if (offset >= reader->iterator_offset) { offset -= reader->iterator_offset; reader->iterator_offset = 0; diff --git a/doc/guide.md b/doc/guide.md index 6f7d3c8e..14a4b29a 100644 --- a/doc/guide.md +++ b/doc/guide.md @@ -96,7 +96,7 @@ struct SqshFile *file = sqsh_open(archive, "/path/to/file.txt", &err); assert(err == 0); struct SqshFileReader *reader = sqsh_file_reader_new(file, &err); assert(err == 0); -err = sqsh_file_reader_advance(reader, 0, 10); +err = sqsh_file_reader_advance2(reader, 0, 10); assert(err == 0); const uint8_t *data = sqsh_file_reader_data(reader); diff --git a/fuzzer/simple.c b/fuzzer/simple.c index a5a11659..227afc63 100644 --- a/fuzzer/simple.c +++ b/fuzzer/simple.c @@ -36,7 +36,7 @@ read_file(const struct SqshTreeTraversal *traversal) { if (chunk_size > size) { chunk_size = size; } - rv = sqsh_file_reader_advance(file, advance, chunk_size); + rv = sqsh_file_reader_advance2(file, advance, chunk_size); if (rv < 0) { goto out; } diff --git a/include/sqsh_file.h b/include/sqsh_file.h index cbaca5cf..1eacb500 100644 --- a/include/sqsh_file.h +++ b/include/sqsh_file.h @@ -66,6 +66,7 @@ struct SqshFileReader * sqsh_file_reader_new(const struct SqshFile *file, int *err); /** + * @deprecated Since 1.5.0. Use sqsh_file_reader_advance2() instead. * @brief Advances the file reader by a certain amount of data and presents * `size` bytes of data to the user. * @memberof SqshFileReader @@ -76,9 +77,25 @@ sqsh_file_reader_new(const struct SqshFile *file, int *err); * * @return 0 on success, less than 0 on error. */ -int sqsh_file_reader_advance( +__attribute__((deprecated( + "Since 1.5.0. Use sqsh_file_reader_advance2() instead."))) int +sqsh_file_reader_advance( struct SqshFileReader *reader, sqsh_index_t offset, size_t size); +/** + * @brief Advances the file reader by a certain amount of data and presents + * `size` bytes of data to the user. + * @memberof SqshFileReader + * + * @param[in,out] reader The file reader to skip data in. + * @param[in] offset The offset to skip. + * @param[in] size The size of the data to skip. + * + * @return 0 on success, less than 0 on error. + */ +int sqsh_file_reader_advance2( + struct SqshFileReader *reader, uint64_t offset, size_t size); + /** * @brief Gets a pointer to the current data in the file reader. * @memberof SqshFileReader @@ -145,6 +162,7 @@ SQSH_NO_UNUSED bool sqsh_file_iterator_next( struct SqshFileIterator *iterator, size_t desired_size, int *err); /** + * @deprecated Since 1.5.0. Use sqsh_file_iterator_skip2() instead. * @memberof SqshFileIterator * @brief Skips blocks until the block containing the offset is reached. * Note that calling this function will invalidate the data pointer returned by @@ -177,10 +195,50 @@ SQSH_NO_UNUSED bool sqsh_file_iterator_next( * * @return 0 on success, less than 0 on error. */ -SQSH_NO_UNUSED int sqsh_file_iterator_skip( +__attribute__(( + deprecated("Since 1.5.0. Use sqsh_file_iterator_skip2() instead."))) +SQSH_NO_UNUSED int +sqsh_file_iterator_skip( struct SqshFileIterator *iterator, sqsh_index_t *offset, size_t desired_size); +/** + * @memberof SqshFileIterator + * @brief Skips blocks until the block containing the offset is reached. + * Note that calling this function will invalidate the data pointer returned by + * sqsh_file_iterator_data(). + * + * The offset is relative to the beginning of the current block or, if the + * iterator hasn't been forwarded with previous calls to + * sqsh_file_iterator_skip() or sqsh_file_iterator_next() the beginning of the + * first block. + * + * After calling this function `offset` is updated to the same position relative + * to the new block. See this visualisation: + * + * ``` + * current_block: |<--- block 8000 --->| + * offset = 10000 --^ + * --> sqsh_file_iterator_skip(i, &offset, 1) + * current_block: |<--- block 8000 --->| + * offset = 2000 --^ + * ``` + * + * If libsqsh can map more than one block at once, it will do so until + * `desired_size` is reached. Note that `desired_size` is only a hint and + * libsqsh may return more or less data than requested. + * + * @param[in,out] iterator The file iterator to skip data in. + * @param[in,out] offset The offset that is contained in the block to + * skip to. + * @param[in] desired_size The desired size of the data to read. + * + * @return 0 on success, less than 0 on error. + */ +SQSH_NO_UNUSED int sqsh_file_iterator_skip2( + struct SqshFileIterator *iterator, uint64_t *offset, + size_t desired_size); + /** * @brief Gets a pointer to the current data in the file iterator. * @memberof SqshFileIterator diff --git a/libsqsh/include/sqsh_mapper_private.h b/libsqsh/include/sqsh_mapper_private.h index 658541c6..882867c7 100644 --- a/libsqsh/include/sqsh_mapper_private.h +++ b/libsqsh/include/sqsh_mapper_private.h @@ -326,7 +326,7 @@ sqsh__map_iterator_next(struct SqshMapIterator *iterator, int *err); * @return 0 on success, less than 0 on error. */ SQSH_NO_EXPORT SQSH_NO_UNUSED int -sqsh__map_iterator_skip(struct SqshMapIterator *iterator, sqsh_index_t *offset); +sqsh__map_iterator_skip(struct SqshMapIterator *iterator, uint64_t *offset); /** * @internal @@ -437,7 +437,7 @@ sqsh__map_reader_address(const struct SqshMapReader *reader); * @return 0 on success, negative on error */ SQSH_NO_EXPORT SQSH_NO_UNUSED int sqsh__map_reader_advance( - struct SqshMapReader *reader, sqsh_index_t offset, size_t size); + struct SqshMapReader *reader, uint64_t offset, size_t size); /** * @internal diff --git a/libsqsh/include/sqsh_metablock_private.h b/libsqsh/include/sqsh_metablock_private.h index f48e7822..bf1b7936 100644 --- a/libsqsh/include/sqsh_metablock_private.h +++ b/libsqsh/include/sqsh_metablock_private.h @@ -106,7 +106,7 @@ sqsh__metablock_iterator_next(struct SqshMetablockIterator *iterator, int *err); * @return 0 on success, less than 0 on error. */ SQSH_NO_EXPORT SQSH_NO_UNUSED int sqsh__metablock_iterator_skip( - struct SqshMetablockIterator *iterator, sqsh_index_t *offset); + struct SqshMetablockIterator *iterator, uint64_t *offset); /** * @internal @@ -184,7 +184,7 @@ SQSH_NO_EXPORT SQSH_NO_UNUSED int sqsh__metablock_reader_init( * @return 0 on success, less than zero on error. */ SQSH_NO_EXPORT SQSH_NO_UNUSED int sqsh__metablock_reader_advance( - struct SqshMetablockReader *reader, sqsh_index_t offset, size_t size); + struct SqshMetablockReader *reader, uint64_t offset, size_t size); /** * @internal diff --git a/libsqsh/src/file/file_iterator.c b/libsqsh/src/file/file_iterator.c index ae2556de..608fa35d 100644 --- a/libsqsh/src/file/file_iterator.c +++ b/libsqsh/src/file/file_iterator.c @@ -305,6 +305,16 @@ int sqsh_file_iterator_skip( struct SqshFileIterator *iterator, sqsh_index_t *offset, size_t desired_size) { + uint64_t offset64 = *offset; + int rv = sqsh_file_iterator_skip2(iterator, &offset64, desired_size); + *offset = (size_t)offset64; + return rv; +} + +int +sqsh_file_iterator_skip2( + struct SqshFileIterator *iterator, uint64_t *offset, + size_t desired_size) { int rv = 0; const size_t block_size = iterator->block_size; const size_t current_block_size = sqsh_file_iterator_size(iterator); @@ -315,7 +325,7 @@ sqsh_file_iterator_skip( *offset -= current_block_size; - sqsh_index_t skip_index = *offset / block_size; + uint64_t skip_index = *offset / block_size; if (current_block_size != 0) { skip_index += 1; } diff --git a/libsqsh/src/file/file_reader.c b/libsqsh/src/file/file_reader.c index 3f6fdbbc..ce197b6d 100644 --- a/libsqsh/src/file/file_reader.c +++ b/libsqsh/src/file/file_reader.c @@ -44,8 +44,8 @@ file_iterator_next(void *iterator, size_t desired_size, int *err) { return sqsh_file_iterator_next(iterator, desired_size, err); } static int -file_iterator_skip(void *iterator, sqsh_index_t *offset, size_t desired_size) { - return sqsh_file_iterator_skip(iterator, offset, desired_size); +file_iterator_skip(void *iterator, uint64_t *offset, size_t desired_size) { + return sqsh_file_iterator_skip2(iterator, offset, desired_size); } static const uint8_t * file_iterator_data(const void *iterator) { @@ -88,6 +88,12 @@ sqsh_file_reader_advance( return sqsh__reader_advance(&reader->reader, offset, size); } +int +sqsh_file_reader_advance2( + struct SqshFileReader *reader, uint64_t offset, size_t size) { + return sqsh__reader_advance(&reader->reader, offset, size); +} + const uint8_t * sqsh_file_reader_data(const struct SqshFileReader *reader) { return sqsh__reader_data(&reader->reader); diff --git a/libsqsh/src/mapper/map_iterator.c b/libsqsh/src/mapper/map_iterator.c index 777fcd9e..f159e6c9 100644 --- a/libsqsh/src/mapper/map_iterator.c +++ b/libsqsh/src/mapper/map_iterator.c @@ -68,12 +68,10 @@ sqsh__map_iterator_init( return 0; } -#include int -sqsh__map_iterator_skip( - struct SqshMapIterator *iterator, sqsh_index_t *offset) { +sqsh__map_iterator_skip(struct SqshMapIterator *iterator, uint64_t *offset) { int rv = 0; - sqsh_index_t index; + uint64_t index; size_t block_size = sqsh__map_manager_block_size(iterator->map_manager); size_t current_size = sqsh__map_iterator_size(iterator); @@ -88,8 +86,12 @@ sqsh__map_iterator_skip( */ index--; } + if (index > SIZE_MAX) { + rv = -SQSH_ERROR_INTEGER_OVERFLOW; + goto out; + } - iterator->next_index = index; + iterator->next_index = (size_t)index; bool has_next = sqsh__map_iterator_next(iterator, &rv); if (rv < 0) { goto out; diff --git a/libsqsh/src/mapper/map_reader.c b/libsqsh/src/mapper/map_reader.c index c88bdd85..79feb728 100644 --- a/libsqsh/src/mapper/map_reader.c +++ b/libsqsh/src/mapper/map_reader.c @@ -42,7 +42,7 @@ map_iterator_next(void *iterator, size_t desired_size, int *err) { return sqsh__map_iterator_next(iterator, err); } static int -map_iterator_skip(void *iterator, sqsh_index_t *offset, size_t desired_size) { +map_iterator_skip(void *iterator, uint64_t *offset, size_t desired_size) { (void)desired_size; return sqsh__map_iterator_skip(iterator, offset); } @@ -110,7 +110,7 @@ sqsh__map_reader_address(const struct SqshMapReader *reader) { int sqsh__map_reader_advance( - struct SqshMapReader *reader, sqsh_index_t offset, size_t size) { + struct SqshMapReader *reader, uint64_t offset, size_t size) { reader->address += offset; return sqsh__reader_advance(&reader->reader, offset, size); } diff --git a/libsqsh/src/metablock/metablock_iterator.c b/libsqsh/src/metablock/metablock_iterator.c index 82c40e94..f20ce8c9 100644 --- a/libsqsh/src/metablock/metablock_iterator.c +++ b/libsqsh/src/metablock/metablock_iterator.c @@ -156,7 +156,7 @@ sqsh__metablock_iterator_next( int sqsh__metablock_iterator_skip( - struct SqshMetablockIterator *iterator, sqsh_index_t *offset) { + struct SqshMetablockIterator *iterator, uint64_t *offset) { int rv = 0; size_t current_size = sqsh__metablock_iterator_size(iterator); diff --git a/libsqsh/src/metablock/metablock_reader.c b/libsqsh/src/metablock/metablock_reader.c index eaf15302..0cbc71e4 100644 --- a/libsqsh/src/metablock/metablock_reader.c +++ b/libsqsh/src/metablock/metablock_reader.c @@ -46,8 +46,7 @@ metablock_iterator_next(void *iterator, size_t desired_size, int *err) { return sqsh__metablock_iterator_next(iterator, err); } static int -metablock_iterator_skip( - void *iterator, sqsh_index_t *offset, size_t desired_size) { +metablock_iterator_skip(void *iterator, uint64_t *offset, size_t desired_size) { (void)desired_size; return sqsh__metablock_iterator_skip(iterator, offset); } @@ -85,7 +84,7 @@ sqsh__metablock_reader_init( int sqsh__metablock_reader_advance( - struct SqshMetablockReader *reader, sqsh_index_t offset, size_t size) { + struct SqshMetablockReader *reader, uint64_t offset, size_t size) { return sqsh__reader_advance(&reader->reader, offset, size); } diff --git a/test/libsqsh/reader/reader.c b/test/libsqsh/reader/reader.c index 06a02912..61bb6370 100644 --- a/test/libsqsh/reader/reader.c +++ b/test/libsqsh/reader/reader.c @@ -75,7 +75,7 @@ test_iter_next(void *data, size_t desired_size, int *err) { } static int -test_iter_skip(void *iterator, sqsh_index_t *offset, size_t desired_size) { +test_iter_skip(void *iterator, uint64_t *offset, size_t desired_size) { int rv = 0; size_t current_size = test_iter_size(iterator); diff --git a/tools/src/fs-common.c b/tools/src/fs-common.c index e4f61031..6522b56b 100644 --- a/tools/src/fs-common.c +++ b/tools/src/fs-common.c @@ -152,7 +152,7 @@ fs_common_read( return 0; } - rv = sqsh_file_reader_advance(*reader, offset, size); + rv = sqsh_file_reader_advance2(*reader, offset, size); if (rv < 0) { goto out; }