git: 750cc0502912 - stable/15 - libarchive: merge from vendor branch

From: Martin Matuska <mm_at_FreeBSD.org>
Date: Mon, 24 Aug 2026 09:52:32 UTC
The branch stable/15 has been updated by mm:

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

commit 750cc050291298b462abd099191cb995057eb34e
Author:     Martin Matuska <mm@FreeBSD.org>
AuthorDate: 2026-07-30 08:13:34 +0000
Commit:     Martin Matuska <mm@FreeBSD.org>
CommitDate: 2026-08-24 09:20:52 +0000

    libarchive: merge from vendor branch
    
    libarchive 3.8.9
    
    ChangeLog:
    https://github.com/libarchive/libarchive/compare/v3.8.7...v3.8.9
    
    Obtained from:  libarchive
    Vendor commit:  27cbc7827172698143e440801fc0ba39ccb4f1f5
    MFC after:      2 weeks
    
    (cherry picked from commit 185becb1e1bd2657c156f78aeb52edac05ba5fb5)
---
 contrib/libarchive/FREEBSD-Xlist                   |     6 +
 contrib/libarchive/NEWS                            |     4 +
 contrib/libarchive/SECURITY.md                     |    19 +-
 .../github_actions/install-macos-dependencies.sh   |    22 -
 contrib/libarchive/cpio/cpio.c                     |    10 +-
 .../cpio/test/test_extract_cpio_absolute_paths.c   |     1 +
 contrib/libarchive/cpio/test/test_format_newc.c    |     2 +-
 contrib/libarchive/libarchive/archive.h            |     9 +-
 contrib/libarchive/libarchive/archive_acl.c        |   457 +-
 .../libarchive/libarchive/archive_acl_private.h    |     2 +
 .../libarchive/libarchive/archive_check_magic.c    |     1 +
 contrib/libarchive/libarchive/archive_cmdline.c    |    28 +-
 contrib/libarchive/libarchive/archive_crc32.h      |    71 +-
 contrib/libarchive/libarchive/archive_cryptor.c    |     4 +-
 .../libarchive/archive_cryptor_private.h           |    12 +-
 contrib/libarchive/libarchive/archive_digest.c     |    69 +-
 .../libarchive/libarchive/archive_digest_private.h |    12 +-
 contrib/libarchive/libarchive/archive_endian.h     |    41 +
 contrib/libarchive/libarchive/archive_entry.c      |    30 +-
 contrib/libarchive/libarchive/archive_entry.h      |     4 +-
 .../libarchive/archive_entry_link_resolver.c       |    19 +-
 .../libarchive/libarchive/archive_entry_sparse.c   |     5 +-
 .../libarchive/libarchive/archive_entry_strmode.c  |    45 +-
 .../libarchive/libarchive/archive_entry_xattr.c    |    10 +-
 contrib/libarchive/libarchive/archive_hmac.c       |     2 +-
 .../libarchive/libarchive/archive_hmac_private.h   |     2 +-
 contrib/libarchive/libarchive/archive_integer.h    |   267 +
 contrib/libarchive/libarchive/archive_match.c      |    45 +-
 contrib/libarchive/libarchive/archive_options.c    |    20 +-
 contrib/libarchive/libarchive/archive_pack_dev.c   |     2 +-
 contrib/libarchive/libarchive/archive_parse_date.c |    72 +-
 contrib/libarchive/libarchive/archive_pathmatch.c  |    54 +-
 contrib/libarchive/libarchive/archive_private.h    |    26 +
 contrib/libarchive/libarchive/archive_random.c     |    26 -
 contrib/libarchive/libarchive/archive_read.c       |   452 +-
 .../libarchive/archive_read_append_filter.c        |    82 +-
 .../libarchive/archive_read_data_into_fd.c         |    98 +-
 .../libarchive/archive_read_disk_entry_from_file.c |     7 +-
 .../libarchive/archive_read_disk_posix.c           |    21 +-
 .../archive_read_disk_set_standard_lookup.c        |     7 +-
 .../libarchive/libarchive/archive_read_filter.3    |     5 +-
 contrib/libarchive/libarchive/archive_read_open.3  |    16 +
 .../libarchive/libarchive/archive_read_open_fd.c   |     5 +-
 .../libarchive/libarchive/archive_read_open_file.c |     5 +-
 .../libarchive/archive_read_open_filename.c        |     7 +-
 .../libarchive/archive_read_open_memory.c          |     5 +-
 .../libarchive/libarchive/archive_read_private.h   |    15 +-
 .../libarchive/archive_read_support_filter_all.c   |    14 +-
 .../libarchive/archive_read_support_filter_bzip2.c |   149 +-
 .../archive_read_support_filter_compress.c         |   235 +-
 .../libarchive/archive_read_support_filter_grzip.c |    19 +-
 .../libarchive/archive_read_support_filter_gzip.c  |   223 +-
 .../libarchive/archive_read_support_filter_lrzip.c |    20 +-
 .../libarchive/archive_read_support_filter_lz4.c   |   432 +-
 .../libarchive/archive_read_support_filter_lzop.c  |   225 +-
 .../archive_read_support_filter_program.c          |   183 +-
 .../libarchive/archive_read_support_filter_rpm.c   |   251 +-
 .../libarchive/archive_read_support_filter_uu.c    |   269 +-
 .../libarchive/archive_read_support_filter_xz.c    |   299 +-
 .../libarchive/archive_read_support_filter_zstd.c  |   200 +-
 .../libarchive/archive_read_support_format_7zip.c  |  1374 +-
 .../libarchive/archive_read_support_format_all.c   |     2 +-
 .../libarchive/archive_read_support_format_ar.c    |   166 +-
 .../libarchive/archive_read_support_format_cab.c   |   887 +-
 .../libarchive/archive_read_support_format_cpio.c  |   167 +-
 .../archive_read_support_format_iso9660.c          |   228 +-
 .../libarchive/archive_read_support_format_lha.c   |   145 +-
 .../libarchive/archive_read_support_format_mtree.c |   122 +-
 .../libarchive/archive_read_support_format_rar.c   |   223 +-
 .../libarchive/archive_read_support_format_rar5.c  |  1265 +-
 .../libarchive/archive_read_support_format_raw.c   |    65 +-
 .../libarchive/archive_read_support_format_tar.c   |   349 +-
 .../libarchive/archive_read_support_format_warc.c  |   551 +-
 .../libarchive/archive_read_support_format_xar.c   |   443 +-
 .../libarchive/archive_read_support_format_zip.c   |   638 +-
 contrib/libarchive/libarchive/archive_string.c     |     7 +-
 contrib/libarchive/libarchive/archive_time.c       |    27 +-
 contrib/libarchive/libarchive/archive_util.3       |    35 +-
 contrib/libarchive/libarchive/archive_util.c       |    68 +-
 .../libarchive/archive_version_details.c           |    27 +-
 contrib/libarchive/libarchive/archive_write.c      |   115 +-
 .../libarchive/archive_write_add_filter.c          |     2 +-
 .../archive_write_add_filter_b64encode.c           |   121 +-
 .../libarchive/archive_write_add_filter_bzip2.c    |   204 +-
 .../libarchive/archive_write_add_filter_compress.c |   240 +-
 .../libarchive/archive_write_add_filter_grzip.c    |    68 +-
 .../libarchive/archive_write_add_filter_gzip.c     |   274 +-
 .../libarchive/archive_write_add_filter_lrzip.c    |    88 +-
 .../libarchive/archive_write_add_filter_lz4.c      |   486 +-
 .../libarchive/archive_write_add_filter_lzop.c     |   260 +-
 .../libarchive/archive_write_add_filter_program.c  |    81 +-
 .../libarchive/archive_write_add_filter_uuencode.c |   123 +-
 .../libarchive/archive_write_add_filter_xz.c       |   280 +-
 .../libarchive/archive_write_add_filter_zstd.c     |   272 +-
 .../libarchive/archive_write_disk_posix.c          |    83 +-
 .../archive_write_disk_set_standard_lookup.c       |     7 +-
 .../libarchive/libarchive/archive_write_filter.3   |     8 +
 .../libarchive/libarchive/archive_write_format.3   |     4 +-
 .../libarchive/libarchive/archive_write_private.h  |     4 +-
 .../libarchive/archive_write_set_format_7zip.c     |    64 +-
 .../libarchive/archive_write_set_format_ar.c       |    99 +-
 .../archive_write_set_format_cpio_binary.c         |    52 +-
 .../archive_write_set_format_cpio_newc.c           |    37 +-
 .../libarchive/archive_write_set_format_cpio_odc.c |    52 +-
 .../libarchive/archive_write_set_format_gnutar.c   |    47 +-
 .../libarchive/archive_write_set_format_iso9660.c  |   180 +-
 .../libarchive/archive_write_set_format_mtree.c    |   139 +-
 .../libarchive/archive_write_set_format_pax.c      |   258 +-
 .../libarchive/archive_write_set_format_raw.c      |     8 +-
 .../libarchive/archive_write_set_format_shar.c     |    77 +-
 .../libarchive/archive_write_set_format_ustar.c    |    23 +-
 .../libarchive/archive_write_set_format_v7tar.c    |    23 +-
 .../libarchive/archive_write_set_format_warc.c     |   550 +-
 .../libarchive/archive_write_set_format_xar.c      |   275 +-
 .../libarchive/archive_write_set_format_zip.c      |    64 +-
 .../libarchive/archive_write_set_options.3         |    28 +-
 contrib/libarchive/libarchive/libarchive-formats.5 |     2 +-
 .../libarchive/libarchive/test/read_open_memory.c  |     8 +-
 .../libarchive/test/test_acl_from_text_overread.c  |    98 +
 .../test/test_acl_nfs4_null_id_overflow.c          |   105 +
 .../libarchive/test/test_acl_nfs4_text.c           |   426 +
 .../libarchive/test/test_acl_posix1e_text.c        |   530 +
 .../libarchive/test/test_archive_match_path.c      |    16 +-
 .../libarchive/test/test_archive_parse_date.c      |    83 +-
 .../libarchive/test/test_archive_pathmatch.c       |    16 +
 .../libarchive/test/test_archive_pathmatch_oob.c   |   156 +
 .../test/test_archive_pathmatch_oob_bracket.bin.uu |     4 +
 .../test/test_archive_pathmatch_oob_strchr.bin.uu  |     8 +
 .../test/test_archive_read_close_twice.c           |    46 +-
 .../libarchive/test/test_archive_read_set_option.c |    68 -
 .../test/test_archive_read_set_options.c           |   150 +-
 .../test/test_archive_seek_data_unsupported.c      |    95 +
 .../libarchive/test/test_archive_string.c          |     1 +
 .../test/test_archive_string_conversion.c          |    14 +-
 .../test/test_archive_string_conversion_overread.c |    87 +
 .../test/test_archive_write_add_filter.c           |   208 +
 .../test/test_archive_write_add_filter_by_name.c   |     2 +-
 .../test/test_archive_write_set_format_by_name.c   |     2 +-
 .../test_archive_write_set_format_filter_by_ext.c  |     2 +-
 .../test/test_archive_write_set_format_option.c    |    66 -
 .../test/test_archive_write_set_option.c           |    68 -
 .../test/test_archive_write_set_options.c          |   150 +-
 .../libarchive/libarchive/test/test_compat_bzip2.c |     1 +
 .../libarchive/libarchive/test/test_compat_cpio.c  |     2 +-
 .../libarchive/libarchive/test/test_compat_gtar.c  |     4 +-
 .../libarchive/test/test_compat_gtar_large.c       |     2 +-
 .../libarchive/libarchive/test/test_compat_gzip.c  |     2 +-
 .../libarchive/libarchive/test/test_compat_lz4.c   |     4 +-
 .../libarchive/libarchive/test/test_compat_lzip.c  |     6 +-
 .../libarchive/libarchive/test/test_compat_lzma.c  |     2 +-
 .../libarchive/libarchive/test/test_compat_lzop.c  |     6 +-
 .../libarchive/libarchive/test/test_compat_mac.c   |     4 +-
 .../libarchive/test/test_compat_perl_archive_tar.c |     2 +-
 .../test/test_compat_plexus_archiver_tar.c         |     2 +-
 .../test/test_compat_solaris_pax_sparse.c          |     4 +-
 .../libarchive/test/test_compat_tar_directory.c    |     2 +-
 .../libarchive/test/test_compat_tar_hardlink.c     |     2 +-
 .../libarchive/libarchive/test/test_compat_xz.c    |     2 +-
 .../libarchive/libarchive/test/test_compat_zip.c   |    22 +-
 .../libarchive/libarchive/test/test_compat_zstd.c  |     2 +-
 contrib/libarchive/libarchive/test/test_entry.c    |    28 +
 contrib/libarchive/libarchive/test/test_fuzz.c     |     2 +-
 .../libarchive/test/test_fuzz_consumer.h           |   143 +
 .../test/test_gnutar_filename_encoding.c           |    59 +-
 .../libarchive/test/test_open_filename.c           |    23 +
 .../libarchive/test/test_pax_filename_encoding.c   |     8 +-
 .../libarchive/test/test_pax_xattr_header.c        |     8 +-
 .../test_read_data_into_fd_size_exceeds_declared.c |   119 +
 ...ta_into_fd_size_exceeds_declared_deflate.zip.uu |    23 +
 ...ata_into_fd_size_exceeds_declared_stored.zip.uu |     9 +
 .../libarchive/test/test_read_data_large.c         |    92 +
 .../test/test_read_disk_directory_traversals.c     |    38 +-
 ...ilter_option.c => test_read_files_compressed.c} |    48 +-
 .../test/test_read_files_compressed.part01.uu      |     4 +
 .../test/test_read_files_compressed.part02.uu      |     4 +
 .../libarchive/test/test_read_filter_compress.c    |     6 +-
 .../libarchive/test/test_read_filter_grzip.c       |     2 +-
 .../test/test_read_filter_gzip_recursive.c         |     2 +-
 .../libarchive/test/test_read_filter_lrzip.c       |     2 +-
 ..._filter_option.c => test_read_filter_lz4_raw.c} |    36 +-
 .../test/test_read_filter_lz4_raw_skip.uu          |     4 +
 .../libarchive/test/test_read_filter_lzop.c        |     2 +-
 .../test/test_read_filter_lzop_multiple_parts.c    |     2 +-
 .../libarchive/test/test_read_filter_program.c     |     2 +
 .../test/test_read_filter_uudecode_raw.c           |     4 +-
 ...twice_open_fd.c => test_read_filter_zstd_raw.c} |    28 +-
 .../test/test_read_filter_zstd_raw_loop.uu         |     4 +
 .../libarchive/test/test_read_format_7zip.c        |   112 +-
 .../test_read_format_7zip_archive_properties.7z.uu |     5 +
 .../test/test_read_format_7zip_encryption_data.c   |     4 +-
 .../test/test_read_format_7zip_encryption_header.c |     2 +-
 .../test_read_format_7zip_encryption_partially.c   |     6 +-
 .../test/test_read_format_7zip_entries_oom.7z.uu   |     8 +
 .../test/test_read_format_7zip_entries_oom.c       |    56 +
 .../test/test_read_format_7zip_folders_oom.7z.uu   |     8 +
 .../test/test_read_format_7zip_folders_oom.c       |    50 +
 .../test/test_read_format_7zip_issue2765.c         |     2 +-
 .../test/test_read_format_7zip_malformed.c         |    43 +-
 .../test/test_read_format_7zip_malformed4.7z.uu    |     5 +
 ...t_read_format_7zip_malformed_numfiles_oom.7z.uu |     5 +
 .../test/test_read_format_7zip_packinfo_digests.c  |     2 +-
 .../test_read_format_7zip_sfx_boundary_elf.elf.uu  |    22 +
 .../test_read_format_7zip_sfx_boundary_pe.exe.uu   |    22 +
 .../libarchive/test/test_read_format_cab.c         |     6 +-
 .../test/test_read_format_cab_filename.c           |     4 +-
 .../test/test_read_format_cab_lzx_16bit.c          |    52 +
 .../test/test_read_format_cab_lzx_16bit.cab.uu     |     6 +
 .../libarchive/test/test_read_format_cab_lzx_e8.c  |    59 +
 .../test/test_read_format_cab_lzx_e8.cab.uu        |     6 +
 .../test/test_read_format_cab_mszip_oob.c          |    93 +
 .../libarchive/test/test_read_format_cab_multi.c   |    72 +
 .../test/test_read_format_cab_multi.p1.cab.uu      |    15 +
 .../test/test_read_format_cab_multi.p2.cab.uu      |     8 +
 .../libarchive/test/test_read_format_cpio_afio.c   |    26 +-
 ...test_read_format_cpio_afio_header.part1.cpio.uu |     5 +
 ...test_read_format_cpio_afio_header.part2.cpio.uu |     4 +
 .../test/test_read_format_cpio_bin_bz2.c           |     2 +-
 .../libarchive/test/test_read_format_cpio_bin_gz.c |     2 +-
 .../test/test_read_format_cpio_filename.c          |    86 +-
 .../test/test_read_format_cpio_svr4_bzip2_rpm.c    |     2 +-
 .../test/test_read_format_cpio_svr4_gzip.c         |     2 +-
 .../test/test_read_format_cpio_svr4_gzip_rpm.c     |     2 +-
 .../test/test_read_format_cpio_symlink_trailer.c   |    58 +
 .../test_read_format_cpio_symlink_trailer.cpio.uu  |  2919 +++
 .../test/test_read_format_gtar_filename.c          |    18 +-
 .../libarchive/test/test_read_format_gtar_gz.c     |     2 +-
 .../test/test_read_format_gtar_redundant_L.c       |     2 +-
 .../libarchive/test/test_read_format_gtar_sparse.c |    54 +
 .../test/test_read_format_gtar_sparse_reuse.tar.uu |    48 +
 .../test/test_read_format_gtar_sparse_skip_entry.c |     4 +-
 .../libarchive/test/test_read_format_huge_rpm.c    |    17 +-
 .../test_read_format_iso_joliet_utf16be_overflow.c |    61 +
 ..._read_format_iso_joliet_utf16be_overflow.iso.uu |  1278 +
 ...test_read_format_iso_rockridge_ce_loop.iso.Z.uu |    61 +
 .../test_read_format_iso_rockridge_zf_overflow.c   |    77 +
 ...st_read_format_iso_rockridge_zf_overflow.iso.uu |  1096 +
 ...bz2.c => test_read_format_isojoliet_compress.c} |     6 +-
 .../test/test_read_format_isorr_ce_loop.c          |    58 +
 ...orr_bz2.c => test_read_format_isorr_compress.c} |     6 +-
 ...bz2.c => test_read_format_isorr_new_compress.c} |     6 +-
 ...bz2.c => test_read_format_isozisofs_compress.c} |     4 +-
 .../libarchive/test/test_read_format_lha.c         |     2 +-
 .../test/test_read_format_lha_bugfix_0.c           |     2 +-
 .../test/test_read_format_lha_filename.c           |     6 +-
 .../test/test_read_format_lha_filename_utf16.c     |     2 +-
 .../test_read_format_lha_symlink_missing_target.c  |   159 +
 ...t_read_format_lha_symlink_missing_target.lzh.uu |    11 +
 .../libarchive/test/test_read_format_mtree.c       |    91 +-
 .../libarchive/test/test_read_format_pax_bz2.c     |     2 +-
 .../libarchive/test/test_read_format_rar.c         |   129 +-
 .../test_read_format_rar3_lowdist_reset.rar.uu     |    16 +
 .../libarchive/test/test_read_format_rar5.c        |   122 +-
 .../test/test_read_format_rar5_bad_filter.c        |   130 +
 .../test/test_read_format_rar5_bad_tables.c        |    59 +
 .../test/test_read_format_rar5_bad_tables.rar.uu   |     8 +
 .../test_read_format_rar5_block_hdr_fail_loop.c    |    37 +
 ...ad_format_rar5_bytes_remaining_underflow.rar.uu |     5 +
 ..._read_format_rar5_main_block_extra_bytes.rar.uu |     6 +
 ..._read_format_rar5_skip_block_extra_bytes.rar.uu |     6 +
 ...rmat_rar5_unpacked_size_exceeds_declared.rar.uu |    10 +
 .../test/test_read_format_rar_encryption.c         |    10 +-
 .../test/test_read_format_rar_encryption_data.c    |     6 +-
 .../test/test_read_format_rar_encryption_header.c  |     2 +-
 .../test_read_format_rar_encryption_partially.c    |     4 +-
 .../test/test_read_format_rar_invalid1.c           |     2 +-
 .../test_read_format_rar_newsub_rr_over_1m.rar.uu  | 23307 +++++++++++++++++++
 .../test/test_read_format_rar_overflow.c           |     2 +-
 .../test_read_format_rar_seek_data_cursor0.rar.uu  |   164 +
 .../test_read_format_rar_unbound_staticdata.rar.uu |     6 +
 ...ename.c => test_read_format_tar_acl_oob_read.c} |    36 +-
 .../test/test_read_format_tar_acl_oob_read.tar.uu  |   129 +
 .../test/test_read_format_tar_concatenated.c       |     4 +-
 .../test/test_read_format_tar_empty_filename.c     |     2 +-
 .../test/test_read_format_tar_empty_pax.c          |    69 +
 .../test_read_format_tar_empty_with_gnulabel.c     |     2 +-
 .../test/test_read_format_tar_filename.c           |    12 +-
 .../test/test_read_format_tar_mac_metadata.c       |     2 +-
 .../test/test_read_format_tar_pax_g_large.c        |     2 +-
 .../test/test_read_format_tar_pax_large_attr.c     |     2 +-
 .../test/test_read_format_tar_pax_negative_time.c  |     2 +-
 .../test/test_read_format_tar_pax_sun_holesdata.c  |    76 +
 .../test_read_format_tar_pax_sun_holesdata.tar.uu  |    95 +
 .../test/test_read_format_tar_pax_timestamps.c     |    64 +
 .../test_read_format_tar_pax_timestamps.tar.uu     |    60 +
 .../test/test_read_format_tar_timestamp_overflow.c |    55 +
 .../test_read_format_tar_timestamp_overflow.tar.uu |    38 +
 .../libarchive/test/test_read_format_tgz.c         |     2 +-
 .../test/test_read_format_ustar_filename.c         |    18 +-
 .../libarchive/test/test_read_format_warc.c        |   100 +
 .../libarchive/test/test_read_format_xar.c         |   184 +
 .../test_read_format_xar_atou64_overread.xar.uu    |     7 +
 .../test/test_read_format_xar_base64_oob.xar.uu    |     7 +
 .../test/test_read_format_xar_large_mode.xar.uu    |    11 +
 ...test_read_format_xar_parse_time_overread.xar.uu |     8 +
 .../libarchive/test/test_read_format_zip.c         |   130 +-
 .../test/test_read_format_zip_7075_utf8_paths.c    |     4 +-
 .../test/test_read_format_zip_comment_stored.c     |     2 +-
 .../test/test_read_format_zip_encryption_data.c    |     2 +-
 .../test/test_read_format_zip_encryption_header.c  |     2 +-
 .../test_read_format_zip_encryption_partially.c    |     2 +-
 .../test/test_read_format_zip_filename.c           |    40 +-
 .../libarchive/test/test_read_format_zip_jar.c     |     2 +-
 .../test/test_read_format_zip_mac_metadata.c       |     2 +-
 .../test/test_read_format_zip_malformed.c          |     4 +-
 .../libarchive/test/test_read_format_zip_nested.c  |     4 +-
 .../test/test_read_format_zip_nofiletype.c         |     2 +-
 .../libarchive/test/test_read_format_zip_padded.c  |     2 +-
 .../test/test_read_format_zip_pkware_unix.zip.uu   |     7 +
 ..._read_format_zip_ppmd8_aes256_streaming.zipx.uu |    16 +
 .../libarchive/test/test_read_format_zip_sfx.c     |     2 +-
 .../test_read_format_zip_size_exceeds_declared.c   |   145 +
 ...format_zip_size_exceeds_declared_deflate.zip.uu |    23 +
 ..._format_zip_size_exceeds_declared_stored.zip.uu |     9 +
 ...ad_format_zip_symlink_unsupported_compression.c |   168 +
 ...rmat_zip_symlink_unsupported_compression.zip.uu |    16 +
 ...t_read_format_zip_traditional_encryption_data.c |     4 +-
 ...read_format_zip_uncompressed_size_off_by_4gib.c |   106 +
 ...format_zip_uncompressed_size_off_by_4gib.zip.uu |     7 +
 .../test/test_read_format_zip_winzip_aes.c         |     4 +-
 ...ead_format_zip_winzip_aes256_large_bzip2.zip.uu |  1616 ++
 ...read_format_zip_winzip_aes256_large_lzma.zip.uu |  1893 ++
 ...read_format_zip_winzip_aes256_large_ppmd.zip.uu |  1399 ++
 ...t_read_format_zip_winzip_aes256_large_xz.zip.uu |  1898 ++
 ...read_format_zip_winzip_aes256_large_zstd.zip.uu |  2053 ++
 .../test/test_read_format_zip_winzip_aes_large.c   |   276 +-
 ...read_format_zip_with_invalid_traditional_eocd.c |     2 +-
 .../libarchive/test/test_read_format_zip_zip64.c   |     4 +-
 .../test/test_read_format_zip_zipx_encrypted.c     |   268 +
 .../test/test_read_format_zip_zipx_lzma_oom.c      |    63 +
 .../test_read_format_zip_zipx_lzma_oom.zipx.uu     |     4 +
 .../test/test_read_pax_empty_val_no_nl.c           |     2 +-
 .../test_read_pax_xattr_rht_security_selinux.c     |     2 +-
 .../libarchive/test/test_read_pax_xattr_schily.c   |     2 +-
 .../libarchive/test/test_read_set_format.c         |   170 +-
 .../libarchive/libarchive/test/test_sparse_basic.c |    43 +-
 .../libarchive/test/test_ustar_filename_encoding.c |    10 +-
 .../libarchive/test/test_write_disk_appledouble.c  |     6 +-
 .../test/test_write_disk_hfs_compression.c         |     4 +-
 .../libarchive/test/test_write_disk_mac_metadata.c |     4 +-
 .../test/test_write_disk_no_hfs_compression.c      |     4 +-
 .../libarchive/test/test_write_disk_secure.c       |   292 +-
 .../libarchive/test/test_write_disk_secure744.c    |    11 +-
 .../libarchive/test/test_write_disk_secure745.c    |     3 +-
 .../libarchive/test/test_write_disk_secure746.c    |     9 +-
 .../test/test_write_disk_secure_noabsolutepaths.c  |     1 +
 .../libarchive/test/test_write_filter_b64encode.c  |     6 +-
 .../libarchive/test/test_write_filter_bzip2.c      |     6 +-
 .../libarchive/test/test_write_filter_gzip.c       |    23 +-
 .../libarchive/test/test_write_filter_lrzip.c      |     6 +-
 .../libarchive/test/test_write_filter_lz4.c        |     8 +-
 .../libarchive/test/test_write_filter_lzip.c       |     6 +-
 .../libarchive/test/test_write_filter_lzma.c       |    82 +-
 .../libarchive/test/test_write_filter_lzop.c       |     6 +-
 .../libarchive/test/test_write_filter_uuencode.c   |     6 +-
 .../libarchive/test/test_write_filter_xz.c         |    95 +-
 .../libarchive/test/test_write_filter_zstd.c       |     6 +-
 .../libarchive/test/test_write_format_7zip.c       |    47 +-
 .../libarchive/test/test_write_format_7zip_empty.c |    10 +-
 .../libarchive/test/test_write_format_7zip_large.c |     2 +-
 .../libarchive/test/test_write_format_gnutar.c     |    15 +-
 .../test/test_write_format_gnutar_filenames.c      |     8 +-
 .../test/test_write_format_gnutar_huge.c           |    57 +
 .../libarchive/test/test_write_format_iso9660.c    |    12 +-
 .../test/test_write_format_iso9660_boot.c          |     4 +-
 .../test/test_write_format_iso9660_bugs.c          |   305 +
 .../test/test_write_format_iso9660_empty.c         |     4 +-
 .../test/test_write_format_iso9660_filename.c      |     4 +-
 .../test/test_write_format_iso9660_joliet_id.c     |   113 +
 ...est_write_format_iso9660_joliet_overflow.bin.uu |     4 +
 .../test_write_format_iso9660_null_deref.bin.uu    |     5 +
 ...ion.c => test_write_format_iso9660_rockridge.c} |    64 +-
 .../test_write_format_iso9660_rockridge_overflow.c |    74 +
 .../test_write_format_iso9660_underflow.bin.uu     |     5 +
 .../test/test_write_format_iso9660_zisofs.c        |    12 +-
 .../test_write_format_iso9660_zisofs_overflow.c    |   127 +
 .../libarchive/test/test_write_format_mtree.c      |     4 +-
 .../test/test_write_format_mtree_absolute.c        |   132 +
 .../test/test_write_format_mtree_dotdot.c          |   103 +
 .../test/test_write_format_mtree_null_deref.bin.uu |     4 +
 .../test/test_write_format_mtree_null_deref.c      |   233 +
 .../test/test_write_format_mtree_preset_digests.c  |   105 +-
 .../libarchive/test/test_write_format_pax.c        |    35 +-
 .../libarchive/test/test_write_format_pax_align.c  |   246 +
 .../test/test_write_format_tar_empty_dirname.c     |    82 +
 .../libarchive/test/test_write_format_tar_ustar.c  |    14 +-
 .../libarchive/test/test_write_format_warc.c       |   106 +
 .../libarchive/test/test_write_format_xar.c        |   112 +-
 .../libarchive/test/test_write_format_xar_bugs.c   |   170 +
 .../libarchive/test/test_write_format_xar_empty.c  |     2 +-
 .../libarchive/test/test_write_format_xar_fflags.c |    78 +
 .../test_write_format_xar_strcpy_overlap.bin.uu    |     6 +
 .../test/test_write_format_xar_underflow.bin.uu    |     6 +
 .../libarchive/test/test_write_format_zip.c        |     8 +-
 ...=> test_write_format_zip_compression_lzma_xz.c} |    20 +-
 .../test/test_write_format_zip_empty_pathname.c    |    75 +
 .../test/test_write_format_zip_long_pathname.c     |   114 +
 .../test/test_write_format_zip_windows_path.c      |     3 +-
 .../libarchive/test/test_write_format_zip_zip64.c  |     2 +-
 .../libarchive/test/test_write_read_format_zip.c   |     8 +-
 contrib/libarchive/libarchive/xxhash.c             |     2 +
 contrib/libarchive/libarchive_fe/lafe_fnmatch.c    |   317 +
 contrib/libarchive/libarchive_fe/lafe_fnmatch.h    |    56 +
 contrib/libarchive/tar/bsdtar.h                    |     3 +-
 contrib/libarchive/tar/read.c                      |    31 +-
 contrib/libarchive/tar/subst.c                     |    17 +-
 contrib/libarchive/tar/test/test_option_P_upper.c  |     1 +
 contrib/libarchive/tar/test/test_option_mtime.c    |    17 -
 contrib/libarchive/tar/test/test_option_s.c        |     4 +-
 .../test_option_stdout_size_exceeds_declared.c     |    50 +
 ...ion_stdout_size_exceeds_declared_deflate.zip.uu |    23 +
 ...tion_stdout_size_exceeds_declared_stored.zip.uu |     9 +
 contrib/libarchive/tar/test/test_stdio.c           |     2 +-
 contrib/libarchive/tar/util.c                      |    40 +-
 contrib/libarchive/tar/write.c                     |    43 +-
 contrib/libarchive/test_utils/test_main.c          |   109 +-
 contrib/libarchive/test_utils/test_utils.c         |     2 +-
 contrib/libarchive/unzip/bsdunzip.c                |    84 +-
 contrib/libarchive/unzip/bsdunzip_platform.h       |     4 +
 contrib/libarchive/unzip/test/test_I.c             |     8 +-
 contrib/libarchive/unzip/test/test_P_encryption.c  |     4 +
 contrib/libarchive/unzip/test/test_f.c             |    39 +
 contrib/libarchive/unzip/test/test_f_new.zip.uu    |     8 +
 contrib/libarchive/unzip/test/test_f_old.zip.uu    |     8 +
 contrib/libarchive/unzip/test/test_symlink.c       |    53 +
 .../libarchive/unzip/test/test_symlink_1.zip.uu    |    21 +
 .../libarchive/unzip/test/test_symlink_2.zip.uu    |    12 +
 .../libarchive/unzip/test/test_symlink_dotdot.c    |    36 +
 .../unzip/test/test_symlink_dotdot.zip.uu          |    10 +
 contrib/libarchive/unzip/test/test_u.c             |    32 +
 contrib/libarchive/unzip/test/test_u_new.zip.uu    |     8 +
 contrib/libarchive/unzip/test/test_u_old.zip.uu    |     8 +
 lib/libarchive/tests/Makefile                      |   132 +-
 usr.bin/tar/tests/Makefile                         |     3 +
 usr.bin/unzip/tests/Makefile                       |    12 +-
 434 files changed, 57366 insertions(+), 8560 deletions(-)

