The branch stable/14 has been updated by mm:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=d39dd181c8ab36264a60ad0b329e80929a0db7f8

commit d39dd181c8ab36264a60ad0b329e80929a0db7f8
Author:     Martin Matuska <[email protected]>
AuthorDate: 2025-12-01 13:05:35 +0000
Commit:     Martin Matuska <[email protected]>
CommitDate: 2026-01-15 20:04:49 +0000

    libarchive: merge from vendor branch
    
    libarchive 3.8.4
    
    Important bugfixes:
         #2787 bsdtar: Fix zero-length pattern issue
         #2797 lib: Fix regression introduced in libarchive 3.8.2
                    when walking enterable but unreadable directories
    
    Obtained from:  libarchive
    Vendor commit:  d114ceee6de08a7a60ff1209492ba38bf9436f79
    MFC after:      1 week
    
    (cherry picked from commit c1e033c33e8b290cd40f4069249c879efcbae6a6)
---
 contrib/libarchive/NEWS                            |  8 ++++---
 contrib/libarchive/libarchive/archive.h            |  4 ++--
 contrib/libarchive/libarchive/archive_cryptor.c    |  6 +++---
 .../libarchive/archive_cryptor_private.h           |  4 ++--
 contrib/libarchive/libarchive/archive_entry.h      |  2 +-
 .../libarchive/archive_read_disk_entry_from_file.c |  5 ++---
 .../libarchive/archive_read_disk_posix.c           | 25 ++++++++++------------
 .../libarchive/archive_read_support_format_mtree.c |  2 +-
 .../libarchive/archive_version_details.c           |  2 +-
 contrib/libarchive/libarchive/archive_write.c      |  2 +-
 .../libarchive/archive_write_disk_posix.c          |  6 +++---
 .../libarchive/archive_write_set_format_xar.c      | 12 +++++------
 .../test/test_archive_read_multiple_data_objects.c |  2 +-
 .../libarchive/test/test_write_disk_perms.c        |  6 +++---
 .../libarchive/test/test_write_filter_bzip2.c      |  3 ++-
 contrib/libarchive/tar/subst.c                     | 19 ++++++++++------
 contrib/libarchive/tar/test/test_option_s.c        |  8 ++++++-
 17 files changed, 63 insertions(+), 53 deletions(-)

diff --git a/contrib/libarchive/NEWS b/contrib/libarchive/NEWS
index 971ae8e441e1..fbbb65440b39 100644
--- a/contrib/libarchive/NEWS
+++ b/contrib/libarchive/NEWS
@@ -1,8 +1,10 @@
-Nov 17, 2026: libarchive 3.8.3 released
+Dec 01, 2025: libarchive 3.8.4 released
 
-Oct 15, 2026: libarchive 3.8.2 released
+Nov 17, 2025: libarchive 3.8.3 released
 
-Jun 01, 2026: libarchive 3.8.1 released
+Oct 15, 2025: libarchive 3.8.2 released
+
+Jun 01, 2025: libarchive 3.8.1 released
 
 May 20, 2025: libarchive 3.8.0 released
 
diff --git a/contrib/libarchive/libarchive/archive.h 
b/contrib/libarchive/libarchive/archive.h
index 9794dced6ca9..0eda822ae6bf 100644
--- a/contrib/libarchive/libarchive/archive.h
+++ b/contrib/libarchive/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 3008003
+#define        ARCHIVE_VERSION_NUMBER 3008004
 
 #include <sys/stat.h>
 #include <stddef.h>  /* 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.3"
+#define        ARCHIVE_VERSION_ONLY_STRING "3.8.4"
 #define        ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
 __LA_DECL const char * archive_version_string(void);
 
