mirror of
				https://github.com/facebook/zstd.git
				synced 2025-10-31 16:47:48 +02:00 
			
		
		
		
	[legacy] Fix ZSTDv0*_decodeSequence()
* Version <= 0.5 could read beyond the end of `dumps`, which points into the input buffer. * Check the validity of `dumps` before using it, if it is out of bounds return garbage values. There is no return code for this function. * Introduce `MEM_readLE24()` for simplicity, since I don't want to trust that there is an extra byte after `dumps`.
This commit is contained in:
		| @@ -1358,8 +1358,6 @@ static unsigned ZSTD_isLittleEndian(void) | ||||
|  | ||||
| static U16    ZSTD_read16(const void* p) { U16 r; memcpy(&r, p, sizeof(r)); return r; } | ||||
|  | ||||
| static U32    ZSTD_read32(const void* p) { U32 r; memcpy(&r, p, sizeof(r)); return r; } | ||||
|  | ||||
| static void   ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); } | ||||
|  | ||||
| static void   ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); } | ||||
| @@ -1384,16 +1382,9 @@ static U16 ZSTD_readLE16(const void* memPtr) | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| static U32 ZSTD_readLE32(const void* memPtr) | ||||
| static U32 ZSTD_readLE24(const void* memPtr) | ||||
| { | ||||
|     if (ZSTD_isLittleEndian()) | ||||
|         return ZSTD_read32(memPtr); | ||||
|     else | ||||
|     { | ||||
|         const BYTE* p = (const BYTE*)memPtr; | ||||
|         return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24)); | ||||
|     } | ||||
|     return ZSTD_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16); | ||||
| } | ||||
|  | ||||
| static U32 ZSTD_readBE32(const void* memPtr) | ||||
| @@ -1707,13 +1698,13 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState) | ||||
|     seqState->prevOffset = seq->offset; | ||||
|     if (litLength == MaxLL) | ||||
|     { | ||||
|         U32 add = dumps<de ? *dumps++ : 0; | ||||
|         const U32 add = dumps<de ? *dumps++ : 0; | ||||
|         if (add < 255) litLength += add; | ||||
|         else | ||||
|         { | ||||
|             if (dumps<=(de-3)) | ||||
|             { | ||||
|                 litLength = ZSTD_readLE32(dumps) & 0xFFFFFF;  /* no pb : dumps is always followed by seq tables > 1 byte */ | ||||
|                 litLength = ZSTD_readLE24(dumps); | ||||
|                 dumps += 3; | ||||
|             } | ||||
|         } | ||||
| @@ -1735,13 +1726,13 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState) | ||||
|     matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream)); | ||||
|     if (matchLength == MaxML) | ||||
|     { | ||||
|         U32 add = dumps<de ? *dumps++ : 0; | ||||
|         const U32 add = dumps<de ? *dumps++ : 0; | ||||
|         if (add < 255) matchLength += add; | ||||
|         else | ||||
|         { | ||||
|             if (dumps<=(de-3)) | ||||
|             { | ||||
|                 matchLength = ZSTD_readLE32(dumps) & 0xFFFFFF;  /* no pb : dumps is always followed by seq tables > 1 byte */ | ||||
|                 matchLength = ZSTD_readLE24(dumps); | ||||
|                 dumps += 3; | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -217,6 +217,11 @@ MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val) | ||||
|     } | ||||
| } | ||||
|  | ||||
| MEM_STATIC U32 MEM_readLE24(const void* memPtr) | ||||
| { | ||||
|     return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16); | ||||
| } | ||||
|  | ||||
| MEM_STATIC U32 MEM_readLE32(const void* memPtr) | ||||
| { | ||||
|     if (MEM_isLittleEndian()) | ||||
| @@ -3043,11 +3048,11 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState) | ||||
|     seqState->prevOffset = seq->offset; | ||||
|     if (litLength == MaxLL) | ||||
|     { | ||||
|         U32 add = *dumps++; | ||||
|         const U32 add = dumps<de ? *dumps++ : 0; | ||||
|         if (add < 255) litLength += add; | ||||
|         else | ||||
|         else if (dumps + 3 <= de) | ||||
|         { | ||||
|             litLength = MEM_readLE32(dumps) & 0xFFFFFF;  /* no pb : dumps is always followed by seq tables > 1 byte */ | ||||
|             litLength = MEM_readLE24(dumps); | ||||
|             dumps += 3; | ||||
|         } | ||||
|         if (dumps >= de) dumps = de-1;   /* late correction, to avoid read overflow (data is now corrupted anyway) */ | ||||
| @@ -3073,11 +3078,11 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState) | ||||
|     matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream)); | ||||
|     if (matchLength == MaxML) | ||||
|     { | ||||
|         U32 add = *dumps++; | ||||
|         const U32 add = dumps<de ? *dumps++ : 0; | ||||
|         if (add < 255) matchLength += add; | ||||
|         else | ||||
|         else if (dumps + 3 <= de) | ||||
|         { | ||||
|             matchLength = MEM_readLE32(dumps) & 0xFFFFFF;  /* no pb : dumps is always followed by seq tables > 1 byte */ | ||||
|             matchLength = MEM_readLE24(dumps); | ||||
|             dumps += 3; | ||||
|         } | ||||
|         if (dumps >= de) dumps = de-1;   /* late correction, to avoid read overflow (data is now corrupted anyway) */ | ||||
|   | ||||
| @@ -219,6 +219,11 @@ MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val) | ||||
|     } | ||||
| } | ||||
|  | ||||
| MEM_STATIC U32 MEM_readLE24(const void* memPtr) | ||||
| { | ||||
|     return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16); | ||||
| } | ||||
|  | ||||
| MEM_STATIC U32 MEM_readLE32(const void* memPtr) | ||||
| { | ||||
|     if (MEM_isLittleEndian()) | ||||
| @@ -2684,11 +2689,11 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState) | ||||
|     seqState->prevOffset = seq->offset; | ||||
|     if (litLength == MaxLL) | ||||
|     { | ||||
|         U32 add = *dumps++; | ||||
|         const U32 add = dumps<de ? *dumps++ : 0; | ||||
|         if (add < 255) litLength += add; | ||||
|         else | ||||
|         else if (dumps + 3 <= de) | ||||
|         { | ||||
|             litLength = MEM_readLE32(dumps) & 0xFFFFFF;  /* no pb : dumps is always followed by seq tables > 1 byte */ | ||||
|             litLength = MEM_readLE24(dumps); | ||||
|             dumps += 3; | ||||
|         } | ||||
|         if (dumps >= de) dumps = de-1;   /* late correction, to avoid read overflow (data is now corrupted anyway) */ | ||||
| @@ -2714,11 +2719,11 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState) | ||||
|     matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream)); | ||||
|     if (matchLength == MaxML) | ||||
|     { | ||||
|         U32 add = *dumps++; | ||||
|         const U32 add = dumps<de ? *dumps++ : 0; | ||||
|         if (add < 255) matchLength += add; | ||||
|         else | ||||
|         else if (dumps + 3 <= de) | ||||
|         { | ||||
|             matchLength = MEM_readLE32(dumps) & 0xFFFFFF;  /* no pb : dumps is always followed by seq tables > 1 byte */ | ||||
|             matchLength = MEM_readLE24(dumps); | ||||
|             dumps += 3; | ||||
|         } | ||||
|         if (dumps >= de) dumps = de-1;   /* late correction, to avoid read overflow (data is now corrupted anyway) */ | ||||
|   | ||||
| @@ -189,6 +189,11 @@ MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val) | ||||
|     } | ||||
| } | ||||
|  | ||||
| MEM_STATIC U32 MEM_readLE24(const void* memPtr) | ||||
| { | ||||
|     return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16); | ||||
| } | ||||
|  | ||||
| MEM_STATIC U32 MEM_readLE32(const void* memPtr) | ||||
| { | ||||
|     if (MEM_isLittleEndian()) | ||||
| @@ -2808,13 +2813,12 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState) | ||||
|     litLength = FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream)); | ||||
|     prevOffset = litLength ? seq->offset : seqState->prevOffset; | ||||
|     if (litLength == MaxLL) { | ||||
|         U32 add = *dumps++; | ||||
|         const U32 add = dumps<de ? *dumps++ : 0; | ||||
|         if (add < 255) litLength += add; | ||||
|         else { | ||||
|             litLength = dumps[0] + (dumps[1]<<8) + (dumps[2]<<16); | ||||
|         else if (dumps + 3 <= de) { | ||||
|             litLength = MEM_readLE24(dumps); | ||||
|             dumps += 3; | ||||
|         } | ||||
|         if (dumps > de) { litLength = MaxLL+255; }  /* late correction, to avoid using uninitialized memory */ | ||||
|         if (dumps >= de) { dumps = de-1; }  /* late correction, to avoid read overflow (data is now corrupted anyway) */ | ||||
|     } | ||||
|  | ||||
| @@ -2837,13 +2841,12 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState) | ||||
|     /* MatchLength */ | ||||
|     matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream)); | ||||
|     if (matchLength == MaxML) { | ||||
|         U32 add = *dumps++; | ||||
|         const U32 add = dumps<de ? *dumps++ : 0; | ||||
|         if (add < 255) matchLength += add; | ||||
|         else { | ||||
|             matchLength = dumps[0] + (dumps[1]<<8) + (dumps[2]<<16); | ||||
|         else if (dumps + 3 <= de){ | ||||
|             matchLength = MEM_readLE24(dumps); | ||||
|             dumps += 3; | ||||
|         } | ||||
|         if (dumps > de) { matchLength = MaxML+255; }  /* late correction, to avoid using uninitialized memory */ | ||||
|         if (dumps >= de) { dumps = de-1; }  /* late correction, to avoid read overflow (data is now corrupted anyway) */ | ||||
|     } | ||||
|     matchLength += MINMATCH; | ||||
|   | ||||
| @@ -218,6 +218,11 @@ MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val) | ||||
|     } | ||||
| } | ||||
|  | ||||
| MEM_STATIC U32 MEM_readLE24(const void* memPtr) | ||||
| { | ||||
|     return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16); | ||||
| } | ||||
|  | ||||
| MEM_STATIC U32 MEM_readLE32(const void* memPtr) | ||||
| { | ||||
|     if (MEM_isLittleEndian()) | ||||
| @@ -3151,14 +3156,13 @@ static void ZSTDv05_decodeSequence(seq_t* seq, seqState_t* seqState) | ||||
|     litLength = FSEv05_peakSymbol(&(seqState->stateLL)); | ||||
|     prevOffset = litLength ? seq->offset : seqState->prevOffset; | ||||
|     if (litLength == MaxLL) { | ||||
|         U32 add = *dumps++; | ||||
|         const U32 add = *dumps++; | ||||
|         if (add < 255) litLength += add; | ||||
|         else { | ||||
|             litLength = MEM_readLE32(dumps) & 0xFFFFFF;  /* no risk : dumps is always followed by seq tables > 1 byte */ | ||||
|         else if (dumps + 3 <= de) { | ||||
|             litLength = MEM_readLE24(dumps); | ||||
|             if (litLength&1) litLength>>=1, dumps += 3; | ||||
|             else litLength = (U16)(litLength)>>1, dumps += 2; | ||||
|         } | ||||
|         if (dumps > de) { litLength = MaxLL+255; }  /* late correction, to avoid using uninitialized memory */ | ||||
|         if (dumps >= de) { dumps = de-1; }  /* late correction, to avoid read overflow (data is now corrupted anyway) */ | ||||
|     } | ||||
|  | ||||
| @@ -3185,14 +3189,13 @@ static void ZSTDv05_decodeSequence(seq_t* seq, seqState_t* seqState) | ||||
|     /* MatchLength */ | ||||
|     matchLength = FSEv05_decodeSymbol(&(seqState->stateML), &(seqState->DStream)); | ||||
|     if (matchLength == MaxML) { | ||||
|         U32 add = *dumps++; | ||||
|         const U32 add = dumps<de ? *dumps++ : 0; | ||||
|         if (add < 255) matchLength += add; | ||||
|         else { | ||||
|             matchLength = MEM_readLE32(dumps) & 0xFFFFFF;  /* no pb : dumps is always followed by seq tables > 1 byte */ | ||||
|         else if (dumps + 3 <= de) { | ||||
|             matchLength = MEM_readLE24(dumps); | ||||
|             if (matchLength&1) matchLength>>=1, dumps += 3; | ||||
|             else matchLength = (U16)(matchLength)>>1, dumps += 2; | ||||
|         } | ||||
|         if (dumps > de) { matchLength = MaxML+255; }  /* late correction, to avoid using uninitialized memory */ | ||||
|         if (dumps >= de) { dumps = de-1; }  /* late correction, to avoid read overflow (data is now corrupted anyway) */ | ||||
|     } | ||||
|     matchLength += MINMATCH; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user