diff --git a/contrib/libarchive/FREEBSD-Xlist b/contrib/libarchive/FREEBSD-Xlist
index 70a015527c05..98a7099d7e04 100644
--- a/contrib/libarchive/FREEBSD-Xlist
+++ b/contrib/libarchive/FREEBSD-Xlist
@@ -1,5 +1,6 @@
 .git
 .gitattributes
+.github
 .gitignore
 .travis.yml
 CMakeLists.txt
@@ -34,8 +35,13 @@ libarchive/mtree.5
 libarchive/test/.cvsignore
 libarchive/test/CMakeLists.txt
 tar/CMakeLists.txt
+tar/bsdtar.exe.manifest
+tar/bsdtar.rc
 tar/bsdtar_windows.c
 tar/bsdtar_windows.h
 tar/config_freebsd.h
 tar/test/CMakeLists.txt
 tar/test/test_windows.c
+unzip/bsdunzip.exe.manifest
+unzip/bsdunzip.rc
+unzip/bsdunzip_windows.h
diff --git a/contrib/libarchive/NEWS b/contrib/libarchive/NEWS
index d5e9769771e2..a46b69aaf3e9 100644
--- a/contrib/libarchive/NEWS
+++ b/contrib/libarchive/NEWS
@@ -1,3 +1,7 @@
+Jul 28, 2026: libarchive 3.8.9 released
+
+Jun 23, 2026: libarchive 3.8.8 released
+
 Apr 13, 2026: libarchive 3.8.7 released
 
 Mar 10, 2026: libarchive 3.8.6 released
