From 6445be4ea62b8b7552f2be4da8949a9e51d1bf26 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Sun, 25 May 2025 16:22:59 -0700 Subject: [PATCH] Merge pull request #2637 from stoeckmann/pax_nl tar: Keep block alignment after pax error (cherry picked from commit 341dd5d1d45ce320ff05928e50efafd8ed42ed81) --- Makefile.am | 2 + libarchive/archive_read_support_format_tar.c | 7 ++ libarchive/test/CMakeLists.txt | 1 + .../test/test_read_pax_empty_val_no_nl.c | 65 +++++++++++++++++++ .../test/test_read_pax_empty_val_no_nl.tar.uu | 60 +++++++++++++++++ 5 files changed, 135 insertions(+) create mode 100644 libarchive/test/test_read_pax_empty_val_no_nl.c create mode 100644 libarchive/test/test_read_pax_empty_val_no_nl.tar.uu diff --git a/Makefile.am b/Makefile.am index d159f2970..22253d709 100644 --- a/Makefile.am +++ b/Makefile.am @@ -566,6 +566,7 @@ libarchive_test_SOURCES= \ libarchive/test/test_read_format_zip_zip64.c \ libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c \ libarchive/test/test_read_large.c \ + libarchive/test/test_read_pax_empty_val_no_nl.c \ libarchive/test/test_read_pax_xattr_rht_security_selinux.c \ libarchive/test/test_read_pax_xattr_schily.c \ libarchive/test/test_read_pax_truncated.c \ @@ -1043,6 +1044,7 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_large_splitted_rar_ac.uu \ libarchive/test/test_read_large_splitted_rar_ad.uu \ libarchive/test/test_read_large_splitted_rar_ae.uu \ + libarchive/test/test_read_pax_empty_val_no_nl.tar.uu \ libarchive/test/test_read_pax_xattr_rht_security_selinux.tar.uu \ libarchive/test/test_read_pax_xattr_schily.tar.uu \ libarchive/test/test_read_splitted_rar_aa.uu \ diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c index 4ead50c7d..1cc667169 100644 --- a/libarchive/archive_read_support_format_tar.c +++ b/libarchive/archive_read_support_format_tar.c @@ -2001,6 +2001,13 @@ header_pax_extension(struct archive_read *a, struct tar *tar, *unconsumed += p - attr_start; tar_flush_unconsumed(a, unconsumed); + if (value_length == 0) { + archive_set_error(&a->archive, EINVAL, + "Malformed pax attributes"); + *unconsumed += ext_size + ext_padding; + return (ARCHIVE_WARN); + } + /* pax_attribute will consume value_length - 1 */ r = pax_attribute(a, tar, entry, attr_name.s, archive_strlen(&attr_name), value_length - 1, unconsumed); ext_size -= value_length - 1; diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt index 2fa8b01c8..1443f1c9d 100644 --- a/libarchive/test/CMakeLists.txt +++ b/libarchive/test/CMakeLists.txt @@ -209,6 +209,7 @@ IF(ENABLE_TEST) test_read_format_zip_zip64.c test_read_format_zip_with_invalid_traditional_eocd.c test_read_large.c + test_read_pax_empty_val_no_nl.c test_read_pax_xattr_rht_security_selinux.c test_read_pax_xattr_schily.c test_read_pax_truncated.c diff --git a/libarchive/test/test_read_pax_empty_val_no_nl.c b/libarchive/test/test_read_pax_empty_val_no_nl.c new file mode 100644 index 000000000..f98548875 --- /dev/null +++ b/libarchive/test/test_read_pax_empty_val_no_nl.c @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2025 Tobias Stoeckmann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * Read a pax formatted tar archive that contains an invalid attribute, + * because it does not end in a newline. Additionally, value is empty. + * The pax reader should stop and tar reader should continue with warning. + */ +DEFINE_TEST(test_read_pax_empty_val_no_nl) +{ + char name[] = "test_read_pax_empty_val_no_nl.tar"; + struct archive_entry *ae; + struct archive *a; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); + + /* Read first entry. */ + assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae)); + assertEqualString("empty", archive_entry_pathname(ae)); + assertEqualInt(1748163748, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_uid(ae)); + assertEqualString("root", archive_entry_uname(ae)); + assertEqualInt(0, archive_entry_gid(ae)); + assertEqualString("root", archive_entry_gname(ae)); + assertEqualInt(0100600, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_pax_empty_val_no_nl.tar.uu b/libarchive/test/test_read_pax_empty_val_no_nl.tar.uu new file mode 100644 index 000000000..5de8b25ec --- /dev/null +++ b/libarchive/test/test_read_pax_empty_val_no_nl.tar.uu @@ -0,0 +1,60 @@ +begin 600 test_read_pax_empty_val_no_nl.tar +M4&%X2&5A9&5R+V5M<'1Y```````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````#`P,#8P,"``,#`P,#`P(``P,#`P,#`@`#`P,#`P,#`P,#`T +M(#$U,#$T-34V,C0T(#`Q-#`U-@`@>``````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!U