From 450feb0f95636a7622e3c4b1e14ba33253a8c5c9 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Wed, 17 Apr 2019 11:14:49 -0700 Subject: [PATCH] [libzstd] Fix ZSTD_decompressBound() on bad skippable frames The function didn't verify that the skippable frame size is correct. --- lib/decompress/zstd_decompress.c | 5 ++++- lib/legacy/zstd_legacy.h | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 675596f5a..b839a274f 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -467,6 +467,9 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize if ((srcSize >= ZSTD_SKIPPABLEHEADERSIZE) && (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize); + if (frameSizeInfo.compressedSize > srcSize) { + return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong)); + } return frameSizeInfo; } else { const BYTE* ip = (const BYTE*)src; @@ -529,7 +532,6 @@ size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize) return frameSizeInfo.compressedSize; } - /** ZSTD_decompressBound() : * compatible with legacy mode * `src` must point to the start of a ZSTD frame or a skippeable frame @@ -546,6 +548,7 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize) unsigned long long const decompressedBound = frameSizeInfo.decompressedBound; if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR) return ZSTD_CONTENTSIZE_ERROR; + assert(srcSize >= compressedSize); src = (const BYTE*)src + compressedSize; srcSize -= compressedSize; bound += decompressedBound; diff --git a/lib/legacy/zstd_legacy.h b/lib/legacy/zstd_legacy.h index e5b383ee4..27f887024 100644 --- a/lib/legacy/zstd_legacy.h +++ b/lib/legacy/zstd_legacy.h @@ -238,6 +238,10 @@ MEM_STATIC ZSTD_frameSizeInfo ZSTD_findFrameSizeInfoLegacy(const void *src, size frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR; break; } + if (frameSizeInfo.compressedSize > srcSize) { + frameSizeInfo.compressedSize = ERROR(srcSize_wrong); + frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR; + } return frameSizeInfo; }