]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
cpio: fix read-ahead pointer lifetime issue 3277/head
authordatauwu <datauwu@users.noreply.github.com>
Sat, 11 Jul 2026 04:06:46 +0000 (12:06 +0800)
committerdatauwu <datauwu@users.noreply.github.com>
Sat, 11 Jul 2026 04:11:53 +0000 (12:11 +0800)
Cache the CPIO trailer-name check before consuming the pathname
buffer.

The reader kept a pointer returned by __archive_read_ahead() and used
it after __archive_read_consume(), and after possible symlink body
processing. Read-ahead pointers are views into libarchive input buffers
and should not be relied on after the associated bytes are consumed.

Store the TRAILER!!! decision while the pathname buffer is still valid,
then use the saved boolean after the remaining header handling.

libarchive/archive_read_support_format_cpio.c

index 5df8f9a0b37bee26a3e3b1947ec054f846b1a541..7341aa0c16f5264c114841ccf1c7e3daa804accb 100644 (file)
@@ -369,6 +369,7 @@ archive_read_format_cpio_read_header(struct archive_read *a,
        struct archive_string_conv *sconv;
        size_t namelength;
        size_t name_pad;
+       int is_trailer;
        int r;
 
        cpio = (struct cpio *)(a->format->data);
@@ -411,6 +412,9 @@ archive_read_format_cpio_read_header(struct archive_read *a,
                    archive_string_conversion_charset_name(sconv));
                r = ARCHIVE_WARN;
        }
+       /* Save this before consuming the name buffer below. */
+       is_trailer = (namelength == 11 &&
+           memcmp((const char *)h, "TRAILER!!!", 10) == 0);
        cpio->entry_offset = 0;
 
        __archive_read_consume(a, namelength);
@@ -451,8 +455,7 @@ archive_read_format_cpio_read_header(struct archive_read *a,
         * header.  XXX */
 
        /* Compare name to "TRAILER!!!" to test for end-of-archive. */
-       if (namelength == 11 && strncmp((const char *)h, "TRAILER!!!",
-           10) == 0) {
+       if (is_trailer) {
                /* TODO: Store file location of start of block. */
                archive_clear_error(&a->archive);
                return (ARCHIVE_EOF);