From a57125009c99fdd4675b71498987e91fc53a7d2f Mon Sep 17 00:00:00 2001 From: cielavenir Date: Fri, 18 Feb 2022 18:19:12 +0900 Subject: [PATCH] Fix 7z PPMD reading beyond boundary --- libarchive/archive_read_support_format_7zip.c | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/libarchive/archive_read_support_format_7zip.c b/libarchive/archive_read_support_format_7zip.c index 63cbb7df3..f15374f7a 100644 --- a/libarchive/archive_read_support_format_7zip.c +++ b/libarchive/archive_read_support_format_7zip.c @@ -287,6 +287,7 @@ struct _7zip { const unsigned char *next_in; int64_t avail_in; int64_t total_in; + int64_t stream_in; unsigned char *next_out; int64_t avail_out; int64_t total_out; @@ -986,15 +987,27 @@ ppmd_read(void *p) struct _7zip *zip = (struct _7zip *)(a->format->data); Byte b; - if (zip->ppstream.avail_in == 0) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Truncated RAR file data"); - zip->ppstream.overconsumed = 1; - return (0); + if (zip->ppstream.avail_in <= 0) { + // Ppmd7_DecodeSymbol might require reading multiple bytes and we are on boundary; last resort to read using __archive_read_ahead. + ssize_t bytes_avail = 0; + const uint8_t* data = __archive_read_ahead(a, zip->ppstream.stream_in+1, &bytes_avail); + if(bytes_avail < zip->ppstream.stream_in+1) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7z file data"); + zip->ppstream.overconsumed = 1; + return (0); + } + zip->ppstream.next_in++; + b = data[zip->ppstream.stream_in]; + zip->ppstream.avail_in--; + zip->ppstream.total_in++; + zip->ppstream.stream_in++; + } else { + b = *zip->ppstream.next_in++; + zip->ppstream.avail_in--; + zip->ppstream.total_in++; + zip->ppstream.stream_in++; } - b = *zip->ppstream.next_in++; - zip->ppstream.avail_in--; - zip->ppstream.total_in++; return (b); } @@ -1485,6 +1498,7 @@ decompress(struct archive_read *a, struct _7zip *zip, } zip->ppstream.next_in = t_next_in; zip->ppstream.avail_in = t_avail_in; + zip->ppstream.stream_in = 0; zip->ppstream.next_out = t_next_out; zip->ppstream.avail_out = t_avail_out; if (zip->ppmd7_stat == 0) { -- 2.47.2