Fix Data Corruption Bug when Streaming with an Attached Dict in HC Mode
authorW. Felix Handte <w@felixhandte.com>
Thu, 18 Jul 2019 16:41:12 +0000 (12:41 -0400)
committerW. Felix Handte <w@felixhandte.com>
Thu, 18 Jul 2019 16:48:41 +0000 (12:48 -0400)
This diff fixes an issue in which we failed to clear the `dictCtx` in HC
compression. The `dictCtx` is not supposed to be used when an `extDict` is
present: matches found in the `dictCtx` do not account for the presence of an
`extDict` segment, and their offsets are therefore miscalculated when one is
present. This can lead to data corruption.

This diff clears the `dictCtx` whenever setting an `extDict`.

This issue was uncovered by @terrelln's fuzzing work.

lib/lz4hc.c

index 46c20bc..d9e55a0 100644 (file)
@@ -998,6 +998,11 @@ static void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const BYTE* newBl
     if (ctxPtr->end >= ctxPtr->base + ctxPtr->dictLimit + 4)
         LZ4HC_Insert (ctxPtr, ctxPtr->end-3);   /* Referencing remaining dictionary content */
 
+    /* cannot reference an extDict and a dictCtx at the same time */
+    if (ctxPtr->dictCtx != NULL) {
+        ctxPtr->dictCtx = NULL;
+    }
+
     /* Only one memory segment for extDict, so any previous extDict is lost at this stage */
     ctxPtr->lowLimit  = ctxPtr->dictLimit;
     ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base);