git: 80c954a926c6 - stable/15 - libarchive: merge from vendor branch
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 03 Nov 2026 14:22:34 UTC
The branch stable/15 has been updated by mm:
URL: https://cgit.FreeBSD.org/src/commit/?id=80c954a926c6ac4a7dda462423fd732f4ce06f40
commit 80c954a926c6ac4a7dda462423fd732f4ce06f40
Author: Martin Matuska <mm@FreeBSD.org>
AuthorDate: 2026-10-31 23:39:49 +0000
Commit: Martin Matuska <mm@FreeBSD.org>
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 <filelist >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 <archive.out >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 <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.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 <errno.h>
#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#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 ***