]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Merge pull request #3095 from stoeckmann/afio_header
authorMartin Matuška <martin@matuska.de>
Mon, 1 Jun 2026 07:54:26 +0000 (09:54 +0200)
committerMartin Matuska <martin@matuska.de>
Tue, 23 Jun 2026 08:56:53 +0000 (10:56 +0200)
cpio: Improve afio header detection
(cherry picked from commit 36d69b3ec81affb13f8b1deadd7dcc8bfeb81459)

Makefile.am
libarchive/archive_read_support_format_cpio.c
libarchive/test/test_read_format_cpio_afio.c
libarchive/test/test_read_format_cpio_afio_header.part1.cpio.uu [new file with mode: 0644]
libarchive/test/test_read_format_cpio_afio_header.part2.cpio.uu [new file with mode: 0644]

index 9d9a637a9797ec41a86ceeea2b89150aa63d3102..feee8b399a8f9b2265c0d0757a3681119a951c6a 100644 (file)
@@ -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 \
index 4fd5f13835f23e294f62893c9214b8c66d916bd2..e108843b3e5b1bd23e8be67d52030eb46352db14 100644 (file)
@@ -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);
index be386e1f40c3fa1b524c288f646cc842b18976aa..a1fb683e38d49857b1fee632c80d0fb84e561075 100644 (file)
@@ -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 (file)
index 0000000..0d06cb2
--- /dev/null
@@ -0,0 +1,5 @@
+begin 644 test_read_format_cpio_afio_header.part1.cpio
+M,#<P-S(W,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P;3`P,#`P,#`P,#`P,#`P
+?,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,```
+`
+end
diff --git a/libarchive/test/test_read_format_cpio_afio_header.part2.cpio.uu b/libarchive/test/test_read_format_cpio_afio_header.part2.cpio.uu
new file mode 100644 (file)
index 0000000..0a3d595
--- /dev/null
@@ -0,0 +1,4 @@
+begin 644 test_read_format_cpio_afio_header.part2.cpio
+I,#`P,#`P,#`P;C`P,#$P,#`P,#`P,',P,#`P,#`P,#`P,#`P,#`P.F$`
+`
+end