diff options
author | lutianxiong <lutianxiong@huawei.com> | 2020-08-20 19:09:03 +0800 |
---|---|---|
committer | lutianxiong <lutianxiong@huawei.com> | 2020-08-20 19:09:03 +0800 |
commit | 4e575be32d0d128fa046ca74353d1ac880436948 (patch) | |
tree | 0edc80819b6d4500f4fd0fa59b06f47255a30b0c | |
parent | 34940ef6ea0b21d77cb501d235164ad88f19d40c (diff) | |
download | libarchive-4e575be32d0d128fa046ca74353d1ac880436948.tar.gz |
Add a loop checker in read_data_compressed to avoid stack overflow.
Signed-off-by: lutianxiong <lutianxiong@huawei.com>
-rw-r--r-- | libarchive/archive_read_support_format_rar.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c index 98efbb1a..283a9604 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. */ |