diff --git a/contrib/libarchive/libarchive/archive_cryptor.c 
b/contrib/libarchive/libarchive/archive_cryptor.c
index 9f03f9ca6dd0..b6a02fd1e7cb 100644
--- a/contrib/libarchive/libarchive/archive_cryptor.c
+++ b/contrib/libarchive/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/contrib/libarchive/libarchive/archive_cryptor_private.h 
b/contrib/libarchive/libarchive/archive_cryptor_private.h
index 1dbc5c17a01a..272f2f84b9c9 100644
--- a/contrib/libarchive/libarchive/archive_cryptor_private.h
+++ b/contrib/libarchive/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/contrib/libarchive/libarchive/archive_entry.h 
b/contrib/libarchive/libarchive/archive_entry.h
index 924b67a301cf..74466f394c4a 100644
--- a/contrib/libarchive/libarchive/archive_entry.h
+++ b/contrib/libarchive/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 3008003
+#define        ARCHIVE_VERSION_NUMBER 3008004
 
 /*
  * Note: archive_entry.h is for use outside of libarchive; the
diff --git a/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c 
b/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c
index 121af19872e9..6e6bae6a4e06 100644
--- a/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c
+++ b/contrib/libarchive/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) {
@@ -892,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
@@ -1079,4 +1079,3 @@ setup_sparse(struct archive_read_disk *a,
 #endif
 
 #endif /* !defined(_WIN32) || defined(__CYGWIN__) */
-
diff --git a/contrib/libarchive/libarchive/archive_read_disk_posix.c 
b/contrib/libarchive/libarchive/archive_read_disk_posix.c
index 7cd292f259ff..94fa8fef963f 100644
--- a/contrib/libarchive/libarchive/archive_read_disk_posix.c
+++ b/contrib/libarchive/libarchive/archive_read_disk_posix.c
@@ -2018,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);
 }
 
 /*
@@ -2144,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);
 }
 
@@ -2359,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/contrib/libarchive/libarchive/archive_read_support_format_mtree.c 
b/contrib/libarchive/libarchive/archive_read_support_format_mtree.c
index ded13bee79a3..96d2c71f4c4f 100644
--- a/contrib/libarchive/libarchive/archive_read_support_format_mtree.c
+++ b/contrib/libarchive/libarchive/archive_read_support_format_mtree.c
@@ -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/contrib/libarchive/libarchive/archive_version_details.c 
b/contrib/libarchive/libarchive/archive_version_details.c
index 0cf92db73194..9063faa79426 100644
--- a/contrib/libarchive/libarchive/archive_version_details.c
+++ b/contrib/libarchive/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/contrib/libarchive/libarchive/archive_write.c 
b/contrib/libarchive/libarchive/archive_write.c
index 9b9cb196f0f9..e1ce5d57288d 100644
--- a/contrib/libarchive/libarchive/archive_write.c
+++ b/contrib/libarchive/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/contrib/libarchive/libarchive/archive_write_disk_posix.c 
b/contrib/libarchive/libarchive/archive_write_disk_posix.c
index d69f041dde7e..cc59e58e4df6 100644
--- a/contrib/libarchive/libarchive/archive_write_disk_posix.c
+++ b/contrib/libarchive/libarchive/archive_write_disk_posix.c
@@ -2561,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)) {
@@ -4447,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/contrib/libarchive/libarchive/archive_write_set_format_xar.c 
b/contrib/libarchive/libarchive/archive_write_set_format_xar.c
index 9921f1032be5..ec3219057e4e 100644
--- a/contrib/libarchive/libarchive/archive_write_set_format_xar.c
+++ b/contrib/libarchive/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, "<inode>".
         */
        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, "<uid>" and "<user>.
         */
        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, "<gid>" and "<group>.
         */
        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/contrib/libarchive/libarchive/test/test_archive_read_multiple_data_objects.c 
b/contrib/libarchive/libarchive/test/test_archive_read_multiple_data_objects.c
index f9f75d96fa6b..791c7ad01121 100644
--- 
a/contrib/libarchive/libarchive/test/test_archive_read_multiple_data_objects.c
+++ 
b/contrib/libarchive/libarchive/test/test_archive_read_multiple_data_objects.c
@@ -202,7 +202,7 @@ static int64_t
 file_skip(struct archive *a, void *data, int64_t request)
 {
   struct mydata *mydata = (struct mydata *)data;
-  int64_t result = lseek(mydata->fd, SEEK_CUR, request);
+  int64_t result = lseek(mydata->fd, request, SEEK_CUR);
   if (result >= 0)
     return result;
   archive_set_error(a, errno, "Error seeking in '%s'", mydata->filename);
diff --git a/contrib/libarchive/libarchive/test/test_write_disk_perms.c 
b/contrib/libarchive/libarchive/test/test_write_disk_perms.c
index 77a15d1a3e42..72b55179d86e 100644
--- a/contrib/libarchive/libarchive/test/test_write_disk_perms.c
+++ b/contrib/libarchive/libarchive/test/test_write_disk_perms.c
@@ -94,21 +94,21 @@ searchgid(void)
        close(fd);
 }
 
