summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcielavenir <cielartisan@gmail.com>2022-02-18 18:19:12 +0900
committercielavenir <cielartisan@gmail.com>2022-02-18 18:19:12 +0900
commita57125009c99fdd4675b71498987e91fc53a7d2f (patch)
tree38780dfa6a1d4da6c13cd822161a81751ac2c32b
parent93f03b0f5d7316714df9b289a49150ab7a63bfaf (diff)
downloadlibarchive-a57125009c99fdd4675b71498987e91fc53a7d2f.tar.gz
Fix 7z PPMD reading beyond boundary
-rw-r--r--libarchive/archive_read_support_format_7zip.c30
1 files changed, 22 insertions, 8 deletions
diff --git a/libarchive/archive_read_support_format_7zip.c b/libarchive/archive_read_support_format_7zip.c
index 63cbb7df..f15374f7 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) {