From: lutianxiong Date: Thu, 20 Aug 2020 11:09:03 +0000 (+0800) Subject: Add a loop checker in read_data_compressed to avoid stack overflow. X-Git-Tag: v3.5.0~2^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F1429%2Fhead;p=thirdparty%2Flibarchive.git Add a loop checker in read_data_compressed to avoid stack overflow. Signed-off-by: lutianxiong --- diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c index 98efbb1a6..283a96044 100644 --- a/libarchive/archive_read_support_format_rar.c +++ b/libarchive/archive_read_support_format_rar.c @@ -151,6 +151,9 @@ #undef minimum #define minimum(a, b) ((a)<(b)?(a):(b)) +/* Stack overflow check */ +#define MAX_COMPRESS_DEPTH 1024 + /* Fields common to all headers */ struct rar_header { @@ -340,7 +343,7 @@ static int read_symlink_stored(struct archive_read *, struct archive_entry *, static int read_data_stored(struct archive_read *, const void **, size_t *, int64_t *); static int read_data_compressed(struct archive_read *, const void **, size_t *, - int64_t *); + int64_t *, size_t); static int rar_br_preparation(struct archive_read *, struct rar_br *); static int parse_codes(struct archive_read *); static void free_codes(struct archive_read *); @@ -1026,7 +1029,7 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff, case COMPRESS_METHOD_NORMAL: case COMPRESS_METHOD_GOOD: case COMPRESS_METHOD_BEST: - ret = read_data_compressed(a, buff, size, offset); + ret = read_data_compressed(a, buff, size, offset, 0); if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN) { __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context); rar->start_new_table = 1; @@ -1883,8 +1886,11 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size, static int read_data_compressed(struct archive_read *a, const void **buff, size_t *size, - int64_t *offset) + int64_t *offset, size_t looper) { + if (looper++ > MAX_COMPRESS_DEPTH) + return (ARCHIVE_FATAL); + struct rar *rar; int64_t start, end, actualend; size_t bs; @@ -1982,7 +1988,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, { case 0: rar->start_new_table = 1; - return read_data_compressed(a, buff, size, offset); + return read_data_compressed(a, buff, size, offset, looper); case 2: rar->ppmd_eod = 1;/* End Of ppmd Data. */