From: Sen Huang Date: Tue, 2 Mar 2021 22:30:03 +0000 (-0800) Subject: Fix seekable decompress hanging X-Git-Tag: v1.4.10~29^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=527a20c3cdd8d5d887e82213e2aad42f050b68ce;p=thirdparty%2Fzstd.git Fix seekable decompress hanging --- diff --git a/contrib/seekable_format/tests/seekable_tests.c b/contrib/seekable_format/tests/seekable_tests.c index 44efe2b01..2a159a319 100644 --- a/contrib/seekable_format/tests/seekable_tests.c +++ b/contrib/seekable_format/tests/seekable_tests.c @@ -53,7 +53,7 @@ int main(int argc, const char** argv) } printf("Success!\n"); - printf("Test %u - check that seekable decompress does not hang: ", testNb++); + printf("Test %u - check #2 that seekable decompress does not hang: ", testNb++); { /* Github issue #FIXME */ const size_t compressed_size = 27; const uint8_t compressed_data[27] = { @@ -85,8 +85,8 @@ int main(int argc, const char** argv) '\x92', '\x8f', }; - const size_t uncompressed_size = 8936; - uint8_t uncompressed_data[8936]; + const size_t uncompressed_size = 400; + uint8_t uncompressed_data[400]; ZSTD_seekable* stream = ZSTD_seekable_create(); size_t status = ZSTD_seekable_initBuff(stream, compressed_data, compressed_size); diff --git a/contrib/seekable_format/zstdseek_decompress.c b/contrib/seekable_format/zstdseek_decompress.c index 4f76158e2..ed0880ef8 100644 --- a/contrib/seekable_format/zstdseek_decompress.c +++ b/contrib/seekable_format/zstdseek_decompress.c @@ -383,6 +383,7 @@ size_t ZSTD_seekable_decompress(ZSTD_seekable* zs, void* dst, size_t len, unsign { U32 targetFrame = ZSTD_seekable_offsetToFrameIndex(zs, offset); U32 noOutputProgressCount = 0; + size_t srcBytesRead = 0; do { /* check if we can continue from a previous decompress job */ if (targetFrame != zs->curFrame || offset != zs->decompressedOffset) { @@ -395,12 +396,16 @@ size_t ZSTD_seekable_decompress(ZSTD_seekable* zs, void* dst, size_t len, unsign zs->in = (ZSTD_inBuffer){zs->inBuff, 0, 0}; XXH64_reset(&zs->xxhState, 0); ZSTD_DCtx_reset(zs->dstream, ZSTD_reset_session_only); + if (srcBytesRead > zs->buffWrapper.size) { + return ERROR(seekableIO); + } } while (zs->decompressedOffset < offset + len) { size_t toRead; ZSTD_outBuffer outTmp; size_t prevOutPos; + size_t prevInPos; size_t forwardProgress; if (zs->decompressedOffset < offset) { /* dummy decompressions until we get to the target offset */ @@ -410,6 +415,7 @@ size_t ZSTD_seekable_decompress(ZSTD_seekable* zs, void* dst, size_t len, unsign } prevOutPos = outTmp.pos; + prevInPos = zs->in.pos; toRead = ZSTD_decompressStream(zs->dstream, &outTmp, &zs->in); if (ZSTD_isError(toRead)) { return toRead; @@ -428,6 +434,7 @@ size_t ZSTD_seekable_decompress(ZSTD_seekable* zs, void* dst, size_t len, unsign noOutputProgressCount = 0; } zs->decompressedOffset += forwardProgress; + srcBytesRead += zs->in.pos - prevInPos; if (toRead == 0) { /* frame complete */