From 5bb36db5e19aecabccec8f351ec22f8c3a8695f0 Mon Sep 17 00:00:00 2001 From: Zhaofeng Li Date: Sat, 24 May 2025 13:45:18 -0600 Subject: [PATCH] tar: Reset accumulated header state after reading macOS metadata blob AppleDouble extension entries are present as separate files immediately preceding the corresponding real files. In libarchive, we process the entire metadata file (headers + data) as if it were a header in the real file. However, the code forgets to reset the accumulated header state before parsing the real file's headers. In one code path, this causes the metadata file's name to be used as the real file's name. Specifically, this can be triggered with a tar containing two files: 1. A file named `._badname` with pax header containing the `path` attribute 2. A file named `goodname` _with_ a pax header but _without_ the `path` attribute libarchive will list one file, `._badname` containing the data of `goodname`. This code is pretty brittle and we really should let the client deal with it :( Fixes #2510. Signed-off-by: Zhaofeng Li --- libarchive/archive_read_support_format_tar.c | 25 ++++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c index e9b3312a2..4ead50c7d 100644 --- a/libarchive/archive_read_support_format_tar.c +++ b/libarchive/archive_read_support_format_tar.c @@ -701,6 +701,22 @@ archive_read_format_tar_skip(struct archive_read *a) return (ARCHIVE_OK); } +/* + * This function resets the accumulated state while reading + * a header. + */ +static void +tar_reset_header_state(struct tar *tar) +{ + tar->pax_hdrcharset_utf8 = 1; + tar->sparse_gnu_attributes_seen = 0; + archive_string_empty(&(tar->entry_gname)); + archive_string_empty(&(tar->entry_pathname)); + archive_string_empty(&(tar->entry_pathname_override)); + archive_string_empty(&(tar->entry_uname)); + archive_string_empty(&tar->entry_linkpath); +} + /* * This function reads and interprets all of the headers associated * with a single entry. @@ -726,13 +742,7 @@ tar_read_header(struct archive_read *a, struct tar *tar, static const int32_t seen_x_header = 32; /* Also X */ static const int32_t seen_mac_metadata = 512; - tar->pax_hdrcharset_utf8 = 1; - tar->sparse_gnu_attributes_seen = 0; - archive_string_empty(&(tar->entry_gname)); - archive_string_empty(&(tar->entry_pathname)); - archive_string_empty(&(tar->entry_pathname_override)); - archive_string_empty(&(tar->entry_uname)); - archive_string_empty(&tar->entry_linkpath); + tar_reset_header_state(tar); /* Ensure format is set. */ if (a->archive.archive_format_name == NULL) { @@ -936,6 +946,7 @@ tar_read_header(struct archive_read *a, struct tar *tar, err = err_combine(err, err2); /* Note: Other headers can appear again. */ seen_headers = seen_mac_metadata; + tar_reset_header_state(tar); break; } -- 2.47.3