From a0ed1750089d03cb27c2cb34b00cfd84c14f8cd8 Mon Sep 17 00:00:00 2001 From: LibArchive Upstream Date: Mon, 5 Jan 2026 10:49:24 +0100 Subject: [PATCH] LibArchive 2026-01-05 (dd897a78) Code extracted from: https://github.com/libarchive/libarchive.git at commit dd897a78c662a2c7a003e7ec158cea7909557bee (v3.8.5). --- CMakeLists.txt | 17 ++-- build/cmake/FindLIBGCC.cmake | 44 +++++----- build/cmake/FindNettle.cmake | 46 +++++----- build/cmake/FindPCRE2POSIX.cmake | 68 +++++++-------- build/cmake/FindPCREPOSIX.cmake | 68 +++++++-------- build/version | 2 +- libarchive/archive.h | 4 +- libarchive/archive_cryptor.c | 6 +- libarchive/archive_cryptor_private.h | 4 +- libarchive/archive_disk_acl_darwin.c | 3 +- libarchive/archive_entry.h | 2 +- libarchive/archive_entry_stat.3 | 2 +- .../archive_read_disk_entry_from_file.c | 15 ++-- libarchive/archive_read_disk_posix.c | 35 ++++---- libarchive/archive_read_disk_windows.c | 10 ++- libarchive/archive_read_support_filter_lz4.c | 84 +++++++++++++++---- libarchive/archive_read_support_filter_uu.c | 8 +- libarchive/archive_read_support_filter_zstd.c | 67 ++++++++++++--- libarchive/archive_read_support_format_7zip.c | 8 +- libarchive/archive_read_support_format_cab.c | 2 +- libarchive/archive_read_support_format_cpio.c | 6 +- libarchive/archive_read_support_format_lha.c | 4 +- .../archive_read_support_format_mtree.c | 14 ++-- libarchive/archive_read_support_format_tar.c | 1 + libarchive/archive_read_support_format_zip.c | 28 ++++--- libarchive/archive_string.c | 24 +++++- libarchive/archive_string.h | 4 + libarchive/archive_util.c | 2 +- libarchive/archive_version_details.c | 2 +- libarchive/archive_windows.c | 5 +- libarchive/archive_write.c | 2 +- libarchive/archive_write_disk_posix.c | 26 +++--- libarchive/archive_write_open_fd.c | 6 +- libarchive/archive_write_open_file.c | 6 +- libarchive/archive_write_open_filename.c | 2 + libarchive/archive_write_open_memory.c | 6 +- libarchive/archive_write_set_format_shar.c | 5 +- libarchive/archive_write_set_format_ustar.c | 2 +- libarchive/archive_write_set_format_xar.c | 12 +-- libarchive/module.modulemap | 34 ++++++++ 40 files changed, 431 insertions(+), 255 deletions(-) create mode 100644 libarchive/module.modulemap diff --git a/CMakeLists.txt b/CMakeLists.txt index fc9aca4e96..3ab6291332 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -139,7 +139,12 @@ IF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR # either of the following two, yet neither is supported as of 3.0.2 # - check_linker_flag - does not exist # - try_compile - does not support linker flags - IF(NOT CMAKE_SYSTEM_NAME MATCHES "Darwin") + IF(CMAKE_SYSTEM_NAME MATCHES "Darwin") + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-dead_strip") + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-dead_strip") + ELSEIF(CMAKE_SYSTEM_NAME MATCHES "SunOS") + # SunOS linker doesn't support --gc-sections + ELSE() # Place the functions and data into separate sections, allowing the linker # to garbage collect the unused ones. SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections") @@ -148,10 +153,7 @@ IF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR # Printing the discarded section is "too much", so enable on demand. #SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -Wl,--print-gc-sections") #SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -Wl,--print-gc-sections") - ELSE() - SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-dead_strip") - SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-dead_strip") - ENDIF(NOT CMAKE_SYSTEM_NAME MATCHES "Darwin") + ENDIF() ENDIF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR CMAKE_C_COMPILER_ID MATCHES "^Clang$" AND NOT MSVC) IF (CMAKE_C_COMPILER_ID MATCHES "^XL$") @@ -1085,8 +1087,8 @@ MACRO(CHECK_ICONV LIB TRY_ICONV_CONST) CMAKE_C_COMPILER_ID MATCHES "^Clang$") # # During checking iconv proto type, we should use -Werror to avoid the - # success of iconv detection with a warning which success is a miss - # detection. So this needs for all build mode(even it's a release mode). + # success of iconv detection with a warning, which would be a false + # positive. So this is needed for all build modes, even in release mode. # SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror") ENDIF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR @@ -1529,6 +1531,7 @@ CHECK_FUNCTION_EXISTS_GLIBC(nl_langinfo HAVE_NL_LANGINFO) CHECK_FUNCTION_EXISTS_GLIBC(openat HAVE_OPENAT) CHECK_FUNCTION_EXISTS_GLIBC(pipe HAVE_PIPE) CHECK_FUNCTION_EXISTS_GLIBC(poll HAVE_POLL) +CHECK_FUNCTION_EXISTS_GLIBC(posix_spawn HAVE_POSIX_SPAWN) CHECK_FUNCTION_EXISTS_GLIBC(posix_spawnp HAVE_POSIX_SPAWNP) CHECK_FUNCTION_EXISTS_GLIBC(readlink HAVE_READLINK) CHECK_FUNCTION_EXISTS_GLIBC(readpassphrase HAVE_READPASSPHRASE) diff --git a/build/cmake/FindLIBGCC.cmake b/build/cmake/FindLIBGCC.cmake index 7985f2b003..5883ff8026 100644 --- a/build/cmake/FindLIBGCC.cmake +++ b/build/cmake/FindLIBGCC.cmake @@ -1,22 +1,22 @@ -# - Find libgcc -# Find the libgcc library. -# -# LIBGCC_LIBRARIES - List of libraries when using libgcc -# LIBGCC_FOUND - True if libgcc found. - -IF (LIBGCC_LIBRARY) - # Already in cache, be silent - SET(LIBGCC_FIND_QUIETLY TRUE) -ENDIF (LIBGCC_LIBRARY) - -FIND_LIBRARY(LIBGCC_LIBRARY NAMES gcc libgcc) - -# handle the QUIETLY and REQUIRED arguments and set LIBGCC_FOUND to TRUE if -# all listed variables are TRUE -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBGCC DEFAULT_MSG LIBGCC_LIBRARY) - -IF(LIBGCC_FOUND) - SET(LIBGCC_LIBRARIES ${LIBGCC_LIBRARY}) - SET(HAVE_LIBGCC 1) -ENDIF(LIBGCC_FOUND) +# - Find libgcc +# Find the libgcc library. +# +# LIBGCC_LIBRARIES - List of libraries when using libgcc +# LIBGCC_FOUND - True if libgcc found. + +IF (LIBGCC_LIBRARY) + # Already in cache, be silent + SET(LIBGCC_FIND_QUIETLY TRUE) +ENDIF (LIBGCC_LIBRARY) + +FIND_LIBRARY(LIBGCC_LIBRARY NAMES gcc libgcc) + +# handle the QUIETLY and REQUIRED arguments and set LIBGCC_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBGCC DEFAULT_MSG LIBGCC_LIBRARY) + +IF(LIBGCC_FOUND) + SET(LIBGCC_LIBRARIES ${LIBGCC_LIBRARY}) + SET(HAVE_LIBGCC 1) +ENDIF(LIBGCC_FOUND) diff --git a/build/cmake/FindNettle.cmake b/build/cmake/FindNettle.cmake index 1f66610f01..54ec9f5d39 100644 --- a/build/cmake/FindNettle.cmake +++ b/build/cmake/FindNettle.cmake @@ -1,23 +1,23 @@ -# - Find Nettle -# Find the Nettle include directory and library -# -# NETTLE_INCLUDE_DIR - where to find , etc. -# NETTLE_LIBRARIES - List of libraries when using libnettle. -# NETTLE_FOUND - True if libnettle found. - -IF (NETTLE_INCLUDE_DIR) - # Already in cache, be silent - SET(NETTLE_FIND_QUIETLY TRUE) -ENDIF (NETTLE_INCLUDE_DIR) - -FIND_PATH(NETTLE_INCLUDE_DIR nettle/md5.h nettle/ripemd160.h nettle/sha.h) -FIND_LIBRARY(NETTLE_LIBRARY NAMES nettle libnettle) - -# handle the QUIETLY and REQUIRED arguments and set NETTLE_FOUND to TRUE if -# all listed variables are TRUE -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(NETTLE DEFAULT_MSG NETTLE_LIBRARY NETTLE_INCLUDE_DIR) - -IF(NETTLE_FOUND) - SET(NETTLE_LIBRARIES ${NETTLE_LIBRARY}) -ENDIF(NETTLE_FOUND) +# - Find Nettle +# Find the Nettle include directory and library +# +# NETTLE_INCLUDE_DIR - where to find , etc. +# NETTLE_LIBRARIES - List of libraries when using libnettle. +# NETTLE_FOUND - True if libnettle found. + +IF (NETTLE_INCLUDE_DIR) + # Already in cache, be silent + SET(NETTLE_FIND_QUIETLY TRUE) +ENDIF (NETTLE_INCLUDE_DIR) + +FIND_PATH(NETTLE_INCLUDE_DIR nettle/md5.h nettle/ripemd160.h nettle/sha.h) +FIND_LIBRARY(NETTLE_LIBRARY NAMES nettle libnettle) + +# handle the QUIETLY and REQUIRED arguments and set NETTLE_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(NETTLE DEFAULT_MSG NETTLE_LIBRARY NETTLE_INCLUDE_DIR) + +IF(NETTLE_FOUND) + SET(NETTLE_LIBRARIES ${NETTLE_LIBRARY}) +ENDIF(NETTLE_FOUND) diff --git a/build/cmake/FindPCRE2POSIX.cmake b/build/cmake/FindPCRE2POSIX.cmake index 76bb7a455f..4104f3791a 100644 --- a/build/cmake/FindPCRE2POSIX.cmake +++ b/build/cmake/FindPCRE2POSIX.cmake @@ -1,34 +1,34 @@ -# - Find pcre2posix -# Find the native PCRE2-8 and PCRE2-POSIX include and libraries -# -# PCRE2_INCLUDE_DIR - where to find pcre2posix.h, etc. -# PCRE2POSIX_LIBRARIES - List of libraries when using libpcre2-posix. -# PCRE2_LIBRARIES - List of libraries when using libpcre2-8. -# PCRE2POSIX_FOUND - True if libpcre2-posix found. -# PCRE2_FOUND - True if libpcre2-8 found. - -IF (PCRE2_INCLUDE_DIR) - # Already in cache, be silent - SET(PCRE2_FIND_QUIETLY TRUE) -ENDIF (PCRE2_INCLUDE_DIR) - -FIND_PATH(PCRE2_INCLUDE_DIR pcre2posix.h) -FIND_LIBRARY(PCRE2POSIX_LIBRARY NAMES pcre2-posix libpcre2-posix pcre2-posix-static) -FIND_LIBRARY(PCRE2_LIBRARY NAMES pcre2-8 libpcre2-8 pcre2-8-static) - -# handle the QUIETLY and REQUIRED arguments and set PCRE2POSIX_FOUND to TRUE if -# all listed variables are TRUE -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE2POSIX DEFAULT_MSG PCRE2POSIX_LIBRARY PCRE2_INCLUDE_DIR) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE2 DEFAULT_MSG PCRE2_LIBRARY) - -IF(PCRE2POSIX_FOUND) - SET(PCRE2POSIX_LIBRARIES ${PCRE2POSIX_LIBRARY}) - SET(HAVE_LIBPCRE2POSIX 1) - SET(HAVE_PCRE2POSIX_H 1) -ENDIF(PCRE2POSIX_FOUND) - -IF(PCRE2_FOUND) - SET(PCRE2_LIBRARIES ${PCRE2_LIBRARY}) - SET(HAVE_LIBPCRE2 1) -ENDIF(PCRE2_FOUND) +# - Find pcre2posix +# Find the native PCRE2-8 and PCRE2-POSIX include and libraries +# +# PCRE2_INCLUDE_DIR - where to find pcre2posix.h, etc. +# PCRE2POSIX_LIBRARIES - List of libraries when using libpcre2-posix. +# PCRE2_LIBRARIES - List of libraries when using libpcre2-8. +# PCRE2POSIX_FOUND - True if libpcre2-posix found. +# PCRE2_FOUND - True if libpcre2-8 found. + +IF (PCRE2_INCLUDE_DIR) + # Already in cache, be silent + SET(PCRE2_FIND_QUIETLY TRUE) +ENDIF (PCRE2_INCLUDE_DIR) + +FIND_PATH(PCRE2_INCLUDE_DIR pcre2posix.h) +FIND_LIBRARY(PCRE2POSIX_LIBRARY NAMES pcre2-posix libpcre2-posix pcre2-posix-static) +FIND_LIBRARY(PCRE2_LIBRARY NAMES pcre2-8 libpcre2-8 pcre2-8-static) + +# handle the QUIETLY and REQUIRED arguments and set PCRE2POSIX_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE2POSIX DEFAULT_MSG PCRE2POSIX_LIBRARY PCRE2_INCLUDE_DIR) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE2 DEFAULT_MSG PCRE2_LIBRARY) + +IF(PCRE2POSIX_FOUND) + SET(PCRE2POSIX_LIBRARIES ${PCRE2POSIX_LIBRARY}) + SET(HAVE_LIBPCRE2POSIX 1) + SET(HAVE_PCRE2POSIX_H 1) +ENDIF(PCRE2POSIX_FOUND) + +IF(PCRE2_FOUND) + SET(PCRE2_LIBRARIES ${PCRE2_LIBRARY}) + SET(HAVE_LIBPCRE2 1) +ENDIF(PCRE2_FOUND) diff --git a/build/cmake/FindPCREPOSIX.cmake b/build/cmake/FindPCREPOSIX.cmake index 7cc40ec0fb..56cc17eacb 100644 --- a/build/cmake/FindPCREPOSIX.cmake +++ b/build/cmake/FindPCREPOSIX.cmake @@ -1,34 +1,34 @@ -# - Find pcreposix -# Find the native PCRE and PCREPOSIX include and libraries -# -# PCRE_INCLUDE_DIR - where to find pcreposix.h, etc. -# PCREPOSIX_LIBRARIES - List of libraries when using libpcreposix. -# PCRE_LIBRARIES - List of libraries when using libpcre. -# PCREPOSIX_FOUND - True if libpcreposix found. -# PCRE_FOUND - True if libpcre found. - -IF (PCRE_INCLUDE_DIR) - # Already in cache, be silent - SET(PCRE_FIND_QUIETLY TRUE) -ENDIF (PCRE_INCLUDE_DIR) - -FIND_PATH(PCRE_INCLUDE_DIR pcreposix.h) -FIND_LIBRARY(PCREPOSIX_LIBRARY NAMES pcreposix libpcreposix) -FIND_LIBRARY(PCRE_LIBRARY NAMES pcre libpcre) - -# handle the QUIETLY and REQUIRED arguments and set PCREPOSIX_FOUND to TRUE if -# all listed variables are TRUE -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCREPOSIX DEFAULT_MSG PCREPOSIX_LIBRARY PCRE_INCLUDE_DIR) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE DEFAULT_MSG PCRE_LIBRARY) - -IF(PCREPOSIX_FOUND) - SET(PCREPOSIX_LIBRARIES ${PCREPOSIX_LIBRARY}) - SET(HAVE_LIBPCREPOSIX 1) - SET(HAVE_PCREPOSIX_H 1) -ENDIF(PCREPOSIX_FOUND) - -IF(PCRE_FOUND) - SET(PCRE_LIBRARIES ${PCRE_LIBRARY}) - SET(HAVE_LIBPCRE 1) -ENDIF(PCRE_FOUND) +# - Find pcreposix +# Find the native PCRE and PCREPOSIX include and libraries +# +# PCRE_INCLUDE_DIR - where to find pcreposix.h, etc. +# PCREPOSIX_LIBRARIES - List of libraries when using libpcreposix. +# PCRE_LIBRARIES - List of libraries when using libpcre. +# PCREPOSIX_FOUND - True if libpcreposix found. +# PCRE_FOUND - True if libpcre found. + +IF (PCRE_INCLUDE_DIR) + # Already in cache, be silent + SET(PCRE_FIND_QUIETLY TRUE) +ENDIF (PCRE_INCLUDE_DIR) + +FIND_PATH(PCRE_INCLUDE_DIR pcreposix.h) +FIND_LIBRARY(PCREPOSIX_LIBRARY NAMES pcreposix libpcreposix) +FIND_LIBRARY(PCRE_LIBRARY NAMES pcre libpcre) + +# handle the QUIETLY and REQUIRED arguments and set PCREPOSIX_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCREPOSIX DEFAULT_MSG PCREPOSIX_LIBRARY PCRE_INCLUDE_DIR) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE DEFAULT_MSG PCRE_LIBRARY) + +IF(PCREPOSIX_FOUND) + SET(PCREPOSIX_LIBRARIES ${PCREPOSIX_LIBRARY}) + SET(HAVE_LIBPCREPOSIX 1) + SET(HAVE_PCREPOSIX_H 1) +ENDIF(PCREPOSIX_FOUND) + +IF(PCRE_FOUND) + SET(PCRE_LIBRARIES ${PCRE_LIBRARY}) + SET(HAVE_LIBPCRE 1) +ENDIF(PCRE_FOUND) diff --git a/build/version b/build/version index 4c388c39c7..3f78540c62 100644 --- a/build/version +++ b/build/version @@ -1 +1 @@ -3008002 +3008005 diff --git a/libarchive/archive.h b/libarchive/archive.h index 98d7674e18..a9d34beb4f 100644 --- a/libarchive/archive.h +++ b/libarchive/archive.h @@ -34,7 +34,7 @@ * assert that ARCHIVE_VERSION_NUMBER >= 2012108. */ /* Note: Compiler will complain if this does not match archive_entry.h! */ -#define ARCHIVE_VERSION_NUMBER 3008002 +#define ARCHIVE_VERSION_NUMBER 3008005 #include #include /* for wchar_t */ @@ -177,7 +177,7 @@ __LA_DECL int archive_version_number(void); /* * Textual name/version of the library, useful for version displays. */ -#define ARCHIVE_VERSION_ONLY_STRING "3.8.2" +#define ARCHIVE_VERSION_ONLY_STRING "3.8.5" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); diff --git a/libarchive/archive_cryptor.c b/libarchive/archive_cryptor.c index 9f03f9ca6d..b6a02fd1e7 100644 --- a/libarchive/archive_cryptor.c +++ b/libarchive/archive_cryptor.c @@ -490,9 +490,9 @@ aes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in, size_t in_len, uint8_t * const out, size_t *out_len) { uint8_t *const ebuf = ctx->encr_buf; - unsigned pos = ctx->encr_pos; - unsigned max = (unsigned)((in_len < *out_len)? in_len: *out_len); - unsigned i; + size_t pos = ctx->encr_pos; + size_t max = (in_len < *out_len)? in_len: *out_len; + size_t i; for (i = 0; i < max; ) { if (pos == AES_BLOCK_SIZE) { diff --git a/libarchive/archive_cryptor_private.h b/libarchive/archive_cryptor_private.h index 1dbc5c17a0..272f2f84b9 100644 --- a/libarchive/archive_cryptor_private.h +++ b/libarchive/archive_cryptor_private.h @@ -56,10 +56,10 @@ int __libarchive_cryptor_build_hack(void); typedef struct { CCCryptorRef ctx; uint8_t key[AES_MAX_KEY_SIZE]; - unsigned key_len; + size_t key_len; uint8_t nonce[AES_BLOCK_SIZE]; uint8_t encr_buf[AES_BLOCK_SIZE]; - unsigned encr_pos; + size_t encr_pos; } archive_crypto_ctx; #elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA diff --git a/libarchive/archive_disk_acl_darwin.c b/libarchive/archive_disk_acl_darwin.c index 12c3587c53..b4842d1848 100644 --- a/libarchive/archive_disk_acl_darwin.c +++ b/libarchive/archive_disk_acl_darwin.c @@ -124,7 +124,6 @@ static void add_trivial_nfs4_acl(struct archive_entry *entry) { mode_t mode; - int i; const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA; const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA | ARCHIVE_ENTRY_ACL_APPEND_DATA; @@ -195,7 +194,7 @@ add_trivial_nfs4_acl(struct archive_entry *entry) } else if ((mode & 0010) || (mode & 0001)) tacl_entry[1].permset |= eperm; - for (i = 0; i < sizeof(tacl_entry) / sizeof(tacl_entry[0]); i++) { + for (size_t i = 0; i < sizeof(tacl_entry) / sizeof(tacl_entry[0]); i++) { if (tacl_entry[i].permset != 0) { archive_entry_acl_add_entry(entry, tacl_entry[i].type, tacl_entry[i].permset, diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h index 344f33bffa..b43435692c 100644 --- a/libarchive/archive_entry.h +++ b/libarchive/archive_entry.h @@ -28,7 +28,7 @@ #define ARCHIVE_ENTRY_H_INCLUDED /* Note: Compiler will complain if this does not match archive.h! */ -#define ARCHIVE_VERSION_NUMBER 3008002 +#define ARCHIVE_VERSION_NUMBER 3008005 /* * Note: archive_entry.h is for use outside of libarchive; the diff --git a/libarchive/archive_entry_stat.3 b/libarchive/archive_entry_stat.3 index 29a53f7560..2f4a1920eb 100644 --- a/libarchive/archive_entry_stat.3 +++ b/libarchive/archive_entry_stat.3 @@ -207,7 +207,7 @@ for setting is recommended. The function .Fn archive_entry_size returns the file size, if it has been set, and 0 otherwise. -.Fn archive_entry_size +.Fn archive_entry_size_is_set can be used to query that status. .Fn archive_entry_set_size and diff --git a/libarchive/archive_read_disk_entry_from_file.c b/libarchive/archive_read_disk_entry_from_file.c index 42af4034b0..6e6bae6a4e 100644 --- a/libarchive/archive_read_disk_entry_from_file.c +++ b/libarchive/archive_read_disk_entry_from_file.c @@ -254,7 +254,7 @@ archive_read_disk_entry_from_file(struct archive *_a, if (S_ISLNK(st->st_mode)) { size_t linkbuffer_len = st->st_size; char *linkbuffer; - int lnklen; + ssize_t lnklen; linkbuffer = malloc(linkbuffer_len + 1); if (linkbuffer == NULL) { @@ -358,12 +358,10 @@ setup_mac_metadata(struct archive_read_disk *a, return (ARCHIVE_OK); archive_string_init(&tempfile); - if (__archive_get_tempdir(&tempfile) != ARCHIVE_OK) { - ret = ARCHIVE_WARN; - goto cleanup; - } - archive_strcat(&tempfile, "tar.md.XXXXXX"); - tempfd = mkstemp(tempfile.s); + archive_strcpy(&tempfile, name); + archive_string_dirname(&tempfile); + archive_strcat(&tempfile, "/tar.XXXXXXXX"); + tempfd = __archive_mkstemp(tempfile.s); if (tempfd < 0) { archive_set_error(&a->archive, errno, "Could not open extended attribute file"); @@ -894,7 +892,7 @@ setup_sparse_fiemap(struct archive_read_disk *a, for (iters = 0; ; ++iters) { int i, r; - r = ioctl(*fd, FS_IOC_FIEMAP, fm); + r = ioctl(*fd, FS_IOC_FIEMAP, fm); if (r < 0) { /* When something error happens, it is better we * should return ARCHIVE_OK because an earlier @@ -1081,4 +1079,3 @@ setup_sparse(struct archive_read_disk *a, #endif #endif /* !defined(_WIN32) || defined(__CYGWIN__) */ - diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c index 54a8e66188..94fa8fef96 100644 --- a/libarchive/archive_read_disk_posix.c +++ b/libarchive/archive_read_disk_posix.c @@ -107,6 +107,8 @@ #define O_CLOEXEC 0 #endif +#define MAX_FILESYSTEM_ID 1000000 + #if defined(__hpux) && !defined(HAVE_DIRFD) #define dirfd(x) ((x)->__dd_fd) #define HAVE_DIRFD @@ -1412,8 +1414,12 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) * This is the new filesystem which we have to generate a new ID for. */ fid = t->max_filesystem_id++; + if (fid > MAX_FILESYSTEM_ID) { + archive_set_error(&a->archive, ENOMEM, "Too many filesystems"); + return (ARCHIVE_FATAL); + } if (t->max_filesystem_id > t->allocated_filesystem) { - size_t s; + int s; void *p; s = t->max_filesystem_id * 2; @@ -1693,8 +1699,6 @@ setup_current_filesystem(struct archive_read_disk *a) #endif t->current_filesystem->noatime = 0; - /* Set maximum filename length. */ - t->current_filesystem->name_max = svfs.f_namemax; return (ARCHIVE_OK); } @@ -2014,11 +2018,8 @@ tree_dup(int fd) } #endif /* F_DUPFD_CLOEXEC */ new_fd = dup(fd); - if (new_fd != -1) { - __archive_ensure_cloexec_flag(new_fd); - return (new_fd); - } - return (-1); + __archive_ensure_cloexec_flag(new_fd); + return (new_fd); } /* @@ -2140,16 +2141,11 @@ tree_reopen(struct tree *t, const char *path, int restore_time) * so try again for execute. The consequences of not opening this are * unhelpful and unnecessary errors later. */ - if (t->initial_dir_fd < 0) { + if (t->initial_dir_fd < 0) t->initial_dir_fd = open(".", o_flag | O_CLOEXEC); - if (t->initial_dir_fd < 0) - return NULL; - } #endif __archive_ensure_cloexec_flag(t->initial_dir_fd); t->working_dir_fd = tree_dup(t->initial_dir_fd); - if (t->working_dir_fd < 0) - return NULL; return (t); } @@ -2355,15 +2351,20 @@ static int tree_dir_next_posix(struct tree *t) { int r; +#if defined(HAVE_FDOPENDIR) + int fd; +#endif const char *name; size_t namelen; if (t->d == NULL) { #if defined(HAVE_FDOPENDIR) - int fd = tree_dup(t->working_dir_fd); - if (fd != -1) - t->d = fdopendir(fd); + if (t->working_dir_fd >= 0) { + fd = tree_dup(t->working_dir_fd); + if (fd != -1) + t->d = fdopendir(fd); + } #else /* HAVE_FDOPENDIR */ if (tree_enter_working_dir(t) == 0) { t->d = opendir("."); diff --git a/libarchive/archive_read_disk_windows.c b/libarchive/archive_read_disk_windows.c index 689a45958c..117ca505fa 100644 --- a/libarchive/archive_read_disk_windows.c +++ b/libarchive/archive_read_disk_windows.c @@ -53,6 +53,8 @@ /* To deal with absolute symlink issues */ #define START_ABSOLUTE_SYMLINK_REPARSE L"\\??\\" +#define MAX_FILESYSTEM_ID 1000000 + /*- * This is a new directory-walking system that addresses a number * of problems I've had with fts(3). In particular, it has no @@ -1449,8 +1451,12 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) * There is a new filesystem, we generate a new ID for. */ fid = t->max_filesystem_id++; + if (fid > MAX_FILESYSTEM_ID) { + archive_set_error(&a->archive, ENOMEM, "Too many filesystems"); + return (ARCHIVE_FATAL); + } if (t->max_filesystem_id > t->allocated_filesystem) { - size_t s; + int s; void *p; s = t->max_filesystem_id * 2; @@ -1462,7 +1468,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) return (ARCHIVE_FATAL); } t->filesystem_table = (struct filesystem *)p; - t->allocated_filesystem = (int)s; + t->allocated_filesystem = s; } t->current_filesystem_id = fid; t->current_filesystem = &(t->filesystem_table[fid]); diff --git a/libarchive/archive_read_support_filter_lz4.c b/libarchive/archive_read_support_filter_lz4.c index 760e6d938d..144572ef23 100644 --- a/libarchive/archive_read_support_filter_lz4.c +++ b/libarchive/archive_read_support_filter_lz4.c @@ -49,9 +49,12 @@ #include "archive_xxhash.h" #define LZ4_MAGICNUMBER 0x184d2204 -#define LZ4_SKIPPABLED 0x184d2a50 #define LZ4_LEGACY 0x184c2102 +// Note: LZ4 and zstd share the same skippable frame format with the same magic numbers. +#define LZ4_SKIPPABLE_START 0x184D2A50 +#define LZ4_SKIPPABLE_MASK 0xFFFFFFF0 + #if defined(HAVE_LIBLZ4) struct private_data { enum { SELECT_STREAM, @@ -141,19 +144,67 @@ lz4_reader_bid(struct archive_read_filter_bidder *self, { const unsigned char *buffer; ssize_t avail; - int bits_checked; - uint32_t number; + int bits_checked = 0; + ssize_t min_lz4_archive_size = 11; - (void)self; /* UNUSED */ + // LZ4 skippable frames contain a 4 byte magic number followed by + // a 4 byte frame data size, then that number of bytes of data. Regular + // frames contain a 4 byte magic number followed by a 2-14 byte frame + // header, some data, and a 3 byte end marker. + ssize_t min_lz4_frame_size = 8; - /* Minimal lz4 archive is 11 bytes. */ - buffer = __archive_read_filter_ahead(filter, 11, &avail); + ssize_t offset_in_buffer = 0; + ssize_t max_lookahead = 64 * 1024; + + (void)self; // UNUSED + + // Zstd and LZ4 skippable frame magic numbers are identical. To + // differentiate these two, we need to look for a non-skippable + // frame. + + // Minimal lz4 archive is 11 bytes. + buffer = __archive_read_filter_ahead(filter, min_lz4_archive_size, &avail); if (buffer == NULL) return (0); - /* First four bytes must be LZ4 magic numbers. */ - bits_checked = 0; - if ((number = archive_le32dec(buffer)) == LZ4_MAGICNUMBER) { + uint32_t magic_number = archive_le32dec(buffer); + + while ((magic_number & LZ4_SKIPPABLE_MASK) == LZ4_SKIPPABLE_START) { + + offset_in_buffer += 4; // Skip over the magic number + + // Ensure that we can read another 4 bytes. + if (offset_in_buffer + 4 > avail) { + buffer = __archive_read_filter_ahead(filter, offset_in_buffer + 4, &avail); + if (buffer == NULL) + return (0); + } + + uint32_t frame_data_size = archive_le32dec(buffer + offset_in_buffer); + + // Skip over the 4 frame data size bytes, plus the value stored there. + offset_in_buffer += 4 + frame_data_size; + + // There should be at least one more frame if this is LZ4 data. + if (offset_in_buffer + min_lz4_frame_size > avail) { // TODO: should this be >= ? + if (offset_in_buffer + min_lz4_frame_size > max_lookahead) + return (0); + + buffer = __archive_read_filter_ahead(filter, offset_in_buffer + min_lz4_frame_size, &avail); + if (buffer == NULL) + return (0); + } + + magic_number = archive_le32dec(buffer + offset_in_buffer); + } + + // We have skipped over any skippable frames. Either a regular LZ4 frame + // follows, or this isn't LZ4 data. + + bits_checked = offset_in_buffer; + buffer = buffer + offset_in_buffer; + + if (magic_number == LZ4_MAGICNUMBER) { unsigned char flag, BD; bits_checked += 32; @@ -175,11 +226,16 @@ lz4_reader_bid(struct archive_read_filter_bidder *self, if (BD & ~0x70) return (0); bits_checked += 8; - } else if (number == LZ4_LEGACY) { - bits_checked += 32; + + return (bits_checked); } - - return (bits_checked); + + if (magic_number == LZ4_LEGACY) { + bits_checked += 32; + return (bits_checked); + } + + return (0); } #if !defined(HAVE_LIBLZ4) @@ -342,7 +398,7 @@ lz4_filter_read(struct archive_read_filter *self, const void **p) return lz4_filter_read_default_stream(self, p); else if (number == LZ4_LEGACY) return lz4_filter_read_legacy_stream(self, p); - else if ((number & ~0xF) == LZ4_SKIPPABLED) { + else if ((number & LZ4_SKIPPABLE_MASK) == LZ4_SKIPPABLE_START) { read_buf = __archive_read_filter_ahead( self->upstream, 4, NULL); if (read_buf == NULL) { diff --git a/libarchive/archive_read_support_filter_uu.c b/libarchive/archive_read_support_filter_uu.c index d722fe3436..acb8feb79b 100644 --- a/libarchive/archive_read_support_filter_uu.c +++ b/libarchive/archive_read_support_filter_uu.c @@ -232,8 +232,8 @@ bid_get_line(struct archive_read_filter *filter, size_t nbytes_req = (*ravail+1023) & ~1023U; ssize_t tested; - /* Increase reading bytes if it is not enough to at least - * new two lines. */ + /* Increase reading bytes if it is not enough for at least + * two new lines. */ if (nbytes_req < (size_t)*ravail + 160) nbytes_req <<= 1; @@ -411,7 +411,7 @@ ensure_in_buff_size(struct archive_read_filter *self, /* * Calculate a new buffer size for in_buff. - * Increase its value until it has enough size we need. + * Increase its value until it is enough for our needs. */ newsize = uudecode->in_allocated; do { @@ -494,7 +494,7 @@ read_more: } /* * If there is remaining data which is saved by - * previous calling, use it first. + * a previous call, use it first. */ if (ensure_in_buff_size(self, uudecode, avail_in + uudecode->in_cnt) != ARCHIVE_OK) diff --git a/libarchive/archive_read_support_filter_zstd.c b/libarchive/archive_read_support_filter_zstd.c index 9a1dd71abd..da7c540dbc 100644 --- a/libarchive/archive_read_support_filter_zstd.c +++ b/libarchive/archive_read_support_filter_zstd.c @@ -110,24 +110,67 @@ zstd_bidder_bid(struct archive_read_filter_bidder *self, { const unsigned char *buffer; ssize_t avail; - unsigned prefix; - /* Zstd frame magic values */ - unsigned zstd_magic = 0xFD2FB528U; - unsigned zstd_magic_skippable_start = 0x184D2A50U; - unsigned zstd_magic_skippable_mask = 0xFFFFFFF0; + // Zstandard skippable frames contain a 4 byte magic number followed by + // a 4 byte frame data size, then that number of bytes of data. Regular + // frames contain a 4 byte magic number followed by a 2-14 byte frame + // header, some data, and a 3 byte end marker. + ssize_t min_zstd_frame_size = 8; - (void) self; /* UNUSED */ + ssize_t offset_in_buffer = 0; + ssize_t max_lookahead = 64 * 1024; - buffer = __archive_read_filter_ahead(filter, 4, &avail); + // Zstd regular frame magic number. + uint32_t zstd_magic = 0xFD2FB528U; + + // Note: Zstd and LZ4 skippable frame magic numbers are identical. + // To differentiate these two, we need to look for a non-skippable + // frame. + uint32_t zstd_magic_skippable_start = 0x184D2A50; + uint32_t zstd_magic_skippable_mask = 0xFFFFFFF0; + + (void) self; // UNUSED + + buffer = __archive_read_filter_ahead(filter, min_zstd_frame_size, &avail); if (buffer == NULL) return (0); - prefix = archive_le32dec(buffer); - if (prefix == zstd_magic) - return (32); - if ((prefix & zstd_magic_skippable_mask) == zstd_magic_skippable_start) - return (32); + uint32_t magic_number = archive_le32dec(buffer); + + while ((magic_number & zstd_magic_skippable_mask) == zstd_magic_skippable_start) { + + offset_in_buffer += 4; // Skip over the magic number + + // Ensure that we can read another 4 bytes. + if (offset_in_buffer + 4 > avail) { + buffer = __archive_read_filter_ahead(filter, offset_in_buffer + 4, &avail); + if (buffer == NULL) + return (0); + } + + uint32_t frame_data_size = archive_le32dec(buffer + offset_in_buffer); + + // Skip over the 4 frame data size bytes, plus the value stored there. + offset_in_buffer += 4 + frame_data_size; + + // There should be at least one more frame if this is zstd data. + if (offset_in_buffer + min_zstd_frame_size > avail) { + if (offset_in_buffer + min_zstd_frame_size > max_lookahead) + return (0); + + buffer = __archive_read_filter_ahead(filter, offset_in_buffer + min_zstd_frame_size, &avail); + if (buffer == NULL) + return (0); + } + + magic_number = archive_le32dec(buffer + offset_in_buffer); + } + + // We have skipped over any skippable frames. Either a regular zstd frame + // follows, or this isn't zstd data. + + if (magic_number == zstd_magic) + return (offset_in_buffer + 4); return (0); } diff --git a/libarchive/archive_read_support_format_7zip.c b/libarchive/archive_read_support_format_7zip.c index 5954627331..330d5515dd 100644 --- a/libarchive/archive_read_support_format_7zip.c +++ b/libarchive/archive_read_support_format_7zip.c @@ -744,6 +744,7 @@ find_elf_data_sec(struct archive_read *a) const char *h; char big_endian, format_64; ssize_t bytes, min_addr = SFX_MIN_ADDR; + ssize_t request; uint64_t e_shoff, strtab_offset, strtab_size; uint16_t e_shentsize, e_shnum, e_shstrndx; uint16_t (*dec16)(const void *); @@ -796,7 +797,12 @@ find_elf_data_sec(struct archive_read *a) if (__archive_read_seek(a, e_shoff, SEEK_SET) < 0) { break; } - h = __archive_read_ahead(a, (size_t)e_shnum * (size_t)e_shentsize, NULL); + if (format_64) { + request = (size_t)e_shnum * (size_t)e_shentsize + 0x28; + } else { + request = (size_t)e_shnum * (size_t)e_shentsize + 0x18; + } + h = __archive_read_ahead(a, request, &bytes); if (h == NULL) { break; } diff --git a/libarchive/archive_read_support_format_cab.c b/libarchive/archive_read_support_format_cab.c index a96f7d3139..63755ef9e5 100644 --- a/libarchive/archive_read_support_format_cab.c +++ b/libarchive/archive_read_support_format_cab.c @@ -2813,7 +2813,7 @@ lzx_decode_blocks(struct lzx_stream *strm, int last) lzx_br_bits(&bre, mt_max_bits)); lzx_br_consume(&bre, mt_bitlen[c]); } - if (c > UCHAR_MAX) + if ((unsigned int)c > UCHAR_MAX) break; /* * 'c' is exactly literal code. diff --git a/libarchive/archive_read_support_format_cpio.c b/libarchive/archive_read_support_format_cpio.c index 74f3549d15..526096b39f 100644 --- a/libarchive/archive_read_support_format_cpio.c +++ b/libarchive/archive_read_support_format_cpio.c @@ -825,9 +825,9 @@ header_odc(struct archive_read *a, struct cpio *cpio, } /* - * NOTE: if a filename suffix is ".z", it is the file gziped by afio. - * it would be nice that we can show uncompressed file size and we can - * uncompressed file contents automatically, unfortunately we have nothing + * NOTE: if a filename suffix is ".z", it is a file gzipped by afio. + * it would be nice if we could show uncompressed file size and + * uncompress file contents automatically, unfortunately we have nothing * to get a uncompressed file size while reading each header. It means * we also cannot uncompress file contents under our framework. */ diff --git a/libarchive/archive_read_support_format_lha.c b/libarchive/archive_read_support_format_lha.c index 2a84ad9dd3..cf6a147abd 100644 --- a/libarchive/archive_read_support_format_lha.c +++ b/libarchive/archive_read_support_format_lha.c @@ -689,7 +689,7 @@ archive_read_format_lha_read_header(struct archive_read *a, * a pathname and a symlink has '\' character, a directory * separator in DOS/Windows. So we should convert it to '/'. */ - if (p[H_LEVEL_OFFSET] == 0) + if (lha->level == 0) lha_replace_path_separator(lha, entry); archive_entry_set_mode(entry, lha->mode); @@ -2374,7 +2374,7 @@ lzh_decode_blocks(struct lzh_stream *strm, int last) lzh_br_consume(&bre, lt_bitlen[c]); } blocks_avail--; - if (c > UCHAR_MAX) + if ((unsigned int)c > UCHAR_MAX) /* Current block is a match data. */ break; /* diff --git a/libarchive/archive_read_support_format_mtree.c b/libarchive/archive_read_support_format_mtree.c index ded13bee79..10c07b05d9 100644 --- a/libarchive/archive_read_support_format_mtree.c +++ b/libarchive/archive_read_support_format_mtree.c @@ -392,8 +392,8 @@ next_line(struct archive_read *a, if (len >= MAX_LINE_LEN) return (-1); - /* Increase reading bytes if it is not enough to at least - * new two lines. */ + /* Increase reading bytes if it is not enough for at least + * two new lines. */ if (nbytes_req < (size_t)*ravail + 160) nbytes_req <<= 1; @@ -568,8 +568,8 @@ bid_keyword_list(const char *p, ssize_t len, int unset, int last_is_path) --len; value = 1; } - /* A keyword should have a its value unless - * "/unset" operation. */ + /* A keyword should have a value unless this is + * an "/unset" operation. */ if (!unset && value == 0) return (-1); } @@ -752,7 +752,7 @@ detect_form(struct archive_read *a, int *is_form_d) } else if (form_D == 1) { if (!last_is_path && keywords > 0) /* This this is not `form D' - * and We cannot accept mixed + * and we cannot accept mixed * format. */ break; } @@ -805,7 +805,7 @@ detect_form(struct archive_read *a, int *is_form_d) * to read the entire mtree file into memory up front. * * The parsing is done in two steps. First, it is decided if a line - * changes the global defaults and if it is, processed accordingly. + * changes the global defaults and if it does, it is processed accordingly. * Otherwise, the options of the line are merged with the current * global options. */ @@ -1254,7 +1254,7 @@ parse_file(struct archive_read *a, struct archive_entry *entry, archive_entry_filetype(entry) == AE_IFDIR) { mtree->fd = open(path, O_RDONLY | O_BINARY | O_CLOEXEC); __archive_ensure_cloexec_flag(mtree->fd); - if (mtree->fd < 0 && ( + if (mtree->fd == -1 && ( #if defined(_WIN32) && !defined(__CYGWIN__) /* * On Windows, attempting to open a file with an diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c index eeb2c725f6..98f7d69957 100644 --- a/libarchive/archive_read_support_format_tar.c +++ b/libarchive/archive_read_support_format_tar.c @@ -2311,6 +2311,7 @@ pax_attribute_read_number(struct archive_read *a, size_t value_length, int64_t * archive_string_init(&as); r = read_bytes_to_string(a, &as, value_length, &unconsumed); if (tar_flush_unconsumed(a, &unconsumed) != ARCHIVE_OK) { + *result = 0; return (ARCHIVE_FATAL); } if (r < ARCHIVE_OK) { diff --git a/libarchive/archive_read_support_format_zip.c b/libarchive/archive_read_support_format_zip.c index 9abd55709e..0c86ce935e 100644 --- a/libarchive/archive_read_support_format_zip.c +++ b/libarchive/archive_read_support_format_zip.c @@ -78,6 +78,12 @@ #include "archive_crc32.h" #endif +/* length of local file header, not including filename and extra */ +#define ZIP_LOCHDR_LEN 30U + +/* maximum length of Mac metadata in MiB */ +#define ZIP_MAX_METADATA 10U + struct zip_entry { struct archive_rb_node node; struct zip_entry *next; @@ -933,7 +939,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, zip->init_default_conversion = 1; } - if ((p = __archive_read_ahead(a, 30, NULL)) == NULL) { + if ((p = __archive_read_ahead(a, ZIP_LOCHDR_LEN, NULL)) == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated ZIP file header"); return (ARCHIVE_FATAL); @@ -969,7 +975,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, filename_length = archive_le16dec(p + 26); extra_length = archive_le16dec(p + 28); - __archive_read_consume(a, 30); + __archive_read_consume(a, ZIP_LOCHDR_LEN); /* Read the filename. */ if ((h = __archive_read_ahead(a, filename_length, NULL)) == NULL) { @@ -3637,7 +3643,7 @@ read_eocd(struct zip *zip, const char *p, int64_t current_offset) { uint16_t disk_num; uint32_t cd_size, cd_offset; - + disk_num = archive_le16dec(p + 4); cd_size = archive_le32dec(p + 12); cd_offset = archive_le32dec(p + 16); @@ -4097,7 +4103,7 @@ zip_get_local_file_header_size(struct archive_read *a, size_t extra) const char *p; ssize_t filename_length, extra_length; - if ((p = __archive_read_ahead(a, extra + 30, NULL)) == NULL) { + if ((p = __archive_read_ahead(a, extra + ZIP_LOCHDR_LEN, NULL)) == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated ZIP file header"); return (ARCHIVE_WARN); @@ -4111,7 +4117,7 @@ zip_get_local_file_header_size(struct archive_read *a, size_t extra) filename_length = archive_le16dec(p + 26); extra_length = archive_le16dec(p + 28); - return (30 + filename_length + extra_length); + return (ZIP_LOCHDR_LEN + filename_length + extra_length); } static int @@ -4148,16 +4154,16 @@ zip_read_mac_metadata(struct archive_read *a, struct archive_entry *entry, return (ARCHIVE_WARN); } - if (rsrc->uncompressed_size > (4 * 1024 * 1024)) { + if (rsrc->uncompressed_size > ZIP_MAX_METADATA * 1048576U) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Mac metadata is too large: %jd > 4M bytes", - (intmax_t)rsrc->uncompressed_size); + "Mac metadata is too large: %jd > %u MiB", + (intmax_t)rsrc->uncompressed_size, ZIP_MAX_METADATA); return (ARCHIVE_WARN); } - if (rsrc->compressed_size > (4 * 1024 * 1024)) { + if (rsrc->compressed_size > ZIP_MAX_METADATA * 1048576U) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Mac metadata is too large: %jd > 4M bytes", - (intmax_t)rsrc->compressed_size); + "Mac metadata is too large: %jd > %u MiB", + (intmax_t)rsrc->compressed_size, ZIP_MAX_METADATA); return (ARCHIVE_WARN); } diff --git a/libarchive/archive_string.c b/libarchive/archive_string.c index 3bb978335e..a776dc85c6 100644 --- a/libarchive/archive_string.c +++ b/libarchive/archive_string.c @@ -2054,6 +2054,26 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n, return (r); } +struct archive_string * +archive_string_dirname(struct archive_string *as) +{ + /* strip trailing separators */ + while (as->length > 1 && as->s[as->length - 1] == '/') + as->length--; + /* strip final component */ + while (as->length > 0 && as->s[as->length - 1] != '/') + as->length--; + /* empty path -> cwd */ + if (as->length == 0) + return (archive_strcat(as, ".")); + /* strip separator(s) */ + while (as->length > 1 && as->s[as->length - 1] == '/') + as->length--; + /* terminate */ + as->s[as->length] = '\0'; + return (as); +} + #if HAVE_ICONV /* @@ -3553,7 +3573,7 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes, if (sc->to_cp == CP_C_LOCALE) { /* - * "C" locale special process. + * "C" locale special processing. */ u16 = _p; ll = 0; @@ -3670,7 +3690,7 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p, avail = as16->buffer_length - 2; if (sc->from_cp == CP_C_LOCALE) { /* - * "C" locale special process. + * "C" locale special processing. */ count = 0; while (count < length && *s) { diff --git a/libarchive/archive_string.h b/libarchive/archive_string.h index e8987867d3..d5f5c03aca 100644 --- a/libarchive/archive_string.h +++ b/libarchive/archive_string.h @@ -192,6 +192,10 @@ void archive_string_vsprintf(struct archive_string *, const char *, void archive_string_sprintf(struct archive_string *, const char *, ...) __LA_PRINTF(2, 3); +/* Equivalent to dirname(3) */ +struct archive_string * +archive_string_dirname(struct archive_string *); + /* Translates from MBS to Unicode. */ /* Returns non-zero if conversion failed in any way. */ int archive_wstring_append_from_mbs(struct archive_wstring *dest, diff --git a/libarchive/archive_util.c b/libarchive/archive_util.c index d048bbc946..0d1de1ef20 100644 --- a/libarchive/archive_util.c +++ b/libarchive/archive_util.c @@ -456,7 +456,7 @@ __archive_issetugid(void) return (-1); if (ruid != euid || ruid != suid) return (1); - if (getresgid(&ruid, &egid, &sgid) != 0) + if (getresgid(&rgid, &egid, &sgid) != 0) return (-1); if (rgid != egid || rgid != sgid) return (1); diff --git a/libarchive/archive_version_details.c b/libarchive/archive_version_details.c index 0cf92db731..9063faa794 100644 --- a/libarchive/archive_version_details.c +++ b/libarchive/archive_version_details.c @@ -333,7 +333,7 @@ archive_libbsdxml_version(void) const char * archive_libxml2_version(void) { -#if HAVE_LIBXML_XMLREADER_H && HAVE_LIBXML2 +#if HAVE_LIBXML_XMLVERSION_H && HAVE_LIBXML2 return LIBXML_DOTTED_VERSION; #else return NULL; diff --git a/libarchive/archive_windows.c b/libarchive/archive_windows.c index e55f995c77..3fbea6c5b6 100644 --- a/libarchive/archive_windows.c +++ b/libarchive/archive_windows.c @@ -253,7 +253,7 @@ la_CreateFile(const char *path, DWORD dwDesiredAccess, DWORD dwShareMode, createExParams.dwSize = sizeof(createExParams); createExParams.dwFileAttributes = dwFlagsAndAttributes & 0xFFFF; createExParams.dwFileFlags = dwFlagsAndAttributes & 0xFFF00000; - createExParams.dwSecurityQosFlags = dwFlagsAndAttributes & 0x000F00000; + createExParams.dwSecurityQosFlags = dwFlagsAndAttributes & 0x000F0000; createExParams.lpSecurityAttributes = lpSecurityAttributes; createExParams.hTemplateFile = hTemplateFile; handle = CreateFile2(wpath, dwDesiredAccess, dwShareMode, @@ -747,7 +747,8 @@ __la_seek_fstat(int fd, la_seek_stat_t *st) int ret; ret = __hstat((HANDLE)_get_osfhandle(fd), &u); - copy_seek_stat(st, &u); + if (ret >= 0) + copy_seek_stat(st, &u); return (ret); } diff --git a/libarchive/archive_write.c b/libarchive/archive_write.c index 9b9cb196f0..e1ce5d5728 100644 --- a/libarchive/archive_write.c +++ b/libarchive/archive_write.c @@ -821,7 +821,7 @@ _archive_write_data(struct archive *_a, const void *buff, size_t s) { struct archive_write *a = (struct archive_write *)_a; const size_t max_write = INT_MAX; - int ret; + ssize_t ret; archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_DATA, "archive_write_data"); diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c index 6fcf3929b5..d1f043d244 100644 --- a/libarchive/archive_write_disk_posix.c +++ b/libarchive/archive_write_disk_posix.c @@ -412,12 +412,14 @@ static ssize_t _archive_write_disk_data_block(struct archive *, const void *, static int la_mktemp(struct archive_write_disk *a) { + struct archive_string *tmp = &a->_tmpname_data; int oerrno, fd; mode_t mode; - archive_string_empty(&a->_tmpname_data); - archive_string_sprintf(&a->_tmpname_data, "%s.XXXXXX", a->name); - a->tmpname = a->_tmpname_data.s; + archive_strcpy(tmp, a->name); + archive_string_dirname(tmp); + archive_strcat(tmp, "/tar.XXXXXXXX"); + a->tmpname = tmp->s; fd = __archive_mkstemp(a->tmpname); if (fd == -1) @@ -2559,9 +2561,9 @@ _archive_write_disk_close(struct archive *_a) * for directories. For other file types * we need to verify via fstat() or lstat() */ - if (fd < 0 || p->filetype != AE_IFDIR) { + if (fd == -1 || p->filetype != AE_IFDIR) { #if HAVE_FSTAT - if (fd >= 0 && ( + if (fd > 0 && ( fstat(fd, &st) != 0 || la_verify_filetype(st.st_mode, p->filetype) == 0)) { @@ -4287,8 +4289,10 @@ create_tempdatafork(struct archive_write_disk *a, const char *pathname) int tmpfd; archive_string_init(&tmpdatafork); - archive_strcpy(&tmpdatafork, "tar.md.XXXXXX"); - tmpfd = mkstemp(tmpdatafork.s); + archive_strcpy(&tmpdatafork, pathname); + archive_string_dirname(&tmpdatafork); + archive_strcat(&tmpdatafork, "/tar.XXXXXXXX"); + tmpfd = __archive_mkstemp(tmpdatafork.s); if (tmpfd < 0) { archive_set_error(&a->archive, errno, "Failed to mkstemp"); @@ -4367,8 +4371,10 @@ set_mac_metadata(struct archive_write_disk *a, const char *pathname, * silly dance of writing the data to disk just so that * copyfile() can read it back in again. */ archive_string_init(&tmp); - archive_strcpy(&tmp, "tar.mmd.XXXXXX"); - fd = mkstemp(tmp.s); + archive_strcpy(&tmp, pathname); + archive_string_dirname(&tmp); + archive_strcat(&tmp, "/tar.XXXXXXXX"); + fd = __archive_mkstemp(tmp.s); if (fd < 0) { archive_set_error(&a->archive, errno, @@ -4441,7 +4447,7 @@ fixup_appledouble(struct archive_write_disk *a, const char *pathname) */ fd = open(pathname, O_RDONLY | O_BINARY | O_CLOEXEC); __archive_ensure_cloexec_flag(fd); - if (fd < 0) { + if (fd == -1) { archive_set_error(&a->archive, errno, "Failed to open a restoring file"); ret = ARCHIVE_WARN; diff --git a/libarchive/archive_write_open_fd.c b/libarchive/archive_write_open_fd.c index ba034ed92f..a795552020 100644 --- a/libarchive/archive_write_open_fd.c +++ b/libarchive/archive_write_open_fd.c @@ -135,11 +135,7 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length static int file_free(struct archive *a, void *client_data) { - struct write_fd_data *mine = (struct write_fd_data *)client_data; - (void)a; /* UNUSED */ - if (mine == NULL) - return (ARCHIVE_OK); - free(mine); + free(client_data); return (ARCHIVE_OK); } diff --git a/libarchive/archive_write_open_file.c b/libarchive/archive_write_open_file.c index 0b310f3da8..6271b368d0 100644 --- a/libarchive/archive_write_open_file.c +++ b/libarchive/archive_write_open_file.c @@ -96,11 +96,7 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length static int file_free(struct archive *a, void *client_data) { - struct write_FILE_data *mine = client_data; - (void)a; /* UNUSED */ - if (mine == NULL) - return (ARCHIVE_OK); - free(mine); + free(client_data); return (ARCHIVE_OK); } diff --git a/libarchive/archive_write_open_filename.c b/libarchive/archive_write_open_filename.c index 7d0f9bde1d..430de21fde 100644 --- a/libarchive/archive_write_open_filename.c +++ b/libarchive/archive_write_open_filename.c @@ -191,6 +191,8 @@ file_open(struct archive *a, void *client_data) archive_set_error(a, errno, "Couldn't stat '%s'", mbs); else archive_set_error(a, errno, "Couldn't stat '%ls'", wcs); + close(mine->fd); + mine->fd = -1; return (ARCHIVE_FATAL); } diff --git a/libarchive/archive_write_open_memory.c b/libarchive/archive_write_open_memory.c index e316504472..3b929ac7f6 100644 --- a/libarchive/archive_write_open_memory.c +++ b/libarchive/archive_write_open_memory.c @@ -104,11 +104,7 @@ memory_write(struct archive *a, void *client_data, const void *buff, size_t leng static int memory_write_free(struct archive *a, void *client_data) { - struct write_memory_data *mine; (void)a; /* UNUSED */ - mine = client_data; - if (mine == NULL) - return (ARCHIVE_OK); - free(mine); + free(client_data); return (ARCHIVE_OK); } diff --git a/libarchive/archive_write_set_format_shar.c b/libarchive/archive_write_set_format_shar.c index be9f78ce96..f6f28debdf 100644 --- a/libarchive/archive_write_set_format_shar.c +++ b/libarchive/archive_write_set_format_shar.c @@ -144,7 +144,9 @@ archive_write_set_format_shar_dump(struct archive *_a) struct archive_write *a = (struct archive_write *)_a; struct shar *shar; - archive_write_set_format_shar(&a->archive); + int ret = archive_write_set_format_shar(&a->archive); + if (ret != ARCHIVE_OK) + return ret; shar = (struct shar *)a->format_data; shar->dump = 1; a->format_write_data = archive_write_shar_data_uuencode; @@ -240,6 +242,7 @@ archive_write_shar_header(struct archive_write *a, struct archive_entry *entry) shar_quote(&shar->work, p, 1); archive_strcat(&shar->work, " > /dev/null 2>&1\n"); + free(shar->last_dir); shar->last_dir = p; } } else { diff --git a/libarchive/archive_write_set_format_ustar.c b/libarchive/archive_write_set_format_ustar.c index 09b71fe667..4084eb4559 100644 --- a/libarchive/archive_write_set_format_ustar.c +++ b/libarchive/archive_write_set_format_ustar.c @@ -539,7 +539,7 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512], ret = ARCHIVE_WARN; } if (copy_length > 0) { - if (strlen(p) > USTAR_gname_size) { + if (copy_length > USTAR_gname_size) { if (tartype != 'x') { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Group name too long"); diff --git a/libarchive/archive_write_set_format_xar.c b/libarchive/archive_write_set_format_xar.c index 9921f1032b..ec3219057e 100644 --- a/libarchive/archive_write_set_format_xar.c +++ b/libarchive/archive_write_set_format_xar.c @@ -1000,13 +1000,13 @@ xmlwrite_heap(struct archive_write *a, struct xml_writer *writer, const char *encname; int r; - r = xmlwrite_fstring(a, writer, "length", "%ju", heap->length); + r = xmlwrite_fstring(a, writer, "length", "%ju", (uintmax_t)heap->length); if (r < 0) return (ARCHIVE_FATAL); - r = xmlwrite_fstring(a, writer, "offset", "%ju", heap->temp_offset); + r = xmlwrite_fstring(a, writer, "offset", "%ju", (uintmax_t)heap->temp_offset); if (r < 0) return (ARCHIVE_FATAL); - r = xmlwrite_fstring(a, writer, "size", "%ju", heap->size); + r = xmlwrite_fstring(a, writer, "size", "%ju", (uintmax_t)heap->size); if (r < 0) return (ARCHIVE_FATAL); switch (heap->compression) { @@ -1356,7 +1356,7 @@ make_file_entry(struct archive_write *a, struct xml_writer *writer, * Make a inode entry, "". */ r = xmlwrite_fstring(a, writer, "inode", - "%jd", archive_entry_ino64(file->entry)); + "%jd", (intmax_t)archive_entry_ino64(file->entry)); if (r < 0) return (ARCHIVE_FATAL); if (archive_entry_dev(file->entry) != 0) { @@ -1378,7 +1378,7 @@ make_file_entry(struct archive_write *a, struct xml_writer *writer, * Make a user entry, "" and ". */ r = xmlwrite_fstring(a, writer, "uid", - "%d", archive_entry_uid(file->entry)); + "%jd", (intmax_t)archive_entry_uid(file->entry)); if (r < 0) return (ARCHIVE_FATAL); r = archive_entry_uname_l(file->entry, &p, &len, xar->sconv); @@ -1404,7 +1404,7 @@ make_file_entry(struct archive_write *a, struct xml_writer *writer, * Make a group entry, "" and ". */ r = xmlwrite_fstring(a, writer, "gid", - "%d", archive_entry_gid(file->entry)); + "%jd", (intmax_t)archive_entry_gid(file->entry)); if (r < 0) return (ARCHIVE_FATAL); r = archive_entry_gname_l(file->entry, &p, &len, xar->sconv); diff --git a/libarchive/module.modulemap b/libarchive/module.modulemap new file mode 100644 index 0000000000..70f70fc3a1 --- /dev/null +++ b/libarchive/module.modulemap @@ -0,0 +1,34 @@ +/* + * Clang Module Map for libarchive + * + * What this is: + * This file tells the Clang compiler how to treat libarchive as a "module" - + * a self-contained unit of code that can be imported all at once instead of + * including individual header files. Think of it like a package definition. + * + * How it works: + * - When you write `@import CArchive` (Objective-C) or `import CArchive` (Swift), + * the compiler uses this file to know which headers belong to libarchive + * - Instead of processing each #include separately, the compiler can load a + * pre-compiled version of the entire library, making builds faster + * - This also provides better dependency tracking and can catch issues like + * conflicting macro definitions between libraries + * + * When to update: + * Update this file whenever: + * - New public header files are added to libarchive's libarchive/ directory + * - Public headers are removed or renamed + * - The library's API structure changes significantly + * + * You typically don't need to update this for: + * - Internal implementation changes + * - Private/internal header modifications + * - Documentation updates + * + * NOTE: This only affects projects using Clang with modules enabled. Traditional + * #include-based builds will continue to work normally with or without this file. + */ +module CArchive { + header "archive.h" + header "archive_entry.h" +}