From nobody Tue Nov 03 14:22:34 2026 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4jJrPk2hWvz6yJ3V for ; Tue, 03 Nov 2026 14:22:34 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 4jJrPk1Yp7z3QYf for ; Tue, 03 Nov 2026 14:22:34 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1793715754; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=rN/bhiyq0DEJZJXb2dmhE8qZOQuYA/zFW8dEsKodOBc=; b=KOttQVxKGpT8RBq+ooATPi/l9alTvnGELDwlu/WxOgayBu6dkjLDSlc+HizdRCV9VqwkBM me5h1/N10fokMAoV2w0QcLRw2Su+g1R3uGB9WyVl6DGksKn6JZMLHmn0R9cR3CFghBHwGX snfXcA0bmxr35mbAWpd/rvL5imcjB4HBtd+9NfMK3EioTf6oaCjHOm2d8MplDDHfcYp/bD diZ6jjQSvjS2IbvnAqi/OF252m8k5qv6bQ6T4kDJ0keGaADxxtlddSlLvduEuyDQ3DUxvI s3p+BNCvGlXX0vSjDVcL1h4x1LSyNXz9riWm33eqmHNZ/yHZieHjz1zISFaqHg== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1793715754; b=b2TpoJRZyeWR4uI55U6ttVZcoMAitM9PQQYLJKa/DGzJDfyaslGpoFnv5NQLW9WTQTr6JZ oViIgVDI7Vi04MQn09ofd9R4TS0c2goQVHqhDsc+xIGtABoNPD3b2hf5yscP0w+LZ05XHw bToplAxaLZi/Bt1TzcWYCZYg1zyN69OfETv0XqvluNuwrGNcBMUaWh0OJSyjftcrVk24WA /TJkyuHR2FProGf2vV5pwQmIulx1t3sWm4aDfulcOCjvkBea/MCPd6Zafuhn1hQirsevG7 1AzpQkdx45rswGNzsJX8hejctDSyuSCFl0fIWHOSeIOKM01QpcY3B6MNBmbdAA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1793715754; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=rN/bhiyq0DEJZJXb2dmhE8qZOQuYA/zFW8dEsKodOBc=; b=L7A7nbR3ToSt20+ow+NZi9ZW+8+GgJ97SwBNNMrJPP0AAPbMNh74bWWPyKIbIaAKMJgR2J 1asdtTItq55euDmVbQYShIvfgrmv+3lRwfvOvBQy4kdSaPDAKq9nxVMwkzmni0X4xZapcK 5tbmSIi7Ii28ZCug2oI6sPF5bpW5/7LwRYfoR6SAbv0hjoFyuljRIIRj2op8Wv0x9hE5qE qNfpzRaAQAx2im/1K0Jp9+Ya7T7pKHZ6kd5mdUCGML3EGRKaF2eyOaqgMfzP5upBkLlpLi 6MBztkxVE2oidf0g9oAHBRPa7bu249QGF3ACzF01HdkQSFQV5u60mNnnrxc/Pw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4jJrPk1CZvzKBf for ; Tue, 03 Nov 2026 14:22:34 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3d4ec by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 03 Nov 2026 14:22:34 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Martin Matuska Subject: git: 80c954a926c6 - stable/15 - libarchive: merge from vendor branch List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org List-Id: Commits to the stable branches of the FreeBSD src repository List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mm X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: 80c954a926c6ac4a7dda462423fd732f4ce06f40 Auto-Submitted: auto-generated Date: Tue, 03 Nov 2026 14:22:34 +0000 Message-Id: <6ae9ee2a.3d4ec.5d5e51ad@gitrepo.freebsd.org> The branch stable/15 has been updated by mm: URL: https://cgit.FreeBSD.org/src/commit/?id=80c954a926c6ac4a7dda462423fd732f4ce06f40 commit 80c954a926c6ac4a7dda462423fd732f4ce06f40 Author: Martin Matuska AuthorDate: 2026-10-31 23:39:49 +0000 Commit: Martin Matuska CommitDate: 2026-11-03 14:22:05 +0000 libarchive: merge from vendor branch libarchive 3.8.11 ChangeLog: https://github.com/libarchive/libarchive/compare/v3.8.10...v3.8.11 Obtained from: libarchive Vendor commit: 03036ffa409a2aa1c5bbad35be2202641a040fda MFC after: 3 days (cherry picked from commit 322d4227521380a61850b3d4f2ebd2b42343a254) --- contrib/libarchive/NEWS | 2 + contrib/libarchive/cpio/cpio.c | 6 + .../cpio/test/test_option_o_rejected_entry.c | 38 +++++ contrib/libarchive/libarchive/archive.h | 6 +- .../libarchive/libarchive/archive_digest_private.h | 3 - contrib/libarchive/libarchive/archive_entry.h | 2 +- contrib/libarchive/libarchive/archive_read.c | 146 ++++++++++++------ .../libarchive/archive_read_append_filter.c | 69 +++------ .../libarchive/archive_read_data_into_fd.c | 26 +++- .../libarchive/archive_read_disk_entry_from_file.c | 24 ++- .../libarchive/archive_read_open_filename.c | 3 +- .../archive_read_support_filter_by_code.c | 1 + .../libarchive/archive_read_support_filter_uu.c | 67 +++++++- .../libarchive/archive_read_support_format_7zip.c | 34 +++++ .../libarchive/archive_read_support_format_cpio.c | 4 + .../archive_read_support_format_iso9660.c | 103 +++++++------ .../libarchive/archive_read_support_format_mtree.c | 17 ++- .../libarchive/archive_read_support_format_rar.c | 4 +- .../libarchive/archive_read_support_format_tar.c | 18 ++- .../libarchive/archive_read_support_format_xar.c | 19 ++- .../libarchive/archive_read_support_format_zip.c | 67 ++------ contrib/libarchive/libarchive/archive_string.c | 25 ++- contrib/libarchive/libarchive/archive_write.c | 9 +- .../libarchive/archive_write_add_filter.c | 1 + .../archive_write_add_filter_b64encode.c | 12 +- .../libarchive/archive_write_add_filter_uuencode.c | 8 +- .../libarchive/archive_write_add_filter_zstd.c | 12 +- .../libarchive/archive_write_disk_posix.c | 2 +- .../libarchive/archive_write_set_format_7zip.c | 4 +- .../libarchive/archive_write_set_format_iso9660.c | 12 +- .../libarchive/archive_write_set_format_pax.c | 15 +- .../libarchive/archive_write_set_format_xar.c | 6 +- .../libarchive/archive_write_set_format_zip.c | 5 +- .../libarchive/libarchive/archive_xml_private.h | 3 - .../libarchive/libarchive/test/test_archive_read.c | 2 + .../test/test_archive_read_append_filter.c | 41 +++-- .../test/test_archive_read_open_filenames.c | 10 +- .../test/test_archive_write_add_filter.c | 9 ++ .../test/test_archive_write_add_filter_by_name.c | 4 + .../test/test_archive_write_close_callback.c | 106 +++++++++++++ .../test/test_create_child_environment.c | 36 +++-- .../test/test_gnutar_filename_encoding.c | 7 +- .../libarchive/test/test_open_filename.c | 90 +++++++++++ .../libarchive/test/test_read_data_large.c | 93 +++++++++++ .../libarchive/test/test_read_filter_compress.c | 41 +++++ ...est_read_filter_compress_multi_volume.part01.uu | 8 + ...est_read_filter_compress_multi_volume.part02.uu | 8 + ...est_read_filter_compress_multi_volume.part03.uu | 4 + .../libarchive/test/test_read_filter_uudecode.c | 1 - .../libarchive/test/test_read_format_7zip.c | 31 ++++ .../test/test_read_format_7zip_chained_lzma2.7z.uu | 13 ++ .../test/test_read_format_cpio_newc_resync.c | 89 +++++++++++ .../test_read_format_iso_joliet_overlong.iso.Z.uu | 69 +++++++++ .../test_read_format_iso_joliet_utf16be_cycle.c | 65 ++++++++ ...t_read_format_iso_joliet_utf16be_cycle.iso.Z.uu | 21 +++ .../test/test_read_format_iso_rockridge_sl_leak.c | 55 +++++++ .../test_read_format_iso_rockridge_sl_leak.iso.uu | 53 +++++++ .../test/test_read_format_isojoliet_long.c | 31 +++- .../libarchive/test/test_read_format_mtree.c | 78 ++++++++++ .../libarchive/test/test_read_format_rar.c | 29 ++++ .../test/test_read_format_tar_gnu_sparse_map.c | 75 +++++++++ ...t_read_format_tar_gnu_sparse_map_invalid.tar.uu | 72 +++++++++ ..._read_format_tar_gnu_sparse_map_overflow.tar.uu | 72 +++++++++ .../libarchive/test/test_read_format_xar.c | 57 +++++++ ...test_read_format_xar_invalid_seek_offset.xar.uu | 14 ++ .../test/test_read_format_zip_streamable_skip.c | 99 ++++++++++++ .../libarchive/test/test_ustar_filename_encoding.c | 7 +- .../libarchive/test/test_v7tar_filename_encoding.c | 7 +- .../libarchive/test/test_write_disk_secure744.c | 9 +- .../libarchive/test/test_write_filter_b64encode.c | 60 ++++++++ .../libarchive/test/test_write_filter_uuencode.c | 48 ++++++ .../libarchive/test/test_write_filter_zstd.c | 17 +++ .../test_write_format_iso9660_boot_load_size.c | 41 +++++ .../test/test_write_format_option_missing_value.c | 55 +++++++ .../test/test_write_format_pax_mac_meta.c | 170 +++++++++++++++++++++ .../libarchive/test/test_zip_filename_encoding.c | 7 +- contrib/libarchive/libarchive_fe/lafe_fnmatch.c | 2 +- contrib/libarchive/tar/creation_set.c | 163 ++++++++------------ contrib/libarchive/tar/subst.c | 38 ++--- .../libarchive/tar/test/test_copy_data_warning.c | 25 +++ .../tar/test/test_copy_data_warning.lzh.uu | 17 +++ contrib/libarchive/tar/test/test_option_s.c | 20 +++ contrib/libarchive/tar/util.c | 6 + contrib/libarchive/tar/write.c | 6 + contrib/libarchive/test_utils/test_common.h | 3 - contrib/libarchive/test_utils/test_main.c | 34 +++-- contrib/libarchive/unzip/bsdunzip.c | 44 ++++-- contrib/libarchive/unzip/test/test_prompt.c | 31 ++++ contrib/libarchive/unzip/test/test_prompt.zip.uu | 9 ++ contrib/libarchive/unzip/test/test_stdin.c | 21 +++ lib/libarchive/tests/Makefile | 23 ++- usr.bin/cpio/tests/Makefile | 1 + usr.bin/tar/tests/Makefile | 2 + usr.bin/unzip/tests/Makefile | 3 + 94 files changed, 2556 insertions(+), 469 deletions(-) diff --git a/contrib/libarchive/NEWS b/contrib/libarchive/NEWS index e0dc5f5c110a..e9fbd32bee84 100644 --- a/contrib/libarchive/NEWS +++ b/contrib/libarchive/NEWS @@ -1,3 +1,5 @@ +Oct 30, 2026: libarchive 3.8.11 released + Oct 14, 2026: libarchive 3.8.10 released Jul 28, 2026: libarchive 3.8.9 released diff --git a/contrib/libarchive/cpio/cpio.c b/contrib/libarchive/cpio/cpio.c index 9ba153d82770..4310c83ad9b4 100644 --- a/contrib/libarchive/cpio/cpio.c +++ b/contrib/libarchive/cpio/cpio.c @@ -886,6 +886,8 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry) if (r == ARCHIVE_FATAL) exit(1); + if (r == ARCHIVE_FAILED) + cpio->return_value = 1; if (r >= ARCHIVE_WARN && archive_entry_size(entry) > 0 && fd >= 0) { static char buff[16384]; @@ -906,6 +908,10 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry) } bytes_read = read(fd, buff, sizeof(buff)); } + if (bytes_read < 0) { + lafe_warnc(errno, "%s: read error", srcpath); + cpio->return_value = 1; + } } fd = restore_time(cpio, entry, srcpath, fd); diff --git a/contrib/libarchive/cpio/test/test_option_o_rejected_entry.c b/contrib/libarchive/cpio/test/test_option_o_rejected_entry.c new file mode 100644 index 000000000000..2e13032a8eb6 --- /dev/null +++ b/contrib/libarchive/cpio/test/test_option_o_rejected_entry.c @@ -0,0 +1,38 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2026 Martin Mirchev + * All rights reserved. + */ +#include "test.h" + +/* + * If the archive format cannot store an entry, bsdcpio -o warns and omits + * the entry; the exit status must report that the archive is incomplete. + */ +DEFINE_TEST(test_option_o_rejected_entry) +{ + char name[121]; + char filelist[sizeof(name) + 8]; + int r; + + /* A file name of 120 characters does not fit a ustar header. */ + memset(name, 'f', sizeof(name) - 1); + name[sizeof(name) - 1] = '\0'; + + assertMakeFile("small", 0644, "hello"); + assertMakeFile(name, 0644, "x"); + snprintf(filelist, sizeof(filelist), "small\n%s\n", name); + assertMakeFile("filelist", 0644, filelist); + + r = systemf("%s -o -H ustar archive.out 2>archive.err", + testprog); + failure("The omitted entry must be reported in the exit status"); + assert(r != 0); + assertNonEmptyFile("archive.err"); + + /* The other entry is still written. */ + r = systemf("%s -it list.out 2>list.err", testprog); + assertEqualInt(r, 0); + assertTextFileContents("small\n", "list.out"); +} diff --git a/contrib/libarchive/libarchive/archive.h b/contrib/libarchive/libarchive/archive.h index 19b316a40b73..2c1390828ca2 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 3008010 +#define ARCHIVE_VERSION_NUMBER 3008011 #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.10" +#define ARCHIVE_VERSION_ONLY_STRING "3.8.11" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); @@ -323,6 +323,7 @@ typedef const char *archive_passphrase_callback(struct archive *, #define ARCHIVE_FILTER_GRZIP 12 #define ARCHIVE_FILTER_LZ4 13 #define ARCHIVE_FILTER_ZSTD 14 +#define ARCHIVE_FILTER_B64 15 #if ARCHIVE_VERSION_NUMBER < 4000000 #define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE @@ -336,6 +337,7 @@ typedef const char *archive_passphrase_callback(struct archive *, #define ARCHIVE_COMPRESSION_RPM ARCHIVE_FILTER_RPM #define ARCHIVE_COMPRESSION_LZIP ARCHIVE_FILTER_LZIP #define ARCHIVE_COMPRESSION_LRZIP ARCHIVE_FILTER_LRZIP +#define ARCHIVE_COMPRESSION_B64 ARCHIVE_FILTER_B64 #endif /* diff --git a/contrib/libarchive/libarchive/archive_digest_private.h b/contrib/libarchive/libarchive/archive_digest_private.h index 032bd8c20427..cd2956e6ce36 100644 --- a/contrib/libarchive/libarchive/archive_digest_private.h +++ b/contrib/libarchive/libarchive/archive_digest_private.h @@ -30,9 +30,6 @@ #ifndef __LIBARCHIVE_BUILD #error This header is only to be used internally to libarchive. #endif -#ifndef __LIBARCHIVE_CONFIG_H_INCLUDED -#error "Should have include config.h first!" -#endif /* * Crypto support in various Operating Systems: diff --git a/contrib/libarchive/libarchive/archive_entry.h b/contrib/libarchive/libarchive/archive_entry.h index 50e10a1e33a2..ce9626a68e7d 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 3008010 +#define ARCHIVE_VERSION_NUMBER 3008011 /* * Note: archive_entry.h is for use outside of libarchive; the diff --git a/contrib/libarchive/libarchive/archive_read.c b/contrib/libarchive/libarchive/archive_read.c index 2f006fb96da9..6235d66d99e3 100644 --- a/contrib/libarchive/libarchive/archive_read.c +++ b/contrib/libarchive/libarchive/archive_read.c @@ -378,7 +378,7 @@ archive_read_set_callback_data2(struct archive *_a, void *client_data, return ARCHIVE_FATAL; } a->client.dataset[iindex].data = client_data; - a->client.dataset[iindex].begin_position = -1; + a->client.dataset[iindex].begin_position = 0; a->client.dataset[iindex].total_size = -1; return ARCHIVE_OK; } @@ -422,11 +422,11 @@ archive_read_add_callback_data(struct archive *_a, void *client_data, for (i = a->client.nodes - 1; i > iindex; i--) { a->client.dataset[i].data = a->client.dataset[i-1].data; - a->client.dataset[i].begin_position = -1; + a->client.dataset[i].begin_position = 0; a->client.dataset[i].total_size = -1; } a->client.dataset[iindex].data = client_data; - a->client.dataset[iindex].begin_position = -1; + a->client.dataset[iindex].begin_position = 0; a->client.dataset[iindex].total_size = -1; return ARCHIVE_OK; } @@ -454,7 +454,7 @@ int archive_read_open1(struct archive *_a) { struct archive_read *a = (struct archive_read *)_a; - struct archive_read_filter *f, *tmp; + struct archive_read_filter *f; int slot, e = ARCHIVE_OK; archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, @@ -510,11 +510,41 @@ archive_read_open1(struct archive *_a) } else { + size_t count; + struct archive_read_filter *f2; + /* Need to add "NONE" type filter at the end of the filter chain */ - tmp = a->filter; - while (tmp->upstream) - tmp = tmp->upstream; - tmp->upstream = f; + count = 1; + for (f2 = a->filter; f2->upstream != NULL; f2 = f2->upstream) + count++; + f2->upstream = f; + + while (count-- > 0) { + struct archive_read_filter_bidder *bidder; + size_t i; + int r; + + f2 = a->filter; + for (i = 0; i < count; i++) + f2 = f2->upstream; + bidder = f2->bidder; + + r = (bidder->vtable->bid)(bidder, f2->upstream); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Registered filter does not match"); + close_filters(a); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + r = (bidder->vtable->init)(f2); + if (r != ARCHIVE_OK) { + close_filters(a); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + } } if (!a->format) @@ -541,8 +571,6 @@ archive_read_open1(struct archive *_a) a->archive.state = ARCHIVE_STATE_HEADER; - /* Ensure libarchive starts from the first node in a multivolume set */ - client_switch_proxy(f, 0); return (e); } @@ -1692,6 +1720,44 @@ advance_file_pointer(struct archive_read_filter *f, int64_t request) } } +static int64_t +get_archive_size(struct archive_read_filter *f) +{ + struct archive_read_client *client = &(f->archive->client); + int64_t size; + unsigned int cursor; + + /* Try to calculate size without switching client objects. */ + size = 0; + for (cursor = 0; cursor < client->nodes; cursor++) { + int64_t total_size = client->dataset[cursor].total_size; + + if (total_size < 0) + break; + if (archive_ckd_add_i64(&size, size, total_size)) + return (ARCHIVE_FATAL); + } + + /* Seek through remaining client objects to calculate size. */ + for (; cursor < client->nodes; cursor++) { + int64_t r; + + client->dataset[cursor].begin_position = size; + r = client_switch_proxy(f, cursor); + if (r != ARCHIVE_OK) + return (r); + r = client_seek_proxy(f, 0, SEEK_END); + if (r < 0) + return (r); + client->dataset[cursor].total_size = r; + if (archive_ckd_add_i64(&size, size, r)) + return (ARCHIVE_FATAL); + f->position = size; + } + + return (size); +} + /** * Returns ARCHIVE_FAILED if seeking isn't supported. */ @@ -1706,9 +1772,8 @@ __archive_read_filter_seek(struct archive_read_filter *f, int64_t offset, int whence) { struct archive_read_client *client; - int64_t r; + int64_t old_position, r; unsigned int cursor, old_cursor; - int sought = 0; if (f->closed || f->fatal) return (ARCHIVE_FATAL); @@ -1717,6 +1782,7 @@ __archive_read_filter_seek(struct archive_read_filter *f, int64_t offset, client = &(f->archive->client); old_cursor = client->cursor; + old_position = f->position; switch (whence) { case SEEK_CUR: @@ -1727,8 +1793,7 @@ __archive_read_filter_seek(struct archive_read_filter *f, int64_t offset, cursor = 0; while (1) { - if (client->dataset[cursor].begin_position < 0 || - client->dataset[cursor].total_size < 0 || + if (client->dataset[cursor].total_size < 0 || client->dataset[cursor].begin_position + client->dataset[cursor].total_size > offset || cursor + 1 >= client->nodes) @@ -1741,10 +1806,14 @@ __archive_read_filter_seek(struct archive_read_filter *f, int64_t offset, r = client_switch_proxy(f, cursor); if (r != ARCHIVE_OK) goto clear_buffer; - if ((r = client_seek_proxy(f, 0, SEEK_END)) < 0) - goto clear_buffer; - sought = 1; - client->dataset[cursor].total_size = r; + if (client->dataset[cursor].total_size < 0) { + if ((r = client_seek_proxy(f, + 0, SEEK_END)) < 0) + goto clear_buffer; + client->dataset[cursor].total_size = r; + f->position = r + + client->dataset[cursor].begin_position; + } if (client->dataset[cursor].begin_position + client->dataset[cursor].total_size > offset || cursor + 1 >= client->nodes) @@ -1761,34 +1830,13 @@ __archive_read_filter_seek(struct archive_read_filter *f, int64_t offset, } if ((r = client_seek_proxy(f, offset, SEEK_SET)) < 0) goto clear_buffer; - sought = 1; break; case SEEK_END: - cursor = 0; - while (1) { - if (client->dataset[cursor].begin_position < 0 || - client->dataset[cursor].total_size < 0 || - cursor + 1 >= client->nodes) - break; - r = client->dataset[cursor].begin_position + - client->dataset[cursor].total_size; - client->dataset[++cursor].begin_position = r; - } - while (1) { - r = client_switch_proxy(f, cursor); - if (r != ARCHIVE_OK) - goto clear_buffer; - if ((r = client_seek_proxy(f, 0, SEEK_END)) < 0) - goto clear_buffer; - sought = 1; - client->dataset[cursor].total_size = r; - r = client->dataset[cursor].begin_position + - client->dataset[cursor].total_size; - if (cursor + 1 >= client->nodes) - break; - client->dataset[++cursor].begin_position = r; - } + r = get_archive_size(f); + if (r < 0) + goto clear_buffer; + cursor = client->nodes - 1; while (1) { if (r + offset >= client->dataset[cursor].begin_position) @@ -1806,16 +1854,17 @@ __archive_read_filter_seek(struct archive_read_filter *f, int64_t offset, r = client_seek_proxy(f, offset, SEEK_SET); if (r < ARCHIVE_OK) goto clear_buffer; - sought = 1; break; default: return (ARCHIVE_FATAL); } r += client->dataset[cursor].begin_position; + f->position = r; clear_buffer: - if (r == ARCHIVE_FAILED && !sought && old_cursor == client->cursor) { + if (r == ARCHIVE_FAILED && + old_cursor == client->cursor && old_position == f->position) { /* Seek failed without moving position: keep buffer */ return (r); } @@ -1839,11 +1888,12 @@ clear_buffer: */ f->avail = f->client_avail = 0; f->next = f->buffer; - if (r >= 0) { - f->position = r; + if (r >= 0) f->end_of_file = 0; - } else + else { + f->position = -1; f->fatal = 1; + } return r; } diff --git a/contrib/libarchive/libarchive/archive_read_append_filter.c b/contrib/libarchive/libarchive/archive_read_append_filter.c index 5cc8ff55d6b0..d03f1a8b5332 100644 --- a/contrib/libarchive/libarchive/archive_read_append_filter.c +++ b/contrib/libarchive/libarchive/archive_read_append_filter.c @@ -47,6 +47,28 @@ get_last_bidder(struct archive_read *a) return a->bidders + (i - 1); } +static int +archive_read_append_filter_last_bidder(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *b; + struct archive_read_filter *f; + + f = calloc(1, sizeof(*f)); + if (f == NULL) + { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + b = get_last_bidder(a); + f->bidder = b; + f->archive = a; + f->upstream = a->filter; + a->filter = f; + a->bypass_filter_bidding = 1; + return (ARCHIVE_OK); +} + int archive_read_append_filter(struct archive *_a, int code) { @@ -82,6 +104,7 @@ archive_read_append_filter(struct archive *_a, int code) case ARCHIVE_FILTER_XZ: r1 = archive_read_support_filter_xz(_a); break; + case ARCHIVE_FILTER_B64: case ARCHIVE_FILTER_UU: r1 = archive_read_support_filter_uu(_a); break; @@ -114,28 +137,9 @@ archive_read_append_filter(struct archive *_a, int code) if (r1 > ARCHIVE_FATAL && code != ARCHIVE_FILTER_NONE) { - struct archive_read_filter_bidder *b; - struct archive_read_filter *f; - - f = calloc(1, sizeof(*f)); - if (f == NULL) - { - archive_set_error(&a->archive, ENOMEM, "Out of memory"); - return (ARCHIVE_FATAL); - } - b = get_last_bidder(a); - f->bidder = b; - f->archive = a; - f->upstream = a->filter; - a->filter = f; - r2 = (b->vtable->init)(a->filter); - if (r2 != ARCHIVE_OK) { - __archive_read_free_filters(a); - return (ARCHIVE_FATAL); - } + r2 = archive_read_append_filter_last_bidder(_a); } - a->bypass_filter_bidding = 1; return (r1 < r2) ? r1 : r2; } @@ -149,32 +153,9 @@ int archive_read_append_filter_program_signature(struct archive *_a, const char *cmd, const void *signature, size_t signature_len) { - struct archive_read *a = (struct archive_read *)_a; - struct archive_read_filter_bidder *b; - struct archive_read_filter *f; - int r; - if (archive_read_support_filter_program_signature(_a, cmd, signature, signature_len) != (ARCHIVE_OK)) return (ARCHIVE_FATAL); - f = calloc(1, sizeof(*f)); - if (f == NULL) - { - archive_set_error(&a->archive, ENOMEM, "Out of memory"); - return (ARCHIVE_FATAL); - } - b = get_last_bidder(a); - f->bidder = b; - f->archive = a; - f->upstream = a->filter; - a->filter = f; - r = (b->vtable->init)(a->filter); - if (r != ARCHIVE_OK) { - __archive_read_free_filters(a); - return (ARCHIVE_FATAL); - } - - a->bypass_filter_bidding = 1; - return r; + return (archive_read_append_filter_last_bidder(_a)); } diff --git a/contrib/libarchive/libarchive/archive_read_data_into_fd.c b/contrib/libarchive/libarchive/archive_read_data_into_fd.c index b63fbf9236a6..8eee19f769a4 100644 --- a/contrib/libarchive/libarchive/archive_read_data_into_fd.c +++ b/contrib/libarchive/libarchive/archive_read_data_into_fd.c @@ -31,6 +31,9 @@ #ifdef HAVE_ERRNO_H #include #endif +#ifdef HAVE_FCNTL_H +#include +#endif #ifdef HAVE_UNISTD_H #include #endif @@ -86,11 +89,30 @@ pad_to(struct archive *a, int fd, int can_lseek, return (ARCHIVE_OK); } +static int +lseek_available(int fd) +{ + struct stat st; + int ret; + + /* Support holes only with regular files. */ + ret = (fstat(fd, &st) == 0) && S_ISREG(st.st_mode); +#ifdef HAVE_FCNTL + if (ret) { + int flags = fcntl(fd, F_GETFL); + + /* O_APPEND defeats lseek's sparse file purpose. */ + if (flags != -1 && flags & O_APPEND) + ret = 0; + } +#endif + + return (ret); +} int archive_read_data_into_fd(struct archive *a, int fd) { - struct stat st; int r, r2; const void *buff; size_t size, bytes_to_write; @@ -107,7 +129,7 @@ archive_read_data_into_fd(struct archive *a, int fd) declared_size = ((struct archive_read *)a)->entry_bytes_declared; - can_lseek = (fstat(fd, &st) == 0) && S_ISREG(st.st_mode); + can_lseek = lseek_available(fd); if (can_lseek) { fd_offset = lseek(fd, 0, SEEK_CUR); if (fd_offset == -1) 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 c4ad595fa4d8..7bd023401eb3 100644 --- a/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c +++ b/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c @@ -486,7 +486,17 @@ setup_xattr(struct archive_read_disk *a, return (ARCHIVE_WARN); } - if (size > 0 && (value = malloc(size)) == NULL) { + /* + * Do not query an empty value again: if it has grown in the + * meantime, the second call would return the new size without + * storing anything. + */ + if (size == 0) { + archive_entry_xattr_add_entry(entry, name, "", 0); + return (ARCHIVE_OK); + } + + if ((value = malloc(size)) == NULL) { archive_set_error(&a->archive, errno, "Out of memory"); return (ARCHIVE_FATAL); } @@ -682,7 +692,17 @@ setup_xattr(struct archive_read_disk *a, struct archive_entry *entry, return (ARCHIVE_WARN); } - if (size > 0 && (value = malloc(size)) == NULL) { + /* + * Do not query an empty value again: if it has grown in the + * meantime, the second call would return the new size without + * storing anything. + */ + if (size == 0) { + archive_entry_xattr_add_entry(entry, fullname, "", 0); + return (ARCHIVE_OK); + } + + if ((value = malloc(size)) == NULL) { archive_set_error(&a->archive, errno, "Out of memory"); return (ARCHIVE_FATAL); } diff --git a/contrib/libarchive/libarchive/archive_read_open_filename.c b/contrib/libarchive/libarchive/archive_read_open_filename.c index 91f64b694a0c..2c442eb12050 100644 --- a/contrib/libarchive/libarchive/archive_read_open_filename.c +++ b/contrib/libarchive/libarchive/archive_read_open_filename.c @@ -583,7 +583,6 @@ file_seek(struct archive *a, void *client_data, int64_t request, int whence) if (r >= 0) return r; - /* If the input is corrupted or truncated, fail. */ err: if (mine->filename_type == FNT_STDIN) archive_set_error(a, errno, "Error seeking in stdin"); @@ -593,7 +592,7 @@ err: else archive_set_error(a, errno, "Error seeking in '%ls'", mine->filename.w); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } static int diff --git a/contrib/libarchive/libarchive/archive_read_support_filter_by_code.c b/contrib/libarchive/libarchive/archive_read_support_filter_by_code.c index 4c8b6cb59c2a..6c184218404c 100644 --- a/contrib/libarchive/libarchive/archive_read_support_filter_by_code.c +++ b/contrib/libarchive/libarchive/archive_read_support_filter_by_code.c @@ -47,6 +47,7 @@ archive_read_support_filter_by_code(struct archive *a, int filter_code) return archive_read_support_filter_lzma(a); case ARCHIVE_FILTER_XZ: return archive_read_support_filter_xz(a); + case ARCHIVE_FILTER_B64: case ARCHIVE_FILTER_UU: return archive_read_support_filter_uu(a); case ARCHIVE_FILTER_RPM: diff --git a/contrib/libarchive/libarchive/archive_read_support_filter_uu.c b/contrib/libarchive/libarchive/archive_read_support_filter_uu.c index 364a3a041660..26b0929e3e40 100644 --- a/contrib/libarchive/libarchive/archive_read_support_filter_uu.c +++ b/contrib/libarchive/libarchive/archive_read_support_filter_uu.c @@ -44,6 +44,11 @@ /* Maximum lookahead during bid phase */ #define MAX_LINE_LENGTH 128*1024 /* in bytes */ +struct uu_bidder { + int code; + const char *name; +}; + struct uu { unsigned char *out_buff; #define OUT_BUFF_SIZE (64 * 1024) @@ -61,6 +66,7 @@ struct uu { static int uudecode_bidder_bid(struct archive_read_filter_bidder *, struct archive_read_filter *f); static int uudecode_bidder_init(struct archive_read_filter *); +static void uudecode_bidder_free(struct archive_read_filter_bidder *); static int uudecode_read_header(struct archive_read_filter *, struct archive_entry *entry); @@ -81,15 +87,27 @@ static const struct archive_read_filter_bidder_vtable uudecode_bidder_vtable = { .bid = uudecode_bidder_bid, .init = uudecode_bidder_init, + .free = uudecode_bidder_free }; int archive_read_support_filter_uu(struct archive *_a) { struct archive_read *a = (struct archive_read *)_a; + struct uu_bidder *data; - return __archive_read_register_bidder(a, NULL, - &uudecode_bidder_vtable); + data = calloc(1, sizeof(*data)); + if (data == NULL) { + archive_set_error(_a, ENOMEM, "Can't allocate memory"); + return ARCHIVE_FATAL; + } + + if (__archive_read_register_bidder(a, data, + &uudecode_bidder_vtable) != ARCHIVE_OK) { + free(data); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); } static const unsigned char uuchar[256] = { @@ -214,6 +232,17 @@ read_line_ahead(struct archive_read_filter *f, ssize_t parsed, line = b + start; *len = p - line; *unconsumed = *len + nl; + + /* Only ASCII lines are valid. */ + while (p > line) { + unsigned char c = *--p; + + if (c < 0x20 || c > 0x7F) { + *len = 0; + *unconsumed = 0; + return (NULL); + } + } } else { /* Keep offset for check of possibly missing \n in \r\n. */ if (step != 1) @@ -276,6 +305,7 @@ static int uudecode_bidder_bid(struct archive_read_filter_bidder *b, struct archive_read_filter *f) { + struct uu_bidder *data = b->data; const unsigned char *p; size_t l; int firstline; @@ -329,9 +359,14 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *b, } offset += unconsumed; p = read_line_ahead(f, 0, offset, &len, &unconsumed); - if (p != NULL && uuchar[*p]) + if (p != NULL && uuchar[*p]) { + data->code = ARCHIVE_FILTER_UU; + data->name = "uu"; return (firstline+30); + } } else if (l == 13) { + int bid = 0; + /* "begin-base64 " */ while (len > 0) { if (!base64[*p++]) @@ -339,9 +374,19 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *b, len--; } if (len == 0) - return (firstline+30); + bid = firstline + 30; if (len == 4 && memcmp(p, "====", 4) == 0) - return (firstline+40); + bid = firstline + 40; + if (bid > 0) { +#if ARCHIVE_VERSION_NUMBER < 4000000 + data->code = ARCHIVE_FILTER_UU; + data->name = "uu"; +#else + data->code = ARCHIVE_FILTER_B64; + data->name = "b64"; +#endif + return (bid); + } } return (0); @@ -357,11 +402,12 @@ uudecode_reader_vtable = { static int uudecode_bidder_init(struct archive_read_filter *f) { + struct uu_bidder *data = f->bidder->data; struct uu *uu; void *out_buff; - f->code = ARCHIVE_FILTER_UU; - f->name = "uu"; + f->code = data->code; + f->name = data->name; uu = calloc(1, sizeof(*uu)); out_buff = malloc(OUT_BUFF_SIZE); @@ -383,6 +429,13 @@ uudecode_bidder_init(struct archive_read_filter *f) return (ARCHIVE_OK); } +static void +uudecode_bidder_free(struct archive_read_filter_bidder *b) +{ + free(b->data); + b->data = NULL; +} + static int uudecode_read_header(struct archive_read_filter *f, struct archive_entry *entry) { diff --git a/contrib/libarchive/libarchive/archive_read_support_format_7zip.c b/contrib/libarchive/libarchive/archive_read_support_format_7zip.c index 254e4a50a3d7..1d1c6217936b 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_7zip.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_7zip.c @@ -3944,6 +3944,22 @@ read_stream(struct archive_read *a, const void **buff, size_t size, return (get_uncompressed_data(a, buff, size, minimum)); } +/* Returns the name of a compressor codec, or NULL if not a compressor. */ +static const char * +compressor_name(int64_t codec) +{ + switch (codec) { + case _7Z_COPY: return ("Copy"); + case _7Z_LZMA: return ("LZMA"); + case _7Z_LZMA2: return ("LZMA2"); + case _7Z_DEFLATE: return ("Deflate"); + case _7Z_BZ2: return ("BZip2"); + case _7Z_PPMD: return ("PPMd"); + case _7Z_ZSTD: return ("Zstd"); + default: return (NULL); + } +} + static int setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, int header) @@ -4006,6 +4022,24 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, return (header ? ARCHIVE_FATAL : ARCHIVE_FAILED); } + /* + * 7-Zip can be asked to chain two compressors in one folder + * (e.g. -m0=LZMA2 -m1=LZMA2). This is slow and gains nothing. + * Our decoder intentionally only supports a compressor + * followed by an optional filter. + */ + if (folder->numCoders == 2 && !found_bcj2 && + compressor_name(folder->coders[0].codec) != NULL && + compressor_name(folder->coders[1].codec) != NULL) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "The %s is compressed twice with chained compressors " + "(%s and %s), which is not supported", cname, + compressor_name(folder->coders[0].codec), + compressor_name(folder->coders[1].codec)); + return (header ? ARCHIVE_FATAL : ARCHIVE_FAILED); + } + /* * Initialize a stream reader. */ diff --git a/contrib/libarchive/libarchive/archive_read_support_format_cpio.c b/contrib/libarchive/libarchive/archive_read_support_format_cpio.c index 9dba42218114..eb1ae982477a 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_cpio.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_cpio.c @@ -581,6 +581,10 @@ find_newc_header(struct archive_read *a) } p += 2; break; + case '7': + /* A header may start two bytes on. */ + p += 2; + break; case '0': p++; break; diff --git a/contrib/libarchive/libarchive/archive_read_support_format_iso9660.c b/contrib/libarchive/libarchive/archive_read_support_format_iso9660.c index 35f4c781bfae..2d95457061b7 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_iso9660.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_iso9660.c @@ -388,9 +388,9 @@ static int archive_read_format_iso9660_read_data(struct archive_read *, static int archive_read_format_iso9660_read_data_skip(struct archive_read *); static int archive_read_format_iso9660_read_header(struct archive_read *, struct archive_entry *); -static const char *build_pathname(struct archive_string *, struct file_info *, int); +static int build_pathname(struct archive_string *, struct file_info *, int); static int build_pathname_utf16be(unsigned char *, size_t, size_t *, - struct file_info *); + struct file_info *, int); #if DEBUG static void dump_isodirrec(FILE *, const unsigned char *isodirrec); #endif @@ -432,6 +432,7 @@ static void parse_rockridge_TF1(struct file_info *, *** 3986 LINES SKIPPED ***