From a11a9271d6c5946a6f29e358e2a297ceef8f0a56 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 17 Jan 2020 12:05:53 -0800 Subject: [PATCH 1/2] Fix lowLimit underflow in overflow correction --- lib/compress/zstd_compress_internal.h | 18 +++++++++++++++--- tests/playTests.sh | 4 ++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index c76189cc..243f0e07 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -745,7 +745,10 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog, */ U32 const cycleMask = (1U << cycleLog) - 1; U32 const current = (U32)((BYTE const*)src - window->base); - U32 const newCurrent = (current & cycleMask) + maxDist; + U32 const currentCycle0 = current & cycleMask; + /* Exclude zero so that newCurrent - maxDist >= 1. */ + U32 const currentCycle1 = currentCycle0 == 0 ? (1U << cycleLog) : currentCycle0; + U32 const newCurrent = currentCycle1 + maxDist; U32 const correction = current - newCurrent; assert((maxDist & cycleMask) == 0); assert(current > newCurrent); @@ -754,8 +757,17 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog, window->base += correction; window->dictBase += correction; - window->lowLimit -= correction; - window->dictLimit -= correction; + if (window->lowLimit <= correction) window->lowLimit = 1; + else window->lowLimit -= correction; + if (window->dictLimit <= correction) window->dictLimit = 1; + else window->dictLimit -= correction; + + /* Ensure we can still reference the full window. */ + assert(newCurrent >= maxDist); + assert(newCurrent - maxDist >= 1); + /* Ensure that lowLimit and dictLimit didn't underflow. */ + assert(window->lowLimit <= newCurrent); + assert(window->dictLimit <= newCurrent); DEBUGLOG(4, "Correction of 0x%x bytes to lowLimit=0x%x", correction, window->lowLimit); diff --git a/tests/playTests.sh b/tests/playTests.sh index ffb455a8..52cbf7d3 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -1239,8 +1239,8 @@ roundTripTest -g18000017 -P88 17 roundTripTest -g18000018 -P94 18 roundTripTest -g18000019 -P96 19 -roundTripTest -g5000000000 -P99 1 -roundTripTest -g1700000000 -P0 "1 --zstd=strategy=6" # ensure btlazy2 can survive an overflow rescale +roundTripTest -g5000000000 -P99 "1 --zstd=wlog=27" +roundTripTest -g3700000000 -P0 "1 --zstd=strategy=6,wlog=27" # ensure btlazy2 can survive an overflow rescale fileRoundTripTest -g4193M -P99 1 From 009f388457101bcc73d08e10d2ec241acae4cc65 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 17 Jan 2020 14:20:44 -0800 Subject: [PATCH 2/2] Fix playTests.sh for 32-bit mode --- tests/playTests.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/playTests.sh b/tests/playTests.sh index 52cbf7d3..6ae5bd8c 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -1239,8 +1239,8 @@ roundTripTest -g18000017 -P88 17 roundTripTest -g18000018 -P94 18 roundTripTest -g18000019 -P96 19 -roundTripTest -g5000000000 -P99 "1 --zstd=wlog=27" -roundTripTest -g3700000000 -P0 "1 --zstd=strategy=6,wlog=27" # ensure btlazy2 can survive an overflow rescale +roundTripTest -g5000000000 -P99 "1 --zstd=wlog=25" +roundTripTest -g3700000000 -P0 "1 --zstd=strategy=6,wlog=25" # ensure btlazy2 can survive an overflow rescale fileRoundTripTest -g4193M -P99 1