From e1f890dc62f7931d971e2483efd8a3d30a98b1f4 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Sun, 3 May 2026 15:20:33 -0700 Subject: [PATCH] archive_read: make ARCHIVE_FATAL sticky in data-reading entry points Three entry points in archive_read.c could return ARCHIVE_FATAL from the format layer without setting a->archive.state = ARCHIVE_STATE_FATAL, so subsequent API calls would not see the archive as fatally broken: - archive_read_data_skip() unconditionally reset state to HEADER even when the format's skip returned ARCHIVE_FATAL. - archive_seek_data() and _archive_read_data_block() forwarded FATAL from the format layer without recording it in the archive state. Fix all three so that ARCHIVE_FATAL causes the state to become ARCHIVE_STATE_FATAL, consistent with the existing behavior of archive_read_next_header(). --- libarchive/archive_read.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/libarchive/archive_read.c b/libarchive/archive_read.c index e5f89bdc8..f681d3ad6 100644 --- a/libarchive/archive_read.c +++ b/libarchive/archive_read.c @@ -934,7 +934,10 @@ archive_read_data_skip(struct archive *_a) if (r == ARCHIVE_EOF) r = ARCHIVE_OK; - a->archive.state = ARCHIVE_STATE_HEADER; + if (r == ARCHIVE_FATAL) + a->archive.state = ARCHIVE_STATE_FATAL; + else + a->archive.state = ARCHIVE_STATE_HEADER; return (r); } @@ -942,6 +945,8 @@ la_int64_t archive_seek_data(struct archive *_a, int64_t offset, int whence) { struct archive_read *a = (struct archive_read *)_a; + la_int64_t r; + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, "archive_seek_data_block"); @@ -949,10 +954,14 @@ archive_seek_data(struct archive *_a, int64_t offset, int whence) archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, "Internal error: " "No format_seek_data_block function registered"); + a->archive.state = ARCHIVE_STATE_FATAL; return (ARCHIVE_FATAL); } - return (a->format->seek_data)(a, offset, whence); + r = (a->format->seek_data)(a, offset, whence); + if (r == ARCHIVE_FATAL) + a->archive.state = ARCHIVE_STATE_FATAL; + return (r); } /* @@ -968,6 +977,8 @@ _archive_read_data_block(struct archive *_a, const void **buff, size_t *size, int64_t *offset) { struct archive_read *a = (struct archive_read *)_a; + int r; + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, "archive_read_data_block"); @@ -975,10 +986,14 @@ _archive_read_data_block(struct archive *_a, archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, "Internal error: " "No format->read_data function registered"); + a->archive.state = ARCHIVE_STATE_FATAL; return (ARCHIVE_FATAL); } - return (a->format->read_data)(a, buff, size, offset); + r = (a->format->read_data)(a, buff, size, offset); + if (r == ARCHIVE_FATAL) + a->archive.state = ARCHIVE_STATE_FATAL; + return (r); } static int -- 2.47.3