[bug-fix] Fix a determinism bug with the DUBT

The DUBT can be non-deterministic if an index is equal to
`ZSTD_DUBT_UNSORTED_MARK`. Ensure that never happens by starting the
indices at 2.

This bug was found by the OSS-Fuzz determinism fuzzer. With this change
the fuzzer test passes. And I've confirmed that this is the root cause,
not just hiding the problem.

Aside: This took me a long time to figure out, because I thought I had
tried this first thing. But, apparantly I messed it up, because when I
was going through it again with @felixhandte, I was pointing out that it
wasn't the case, but it turns out it was.

Credit to: OSS-Fuzz
This commit is contained in:
Nick Terrell 2021-07-15 12:14:44 -07:00
parent b18febe52c
commit ba044bd6f1

View File

@ -199,6 +199,8 @@ typedef struct {
*/ */
} ZSTD_window_t; } ZSTD_window_t;
#define ZSTD_WINDOW_START_INDEX 2
typedef struct ZSTD_matchState_t ZSTD_matchState_t; typedef struct ZSTD_matchState_t ZSTD_matchState_t;
#define ZSTD_ROW_HASH_CACHE_SIZE 8 /* Size of prefetching hash cache for row-based matchfinder */ #define ZSTD_ROW_HASH_CACHE_SIZE 8 /* Size of prefetching hash cache for row-based matchfinder */
@ -884,9 +886,9 @@ MEM_STATIC void ZSTD_window_clear(ZSTD_window_t* window)
MEM_STATIC U32 ZSTD_window_isEmpty(ZSTD_window_t const window) MEM_STATIC U32 ZSTD_window_isEmpty(ZSTD_window_t const window)
{ {
return window.dictLimit == 1 && return window.dictLimit == ZSTD_WINDOW_START_INDEX &&
window.lowLimit == 1 && window.lowLimit == ZSTD_WINDOW_START_INDEX &&
(window.nextSrc - window.base) == 1; (window.nextSrc - window.base) == ZSTD_WINDOW_START_INDEX;
} }
/** /**
@ -1151,9 +1153,10 @@ MEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) {
ZSTD_memset(window, 0, sizeof(*window)); ZSTD_memset(window, 0, sizeof(*window));
window->base = (BYTE const*)" "; window->base = (BYTE const*)" ";
window->dictBase = (BYTE const*)" "; window->dictBase = (BYTE const*)" ";
window->dictLimit = 1; /* start from 1, so that 1st position is valid */ ZSTD_STATIC_ASSERT(ZSTD_DUBT_UNSORTED_MARK < ZSTD_WINDOW_START_INDEX); /* Start above ZSTD_DUBT_UNSORTED_MARK */
window->lowLimit = 1; /* it ensures first and later CCtx usages compress the same */ window->dictLimit = ZSTD_WINDOW_START_INDEX; /* start from >0, so that 1st position is valid */
window->nextSrc = window->base + 1; /* see issue #1241 */ window->lowLimit = ZSTD_WINDOW_START_INDEX; /* it ensures first and later CCtx usages compress the same */
window->nextSrc = window->base + ZSTD_WINDOW_START_INDEX; /* see issue #1241 */
window->nbOverflowCorrections = 0; window->nbOverflowCorrections = 0;
} }