diff --git a/contrib/libarchive/SECURITY.md b/contrib/libarchive/SECURITY.md
index f2f60e792a57..33c37e470004 100644
--- a/contrib/libarchive/SECURITY.md
+++ b/contrib/libarchive/SECURITY.md
@@ -1,9 +1,10 @@
 # Security Policy
 
-If you have discovered a security vulnerability in this project, please report it
-privately. **Do not disclose it as a public issue.** This gives us time to work with you
-to fix the issue before public exposure, reducing the chance that the exploit will be
-used before a patch is released.
+If you have discovered a security vulnerability in this project,
+please report it privately.
+**Do not disclose it as a public issue.**
+This gives us time to work with you to fix the issue before public exposure,
+reducing the chance that the exploit will be used before a patch is released.
 
 You may submit the report in the following ways:
 
@@ -15,5 +16,11 @@ Please provide the following information in your report:
 - A description of the vulnerability and its impact
 - How to reproduce the issue
 
-This project is maintained by volunteers on a reasonable-effort basis. As such, we ask
-that you give us 90 days to work on a fix before public exposure.
+While we welcome all reports, we can act most quickly if the report
+includes a complete libarchive test case and a proposed fix.
+See [doc/WRITING_TESTS.md](doc/WRITING_TESTS.md) for guidance on creating a reproduction test case.
+You can provide the test case and proposed fix as separate patch files
+prepared with `git format-patch` or `git diff`.
+
+This project is maintained by volunteers on a reasonable-effort basis.
+We ask that you give us 90 days to work on a fix before public exposure.
diff --git a/contrib/libarchive/build/ci/github_actions/install-macos-dependencies.sh b/contrib/libarchive/build/ci/github_actions/install-macos-dependencies.sh
deleted file mode 100755
index b33aed5e5562..000000000000
--- a/contrib/libarchive/build/ci/github_actions/install-macos-dependencies.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/sh
-set -eux
-
-# Uncommenting these adds a full minute to the CI time
-#brew update > /dev/null
-#brew upgrade > /dev/null
-
-# Workaround for cmake in local/pinned tap issue
-brew uninstall cmake
-
-# This does an upgrade if the package is already installed
-brew install \
-	autoconf \
-	automake \
-	libtool \
-	pkg-config \
-	cmake \
-	xz \
-	lz4 \
-	zstd \
-	libxml2 \
-	openssl
diff --git a/contrib/libarchive/cpio/cpio.c b/contrib/libarchive/cpio/cpio.c
index 6e6c2c3356c0..ebdace394cea 100644
--- a/contrib/libarchive/cpio/cpio.c
+++ b/contrib/libarchive/cpio/cpio.c
@@ -1002,7 +1002,10 @@ mode_in(struct cpio *cpio)
 			lafe_errc(1, archive_errno(a),
 			    "%s", archive_error_string(a));
 		}
