[Buildroot] [PATCH 3/3] package/assimp: fix build on musl
Peter Seiderer
ps.report at gmx.net
Tue Dec 29 20:54:43 UTC 2020
Hello Fabrice, Yann,
On Mon, 28 Dec 2020 13:01:02 +0100, Fabrice Fontaine <fontaine.fabrice at gmail.com> wrote:
> Fixes:
> - http://autobuild.buildroot.net/results/7c2db184ee200d1719308f38f42382bb39d8d5c6
>
> Signed-off-by: Fabrice Fontaine <fontaine.fabrice at gmail.com>
> ---
> ...p-to-fix-gcc-build-for-v9-2-0-32-bit.patch | 1638 +++++++++++++++++
> ...oses-2954-upgrade-to-latest-greatest.patch | 243 +++
> 2 files changed, 1881 insertions(+)
> create mode 100644 package/assimp/0002-closes-2733-update-of-zlip-to-fix-gcc-build-for-v9-2-0-32-bit.patch
Note that this patch is enough to re-fix the musl compile (as it is the complete
one from which the small patch was extracted which you removed/reverted with
'[PATCH 1/3] Revert "package/assimp: fix musl zlib/zip related compile failure"'
Regards,
Peter
> create mode 100644 package/assimp/0003-closes-2954-upgrade-to-latest-greatest.patch
>
> diff --git a/package/assimp/0002-closes-2733-update-of-zlip-to-fix-gcc-build-for-v9-2-0-32-bit.patch b/package/assimp/0002-closes-2733-update-of-zlip-to-fix-gcc-build-for-v9-2-0-32-bit.patch
> new file mode 100644
> index 0000000000..4b86cc584f
> --- /dev/null
> +++ b/package/assimp/0002-closes-2733-update-of-zlip-to-fix-gcc-build-for-v9-2-0-32-bit.patch
> @@ -0,0 +1,1638 @@
> +From f78446b14aff46db2ef27d062a275b6a01fd68b1 Mon Sep 17 00:00:00 2001
> +From: Kim Kulling <kim.kulling at googlemail.com>
> +Date: Tue, 19 Nov 2019 20:30:40 +0100
> +Subject: [PATCH] closes https://github.com/assimp/assimp/issues/2733: update
> + of zlip to fix gcc build for v9.2.0 32 bit
> +
> +[Retrieved (and updated to remove .gitignore and appveyor.yml) from:
> +https://github.com/assimp/assimp/commit/f78446b14aff46db2ef27d062a275b6a01fd68b1]
> +Signed-off-by: Fabrice Fontaine <fontaine.fabrice at gmail.com>
> +---
> + contrib/zip/.gitignore | 2 +
> + contrib/zip/CMakeLists.txt | 83 +++++-
> + contrib/zip/README.md | 12 +-
> + contrib/zip/appveyor.yml | 2 +-
> + contrib/zip/src/miniz.h | 457 ++++++++++++++++++++++++++++----
> + contrib/zip/src/zip.c | 62 +++--
> + contrib/zip/src/zip.h | 457 ++++++++++++++++----------------
> + contrib/zip/test/CMakeLists.txt | 27 +-
> + contrib/zip/test/test.c | 38 ++-
> + contrib/zip/test/test_miniz.c | 25 +-
> + 10 files changed, 821 insertions(+), 344 deletions(-)
> +
> +diff --git a/contrib/zip/CMakeLists.txt b/contrib/zip/CMakeLists.txt
> +index b46dbb1db0..77916d2e14 100644
> +--- a/contrib/zip/CMakeLists.txt
> ++++ b/contrib/zip/CMakeLists.txt
> +@@ -1,10 +1,14 @@
> +-cmake_minimum_required(VERSION 2.8)
> +-project(zip)
> +-enable_language(C)
> ++cmake_minimum_required(VERSION 3.0)
> ++
> ++project(zip
> ++ LANGUAGES C
> ++ VERSION "0.1.15")
> + set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
> +
> ++option(CMAKE_DISABLE_TESTING "Disable test creation" OFF)
> ++
> + if (MSVC)
> +- # Use secure functions by defaualt and suppress warnings about "deprecated" functions
> ++ # Use secure functions by default and suppress warnings about "deprecated" functions
> + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1")
> + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
> + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
> +@@ -12,28 +16,80 @@ elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR
> + "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR
> + "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")
> + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall -Wextra -Werror -pedantic")
> ++ if(ENABLE_COVERAGE)
> ++ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
> ++ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
> ++ endif()
> + endif (MSVC)
> +
> + # zip
> + set(SRC src/miniz.h src/zip.h src/zip.c)
> + add_library(${PROJECT_NAME} ${SRC})
> +-target_include_directories(${PROJECT_NAME} INTERFACE src)
> ++target_include_directories(${PROJECT_NAME} PUBLIC
> ++ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
> ++ $<INSTALL_INTERFACE:include>
> ++)
> +
> + # test
> + if (NOT CMAKE_DISABLE_TESTING)
> + enable_testing()
> + add_subdirectory(test)
> + find_package(Sanitizers)
> +- add_sanitizers(${PROJECT_NAME} test.exe)
> +- add_sanitizers(${PROJECT_NAME} test_miniz.exe)
> ++ add_sanitizers(${PROJECT_NAME} ${test_out} ${test_miniz_out})
> + endif()
> +
> ++####
> ++# Installation (https://github.com/forexample/package-example) {
> ++
> ++set(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}")
> ++set(INCLUDE_INSTALL_DIR "include")
> ++
> ++set(GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
> ++
> ++# Configuration
> ++set(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
> ++set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake")
> ++set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
> ++set(NAMESPACE "${PROJECT_NAME}::")
> ++
> ++# Include module with fuction 'write_basic_package_version_file'
> ++include(CMakePackageConfigHelpers)
> ++
> ++# Note: PROJECT_VERSION is used as a VERSION
> ++write_basic_package_version_file(
> ++ "${VERSION_CONFIG}" COMPATIBILITY SameMajorVersion
> ++)
> ++
> ++# Use variables:
> ++# * TARGETS_EXPORT_NAME
> ++# * PROJECT_NAME
> ++configure_package_config_file(
> ++ "cmake/Config.cmake.in"
> ++ "${PROJECT_CONFIG}"
> ++ INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}"
> ++)
> ++
> ++install(
> ++ FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}"
> ++ DESTINATION "${CONFIG_INSTALL_DIR}"
> ++)
> ++
> ++install(
> ++ EXPORT "${TARGETS_EXPORT_NAME}"
> ++ NAMESPACE "${NAMESPACE}"
> ++ DESTINATION "${CONFIG_INSTALL_DIR}"
> ++)
> ++
> ++# }
> ++
> + install(TARGETS ${PROJECT_NAME}
> ++ EXPORT ${TARGETS_EXPORT_NAME}
> + RUNTIME DESTINATION bin
> + ARCHIVE DESTINATION lib
> + LIBRARY DESTINATION lib
> +- COMPONENT library)
> +-install(FILES ${PROJECT_SOURCE_DIR}/src/zip.h DESTINATION include)
> ++ INCLUDES DESTINATION ${INCLUDE_INSTALL_DIR}
> ++)
> ++install(FILES ${PROJECT_SOURCE_DIR}/src/zip.h DESTINATION ${INCLUDE_INSTALL_DIR}/zip)
> +
> + # uninstall target (https://gitlab.kitware.com/cmake/community/wikis/FAQ#can-i-do-make-uninstall-with-cmake)
> + if(NOT TARGET uninstall)
> +@@ -45,3 +101,12 @@ if(NOT TARGET uninstall)
> + add_custom_target(uninstall
> + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake)
> + endif()
> ++
> ++find_package(Doxygen)
> ++if(DOXYGEN_FOUND)
> ++ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
> ++ add_custom_target(doc
> ++ ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
> ++ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
> ++ COMMENT "Generating API documentation with Doxygen" VERBATIM)
> ++endif()
> +diff --git a/contrib/zip/README.md b/contrib/zip/README.md
> +index d5fb8cd203..14eb9a34c8 100644
> +--- a/contrib/zip/README.md
> ++++ b/contrib/zip/README.md
> +@@ -71,7 +71,7 @@ int arg = 2;
> + zip_extract("foo.zip", "/tmp", on_extract_entry, &arg);
> + ```
> +
> +-* Extract a zip entry into memory.
> ++* Extract a zip entry into memory.
> + ```c
> + void *buf = NULL;
> + size_t bufsize;
> +@@ -89,7 +89,7 @@ zip_close(zip);
> + free(buf);
> + ```
> +
> +-* Extract a zip entry into memory (no internal allocation).
> ++* Extract a zip entry into memory (no internal allocation).
> + ```c
> + unsigned char *buf;
> + size_t bufsize;
> +@@ -110,7 +110,7 @@ zip_close(zip);
> + free(buf);
> + ```
> +
> +-* Extract a zip entry into memory using callback.
> ++* Extract a zip entry into memory using callback.
> + ```c
> + struct buffer_t {
> + char *data;
> +@@ -144,7 +144,7 @@ free(buf.data);
> + ```
> +
> +
> +-* Extract a zip entry into a file.
> ++* Extract a zip entry into a file.
> + ```c
> + struct zip_t *zip = zip_open("foo.zip", 0, 'r');
> + {
> +@@ -157,7 +157,7 @@ struct zip_t *zip = zip_open("foo.zip", 0, 'r');
> + zip_close(zip);
> + ```
> +
> +-* List of all zip entries
> ++* List of all zip entries
> + ```c
> + struct zip_t *zip = zip_open("foo.zip", 0, 'r');
> + int i, n = zip_total_entries(zip);
> +@@ -174,7 +174,7 @@ for (i = 0; i < n; ++i) {
> + zip_close(zip);
> + ```
> +
> +-## Bindings
> ++# Bindings
> + Compile zip library as a dynamic library.
> + ```shell
> + $ mkdir build
> +diff --git a/contrib/zip/src/miniz.h b/contrib/zip/src/miniz.h
> +index 2c27a94d8d..c4fcfb83e6 100644
> +--- a/contrib/zip/src/miniz.h
> ++++ b/contrib/zip/src/miniz.h
> +@@ -221,6 +221,7 @@
> + #ifndef MINIZ_HEADER_INCLUDED
> + #define MINIZ_HEADER_INCLUDED
> +
> ++#include <stdint.h>
> + #include <stdlib.h>
> +
> + // Defines to completely disable specific portions of miniz.c:
> +@@ -284,7 +285,8 @@
> + /* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES only if not set */
> + #if !defined(MINIZ_USE_UNALIGNED_LOADS_AND_STORES)
> + #if MINIZ_X86_OR_X64_CPU
> +-/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses. */
> ++/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient
> ++ * integer loads and stores from unaligned addresses. */
> + #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
> + #define MINIZ_UNALIGNED_USE_MEMCPY
> + #else
> +@@ -354,6 +356,44 @@ enum {
> + MZ_FIXED = 4
> + };
> +
> ++/* miniz error codes. Be sure to update mz_zip_get_error_string() if you add or
> ++ * modify this enum. */
> ++typedef enum {
> ++ MZ_ZIP_NO_ERROR = 0,
> ++ MZ_ZIP_UNDEFINED_ERROR,
> ++ MZ_ZIP_TOO_MANY_FILES,
> ++ MZ_ZIP_FILE_TOO_LARGE,
> ++ MZ_ZIP_UNSUPPORTED_METHOD,
> ++ MZ_ZIP_UNSUPPORTED_ENCRYPTION,
> ++ MZ_ZIP_UNSUPPORTED_FEATURE,
> ++ MZ_ZIP_FAILED_FINDING_CENTRAL_DIR,
> ++ MZ_ZIP_NOT_AN_ARCHIVE,
> ++ MZ_ZIP_INVALID_HEADER_OR_CORRUPTED,
> ++ MZ_ZIP_UNSUPPORTED_MULTIDISK,
> ++ MZ_ZIP_DECOMPRESSION_FAILED,
> ++ MZ_ZIP_COMPRESSION_FAILED,
> ++ MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE,
> ++ MZ_ZIP_CRC_CHECK_FAILED,
> ++ MZ_ZIP_UNSUPPORTED_CDIR_SIZE,
> ++ MZ_ZIP_ALLOC_FAILED,
> ++ MZ_ZIP_FILE_OPEN_FAILED,
> ++ MZ_ZIP_FILE_CREATE_FAILED,
> ++ MZ_ZIP_FILE_WRITE_FAILED,
> ++ MZ_ZIP_FILE_READ_FAILED,
> ++ MZ_ZIP_FILE_CLOSE_FAILED,
> ++ MZ_ZIP_FILE_SEEK_FAILED,
> ++ MZ_ZIP_FILE_STAT_FAILED,
> ++ MZ_ZIP_INVALID_PARAMETER,
> ++ MZ_ZIP_INVALID_FILENAME,
> ++ MZ_ZIP_BUF_TOO_SMALL,
> ++ MZ_ZIP_INTERNAL_ERROR,
> ++ MZ_ZIP_FILE_NOT_FOUND,
> ++ MZ_ZIP_ARCHIVE_TOO_LARGE,
> ++ MZ_ZIP_VALIDATION_FAILED,
> ++ MZ_ZIP_WRITE_CALLBACK_FAILED,
> ++ MZ_ZIP_TOTAL_ERRORS
> ++} mz_zip_error;
> ++
> + // Method
> + #define MZ_DEFLATED 8
> +
> +@@ -696,6 +736,7 @@ typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs,
> + void *pBuf, size_t n);
> + typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs,
> + const void *pBuf, size_t n);
> ++typedef mz_bool (*mz_file_needs_keepalive)(void *pOpaque);
> +
> + struct mz_zip_internal_state_tag;
> + typedef struct mz_zip_internal_state_tag mz_zip_internal_state;
> +@@ -707,13 +748,27 @@ typedef enum {
> + MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3
> + } mz_zip_mode;
> +
> +-typedef struct mz_zip_archive_tag {
> ++typedef enum {
> ++ MZ_ZIP_TYPE_INVALID = 0,
> ++ MZ_ZIP_TYPE_USER,
> ++ MZ_ZIP_TYPE_MEMORY,
> ++ MZ_ZIP_TYPE_HEAP,
> ++ MZ_ZIP_TYPE_FILE,
> ++ MZ_ZIP_TYPE_CFILE,
> ++ MZ_ZIP_TOTAL_TYPES
> ++} mz_zip_type;
> ++
> ++typedef struct {
> + mz_uint64 m_archive_size;
> + mz_uint64 m_central_directory_file_ofs;
> +- mz_uint m_total_files;
> ++
> ++ /* We only support up to UINT32_MAX files in zip64 mode. */
> ++ mz_uint32 m_total_files;
> + mz_zip_mode m_zip_mode;
> ++ mz_zip_type m_zip_type;
> ++ mz_zip_error m_last_error;
> +
> +- mz_uint m_file_offset_alignment;
> ++ mz_uint64 m_file_offset_alignment;
> +
> + mz_alloc_func m_pAlloc;
> + mz_free_func m_pFree;
> +@@ -722,6 +777,7 @@ typedef struct mz_zip_archive_tag {
> +
> + mz_file_read_func m_pRead;
> + mz_file_write_func m_pWrite;
> ++ mz_file_needs_keepalive m_pNeeds_keepalive;
> + void *m_pIO_opaque;
> +
> + mz_zip_internal_state *m_pState;
> +@@ -1263,6 +1319,9 @@ mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits,
> + int strategy);
> + #endif // #ifndef MINIZ_NO_ZLIB_APIS
> +
> ++#define MZ_UINT16_MAX (0xFFFFU)
> ++#define MZ_UINT32_MAX (0xFFFFFFFFU)
> ++
> + #ifdef __cplusplus
> + }
> + #endif
> +@@ -1311,6 +1370,11 @@ typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1];
> + ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U))
> + #endif
> +
> ++#define MZ_READ_LE64(p) \
> ++ (((mz_uint64)MZ_READ_LE32(p)) | \
> ++ (((mz_uint64)MZ_READ_LE32((const mz_uint8 *)(p) + sizeof(mz_uint32))) \
> ++ << 32U))
> ++
> + #ifdef _MSC_VER
> + #define MZ_FORCEINLINE __forceinline
> + #elif defined(__GNUC__)
> +@@ -4160,6 +4224,17 @@ enum {
> + MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30,
> + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46,
> + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
> ++
> ++ /* ZIP64 archive identifier and record sizes */
> ++ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50,
> ++ MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50,
> ++ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56,
> ++ MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20,
> ++ MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001,
> ++ MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50,
> ++ MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24,
> ++ MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16,
> ++
> + // Central directory header record offsets
> + MZ_ZIP_CDH_SIG_OFS = 0,
> + MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4,
> +@@ -4199,6 +4274,31 @@ enum {
> + MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12,
> + MZ_ZIP_ECDH_CDIR_OFS_OFS = 16,
> + MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
> ++
> ++ /* ZIP64 End of central directory locator offsets */
> ++ MZ_ZIP64_ECDL_SIG_OFS = 0, /* 4 bytes */
> ++ MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4, /* 4 bytes */
> ++ MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8, /* 8 bytes */
> ++ MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */
> ++
> ++ /* ZIP64 End of central directory header offsets */
> ++ MZ_ZIP64_ECDH_SIG_OFS = 0, /* 4 bytes */
> ++ MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4, /* 8 bytes */
> ++ MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12, /* 2 bytes */
> ++ MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14, /* 2 bytes */
> ++ MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16, /* 4 bytes */
> ++ MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20, /* 4 bytes */
> ++ MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */
> ++ MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32, /* 8 bytes */
> ++ MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40, /* 8 bytes */
> ++ MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48, /* 8 bytes */
> ++ MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0,
> ++ MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10,
> ++ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1,
> ++ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32,
> ++ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64,
> ++ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192,
> ++ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11
> + };
> +
> + typedef struct {
> +@@ -4211,7 +4311,24 @@ struct mz_zip_internal_state_tag {
> + mz_zip_array m_central_dir;
> + mz_zip_array m_central_dir_offsets;
> + mz_zip_array m_sorted_central_dir_offsets;
> ++
> ++ /* The flags passed in when the archive is initially opened. */
> ++ uint32_t m_init_flags;
> ++
> ++ /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc.
> ++ */
> ++ mz_bool m_zip64;
> ++
> ++ /* MZ_TRUE if we found zip64 extended info in the central directory (m_zip64
> ++ * will also be slammed to true too, even if we didn't find a zip64 end of
> ++ * central dir header, etc.) */
> ++ mz_bool m_zip64_has_extended_info_fields;
> ++
> ++ /* These fields are used by the file, FILE, memory, and memory/heap read/write
> ++ * helpers. */
> + MZ_FILE *m_pFile;
> ++ mz_uint64 m_file_archive_start_ofs;
> ++
> + void *m_pMem;
> + size_t m_mem_size;
> + size_t m_mem_capacity;
> +@@ -4363,6 +4480,13 @@ static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time,
> + #endif /* #ifndef MINIZ_NO_STDIO */
> + #endif /* #ifndef MINIZ_NO_TIME */
> +
> ++static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip,
> ++ mz_zip_error err_num) {
> ++ if (pZip)
> ++ pZip->m_last_error = err_num;
> ++ return MZ_FALSE;
> ++}
> ++
> + static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip,
> + mz_uint32 flags) {
> + (void)flags;
> +@@ -4480,127 +4604,346 @@ mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip) {
> + }
> + }
> +
> +-static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip,
> +- mz_uint32 flags) {
> +- mz_uint cdir_size, num_this_disk, cdir_disk_index;
> +- mz_uint64 cdir_ofs;
> ++static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip,
> ++ mz_uint32 record_sig,
> ++ mz_uint32 record_size,
> ++ mz_int64 *pOfs) {
> + mz_int64 cur_file_ofs;
> +- const mz_uint8 *p;
> + mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
> + mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
> +- mz_bool sort_central_dir =
> +- ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
> +- // Basic sanity checks - reject files which are too small, and check the first
> +- // 4 bytes of the file to make sure a local header is there.
> +- if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
> ++
> ++ /* Basic sanity checks - reject files which are too small */
> ++ if (pZip->m_archive_size < record_size)
> + return MZ_FALSE;
> +- // Find the end of central directory record by scanning the file from the end
> +- // towards the beginning.
> ++
> ++ /* Find the record by scanning the file from the end towards the beginning. */
> + cur_file_ofs =
> + MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
> + for (;;) {
> + int i,
> + n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
> ++
> + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
> + return MZ_FALSE;
> +- for (i = n - 4; i >= 0; --i)
> +- if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
> +- break;
> ++
> ++ for (i = n - 4; i >= 0; --i) {
> ++ mz_uint s = MZ_READ_LE32(pBuf + i);
> ++ if (s == record_sig) {
> ++ if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)
> ++ break;
> ++ }
> ++ }
> ++
> + if (i >= 0) {
> + cur_file_ofs += i;
> + break;
> + }
> ++
> ++ /* Give up if we've searched the entire file, or we've gone back "too far"
> ++ * (~64kb) */
> + if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >=
> +- (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
> ++ (MZ_UINT16_MAX + record_size)))
> + return MZ_FALSE;
> ++
> + cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
> + }
> +- // Read and verify the end of central directory record.
> ++
> ++ *pOfs = cur_file_ofs;
> ++ return MZ_TRUE;
> ++}
> ++
> ++static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip,
> ++ mz_uint flags) {
> ++ mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0,
> ++ cdir_disk_index = 0;
> ++ mz_uint64 cdir_ofs = 0;
> ++ mz_int64 cur_file_ofs = 0;
> ++ const mz_uint8 *p;
> ++
> ++ mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
> ++ mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
> ++ mz_bool sort_central_dir =
> ++ ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
> ++ mz_uint32 zip64_end_of_central_dir_locator_u32
> ++ [(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) /
> ++ sizeof(mz_uint32)];
> ++ mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32;
> ++
> ++ mz_uint32 zip64_end_of_central_dir_header_u32
> ++ [(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
> ++ sizeof(mz_uint32)];
> ++ mz_uint8 *pZip64_end_of_central_dir =
> ++ (mz_uint8 *)zip64_end_of_central_dir_header_u32;
> ++
> ++ mz_uint64 zip64_end_of_central_dir_ofs = 0;
> ++
> ++ /* Basic sanity checks - reject files which are too small, and check the first
> ++ * 4 bytes of the file to make sure a local header is there. */
> ++ if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
> ++ return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
> ++
> ++ if (!mz_zip_reader_locate_header_sig(
> ++ pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG,
> ++ MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs))
> ++ return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR);
> ++
> ++ /* Read and verify the end of central directory record. */
> + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf,
> + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) !=
> + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
> +- return MZ_FALSE;
> +- if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) !=
> +- MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) ||
> +- ((pZip->m_total_files =
> +- MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) !=
> +- MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS)))
> +- return MZ_FALSE;
> ++ return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
> ++
> ++ if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) !=
> ++ MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
> ++ return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
> ++
> ++ if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE +
> ++ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) {
> ++ if (pZip->m_pRead(pZip->m_pIO_opaque,
> ++ cur_file_ofs - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE,
> ++ pZip64_locator,
> ++ MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) ==
> ++ MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) {
> ++ if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) ==
> ++ MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG) {
> ++ zip64_end_of_central_dir_ofs = MZ_READ_LE64(
> ++ pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS);
> ++ if (zip64_end_of_central_dir_ofs >
> ++ (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
> ++ return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
> ++
> ++ if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs,
> ++ pZip64_end_of_central_dir,
> ++ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) ==
> ++ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) {
> ++ if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) ==
> ++ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG) {
> ++ pZip->m_pState->m_zip64 = MZ_TRUE;
> ++ }
> ++ }
> ++ }
> ++ }
> ++ }
> +
> ++ pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS);
> ++ cdir_entries_on_this_disk =
> ++ MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
> + num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
> + cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
> ++ cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS);
> ++ cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
> ++
> ++ if (pZip->m_pState->m_zip64) {
> ++ mz_uint32 zip64_total_num_of_disks =
> ++ MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS);
> ++ mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(
> ++ pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS);
> ++ mz_uint64 zip64_cdir_total_entries_on_this_disk = MZ_READ_LE64(
> ++ pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
> ++ mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64(
> ++ pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS);
> ++ mz_uint64 zip64_size_of_central_directory =
> ++ MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS);
> ++
> ++ if (zip64_size_of_end_of_central_dir_record <
> ++ (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12))
> ++ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
> ++
> ++ if (zip64_total_num_of_disks != 1U)
> ++ return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
> ++
> ++ /* Check for miniz's practical limits */
> ++ if (zip64_cdir_total_entries > MZ_UINT32_MAX)
> ++ return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
> ++
> ++ pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries;
> ++
> ++ if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX)
> ++ return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
> ++
> ++ cdir_entries_on_this_disk =
> ++ (mz_uint32)zip64_cdir_total_entries_on_this_disk;
> ++
> ++ /* Check for miniz's current practical limits (sorry, this should be enough
> ++ * for millions of files) */
> ++ if (zip64_size_of_central_directory > MZ_UINT32_MAX)
> ++ return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
> ++
> ++ cdir_size = (mz_uint32)zip64_size_of_central_directory;
> ++
> ++ num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir +
> ++ MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS);
> ++
> ++ cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir +
> ++ MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS);
> ++
> ++ cdir_ofs =
> ++ MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS);
> ++ }
> ++
> ++ if (pZip->m_total_files != cdir_entries_on_this_disk)
> ++ return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
> ++
> + if (((num_this_disk | cdir_disk_index) != 0) &&
> + ((num_this_disk != 1) || (cdir_disk_index != 1)))
> +- return MZ_FALSE;
> ++ return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
> +
> +- if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) <
> +- pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
> +- return MZ_FALSE;
> ++ if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
> ++ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
> +
> +- cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
> + if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
> +- return MZ_FALSE;
> ++ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
> +
> + pZip->m_central_directory_file_ofs = cdir_ofs;
> +
> + if (pZip->m_total_files) {
> + mz_uint i, n;
> +-
> +- // Read the entire central directory into a heap block, and allocate another
> +- // heap block to hold the unsorted central dir file record offsets, and
> +- // another to hold the sorted indices.
> ++ /* Read the entire central directory into a heap block, and allocate another
> ++ * heap block to hold the unsorted central dir file record offsets, and
> ++ * possibly another to hold the sorted indices. */
> + if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size,
> + MZ_FALSE)) ||
> + (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets,
> + pZip->m_total_files, MZ_FALSE)))
> +- return MZ_FALSE;
> ++ return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
> +
> + if (sort_central_dir) {
> + if (!mz_zip_array_resize(pZip,
> + &pZip->m_pState->m_sorted_central_dir_offsets,
> + pZip->m_total_files, MZ_FALSE))
> +- return MZ_FALSE;
> ++ return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
> + }
> +
> + if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs,
> + pZip->m_pState->m_central_dir.m_p,
> + cdir_size) != cdir_size)
> +- return MZ_FALSE;
> ++ return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
> +
> +- // Now create an index into the central directory file records, do some
> +- // basic sanity checking on each record, and check for zip64 entries (which
> +- // are not yet supported).
> ++ /* Now create an index into the central directory file records, do some
> ++ * basic sanity checking on each record */
> + p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
> + for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) {
> +- mz_uint total_header_size, comp_size, decomp_size, disk_index;
> ++ mz_uint total_header_size, disk_index, bit_flags, filename_size,
> ++ ext_data_size;
> ++ mz_uint64 comp_size, decomp_size, local_header_ofs;
> ++
> + if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) ||
> + (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
> +- return MZ_FALSE;
> ++ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
> ++
> + MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
> + i) =
> + (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);
> ++
> + if (sort_central_dir)
> + MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets,
> + mz_uint32, i) = i;
> ++
> + comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
> + decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
> +- if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) &&
> +- (decomp_size != comp_size)) ||
> +- (decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) ||
> +- (comp_size == 0xFFFFFFFF))
> +- return MZ_FALSE;
> ++ local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
> ++ filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
> ++ ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
> ++
> ++ if ((!pZip->m_pState->m_zip64_has_extended_info_fields) &&
> ++ (ext_data_size) &&
> ++ (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) ==
> ++ MZ_UINT32_MAX)) {
> ++ /* Attempt to find zip64 extended information field in the entry's extra
> ++ * data */
> ++ mz_uint32 extra_size_remaining = ext_data_size;
> ++
> ++ if (extra_size_remaining) {
> ++ const mz_uint8 *pExtra_data;
> ++ void *buf = NULL;
> ++
> ++ if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size >
> ++ n) {
> ++ buf = MZ_MALLOC(ext_data_size);
> ++ if (buf == NULL)
> ++ return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
> ++
> ++ if (pZip->m_pRead(pZip->m_pIO_opaque,
> ++ cdir_ofs + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
> ++ filename_size,
> ++ buf, ext_data_size) != ext_data_size) {
> ++ MZ_FREE(buf);
> ++ return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
> ++ }
> ++
> ++ pExtra_data = (mz_uint8 *)buf;
> ++ } else {
> ++ pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size;
> ++ }
> ++
> ++ do {
> ++ mz_uint32 field_id;
> ++ mz_uint32 field_data_size;
> ++
> ++ if (extra_size_remaining < (sizeof(mz_uint16) * 2)) {
> ++ MZ_FREE(buf);
> ++ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
> ++ }
> ++
> ++ field_id = MZ_READ_LE16(pExtra_data);
> ++ field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
> ++
> ++ if ((field_data_size + sizeof(mz_uint16) * 2) >
> ++ extra_size_remaining) {
> ++ MZ_FREE(buf);
> ++ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
> ++ }
> ++
> ++ if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) {
> ++ /* Ok, the archive didn't have any zip64 headers but it uses a
> ++ * zip64 extended information field so mark it as zip64 anyway
> ++ * (this can occur with infozip's zip util when it reads
> ++ * compresses files from stdin). */
> ++ pZip->m_pState->m_zip64 = MZ_TRUE;
> ++ pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE;
> ++ break;
> ++ }
> ++
> ++ pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
> ++ extra_size_remaining =
> ++ extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
> ++ } while (extra_size_remaining);
> ++
> ++ MZ_FREE(buf);
> ++ }
> ++ }
> ++
> ++ /* I've seen archives that aren't marked as zip64 that uses zip64 ext
> ++ * data, argh */
> ++ if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX)) {
> ++ if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) &&
> ++ (decomp_size != comp_size)) ||
> ++ (decomp_size && !comp_size))
> ++ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
> ++ }
> ++
> + disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
> +- if ((disk_index != num_this_disk) && (disk_index != 1))
> +- return MZ_FALSE;
> +- if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) +
> +- MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
> +- return MZ_FALSE;
> ++ if ((disk_index == MZ_UINT16_MAX) ||
> ++ ((disk_index != num_this_disk) && (disk_index != 1)))
> ++ return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
> ++
> ++ if (comp_size != MZ_UINT32_MAX) {
> ++ if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) +
> ++ MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
> ++ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
> ++ }
> ++
> ++ bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
> ++ if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED)
> ++ return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
> ++
> + if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
> + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
> + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) +
> + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) >
> + n)
> +- return MZ_FALSE;
> ++ return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
> ++
> + n -= total_header_size;
> + p += total_header_size;
> + }
> +diff --git a/contrib/zip/src/zip.c b/contrib/zip/src/zip.c
> +index ff3a8fe1e6..1abcfd8fd1 100644
> +--- a/contrib/zip/src/zip.c
> ++++ b/contrib/zip/src/zip.c
> +@@ -24,7 +24,6 @@
> + ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) && \
> + (P)[1] == ':')
> + #define FILESYSTEM_PREFIX_LEN(P) (HAS_DEVICE(P) ? 2 : 0)
> +-#define ISSLASH(C) ((C) == '/' || (C) == '\\')
> +
> + #else
> +
> +@@ -48,7 +47,7 @@ int symlink(const char *target, const char *linkpath); // needed on Linux
> + #endif
> +
> + #ifndef ISSLASH
> +-#define ISSLASH(C) ((C) == '/')
> ++#define ISSLASH(C) ((C) == '/' || (C) == '\\')
> + #endif
> +
> + #define CLEANUP(ptr) \
> +@@ -78,26 +77,34 @@ static const char *base_name(const char *name) {
> + return base;
> + }
> +
> +-static int mkpath(const char *path) {
> +- char const *p;
> ++static int mkpath(char *path) {
> ++ char *p;
> + char npath[MAX_PATH + 1];
> + int len = 0;
> + int has_device = HAS_DEVICE(path);
> +
> + memset(npath, 0, MAX_PATH + 1);
> +-
> +-#ifdef _WIN32
> +- // only on windows fix the path
> +- npath[0] = path[0];
> +- npath[1] = path[1];
> +- len = 2;
> +-#endif // _WIN32
> +-
> ++ if (has_device) {
> ++ // only on windows
> ++ npath[0] = path[0];
> ++ npath[1] = path[1];
> ++ len = 2;
> ++ }
> + for (p = path + len; *p && len < MAX_PATH; p++) {
> + if (ISSLASH(*p) && ((!has_device && len > 0) || (has_device && len > 2))) {
> +- if (MKDIR(npath) == -1)
> +- if (errno != EEXIST)
> ++#if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \
> ++ defined(__MINGW32__)
> ++#else
> ++ if ('\\' == *p) {
> ++ *p = '/';
> ++ }
> ++#endif
> ++
> ++ if (MKDIR(npath) == -1) {
> ++ if (errno != EEXIST) {
> + return -1;
> ++ }
> ++ }
> + }
> + npath[len++] = *p;
> + }
> +@@ -279,7 +286,14 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) {
> + zip->entry.header_offset = zip->archive.m_archive_size;
> + memset(zip->entry.header, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE * sizeof(mz_uint8));
> + zip->entry.method = 0;
> ++
> ++ // UNIX or APPLE
> ++#if MZ_PLATFORM == 3 || MZ_PLATFORM == 19
> ++ // regular file with rw-r--r-- persmissions
> ++ zip->entry.external_attr = (mz_uint32)(0100644) << 16;
> ++#else
> + zip->entry.external_attr = 0;
> ++#endif
> +
> + num_alignment_padding_bytes =
> + mz_zip_writer_compute_padding_needed_for_file_alignment(pzip);
> +@@ -660,7 +674,7 @@ ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, size_t bufsize) {
> + }
> +
> + if (!mz_zip_reader_extract_to_mem_no_alloc(pzip, (mz_uint)zip->entry.index,
> +- buf, bufsize, 0, NULL, 0)) {
> ++ buf, bufsize, 0, NULL, 0)) {
> + return -1;
> + }
> +
> +@@ -670,10 +684,7 @@ ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, size_t bufsize) {
> + int zip_entry_fread(struct zip_t *zip, const char *filename) {
> + mz_zip_archive *pzip = NULL;
> + mz_uint idx;
> +-#if defined(_MSC_VER)
> +-#else
> + mz_uint32 xattr = 0;
> +-#endif
> + mz_zip_archive_file_stat info;
> +
> + if (!zip) {
> +@@ -875,12 +886,19 @@ int zip_extract(const char *zipname, const char *dir,
> + goto out;
> + }
> +
> +- if ((((info.m_version_made_by >> 8) == 3) || ((info.m_version_made_by >> 8) == 19)) // if zip is produced on Unix or macOS (3 and 19 from section 4.4.2.2 of zip standard)
> +- && info.m_external_attr & (0x20 << 24)) { // and has sym link attribute (0x80 is file, 0x40 is directory)
> ++ if ((((info.m_version_made_by >> 8) == 3) ||
> ++ ((info.m_version_made_by >> 8) ==
> ++ 19)) // if zip is produced on Unix or macOS (3 and 19 from
> ++ // section 4.4.2.2 of zip standard)
> ++ && info.m_external_attr &
> ++ (0x20 << 24)) { // and has sym link attribute (0x80 is file, 0x40
> ++ // is directory)
> + #if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \
> + defined(__MINGW32__)
> +-#else
> +- if (info.m_uncomp_size > MAX_PATH || !mz_zip_reader_extract_to_mem_no_alloc(&zip_archive, i, symlink_to, MAX_PATH, 0, NULL, 0)) {
> ++#else
> ++ if (info.m_uncomp_size > MAX_PATH ||
> ++ !mz_zip_reader_extract_to_mem_no_alloc(&zip_archive, i, symlink_to,
> ++ MAX_PATH, 0, NULL, 0)) {
> + goto out;
> + }
> + symlink_to[info.m_uncomp_size] = '\0';
> +diff --git a/contrib/zip/src/zip.h b/contrib/zip/src/zip.h
> +index 5f39df50ad..a48d64d6de 100644
> +--- a/contrib/zip/src/zip.h
> ++++ b/contrib/zip/src/zip.h
> +@@ -20,241 +20,240 @@ extern "C" {
> + #endif
> +
> + #if !defined(_SSIZE_T_DEFINED) && !defined(_SSIZE_T_DEFINED_) && \
> +- !defined(_SSIZE_T) && !defined(_SSIZE_T_) && !defined(__ssize_t_defined)
> +-#define _SSIZE_T
> ++ !defined(__DEFINED_ssize_t) && !defined(__ssize_t_defined) && \
> ++ !defined(_SSIZE_T) && !defined(_SSIZE_T_)
> ++
> + // 64-bit Windows is the only mainstream platform
> + // where sizeof(long) != sizeof(void*)
> + #ifdef _WIN64
> +-typedef long long ssize_t; /* byte count or error */
> ++typedef long long ssize_t; /* byte count or error */
> + #else
> +-typedef long ssize_t; /* byte count or error */
> ++typedef long ssize_t; /* byte count or error */
> + #endif
> ++
> ++#define _SSIZE_T_DEFINED
> ++#define _SSIZE_T_DEFINED_
> ++#define __DEFINED_ssize_t
> ++#define __ssize_t_defined
> ++#define _SSIZE_T
> ++#define _SSIZE_T_
> ++
> + #endif
> +
> + #ifndef MAX_PATH
> + #define MAX_PATH 32767 /* # chars in a path name including NULL */
> + #endif
> +
> ++/**
> ++ * @mainpage
> ++ *
> ++ * Documenation for @ref zip.
> ++ */
> ++
> ++/**
> ++ * @addtogroup zip
> ++ * @{
> ++ */
> ++
> ++/**
> ++ * Default zip compression level.
> ++ */
> ++
> + #define ZIP_DEFAULT_COMPRESSION_LEVEL 6
> +
> +-/*
> +- This data structure is used throughout the library to represent zip archive
> +- - forward declaration.
> +-*/
> ++/**
> ++ * @struct zip_t
> ++ *
> ++ * This data structure is used throughout the library to represent zip archive -
> ++ * forward declaration.
> ++ */
> + struct zip_t;
> +
> +-/*
> +- Opens zip archive with compression level using the given mode.
> +-
> +- Args:
> +- zipname: zip archive file name.
> +- level: compression level (0-9 are the standard zlib-style levels).
> +- mode: file access mode.
> +- 'r': opens a file for reading/extracting (the file must exists).
> +- 'w': creates an empty file for writing.
> +- 'a': appends to an existing archive.
> +-
> +- Returns:
> +- The zip archive handler or NULL on error
> +-*/
> ++/**
> ++ * Opens zip archive with compression level using the given mode.
> ++ *
> ++ * @param zipname zip archive file name.
> ++ * @param level compression level (0-9 are the standard zlib-style levels).
> ++ * @param mode file access mode.
> ++ * - 'r': opens a file for reading/extracting (the file must exists).
> ++ * - 'w': creates an empty file for writing.
> ++ * - 'a': appends to an existing archive.
> ++ *
> ++ * @return the zip archive handler or NULL on error
> ++ */
> + extern struct zip_t *zip_open(const char *zipname, int level, char mode);
> +
> +-/*
> +- Closes the zip archive, releases resources - always finalize.
> +-
> +- Args:
> +- zip: zip archive handler.
> +-*/
> ++/**
> ++ * Closes the zip archive, releases resources - always finalize.
> ++ *
> ++ * @param zip zip archive handler.
> ++ */
> + extern void zip_close(struct zip_t *zip);
> +
> +-/*
> +- Opens an entry by name in the zip archive.
> +- For zip archive opened in 'w' or 'a' mode the function will append
> +- a new entry. In readonly mode the function tries to locate the entry
> +- in global dictionary.
> +-
> +- Args:
> +- zip: zip archive handler.
> +- entryname: an entry name in local dictionary.
> +-
> +- Returns:
> +- The return code - 0 on success, negative number (< 0) on error.
> +-*/
> ++/**
> ++ * Opens an entry by name in the zip archive.
> ++ *
> ++ * For zip archive opened in 'w' or 'a' mode the function will append
> ++ * a new entry. In readonly mode the function tries to locate the entry
> ++ * in global dictionary.
> ++ *
> ++ * @param zip zip archive handler.
> ++ * @param entryname an entry name in local dictionary.
> ++ *
> ++ * @return the return code - 0 on success, negative number (< 0) on error.
> ++ */
> + extern int zip_entry_open(struct zip_t *zip, const char *entryname);
> +
> +-/*
> +- Opens a new entry by index in the zip archive.
> +- This function is only valid if zip archive was opened in 'r' (readonly) mode.
> +-
> +- Args:
> +- zip: zip archive handler.
> +- index: index in local dictionary.
> +-
> +- Returns:
> +- The return code - 0 on success, negative number (< 0) on error.
> +-*/
> ++/**
> ++ * Opens a new entry by index in the zip archive.
> ++ *
> ++ * This function is only valid if zip archive was opened in 'r' (readonly) mode.
> ++ *
> ++ * @param zip zip archive handler.
> ++ * @param index index in local dictionary.
> ++ *
> ++ * @return the return code - 0 on success, negative number (< 0) on error.
> ++ */
> + extern int zip_entry_openbyindex(struct zip_t *zip, int index);
> +
> +-/*
> +- Closes a zip entry, flushes buffer and releases resources.
> +-
> +- Args:
> +- zip: zip archive handler.
> +-
> +- Returns:
> +- The return code - 0 on success, negative number (< 0) on error.
> +-*/
> ++/**
> ++ * Closes a zip entry, flushes buffer and releases resources.
> ++ *
> ++ * @param zip zip archive handler.
> ++ *
> ++ * @return the return code - 0 on success, negative number (< 0) on error.
> ++ */
> + extern int zip_entry_close(struct zip_t *zip);
> +
> +-/*
> +- Returns a local name of the current zip entry.
> +- The main difference between user's entry name and local entry name
> +- is optional relative path.
> +- Following .ZIP File Format Specification - the path stored MUST not contain
> +- a drive or device letter, or a leading slash.
> +- All slashes MUST be forward slashes '/' as opposed to backwards slashes '\'
> +- for compatibility with Amiga and UNIX file systems etc.
> +-
> +- Args:
> +- zip: zip archive handler.
> +-
> +- Returns:
> +- The pointer to the current zip entry name, or NULL on error.
> +-*/
> ++/**
> ++ * Returns a local name of the current zip entry.
> ++ *
> ++ * The main difference between user's entry name and local entry name
> ++ * is optional relative path.
> ++ * Following .ZIP File Format Specification - the path stored MUST not contain
> ++ * a drive or device letter, or a leading slash.
> ++ * All slashes MUST be forward slashes '/' as opposed to backwards slashes '\'
> ++ * for compatibility with Amiga and UNIX file systems etc.
> ++ *
> ++ * @param zip: zip archive handler.
> ++ *
> ++ * @return the pointer to the current zip entry name, or NULL on error.
> ++ */
> + extern const char *zip_entry_name(struct zip_t *zip);
> +
> +-/*
> +- Returns an index of the current zip entry.
> +-
> +- Args:
> +- zip: zip archive handler.
> +-
> +- Returns:
> +- The index on success, negative number (< 0) on error.
> +-*/
> ++/**
> ++ * Returns an index of the current zip entry.
> ++ *
> ++ * @param zip zip archive handler.
> ++ *
> ++ * @return the index on success, negative number (< 0) on error.
> ++ */
> + extern int zip_entry_index(struct zip_t *zip);
> +
> +-/*
> +- Determines if the current zip entry is a directory entry.
> +-
> +- Args:
> +- zip: zip archive handler.
> +-
> +- Returns:
> +- The return code - 1 (true), 0 (false), negative number (< 0) on error.
> +-*/
> ++/**
> ++ * Determines if the current zip entry is a directory entry.
> ++ *
> ++ * @param zip zip archive handler.
> ++ *
> ++ * @return the return code - 1 (true), 0 (false), negative number (< 0) on
> ++ * error.
> ++ */
> + extern int zip_entry_isdir(struct zip_t *zip);
> +
> +-/*
> +- Returns an uncompressed size of the current zip entry.
> +-
> +- Args:
> +- zip: zip archive handler.
> +-
> +- Returns:
> +- The uncompressed size in bytes.
> +-*/
> ++/**
> ++ * Returns an uncompressed size of the current zip entry.
> ++ *
> ++ * @param zip zip archive handler.
> ++ *
> ++ * @return the uncompressed size in bytes.
> ++ */
> + extern unsigned long long zip_entry_size(struct zip_t *zip);
> +
> +-/*
> +- Returns CRC-32 checksum of the current zip entry.
> +-
> +- Args:
> +- zip: zip archive handler.
> +-
> +- Returns:
> +- The CRC-32 checksum.
> +-*/
> ++/**
> ++ * Returns CRC-32 checksum of the current zip entry.
> ++ *
> ++ * @param zip zip archive handler.
> ++ *
> ++ * @return the CRC-32 checksum.
> ++ */
> + extern unsigned int zip_entry_crc32(struct zip_t *zip);
> +
> +-/*
> +- Compresses an input buffer for the current zip entry.
> +-
> +- Args:
> +- zip: zip archive handler.
> +- buf: input buffer.
> +- bufsize: input buffer size (in bytes).
> +-
> +- Returns:
> +- The return code - 0 on success, negative number (< 0) on error.
> +-*/
> ++/**
> ++ * Compresses an input buffer for the current zip entry.
> ++ *
> ++ * @param zip zip archive handler.
> ++ * @param buf input buffer.
> ++ * @param bufsize input buffer size (in bytes).
> ++ *
> ++ * @return the return code - 0 on success, negative number (< 0) on error.
> ++ */
> + extern int zip_entry_write(struct zip_t *zip, const void *buf, size_t bufsize);
> +
> +-/*
> +- Compresses a file for the current zip entry.
> +-
> +- Args:
> +- zip: zip archive handler.
> +- filename: input file.
> +-
> +- Returns:
> +- The return code - 0 on success, negative number (< 0) on error.
> +-*/
> ++/**
> ++ * Compresses a file for the current zip entry.
> ++ *
> ++ * @param zip zip archive handler.
> ++ * @param filename input file.
> ++ *
> ++ * @return the return code - 0 on success, negative number (< 0) on error.
> ++ */
> + extern int zip_entry_fwrite(struct zip_t *zip, const char *filename);
> +
> +-/*
> +- Extracts the current zip entry into output buffer.
> +- The function allocates sufficient memory for a output buffer.
> +-
> +- Args:
> +- zip: zip archive handler.
> +- buf: output buffer.
> +- bufsize: output buffer size (in bytes).
> +-
> +- Note:
> +- - remember to release memory allocated for a output buffer.
> +- - for large entries, please take a look at zip_entry_extract function.
> +-
> +- Returns:
> +- The return code - the number of bytes actually read on success.
> +- Otherwise a -1 on error.
> +-*/
> ++/**
> ++ * Extracts the current zip entry into output buffer.
> ++ *
> ++ * The function allocates sufficient memory for a output buffer.
> ++ *
> ++ * @param zip zip archive handler.
> ++ * @param buf output buffer.
> ++ * @param bufsize output buffer size (in bytes).
> ++ *
> ++ * @note remember to release memory allocated for a output buffer.
> ++ * for large entries, please take a look at zip_entry_extract function.
> ++ *
> ++ * @return the return code - the number of bytes actually read on success.
> ++ * Otherwise a -1 on error.
> ++ */
> + extern ssize_t zip_entry_read(struct zip_t *zip, void **buf, size_t *bufsize);
> +
> +-/*
> +- Extracts the current zip entry into a memory buffer using no memory
> +- allocation.
> +-
> +- Args:
> +- zip: zip archive handler.
> +- buf: preallocated output buffer.
> +- bufsize: output buffer size (in bytes).
> +-
> +- Note:
> +- - ensure supplied output buffer is large enough.
> +- - zip_entry_size function (returns uncompressed size for the current entry)
> +- can be handy to estimate how big buffer is needed.
> +- - for large entries, please take a look at zip_entry_extract function.
> +-
> +- Returns:
> +- The return code - the number of bytes actually read on success.
> +- Otherwise a -1 on error (e.g. bufsize is not large enough).
> +-*/
> +-extern ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, size_t bufsize);
> +-
> +-/*
> +- Extracts the current zip entry into output file.
> +-
> +- Args:
> +- zip: zip archive handler.
> +- filename: output file.
> +-
> +- Returns:
> +- The return code - 0 on success, negative number (< 0) on error.
> +-*/
> ++/**
> ++ * Extracts the current zip entry into a memory buffer using no memory
> ++ * allocation.
> ++ *
> ++ * @param zip zip archive handler.
> ++ * @param buf preallocated output buffer.
> ++ * @param bufsize output buffer size (in bytes).
> ++ *
> ++ * @note ensure supplied output buffer is large enough.
> ++ * zip_entry_size function (returns uncompressed size for the current
> ++ * entry) can be handy to estimate how big buffer is needed. for large
> ++ * entries, please take a look at zip_entry_extract function.
> ++ *
> ++ * @return the return code - the number of bytes actually read on success.
> ++ * Otherwise a -1 on error (e.g. bufsize is not large enough).
> ++ */
> ++extern ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf,
> ++ size_t bufsize);
> ++
> ++/**
> ++ * Extracts the current zip entry into output file.
> ++ *
> ++ * @param zip zip archive handler.
> ++ * @param filename output file.
> ++ *
> ++ * @return the return code - 0 on success, negative number (< 0) on error.
> ++ */
> + extern int zip_entry_fread(struct zip_t *zip, const char *filename);
> +
> +-/*
> +- Extracts the current zip entry using a callback function (on_extract).
> +-
> +- Args:
> +- zip: zip archive handler.
> +- on_extract: callback function.
> +- arg: opaque pointer (optional argument,
> +- which you can pass to the on_extract callback)
> +-
> +- Returns:
> +- The return code - 0 on success, negative number (< 0) on error.
> ++/**
> ++ * Extracts the current zip entry using a callback function (on_extract).
> ++ *
> ++ * @param zip zip archive handler.
> ++ * @param on_extract callback function.
> ++ * @param arg opaque pointer (optional argument, which you can pass to the
> ++ * on_extract callback)
> ++ *
> ++ * @return the return code - 0 on success, negative number (< 0) on error.
> + */
> + extern int
> + zip_entry_extract(struct zip_t *zip,
> +@@ -262,53 +261,49 @@ zip_entry_extract(struct zip_t *zip,
> + const void *data, size_t size),
> + void *arg);
> +
> +-/*
> +- Returns the number of all entries (files and directories) in the zip archive.
> +-
> +- Args:
> +- zip: zip archive handler.
> +-
> +- Returns:
> +- The return code - the number of entries on success,
> +- negative number (< 0) on error.
> +-*/
> ++/**
> ++ * Returns the number of all entries (files and directories) in the zip archive.
> ++ *
> ++ * @param zip zip archive handler.
> ++ *
> ++ * @return the return code - the number of entries on success, negative number
> ++ * (< 0) on error.
> ++ */
> + extern int zip_total_entries(struct zip_t *zip);
> +
> +-/*
> +- Creates a new archive and puts files into a single zip archive.
> +-
> +- Args:
> +- zipname: zip archive file.
> +- filenames: input files.
> +- len: number of input files.
> +-
> +- Returns:
> +- The return code - 0 on success, negative number (< 0) on error.
> +-*/
> ++/**
> ++ * Creates a new archive and puts files into a single zip archive.
> ++ *
> ++ * @param zipname zip archive file.
> ++ * @param filenames input files.
> ++ * @param len: number of input files.
> ++ *
> ++ * @return the return code - 0 on success, negative number (< 0) on error.
> ++ */
> + extern int zip_create(const char *zipname, const char *filenames[], size_t len);
> +
> +-/*
> +- Extracts a zip archive file into directory.
> +-
> +- If on_extract_entry is not NULL, the callback will be called after
> +- successfully extracted each zip entry.
> +- Returning a negative value from the callback will cause abort and return an
> +- error. The last argument (void *arg) is optional, which you can use to pass
> +- data to the on_extract_entry callback.
> +-
> +- Args:
> +- zipname: zip archive file.
> +- dir: output directory.
> +- on_extract_entry: on extract callback.
> +- arg: opaque pointer.
> +-
> +- Returns:
> +- The return code - 0 on success, negative number (< 0) on error.
> +-*/
> ++/**
> ++ * Extracts a zip archive file into directory.
> ++ *
> ++ * If on_extract_entry is not NULL, the callback will be called after
> ++ * successfully extracted each zip entry.
> ++ * Returning a negative value from the callback will cause abort and return an
> ++ * error. The last argument (void *arg) is optional, which you can use to pass
> ++ * data to the on_extract_entry callback.
> ++ *
> ++ * @param zipname zip archive file.
> ++ * @param dir output directory.
> ++ * @param on_extract_entry on extract callback.
> ++ * @param arg opaque pointer.
> ++ *
> ++ * @return the return code - 0 on success, negative number (< 0) on error.
> ++ */
> + extern int zip_extract(const char *zipname, const char *dir,
> + int (*on_extract_entry)(const char *filename, void *arg),
> + void *arg);
> +
> ++/** @} */
> ++
> + #ifdef __cplusplus
> + }
> + #endif
> +diff --git a/contrib/zip/test/CMakeLists.txt b/contrib/zip/test/CMakeLists.txt
> +index 9b2a8db106..cc060b00fe 100644
> +--- a/contrib/zip/test/CMakeLists.txt
> ++++ b/contrib/zip/test/CMakeLists.txt
> +@@ -1,19 +1,16 @@
> + cmake_minimum_required(VERSION 2.8)
> +
> +-if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")
> +- if(ENABLE_COVERAGE)
> +- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g ")
> +- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")
> +- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs")
> +- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftest-coverage")
> +- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
> +- endif()
> +-endif ()
> +-
> + # test
> +-include_directories(../src)
> +-add_executable(test.exe test.c ../src/zip.c)
> +-add_executable(test_miniz.exe test_miniz.c)
> ++set(test_out test.out)
> ++set(test_miniz_out test_miniz.out)
> ++
> ++add_executable(${test_out} test.c)
> ++target_link_libraries(${test_out} zip)
> ++add_executable(${test_miniz_out} test_miniz.c)
> ++target_link_libraries(${test_miniz_out} zip)
> ++
> ++add_test(NAME ${test_out} COMMAND ${test_out})
> ++add_test(NAME ${test_miniz_out} COMMAND ${test_miniz_out})
> +
> +-add_test(NAME test COMMAND test.exe)
> +-add_test(NAME test_miniz COMMAND test_miniz.exe)
> ++set(test_out ${test_out} PARENT_SCOPE)
> ++set(test_miniz_out ${test_miniz_out} PARENT_SCOPE)
> +diff --git a/contrib/zip/test/test.c b/contrib/zip/test/test.c
> +index 454430533a..a9b2ddab1e 100644
> +--- a/contrib/zip/test/test.c
> ++++ b/contrib/zip/test/test.c
> +@@ -29,6 +29,8 @@
> + #define XFILE "7.txt\0"
> + #define XMODE 0100777
> +
> ++#define UNIXMODE 0100644
> ++
> + #define UNUSED(x) (void)x
> +
> + static int total_entries = 0;
> +@@ -102,7 +104,8 @@ static void test_read(void) {
> + assert(0 == zip_entry_close(zip));
> + free(buf);
> + buf = NULL;
> +-
> ++ bufsize = 0;
> ++
> + assert(0 == zip_entry_open(zip, "test/test-2.txt"));
> + assert(strlen(TESTDATA2) == zip_entry_size(zip));
> + assert(CRC32DATA2 == zip_entry_crc32(zip));
> +@@ -131,7 +134,8 @@ static void test_read(void) {
> + assert(0 == zip_entry_close(zip));
> + free(buf);
> + buf = NULL;
> +-
> ++ bufsize = 0;
> ++
> + buftmp = strlen(TESTDATA1);
> + buf = calloc(buftmp, sizeof(char));
> + assert(0 == zip_entry_open(zip, "test/test-1.txt"));
> +@@ -433,6 +437,35 @@ static void test_mtime(void) {
> + remove(ZIPNAME);
> + }
> +
> ++static void test_unix_permissions(void) {
> ++#if defined(_WIN64) || defined(_WIN32) || defined(__WIN32__)
> ++#else
> ++ // UNIX or APPLE
> ++ struct MZ_FILE_STAT_STRUCT file_stats;
> ++
> ++ remove(ZIPNAME);
> ++
> ++ struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
> ++ assert(zip != NULL);
> ++
> ++ assert(0 == zip_entry_open(zip, RFILE));
> ++ assert(0 == zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1)));
> ++ assert(0 == zip_entry_close(zip));
> ++
> ++ zip_close(zip);
> ++
> ++ remove(RFILE);
> ++
> ++ assert(0 == zip_extract(ZIPNAME, ".", NULL, NULL));
> ++
> ++ assert(0 == MZ_FILE_STAT(RFILE, &file_stats));
> ++ assert(UNIXMODE == file_stats.st_mode);
> ++
> ++ remove(RFILE);
> ++ remove(ZIPNAME);
> ++#endif
> ++}
> ++
> + int main(int argc, char *argv[]) {
> + UNUSED(argc);
> + UNUSED(argv);
> +@@ -453,6 +486,7 @@ int main(int argc, char *argv[]) {
> + test_write_permissions();
> + test_exe_permissions();
> + test_mtime();
> ++ test_unix_permissions();
> +
> + remove(ZIPNAME);
> + return 0;
> +diff --git a/contrib/zip/test/test_miniz.c b/contrib/zip/test/test_miniz.c
> +index ebc0564dc3..babcaecdb6 100644
> +--- a/contrib/zip/test/test_miniz.c
> ++++ b/contrib/zip/test/test_miniz.c
> +@@ -23,16 +23,39 @@ int main(int argc, char *argv[]) {
> + uint step = 0;
> + int cmp_status;
> + uLong src_len = (uLong)strlen(s_pStr);
> +- uLong cmp_len = compressBound(src_len);
> + uLong uncomp_len = src_len;
> ++ uLong cmp_len;
> + uint8 *pCmp, *pUncomp;
> ++ size_t sz;
> + uint total_succeeded = 0;
> + (void)argc, (void)argv;
> +
> + printf("miniz.c version: %s\n", MZ_VERSION);
> +
> + do {
> ++ pCmp = (uint8 *)tdefl_compress_mem_to_heap(s_pStr, src_len, &cmp_len, 0);
> ++ if (!pCmp) {
> ++ printf("tdefl_compress_mem_to_heap failed\n");
> ++ return EXIT_FAILURE;
> ++ }
> ++ if (src_len <= cmp_len) {
> ++ printf("tdefl_compress_mem_to_heap failed: from %u to %u bytes\n",
> ++ (mz_uint32)uncomp_len, (mz_uint32)cmp_len);
> ++ free(pCmp);
> ++ return EXIT_FAILURE;
> ++ }
> ++
> ++ sz = tdefl_compress_mem_to_mem(pCmp, cmp_len, s_pStr, src_len, 0);
> ++ if (sz != cmp_len) {
> ++ printf("tdefl_compress_mem_to_mem failed: expected %u, got %u\n",
> ++ (mz_uint32)cmp_len, (mz_uint32)sz);
> ++ free(pCmp);
> ++ return EXIT_FAILURE;
> ++ }
> ++
> + // Allocate buffers to hold compressed and uncompressed data.
> ++ free(pCmp);
> ++ cmp_len = compressBound(src_len);
> + pCmp = (mz_uint8 *)malloc((size_t)cmp_len);
> + pUncomp = (mz_uint8 *)malloc((size_t)src_len);
> + if ((!pCmp) || (!pUncomp)) {
> diff --git a/package/assimp/0003-closes-2954-upgrade-to-latest-greatest.patch b/package/assimp/0003-closes-2954-upgrade-to-latest-greatest.patch
> new file mode 100644
> index 0000000000..9bd24630c5
> --- /dev/null
> +++ b/package/assimp/0003-closes-2954-upgrade-to-latest-greatest.patch
> @@ -0,0 +1,243 @@
> +From bb3db0ebaffc6b76de256e597ec1d1e4d2a6663f Mon Sep 17 00:00:00 2001
> +From: kimkulling <kim.kulling at googlemail.com>
> +Date: Mon, 9 Mar 2020 10:51:26 +0100
> +Subject: [PATCH] closes https://github.com/assimp/assimp/issues/2954: upgrade
> + to latest greatest.
> +
> +[Retrieved from:
> +https://github.com/assimp/assimp/commit/bb3db0ebaffc6b76de256e597ec1d1e4d2a6663f]
> +Signed-off-by: Fabrice Fontaine <fontaine.fabrice at gmail.com>
> +---
> + contrib/zip/CMakeLists.txt | 8 ++----
> + contrib/zip/README.md | 51 +++++++++++++++++++++++++++++++--
> + contrib/zip/src/zip.c | 17 ++++++++++-
> + contrib/zip/src/zip.h | 13 ++++++++-
> + contrib/zip/test/CMakeLists.txt | 5 ----
> + contrib/zip/test/test.c | 4 ++-
> + 6 files changed, 81 insertions(+), 17 deletions(-)
> +
> +diff --git a/contrib/zip/CMakeLists.txt b/contrib/zip/CMakeLists.txt
> +index 77916d2e14..f194649ede 100644
> +--- a/contrib/zip/CMakeLists.txt
> ++++ b/contrib/zip/CMakeLists.txt
> +@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0)
> +
> + project(zip
> + LANGUAGES C
> +- VERSION "0.1.15")
> ++ VERSION "0.1.18")
> + set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
> +
> + option(CMAKE_DISABLE_TESTING "Disable test creation" OFF)
> +@@ -16,10 +16,6 @@ elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR
> + "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR
> + "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")
> + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall -Wextra -Werror -pedantic")
> +- if(ENABLE_COVERAGE)
> +- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
> +- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
> +- endif()
> + endif (MSVC)
> +
> + # zip
> +@@ -35,7 +31,7 @@ if (NOT CMAKE_DISABLE_TESTING)
> + enable_testing()
> + add_subdirectory(test)
> + find_package(Sanitizers)
> +- add_sanitizers(${PROJECT_NAME} ${test_out} ${test_miniz_out})
> ++ add_sanitizers(${PROJECT_NAME} ${test_out})
> + endif()
> +
> + ####
> +diff --git a/contrib/zip/README.md b/contrib/zip/README.md
> +index 14eb9a34c8..bdd0822b67 100644
> +--- a/contrib/zip/README.md
> ++++ b/contrib/zip/README.md
> +@@ -1,10 +1,8 @@
> + ### A portable (OSX/Linux/Windows), simple zip library written in C
> + This is done by hacking awesome [miniz](https://code.google.com/p/miniz) library and layering functions on top of the miniz v1.15 API.
> +
> +-[![Windows](https://ci.appveyor.com/api/projects/status/bph8dr3jacgmjv32/branch/master?svg=true&label=windows)](https://ci.appveyor.com/project/kuba--/zip)
> +-[![Linux](https://travis-ci.org/kuba--/zip.svg?branch=master&label=linux%2fosx)](https://travis-ci.org/kuba--/zip)
> ++[![Build](https://github.com/kuba--/zip/workflows/build/badge.svg)](https://github.com/kuba--/zip/actions?query=workflow%3Abuild)
> + [![Version](https://badge.fury.io/gh/kuba--%2Fzip.svg)](https://github.com/kuba--/zip/releases)
> +-[![Codecov](https://codecov.io/gh/kuba--/zip/branch/master/graph/badge.svg)](https://codecov.io/gh/kuba--/zip)
> +
> +
> + # The Idea
> +@@ -213,6 +211,53 @@ func main() {
> + }
> + ```
> +
> ++### Rust (ffi)
> ++```rust
> ++extern crate libc;
> ++use std::ffi::CString;
> ++
> ++#[repr(C)]
> ++pub struct Zip {
> ++ _private: [u8; 0],
> ++}
> ++
> ++#[link(name = "zip")]
> ++extern "C" {
> ++ fn zip_open(path: *const libc::c_char, level: libc::c_int, mode: libc::c_char) -> *mut Zip;
> ++ fn zip_close(zip: *mut Zip) -> libc::c_void;
> ++
> ++ fn zip_entry_open(zip: *mut Zip, entryname: *const libc::c_char) -> libc::c_int;
> ++ fn zip_entry_close(zip: *mut Zip) -> libc::c_int;
> ++ fn zip_entry_write(
> ++ zip: *mut Zip,
> ++ buf: *const libc::c_void,
> ++ bufsize: libc::size_t,
> ++ ) -> libc::c_int;
> ++}
> ++
> ++fn main() {
> ++ let path = CString::new("/tmp/test.zip").unwrap();
> ++ let mode: libc::c_char = 'w' as libc::c_char;
> ++
> ++ let entryname = CString::new("test.txt").unwrap();
> ++ let content = "test content\0";
> ++
> ++ unsafe {
> ++ let zip: *mut Zip = zip_open(path.as_ptr(), 5, mode);
> ++ {
> ++ zip_entry_open(zip, entryname.as_ptr());
> ++ {
> ++ let buf = content.as_ptr() as *const libc::c_void;
> ++ let bufsize = content.len() as libc::size_t;
> ++ zip_entry_write(zip, buf, bufsize);
> ++ }
> ++ zip_entry_close(zip);
> ++ }
> ++ zip_close(zip);
> ++ }
> ++}
> ++```
> ++
> + ### Ruby (ffi)
> + Install _ffi_ gem.
> + ```shell
> +diff --git a/contrib/zip/src/zip.c b/contrib/zip/src/zip.c
> +index 1abcfd8fd1..3b2821e6a3 100644
> +--- a/contrib/zip/src/zip.c
> ++++ b/contrib/zip/src/zip.c
> +@@ -222,6 +222,20 @@ void zip_close(struct zip_t *zip) {
> + }
> + }
> +
> ++int zip_is64(struct zip_t *zip) {
> ++ if (!zip) {
> ++ // zip_t handler is not initialized
> ++ return -1;
> ++ }
> ++
> ++ if (!zip->archive.m_pState) {
> ++ // zip state is not initialized
> ++ return -1;
> ++ }
> ++
> ++ return (int)zip->archive.m_pState->m_zip64;
> ++}
> ++
> + int zip_entry_open(struct zip_t *zip, const char *entryname) {
> + size_t entrylen = 0;
> + mz_zip_archive *pzip = NULL;
> +@@ -794,7 +808,8 @@ int zip_create(const char *zipname, const char *filenames[], size_t len) {
> +
> + if (MZ_FILE_STAT(name, &file_stat) != 0) {
> + // problem getting information - check errno
> +- return -1;
> ++ status = -1;
> ++ break;
> + }
> +
> + if ((file_stat.st_mode & 0200) == 0) {
> +diff --git a/contrib/zip/src/zip.h b/contrib/zip/src/zip.h
> +index a48d64d6de..cd3ab5cd00 100644
> +--- a/contrib/zip/src/zip.h
> ++++ b/contrib/zip/src/zip.h
> +@@ -21,7 +21,7 @@ extern "C" {
> +
> + #if !defined(_SSIZE_T_DEFINED) && !defined(_SSIZE_T_DEFINED_) && \
> + !defined(__DEFINED_ssize_t) && !defined(__ssize_t_defined) && \
> +- !defined(_SSIZE_T) && !defined(_SSIZE_T_)
> ++ !defined(_SSIZE_T) && !defined(_SSIZE_T_) && !defined(_SSIZE_T_DECLARED)
> +
> + // 64-bit Windows is the only mainstream platform
> + // where sizeof(long) != sizeof(void*)
> +@@ -37,6 +37,7 @@ typedef long ssize_t; /* byte count or error */
> + #define __ssize_t_defined
> + #define _SSIZE_T
> + #define _SSIZE_T_
> ++#define _SSIZE_T_DECLARED
> +
> + #endif
> +
> +@@ -90,6 +91,16 @@ extern struct zip_t *zip_open(const char *zipname, int level, char mode);
> + */
> + extern void zip_close(struct zip_t *zip);
> +
> ++/**
> ++ * Determines if the archive has a zip64 end of central directory headers.
> ++ *
> ++ * @param zip zip archive handler.
> ++ *
> ++ * @return the return code - 1 (true), 0 (false), negative number (< 0) on
> ++ * error.
> ++ */
> ++extern int zip_is64(struct zip_t *zip);
> ++
> + /**
> + * Opens an entry by name in the zip archive.
> + *
> +diff --git a/contrib/zip/test/CMakeLists.txt b/contrib/zip/test/CMakeLists.txt
> +index cc060b00fe..1224115858 100644
> +--- a/contrib/zip/test/CMakeLists.txt
> ++++ b/contrib/zip/test/CMakeLists.txt
> +@@ -2,15 +2,10 @@ cmake_minimum_required(VERSION 2.8)
> +
> + # test
> + set(test_out test.out)
> +-set(test_miniz_out test_miniz.out)
> +
> + add_executable(${test_out} test.c)
> + target_link_libraries(${test_out} zip)
> +-add_executable(${test_miniz_out} test_miniz.c)
> +-target_link_libraries(${test_miniz_out} zip)
> +
> + add_test(NAME ${test_out} COMMAND ${test_out})
> +-add_test(NAME ${test_miniz_out} COMMAND ${test_miniz_out})
> +
> + set(test_out ${test_out} PARENT_SCOPE)
> +-set(test_miniz_out ${test_miniz_out} PARENT_SCOPE)
> +diff --git a/contrib/zip/test/test.c b/contrib/zip/test/test.c
> +index a9b2ddab1e..9cc2248ac0 100644
> +--- a/contrib/zip/test/test.c
> ++++ b/contrib/zip/test/test.c
> +@@ -47,7 +47,7 @@ static void test_write(void) {
> + assert(CRC32DATA1 == zip_entry_crc32(zip));
> + ++total_entries;
> + assert(0 == zip_entry_close(zip));
> +-
> ++ assert(0 == zip_is64(zip));
> + zip_close(zip);
> + }
> +
> +@@ -92,6 +92,7 @@ static void test_read(void) {
> + size_t buftmp;
> + struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
> + assert(zip != NULL);
> ++ assert(0 == zip_is64(zip));
> +
> + assert(0 == zip_entry_open(zip, "test\\test-1.txt"));
> + assert(strlen(TESTDATA1) == zip_entry_size(zip));
> +@@ -310,6 +311,7 @@ static void test_fwrite(void) {
> + assert(0 == zip_entry_open(zip, WFILE));
> + assert(0 == zip_entry_fwrite(zip, WFILE));
> + assert(0 == zip_entry_close(zip));
> ++ assert(0 == zip_is64(zip));
> +
> + zip_close(zip);
> + remove(WFILE);
More information about the buildroot
mailing list