]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
mtree: fix out-of-bounds read in process_global_set 3258/head
authorKaif Khan <kaif@bugqore.com>
Tue, 7 Jul 2026 08:49:03 +0000 (14:19 +0530)
committerKaif Khan <kaif@bugqore.com>
Tue, 7 Jul 2026 08:49:03 +0000 (14:19 +0530)
libarchive/archive_read_support_format_mtree.c
libarchive/test/test_read_format_mtree.c

index ade200f1140fb2cc5b00cfd835564ef5e61f961f..2f88361caacde182b30450d6225a484ef5751f68 100644 (file)
@@ -826,7 +826,7 @@ process_global_set(struct archive_read *a,
                line = next;
                next = line + strcspn(line, " \t\r\n");
                eq = strchr(line, '=');
-               if (eq > next)
+               if (eq == NULL || eq > next)
                        len = next - line;
                else
                        len = eq - line;
index e95bdabc39231b205d7212a4b68ad588496fbc8d..a38b27038a43538f264f567325c3f009e843188e 100644 (file)
@@ -878,3 +878,35 @@ DEFINE_TEST(test_read_format_mtree_nano)
        assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
        assertEqualInt(ARCHIVE_OK, archive_read_free(a));
 }
+
+/*
+ * A /set line whose value-less keyword (no '=') repeats made
+ * process_global_set() compute a bogus length and over-read the option
+ * buffer in remove_option().  Parsing must stay in bounds and succeed.
+ */
+DEFINE_TEST(test_read_format_mtree_global_set_no_value)
+{
+       static char archive[] =
+           "#mtree\n"
+           "/set nochange nochange\n"
+           "a type=file\n";
+       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));
+       assertEqualIntA(a, ARCHIVE_OK,
+           archive_read_open_memory(a, archive, sizeof(archive)));
+
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+       assertEqualString(archive_entry_pathname(ae), "a");
+       assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
+
+       assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+       assertEqualInt(1, archive_file_count(a));
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
+       assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}