-		if (archive_match_path_excluded(cpio->matching, entry))
+		r = archive_match_path_excluded(cpio->matching, entry);
+		if (r < 0)
+			lafe_errc(1, 0, "%s", archive_error_string(cpio->matching));
+		if (r)
 			continue;
 		if (cpio->option_rename)
 			cpio_rename(entry);
@@ -1117,7 +1120,10 @@ mode_list(struct cpio *cpio)
 			lafe_errc(1, archive_errno(a),
 			    "%s", archive_error_string(a));
 		}
-		if (archive_match_path_excluded(cpio->matching, entry))
+		r = archive_match_path_excluded(cpio->matching, entry);
+		if (r < 0)
+			lafe_errc(1, 0, "%s", archive_error_string(cpio->matching));
+		if (r)
 			continue;
 		if (cpio->verbose)
 			list_item_verbose(cpio, entry);
diff --git a/contrib/libarchive/cpio/test/test_extract_cpio_absolute_paths.c b/contrib/libarchive/cpio/test/test_extract_cpio_absolute_paths.c
index 51650bc00f5a..e3a72f9ccaf3 100644
--- a/contrib/libarchive/cpio/test/test_extract_cpio_absolute_paths.c
+++ b/contrib/libarchive/cpio/test/test_extract_cpio_absolute_paths.c
@@ -50,4 +50,5 @@ DEFINE_TEST(test_extract_cpio_absolute_paths)
 	r = systemf("%s -i --insecure < archive.cpio 2> stderr3.txt", testprog);
 	assert(r == 0);
 	assertFileExists(temp_absolute_file_name);
