From: datauwu Date: Fri, 17 Jul 2026 16:05:01 +0000 (+0800) Subject: archive_write: test format switch UAF cleanup X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9c805a24ea9db1879da588544cbcb62bc1815e5c;p=thirdparty%2Flibarchive.git archive_write: test format switch UAF cleanup Test that unregistering 7-Zip and XAR clears format state and is safe to repeat. Also test switching from 7-Zip to GNU tar and selecting GNU tar again. --- diff --git a/libarchive/test/test_write_format_7zip.c b/libarchive/test/test_write_format_7zip.c index ef5b40906..43a86bb70 100644 --- a/libarchive/test/test_write_format_7zip.c +++ b/libarchive/test/test_write_format_7zip.c @@ -26,6 +26,9 @@ #include "test.h" +#define __LIBARCHIVE_TEST +#include "archive_write_private.h" + static void test_basic(const char *compression_type) { @@ -573,3 +576,39 @@ DEFINE_TEST(test_write_format_7zip_basic_zstd) /* Test that making a 7-Zip archive file with zstandard compression. */ test_basic("zstd"); } + +DEFINE_TEST(test_write_format_7zip_unregister) +{ + struct archive *a; + struct archive_write *aw; + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_7zip(a)); + + aw = (struct archive_write *)a; + assert(aw->format_data != NULL); + assert(aw->format_free != NULL); + + assertEqualIntA(a, ARCHIVE_OK, + __archive_write_unregister_format(aw)); + + assert(aw->format_data == NULL); + assert(aw->format_name == NULL); + assert(aw->format_init == NULL); + assert(aw->format_options == NULL); + assert(aw->format_finish_entry == NULL); + assert(aw->format_write_header == NULL); + assert(aw->format_write_data == NULL); + assert(aw->format_close == NULL); + assert(aw->format_free == NULL); + assertEqualInt(0, aw->archive.archive_format); + assert(aw->archive.archive_format_name == NULL); + + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_format_option(a, NULL, "compression", + "store")); + + assertEqualIntA(a, ARCHIVE_OK, + __archive_write_unregister_format(aw)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); +} diff --git a/libarchive/test/test_write_format_gnutar.c b/libarchive/test/test_write_format_gnutar.c index 213efe3a6..00dc516d7 100644 --- a/libarchive/test/test_write_format_gnutar.c +++ b/libarchive/test/test_write_format_gnutar.c @@ -278,3 +278,14 @@ DEFINE_TEST(test_write_format_gnutar) free(buff); } + +DEFINE_TEST(test_write_format_gnutar_switch) +{ + struct archive *a; + + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_7zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_gnutar(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_gnutar(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); +} diff --git a/libarchive/test/test_write_format_xar.c b/libarchive/test/test_write_format_xar.c index 495400a34..bb24fffc3 100644 --- a/libarchive/test/test_write_format_xar.c +++ b/libarchive/test/test_write_format_xar.c @@ -25,6 +25,9 @@ */ #include "test.h" +#define __LIBARCHIVE_TEST +#include "archive_write_private.h" + #include static void @@ -380,3 +383,43 @@ DEFINE_TEST(test_write_format_xar_entry_trunc) assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); } + +DEFINE_TEST(test_write_format_xar_unregister) +{ + struct archive *a; + struct archive_write *aw; + + assert((a = archive_write_new()) != NULL); + if (archive_write_set_format_xar(a) != ARCHIVE_OK) { + skipping("xar is not supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + return; + } + + aw = (struct archive_write *)a; + assert(aw->format_data != NULL); + assert(aw->format_free != NULL); + + assertEqualIntA(a, ARCHIVE_OK, + __archive_write_unregister_format(aw)); + + assert(aw->format_data == NULL); + assert(aw->format_name == NULL); + assert(aw->format_init == NULL); + assert(aw->format_options == NULL); + assert(aw->format_finish_entry == NULL); + assert(aw->format_write_header == NULL); + assert(aw->format_write_data == NULL); + assert(aw->format_close == NULL); + assert(aw->format_free == NULL); + assertEqualInt(0, aw->archive.archive_format); + assert(aw->archive.archive_format_name == NULL); + + assertEqualIntA(a, ARCHIVE_FAILED, + archive_write_set_format_option(a, NULL, "compression", + "gzip")); + + assertEqualIntA(a, ARCHIVE_OK, + __archive_write_unregister_format(aw)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); +}