From nobody Thu Jan 15 23:09:48 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 4dsdwr5RS2z6NKSV for ; Thu, 15 Jan 2026 23:09:48 +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 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4dsdwr2spmz3SQ5 for ; Thu, 15 Jan 2026 23:09:48 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1768518588; 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=bnqihhiN5+DoiKDwuUX63asbOSU/AL/czTVNiaofK9g=; b=pGFoZVieXYuPwrHryPOKN8nCNvUUpjL5QYPLM8I2Pb//gPgzDlZ3eIqQvRPEa98ZyijwWo BadqmZ/DbPMdjJDddsxK8EaoMvm5rx++p6dzzYfPpeE0zINda27oJcIaaWqwMJesw/50E9 gF8KoPTU/bWeNJ76F2quEnSRi/VvMhIltWod/5WTAV/+FoFfUvxFSvb6U9zaY+2qGyQd6/ ePF0zUetimSgg/asP/nWPEvalEP0Z7xQrHaKg6zqw4fKcLvpaobcfZSGijpNuSxWNmtskv aRgoryQXDotTMUSOnvsQMKrNI9SZJ7FOIdkPvjvZAryYV+xMVMc/x5NU6oEHvQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1768518588; 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=bnqihhiN5+DoiKDwuUX63asbOSU/AL/czTVNiaofK9g=; b=nzk/sWf3kDsXQKwp58C4KE5UhrJ2uuBKB3P/VZhtANG3+Ntnf1hFx2rOhLAF5+oJEZShLb Ki1wSu5CSHgX8uvY0kmm5E6pHEU593eqKl5/evNJfcP5N5j5B/G0QrNug2CiEt658AvTxp zUr9Mj1p3VcOrtSuy6mwon7zqyqYromBmt6p7/ouQEuhmTBWR1NZwp/90xJJxHY9G0EPHv OxKeGaSl4pVVC4R8/YwOprH3tp8EHs4mxMkxzW8txcnATZr6TEMPjd2NNf6z5KkcUID3W7 vE7MYgZznL4w+HdajEXMwxXxxLMiSJzdvAbFdzdAbe4RFMbhANSuL07K7KpBnA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1768518588; a=rsa-sha256; cv=none; b=k4FucEtwi1rf9z8SqbJZh1CMZuomJj5GxZrTaDwcHnDQ+wTAd0FDUFO8bBbSOg7WRf+/iz PdRt9A/Fti7rNSmHTDqpB+Js9XQsr6/6cEiPTEFfWuHwK6HfbXfPYvnU2Q9yOtLKQarZL0 QNU5ByVUI01NjraKEgOa9QSSb/VLIzdRMT60n0dLHrjb6DXiChWkcWWgrNeJ772tMJw7iz 4MaDijE+hrQnlWJZjJCw5s8op6UdSoEqoZ3eUsCe49ZCjy9zh75SytgW0p6hSSCuu7w5Ss x3HEuvqoYMjP6o0zXO7YdKy8TxrMi1DHlBfPu/An2o0YE2x7STKynx2Sr6U6sA== 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 4dsdwr1qtqzpYZ for ; Thu, 15 Jan 2026 23:09:48 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 33cad by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 15 Jan 2026 23:09:48 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Martin Matuska Subject: git: d2131c8276f3 - stable/13 - libarchive: merge from vendor branch List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org 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/13 X-Git-Reftype: branch X-Git-Commit: d2131c8276f3c05a521ce971b6dda194ab417adc Auto-Submitted: auto-generated Date: Thu, 15 Jan 2026 23:09:48 +0000 Message-Id: <696973bc.33cad.6e3b55aa@gitrepo.freebsd.org> The branch stable/13 has been updated by mm: URL: https://cgit.FreeBSD.org/src/commit/?id=d2131c8276f3c05a521ce971b6dda194ab417adc commit d2131c8276f3c05a521ce971b6dda194ab417adc Author: Martin Matuska AuthorDate: 2025-11-19 13:33:40 +0000 Commit: Martin Matuska CommitDate: 2026-01-15 21:25:45 +0000 libarchive: merge from vendor branch libarchive 3.8.3 Important bugfixes: #2753 lib: Create temporary files in the target directory #2768 lha: Fix for an out-of-bounds buffer overrun when using p[H_LEVEL_OFFSET] #2769 7-zip: Fix a buffer overrun when reading truncated 7zip headers #2771 lz4 and zstd: Support both lz4 and zstd data with leading skippable frames Obtained from: libarchive Vendor commit: 1368b08875351df8aa268237b882c8f4ceb0882d MFC after: 1 week (cherry picked from commit 007679a138089676aadc9a712277f4004403b905) --- contrib/libarchive/NEWS | 2 + contrib/libarchive/libarchive/archive.h | 4 +- contrib/libarchive/libarchive/archive_entry.h | 2 +- contrib/libarchive/libarchive/archive_entry_stat.3 | 2 +- .../libarchive/archive_read_disk_entry_from_file.c | 10 +- .../libarchive/archive_read_disk_posix.c | 10 +- .../libarchive/archive_read_support_filter_lz4.c | 82 +- .../libarchive/archive_read_support_filter_zstd.c | 67 +- .../libarchive/archive_read_support_format_7zip.c | 8 +- .../libarchive/archive_read_support_format_lha.c | 2 +- .../libarchive/archive_read_support_format_tar.c | 1 + .../libarchive/archive_read_support_format_zip.c | 28 +- contrib/libarchive/libarchive/archive_string.c | 20 + contrib/libarchive/libarchive/archive_string.h | 4 + .../libarchive/archive_write_disk_posix.c | 20 +- .../libarchive/archive_write_open_filename.c | 2 + contrib/libarchive/libarchive/module.modulemap | 34 + .../libarchive/test/test_archive_string.c | 38 + .../libarchive/libarchive/test/test_compat_lz4.c | 2 + .../test_compat_lz4_skippable_frames_B4.tar.lz4.uu | 6739 ++++++++++++++++++++ .../test/test_read_format_7zip_issue2765.7z.uu | 5 + .../test/test_read_format_7zip_issue2765.c | 51 + .../libarchive/tar/test/test_option_safe_writes.c | 1 + contrib/libarchive/tar/util.c | 5 +- contrib/libarchive/test_utils/test_main.c | 27 +- lib/libarchive/tests/Makefile | 3 + 26 files changed, 7109 insertions(+), 60 deletions(-) diff --git a/contrib/libarchive/NEWS b/contrib/libarchive/NEWS index f2dd4102fa04..971ae8e441e1 100644 --- a/contrib/libarchive/NEWS +++ b/contrib/libarchive/NEWS @@ -1,3 +1,5 @@ +Nov 17, 2026: libarchive 3.8.3 released + Oct 15, 2026: libarchive 3.8.2 released Jun 01, 2026: libarchive 3.8.1 released diff --git a/contrib/libarchive/libarchive/archive.h b/contrib/libarchive/libarchive/archive.h index 98d7674e18f1..9794dced6ca9 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 3008002 +#define ARCHIVE_VERSION_NUMBER 3008003 #include #include /* for wchar_t */ @@ -177,7 +177,7 @@ __LA_DECL int archive_version_number(void); /* * Textual name/version of the library, useful for version displays. */ -#define ARCHIVE_VERSION_ONLY_STRING "3.8.2" +#define ARCHIVE_VERSION_ONLY_STRING "3.8.3" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); diff --git a/contrib/libarchive/libarchive/archive_entry.h b/contrib/libarchive/libarchive/archive_entry.h index 344f33bffac2..924b67a301cf 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 3008002 +#define ARCHIVE_VERSION_NUMBER 3008003 /* * Note: archive_entry.h is for use outside of libarchive; the diff --git a/contrib/libarchive/libarchive/archive_entry_stat.3 b/contrib/libarchive/libarchive/archive_entry_stat.3 index 29a53f75607f..2f4a1920eb64 100644 --- a/contrib/libarchive/libarchive/archive_entry_stat.3 +++ b/contrib/libarchive/libarchive/archive_entry_stat.3 @@ -207,7 +207,7 @@ for setting is recommended. The function .Fn archive_entry_size returns the file size, if it has been set, and 0 otherwise. -.Fn archive_entry_size +.Fn archive_entry_size_is_set can be used to query that status. .Fn archive_entry_set_size and diff --git a/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c b/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c index 42af4034b07e..121af19872e9 100644 --- a/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c +++ b/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c @@ -358,12 +358,10 @@ setup_mac_metadata(struct archive_read_disk *a, return (ARCHIVE_OK); archive_string_init(&tempfile); - if (__archive_get_tempdir(&tempfile) != ARCHIVE_OK) { - ret = ARCHIVE_WARN; - goto cleanup; - } - archive_strcat(&tempfile, "tar.md.XXXXXX"); - tempfd = mkstemp(tempfile.s); + archive_strcpy(&tempfile, name); + archive_string_dirname(&tempfile); + archive_strcat(&tempfile, "/tar.XXXXXXXX"); + tempfd = __archive_mkstemp(tempfile.s); if (tempfd < 0) { archive_set_error(&a->archive, errno, "Could not open extended attribute file"); diff --git a/contrib/libarchive/libarchive/archive_read_disk_posix.c b/contrib/libarchive/libarchive/archive_read_disk_posix.c index 54a8e66188f8..7cd292f259ff 100644 --- a/contrib/libarchive/libarchive/archive_read_disk_posix.c +++ b/contrib/libarchive/libarchive/archive_read_disk_posix.c @@ -107,6 +107,8 @@ #define O_CLOEXEC 0 #endif +#define MAX_FILESYSTEM_ID 1000000 + #if defined(__hpux) && !defined(HAVE_DIRFD) #define dirfd(x) ((x)->__dd_fd) #define HAVE_DIRFD @@ -1412,8 +1414,12 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) * This is the new filesystem which we have to generate a new ID for. */ fid = t->max_filesystem_id++; + if (fid > MAX_FILESYSTEM_ID) { + archive_set_error(&a->archive, ENOMEM, "Too many filesystems"); + return (ARCHIVE_FATAL); + } if (t->max_filesystem_id > t->allocated_filesystem) { - size_t s; + int s; void *p; s = t->max_filesystem_id * 2; @@ -1693,8 +1699,6 @@ setup_current_filesystem(struct archive_read_disk *a) #endif t->current_filesystem->noatime = 0; - /* Set maximum filename length. */ - t->current_filesystem->name_max = svfs.f_namemax; return (ARCHIVE_OK); } diff --git a/contrib/libarchive/libarchive/archive_read_support_filter_lz4.c b/contrib/libarchive/libarchive/archive_read_support_filter_lz4.c index 760e6d938d2a..144572ef2362 100644 --- a/contrib/libarchive/libarchive/archive_read_support_filter_lz4.c +++ b/contrib/libarchive/libarchive/archive_read_support_filter_lz4.c @@ -49,9 +49,12 @@ #include "archive_xxhash.h" #define LZ4_MAGICNUMBER 0x184d2204 -#define LZ4_SKIPPABLED 0x184d2a50 #define LZ4_LEGACY 0x184c2102 +// Note: LZ4 and zstd share the same skippable frame format with the same magic numbers. +#define LZ4_SKIPPABLE_START 0x184D2A50 +#define LZ4_SKIPPABLE_MASK 0xFFFFFFF0 + #if defined(HAVE_LIBLZ4) struct private_data { enum { SELECT_STREAM, @@ -141,19 +144,67 @@ lz4_reader_bid(struct archive_read_filter_bidder *self, { const unsigned char *buffer; ssize_t avail; - int bits_checked; - uint32_t number; + int bits_checked = 0; + ssize_t min_lz4_archive_size = 11; + + // LZ4 skippable frames contain a 4 byte magic number followed by + // a 4 byte frame data size, then that number of bytes of data. Regular + // frames contain a 4 byte magic number followed by a 2-14 byte frame + // header, some data, and a 3 byte end marker. + ssize_t min_lz4_frame_size = 8; + + ssize_t offset_in_buffer = 0; + ssize_t max_lookahead = 64 * 1024; - (void)self; /* UNUSED */ + (void)self; // UNUSED - /* Minimal lz4 archive is 11 bytes. */ - buffer = __archive_read_filter_ahead(filter, 11, &avail); + // Zstd and LZ4 skippable frame magic numbers are identical. To + // differentiate these two, we need to look for a non-skippable + // frame. + + // Minimal lz4 archive is 11 bytes. + buffer = __archive_read_filter_ahead(filter, min_lz4_archive_size, &avail); if (buffer == NULL) return (0); - /* First four bytes must be LZ4 magic numbers. */ - bits_checked = 0; - if ((number = archive_le32dec(buffer)) == LZ4_MAGICNUMBER) { + uint32_t magic_number = archive_le32dec(buffer); + + while ((magic_number & LZ4_SKIPPABLE_MASK) == LZ4_SKIPPABLE_START) { + + offset_in_buffer += 4; // Skip over the magic number + + // Ensure that we can read another 4 bytes. + if (offset_in_buffer + 4 > avail) { + buffer = __archive_read_filter_ahead(filter, offset_in_buffer + 4, &avail); + if (buffer == NULL) + return (0); + } + + uint32_t frame_data_size = archive_le32dec(buffer + offset_in_buffer); + + // Skip over the 4 frame data size bytes, plus the value stored there. + offset_in_buffer += 4 + frame_data_size; + + // There should be at least one more frame if this is LZ4 data. + if (offset_in_buffer + min_lz4_frame_size > avail) { // TODO: should this be >= ? + if (offset_in_buffer + min_lz4_frame_size > max_lookahead) + return (0); + + buffer = __archive_read_filter_ahead(filter, offset_in_buffer + min_lz4_frame_size, &avail); + if (buffer == NULL) + return (0); + } + + magic_number = archive_le32dec(buffer + offset_in_buffer); + } + + // We have skipped over any skippable frames. Either a regular LZ4 frame + // follows, or this isn't LZ4 data. + + bits_checked = offset_in_buffer; + buffer = buffer + offset_in_buffer; + + if (magic_number == LZ4_MAGICNUMBER) { unsigned char flag, BD; bits_checked += 32; @@ -175,11 +226,16 @@ lz4_reader_bid(struct archive_read_filter_bidder *self, if (BD & ~0x70) return (0); bits_checked += 8; - } else if (number == LZ4_LEGACY) { + + return (bits_checked); + } + + if (magic_number == LZ4_LEGACY) { bits_checked += 32; + return (bits_checked); } - - return (bits_checked); + + return (0); } #if !defined(HAVE_LIBLZ4) @@ -342,7 +398,7 @@ lz4_filter_read(struct archive_read_filter *self, const void **p) return lz4_filter_read_default_stream(self, p); else if (number == LZ4_LEGACY) return lz4_filter_read_legacy_stream(self, p); - else if ((number & ~0xF) == LZ4_SKIPPABLED) { + else if ((number & LZ4_SKIPPABLE_MASK) == LZ4_SKIPPABLE_START) { read_buf = __archive_read_filter_ahead( self->upstream, 4, NULL); if (read_buf == NULL) { diff --git a/contrib/libarchive/libarchive/archive_read_support_filter_zstd.c b/contrib/libarchive/libarchive/archive_read_support_filter_zstd.c index 9a1dd71abdf6..da7c540dbcd9 100644 --- a/contrib/libarchive/libarchive/archive_read_support_filter_zstd.c +++ b/contrib/libarchive/libarchive/archive_read_support_filter_zstd.c @@ -110,24 +110,67 @@ zstd_bidder_bid(struct archive_read_filter_bidder *self, { const unsigned char *buffer; ssize_t avail; - unsigned prefix; - /* Zstd frame magic values */ - unsigned zstd_magic = 0xFD2FB528U; - unsigned zstd_magic_skippable_start = 0x184D2A50U; - unsigned zstd_magic_skippable_mask = 0xFFFFFFF0; + // Zstandard skippable frames contain a 4 byte magic number followed by + // a 4 byte frame data size, then that number of bytes of data. Regular + // frames contain a 4 byte magic number followed by a 2-14 byte frame + // header, some data, and a 3 byte end marker. + ssize_t min_zstd_frame_size = 8; - (void) self; /* UNUSED */ + ssize_t offset_in_buffer = 0; + ssize_t max_lookahead = 64 * 1024; - buffer = __archive_read_filter_ahead(filter, 4, &avail); + // Zstd regular frame magic number. + uint32_t zstd_magic = 0xFD2FB528U; + + // Note: Zstd and LZ4 skippable frame magic numbers are identical. + // To differentiate these two, we need to look for a non-skippable + // frame. + uint32_t zstd_magic_skippable_start = 0x184D2A50; + uint32_t zstd_magic_skippable_mask = 0xFFFFFFF0; + + (void) self; // UNUSED + + buffer = __archive_read_filter_ahead(filter, min_zstd_frame_size, &avail); if (buffer == NULL) return (0); - prefix = archive_le32dec(buffer); - if (prefix == zstd_magic) - return (32); - if ((prefix & zstd_magic_skippable_mask) == zstd_magic_skippable_start) - return (32); + uint32_t magic_number = archive_le32dec(buffer); + + while ((magic_number & zstd_magic_skippable_mask) == zstd_magic_skippable_start) { + + offset_in_buffer += 4; // Skip over the magic number + + // Ensure that we can read another 4 bytes. + if (offset_in_buffer + 4 > avail) { + buffer = __archive_read_filter_ahead(filter, offset_in_buffer + 4, &avail); + if (buffer == NULL) + return (0); + } + + uint32_t frame_data_size = archive_le32dec(buffer + offset_in_buffer); + + // Skip over the 4 frame data size bytes, plus the value stored there. + offset_in_buffer += 4 + frame_data_size; + + // There should be at least one more frame if this is zstd data. + if (offset_in_buffer + min_zstd_frame_size > avail) { + if (offset_in_buffer + min_zstd_frame_size > max_lookahead) + return (0); + + buffer = __archive_read_filter_ahead(filter, offset_in_buffer + min_zstd_frame_size, &avail); + if (buffer == NULL) + return (0); + } + + magic_number = archive_le32dec(buffer + offset_in_buffer); + } + + // We have skipped over any skippable frames. Either a regular zstd frame + // follows, or this isn't zstd data. + + if (magic_number == zstd_magic) + return (offset_in_buffer + 4); return (0); } diff --git a/contrib/libarchive/libarchive/archive_read_support_format_7zip.c b/contrib/libarchive/libarchive/archive_read_support_format_7zip.c index 595462733104..330d5515dd50 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_7zip.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_7zip.c @@ -744,6 +744,7 @@ find_elf_data_sec(struct archive_read *a) const char *h; char big_endian, format_64; ssize_t bytes, min_addr = SFX_MIN_ADDR; + ssize_t request; uint64_t e_shoff, strtab_offset, strtab_size; uint16_t e_shentsize, e_shnum, e_shstrndx; uint16_t (*dec16)(const void *); @@ -796,7 +797,12 @@ find_elf_data_sec(struct archive_read *a) if (__archive_read_seek(a, e_shoff, SEEK_SET) < 0) { break; } - h = __archive_read_ahead(a, (size_t)e_shnum * (size_t)e_shentsize, NULL); + if (format_64) { + request = (size_t)e_shnum * (size_t)e_shentsize + 0x28; + } else { + request = (size_t)e_shnum * (size_t)e_shentsize + 0x18; + } + h = __archive_read_ahead(a, request, &bytes); if (h == NULL) { break; } diff --git a/contrib/libarchive/libarchive/archive_read_support_format_lha.c b/contrib/libarchive/libarchive/archive_read_support_format_lha.c index 2a84ad9dd307..abf8b8799636 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_lha.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_lha.c @@ -689,7 +689,7 @@ archive_read_format_lha_read_header(struct archive_read *a, * a pathname and a symlink has '\' character, a directory * separator in DOS/Windows. So we should convert it to '/'. */ - if (p[H_LEVEL_OFFSET] == 0) + if (lha->level == 0) lha_replace_path_separator(lha, entry); archive_entry_set_mode(entry, lha->mode); diff --git a/contrib/libarchive/libarchive/archive_read_support_format_tar.c b/contrib/libarchive/libarchive/archive_read_support_format_tar.c index eeb2c725f6eb..98f7d699570a 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_tar.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_tar.c @@ -2311,6 +2311,7 @@ pax_attribute_read_number(struct archive_read *a, size_t value_length, int64_t * archive_string_init(&as); r = read_bytes_to_string(a, &as, value_length, &unconsumed); if (tar_flush_unconsumed(a, &unconsumed) != ARCHIVE_OK) { + *result = 0; return (ARCHIVE_FATAL); } if (r < ARCHIVE_OK) { diff --git a/contrib/libarchive/libarchive/archive_read_support_format_zip.c b/contrib/libarchive/libarchive/archive_read_support_format_zip.c index 9abd55709e3f..0c86ce935e26 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_zip.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_zip.c @@ -78,6 +78,12 @@ #include "archive_crc32.h" #endif +/* length of local file header, not including filename and extra */ +#define ZIP_LOCHDR_LEN 30U + +/* maximum length of Mac metadata in MiB */ +#define ZIP_MAX_METADATA 10U + struct zip_entry { struct archive_rb_node node; struct zip_entry *next; @@ -933,7 +939,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, zip->init_default_conversion = 1; } - if ((p = __archive_read_ahead(a, 30, NULL)) == NULL) { + if ((p = __archive_read_ahead(a, ZIP_LOCHDR_LEN, NULL)) == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated ZIP file header"); return (ARCHIVE_FATAL); @@ -969,7 +975,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, filename_length = archive_le16dec(p + 26); extra_length = archive_le16dec(p + 28); - __archive_read_consume(a, 30); + __archive_read_consume(a, ZIP_LOCHDR_LEN); /* Read the filename. */ if ((h = __archive_read_ahead(a, filename_length, NULL)) == NULL) { @@ -3637,7 +3643,7 @@ read_eocd(struct zip *zip, const char *p, int64_t current_offset) { uint16_t disk_num; uint32_t cd_size, cd_offset; - + disk_num = archive_le16dec(p + 4); cd_size = archive_le32dec(p + 12); cd_offset = archive_le32dec(p + 16); @@ -4097,7 +4103,7 @@ zip_get_local_file_header_size(struct archive_read *a, size_t extra) const char *p; ssize_t filename_length, extra_length; - if ((p = __archive_read_ahead(a, extra + 30, NULL)) == NULL) { + if ((p = __archive_read_ahead(a, extra + ZIP_LOCHDR_LEN, NULL)) == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated ZIP file header"); return (ARCHIVE_WARN); @@ -4111,7 +4117,7 @@ zip_get_local_file_header_size(struct archive_read *a, size_t extra) filename_length = archive_le16dec(p + 26); extra_length = archive_le16dec(p + 28); - return (30 + filename_length + extra_length); + return (ZIP_LOCHDR_LEN + filename_length + extra_length); } static int @@ -4148,16 +4154,16 @@ zip_read_mac_metadata(struct archive_read *a, struct archive_entry *entry, return (ARCHIVE_WARN); } - if (rsrc->uncompressed_size > (4 * 1024 * 1024)) { + if (rsrc->uncompressed_size > ZIP_MAX_METADATA * 1048576U) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Mac metadata is too large: %jd > 4M bytes", - (intmax_t)rsrc->uncompressed_size); + "Mac metadata is too large: %jd > %u MiB", + (intmax_t)rsrc->uncompressed_size, ZIP_MAX_METADATA); return (ARCHIVE_WARN); } - if (rsrc->compressed_size > (4 * 1024 * 1024)) { + if (rsrc->compressed_size > ZIP_MAX_METADATA * 1048576U) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Mac metadata is too large: %jd > 4M bytes", - (intmax_t)rsrc->compressed_size); + "Mac metadata is too large: %jd > %u MiB", + (intmax_t)rsrc->compressed_size, ZIP_MAX_METADATA); return (ARCHIVE_WARN); } diff --git a/contrib/libarchive/libarchive/archive_string.c b/contrib/libarchive/libarchive/archive_string.c index 3bb978335eb8..740308b6e4e3 100644 --- a/contrib/libarchive/libarchive/archive_string.c +++ b/contrib/libarchive/libarchive/archive_string.c @@ -2054,6 +2054,26 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n, return (r); } +struct archive_string * +archive_string_dirname(struct archive_string *as) +{ + /* strip trailing separators */ + while (as->length > 1 && as->s[as->length - 1] == '/') + as->length--; + /* strip final component */ + while (as->length > 0 && as->s[as->length - 1] != '/') + as->length--; + /* empty path -> cwd */ + if (as->length == 0) + return (archive_strcat(as, ".")); + /* strip separator(s) */ + while (as->length > 1 && as->s[as->length - 1] == '/') + as->length--; + /* terminate */ + as->s[as->length] = '\0'; + return (as); +} + #if HAVE_ICONV /* diff --git a/contrib/libarchive/libarchive/archive_string.h b/contrib/libarchive/libarchive/archive_string.h index e8987867d3ce..d5f5c03aca30 100644 --- a/contrib/libarchive/libarchive/archive_string.h +++ b/contrib/libarchive/libarchive/archive_string.h @@ -192,6 +192,10 @@ void archive_string_vsprintf(struct archive_string *, const char *, void archive_string_sprintf(struct archive_string *, const char *, ...) __LA_PRINTF(2, 3); +/* Equivalent to dirname(3) */ +struct archive_string * +archive_string_dirname(struct archive_string *); + /* Translates from MBS to Unicode. */ /* Returns non-zero if conversion failed in any way. */ int archive_wstring_append_from_mbs(struct archive_wstring *dest, diff --git a/contrib/libarchive/libarchive/archive_write_disk_posix.c b/contrib/libarchive/libarchive/archive_write_disk_posix.c index aeb27e1270ad..d69f041dde7e 100644 --- a/contrib/libarchive/libarchive/archive_write_disk_posix.c +++ b/contrib/libarchive/libarchive/archive_write_disk_posix.c @@ -412,12 +412,14 @@ static ssize_t _archive_write_disk_data_block(struct archive *, const void *, static int la_mktemp(struct archive_write_disk *a) { + struct archive_string *tmp = &a->_tmpname_data; int oerrno, fd; mode_t mode; - archive_string_empty(&a->_tmpname_data); - archive_string_sprintf(&a->_tmpname_data, "%s.XXXXXX", a->name); - a->tmpname = a->_tmpname_data.s; + archive_strcpy(tmp, a->name); + archive_string_dirname(tmp); + archive_strcat(tmp, "/tar.XXXXXXXX"); + a->tmpname = tmp->s; fd = __archive_mkstemp(a->tmpname); if (fd == -1) @@ -4287,8 +4289,10 @@ create_tempdatafork(struct archive_write_disk *a, const char *pathname) int tmpfd; archive_string_init(&tmpdatafork); - archive_strcpy(&tmpdatafork, "tar.md.XXXXXX"); - tmpfd = mkstemp(tmpdatafork.s); + archive_strcpy(&tmpdatafork, pathname); + archive_string_dirname(&tmpdatafork); + archive_strcat(&tmpdatafork, "/tar.XXXXXXXX"); + tmpfd = __archive_mkstemp(tmpdatafork.s); if (tmpfd < 0) { archive_set_error(&a->archive, errno, "Failed to mkstemp"); @@ -4367,8 +4371,10 @@ set_mac_metadata(struct archive_write_disk *a, const char *pathname, * silly dance of writing the data to disk just so that * copyfile() can read it back in again. */ archive_string_init(&tmp); - archive_strcpy(&tmp, "tar.mmd.XXXXXX"); - fd = mkstemp(tmp.s); + archive_strcpy(&tmp, pathname); + archive_string_dirname(&tmp); + archive_strcat(&tmp, "/tar.XXXXXXXX"); + fd = __archive_mkstemp(tmp.s); if (fd < 0) { archive_set_error(&a->archive, errno, diff --git a/contrib/libarchive/libarchive/archive_write_open_filename.c b/contrib/libarchive/libarchive/archive_write_open_filename.c index 7d0f9bde1dbb..430de21fde14 100644 --- a/contrib/libarchive/libarchive/archive_write_open_filename.c +++ b/contrib/libarchive/libarchive/archive_write_open_filename.c @@ -191,6 +191,8 @@ file_open(struct archive *a, void *client_data) archive_set_error(a, errno, "Couldn't stat '%s'", mbs); else archive_set_error(a, errno, "Couldn't stat '%ls'", wcs); + close(mine->fd); + mine->fd = -1; return (ARCHIVE_FATAL); } diff --git a/contrib/libarchive/libarchive/module.modulemap b/contrib/libarchive/libarchive/module.modulemap new file mode 100644 index 000000000000..70f70fc3a1a2 --- /dev/null +++ b/contrib/libarchive/libarchive/module.modulemap @@ -0,0 +1,34 @@ +/* + * Clang Module Map for libarchive + * + * What this is: + * This file tells the Clang compiler how to treat libarchive as a "module" - + * a self-contained unit of code that can be imported all at once instead of + * including individual header files. Think of it like a package definition. + * + * How it works: + * - When you write `@import CArchive` (Objective-C) or `import CArchive` (Swift), + * the compiler uses this file to know which headers belong to libarchive + * - Instead of processing each #include separately, the compiler can load a + * pre-compiled version of the entire library, making builds faster + * - This also provides better dependency tracking and can catch issues like + * conflicting macro definitions between libraries + * + * When to update: + * Update this file whenever: + * - New public header files are added to libarchive's libarchive/ directory + * - Public headers are removed or renamed + * - The library's API structure changes significantly + * + * You typically don't need to update this for: + * - Internal implementation changes + * - Private/internal header modifications + * - Documentation updates + * + * NOTE: This only affects projects using Clang with modules enabled. Traditional + * #include-based builds will continue to work normally with or without this file. + */ +module CArchive { + header "archive.h" + header "archive_entry.h" +} diff --git a/contrib/libarchive/libarchive/test/test_archive_string.c b/contrib/libarchive/libarchive/test/test_archive_string.c index 30f7a800eae8..bf822c0d5e82 100644 --- a/contrib/libarchive/libarchive/test/test_archive_string.c +++ b/contrib/libarchive/libarchive/test/test_archive_string.c @@ -353,6 +353,43 @@ test_archive_string_sprintf(void) archive_string_free(&s); } +static void +test_archive_string_dirname(void) +{ + static struct pair { const char *str, *exp; } pairs[] = { + { "", "." }, + { "/", "/" }, + { "//", "/" }, + { "///", "/" }, + { "./", "." }, + { ".", "." }, + { "..", "." }, + { "foo", "." }, + { "foo/", "." }, + { "foo//", "." }, + { "foo/bar", "foo" }, + { "foo/bar/", "foo" }, + { "foo/bar//", "foo" }, + { "foo//bar", "foo" }, + { "foo//bar/", "foo" }, + { "foo//bar//", "foo" }, + { "/foo", "/" }, + { "//foo", "/" }, + { "//foo/", "/" }, + { "//foo//", "/" }, + { 0 }, + }; + struct pair *pair; + struct archive_string s; + + archive_string_init(&s); + for (pair = pairs; pair->str; pair++) { + archive_strcpy(&s, pair->str); + archive_string_dirname(&s); + assertEqualString(pair->exp, s.s); + } +} + DEFINE_TEST(test_archive_string) { test_archive_string_ensure(); @@ -364,6 +401,7 @@ DEFINE_TEST(test_archive_string) test_archive_string_concat(); test_archive_string_copy(); test_archive_string_sprintf(); + test_archive_string_dirname(); } static const char *strings[] = diff --git a/contrib/libarchive/libarchive/test/test_compat_lz4.c b/contrib/libarchive/libarchive/test/test_compat_lz4.c index 9e309a9fbd20..8ab9208b0918 100644 --- a/contrib/libarchive/libarchive/test/test_compat_lz4.c +++ b/contrib/libarchive/libarchive/test/test_compat_lz4.c @@ -98,6 +98,8 @@ DEFINE_TEST(test_compat_lz4) verify("test_compat_lz4_3.tar.lz4.uu", n); /* This sample has been compressed with -B4 option. */ verify("test_compat_lz4_B4.tar.lz4.uu", n2); + /* This sample has been compresed with -B4, and has two skippable frames at the start. */ + verify("test_compat_lz4_skippable_frames_B4.tar.lz4.uu", n2); /* This sample has been compressed with -B5 option. */ verify("test_compat_lz4_B5.tar.lz4.uu", n2); /* This sample has been compressed with -B6 option. */ diff --git a/contrib/libarchive/libarchive/test/test_compat_lz4_skippable_frames_B4.tar.lz4.uu b/contrib/libarchive/libarchive/test/test_compat_lz4_skippable_frames_B4.tar.lz4.uu new file mode 100644 index 000000000000..f45b1ac8f8dd --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_compat_lz4_skippable_frames_B4.tar.lz4.uu @@ -0,0 +1,6739 @@ +begin 664 test_compat_lz4_skippable_frames_B4.tar.lz4.uu +M4"I-&`````!1*DT8"@`````!`@,$!08'"`D$(DT89$"GE1$``&]X9FEL90`! +M`$OA,#`P-C0T(``P,#`W-C4(`"(P,A``(C(P`0#_!R`Q,C,U,S4U,S4Q,B`P +M,3(P,C,`(#"7`$L"`@"O=7-T87(`,#!C=0`<``$D!0'-U8V@G`%`J(&5X84D`0',Z(%,R`U1S;6%L;!4`!#X!`+X!\`!A +M="!Y;W4@;6%Y(&9I;F30`C%F=6PO`@9%`%$O;6EN:84!$6'C`5%A8W0@2#R`@!3!%`N"@I4:)T!,'`M;`P$HB!D:7)E +M8W1O@`K1#3U!924Y'("T@=U$!8F-A;B!D;Y\` +M,W1H:2D`\@))3E-404Q,("T@:6YS=&%L;'4```T`(7)U*@(#*0`#0`41+3P` +M`94```\!`4D!@&9I9W5R92`MS@`!#``"1`"U'2(`#!P=71>`H$@(F-M86ME(B0#:60@=&]O +M;$T``E8!!NL#`2D!,2!I;DP!#VT!`3!AM``,D +M!`"3``!.`/4!+F%M+"!A8VQO8V%L+FTT+.$`0&4N86/_```"`!(M5``D=&^H +M``RB!+(L(&]N;'D@;F5E9'P`,6UA:?8!(V5R7`$%<``D:6YD`/(#+F@N:6X* +M"2T@=&5M<&QA=&5S9P`18C0"`68!$V6U`&`*"D=U:63S`"@@1%0&!-(!`G4` +M`;P$2+8($-7,N-:H(`J\``!D# +M`/(`@&UA=',@=&%R +M+C54`0CQ!$%A8F]U4P4@P`(2PF!:&%R9"UT;RTP +M!@1;`0%'``!!`&%M;V1E``%4!%"`"X +M!!,BO0(R+F@BJ0"`:&4*2R"```[!P$C"4!A=71ODP8`_P(0><$",&5C=)D# +M$635``,<`@5X"1!F+``!MP91*B!'3E5U`0(U`B8@*`0+`!H`06QO;F=0!F)N +M86UE+``-J`0`9`X$J(%!/4TE8("`-`5L` +M`A``,G!A>%H)`ED'`W@"!R$`P&]C=&5T+6]R:65N=!<$('!I?@G&*B!35E(T +M($%30TE)%``"4P`/,@`%84)I;F%R>2X`P"`H8FEG+65N9&EA;J(!8VQI='1L +M91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"$2AX""!O<,L#P&%L(%)O8VMR +M:61G944`8DIO;&EE="D!`>\!`DD`-%I)4%8#!$``('5N3@DPFEP/@$Q:6]N%0!=8GII<#(6``1\`4TO3%I7'0"B;'IM82P@;'II +MD# +M`*4#(71EVPAA.@H*("H@+1`0:2`*<&AE879I;'G\"#9E86VU!0(1"W`N("!4 +M:&5R-!$S(&YOX@<`@@(#WP@`DP1!(&EN+;F4@``%1`0.;`")E;LD!!RT``'P`"W$`*&1E$0`# +MQ@(1+/```H```(T.`)8!`!8!`$``,&%G8?,/`?$)D6-OP,1<#4`T6%T979E +M$P$/`P),%@`&"1!G5180:2(3`2(`!4H``.,3(6-EA0`A3VZ0`QMEPP`"Y`(R +M<')O.@$!A0%18W1L>2W,`))E9"!O=71P=73O`@!@!/$#;V)J96-T+7-T>6QE +M(&%P<')OR`,`^10"^@#0=&\@:&%V92!M=6QT:<,3!*D``@$$`+D(52!O<&5N +MG@`3(!40`&H0``H!$6DA"&-I=',@(D`\`!(BO0012!FP"`,D*`2L`,VEN("#B)A;N@"`*4'!C0*$"QC`$!D97-P +MH@``;`0!Y`,`7,N"B05$6:X#0]D&O______________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_________________________________________UM09"!O2!O9B<`H69O;&QO=VEN9SJ&`(%U=65N +M8V]D90T`16=Z:7#A`#%I;VX5`%UB>FEP,A8`!`FUA+"!L +M>FEP+!0!*7AZ(P#!"DYO=&5S(&%B;W5TE`!R;&EB=$`\"YT96-T=7)E +M.@H*("H@5&AI0`&EP#@:7,@9&5S:6=N +M960@=&]>`61E>'1E;F1>`3AN97?@``#S`#(*("#.`!!V<@$`]`$22!R97%U:7)E;65N=+(`,G1H80D!`BL`("!BCP&0(')E861A8FQEH@!! +M=W)I=`P`$&$,`0($`0!H``([`$5E86-H;P``E@(3>4,`4&EN9&5PJ@`B;G1_ +M`$%R92!A!`"4=&EC;&5S(&]N@0$#KP+P`2!7:6MI(&5X<&QA:6YI;F?)`#!H +M;W?X``+U``$N("!)9B!Y;W4@9&]N)^P!`+8`\0)I8VET;'D@ +M:6YV;VME(&$@<.L`@'5L87(@9F5A60)`("AS=2\!&7,<`A!AZ0`'+0`$YP,# +M(@("F0%P*2P@:70@=W``\``@9V5T('!U;&QE9"!I;BX^`"=);FX`-RP@:9X` +M`5$!`YL`(F5NR0$'+0``/@`+<0`H9&41``/&`A$L\``"@``B;F6.`@`6`0!` +M`&)A9V%I;G-'`J!C;W)R97-P;VYD)P0(20`-6@`">P,Q:65SPP`!;P.P86QS +M;R!R961U8V6;`C!E('.%`2-O9H@!`+,!$"UV`&%E9"!B:6X]`"`@:2P$@"!E +M;G9IP,1<#4`T6%T +M979E8!(71O(@`%2@!A="!O;F-EA0`A3VZ0`QMEPP`"Y`(R<')O +M.@$!A0%18W1L>2W,`))E9"!O=71P=73O`@!@!/$#;V)J96-T+7-T>6QE(&%P +M<')OR`,`H`4"^@#@=&\@:&%V92!M=6QT:7`E``.E`P(!!`!;!E4@;W!E;IX` +ML2`@8G-D=&%R('5SO`$`/06#;B!I=',@(D#E`!(BR`-&2!B=69F97(@;W*Y`@!E``1R +M`85A('-O8VME=#X#27=IP"`*`'`2L`,VEN +M("0#\`)N86UE('-A>7,N"E)%041-15``!^@&X2!B=6YD;&4N +M"@I1=65S^@*@/R`@27-S=65S/U(`URH@:'1T<#HO+W=W=RX@!S!O3``!( +M`1!HN`*#9F]R(&]N9V]8!Q@@9`!P9&5V96QO<#P%<2P@:6YC;'6]!4!D;V-U +M%``!K`@!3@D`<0``.@`A;FM=`0!=``9S`%`@;6%I;`<"0FQI`<``$D!`)()`"<`4"H@97AA20!`8$(&YDT`(Q9G5L+P(&10`0+T,*`84! +M$6&>"E%A8W0@M``,D!`"3``!.`/``+F%M+"!A8VQO +M8V%L+FTT"0T#[0`P+F%C%P$``@`0+:("`)\`!*@``-D."*($$BP:#@#7"P!9 +M"Q!YR@4!]@$C97*N`05P`"1I;F0`@2YH+FEN"@DM]`<`H!`2=&%R +M+C54`0CQ!`4^$A%S8P0Q<&]PY0\#G`$$>P`(2PE`:&%R9!8,`3`&!%L!`4<` +M`(X!86UO9&5R;H\``.@!`+P'<"!V87)I86Y("0":!3!M86[X"T%P86=E.``` +M,0XD``'?`5=H+`#L' +M`2,)"=H1`,$",&5C=)D#$61A#0,<`@2#%"`@9@82`;<&`D$5!JH+)B`H!`L` +M6Q4@;&\O`#!I;&6M"R)S+!````4+$R`1``!C`%)S<&%RC0."P#``0#E%P$A"00(`0`` +M"@*<$`5+`0!U!`\&`0("@P$#OP,"O`(/'P,8,")R9:`-`!`6$2)'`P)/`,(L +M('=H:6-H('=I;&SK&`!P"``9!`-?`4!S(&5X+10``@(`N04$B1$""Q<#6A3`1!F+`"A#0#46-H86YG?@$W;6%T(0"P;V-T970M;W)I96X!`P!@`@$>`*%35E(T +M($%30TE)=`(!%``"4P`/,@`%84)I;F%R>2X`P"`H8FEG+65N9&EA;J(!8VQI +M='1L91$``OH`\0))4T\Y-C8P($-$+5)/32!I;;<"@"AW:71H(&]PRP/`86P@ +M4F]C:W)I9&=E10!B2F]L:65T*0$![P$"20`T6DE05@,$0`#`=6YC;VUPFEP/@$Q:6]N&`%=8GII<#(6``1\`4TO3%I7 +M'0"B;'IM82P@;'II&-E<$`%`+D%!&D"L"!T:&%T(')E<75IE@4G87C*`E(@ +M*&9O?P(-F5A;;4%X'-YU`P#P!`![``-S!`![ +M``&'"0&C`%0@;VYL>0H#`#@(`+(``1X#`*8$`@P"(2!B-PEQ4,`4&EN9&5PJ@`E +M;G0B`0`8"5!AP,1<#4`T6%T979E