]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
archive_write: test format switch UAF cleanup
authordatauwu <datauwu@users.noreply.github.com>
Fri, 17 Jul 2026 16:05:01 +0000 (00:05 +0800)
committerdatauwu <datauwu@users.noreply.github.com>
Fri, 17 Jul 2026 16:05:01 +0000 (00:05 +0800)
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.

libarchive/test/test_write_format_7zip.c
libarchive/test/test_write_format_gnutar.c
libarchive/test/test_write_format_xar.c

index ef5b40906d163f641e6a405aa4341deb9c096327..43a86bb70de2968889923876ffdf218ab0e815bc 100644 (file)
@@ -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));
+}
index 213efe3a60865b0af771b5f364b11820e35aa030..00dc516d7db0f69651cb3e5738a86b5f469c5acd 100644 (file)
@@ -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));
+}
index 495400a34f921a6a6964df90e7e5bc9fcb1fd08c..bb24fffc3f311036d674879e9e388469487266fc 100644 (file)
@@ -25,6 +25,9 @@
  */
 #include "test.h"
 
+#define __LIBARCHIVE_TEST
+#include "archive_write_private.h"
+
 #include <locale.h>
 
 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));
+}