From cd8d243caede421a060a724021b043b3b5c71d89 Mon Sep 17 00:00:00 2001 From: Enno Boland Date: Mon, 12 Aug 2024 12:02:29 +0200 Subject: [PATCH 1/4] chores: fix 32bit build with -Wconversion --- doc/guide.md | 2 +- examples/read_file.c | 2 +- examples/readme_example.c | 2 +- include/sqsh_easy.h | 28 ++++++++++++ include/sqsh_mapper.h | 36 +++++++++++++++- include/sqsh_table.h | 19 +++++++- libsqsh/README.md | 2 +- libsqsh/include/sqsh_mapper_private.h | 17 ++------ libsqsh/include/sqsh_xattr_private.h | 2 +- libsqsh/src/archive/archive.c | 18 +++++--- libsqsh/src/archive/inode_map.c | 2 +- libsqsh/src/archive/trailing_context.c | 2 +- .../src/directory/directory_index_iterator.c | 2 +- libsqsh/src/easy/file.c | 43 +++++++++++++++---- libsqsh/src/extract/extract_manager.c | 2 +- libsqsh/src/file/file_iterator.c | 8 ++-- libsqsh/src/file/inode_file.c | 5 ++- libsqsh/src/mapper/curl_mapper.c | 14 +++--- libsqsh/src/mapper/map_iterator.c | 17 ++------ libsqsh/src/mapper/map_manager.c | 20 +++++---- libsqsh/src/mapper/map_reader.c | 11 +++-- libsqsh/src/mapper/map_slice.c | 14 ++++-- libsqsh/src/mapper/mapper.c | 23 ++++++++-- libsqsh/src/mapper/static_mapper.c | 9 ++-- libsqsh/src/posix/mmap_mapper.c | 8 ++-- libsqsh/src/table/export_table.c | 10 +++++ libsqsh/src/table/table.c | 5 ++- libsqsh/src/xattr/xattr_iterator.c | 3 +- subprojects/cextras.wrap | 2 +- 29 files changed, 232 insertions(+), 96 deletions(-) diff --git a/doc/guide.md b/doc/guide.md index e4b65c05d..6f7d3c8ea 100644 --- a/doc/guide.md +++ b/doc/guide.md @@ -49,7 +49,7 @@ struct SqshArchive *archive = sqsh_archive_open("archive.squashfs", NULL, NULL); assert(archive != NULL); uint8_t *content = sqsh_easy_file_content(archive, "/path/to/file.txt", NULL); -size_t size = sqsh_easy_file_size(archive, "/path/to/file.txt", NULL); +uint64_t size = sqsh_easy_file_size2(archive, "/path/to/file.txt", NULL); fwrite(content, 1, size, stdout); free(content); diff --git a/examples/read_file.c b/examples/read_file.c index be28ab614..f20b1ebd0 100644 --- a/examples/read_file.c +++ b/examples/read_file.c @@ -22,7 +22,7 @@ main(int argc, char *argv[]) { uint8_t *content = sqsh_easy_file_content(archive, argv[2], NULL); assert(content != NULL); - size_t size = sqsh_easy_file_size(archive, argv[2], NULL); + size_t size = sqsh_easy_file_size2(archive, argv[2], NULL); fwrite(content, size, 1, stdout); diff --git a/examples/readme_example.c b/examples/readme_example.c index 8262dbaa2..f8efb6fb0 100644 --- a/examples/readme_example.c +++ b/examples/readme_example.c @@ -19,7 +19,7 @@ main(int argc, char *argv[]) { uint8_t *contents = sqsh_easy_file_content(archive, "/path/to/file", NULL); assert(contents != NULL); - const size_t size = sqsh_easy_file_size(archive, "/path/to/file", NULL); + const size_t size = sqsh_easy_file_size2(archive, "/path/to/file", NULL); fwrite(contents, 1, size, stdout); free(contents); diff --git a/include/sqsh_easy.h b/include/sqsh_easy.h index 29a87e409..f2d7d6c7a 100644 --- a/include/sqsh_easy.h +++ b/include/sqsh_easy.h @@ -87,6 +87,20 @@ sqsh_easy_file_content(struct SqshArchive *archive, const char *path, int *err); * * @return The size of the file on success, 0 on error. */ +uint64_t +sqsh_easy_file_size2(struct SqshArchive *archive, const char *path, int *err); + +/** + * @deprecated Since 1.5.0. Use sqsh_easy_file_size2() instead. + * @brief retrieves the size of a file. + * + * @param[in] archive The sqsh archive context. + * @param[in] path The path the file or directory. + * @param[out] err Pointer to an int where the error code will be stored. + * + * @return The size of the file on success, 0 on error. + */ +__attribute__((deprecated("Since 1.5.0. Use sqsh_easy_file_size2() instead."))) size_t sqsh_easy_file_size(struct SqshArchive *archive, const char *path, int *err); @@ -111,6 +125,20 @@ mode_t sqsh_easy_file_permission( * * @return The modification time of the file on success, 0 on error. */ +uint32_t +sqsh_easy_file_mtime2(struct SqshArchive *archive, const char *path, int *err); + +/** + * @deprecated Since 1.5.0. Use sqsh_easy_file_mtime2() instead. + * @brief retrieves the modification time of a file. + * + * @param[in] archive The sqsh archive context. + * @param[in] path The path the file or directory. + * @param[out] err Pointer to an int where the error code will be stored. + * + * @return The modification time of the file on success, 0 on error. + */ +__attribute__((deprecated("Since 1.5.0. Use sqsh_easy_file_mtime2() instead."))) time_t sqsh_easy_file_mtime(struct SqshArchive *archive, const char *path, int *err); diff --git a/include/sqsh_mapper.h b/include/sqsh_mapper.h index 28c9788cf..89e38edd0 100644 --- a/include/sqsh_mapper.h +++ b/include/sqsh_mapper.h @@ -57,13 +57,21 @@ struct SqshMemoryMapperImpl { */ size_t block_size_hint; /** + * @deprecated Since 1.5.0. Use SqshMemoryMapperImpl::init2() instead. * @brief The initialization function for the mapper. Use * sqsh_mapper_set_user_data() to set custom user data. */ +#ifndef SQSH__NO_DEPRECATED_FIELD + __attribute__((deprecated("Since 1.5.0. Use init2() instead."))) +#endif int (*init)(struct SqshMapper *mapper, const void *input, size_t *size); /** + * @deprecated Since 1.5.0. Use SqshMemoryMapperImpl::map2() instead. * @brief The function that maps a block of data into memory. */ +#ifndef SQSH__NO_DEPRECATED_FIELD + __attribute__((deprecated("Since 1.5.0. Use init2() instead."))) +#endif int (*map)( const struct SqshMapper *mapper, sqsh_index_t offset, size_t size, uint8_t **data); @@ -75,6 +83,18 @@ struct SqshMemoryMapperImpl { * @brief The cleanup function for the mapper. */ int (*cleanup)(struct SqshMapper *mapper); + /** + * @brief The initialization function for the mapper. Use + * sqsh_mapper_set_user_data() to set custom user data. + */ + + int (*init2)(struct SqshMapper *mapper, const void *input, uint64_t *size); + /** + * @brief The function that maps a block of data into memory. + */ + int (*map2)( + const struct SqshMapper *mapper, uint64_t offset, size_t size, + uint8_t **data); }; /** @@ -96,6 +116,20 @@ void sqsh_mapper_set_user_data(struct SqshMapper *mapper, void *user_data); */ void *sqsh_mapper_user_data(const struct SqshMapper *mapper); +/** + * @deprecated Since 1.5.0. Use sqsh_mapper_size2() instead. + * @internal + * @memberof SqshMapper + * @brief Retrieves the size of the input data in a mapper. + * + * @param[in] mapper The mapper to retrieve the size from. + * + * @return The size of the input data in the mapper. + */ +__attribute__((deprecated("Since 1.5.0. Use sqsh_mapper_size2() instead."))) +size_t +sqsh_mapper_size(const struct SqshMapper *mapper); + /** * @internal * @memberof SqshMapper @@ -105,7 +139,7 @@ void *sqsh_mapper_user_data(const struct SqshMapper *mapper); * * @return The size of the input data in the mapper. */ -size_t sqsh_mapper_size(const struct SqshMapper *mapper); +uint64_t sqsh_mapper_size2(const struct SqshMapper *mapper); /** * @internal diff --git a/include/sqsh_table.h b/include/sqsh_table.h index 68e60ec6b..d7d9e46b6 100644 --- a/include/sqsh_table.h +++ b/include/sqsh_table.h @@ -94,7 +94,24 @@ struct SqshExportTable; * * @return 0 on success, a negative value on error. */ -int sqsh_export_table_resolve_inode( +int sqsh_export_table_resolve_inode2( + const struct SqshExportTable *table, uint32_t inode, + uint64_t *inode_ref); + +/** + * @deprecated Since 1.5.0. Use sqsh_export_table_resolve_inode2 instead. + * @memberof SqshTable + * @brief Retrieves an element from the table. + * + * @param[in] table The table to retrieve the element from. + * @param[in] inode The index of the element to retrieve. + * @param[out] inode_ref A pointer to a uint64_t to store the inode reference + * + * @return 0 on success, a negative value on error. + */ +__attribute__((deprecated( + "Since 1.5.0. Use sqsh_export_table_resolve_inode2 instead."))) int +sqsh_export_table_resolve_inode( const struct SqshExportTable *table, uint64_t inode, uint64_t *inode_ref); diff --git a/libsqsh/README.md b/libsqsh/README.md index 4f7a1acf0..d63a8941a 100644 --- a/libsqsh/README.md +++ b/libsqsh/README.md @@ -48,7 +48,7 @@ assert(archive != NULL); uint8_t *contents = sqsh_easy_file_content(archive, "/path/to/file", NULL); assert(contents != NULL); -const size_t size = sqsh_easy_file_size(archive, "/path/to/file", NULL); +const uint64_t size = sqsh_easy_file_size2(archive, "/path/to/file", NULL); fwrite(contents, 1, size, stdout); free(contents); diff --git a/libsqsh/include/sqsh_mapper_private.h b/libsqsh/include/sqsh_mapper_private.h index 4ae796bb3..658541c6f 100644 --- a/libsqsh/include/sqsh_mapper_private.h +++ b/libsqsh/include/sqsh_mapper_private.h @@ -61,7 +61,7 @@ struct SqshMapper { */ const struct SqshMemoryMapperImpl *impl; size_t block_size; - size_t archive_size; + uint64_t archive_size; void *user_data; }; @@ -154,7 +154,7 @@ SQSH_NO_EXPORT int sqsh__map_slice_cleanup(struct SqshMapSlice *mapping); */ SQSH_NO_EXPORT SQSH_NO_UNUSED int sqsh__map_slice_init( struct SqshMapSlice *mapping, struct SqshMapper *mapper, - sqsh_index_t offset, size_t size); + uint64_t offset, size_t size); /*************************************** * mapper/map_manager.c @@ -276,7 +276,7 @@ struct SqshMapIterator { * @privatesection */ sqsh_index_t next_index; - sqsh_index_t segment_count; + uint64_t segment_count; struct SqshMapManager *map_manager; const struct SqshMapSlice *mapping; const uint8_t *data; @@ -350,17 +350,6 @@ sqsh__map_iterator_data(const struct SqshMapIterator *iterator); SQSH_NO_EXPORT size_t sqsh__map_iterator_block_size(const struct SqshMapIterator *iterator); -/** - * @internal - * @memberof SqshMapIterator - * @brief returns the address of the current chunk. - * - * @param[in] iterator The SqshMapIterator instance. - * @return the address of the current chunk. - */ -SQSH_NO_EXPORT sqsh_index_t -sqsh__map_iterator_address(const struct SqshMapIterator *iterator); - /** * @internal * @memberof SqshMapIterator diff --git a/libsqsh/include/sqsh_xattr_private.h b/libsqsh/include/sqsh_xattr_private.h index ecc8fa074..87bee9bbf 100644 --- a/libsqsh/include/sqsh_xattr_private.h +++ b/libsqsh/include/sqsh_xattr_private.h @@ -60,7 +60,7 @@ struct SqshXattrIterator { size_t remaining_entries; size_t remaining_size; uint64_t upper_limit; - sqsh_index_t next_offset; + uint64_t next_offset; sqsh_index_t value_index; }; diff --git a/libsqsh/src/archive/archive.c b/libsqsh/src/archive/archive.c index 3ef0f3589..a9e846173 100644 --- a/libsqsh/src/archive/archive.c +++ b/libsqsh/src/archive/archive.c @@ -160,13 +160,17 @@ sqsh__archive_init( rv = -SQSH_ERROR_INTEGER_OVERFLOW; goto out; } - const size_t metablock_capacity = SQSH_DIVIDE_CEIL( + const uint64_t metablock_capacity = SQSH_DIVIDE_CEIL( range, sizeof(struct SqshDataMetablock) + SQSH_METABLOCK_BLOCK_SIZE); - + if (metablock_capacity > SIZE_MAX) { + rv = -SQSH_ERROR_INTEGER_OVERFLOW; + goto out; + } rv = sqsh__extract_manager_init( &archive->metablock_extract_manager, archive, - SQSH_METABLOCK_BLOCK_SIZE, metablock_capacity, metablock_lru_size); + SQSH_METABLOCK_BLOCK_SIZE, (size_t)metablock_capacity, + metablock_lru_size); if (rv < 0) { goto out; } @@ -211,14 +215,18 @@ sqsh__archive_data_extract_manager( const struct SqshSuperblock *superblock = sqsh_archive_superblock(archive); const uint64_t range = get_data_segment_size(superblock); - const size_t capacity = + const uint64_t capacity = SQSH_DIVIDE_CEIL(range, sqsh_superblock_block_size(superblock)); const uint32_t datablock_blocksize = sqsh_superblock_block_size(superblock); + if (capacity > SIZE_MAX) { + rv = -SQSH_ERROR_INTEGER_OVERFLOW; + goto out; + } rv = sqsh__extract_manager_init( &archive->data_extract_manager, archive, datablock_blocksize, - capacity, data_lru_size); + (size_t)capacity, data_lru_size); if (rv < 0) { goto out; } diff --git a/libsqsh/src/archive/inode_map.c b/libsqsh/src/archive/inode_map.c index ccafc8849..ede112cb8 100644 --- a/libsqsh/src/archive/inode_map.c +++ b/libsqsh/src/archive/inode_map.c @@ -67,7 +67,7 @@ export_table_get( rv = -SQSH_ERROR_OUT_OF_BOUNDS; goto out; } - rv = sqsh_export_table_resolve_inode( + rv = sqsh_export_table_resolve_inode2( map->export_table, inode_number, &inode_ref); if (rv < 0) { goto out; diff --git a/libsqsh/src/archive/trailing_context.c b/libsqsh/src/archive/trailing_context.c index 240a6ab08..511e23115 100644 --- a/libsqsh/src/archive/trailing_context.c +++ b/libsqsh/src/archive/trailing_context.c @@ -43,7 +43,7 @@ sqsh__trailing_init( const struct SqshSuperblock *superblock = sqsh_archive_superblock(sqsh); uint64_t trailing_start = sqsh_superblock_bytes_used(superblock); struct SqshMapManager *map_manager = sqsh_archive_map_manager(sqsh); - size_t archive_size = sqsh__map_manager_size(map_manager); + uint64_t archive_size = sqsh__map_manager_size(map_manager); uint64_t trailing_size; if (archive_size <= trailing_start) { diff --git a/libsqsh/src/directory/directory_index_iterator.c b/libsqsh/src/directory/directory_index_iterator.c index 69820c5ef..0b34b978d 100644 --- a/libsqsh/src/directory/directory_index_iterator.c +++ b/libsqsh/src/directory/directory_index_iterator.c @@ -38,7 +38,7 @@ #include -static const uint64_t INODE_HEADER_SIZE = sizeof(struct SqshDataInodeHeader) + +static const size_t INODE_HEADER_SIZE = sizeof(struct SqshDataInodeHeader) + sizeof(struct SqshDataInodeDirectoryExt); static const struct SqshDataInodeDirectoryIndex * diff --git a/libsqsh/src/easy/file.c b/libsqsh/src/easy/file.c index 3ef36f1e3..aa93f0b3e 100644 --- a/libsqsh/src/easy/file.c +++ b/libsqsh/src/easy/file.c @@ -89,8 +89,12 @@ sqsh_easy_file_content( goto out; } - size_t file_size = sqsh_file_size(file); - content = calloc(file_size + 1, sizeof(*content)); + uint64_t file_size = sqsh_file_size(file); + if (file_size > SIZE_MAX - 1) { + rv = -SQSH_ERROR_INTEGER_OVERFLOW; + goto out; + } + content = calloc((size_t)file_size + 1, sizeof(*content)); if (content == NULL) { rv = -SQSH_ERROR_MALLOC_FAILED; goto out; @@ -117,11 +121,11 @@ sqsh_easy_file_content( return content; } -size_t -sqsh_easy_file_size(struct SqshArchive *archive, const char *path, int *err) { +uint64_t +sqsh_easy_file_size2(struct SqshArchive *archive, const char *path, int *err) { int rv = 0; struct SqshFile *file = NULL; - size_t file_size = 0; + uint64_t file_size = 0; file = sqsh_open(archive, path, &rv); if (rv < 0) { @@ -138,6 +142,24 @@ sqsh_easy_file_size(struct SqshArchive *archive, const char *path, int *err) { return file_size; } +size_t +sqsh_easy_file_size(struct SqshArchive *archive, const char *path, int *err) { + int rv = 0; + uint64_t file_size = sqsh_easy_file_size2(archive, path, &rv); + if (rv < 0) { + goto out; + } + if (file_size > SIZE_MAX - 1) { + rv = -SQSH_ERROR_INTEGER_OVERFLOW; + goto out; + } +out: + if (err != NULL) { + *err = rv; + } + return (size_t)file_size; +} + mode_t sqsh_easy_file_permission( struct SqshArchive *archive, const char *path, int *err) { @@ -160,11 +182,11 @@ sqsh_easy_file_permission( return permission; } -time_t -sqsh_easy_file_mtime(struct SqshArchive *archive, const char *path, int *err) { +uint32_t +sqsh_easy_file_mtime2(struct SqshArchive *archive, const char *path, int *err) { int rv = 0; struct SqshFile *file = NULL; - time_t modified = 0; + uint32_t modified = 0; file = sqsh_open(archive, path, &rv); if (rv < 0) { @@ -180,3 +202,8 @@ sqsh_easy_file_mtime(struct SqshArchive *archive, const char *path, int *err) { } return modified; } + +time_t +sqsh_easy_file_mtime(struct SqshArchive *archive, const char *path, int *err) { + return (time_t)sqsh_easy_file_mtime2(archive, path, err); +} diff --git a/libsqsh/src/extract/extract_manager.c b/libsqsh/src/extract/extract_manager.c index 719cae8ac..7a3363a82 100644 --- a/libsqsh/src/extract/extract_manager.c +++ b/libsqsh/src/extract/extract_manager.c @@ -66,7 +66,7 @@ maybe_prime(uint64_t n) { return mod_power(a, n - 1, n) == 1; } -static uint64_t +static size_t find_next_maybe_prime(size_t n) { for (; maybe_prime(n) == false; n++) { } diff --git a/libsqsh/src/file/file_iterator.c b/libsqsh/src/file/file_iterator.c index c294b400d..ae2556de3 100644 --- a/libsqsh/src/file/file_iterator.c +++ b/libsqsh/src/file/file_iterator.c @@ -139,7 +139,7 @@ map_block_uncompressed( uint32_t block_index = iterator->block_index; struct SqshMapReader *reader = &iterator->map_reader; const uint64_t block_count = sqsh_file_block_count(file); - uint64_t outer_size = 0; + size_t outer_size = 0; const size_t remaining_direct = sqsh__map_reader_remaining_direct(reader); for (; iterator->sparse_size == 0 && block_index < block_count; @@ -157,7 +157,7 @@ map_block_uncompressed( iterator->sparse_size = iterator->block_size - data_block_size; } - uint64_t new_outer_size; + size_t new_outer_size; if (SQSH_ADD_OVERFLOW(outer_size, data_block_size, &new_outer_size)) { rv = -SQSH_ERROR_INTEGER_OVERFLOW; goto out; @@ -212,7 +212,7 @@ map_block(struct SqshFileIterator *iterator, size_t desired_size) { const uint32_t block_index = iterator->block_index; const size_t block_size = iterator->block_size; const bool is_compressed = sqsh_file_block_is_compressed(file, block_index); - const size_t file_size = sqsh_file_size(file); + const uint64_t file_size = sqsh_file_size(file); const size_t data_block_size = sqsh_file_block_size(file, block_index); const sqsh_index_t next_offset = sqsh__map_reader_size(&iterator->map_reader); @@ -221,7 +221,7 @@ map_block(struct SqshFileIterator *iterator, size_t desired_size) { if (is_last_block(iterator) == false || file_size % block_size == 0) { iterator->sparse_size = block_size; } else { - iterator->sparse_size = file_size % block_size; + iterator->sparse_size = (size_t)file_size % block_size; } rv = map_zero_block(iterator); iterator->block_index++; diff --git a/libsqsh/src/file/inode_file.c b/libsqsh/src/file/inode_file.c index 6471dfdd4..e64c23c2a 100644 --- a/libsqsh/src/file/inode_file.c +++ b/libsqsh/src/file/inode_file.c @@ -57,10 +57,11 @@ calc_block_count( const uint32_t block_size = sqsh_superblock_block_size(superblock); const bool has_fragment = fragment_index != SQSH_INODE_NO_FRAGMENT; + // TODO: integer overflows on 32bit? if (has_fragment) { - return file_size / block_size; + return (size_t)file_size / block_size; } else { - return SQSH_DIVIDE_CEIL(file_size, block_size); + return (size_t)SQSH_DIVIDE_CEIL(file_size, block_size); } } diff --git a/libsqsh/src/mapper/curl_mapper.c b/libsqsh/src/mapper/curl_mapper.c index 654ac66f5..d2c48494f 100644 --- a/libsqsh/src/mapper/curl_mapper.c +++ b/libsqsh/src/mapper/curl_mapper.c @@ -153,7 +153,7 @@ configure_handle(struct SqshCurlMapper *mapper) { static int curl_download( - CURL *handle, sqsh_index_t offset, size_t size, uint8_t **data, + CURL *handle, uint64_t offset, size_t size, uint8_t **data, uint64_t *file_size, uint64_t *file_time) { *data = calloc(size, sizeof(uint8_t)); if (*data == NULL) { @@ -175,7 +175,7 @@ curl_download( long http_code = 0; rv = snprintf( - range_buffer, sizeof(range_buffer), "%zu-%" PRIu64, offset, + range_buffer, sizeof(range_buffer), "%" PRIu64 "-%" PRIu64, offset, end_offset); if (rv >= (int)sizeof(range_buffer)) { rv = -SQSH_ERROR_MAPPER_MAP; @@ -212,7 +212,7 @@ curl_download( static int sqsh_mapper_curl_init( - struct SqshMapper *mapper, const void *input, size_t *size) { + struct SqshMapper *mapper, const void *input, uint64_t *size) { (void)size; int rv = 0; curl_global_init(CURL_GLOBAL_ALL); @@ -254,7 +254,7 @@ sqsh_mapper_curl_init( static int sqsh_mapper_curl_map( - const struct SqshMapper *mapper, sqsh_index_t offset, size_t size, + const struct SqshMapper *mapper, uint64_t offset, size_t size, uint8_t **data) { struct SqshCurlMapper *curl_mapper = sqsh_mapper_user_data(mapper); int rv = 0; @@ -282,7 +282,7 @@ sqsh_mapper_curl_map( goto out; } - if (file_size != sqsh_mapper_size(mapper)) { + if (file_size != sqsh_mapper_size2(mapper)) { rv = -SQSH_ERROR_MAPPER_MAP; goto out; } @@ -315,8 +315,8 @@ sqsh_mapping_curl_unmap( static const struct SqshMemoryMapperImpl impl = { /* 40kb */ - .block_size_hint = 40 * 1024, .init = sqsh_mapper_curl_init, - .map = sqsh_mapper_curl_map, .cleanup = sqsh_mapper_curl_cleanup, + .block_size_hint = 40 * 1024, .init2 = sqsh_mapper_curl_init, + .map2 = sqsh_mapper_curl_map, .cleanup = sqsh_mapper_curl_cleanup, .unmap = sqsh_mapping_curl_unmap, }; const struct SqshMemoryMapperImpl *const sqsh_mapper_impl_curl = &impl; diff --git a/libsqsh/src/mapper/map_iterator.c b/libsqsh/src/mapper/map_iterator.c index a876bb863..777fcd9ea 100644 --- a/libsqsh/src/mapper/map_iterator.c +++ b/libsqsh/src/mapper/map_iterator.c @@ -41,14 +41,10 @@ #include #include -static size_t +static sqsh_index_t address_to_index(const struct SqshMapIterator *iterator, uint64_t address) { - return address / sqsh__map_manager_block_size(iterator->map_manager); -} - -static size_t -index_to_address(const struct SqshMapIterator *iterator, uint64_t index) { - return index * sqsh__map_manager_block_size(iterator->map_manager); + return (sqsh_index_t)address / + sqsh__map_manager_block_size(iterator->map_manager); } int @@ -56,7 +52,7 @@ sqsh__map_iterator_init( struct SqshMapIterator *iterator, struct SqshMapManager *manager, uint64_t start_address) { const size_t block_size = sqsh__map_manager_block_size(manager); - const size_t archive_size = sqsh__map_manager_size(manager); + const uint64_t archive_size = sqsh__map_manager_size(manager); if (start_address >= archive_size) { return -SQSH_ERROR_OUT_OF_BOUNDS; @@ -153,11 +149,6 @@ sqsh__map_iterator_block_size(const struct SqshMapIterator *iterator) { return sqsh__map_manager_block_size(iterator->map_manager); } -sqsh_index_t -sqsh__map_iterator_address(const struct SqshMapIterator *iterator) { - return index_to_address(iterator, iterator->next_index); -} - size_t sqsh__map_iterator_size(const struct SqshMapIterator *iterator) { return iterator->size; diff --git a/libsqsh/src/mapper/map_manager.c b/libsqsh/src/mapper/map_manager.c index 0ff5862cb..6cdaf1c63 100644 --- a/libsqsh/src/mapper/map_manager.c +++ b/libsqsh/src/mapper/map_manager.c @@ -37,8 +37,6 @@ #include #include -#include - static void map_cleanup_cb(void *data) { struct SqshMapSlice *mapping = data; @@ -53,9 +51,9 @@ load_mapping( const size_t block_size = sqsh_mapper_block_size(&manager->mapper); const size_t block_count = sqsh__map_manager_block_count(manager); - const size_t mapper_size = sqsh__map_manager_size(manager); + const uint64_t mapper_size = sqsh__map_manager_size(manager); size_t size = block_size; - sqsh_index_t offset; + uint64_t offset; if (SQSH_MULT_OVERFLOW(index, block_size, &offset)) { return -SQSH_ERROR_INTEGER_OVERFLOW; } @@ -64,7 +62,7 @@ load_mapping( * read past the end of the file, so cap the size to the remaining bytes. */ if (index == block_count - 1 && mapper_size % block_size != 0) { - size = mapper_size % block_size; + size = (size_t)mapper_size % block_size; } if (SQSH_ADD_OVERFLOW(offset, manager->archive_offset, &offset)) { @@ -85,7 +83,7 @@ sqsh__map_manager_init( struct SqshMapManager *manager, const void *input, const struct SqshConfig *config) { int rv; - size_t map_size; + uint64_t map_size; const size_t lru_size = SQSH_CONFIG_DEFAULT(config->mapper_lru_size, 32); const uint64_t archive_offset = config->archive_offset; @@ -98,7 +96,7 @@ sqsh__map_manager_init( goto out; } - const size_t mapper_size = sqsh_mapper_size(&manager->mapper); + const uint64_t mapper_size = sqsh_mapper_size2(&manager->mapper); if (mapper_size < archive_offset) { rv = -SQSH_ERROR_OUT_OF_BOUNDS; @@ -107,10 +105,14 @@ sqsh__map_manager_init( map_size = SQSH_DIVIDE_CEIL( mapper_size - archive_offset, sqsh_mapper_block_size(&manager->mapper)); + if (map_size > SIZE_MAX) { + rv = -SQSH_ERROR_INTEGER_OVERFLOW; + goto out; + } manager->archive_offset = archive_offset; rv = cx_rc_map_init( - &manager->maps, map_size, sizeof(struct SqshMapSlice), + &manager->maps, (size_t)map_size, sizeof(struct SqshMapSlice), map_cleanup_cb); if (rv < 0) { goto out; @@ -126,7 +128,7 @@ sqsh__map_manager_init( uint64_t sqsh__map_manager_size(const struct SqshMapManager *manager) { - return sqsh_mapper_size(&manager->mapper) - manager->archive_offset; + return sqsh_mapper_size2(&manager->mapper) - manager->archive_offset; } size_t diff --git a/libsqsh/src/mapper/map_reader.c b/libsqsh/src/mapper/map_reader.c index a8c88a4c4..c88bdd855 100644 --- a/libsqsh/src/mapper/map_reader.c +++ b/libsqsh/src/mapper/map_reader.c @@ -64,7 +64,7 @@ static const struct SqshReaderIteratorImpl map_reader_impl = { static sqsh_index_t get_offset(const struct SqshMapReader *reader, uint64_t address) { - return address % sqsh__map_iterator_block_size(&reader->iterator); + return (size_t)address % sqsh__map_iterator_block_size(&reader->iterator); } int @@ -73,7 +73,7 @@ sqsh__map_reader_init( uint64_t start_address, const uint64_t upper_limit) { int rv; sqsh_index_t offset = - start_address % sqsh__map_manager_block_size(map_manager); + (size_t)start_address % sqsh__map_manager_block_size(map_manager); rv = sqsh__map_iterator_init( &reader->iterator, map_manager, start_address - offset); @@ -117,8 +117,11 @@ sqsh__map_reader_advance( int sqsh__map_reader_all(struct SqshMapReader *reader) { - return sqsh__map_reader_advance( - reader, 0, reader->upper_limit - reader->address); + uint64_t size = reader->upper_limit - reader->address; + if (size > SIZE_MAX) { + return -SQSH_ERROR_INTEGER_OVERFLOW; + } + return sqsh__map_reader_advance(reader, 0, (size_t)size); } const uint8_t * diff --git a/libsqsh/src/mapper/map_slice.c b/libsqsh/src/mapper/map_slice.c index 44438fb91..56c6a2e65 100644 --- a/libsqsh/src/mapper/map_slice.c +++ b/libsqsh/src/mapper/map_slice.c @@ -31,6 +31,7 @@ * @file map_slice.c */ +#define SQSH__NO_DEPRECATED_FIELD #include #include @@ -40,9 +41,9 @@ int sqsh__map_slice_init( struct SqshMapSlice *mapping, struct SqshMapper *mapper, - sqsh_index_t offset, size_t size) { + uint64_t offset, size_t size) { size_t end_offset; - size_t archive_size = sqsh_mapper_size(mapper); + uint64_t archive_size = sqsh_mapper_size2(mapper); if (offset > archive_size) { return -SQSH_ERROR_SIZE_MISMATCH; } @@ -54,7 +55,14 @@ sqsh__map_slice_init( } mapping->mapper = mapper; mapping->size = size; - return mapper->impl->map(mapper, offset, size, &mapping->data); + if (mapper->impl->map == NULL) { + return mapper->impl->map2(mapper, offset, size, &mapping->data); + } else { + if (offset > SIZE_MAX) { + return -SQSH_ERROR_INTEGER_OVERFLOW; + } + return mapper->impl->map(mapper, (size_t)offset, size, &mapping->data); + } } const uint8_t * diff --git a/libsqsh/src/mapper/mapper.c b/libsqsh/src/mapper/mapper.c index 4e9dd05ee..cab482345 100644 --- a/libsqsh/src/mapper/mapper.c +++ b/libsqsh/src/mapper/mapper.c @@ -31,6 +31,7 @@ * @file mapper.c */ +#define SQSH__NO_DEPRECATED_FIELD #include #include @@ -42,7 +43,7 @@ sqsh__mapper_init( struct SqshMapper *mapper, const void *source, const struct SqshConfig *config) { int rv = 0; - size_t size = config->source_size; + uint64_t size = config->source_size; if (config->source_mapper) { mapper->impl = config->source_mapper; } else { @@ -55,13 +56,24 @@ sqsh__mapper_init( mapper->block_size = mapper->impl->block_size_hint; } - rv = mapper->impl->init(mapper, source, &size); + if (mapper->impl->init == NULL) { + rv = mapper->impl->init2(mapper, source, &size); + } else { + if (size > SIZE_MAX) { + rv = -SQSH_ERROR_INTEGER_OVERFLOW; + goto out; + } + size_t small_size = (size_t)size; + rv = mapper->impl->init(mapper, source, &small_size); + size = small_size; + } if (rv < 0) { - return rv; + goto out; } mapper->archive_size = size; +out: return rv; } @@ -72,6 +84,11 @@ sqsh_mapper_block_size(const struct SqshMapper *mapper) { size_t sqsh_mapper_size(const struct SqshMapper *mapper) { + return (size_t)mapper->archive_size; +} + +uint64_t +sqsh_mapper_size2(const struct SqshMapper *mapper) { return mapper->archive_size; } diff --git a/libsqsh/src/mapper/static_mapper.c b/libsqsh/src/mapper/static_mapper.c index 809ecb8ec..98605cd47 100644 --- a/libsqsh/src/mapper/static_mapper.c +++ b/libsqsh/src/mapper/static_mapper.c @@ -35,7 +35,7 @@ static int sqsh_mapper_static_mem_init( - struct SqshMapper *mapper, const void *input, size_t *size) { + struct SqshMapper *mapper, const void *input, uint64_t *size) { (void)size; sqsh_mapper_set_user_data(mapper, (void *)input); @@ -44,10 +44,9 @@ sqsh_mapper_static_mem_init( } static int sqsh_mapper_static_mem_map( - const struct SqshMapper *mapper, sqsh_index_t offset, size_t size, + const struct SqshMapper *mapper, uint64_t offset, size_t size, uint8_t **data) { (void)size; - /* Cast to remove const qualifier. */ uint8_t *global_data = sqsh_mapper_user_data(mapper); *data = &global_data[offset]; return 0; @@ -68,8 +67,8 @@ sqsh_mapping_static_mem_unmap( static const struct SqshMemoryMapperImpl impl = { .block_size_hint = SIZE_MAX, - .init = sqsh_mapper_static_mem_init, - .map = sqsh_mapper_static_mem_map, + .init2 = sqsh_mapper_static_mem_init, + .map2 = sqsh_mapper_static_mem_map, .cleanup = sqsh_mapper_static_mem_cleanup, .unmap = sqsh_mapping_static_mem_unmap, }; diff --git a/libsqsh/src/posix/mmap_mapper.c b/libsqsh/src/posix/mmap_mapper.c index 0047108a2..41534c670 100644 --- a/libsqsh/src/posix/mmap_mapper.c +++ b/libsqsh/src/posix/mmap_mapper.c @@ -51,7 +51,7 @@ static int sqsh_mapper_mmap_init( - struct SqshMapper *mapper, const void *input, size_t *size) { + struct SqshMapper *mapper, const void *input, uint64_t *size) { (void)size; (void)mapper; int rv = 0; @@ -81,7 +81,7 @@ sqsh_mapper_mmap_init( } static int sqsh_mapping_mmap_map( - const struct SqshMapper *mapper, sqsh_index_t offset, size_t size, + const struct SqshMapper *mapper, uint64_t offset, size_t size, uint8_t **data) { const int fd = FROM_PTR(sqsh_mapper_user_data(mapper)); const long page_size = sysconf(_SC_PAGESIZE); @@ -129,8 +129,8 @@ static const struct SqshMemoryMapperImpl impl = { /* 100 MiB */ .block_size_hint = 100 * 1024 * 1024, #endif - .init = sqsh_mapper_mmap_init, - .map = sqsh_mapping_mmap_map, + .init2 = sqsh_mapper_mmap_init, + .map2 = sqsh_mapping_mmap_map, .unmap = sqsh_mapping_mmap_unmap, .cleanup = sqsh_mapper_mmap_cleanup, }; diff --git a/libsqsh/src/table/export_table.c b/libsqsh/src/table/export_table.c index 7fc7c0492..988eb20d1 100644 --- a/libsqsh/src/table/export_table.c +++ b/libsqsh/src/table/export_table.c @@ -50,6 +50,16 @@ int sqsh_export_table_resolve_inode( const struct SqshExportTable *table, uint64_t inode, uint64_t *inode_ref) { + if (inode > SIZE_MAX) { + return -SQSH_ERROR_INVALID_ARGUMENT; + } + return sqsh_table_get(&table->table, (size_t)inode, inode_ref); +} + +int +sqsh_export_table_resolve_inode2( + const struct SqshExportTable *table, uint32_t inode, + uint64_t *inode_ref) { if (inode < 1) { return -SQSH_ERROR_INVALID_ARGUMENT; } diff --git a/libsqsh/src/table/table.c b/libsqsh/src/table/table.c index 9f0c154b9..6bf634c92 100644 --- a/libsqsh/src/table/table.c +++ b/libsqsh/src/table/table.c @@ -110,7 +110,7 @@ sqsh_table_get( struct SqshArchive *sqsh = table->sqsh; struct SqshMetablockReader metablock = {0}; size_t lookup_table_bytes = sqsh__map_reader_size(&table->lookup_table); - uint64_t lookup_index = + sqsh_index_t lookup_index = index * table->element_size / SQSH_METABLOCK_BLOCK_SIZE; if (lookup_index >= table->element_count || lookup_index * sizeof(uint64_t) >= lookup_table_bytes) { @@ -131,8 +131,9 @@ sqsh_table_get( goto out; } + // TODO: move *readers* to uint64_t offsets and remove this cast rv = sqsh__metablock_reader_advance( - &metablock, element_offset, table->element_size); + &metablock, (sqsh_index_t)element_offset, table->element_size); if (rv < 0) { goto out; } diff --git a/libsqsh/src/xattr/xattr_iterator.c b/libsqsh/src/xattr/xattr_iterator.c index 542874610..b88479598 100644 --- a/libsqsh/src/xattr/xattr_iterator.c +++ b/libsqsh/src/xattr/xattr_iterator.c @@ -187,8 +187,9 @@ sqsh_xattr_iterator_next(struct SqshXattrIterator *iterator, int *err) { } /* Load Key Header */ + // TODO: move *readers* to uint64_t offsets and remove this cast rv = sqsh__metablock_reader_advance( - &iterator->metablock, iterator->next_offset, + &iterator->metablock, (size_t)iterator->next_offset, sizeof(struct SqshDataXattrKey)); if (rv < 0) { goto out; diff --git a/subprojects/cextras.wrap b/subprojects/cextras.wrap index 8ae145973..5562806c5 100644 --- a/subprojects/cextras.wrap +++ b/subprojects/cextras.wrap @@ -1,6 +1,6 @@ [wrap-git] directory = cextras -revision = a6c00f3e332d96b700aeaf3f3d4d14425ea7c9df +revision = 63d5d1eae0ba7f66a34965d3c153bb0add64325d url = https://github.com/Gottox/cextras.git depth = 1 From e282d2409ad00fd4844329f9a8b8ca7173cb7f66 Mon Sep 17 00:00:00 2001 From: Enno Boland Date: Mon, 12 Aug 2024 12:48:42 +0200 Subject: [PATCH 2/4] .github: add wrapfiles to linux32-build --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2b1723d20..aa5e5612c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -184,7 +184,7 @@ jobs: run: | echo "$CROSS_FILE" > cross-file.txt meson setup --cross-file cross-file.txt /tmp/build \ - -Dwerror=false \ + -Dwerror=true \ -Dexamples=true \ -Dtest=false \ -Ddoc=false From 67f216017407812ed23239257cb01fc1828c3035 Mon Sep 17 00:00:00 2001 From: Enno Boland Date: Mon, 12 Aug 2024 17:33:20 +0200 Subject: [PATCH 3/4] 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 +- libsqsh/src/table/table.c | 3 +- libsqsh/src/xattr/xattr_iterator.c | 3 +- test/libsqsh/reader/reader.c | 2 +- test/tools/read-chunk.c | 2 +- tools/src/fs-common.c | 2 +- 18 files changed, 111 insertions(+), 39 deletions(-) diff --git a/common/include/sqsh_reader_private.h b/common/include/sqsh_reader_private.h index cc8a67d7c..304ddd996 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 3ec16f210..91ed56cf7 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 6f7d3c8ea..14a4b29a4 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 a5a11659c..227afc632 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 cbaca5cf0..1eacb5002 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 658541c6f..882867c7a 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 f48e78226..bf1b7936c 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 ae2556de3..608fa35d5 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 3f6fdbbc3..ce197b6d6 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 777fcd9ea..f159e6c91 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 c88bdd855..79feb728a 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 82c40e948..f20ce8c95 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 eaf15302b..0cbc71e46 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/libsqsh/src/table/table.c b/libsqsh/src/table/table.c index 6bf634c92..a7671a1f4 100644 --- a/libsqsh/src/table/table.c +++ b/libsqsh/src/table/table.c @@ -131,9 +131,8 @@ sqsh_table_get( goto out; } - // TODO: move *readers* to uint64_t offsets and remove this cast rv = sqsh__metablock_reader_advance( - &metablock, (sqsh_index_t)element_offset, table->element_size); + &metablock, element_offset, table->element_size); if (rv < 0) { goto out; } diff --git a/libsqsh/src/xattr/xattr_iterator.c b/libsqsh/src/xattr/xattr_iterator.c index b88479598..542874610 100644 --- a/libsqsh/src/xattr/xattr_iterator.c +++ b/libsqsh/src/xattr/xattr_iterator.c @@ -187,9 +187,8 @@ sqsh_xattr_iterator_next(struct SqshXattrIterator *iterator, int *err) { } /* Load Key Header */ - // TODO: move *readers* to uint64_t offsets and remove this cast rv = sqsh__metablock_reader_advance( - &iterator->metablock, (size_t)iterator->next_offset, + &iterator->metablock, iterator->next_offset, sizeof(struct SqshDataXattrKey)); if (rv < 0) { goto out; diff --git a/test/libsqsh/reader/reader.c b/test/libsqsh/reader/reader.c index 06a029129..61bb63706 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/test/tools/read-chunk.c b/test/tools/read-chunk.c index a129a549f..2cfca8897 100644 --- a/test/tools/read-chunk.c +++ b/test/tools/read-chunk.c @@ -38,7 +38,7 @@ main(int argc, char *argv[]) { return EXIT_FAILURE; } - rv = sqsh_file_reader_advance(reader, atoi(argv[3]), atoi(argv[4])); + rv = sqsh_file_reader_advance2(reader, atoi(argv[3]), atoi(argv[4])); if (rv < 0) { sqsh_perror(rv, "sqsh_file_reader_advance"); return EXIT_FAILURE; diff --git a/tools/src/fs-common.c b/tools/src/fs-common.c index e4f610313..6522b56be 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; } From 1f59646766237a520e75375001647490e40522c1 Mon Sep 17 00:00:00 2001 From: Enno Boland Date: Mon, 12 Aug 2024 18:16:41 +0200 Subject: [PATCH 4/4] file: make block_count uint64_t --- include/sqsh_file.h | 17 ++++++++++++++++- libsqsh/src/file/file.c | 16 ++++++++++++---- libsqsh/src/file/file_iterator.c | 8 ++++---- tools/src/stat.c | 7 +++---- 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/include/sqsh_file.h b/include/sqsh_file.h index 1eacb5002..91375987e 100644 --- a/include/sqsh_file.h +++ b/include/sqsh_file.h @@ -425,6 +425,7 @@ uint32_t sqsh_file_modified_time(const struct SqshFile *context); uint64_t sqsh_file_blocks_start(const struct SqshFile *context); /** + * @deprecated Since 1.5.0. Use sqsh_file_blockcount2() instead. * @memberof SqshFile * @brief Getter for the amount of blocks of the file content. This is only * internally used and will be used while retrieving the file content. @@ -434,7 +435,21 @@ uint64_t sqsh_file_blocks_start(const struct SqshFile *context); * @return the amount of blocks of the file content. If the file is not of * of type SQSH_FILE_TYPE_FILE, UINT32_MAX will be returned. */ -uint32_t sqsh_file_block_count(const struct SqshFile *context); +__attribute__((deprecated("Since 1.5.0. Use sqsh_file_blockcount2() instead."))) +uint32_t +sqsh_file_block_count(const struct SqshFile *context); + +/** + * @memberof SqshFile + * @brief Getter for the amount of blocks of the file content. This is only + * internally used and will be used while retrieving the file content. + * + * @param[in] context The file context. + * + * @return the amount of blocks of the file content. If the file is not of + * of type SQSH_FILE_TYPE_FILE, UINT32_MAX will be returned. + */ +uint64_t sqsh_file_block_count2(const struct SqshFile *context); /** * @memberof SqshFile diff --git a/libsqsh/src/file/file.c b/libsqsh/src/file/file.c index 1a62ad9f9..6baa9eaca 100644 --- a/libsqsh/src/file/file.c +++ b/libsqsh/src/file/file.c @@ -282,16 +282,15 @@ sqsh_file_blocks_start(const struct SqshFile *context) { return context->impl->blocks_start(get_inode(context)); } -// TODO: reconsider the return type of this function. -uint32_t -sqsh_file_block_count(const struct SqshFile *context) { +uint64_t +sqsh_file_block_count2(const struct SqshFile *context) { const struct SqshSuperblock *superblock = sqsh_archive_superblock(context->archive); uint64_t file_size = sqsh_file_size(context); uint32_t block_size = sqsh_superblock_block_size(superblock); if (file_size == UINT64_MAX) { - return UINT32_MAX; + return UINT64_MAX; } else if (file_size == 0) { return 0; } else if (sqsh_file_has_fragment(context)) { @@ -301,6 +300,15 @@ sqsh_file_block_count(const struct SqshFile *context) { } } +uint32_t +sqsh_file_block_count(const struct SqshFile *context) { + uint64_t block_count = sqsh_file_block_count2(context); + if (block_count > UINT32_MAX) { + return UINT32_MAX; + } + return (uint32_t)block_count; +} + uint32_t sqsh_file_block_size(const struct SqshFile *context, uint32_t index) { const uint32_t size_info = diff --git a/libsqsh/src/file/file_iterator.c b/libsqsh/src/file/file_iterator.c index 608fa35d5..9dd96e287 100644 --- a/libsqsh/src/file/file_iterator.c +++ b/libsqsh/src/file/file_iterator.c @@ -46,7 +46,7 @@ is_last_block(const struct SqshFileIterator *iterator) { const struct SqshFile *file = iterator->file; const bool has_fragment = sqsh_file_has_fragment(file); const sqsh_index_t block_index = iterator->block_index; - const size_t block_count = sqsh_file_block_count(file); + const uint64_t block_count = sqsh_file_block_count2(file); if (has_fragment) { return block_index == block_count; @@ -138,7 +138,7 @@ map_block_uncompressed( const struct SqshFile *file = iterator->file; uint32_t block_index = iterator->block_index; struct SqshMapReader *reader = &iterator->map_reader; - const uint64_t block_count = sqsh_file_block_count(file); + const uint64_t block_count = sqsh_file_block_count2(file); size_t outer_size = 0; const size_t remaining_direct = sqsh__map_reader_remaining_direct(reader); @@ -265,7 +265,7 @@ sqsh_file_iterator_next( struct SqshFileIterator *iterator, size_t desired_size, int *err) { int rv = 0; const struct SqshFile *file = iterator->file; - size_t block_count = sqsh_file_block_count(file); + const uint64_t block_count = sqsh_file_block_count2(file); const bool has_fragment = sqsh_file_has_fragment(file); bool has_next = true; @@ -338,7 +338,7 @@ sqsh_file_iterator_skip2( sqsh_index_t reader_forward = 0; uint32_t block_index = iterator->block_index; - const size_t block_count = sqsh_file_block_count(iterator->file); + const uint64_t block_count = sqsh_file_block_count2(iterator->file); for (sqsh_index_t i = 0; i < skip_index && block_index < block_count; i++) { reader_forward += sqsh_file_block_size(iterator->file, block_index); block_index += 1; diff --git a/tools/src/stat.c b/tools/src/stat.c index 83ebf72da..9523e1f74 100644 --- a/tools/src/stat.c +++ b/tools/src/stat.c @@ -33,9 +33,7 @@ #include -#include #include -#include #include #include #include @@ -294,8 +292,9 @@ stat_file(struct SqshArchive *archive, const char *path) { printf(" fragment offset: %i\n", sqsh_file_fragment_block_offset(file)); } - printf(" number of blocks: %i\n", sqsh_file_block_count(file)); - for (uint32_t i = 0; i < sqsh_file_block_count(file); i++) { + printf(" number of blocks: %" PRIu64 "\n", + sqsh_file_block_count2(file)); + for (uint32_t i = 0; i < sqsh_file_block_count2(file); i++) { bool is_compressed = sqsh_file_block_is_compressed(file, i); uint32_t size = sqsh_file_block_size(file, i);