fixed MSAN warnings in legacy decoders

In some extraordinary circumstances,
*Length field can be generated from reading a partially uninitialized memory segment.
Data is correctly identified as corrupted later on,
but the read taints some later pointer arithmetic operation.
This commit is contained in:
Yann Collet 2017-01-27 10:44:03 -08:00
parent 122b6aa657
commit cafdd31a38
2 changed files with 9 additions and 15 deletions

View File

@ -3016,12 +3016,11 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)
{ {
U32 add = *dumps++; U32 add = *dumps++;
if (add < 255) litLength += add; if (add < 255) litLength += add;
else else {
{
litLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */ litLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */
dumps += 3; dumps += 3;
} }
if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */ if (dumps >= de) { dumps = de-1; litLength = MaxLL+255; } /* late correction, to avoid read overflow (data is now corrupted anyway) */
} }
/* Offset */ /* Offset */
@ -3043,16 +3042,14 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)
/* MatchLength */ /* MatchLength */
matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream)); matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));
if (matchLength == MaxML) if (matchLength == MaxML) {
{
U32 add = *dumps++; U32 add = *dumps++;
if (add < 255) matchLength += add; if (add < 255) matchLength += add;
else else {
{
matchLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */ matchLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */
dumps += 3; dumps += 3;
} }
if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */ if (dumps >= de) { dumps = de-1; matchLength = MaxML+255; } /* late correction, to avoid read overflow (data is now corrupted anyway) */
} }
matchLength += MINMATCH; matchLength += MINMATCH;
@ -3116,8 +3113,7 @@ static size_t ZSTD_execSequence(BYTE* op,
/* Requirement: op <= oend_8 */ /* Requirement: op <= oend_8 */
/* match within prefix */ /* match within prefix */
if (sequence.offset < 8) if (sequence.offset < 8) {
{
/* close range match, overlap */ /* close range match, overlap */
const int sub2 = dec64table[sequence.offset]; const int sub2 = dec64table[sequence.offset];
op[0] = match[0]; op[0] = match[0];
@ -3127,9 +3123,7 @@ static size_t ZSTD_execSequence(BYTE* op,
match += dec32table[sequence.offset]; match += dec32table[sequence.offset];
ZSTD_copy4(op+4, match); ZSTD_copy4(op+4, match);
match -= sub2; match -= sub2;
} } else {
else
{
ZSTD_copy8(op, match); ZSTD_copy8(op, match);
} }
op += 8; match += 8; op += 8; match += 8;

View File

@ -3230,7 +3230,7 @@ static void ZSTDv05_decodeSequence(seq_t* seq, seqState_t* seqState)
if (litLength&1) litLength>>=1, dumps += 3; if (litLength&1) litLength>>=1, dumps += 3;
else litLength = (U16)(litLength)>>1, dumps += 2; else litLength = (U16)(litLength)>>1, dumps += 2;
} }
if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */ if (dumps >= de) { dumps = de-1; litLength = MaxLL+255; } /* late correction, to avoid read overflow (data is now corrupted anyway) */
} }
/* Offset */ /* Offset */
@ -3263,7 +3263,7 @@ static void ZSTDv05_decodeSequence(seq_t* seq, seqState_t* seqState)
if (matchLength&1) matchLength>>=1, dumps += 3; if (matchLength&1) matchLength>>=1, dumps += 3;
else matchLength = (U16)(matchLength)>>1, dumps += 2; else matchLength = (U16)(matchLength)>>1, dumps += 2;
} }
if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */ if (dumps >= de) { dumps = de-1; matchLength = MaxML+255; } /* late correction, to avoid read overflow (data is now corrupted anyway) */
} }
matchLength += MINMATCH; matchLength += MINMATCH;