aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Matuska <mm@FreeBSD.org>2024-04-26 10:11:59 +0000
committerMartin Matuska <mm@FreeBSD.org>2024-04-26 10:11:59 +0000
commitd6f77d3cfa8e56aed99e2ea250fdb242f51747df (patch)
treec54748bd439b0fa85deafd8f4915301a16d1acd7
parenta509d68f27b9f114b876bbe3b9caa9d0ee0c5606 (diff)
downloadsrc-d6f77d3cfa8e56aed99e2ea250fdb242f51747df.tar.gz
src-d6f77d3cfa8e56aed99e2ea250fdb242f51747df.zip
Update vendor/libarchive to 3.7.4
Security fixes: #2135 rar: Fix OOB in rar e8 filter (CVE-2024-26256) #2145 zip: Fix out of boundary access Important bugfixes: #2131 7zip: Limit amount of properties #2110 bsdtar: Fix error handling around strtol() usages #2116 passphrase: Never allow empty passwords #2124 rar: Fix "File CRC Error" when extracting specific rar4 archives #2123 xar: Avoid infinite link loop #2108 zip: Update AppleDouble support for directories #2071 zstd: Implement core detection Obained from: libarchive Libarchive commit: 313aa1fa10b657de791e3202c168a6c833bc3543
-rw-r--r--.github/dependabot.yml2
-rw-r--r--.github/workflows/ci.yml16
-rw-r--r--.github/workflows/cifuzz.yml2
-rw-r--r--.github/workflows/codeql.yml8
-rw-r--r--.github/workflows/scorecard.yml6
-rw-r--r--.gitignore17
-rw-r--r--CMakeLists.txt13
-rw-r--r--Makefile.am2
-rw-r--r--NEWS2
-rw-r--r--README.md2
-rwxr-xr-xbuild/ci/github_actions/macos.sh1
-rw-r--r--build/cmake/config.h.in3
-rw-r--r--build/version2
-rw-r--r--cat/cmdline.c16
-rw-r--r--configure.ac7
-rw-r--r--cpio/cmdline.c16
-rw-r--r--libarchive/archive.h6
-rw-r--r--libarchive/archive_entry.h2
-rw-r--r--libarchive/archive_entry_acl.32
-rw-r--r--libarchive/archive_read_disk.34
-rw-r--r--libarchive/archive_read_support_format_7zip.c2
-rw-r--r--libarchive/archive_read_support_format_all.c2
-rw-r--r--libarchive/archive_read_support_format_ar.c4
-rw-r--r--libarchive/archive_read_support_format_lha.c4
-rw-r--r--libarchive/archive_read_support_format_mtree.c8
-rw-r--r--libarchive/archive_read_support_format_rar.c15
-rw-r--r--libarchive/archive_read_support_format_warc.c10
-rw-r--r--libarchive/archive_read_support_format_xar.c5
-rw-r--r--libarchive/archive_read_support_format_zip.c15
-rw-r--r--libarchive/archive_util.c3
-rw-r--r--libarchive/archive_write_add_filter_zstd.c23
-rw-r--r--libarchive/archive_write_disk_posix.c3
-rw-r--r--libarchive/archive_write_private.h2
-rw-r--r--libarchive/archive_write_set_format_gnutar.c2
-rw-r--r--libarchive/archive_write_set_passphrase.c35
-rw-r--r--libarchive/libarchive_internals.32
-rw-r--r--libarchive/test/CMakeLists.txt1
-rw-r--r--libarchive/test/test_compat_lzip.c1
-rw-r--r--libarchive/test/test_read_format_xar_doublelink.c55
-rw-r--r--libarchive/test/test_read_format_xar_doublelink.xar.uu12
-rw-r--r--libarchive/test/test_write_disk_appledouble.c84
-rw-r--r--libarchive/test/test_write_disk_appledouble_zip.zip.uu27
-rw-r--r--libarchive_fe/passphrase.c4
-rw-r--r--tar/bsdtar.115
-rw-r--r--tar/bsdtar.c63
-rw-r--r--tar/cmdline.c16
-rw-r--r--unzip/cmdline.c18
-rw-r--r--unzip/test/test_I.c13
48 files changed, 437 insertions, 136 deletions
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index e4b8a2f5e440..4b45e5b2a1b0 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -9,6 +9,8 @@ updates:
directory: "/"
schedule:
interval: "weekly"
+ commit-message:
+ prefix: "CI"
groups:
all-actions:
patterns:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 3ecc4434cd11..dd49533dc087 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -12,7 +12,7 @@ jobs:
matrix:
bs: [autotools, cmake]
steps:
- - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
+ - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
- name: Install dependencies
run: ./build/ci/github_actions/macos.sh prepare
- name: Autogen
@@ -45,7 +45,7 @@ jobs:
run: ./build/ci/build.sh -a artifact
env:
BS: ${{ matrix.bs }}
- - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: libarchive-macos-${{ matrix.bs }}-${{ github.sha }}
path: libarchive.tar.xz
@@ -57,7 +57,7 @@ jobs:
bs: [autotools, cmake]
crypto: [mbedtls, nettle, openssl]
steps:
- - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
+ - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
- name: Update apt cache
run: sudo apt-get update
- name: Install dependencies
@@ -91,14 +91,14 @@ jobs:
run: ./build/ci/build.sh -a artifact
env:
BS: ${{ matrix.bs }}
- - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: libarchive-ubuntu-${{ matrix.bs }}-${{ matrix.crypto }}-${{ github.sha }}
path: libarchive.tar.xz
Ubuntu-distcheck:
runs-on: ubuntu-22.04
steps:
- - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
+ - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
- name: Update package definitions
run: sudo apt-get update
- name: Install dependencies
@@ -113,7 +113,7 @@ jobs:
SKIP_OPEN_FD_ERR_TEST: 1
- name: Dist-Artifact
run: ./build/ci/build.sh -a dist-artifact
- - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: libarchive-${{ github.sha }}
path: libarchive-dist.tar
@@ -125,7 +125,7 @@ jobs:
matrix:
be: [mingw-gcc, msvc]
steps:
- - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
+ - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
- name: Install mingw
if: ${{ matrix.be=='mingw-gcc' }}
run: choco install mingw
@@ -161,7 +161,7 @@ jobs:
shell: cmd
env:
BE: ${{ matrix.be }}
- - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: libarchive-windows-${{ matrix.be }}-${{ github.sha }}
path: libarchive.zip
diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml
index 9dd1dc3ec1a0..ddacccc318cf 100644
--- a/.github/workflows/cifuzz.yml
+++ b/.github/workflows/cifuzz.yml
@@ -21,7 +21,7 @@ jobs:
fuzz-seconds: 600
dry-run: false
- name: Upload Crash
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index b9e4dcc48e5a..17e6bf72dd90 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -26,18 +26,18 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
+ uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
- name: Initialize CodeQL
- uses: github/codeql-action/init@05963f47d870e2cb19a537396c1f668a348c7d8f # v3.24.8
+ uses: github/codeql-action/init@8f596b4ae3cb3c588a5c46780b86dd53fef16c52 # v3.25.2
with:
languages: ${{ matrix.language }}
queries: +security-and-quality
- name: Autobuild
- uses: github/codeql-action/autobuild@05963f47d870e2cb19a537396c1f668a348c7d8f # v3.24.8
+ uses: github/codeql-action/autobuild@8f596b4ae3cb3c588a5c46780b86dd53fef16c52 # v3.25.2
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@05963f47d870e2cb19a537396c1f668a348c7d8f # v3.24.8
+ uses: github/codeql-action/analyze@8f596b4ae3cb3c588a5c46780b86dd53fef16c52 # v3.25.2
with:
category: "/language:${{ matrix.language }}"
diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml
index b6c4f17a9b31..d05080c54d6b 100644
--- a/.github/workflows/scorecard.yml
+++ b/.github/workflows/scorecard.yml
@@ -29,7 +29,7 @@ jobs:
steps:
- name: "Checkout code"
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
+ uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3
with:
persist-credentials: false
@@ -52,7 +52,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: SARIF file
path: results.sarif
@@ -60,6 +60,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@05963f47d870e2cb19a537396c1f668a348c7d8f # v3.24.8
+ uses: github/codeql-action/upload-sarif@8f596b4ae3cb3c588a5c46780b86dd53fef16c52 # v3.25.2
with:
sarif_file: results.sarif
diff --git a/.gitignore b/.gitignore
index 8dc637ee132d..368828b8d0ce 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,13 +1,23 @@
*~
*.o
+*.obj
*.exe
+*.exp
+*.ilk
*.la
+*.lib
*.lo
+*.recipe
+*.sln
+*.tlog
*.cmake
+*.vcxproj
+*.vcxproj.filters
!build/cmake/*.cmake
.deps/
.libs/
bin/
+out/
.dirstamp
Makefile
Makefile.in
@@ -29,7 +39,13 @@ build/autoconf/ltsugar.m4
build/autoconf/ltversion.m4
build/autoconf/lt~obsolete.m4
build/autoconf/missing
+build/build/pkgconfig/libarchive.pc
+build/cat/test/list.h
+build/cpio/test/list.h
+build/libarchive/test/list.h
build/pkgconfig/libarchive.pc
+build/tar/test/list.h
+build/unzip/test/list.h
cat/test/list.h
config.cache
config.h
@@ -47,6 +63,7 @@ CMakeCache.txt
CMakeFiles/
DartConfiguration.tcl
cmake.tmp/
+.vs/
.vscode/
doc/html/*.html
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c0fbd70b38e8..ec97e4c7738c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -34,13 +34,15 @@ IF("${cached_type}" STREQUAL "UNINITIALIZED")
SET(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING "Build Type" FORCE)
ENDIF("${cached_type}" STREQUAL "UNINITIALIZED")
# Check the Build Type.
-IF(NOT "${CMAKE_BUILD_TYPE}"
- MATCHES "^(Debug|Release|RelWithDebInfo|MinSizeRel|None)\$")
+# Convert the CMAKE_BUILD_TYPE to uppercase to perform a case-insensitive comparison.
+string(TOUPPER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_UPPER)
+IF(NOT "${CMAKE_BUILD_TYPE_UPPER}"
+ MATCHES "^(DEBUG|RELEASE|RELWITHDEBINFO|MINSIZEREL|NONE)\$")
MESSAGE(FATAL_ERROR
"Unknown keyword for CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}\n"
- "Acceptable keywords: Debug,Release,RelWithDebInfo,MinSizeRel,None")
-ENDIF(NOT "${CMAKE_BUILD_TYPE}"
- MATCHES "^(Debug|Release|RelWithDebInfo|MinSizeRel|None)\$")
+ "Acceptable keywords: Debug, Release, RelWithDebInfo, MinSizeRel, None")
+ENDIF(NOT "${CMAKE_BUILD_TYPE_UPPER}"
+ MATCHES "^(DEBUG|RELEASE|RELWITHDEBINFO|MINSIZEREL|NONE)\$")
# On MacOS, prefer MacPorts libraries to system libraries.
# I haven't come up with a compelling argument for this to be conditional.
@@ -1495,6 +1497,7 @@ CHECK_FUNCTION_EXISTS_GLIBC(strncpy_s HAVE_STRNCPY_S)
CHECK_FUNCTION_EXISTS_GLIBC(strnlen HAVE_STRNLEN)
CHECK_FUNCTION_EXISTS_GLIBC(strrchr HAVE_STRRCHR)
CHECK_FUNCTION_EXISTS_GLIBC(symlink HAVE_SYMLINK)
+CHECK_FUNCTION_EXISTS_GLIBC(sysconf HAVE_SYSCONF)
CHECK_FUNCTION_EXISTS_GLIBC(timegm HAVE_TIMEGM)
CHECK_FUNCTION_EXISTS_GLIBC(tzset HAVE_TZSET)
CHECK_FUNCTION_EXISTS_GLIBC(unlinkat HAVE_UNLINKAT)
diff --git a/Makefile.am b/Makefile.am
index 286f08694c43..47b6fa1fc63e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -528,6 +528,7 @@ libarchive_test_SOURCES= \
libarchive/test/test_read_format_ustar_filename.c \
libarchive/test/test_read_format_warc.c \
libarchive/test/test_read_format_xar.c \
+ libarchive/test/test_read_format_xar_doublelink.c \
libarchive/test/test_read_format_zip.c \
libarchive/test/test_read_format_zip_7075_utf8_paths.c \
libarchive/test/test_read_format_zip_comment_stored.c \
@@ -932,6 +933,7 @@ libarchive_test_EXTRA_DIST=\
libarchive/test/test_read_format_ustar_filename_eucjp.tar.Z.uu \
libarchive/test/test_read_format_ustar_filename_koi8r.tar.Z.uu \
libarchive/test/test_read_format_warc.warc.uu \
+ libarchive/test/test_read_format_xar_doublelink.xar.uu \
libarchive/test/test_read_format_zip.zip.uu \
libarchive/test/test_read_format_zip_7075_utf8_paths.zip.uu \
libarchive/test/test_read_format_zip_7z_deflate.zip.uu \
diff --git a/NEWS b/NEWS
index f4395fd1c979..ebdbb2a978ec 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,5 @@
+Apr 26, 2024: libarchive 3.7.4 released
+
Apr 08, 2024: libarchive 3.7.3 released
Sep 12, 2023: libarchive 3.7.2 released
diff --git a/README.md b/README.md
index 727ed49856b6..933de6986425 100644
--- a/README.md
+++ b/README.md
@@ -201,7 +201,7 @@ questions we are asked about libarchive:
In case other thread calls the same function in parallel, it might
get interrupted by it and cause the executable to use umask=0 for the
remaining execution.
- This will then lead to implicitely created directories to have 777
+ This will then lead to implicitly created directories to have 777
permissions without sticky bit.
* In particular, libarchive's modules to read or write a directory
diff --git a/build/ci/github_actions/macos.sh b/build/ci/github_actions/macos.sh
index ba72b4a77178..6941bf8738c9 100755
--- a/build/ci/github_actions/macos.sh
+++ b/build/ci/github_actions/macos.sh
@@ -18,6 +18,7 @@ then
xz \
lz4 \
zstd \
+ libxml2 \
openssl
do
brew list $pkg > /dev/null && brew upgrade $pkg || brew install $pkg
diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in
index 045a6b41657e..d47694c0c1f1 100644
--- a/build/cmake/config.h.in
+++ b/build/cmake/config.h.in
@@ -1094,6 +1094,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the `symlink' function. */
#cmakedefine HAVE_SYMLINK 1
+/* Define to 1 if you have the `sysconf' function. */
+#cmakedefine HAVE_SYSCONF 1
+
/* Define to 1 if you have the <sys/acl.h> header file. */
#cmakedefine HAVE_SYS_ACL_H 1
diff --git a/build/version b/build/version
index fcdfc39dcee6..b06fe4726559 100644
--- a/build/version
+++ b/build/version
@@ -1 +1 @@
-3007003
+3007004
diff --git a/cat/cmdline.c b/cat/cmdline.c
index ea1e0eed6d0a..851b63de06e5 100644
--- a/cat/cmdline.c
+++ b/cat/cmdline.c
@@ -114,12 +114,18 @@ bsdcat_getopt(struct bsdcat *bsdcat)
enum { state_start = 0, state_old_tar, state_next_word,
state_short, state_long };
- const struct bsdcat_option *popt, *match = NULL, *match2 = NULL;
- const char *p, *long_prefix = "--";
+ const struct bsdcat_option *popt, *match, *match2;
+ const char *p, *long_prefix;
size_t optlength;
- int opt = '?';
- int required = 0;
+ int opt;
+ int required;
+again:
+ match = NULL;
+ match2 = NULL;
+ long_prefix = "--";
+ opt = '?';
+ required = 0;
bsdcat->argument = NULL;
/* First time through, initialize everything. */
@@ -172,7 +178,7 @@ bsdcat_getopt(struct bsdcat *bsdcat)
if (opt == '\0') {
/* End of this group; recurse to get next option. */
bsdcat->getopt_state = state_next_word;
- return bsdcat_getopt(bsdcat);
+ goto again;
}
/* Does this option take an argument? */
diff --git a/configure.ac b/configure.ac
index 503bb75ac9f8..5668d41cab6f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,8 +4,8 @@ dnl First, define all of the version numbers up front.
dnl In particular, this allows the version macro to be used in AC_INIT
dnl These first two version numbers are updated automatically on each release.
-m4_define([LIBARCHIVE_VERSION_S],[3.7.3])
-m4_define([LIBARCHIVE_VERSION_N],[3007003])
+m4_define([LIBARCHIVE_VERSION_S],[3.7.4])
+m4_define([LIBARCHIVE_VERSION_N],[3007004])
dnl bsdtar and bsdcpio versioning tracks libarchive
m4_define([BSDTAR_VERSION_S],LIBARCHIVE_VERSION_S())
@@ -662,7 +662,7 @@ AC_LINK_IFELSE(
DEAD_CODE_REMOVAL="";])
LDFLAGS=$save_LDFLAGS
-if test "$DEAD_CODE_REMOVAL" == ""; then
+if test "$DEAD_CODE_REMOVAL" = ""; then
# Macos linkers have a -dead_strip flag, which is similar to --gc-sections.
save_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS -Wl,-dead_strip"
@@ -804,6 +804,7 @@ AC_CHECK_FUNCS([nl_langinfo openat pipe poll posix_spawnp readlink readlinkat])
AC_CHECK_FUNCS([readpassphrase])
AC_CHECK_FUNCS([select setenv setlocale sigaction statfs statvfs])
AC_CHECK_FUNCS([strchr strdup strerror strncpy_s strnlen strrchr symlink])
+AC_CHECK_FUNCS([sysconf])
AC_CHECK_FUNCS([timegm tzset unlinkat unsetenv utime utimensat utimes vfork])
AC_CHECK_FUNCS([wcrtomb wcscmp wcscpy wcslen wctomb wmemcmp wmemcpy wmemmove])
AC_CHECK_FUNCS([_fseeki64 _get_timezone])
diff --git a/cpio/cmdline.c b/cpio/cmdline.c
index 312d762c8f46..ab25492ede48 100644
--- a/cpio/cmdline.c
+++ b/cpio/cmdline.c
@@ -114,12 +114,18 @@ cpio_getopt(struct cpio *cpio)
static int state = state_start;
static char *opt_word;
- const struct option *popt, *match = NULL, *match2 = NULL;
- const char *p, *long_prefix = "--";
+ const struct option *popt, *match, *match2;
+ const char *p, *long_prefix;
size_t optlength;
- int opt = '?';
- int required = 0;
+ int opt;
+ int required;
+again:
+ match = NULL;
+ match2 = NULL;
+ long_prefix = "--";
+ opt = '?';
+ required = 0;
cpio->argument = NULL;
/* First time through, initialize everything. */
@@ -169,7 +175,7 @@ cpio_getopt(struct cpio *cpio)
if (opt == '\0') {
/* End of this group; recurse to get next option. */
state = state_next_word;
- return cpio_getopt(cpio);
+ goto again;
}
/* Does this option take an argument? */
diff --git a/libarchive/archive.h b/libarchive/archive.h
index 2e3a9f31cd33..fd4dd20fad13 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 3007003
+#define ARCHIVE_VERSION_NUMBER 3007004
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
@@ -155,7 +155,7 @@ __LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_VERSION_ONLY_STRING "3.7.3"
+#define ARCHIVE_VERSION_ONLY_STRING "3.7.4"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
@@ -895,7 +895,7 @@ __LA_DECL int archive_write_set_options(struct archive *_a,
const char *opts);
/*
- * Set a encryption passphrase.
+ * Set an encryption passphrase.
*/
__LA_DECL int archive_write_set_passphrase(struct archive *_a, const char *p);
__LA_DECL int archive_write_set_passphrase_callback(struct archive *,
diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h
index df9cb765f7e8..1c59ded7c911 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 3007003
+#define ARCHIVE_VERSION_NUMBER 3007004
/*
* Note: archive_entry.h is for use outside of libarchive; the
diff --git a/libarchive/archive_entry_acl.3 b/libarchive/archive_entry_acl.3
index 50dd642c20c6..4d0d8b50ed07 100644
--- a/libarchive/archive_entry_acl.3
+++ b/libarchive/archive_entry_acl.3
@@ -383,7 +383,7 @@ Prefix each default ACL entry with the word
The mask and other ACLs don not contain a double colon.
.El
.Pp
-The following flags are effecive only on NFSv4 ACL:
+The following flags are effective only on NFSv4 ACL:
.Bl -tag -offset indent -compact -width ARCHIV
.It Dv ARCHIVE_ENTRY_ACL_STYLE_COMPACT
Do not output minus characters for unset permissions and flags in NFSv4 ACL
diff --git a/libarchive/archive_read_disk.3 b/libarchive/archive_read_disk.3
index 7cde3c232713..990c1514c4d5 100644
--- a/libarchive/archive_read_disk.3
+++ b/libarchive/archive_read_disk.3
@@ -288,11 +288,11 @@ calls. If matched based on calls to
.Tn archive_match_time_excluded ,
or
.Tn archive_match_owner_excluded ,
-then the callback function specified by the _excluded_func parameter will execute. This function will recieve data provided to the fourth parameter, void *_client_data.
+then the callback function specified by the _excluded_func parameter will execute. This function will receive data provided to the fourth parameter, void *_client_data.
.It Fn archive_read_disk_set_metadata_filter_callback
Allows the caller to set a callback function during calls to
.Xr archive_read_header 3
-to filter out metadata for each entry. The callback function recieves the
+to filter out metadata for each entry. The callback function receives the
.Tn struct archive
object, void* custom filter data, and the
.Tn struct archive_entry .
diff --git a/libarchive/archive_read_support_format_7zip.c b/libarchive/archive_read_support_format_7zip.c
index 92495e628f9a..7e465935c902 100644
--- a/libarchive/archive_read_support_format_7zip.c
+++ b/libarchive/archive_read_support_format_7zip.c
@@ -2037,6 +2037,8 @@ read_Folder(struct archive_read *a, struct _7z_folder *f)
if (parse_7zip_uint64(
a, &(f->coders[i].propertiesSize)) < 0)
return (-1);
+ if (UMAX_ENTRY < f->coders[i].propertiesSize)
+ return (-1);
if ((p = header_bytes(
a, (size_t)f->coders[i].propertiesSize)) == NULL)
return (-1);
diff --git a/libarchive/archive_read_support_format_all.c b/libarchive/archive_read_support_format_all.c
index 5a4e1ab675a5..3b53c9ad5f57 100644
--- a/libarchive/archive_read_support_format_all.c
+++ b/libarchive/archive_read_support_format_all.c
@@ -67,7 +67,7 @@ archive_read_support_format_all(struct archive *a)
* increase the chance that a high bid from someone else will
* make it unnecessary for these to do anything at all.
*/
- /* These three have potentially large look-ahead. */
+ /* These have potentially large look-ahead. */
archive_read_support_format_7zip(a);
archive_read_support_format_cab(a);
archive_read_support_format_rar(a);
diff --git a/libarchive/archive_read_support_format_ar.c b/libarchive/archive_read_support_format_ar.c
index ca8effb0b0ee..6f1be8591fef 100644
--- a/libarchive/archive_read_support_format_ar.c
+++ b/libarchive/archive_read_support_format_ar.c
@@ -270,7 +270,7 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
}
if (ar->strtab != NULL) {
archive_set_error(&a->archive, EINVAL,
- "More than one string tables exist");
+ "More than one string table exists");
return (ARCHIVE_FATAL);
}
@@ -515,7 +515,7 @@ archive_read_format_ar_read_data(struct archive_read *a,
if (ar->entry_padding) {
if (skipped >= 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Truncated ar archive- failed consuming padding");
+ "Truncated ar archive - failed consuming padding");
}
return (ARCHIVE_FATAL);
}
diff --git a/libarchive/archive_read_support_format_lha.c b/libarchive/archive_read_support_format_lha.c
index 1c64b2900b8e..4d6290ac33bb 100644
--- a/libarchive/archive_read_support_format_lha.c
+++ b/libarchive/archive_read_support_format_lha.c
@@ -1693,7 +1693,7 @@ archive_read_format_lha_cleanup(struct archive_read *a)
* example.
* 1. a symbolic-name is 'aaa/bb/cc'
* 2. a filename is 'xxx/bbb'
- * then a archived pathname is 'xxx/bbb|aaa/bb/cc'
+ * then an archived pathname is 'xxx/bbb|aaa/bb/cc'
*/
static int
lha_parse_linkname(struct archive_wstring *linkname,
@@ -2385,7 +2385,7 @@ lzh_decode_blocks(struct lzh_stream *strm, int last)
return (100);
}
- /* lzh_br_read_ahead() always try to fill the
+ /* lzh_br_read_ahead() always tries to fill the
* cache buffer up. In specific situation we
* are close to the end of the data, the cache
* buffer will not be full and thus we have to
diff --git a/libarchive/archive_read_support_format_mtree.c b/libarchive/archive_read_support_format_mtree.c
index 630cff6e3999..6971228eefad 100644
--- a/libarchive/archive_read_support_format_mtree.c
+++ b/libarchive/archive_read_support_format_mtree.c
@@ -416,8 +416,8 @@ next_line(struct archive_read *a,
}
/*
- * Compare characters with a mtree keyword.
- * Returns the length of a mtree keyword if matched.
+ * Compare characters with an mtree keyword.
+ * Returns the length of an mtree keyword if matched.
* Returns 0 if not matched.
*/
static int
@@ -515,7 +515,7 @@ bid_keyword(const char *p, ssize_t len)
/*
* Test whether there is a set of mtree keywords.
- * Returns the number of keyword.
+ * Returns the number of keywords.
* Returns -1 if we got incorrect sequence.
* This function expects a set of "<space characters>keyword=value".
* When "unset" is specified, expects a set of "<space characters>keyword".
@@ -760,7 +760,7 @@ detect_form(struct archive_read *a, int *is_form_d)
multiline = 1;
else {
/* We've got plenty of correct lines
- * to assume that this file is a mtree
+ * to assume that this file is an mtree
* format. */
if (++entry_cnt >= MAX_BID_ENTRY)
break;
diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c
index 99a11d170074..79669a8f40f9 100644
--- a/libarchive/archive_read_support_format_rar.c
+++ b/libarchive/archive_read_support_format_rar.c
@@ -2176,6 +2176,19 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
{
start = rar->offset;
end = start + rar->dictionary_size;
+
+ /* We don't want to overflow the window and overwrite data that we write
+ * at 'start'. Therefore, reduce the end length by the maximum match size,
+ * which is 260 bytes. You can compute this maximum by looking at the
+ * definition of 'expand', in particular when 'symbol >= 271'. */
+ /* NOTE: It's possible for 'dictionary_size' to be less than this 260
+ * value, however that will only be the case when 'unp_size' is small,
+ * which should only happen when the entry size is small and there's no
+ * risk of overflowing the buffer */
+ if (rar->dictionary_size > 260) {
+ end -= 260;
+ }
+
if (rar->filters.filterstart < end) {
end = rar->filters.filterstart;
}
@@ -3615,7 +3628,7 @@ execute_filter_e8(struct rar_filter *filter, struct rar_virtual_machine *vm, siz
uint32_t filesize = 0x1000000;
uint32_t i;
- if (length > PROGRAM_WORK_SIZE || length < 4)
+ if (length > PROGRAM_WORK_SIZE || length <= 4)
return 0;
for (i = 0; i <= length - 5; i++)
diff --git a/libarchive/archive_read_support_format_warc.c b/libarchive/archive_read_support_format_warc.c
index c49d44eba5e5..fcec5bc4cbb9 100644
--- a/libarchive/archive_read_support_format_warc.c
+++ b/libarchive/archive_read_support_format_warc.c
@@ -215,6 +215,7 @@ _warc_rdhdr(struct archive_read *a, struct archive_entry *entry)
const char *buf;
ssize_t nrd;
const char *eoh;
+ char *tmp;
/* for the file name, saves some strndup()'ing */
warc_string_t fnam;
/* warc record type, not that we really use it a lot */
@@ -321,7 +322,14 @@ start_over:
* malloc()+free() roundtrip */
if (fnam.len + 1U > w->pool.len) {
w->pool.len = ((fnam.len + 64U) / 64U) * 64U;
- w->pool.str = realloc(w->pool.str, w->pool.len);
+ tmp = realloc(w->pool.str, w->pool.len);
+ if (tmp == NULL) {
+ archive_set_error(
+ &a->archive, ENOMEM,
+ "Out of memory");
+ return (ARCHIVE_FATAL);
+ }
+ w->pool.str = tmp;
}
memcpy(w->pool.str, fnam.str, fnam.len);
w->pool.str[fnam.len] = '\0';
diff --git a/libarchive/archive_read_support_format_xar.c b/libarchive/archive_read_support_format_xar.c
index fd63594373cb..2c3432642937 100644
--- a/libarchive/archive_read_support_format_xar.c
+++ b/libarchive/archive_read_support_format_xar.c
@@ -2055,6 +2055,11 @@ xml_start(struct archive_read *a, const char *name, struct xmlattr_list *list)
attr = attr->next) {
if (strcmp(attr->name, "link") != 0)
continue;
+ if (xar->file->hdnext != NULL || xar->file->link != 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "File with multiple link targets");
+ return (ARCHIVE_FATAL);
+ }
if (strcmp(attr->value, "original") == 0) {
xar->file->hdnext = xar->hdlink_orgs;
xar->hdlink_orgs = xar->file;
diff --git a/libarchive/archive_read_support_format_zip.c b/libarchive/archive_read_support_format_zip.c
index 212bfff9fa7b..c9759eaf9a89 100644
--- a/libarchive/archive_read_support_format_zip.c
+++ b/libarchive/archive_read_support_format_zip.c
@@ -1393,7 +1393,7 @@ check_authentication_code(struct archive_read *a, const void *_p)
* [CRC32] [compressed low] [compressed high] [uncompressed low] [uncompressed high] [other PK marker]
* ```
* Since the 32-bit and 64-bit compressed sizes both match, the
- * actualy size must fit in 32 bits, which implies the high-order
+ * actual size must fit in 32 bits, which implies the high-order
* word of the compressed size is zero. So we know the uncompressed
* low word is zero, which again implies that if we accept the shorter
* format, there will not be a valid PK marker following it.
@@ -4083,6 +4083,17 @@ slurp_central_directory(struct archive_read *a, struct archive_entry* entry,
} else {
/* Generate resource fork name to find its
* resource file at zip->tree_rsrc. */
+
+ /* If this is an entry ending with slash,
+ * make the resource for name slash-less
+ * as the actual resource fork doesn't end with '/'.
+ */
+ size_t tmp_length = filename_length;
+ if (tmp_length > 0 && name[tmp_length - 1] == '/') {
+ tmp_length--;
+ r = rsrc_basename(name, tmp_length);
+ }
+
archive_strcpy(&(zip_entry->rsrcname),
"__MACOSX/");
archive_strncat(&(zip_entry->rsrcname),
@@ -4090,7 +4101,7 @@ slurp_central_directory(struct archive_read *a, struct archive_entry* entry,
archive_strcat(&(zip_entry->rsrcname), "._");
archive_strncat(&(zip_entry->rsrcname),
name + (r - name),
- filename_length - (r - name));
+ tmp_length - (r - name));
/* Register an entry to RB tree to sort it by
* file offset. */
__archive_rb_tree_insert_node(&zip->tree,
diff --git a/libarchive/archive_util.c b/libarchive/archive_util.c
index 32d4bd40988c..7b918fef04b8 100644
--- a/libarchive/archive_util.c
+++ b/libarchive/archive_util.c
@@ -255,10 +255,9 @@ __archive_mktempx(const char *tmpdir, wchar_t *template)
#endif
fd = -1;
ws = NULL;
+ archive_string_init(&temp_name);
if (template == NULL) {
- archive_string_init(&temp_name);
-
/* Get a temporary directory. */
if (tmpdir == NULL) {
size_t l;
diff --git a/libarchive/archive_write_add_filter_zstd.c b/libarchive/archive_write_add_filter_zstd.c
index 94249accd08b..7ea3d18c9b76 100644
--- a/libarchive/archive_write_add_filter_zstd.c
+++ b/libarchive/archive_write_add_filter_zstd.c
@@ -29,6 +29,9 @@
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
@@ -38,6 +41,9 @@
#ifdef HAVE_STRING_H
#include <string.h>
#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#ifdef HAVE_ZSTD_H
#include <zstd.h>
#endif
@@ -190,6 +196,7 @@ string_to_number(const char *string, intmax_t *numberp)
return (ARCHIVE_OK);
}
+#if HAVE_ZSTD_H && HAVE_ZSTD_compressStream
static int
string_to_size(const char *string, size_t *numberp)
{
@@ -224,6 +231,7 @@ string_to_size(const char *string, size_t *numberp)
*numberp = (size_t)(number << shift);
return (ARCHIVE_OK);
}
+#endif
/*
* Set write options.
@@ -264,7 +272,20 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key,
if (string_to_number(value, &threads) != ARCHIVE_OK) {
return (ARCHIVE_WARN);
}
- if (threads < 0) {
+
+#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
+ if (threads == 0) {
+ threads = sysconf(_SC_NPROCESSORS_ONLN);
+ }
+#elif !defined(__CYGWIN__) && defined(_WIN32_WINNT) && \
+ _WIN32_WINNT >= 0x0601 /* _WIN32_WINNT_WIN7 */
+ if (threads == 0) {
+ DWORD winCores = GetActiveProcessorCount(
+ ALL_PROCESSOR_GROUPS);
+ threads = (intmax_t)winCores;
+ }
+#endif
+ if (threads < 0 || threads > INT_MAX) {
return (ARCHIVE_WARN);
}
data->threads = (int)threads;
diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c
index 58265ee0dc11..92db4ff05b63 100644
--- a/libarchive/archive_write_disk_posix.c
+++ b/libarchive/archive_write_disk_posix.c
@@ -4427,7 +4427,8 @@ fixup_appledouble(struct archive_write_disk *a, const char *pathname)
#else
la_stat(datafork.s, &st) == -1 ||
#endif
- (st.st_mode & AE_IFMT) != AE_IFREG)
+ (((st.st_mode & AE_IFMT) != AE_IFREG) &&
+ ((st.st_mode & AE_IFMT) != AE_IFDIR)))
goto skip_appledouble;
/*
diff --git a/libarchive/archive_write_private.h b/libarchive/archive_write_private.h
index abd5a8ddcd85..f259ccb16546 100644
--- a/libarchive/archive_write_private.h
+++ b/libarchive/archive_write_private.h
@@ -158,7 +158,7 @@ int __archive_write_program_write(struct archive_write_filter *,
struct archive_write_program_data *, const void *, size_t);
/*
- * Get a encryption passphrase.
+ * Get an encryption passphrase.
*/
const char * __archive_write_get_passphrase(struct archive_write *a);
#endif
diff --git a/libarchive/archive_write_set_format_gnutar.c b/libarchive/archive_write_set_format_gnutar.c
index 92b06c5f5fb4..a88350b87411 100644
--- a/libarchive/archive_write_set_format_gnutar.c
+++ b/libarchive/archive_write_set_format_gnutar.c
@@ -387,7 +387,7 @@ archive_write_gnutar_header(struct archive_write *a,
if (r != 0) {
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
- "Can't allocate memory for Pathame");
+ "Can't allocate memory for pathname");
ret = ARCHIVE_FATAL;
goto exit_write_header;
}
diff --git a/libarchive/archive_write_set_passphrase.c b/libarchive/archive_write_set_passphrase.c
index 977fc4a9ee6b..f871c8e2f810 100644
--- a/libarchive/archive_write_set_passphrase.c
+++ b/libarchive/archive_write_set_passphrase.c
@@ -30,14 +30,9 @@
#endif
#include "archive_write_private.h"
-int
-archive_write_set_passphrase(struct archive *_a, const char *p)
+static int
+set_passphrase(struct archive_write *a, const char *p)
{
- struct archive_write *a = (struct archive_write *)_a;
-
- archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW,
- "archive_write_set_passphrase");
-
if (p == NULL || p[0] == '\0') {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Empty passphrase is unacceptable");
@@ -55,6 +50,18 @@ archive_write_set_passphrase(struct archive *_a, const char *p)
int
+archive_write_set_passphrase(struct archive *_a, const char *p)
+{
+ struct archive_write *a = (struct archive_write *)_a;
+
+ archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW,
+ "archive_write_set_passphrase");
+
+ return (set_passphrase(a, p));
+}
+
+
+int
archive_write_set_passphrase_callback(struct archive *_a, void *client_data,
archive_passphrase_callback *cb)
{
@@ -80,15 +87,9 @@ __archive_write_get_passphrase(struct archive_write *a)
const char *p;
p = a->passphrase_callback(&a->archive,
a->passphrase_client_data);
- if (p != NULL) {
- a->passphrase = strdup(p);
- if (a->passphrase == NULL) {
- archive_set_error(&a->archive, ENOMEM,
- "Can't allocate data for passphrase");
- return (NULL);
- }
- return (a->passphrase);
- }
+ set_passphrase(a, p);
+ a->passphrase_callback = NULL;
+ a->passphrase_client_data = NULL;
}
- return (NULL);
+ return (a->passphrase);
}
diff --git a/libarchive/libarchive_internals.3 b/libarchive/libarchive_internals.3
index d4696f648292..2978b48c3e97 100644
--- a/libarchive/libarchive_internals.3
+++ b/libarchive/libarchive_internals.3
@@ -124,7 +124,7 @@ to read the entire file into memory at once and return the
entire file to libarchive as a single block;
other clients may begin asynchronous I/O operations for the
next block on each request.
-.Ss Decompresssion Layer
+.Ss Decompression Layer
The decompression layer not only handles decompression,
it also buffers data so that the format handlers see a
much nicer I/O model.
diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt
index 8209c25a5f8d..7b166c5fba0f 100644
--- a/libarchive/test/CMakeLists.txt
+++ b/libarchive/test/CMakeLists.txt
@@ -172,6 +172,7 @@ IF(ENABLE_TEST)
test_read_format_ustar_filename.c
test_read_format_warc.c
test_read_format_xar.c
+ test_read_format_xar_doublelink.c
test_read_format_zip.c
test_read_format_zip_7075_utf8_paths.c
test_read_format_zip_comment_stored.c
diff --git a/libarchive/test/test_compat_lzip.c b/libarchive/test/test_compat_lzip.c
index d3b8b118322b..1420e5bb9ac0 100644
--- a/libarchive/test/test_compat_lzip.c
+++ b/libarchive/test/test_compat_lzip.c
@@ -195,7 +195,6 @@ compat_lzip_4(const char *name)
assertEqualString("test.bin", archive_entry_pathname(ae));
/* Verify the end-of-archive. */
- archive_set_error(a, ARCHIVE_OK, NULL);
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
/* Verify that the format detection worked. */
diff --git a/libarchive/test/test_read_format_xar_doublelink.c b/libarchive/test/test_read_format_xar_doublelink.c
new file mode 100644
index 000000000000..73ddebd285b9
--- /dev/null
+++ b/libarchive/test/test_read_format_xar_doublelink.c
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 2024 Martin Matuska
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+#define __LIBARCHIVE_BUILD
+
+DEFINE_TEST(test_read_format_xar_doublelink)
+{
+ const char *refname = "test_read_format_xar_doublelink.xar";
+ struct archive *a;
+ struct archive_entry *ae;
+
+ extract_reference_file(refname);
+
+ /* Verify with seeking reader. */
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
+ if(ARCHIVE_OK != archive_read_support_format_xar(a)) {
+ skipping("XAR format unsupported");
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+ return;
+ }
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname,
+ 10240));
+
+ assertA(ARCHIVE_FATAL == archive_read_next_header(a, &ae));
+ assertEqualString(archive_error_string(a),
+ "File with multiple link targets");
+ assert(archive_errno(a) != 0);
+
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
diff --git a/libarchive/test/test_read_format_xar_doublelink.xar.uu b/libarchive/test/test_read_format_xar_doublelink.xar.uu
new file mode 100644
index 000000000000..7aa638a86e7c
--- /dev/null
+++ b/libarchive/test/test_read_format_xar_doublelink.xar.uu
@@ -0,0 +1,12 @@
+begin 664 test_read_format_xar_doublelink.xar
+M>&%R(0`<``$````````!0`````````/7`````7B<[9/!<L(@%$7W?@7#/H60
+MU'0R!'?]`KOICDF>D3&``]'1?GT!-1U;;:=[5[G<=WB0=P>^..@![<%Y94V#
+M\R>*$9C6=LKT#7Y;OF8O>"%F_""=F"$^VC9\$&\=R#'LR$:E03#*RHR6&2N6
+MM*KIO,YS3JZ1M&D-[<;O-/+C<8`&^[7,<:P@;E<K#Z.@G)Q5<KWZB,TY22*V
+M()<>:;52`R#5A6N?VQ@9CHIN.#_IY(['+:!!F4V#K5.],G+`8BU=%SU.8OF?
+MH#*V`U%5K"@9)Z=5*G2P5RT8*YY+3J9%*ND(T?D\%/3$[U0G<DK#+T9ULCPX
+MH75PHDA6/U']A>J=W6T3=E+);&^E4=0%?0^#N\00;G(;8U7`]!<F?\'D%"J)
+MX[Y.@WU/@]U)(_\SACO$8_X_YA_&$]\F)^FE?@)<4AJ<B%QTTZN3JTL:$,<5
+<`XH;(KD-Q0=XG.V3P7+"(!1%]WX%PSZ%D-1T,@``
+`
+end
diff --git a/libarchive/test/test_write_disk_appledouble.c b/libarchive/test/test_write_disk_appledouble.c
index 3265a94d2fed..8de6c8b50413 100644
--- a/libarchive/test/test_write_disk_appledouble.c
+++ b/libarchive/test/test_write_disk_appledouble.c
@@ -236,3 +236,87 @@ DEFINE_TEST(test_write_disk_appledouble)
assertEqualFile("hfscmp/file3", "nocmp/file3");
#endif
}
+
+/* Test writing apple doubles to disk from zip format */
+DEFINE_TEST(test_write_disk_appledouble_zip)
+{
+#if !defined(__APPLE__) || !defined(UF_COMPRESSED) || !defined(HAVE_SYS_XATTR_H)\
+ || !defined(HAVE_ZLIB_H)
+ skipping("MacOS-specific AppleDouble test");
+#else
+ const char *refname = "test_write_disk_appledouble_zip.zip";
+ struct archive *ad, *a;
+ struct archive_entry *ae;
+ struct stat st;
+
+ extract_reference_file(refname);
+
+ /*
+ * Extract an archive to disk.
+ */
+ assert((ad = archive_write_disk_new()) != NULL);
+ assertEqualIntA(ad, ARCHIVE_OK,
+ archive_write_disk_set_standard_lookup(ad));
+ assertEqualIntA(ad, ARCHIVE_OK,
+ archive_write_disk_set_options(ad,
+ ARCHIVE_EXTRACT_TIME |
+ ARCHIVE_EXTRACT_SECURE_SYMLINKS |
+ ARCHIVE_EXTRACT_SECURE_NODOTDOT));
+
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a,
+ refname, 512 * 20));
+
+ /* Skip The top level directory */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualString("apple_double_dir/", archive_entry_pathname(ae));
+
+ /* Extract apple_double_test */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualString("apple_double_dir/apple_double_dir_test/", archive_entry_pathname(ae));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad));
+
+ /* Extract ._apple_double_dir_test which will be merged into apple_double_dir_test as metadata. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualString("apple_double_dir/._apple_double_dir_test", archive_entry_pathname(ae));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad));
+
+ /* Extract test_file */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualString("apple_double_dir/test_file", archive_entry_pathname(ae));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad));
+
+ /* Extract ._test_file which will be merged into test_file as metadata. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualString("apple_double_dir/._test_file", archive_entry_pathname(ae));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_extract2(a, ae, ad));
+
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+ assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad));
+
+ /* Test test_file */
+ assertEqualInt(0, stat("apple_double_dir/test_file", &st));
+ assertFileSize("apple_double_dir/test_file", 5);
+ failure("'%s' should have Resource Fork", "test_file");
+ assertEqualInt(1, has_xattr("apple_double_dir/test_file", "com.apple.ResourceFork"));
+
+ /* Test apple_double_dir_test */
+ failure("'%s' should have quarantine xattr", "apple_double_dir_test");
+ assertEqualInt(1, has_xattr("apple_double_dir/apple_double_dir_test", "com.apple.quarantine"));
+
+ /* Test ._test_file. */
+ failure("'apple_double_dir/._test_file' should be merged and removed");
+ assertFileNotExists("apple_double_dir/._test_file");
+
+ /* Test ._apple_double_dir_test */
+ failure("'apple_double_dir/._._apple_double_dir_test' should be merged and removed");
+ assertFileNotExists("apple_double_dir/._apple_double_dir_test");
+
+ assertChdir("..");
+
+#endif
+}
diff --git a/libarchive/test/test_write_disk_appledouble_zip.zip.uu b/libarchive/test/test_write_disk_appledouble_zip.zip.uu
new file mode 100644
index 000000000000..5ab67533d559
--- /dev/null
+++ b/libarchive/test/test_write_disk_appledouble_zip.zip.uu
@@ -0,0 +1,27 @@
+begin 644 test_write_disk_appledouble_zip.zip
+M4$L#!`H```````MM?%@````````````````1`!``87!P;&5?9&]U8FQE7V1I
+M<B]56`P`O=4%9K75!6;U`10`4$L#!`H```````MM?%@````````````````G
+M`!``87!P;&5?9&]U8FQE7V1I<B]A<'!L95]D;W5B;&5?9&ER7W1E<W0O55@,
+M`+W5!6:UU05F]0$4`%!+`P04``@`"``+;7Q8````````````````*``0`&%P
+M<&QE7V1O=6)L95]D:7(O+E]A<'!L95]D;W5B;&5?9&ER7W1E<W156`P`O=4%
+M9K75!6;U`10`8V`58V=@8F#P34Q6\`]6B%"``I`8`R<0&P%Q!1"#^*L8B`*.
+M(2%!4"9(QPP@%D)3PH@0%TW.S]5++"C(2=4K+$TL2LPKR<Q+92C4-S"P,+8V
+M@`)K:P8`4$L'"!2N=6M7````J@```%!+`P04``@`"`!93GQ8````````````
+M````&@`0`&%P<&QE7V1O=6)L95]D:7(O=&5S=%]F:6QE55@,`+'5!6;IGP5F
+M]0$4`"M)+2[A`@!02P<(QC6Y.P<````%````4$L#!!0`"``(`%E.?%@`````
+M```````````<`!``87!P;&5?9&]U8FQE7V1I<B\N7W1E<W1?9FEL9558#`"Q
+MU05FZ9\%9O4!%`!C8!5C9V!B8/!-3%;P#U:(4(`"D!@#)Q`;`;$;$(/X%4#,
+MQT`0.(:$!$&9%5",`8I2B_-+BY)3%=+RB[*Y`%!+!P@HPLP3/@```(8```!0
+M2P$"%0,*```````+;7Q8````````````````$0`,``````````!`[4$`````
+M87!P;&5?9&]U8FQE7V1I<B]56`@`O=4%9K75!6902P$"%0,*```````+;7Q8
+M````````````````)P`,``````````!`[4$_````87!P;&5?9&]U8FQE7V1I
+M<B]A<'!L95]D;W5B;&5?9&ER7W1E<W0O55@(`+W5!6:UU05F4$L!`A4#%``(
+M``@`"VU\6!2N=6M7````J@```"@`#```````````0*2!E````&%P<&QE7V1O
+M=6)L95]D:7(O+E]A<'!L95]D;W5B;&5?9&ER7W1E<W156`@`O=4%9K75!690
+M2P$"%0,4``@`"`!93GQ8QC6Y.P<````%````&@`,``````````!`I(%1`0``
+M87!P;&5?9&]U8FQE7V1I<B]T97-T7V9I;&556`@`L=4%9NF?!6902P$"%0,4
+M``@`"`!93GQ8*,+,$SX```"&````'``,``````````!`I(&P`0``87!P;&5?
+M9&]U8FQE7V1I<B\N7W1E<W1?9FEL9558"`"QU05FZ9\%9E!+!08`````!0`%
++`+@!``!(`@``````
+`
+end
diff --git a/libarchive_fe/passphrase.c b/libarchive_fe/passphrase.c
index 9d95d527067b..90fef32d254c 100644
--- a/libarchive_fe/passphrase.c
+++ b/libarchive_fe/passphrase.c
@@ -76,6 +76,7 @@
#if defined(_WIN32) && !defined(__CYGWIN__)
+#include <string.h>
#include <windows.h>
static char *
@@ -113,8 +114,7 @@ readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
WriteFile(hStdout, "\r\n", 2, NULL, NULL);
buf[rbytes] = '\0';
/* Remove trailing carriage return(s). */
- if (rbytes > 2 && buf[rbytes - 2] == '\r' && buf[rbytes - 1] == '\n')
- buf[rbytes - 2] = '\0';
+ buf[strcspn(buf, "\r\n")] = '\0';
return (buf);
}
diff --git a/tar/bsdtar.1 b/tar/bsdtar.1
index e570d2a48a01..fe9ec9504674 100644
--- a/tar/bsdtar.1
+++ b/tar/bsdtar.1
@@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd March 1, 2024
+.Dd April 23, 2024
.Dt TAR 1
.Os
.Sh NAME
@@ -644,14 +644,13 @@ A decimal integer from 4 to 7 specifying the lz4 compression block size
.It Cm lz4:block-dependence
Use the previous block of the block being compressed for
a compression dictionary to improve compression ratio.
-.It Cm zstd:compression-level
-A decimal integer specifying the zstd compression level. Supported values depend
+.It Cm zstd:compression-level Ns = Ns Ar N
+A decimal integer specifying the zstd compression level.
+Supported values depend
on the library version, common values are from 1 to 22.
-.It Cm zstd:threads
-Specify the number of worker threads to use.
-Setting threads to a special value 0 makes
-.Xr zstd 1
-use as many threads as there are CPU cores on the system.
+.It Cm zstd:threads Ns = Ns Ar N
+Specify the number of worker threads to use, or 0 to use as many
+threads as there are CPU cores in the system.
.It Cm zstd:frame-per-file
Start a new compression frame at the beginning of each file in the
archive.
diff --git a/tar/bsdtar.c b/tar/bsdtar.c
index b070e0faeb66..42baab2861bd 100644
--- a/tar/bsdtar.c
+++ b/tar/bsdtar.c
@@ -157,6 +157,7 @@ main(int argc, char **argv)
char *tptr, *uptr;
char possible_help_request;
char buff[16];
+ long l;
/*
* Use a pointer for consistency, but stack-allocated storage
@@ -301,16 +302,15 @@ main(int argc, char **argv)
/* libarchive doesn't need this; just ignore it. */
break;
case 'b': /* SUSv2 */
- errno = 0;
tptr = NULL;
- t = (int)strtol(bsdtar->argument, &tptr, 10);
- if (errno || t <= 0 || t > 8192 ||
+ l = strtol(bsdtar->argument, &tptr, 10);
+ if (l <= 0 || l > 8192L ||
*(bsdtar->argument) == '\0' || tptr == NULL ||
*tptr != '\0') {
lafe_errc(1, 0, "Invalid or out of range "
"(1..8192) argument to -b");
}
- bsdtar->bytes_per_block = 512 * t;
+ bsdtar->bytes_per_block = 512 * (int)l;
/* Explicit -b forces last block size. */
bsdtar->bytes_in_last_block = bsdtar->bytes_per_block;
break;
@@ -369,44 +369,42 @@ main(int argc, char **argv)
bsdtar->filename = bsdtar->argument;
break;
case OPTION_GID: /* cpio */
- errno = 0;
tptr = NULL;
- t = (int)strtol(bsdtar->argument, &tptr, 10);
- if (errno || t < 0 || *(bsdtar->argument) == '\0' ||
+ l = strtol(bsdtar->argument, &tptr, 10);
+ if (l < 0 || l >= INT_MAX || *(bsdtar->argument) == '\0' ||
tptr == NULL || *tptr != '\0') {
lafe_errc(1, 0, "Invalid argument to --gid");
}
- bsdtar->gid = t;
+ bsdtar->gid = (int)l;
break;
case OPTION_GNAME: /* cpio */
bsdtar->gname = bsdtar->argument;
break;
case OPTION_GROUP: /* GNU tar */
- errno = 0;
tptr = NULL;
uptr = strchr(bsdtar->argument, ':');
- if(uptr != NULL) {
- if(uptr[1] == 0) {
+ if (uptr != NULL) {
+ if (uptr[1] == '\0') {
lafe_errc(1, 0, "Invalid argument to --group (missing id after :)");
}
uptr[0] = 0;
uptr++;
- t = (int)strtol(uptr, &tptr, 10);
- if (errno || t < 0 || *uptr == '\0' ||
+ l = strtol(uptr, &tptr, 10);
+ if (l < 0 || l >= INT_MAX || *uptr == '\0' ||
tptr == NULL || *tptr != '\0') {
lafe_errc(1, 0, "Invalid argument to --group (%s is not a number)", uptr);
} else {
- bsdtar->gid = t;
+ bsdtar->gid = (int)l;
}
bsdtar->gname = bsdtar->argument;
} else {
- t = (int)strtol(bsdtar->argument, &tptr, 10);
- if (errno || t < 0 || *(bsdtar->argument) == '\0' ||
+ l = strtol(bsdtar->argument, &tptr, 10);
+ if (l < 0 || l >= INT_MAX || *(bsdtar->argument) == '\0' ||
tptr == NULL || *tptr != '\0') {
bsdtar->gname = bsdtar->argument;
} else {
- bsdtar->gid = t;
+ bsdtar->gid = (int)l;
bsdtar->gname = "";
}
}
@@ -662,31 +660,30 @@ main(int argc, char **argv)
bsdtar->option_options = bsdtar->argument;
break;
case OPTION_OWNER: /* GNU tar */
- errno = 0;
tptr = NULL;
uptr = strchr(bsdtar->argument, ':');
- if(uptr != NULL) {
- if(uptr[1] == 0) {
+ if (uptr != NULL) {
+ if (uptr[1] == 0) {
lafe_errc(1, 0, "Invalid argument to --owner (missing id after :)");
}
uptr[0] = 0;
uptr++;
- t = (int)strtol(uptr, &tptr, 10);
- if (errno || t < 0 || *uptr == '\0' ||
+ l = strtol(uptr, &tptr, 10);
+ if (l < 0 || l >= INT_MAX || *uptr == '\0' ||
tptr == NULL || *tptr != '\0') {
lafe_errc(1, 0, "Invalid argument to --owner (%s is not a number)", uptr);
} else {
- bsdtar->uid = t;
+ bsdtar->uid = (int)l;
}
bsdtar->uname = bsdtar->argument;
} else {
- t = (int)strtol(bsdtar->argument, &tptr, 10);
- if (errno || t < 0 || *(bsdtar->argument) == '\0' ||
+ l = strtol(bsdtar->argument, &tptr, 10);
+ if (l < 0 || l >= INT_MAX || *(bsdtar->argument) == '\0' ||
tptr == NULL || *tptr != '\0') {
bsdtar->uname = bsdtar->argument;
} else {
- bsdtar->uid = t;
+ bsdtar->uid = (int)l;
bsdtar->uname = "";
}
}
@@ -748,15 +745,14 @@ main(int argc, char **argv)
bsdtar->extract_flags |= ARCHIVE_EXTRACT_OWNER;
break;
case OPTION_STRIP_COMPONENTS: /* GNU tar 1.15 */
- errno = 0;
tptr = NULL;
- t = (int)strtol(bsdtar->argument, &tptr, 10);
- if (errno || t < 0 || *(bsdtar->argument) == '\0' ||
+ l = strtol(bsdtar->argument, &tptr, 10);
+ if (l < 0 || l > 100000L || *(bsdtar->argument) == '\0' ||
tptr == NULL || *tptr != '\0') {
lafe_errc(1, 0, "Invalid argument to "
"--strip-components");
}
- bsdtar->strip_components = t;
+ bsdtar->strip_components = (int)l;
break;
case 'T': /* GNU tar */
bsdtar->names_from_file = bsdtar->argument;
@@ -776,14 +772,13 @@ main(int argc, char **argv)
set_mode(bsdtar, opt);
break;
case OPTION_UID: /* cpio */
- errno = 0;
tptr = NULL;
- t = (int)strtol(bsdtar->argument, &tptr, 10);
- if (errno || t < 0 || *(bsdtar->argument) == '\0' ||
+ l = strtol(bsdtar->argument, &tptr, 10);
+ if (l < 0 || l >= INT_MAX || *(bsdtar->argument) == '\0' ||
tptr == NULL || *tptr != '\0') {
lafe_errc(1, 0, "Invalid argument to --uid");
}
- bsdtar->uid = t;
+ bsdtar->uid = (int)l;
break;
case OPTION_UNAME: /* cpio */
bsdtar->uname = bsdtar->argument;
diff --git a/tar/cmdline.c b/tar/cmdline.c
index 72292e8f27f3..2a89f42b0880 100644
--- a/tar/cmdline.c
+++ b/tar/cmdline.c
@@ -218,12 +218,18 @@ bsdtar_getopt(struct bsdtar *bsdtar)
enum { state_start = 0, state_old_tar, state_next_word,
state_short, state_long };
- const struct bsdtar_option *popt, *match = NULL, *match2 = NULL;
- const char *p, *long_prefix = "--";
+ const struct bsdtar_option *popt, *match, *match2;
+ const char *p, *long_prefix;
size_t optlength;
- int opt = '?';
- int required = 0;
+ int opt;
+ int required;
+again:
+ match = NULL;
+ match2 = NULL;
+ long_prefix = "--";
+ opt = '?';
+ required = 0;
bsdtar->argument = NULL;
/* First time through, initialize everything. */
@@ -310,7 +316,7 @@ bsdtar_getopt(struct bsdtar *bsdtar)
if (opt == '\0') {
/* End of this group; recurse to get next option. */
bsdtar->getopt_state = state_next_word;
- return bsdtar_getopt(bsdtar);
+ goto again;
}
/* Does this option take an argument? */
diff --git a/unzip/cmdline.c b/unzip/cmdline.c
index ab1aeb31fe18..4c6efc3e0694 100644
--- a/unzip/cmdline.c
+++ b/unzip/cmdline.c
@@ -81,12 +81,18 @@ bsdunzip_getopt(struct bsdunzip *bsdunzip)
{
enum { state_start = 0, state_next_word, state_short, state_long };
- const struct bsdunzip_option *popt, *match = NULL, *match2 = NULL;
- const char *p, *long_prefix = "--";
+ const struct bsdunzip_option *popt, *match, *match2;
+ const char *p, *long_prefix;
size_t optlength;
- int opt = OPTION_NONE;
- int required = 0;
-
+ int opt;
+ int required;
+
+again:
+ match = NULL;
+ match2 = NULL;
+ long_prefix = "--";
+ opt = OPTION_NONE;
+ required = 0;
bsdunzip->argument = NULL;
/* First time through, initialize everything. */
@@ -140,7 +146,7 @@ bsdunzip_getopt(struct bsdunzip *bsdunzip)
if (opt == '\0') {
/* End of this group; recurse to get next option. */
bsdunzip->getopt_state = state_next_word;
- return bsdunzip_getopt(bsdunzip);
+ goto again;
}
/* Does this option take an argument? */
diff --git a/unzip/test/test_I.c b/unzip/test/test_I.c
index a6bad85a011f..5d31ce8d1611 100644
--- a/unzip/test/test_I.c
+++ b/unzip/test/test_I.c
@@ -25,12 +25,25 @@
*/
#include "test.h"
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
/* Test I arg - file name encoding */
DEFINE_TEST(test_I)
{
const char *reffile = "test_I.zip";
int r;
+#if HAVE_SETLOCALE
+ if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) {
+ skipping("en_US.UTF-8 locale not available on this system.");
+ return;
+ }
+#else
+ skipping("setlocale() not available on this system.");
+#endif
+
extract_reference_file(reffile);
r = systemf("%s -I UTF-8 %s >test.out 2>test.err", testprog, reffile);
assertEqualInt(0, r);