From: Martin Matuška Date: Mon, 1 Jun 2026 07:54:26 +0000 (+0200) Subject: Merge pull request #3095 from stoeckmann/afio_header X-Git-Tag: v3.8.8~74 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0332996f6fd8beaeeaba429f904c90ea1dce2e11;p=thirdparty%2Flibarchive.git Merge pull request #3095 from stoeckmann/afio_header cpio: Improve afio header detection (cherry picked from commit 36d69b3ec81affb13f8b1deadd7dcc8bfeb81459) --- diff --git a/Makefile.am b/Makefile.am index 9d9a637a9..feee8b399 100644 --- a/Makefile.am +++ b/Makefile.am @@ -897,6 +897,8 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_cab_filename_cp932.cab.uu \ libarchive/test/test_read_format_cab_lzx_oob.cab.uu \ libarchive/test/test_read_format_cab_skip_malformed.cab.uu \ + libarchive/test/test_read_format_cpio_afio_header.part1.cpio.uu \ + libarchive/test/test_read_format_cpio_afio_header.part2.cpio.uu \ libarchive/test/test_read_format_cpio_bin_be.cpio.uu \ libarchive/test/test_read_format_cpio_bin_le.cpio.uu \ libarchive/test/test_read_format_cpio_filename_cp866.cpio.uu \ diff --git a/libarchive/archive_read_support_format_cpio.c b/libarchive/archive_read_support_format_cpio.c index 4fd5f1383..e108843b3 100644 --- a/libarchive/archive_read_support_format_cpio.c +++ b/libarchive/archive_read_support_format_cpio.c @@ -713,13 +713,24 @@ find_odc_header(struct archive_read *a) { const void *h; const char *p, *q; - size_t skip, skipped = 0; + int64_t skip; + uintmax_t skipped = 0; ssize_t bytes; for (;;) { - h = __archive_read_ahead(a, odc_header_size, &bytes); - if (h == NULL) - return (ARCHIVE_FATAL); + size_t header_size; + + header_size = afiol_header_size; + h = __archive_read_ahead(a, afiol_header_size, &bytes); + if (h == NULL) { + if (bytes >= odc_header_size) { + header_size = odc_header_size; + h = __archive_read_ahead(a, odc_header_size, + &bytes); + } + if (h == NULL) + return (ARCHIVE_FATAL); + } p = h; q = p + bytes; @@ -735,7 +746,7 @@ find_odc_header(struct archive_read *a) * Scan ahead until we find something that looks * like an odc header. */ - while (p + odc_header_size <= q) { + while (p + header_size <= q) { switch (p[5]) { case '7': if ((memcmp("070707", p, 6) == 0 @@ -751,9 +762,9 @@ find_odc_header(struct archive_read *a) if (skipped > 0) { archive_set_error(&a->archive, 0, - "Skipped %d bytes before " + "Skipped %ju bytes before " "finding valid header", - (int)skipped); + skipped); return (ARCHIVE_WARN); } return (ARCHIVE_OK); diff --git a/libarchive/test/test_read_format_cpio_afio.c b/libarchive/test/test_read_format_cpio_afio.c index be386e1f4..a1fb683e3 100644 --- a/libarchive/test/test_read_format_cpio_afio.c +++ b/libarchive/test/test_read_format_cpio_afio.c @@ -125,3 +125,27 @@ DEFINE_TEST(test_read_format_cpio_afio_broken) assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_AFIO_LARGE); archive_read_free(a); } + +DEFINE_TEST(test_read_format_cpio_afio_header) +{ + const char *reffiles[] = + { + "test_read_format_cpio_afio_header.part1.cpio", + "test_read_format_cpio_afio_header.part2.cpio", + NULL + }; + struct archive_entry *ae; + struct archive *a; + + extract_reference_files(reffiles); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_format_cpio(a)); + assertA(0 == archive_read_open_filenames(a, reffiles, 10240)); + + /* File "a" */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("a", archive_entry_pathname(ae)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_format_cpio_afio_header.part1.cpio.uu b/libarchive/test/test_read_format_cpio_afio_header.part1.cpio.uu new file mode 100644 index 000000000..0d06cb299 --- /dev/null +++ b/libarchive/test/test_read_format_cpio_afio_header.part1.cpio.uu @@ -0,0 +1,5 @@ +begin 644 test_read_format_cpio_afio_header.part1.cpio +M,#