File lz4-CVE-2019-17543.patch of Package lz4.16300

Index: lz4-1.8.0/lib/lz4.c
===================================================================
--- lz4-1.8.0.orig/lib/lz4.c	2017-08-17 19:55:30.000000000 +0200
+++ lz4-1.8.0/lib/lz4.c	2019-10-18 10:13:22.790892133 +0200
@@ -471,6 +471,16 @@ FORCE_INLINE const BYTE* LZ4_getPosition
     return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase);
 }
 
+static void LZ4_clearHash(U32 h, void* tableBase, tableType_t const tableType)
+{
+    switch (tableType)
+    {
+    default: /* fallthrough */
+    case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = NULL; return; }
+    case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = 0; return; }
+    case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = 0; return; }
+    }
+}
 
 /** LZ4_compress_generic() :
     inlined, to ensure branches are decided at compilation time */
@@ -610,7 +620,7 @@ _next_match:
             }
 
             if ( outputLimited &&    /* Check output buffer overflow */
-                (unlikely(op + (1 + LASTLITERALS) + (matchCode>>8) > olimit)) )
+                (unlikely(op + (1 + LASTLITERALS) + (matchCode+240)/255 > olimit)) )
                 return 0;
             if (matchCode >= ML_MASK) {
                 *token += ML_MASK;
@@ -759,7 +769,7 @@ static int LZ4_compress_destSize_generic
     BYTE* const oMaxSeq = oMaxLit - 1 /* token */;
 
     U32 forwardH;
-
+    BYTE* const olimit = op + targetDstSize;
 
     /* Init conditions */
     if (targetDstSize < 1) return 0;                                     /* Impossible to store anything */
@@ -776,6 +786,7 @@ static int LZ4_compress_destSize_generic
     for ( ; ; ) {
         const BYTE* match;
         BYTE* token;
+        const BYTE* filledIp;
 
         /* Find a match */
         {   const BYTE* forwardIp = ip;
@@ -799,6 +810,7 @@ static int LZ4_compress_destSize_generic
         }
 
         /* Catch up */
+        filledIp = ip;
         while ((ip>anchor) && (match > lowLimit) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; }
 
         /* Encode Literal length */
@@ -835,6 +847,25 @@ _next_match:
             }
             ip += MINMATCH + matchLength;
 
+            if ( (unlikely(op + (1 + LASTLITERALS) + (matchLength+240)/255 > olimit)) ) {
+                U32 newMatchCode = 15 /* in token */ - 1 /* to avoid needing a zero byte */ + ((U32)(olimit - op) - 1 - LASTLITERALS) * 255;
+                ip -= matchLength - newMatchCode;
+                matchLength = newMatchCode;
+                if (unlikely(ip < filledIp)) {
+                    /* We have already filled up to filledIp so if ip ends up less than filledIp
+                     * we have positions in the hash table beyond the current position. This is
+                     * a problem if we reuse the hash table. So we have to remove these positions
+                     * from the hash table.
+                     */
+                    const BYTE* ptr;
+                    DEBUGLOG(5, "Clearing %u positions", (U32)(filledIp - ip));
+                    for (ptr = ip; ptr <= filledIp; ++ptr) {
+                        U32 const h = LZ4_hashPosition(ptr, tableType);
+                        LZ4_clearHash(h, ctx->hashTable, tableType);
+                    }
+                }
+            }
+
             if (matchLength>=ML_MASK) {
                 *token += ML_MASK;
                 matchLength -= ML_MASK;
openSUSE Build Service is sponsored by