+	free(temp_absolute_file_name);
 }
diff --git a/contrib/libarchive/cpio/test/test_format_newc.c b/contrib/libarchive/cpio/test/test_format_newc.c
index 9d4e4e9fb674..7363fc148f16 100644
--- a/contrib/libarchive/cpio/test/test_format_newc.c
+++ b/contrib/libarchive/cpio/test/test_format_newc.c
@@ -198,7 +198,7 @@ DEFINE_TEST(test_format_newc)
 	t = from_hex(e + 46, 8); /* mtime */
 	failure("t=%#08jx now=%#08jx=%jd", (uintmax_t)t, (uintmax_t)now,
 	    (intmax_t)now);
-	assert(t <= now); /* File wasn't created in future. */
+	assert(t <= now + 1); /* Allow 1 sec margin for timing variations. */
 	failure("t=%#08jx now - 2=%#08jx=%jd", (uintmax_t)t, (uintmax_t)now - 2,
 	    (intmax_t)now - 2);
 	assert(t >= now - 2); /* File was created w/in last 2 secs. */
diff --git a/contrib/libarchive/libarchive/archive.h b/contrib/libarchive/libarchive/archive.h
index 41a5440cac75..a7de6f6dd85b 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 3008007
+#define	ARCHIVE_VERSION_NUMBER 3008009
 
 #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.7"
