From 847a5c72d6aaa865fe3f0c7e8606bedac1e4a1c0 Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Wed, 10 Apr 2024 22:59:40 +0200 Subject: [PATCH] xar: Avoid infinite link loop (#2123) A file may have only one link target at a time. Otherwise the internal link structure could loop. Besides, a hard link realistically can only link to one file, not multiple ones. Consider such an archive invalid. Co-authored-by: Martin Matuska --- Makefile.am | 2 + libarchive/archive_read_support_format_xar.c | 5 ++ libarchive/test/CMakeLists.txt | 1 + .../test/test_read_format_xar_doublelink.c | 51 +++++++++++++++++++ .../test_read_foxmat_xar_doublelink.xar.uu | 12 +++++ 5 files changed, 71 insertions(+) create mode 100644 libarchive/test/test_read_format_xar_doublelink.c create mode 100644 libarchive/test/test_read_foxmat_xar_doublelink.xar.uu diff --git a/Makefile.am b/Makefile.am index 286f08694c..47b6fa1fc6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -528,6 +528,7 @@ libarchive_test_SOURCES= \ libarchive/test/test_read_format_ustar_filename.c \ libarchive/test/test_read_format_warc.c \ libarchive/test/test_read_format_xar.c \ + libarchive/test/test_read_format_xar_doublelink.c \ libarchive/test/test_read_format_zip.c \ libarchive/test/test_read_format_zip_7075_utf8_paths.c \ libarchive/test/test_read_format_zip_comment_stored.c \ @@ -932,6 +933,7 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_ustar_filename_eucjp.tar.Z.uu \ libarchive/test/test_read_format_ustar_filename_koi8r.tar.Z.uu \ libarchive/test/test_read_format_warc.warc.uu \ + libarchive/test/test_read_format_xar_doublelink.xar.uu \ libarchive/test/test_read_format_zip.zip.uu \ libarchive/test/test_read_format_zip_7075_utf8_paths.zip.uu \ libarchive/test/test_read_format_zip_7z_deflate.zip.uu \ diff --git a/libarchive/archive_read_support_format_xar.c b/libarchive/archive_read_support_format_xar.c index fd63594373..2c34326429 100644 --- a/libarchive/archive_read_support_format_xar.c +++ b/libarchive/archive_read_support_format_xar.c @@ -2055,6 +2055,11 @@ xml_start(struct archive_read *a, const char *name, struct xmlattr_list *list) attr = attr->next) { if (strcmp(attr->name, "link") != 0) continue; + if (xar->file->hdnext != NULL || xar->file->link != 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "File with multiple link targets"); + return (ARCHIVE_FATAL); + } if (strcmp(attr->value, "original") == 0) { xar->file->hdnext = xar->hdlink_orgs; xar->hdlink_orgs = xar->file; diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt index 8209c25a5f..7b166c5fba 100644 --- a/libarchive/test/CMakeLists.txt +++ b/libarchive/test/CMakeLists.txt @@ -172,6 +172,7 @@ IF(ENABLE_TEST) test_read_format_ustar_filename.c test_read_format_warc.c test_read_format_xar.c + test_read_format_xar_doublelink.c test_read_format_zip.c test_read_format_zip_7075_utf8_paths.c test_read_format_zip_comment_stored.c diff --git a/libarchive/test/test_read_format_xar_doublelink.c b/libarchive/test/test_read_format_xar_doublelink.c new file mode 100644 index 0000000000..ed6d0f0fd0 --- /dev/null +++ b/libarchive/test/test_read_format_xar_doublelink.c @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2024 Martin Matuska + * 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" + +#define __LIBARCHIVE_BUILD + +DEFINE_TEST(test_read_format_xar_doublelink) +{ + const char *refname = "test_read_foxmat_xar_doublelink.xar"; + struct archive *a; + struct archive_entry *ae; + + extract_reference_file(refname); + + /* Verify with seeking reader. */ + 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)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, + 10240)); + + assertA(ARCHIVE_FATAL == archive_read_next_header(a, &ae)); + assertEqualString(archive_error_string(a), + "File with multiple link targets"); + assert(archive_errno(a) != 0); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_foxmat_xar_doublelink.xar.uu b/libarchive/test/test_read_foxmat_xar_doublelink.xar.uu new file mode 100644 index 0000000000..5fed96af9d --- /dev/null +++ b/libarchive/test/test_read_foxmat_xar_doublelink.xar.uu @@ -0,0 +1,12 @@ +begin 664 test_read_foxmat_xar_doublelink.xar +M>&%R(0`<``$````````!0`````````/7`````7B<[9/!D3&``]'1?GT!-1U;;:=[5[G<=WB0=P>^..@![<%Y94V# +M\R>*$9C6=LKT#7Y;OF8O>"%F_""=F"$^VC9\$&\=R#'LR$:E03#*RHR6&2N6 +MM*KIO,YS3JZ1M&D-[<;O-/+C<8`&^[7,<:P@;E:;52`R#5A6N?VQ@9CHIN.#_IY(['+:!!F4V#K5.],G+`8BU=%SU.8OF? +MH#*V`U%5K"@9)Z=5*G2P5RT8*YY+3J9%*ND(T?D\%/3$[U0GJ=W6T3=E+);&^E4=0%?0^#N\00;G(;8U7`]!