From 1e406c9ea204a8bca9067c40edb60e6c8ae168e6 Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Mon, 6 May 2024 00:40:57 +0200 Subject: [PATCH] uu: Stop processing if lines are too long (#2168) Processing excessively long lines could lead to out of boundary writes or denial of service due to O(n^2) runtime complexity. The OOB is properly fixed with first commit. The second commit stops processing of lines which are longer than uu allows due to its specification. --- libarchive/archive_read_support_filter_uu.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libarchive/archive_read_support_filter_uu.c b/libarchive/archive_read_support_filter_uu.c index 689ceb8f8..7563e861e 100644 --- a/libarchive/archive_read_support_filter_uu.c +++ b/libarchive/archive_read_support_filter_uu.c @@ -43,11 +43,13 @@ /* Maximum lookahead during bid phase */ #define UUENCODE_BID_MAX_READ 128*1024 /* in bytes */ +#define UUENCODE_MAX_LINE_LENGTH 34*1024 /* in bytes */ + struct uudecode { int64_t total; unsigned char *in_buff; #define IN_BUFF_SIZE (1024) - int in_cnt; + ssize_t in_cnt; size_t in_allocated; unsigned char *out_buff; #define OUT_BUFF_SIZE (64 * 1024) @@ -484,6 +486,12 @@ read_more: goto finish; } if (uudecode->in_cnt) { + if (uudecode->in_cnt > UUENCODE_MAX_LINE_LENGTH) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid format data"); + return (ARCHIVE_FATAL); + } /* * If there is remaining data which is saved by * previous calling, use it first. @@ -533,7 +541,7 @@ read_more: return (ARCHIVE_FATAL); if (uudecode->in_buff != b) memmove(uudecode->in_buff, b, len); - uudecode->in_cnt = (int)len; + uudecode->in_cnt = len; if (total == 0) { /* Do not return 0; it means end-of-file. * We should try to read bytes more. */ -- 2.47.2