+#define	ARCHIVE_VERSION_ONLY_STRING "3.8.9"
 #define	ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
 __LA_DECL const char *	archive_version_string(void);
 
@@ -210,7 +210,9 @@ __LA_DECL const char *  archive_openssl_version(void);
 __LA_DECL const char *  archive_libmd_version(void);
 __LA_DECL const char *  archive_commoncrypto_version(void);
 __LA_DECL const char *  archive_cng_version(void);
+#if ARCHIVE_VERSION_NUMBER < 4000000
 __LA_DECL const char *  archive_wincrypt_version(void);
+#endif
 __LA_DECL const char *  archive_librichacl_version(void);
 __LA_DECL const char *  archive_libacl_version(void);
 __LA_DECL const char *  archive_libattr_version(void);
@@ -653,7 +655,6 @@ __LA_DECL int archive_read_data_block(struct archive *a,
 /*-
  * Some convenience functions that are built on archive_read_data:
  *  'skip': skips entire entry
- *  'into_buffer': writes data into memory buffer that you provide
  *  'into_fd': writes data to specified filedes
  */
 __LA_DECL int archive_read_data_skip(struct archive *);
@@ -1234,7 +1235,7 @@ __LA_DECL int	archive_match_exclude_entry(struct archive *,
 		    int _flag, struct archive_entry *);
 
 /*
- * Test if a file is excluded by its uid ,gid, uname or gname.
+ * Test if a file is excluded by its uid, gid, uname or gname.
  * The conditions are set by following functions.
  */
 __LA_DECL int	archive_match_owner_excluded(struct archive *,
diff --git a/contrib/libarchive/libarchive/archive_acl.c b/contrib/libarchive/libarchive/archive_acl.c
index ab601833def6..f1b1232f5eef 100644
--- a/contrib/libarchive/libarchive/archive_acl.c
+++ b/contrib/libarchive/libarchive/archive_acl.c
@@ -56,9 +56,7 @@ static int	archive_acl_add_entry_len_l(struct archive_acl *acl,
 		    int type, int permset, int tag, int id, const char *name,
 		    size_t len, struct archive_string_conv *sc);
 static int	archive_acl_text_want_type(struct archive_acl *acl, int flags);
-static size_t	archive_acl_text_len(struct archive_acl *acl, int want_type,
-		    int flags, int wide, struct archive *a,
-		    struct archive_string_conv *sc);
+static size_t	archive_acl_text_empty(struct archive_acl *acl, int want_type);
 static int	isint_w(const wchar_t *start, const wchar_t *end, int *result);
 static int	ismode_w(const wchar_t *start, const wchar_t *end, int *result);
 static int	is_nfs4_flags_w(const wchar_t *start, const wchar_t *end,
@@ -67,9 +65,9 @@ static int	is_nfs4_perms_w(const wchar_t *start, const wchar_t *end,
 		    int *result);
 static void	next_field_w(const wchar_t **wp, const wchar_t **start,
 		    const wchar_t **end, wchar_t *sep);
-static void	append_entry_w(wchar_t **wp, const wchar_t *prefix, int type,
+static void	append_entry_w(struct archive_wstring *ws, const wchar_t *prefix, int type,
 		    int tag, int flags, const wchar_t *wname, int perm, int id);
-static void	append_id_w(wchar_t **wp, int id);
+static void	append_id_w(struct archive_wstring *ws, int id);
 static int	isint(const char *start, const char *end, int *result);
 static int	ismode(const char *start, const char *end, int *result);
 static int	is_nfs4_flags(const char *start, const char *end,
@@ -78,9 +76,9 @@ static int	is_nfs4_perms(const char *start, const char *end,
 		    int *result);
 static void	next_field(const char **p, size_t *l, const char **start,
 		    const char **end, char *sep);
-static void	append_entry(char **p, const char *prefix, int type,
+static void	append_entry(struct archive_string *s, const char *prefix, int type,
 		    int tag, int flags, const char *name, int perm, int id);
-static void	append_id(char **p, int id);
+static void	append_id(struct archive_string *s, int id);
 
 static const struct {
 	const int perm;
@@ -539,20 +537,12 @@ archive_acl_text_want_type(struct archive_acl *acl, int flags)
 }
 
 /*
- * Calculate ACL text string length
+ * Check if ACL text would be empty
  */
 static size_t
-archive_acl_text_len(struct archive_acl *acl, int want_type, int flags,
-    int wide, struct archive *a, struct archive_string_conv *sc) {
+archive_acl_text_empty(struct archive_acl *acl, int want_type) {
 	struct archive_acl_entry *ap;
-	const char *name;
-	const wchar_t *wname;
-	int count, idlen, tmp, r;
-	size_t length;
-	size_t len;
 
-	count = 0;
-	length = 0;
 	for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
 		if ((ap->type & want_type) == 0)
 			continue;
@@ -565,107 +555,11 @@ archive_acl_text_len(struct archive_acl *acl, int want_type, int flags,
 		    || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ
 		    || ap->tag == ARCHIVE_ENTRY_ACL_OTHER))
 			continue;
-		count++;
-		if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0
-		    && (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
-			length += 8; /* "default:" */
-		switch (ap->tag) {
-		case ARCHIVE_ENTRY_ACL_USER_OBJ:
-			if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-				length += 6; /* "owner@" */
-				break;
-			}
-			/* FALLTHROUGH */
-		case ARCHIVE_ENTRY_ACL_USER:
-		case ARCHIVE_ENTRY_ACL_MASK:
-			length += 4; /* "user", "mask" */
-			break;
-		case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
-			if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-				length += 6; /* "group@" */
-				break;
-			}
-			/* FALLTHROUGH */
-		case ARCHIVE_ENTRY_ACL_GROUP:
-		case ARCHIVE_ENTRY_ACL_OTHER:
-			length += 5; /* "group", "other" */
-			break;
-		case ARCHIVE_ENTRY_ACL_EVERYONE:
-			length += 9; /* "everyone@" */
-			break;
-		}
-		length += 1; /* colon after tag */
-		if (ap->tag == ARCHIVE_ENTRY_ACL_USER ||
-		    ap->tag == ARCHIVE_ENTRY_ACL_GROUP) {
-			if (wide) {
-				r = archive_mstring_get_wcs(a, &ap->name,
-				    &wname);
-				if (r == 0 && wname != NULL)
-					length += wcslen(wname);
-				else if (r < 0 && errno == ENOMEM)
-					return (0);
-				else
-					length += sizeof(uid_t) * 3 + 1;
-			} else {
-				r = archive_mstring_get_mbs_l(a, &ap->name, &name,
-				    &len, sc);
-				if (r != 0)
-					return (0);
-				if (len > 0 && name != NULL)
-					length += len;
-				else
-					length += sizeof(uid_t) * 3 + 1;
-			}
-			length += 1; /* colon after user or group name */
-		} else if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4)
-			length += 1; /* 2nd colon empty user,group or other */
-
-		if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0)
-		    && ((want_type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0)
-		    && (ap->tag == ARCHIVE_ENTRY_ACL_OTHER
-		    || ap->tag == ARCHIVE_ENTRY_ACL_MASK)) {
-			/* Solaris has no colon after other: and mask: */
-			length = length - 1;
-		}
-
-		if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-			/* rwxpdDaARWcCos:fdinSFI:deny */
-			length += 27;
-			if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DENY) == 0)
-				length += 1; /* allow, alarm, audit */
-		} else
-			length += 3; /* rwx */
-
-		if ((ap->tag == ARCHIVE_ENTRY_ACL_USER ||
-		    ap->tag == ARCHIVE_ENTRY_ACL_GROUP) &&
-		    (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0) {
-			length += 1; /* colon */
-			/* ID digit count */
-			idlen = 1;
-			tmp = ap->id;
-			while (tmp > 9) {
-				tmp = tmp / 10;
-				idlen++;
-			}
-			length += idlen;
-		}
-		length ++; /* entry separator */
-	}
 
-	/* Add filemode-mapping access entries to the length */
-	if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
-		if ((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0) {
-			/* "user::rwx\ngroup::rwx\nother:rwx\n" */
-			length += 31;
-		} else {
-			/* "user::rwx\ngroup::rwx\nother::rwx\n" */
-			length += 32;
-		}
-	} else if (count == 0)
 		return (0);
+	}
 