-static int
+static long
 altgid(void)
 {
        searchgid();
        return (_alt_gid);
 }
 
-static int
+static long
 invalidgid(void)
 {
        searchgid();
        return (_invalid_gid);
 }
 
-static int
+static long
 defaultgid(void)
 {
        searchgid();
diff --git a/contrib/libarchive/libarchive/test/test_write_filter_bzip2.c 
b/contrib/libarchive/libarchive/test/test_write_filter_bzip2.c
index 7b2e4f857a75..d7ed95e2c7ff 100644
--- a/contrib/libarchive/libarchive/test/test_write_filter_bzip2.c
+++ b/contrib/libarchive/libarchive/test/test_write_filter_bzip2.c
@@ -40,7 +40,8 @@ DEFINE_TEST(test_write_filter_bzip2)
        size_t buffsize, datasize;
        char path[16];
        size_t used1, used2;
-       int i, r, use_prog;
+       ssize_t r;
+       int i, use_prog;
 
        buffsize = 2000000;
        assert(NULL != (buff = malloc(buffsize)));
diff --git a/contrib/libarchive/tar/subst.c b/contrib/libarchive/tar/subst.c
index a5d644dc5a70..a466f65358a5 100644
--- a/contrib/libarchive/tar/subst.c
+++ b/contrib/libarchive/tar/subst.c
@@ -235,7 +235,9 @@ apply_substitution(struct bsdtar *bsdtar, const char *name, 
char **result,
                        (*result)[0] = 0;
                }
 
-               while (1) {
+               char isEnd = 0;
+               do {
+            isEnd = *name == '\0';
                        if (regexec(&rule->re, name, 10, matches, 0))
                                break;
 
@@ -290,12 +292,15 @@ apply_substitution(struct bsdtar *bsdtar, const char 
*name, char **result,
                        }
 
                        realloc_strcat(result, rule->result + j);
-
-                       name += matches[0].rm_eo;
-
-                       if (!rule->global)
-                               break;
-               }
+                       if (matches[0].rm_eo > 0) {
+                name += matches[0].rm_eo;
+            } else {
+                // We skip a character because the match is 0-length
+                // so we need to add it to the output
+                realloc_strncat(result, name, 1);
+                name += 1;
+            }
+               } while (rule->global && !isEnd); // Testing one step after 
because sed et al. run 0-length patterns a last time on the empty string at the 
end
        }
 
        if (got_match)
diff --git a/contrib/libarchive/tar/test/test_option_s.c 
b/contrib/libarchive/tar/test/test_option_s.c
index 125e971d3304..00753b99be3c 100644
--- a/contrib/libarchive/tar/test/test_option_s.c
+++ b/contrib/libarchive/tar/test/test_option_s.c
@@ -42,7 +42,13 @@ DEFINE_TEST(test_option_s)
        systemf("%s -cf test1_2.tar -s /d1/d2/ in/d1/foo", testprog);
        systemf("%s -xf test1_2.tar -C test1", testprog);
        assertFileContents("foo", 3, "test1/in/d2/foo");
-
+       systemf("%s -cf test1_3.tar -s /o/#/g in/d1/foo", testprog);
+       systemf("%s -xf test1_3.tar -C test1", testprog);
+       assertFileContents("foo", 3, "test1/in/d1/f##");
+       // For the 0-length pattern check, remember that "test1/" isn't part of 
the string affected by the regexp
+       systemf("%s -cf test1_4.tar -s /f*/\\<~\\>/g in/d1/foo", testprog);
+       systemf("%s -xf test1_4.tar -C test1", testprog);
+       assertFileContents("foo", 3, "test1/<>i<>n<>/<>d<>1<>/<f><>o<>o<>");
        /*
         * Test 2: Basic substitution when extracting archive.
         */

Reply via email to