From nobody Wed Oct 27 14:50:34 2021 X-Original-To: dev-commits-ports-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 66446182F7B4; Wed, 27 Oct 2021 14:50:34 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4HfWp22QHBz4pRc; Wed, 27 Oct 2021 14:50:34 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 3448E12066; Wed, 27 Oct 2021 14:50:34 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 19REoY0n039000; Wed, 27 Oct 2021 14:50:34 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 19REoYoD038999; Wed, 27 Oct 2021 14:50:34 GMT (envelope-from git) Date: Wed, 27 Oct 2021 14:50:34 GMT Message-Id: <202110271450.19REoYoD038999@gitrepo.freebsd.org> To: ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-branches@FreeBSD.org From: Yuri Victorovich Subject: git: 6a25fe1ffc96 - 2021Q4 - multimedia/assimp: Fix build on 32 bit platforms List-Id: Commits to the quarterly branches of the FreeBSD ports repository List-Archive: https://lists.freebsd.org/archives/dev-commits-ports-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-ports-branches@freebsd.org X-BeenThere: dev-commits-ports-branches@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: yuri X-Git-Repository: ports X-Git-Refname: refs/heads/2021Q4 X-Git-Reftype: branch X-Git-Commit: 6a25fe1ffc96b5ea79c1fef1bc0bee6ff8453069 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch 2021Q4 has been updated by yuri: URL: https://cgit.FreeBSD.org/ports/commit/?id=6a25fe1ffc96b5ea79c1fef1bc0bee6ff8453069 commit 6a25fe1ffc96b5ea79c1fef1bc0bee6ff8453069 Author: Robert Clausecker AuthorDate: 2021-10-27 14:42:01 +0000 Commit: Yuri Victorovich CommitDate: 2021-10-27 14:48:35 +0000 multimedia/assimp: Fix build on 32 bit platforms PR: 259483 (cherry picked from commit c1f6d03bf9305cd02ab733359989fd33c6675231) --- multimedia/assimp/Makefile | 4 +- multimedia/assimp/files/patch-contrib-zip | 1729 +++++++++++++++++++++++++++++ 2 files changed, 1730 insertions(+), 3 deletions(-) diff --git a/multimedia/assimp/Makefile b/multimedia/assimp/Makefile index 4d42a7b1c32c..6722cb3d1786 100644 --- a/multimedia/assimp/Makefile +++ b/multimedia/assimp/Makefile @@ -1,6 +1,7 @@ PORTNAME= assimp DISTVERSIONPREFIX= v DISTVERSION= 5.0.1 +PORTREVISION= 1 CATEGORIES= multimedia MAINTAINER= yuri@FreeBSD.org @@ -9,9 +10,6 @@ COMMENT= Library to import various 3D model formats in a uniform manner LICENSE= BSD3CLAUSE LICENSE_FILE= ${WRKSRC}/LICENSE -BROKEN_i386= typedef redefinition with different types, see https://github.com/assimp/assimp/issues/2954 -BROKEN_powerpc= typedef redefinition with different types, see https://github.com/assimp/assimp/issues/2954 - LIB_DEPENDS= libminizip.so:archivers/minizip USES= cmake compiler:c++11-lib localbase:ldflags pkgconfig diff --git a/multimedia/assimp/files/patch-contrib-zip b/multimedia/assimp/files/patch-contrib-zip new file mode 100644 index 000000000000..a1d0dd899da6 --- /dev/null +++ b/multimedia/assimp/files/patch-contrib-zip @@ -0,0 +1,1729 @@ +Update contrib/zip to 0.1.18 to fix a build failure on 32 bit platforms. +This patch is a combination of two upstream patches [1][2] slightly +edited to fit FreeBSD conventions and to skip files not shipped in the +distribution. See upstream issue 2954 [3] for details. + +[1]: https://github.com/assimp/assimp/commit/f78446b14aff46db2ef27d062a275b6a01fd68b1.diff +[2]: https://github.com/assimp/assimp/commit/f78446b14aff46db2ef27d062a275b6a01fd68b1.diff +[3]: https://github.com/assimp/assimp/issues/2954 + +diff -u contrib/zip/CMakeLists.txt contrib/zip/CMakeLists.txt +--- contrib/zip/CMakeLists.txt ++++ 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.18") + 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") +@@ -17,23 +21,71 @@ + # 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 ++ $ ++ $ ++) + + # 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}) + 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) +@@ -46,2 +98,11 @@ + 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 -u contrib/zip/README.md contrib/zip/README.md +--- contrib/zip/README.md ++++ 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 +@@ -71,7 +69,7 @@ + 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 +87,7 @@ + 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 +108,7 @@ + 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 +142,7 @@ + ``` + + +-* 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 +155,7 @@ + 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 +172,7 @@ + zip_close(zip); + ``` + +-## Bindings ++# Bindings + Compile zip library as a dynamic library. + ```shell + $ mkdir build +@@ -213,3 +211,50 @@ ++} ++``` ++ ++### 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); ++ } + } + ``` + +unchanged: +--- contrib/zip/src/miniz.h ++++ contrib/zip/src/miniz.h +@@ -221,6 +221,7 @@ + #ifndef MINIZ_HEADER_INCLUDED + #define MINIZ_HEADER_INCLUDED + ++#include + #include + + // 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 -u contrib/zip/src/zip.c contrib/zip/src/zip.c +--- contrib/zip/src/zip.c ++++ 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 @@ + #endif + + #ifndef ISSLASH +-#define ISSLASH(C) ((C) == '/') ++#define ISSLASH(C) ((C) == '/' || (C) == '\\') + #endif + + #define CLEANUP(ptr) \ +@@ -78,26 +77,34 @@ + 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; + } +@@ -215,6 +222,20 @@ + } + } + ++int zip_is64(struct zip_t *zip) { ++ if (!zip) { ++ // zip_t handler is not initialized ++ return -1; ++ } *** 789 LINES SKIPPED ***