-	/* The terminating character is included in count */
-	return (length);
+	return (1);
 }
 
 /*
@@ -676,15 +570,12 @@ wchar_t *
 archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags,
     struct archive *a)
 {
-	int count;
-	size_t length;
-	size_t len;
 	const wchar_t *wname;
 	const wchar_t *prefix;
 	wchar_t separator;
 	struct archive_acl_entry *ap;
+	struct archive_wstring ws;
 	int id, r, want_type;
-	wchar_t *wp, *ws;
 
 	want_type = archive_acl_text_want_type(acl, flags);
 
@@ -695,9 +586,7 @@ archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags,
 	if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)
 		flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
 
-	length = archive_acl_text_len(acl, want_type, flags, 1, a, NULL);
-
-	if (length == 0)
+	if (archive_acl_text_empty(acl, want_type))
 		return (NULL);
 
 	if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA)
@@ -705,28 +594,20 @@ archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags,
 	else
 		separator = L'\n';
 
-	/* Now, allocate the string and actually populate it. */
-	wp = ws = malloc(length * sizeof(*wp));
-	if (wp == NULL) {
-		if (errno == ENOMEM)
-			__archive_errx(1, "No memory");
-		return (NULL);
-	}
-	count = 0;
+	archive_string_init(&ws);
 
 	if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
