From: Tobias Stoeckmann Date: Mon, 20 Apr 2026 18:29:17 +0000 (+0200) Subject: iso9660: Add Rock Ridge regression test X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f105880eb078f6d9ff35d71c27e27e2fa9082d59;p=thirdparty%2Flibarchive.git iso9660: Add Rock Ridge regression test The Rock Ridge rr_move functionality for paths with a depth larger than 8 has a few bugs in it. For one, it might loop over the same entries over and over. And second, rr_move/ directory entries are not verified to be unique. Both issues can lead to NULL pointer dereferences. Add a test case which highlights the NULL pointer dereference. Based on issue #2936. --- diff --git a/Makefile.am b/Makefile.am index 2ea6c3ad6..9d9a637a9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -666,6 +666,7 @@ libarchive_test_SOURCES= \ libarchive/test/test_write_format_iso9660_empty.c \ libarchive/test/test_write_format_iso9660_filename.c \ libarchive/test/test_write_format_iso9660_joliet_id.c \ + libarchive/test/test_write_format_iso9660_rockridge.c \ libarchive/test/test_write_format_iso9660_zisofs.c \ libarchive/test/test_write_format_mtree.c \ libarchive/test/test_write_format_mtree_absolute.c \ diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt index 4f81d8800..6cd95ce00 100644 --- a/libarchive/test/CMakeLists.txt +++ b/libarchive/test/CMakeLists.txt @@ -297,6 +297,7 @@ IF(ENABLE_TEST) test_write_format_iso9660_empty.c test_write_format_iso9660_filename.c test_write_format_iso9660_joliet_id.c + test_write_format_iso9660_rockridge.c test_write_format_iso9660_zisofs.c test_write_format_iso9660_bugs.c test_write_format_mtree.c diff --git a/libarchive/test/test_write_format_iso9660_rockridge.c b/libarchive/test/test_write_format_iso9660_rockridge.c new file mode 100644 index 000000000..db07231ea --- /dev/null +++ b/libarchive/test/test_write_format_iso9660_rockridge.c @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 2026 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" + +DEFINE_TEST(test_write_format_iso9660_rockridge) +{ + struct archive *a; + struct archive_entry *ae; + unsigned char *buff; + size_t buffsize = 128 * 2048; + size_t used; + + buff = malloc(buffsize); + assert(buff != NULL); + if (buff == NULL) + return; + + /* ISO9660 format: Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_iso9660(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_set_bytes_per_block(a, 1)); + assertA(0 == archive_write_set_bytes_in_last_block(a, 1)); + assertA(0 == archive_write_open_memory(a, buff, buffsize, &used)); + + /* Add a file with a depth of 16. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 0); + archive_entry_set_ctime(ae, 4, 0); + archive_entry_set_mtime(ae, 5, 0); + archive_entry_copy_pathname(ae, "1/2/3/4/5/6/7/8/9/A/B/C/D/E/F"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* XXX - Known to fail currently. */ + assertEqualIntA(a, ARCHIVE_FATAL, archive_write_close(a)); + + /* Close out the archive. */ + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + free(buff); +}