From: Kaif Khan Date: Tue, 7 Jul 2026 08:49:03 +0000 (+0530) Subject: mtree: fix out-of-bounds read in process_global_set X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5c61644fdb7970fb4bbf444242ea0096168eecb0;p=thirdparty%2Flibarchive.git mtree: fix out-of-bounds read in process_global_set --- diff --git a/libarchive/archive_read_support_format_mtree.c b/libarchive/archive_read_support_format_mtree.c index ade200f11..2f88361ca 100644 --- a/libarchive/archive_read_support_format_mtree.c +++ b/libarchive/archive_read_support_format_mtree.c @@ -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; diff --git a/libarchive/test/test_read_format_mtree.c b/libarchive/test/test_read_format_mtree.c index e95bdabc3..a38b27038 100644 --- a/libarchive/test/test_read_format_mtree.c +++ b/libarchive/test/test_read_format_mtree.c @@ -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)); +}