-		append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+		append_entry_w(&ws, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
 		    ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL,
 		    acl->mode & 0700, -1);
-		*wp++ = separator;
-		append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+		archive_wstrappend_wchar(&ws, separator);
+		append_entry_w(&ws, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
 		    ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL,
 		    acl->mode & 0070, -1);
-		*wp++ = separator;
-		append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+		archive_wstrappend_wchar(&ws, separator);
+		append_entry_w(&ws, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
 		    ARCHIVE_ENTRY_ACL_OTHER, flags, NULL,
 		    acl->mode & 0007, -1);
-		count += 3;
 	}
 
 	for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
@@ -748,108 +629,95 @@ archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags,
 			prefix = NULL;
 		r = archive_mstring_get_wcs(a, &ap->name, &wname);
 		if (r == 0) {
-			if (count > 0)
-				*wp++ = separator;
-			if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
+			if (ws.length > 0)
+				archive_wstrappend_wchar(&ws, separator);
+			if ((flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) ||
+			    wname == NULL)
 				id = ap->id;
 			else
 				id = -1;
-			append_entry_w(&wp, prefix, ap->type, ap->tag, flags,
+			append_entry_w(&ws, prefix, ap->type, ap->tag, flags,
 			    wname, ap->permset, id);
-			count++;
 		} else if (r < 0 && errno == ENOMEM) {
-			free(ws);
+			archive_wstring_free(&ws);
 			return (NULL);
 		}
 	}
 
-	/* Add terminating character */
-	*wp++ = L'\0';
-
-	len = wcslen(ws);
-
-	if (len > length - 1)
-		__archive_errx(1, "Buffer overrun");
-
 	if (text_len != NULL)
-		*text_len = len;
+		*text_len = ws.length;
 
-	return (ws);
+	return (ws.s);
 }
 
 static void
-append_id_w(wchar_t **wp, int id)
+append_id_w(struct archive_wstring *ws, int id)
 {
 	if (id < 0)
 		id = 0;
 	if (id > 9)
-		append_id_w(wp, id / 10);
-	*(*wp)++ = L"0123456789"[id % 10];
+		append_id_w(ws, id / 10);
+	archive_wstrappend_wchar(ws, L"0123456789"[id % 10]);
 }
 
 static void
-append_entry_w(wchar_t **wp, const wchar_t *prefix, int type,
+append_entry_w(struct archive_wstring *ws, const wchar_t *prefix, int type,
     int tag, int flags, const wchar_t *wname, int perm, int id)
 {
 	int i;
 
-	if (prefix != NULL) {
-		wcscpy(*wp, prefix);
-		*wp += wcslen(*wp);
-	}
+	if (prefix != NULL)
+		archive_wstrcat(ws, prefix);
 	switch (tag) {
 	case ARCHIVE_ENTRY_ACL_USER_OBJ:
 		wname = NULL;
 		id = -1;
 		if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
-			wcscpy(*wp, L"owner@");
+			archive_wstrcat(ws, L"owner@");
 			break;
 		}
 		/* FALLTHROUGH */
 	case ARCHIVE_ENTRY_ACL_USER:
-		wcscpy(*wp, L"user");
+		archive_wstrcat(ws, L"user");
 		break;
 	case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
 		wname = NULL;
 		id = -1;
 		if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
-			wcscpy(*wp, L"group@");
+			archive_wstrcat(ws, L"group@");
 			break;
 		}
 		/* FALLTHROUGH */
 	case ARCHIVE_ENTRY_ACL_GROUP:
-		wcscpy(*wp, L"group");
+		archive_wstrcat(ws, L"group");
 		break;
 	case ARCHIVE_ENTRY_ACL_MASK:
*** 90057 LINES SKIPPED ***