mirror of
https://github.com/facebook/zstd.git
synced 2025-10-09 00:05:28 -04:00
Unitialized memory read in ZSTD_decodeSeqHeaders()
Caused by two things: 1. Not checking that `ip` is in range except for the first byte. 2. `ZSTDv0{5,6}_decodeLiteralsBlock()` could return a value larger than `srcSize`.
This commit is contained in:
parent
7b06ad7a05
commit
bb68062c59
@ -710,10 +710,13 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
|
|||||||
{ int nbSeq = *ip++;
|
{ int nbSeq = *ip++;
|
||||||
if (!nbSeq) { *nbSeqPtr=0; return 1; }
|
if (!nbSeq) { *nbSeqPtr=0; return 1; }
|
||||||
if (nbSeq > 0x7F) {
|
if (nbSeq > 0x7F) {
|
||||||
if (nbSeq == 0xFF)
|
if (nbSeq == 0xFF) {
|
||||||
|
if (ip+2 > iend) return ERROR(srcSize_wrong);
|
||||||
nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
|
nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
|
||||||
else
|
} else {
|
||||||
|
if (ip >= iend) return ERROR(srcSize_wrong);
|
||||||
nbSeq = ((nbSeq-0x80)<<8) + *ip++;
|
nbSeq = ((nbSeq-0x80)<<8) + *ip++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*nbSeqPtr = nbSeq;
|
*nbSeqPtr = nbSeq;
|
||||||
}
|
}
|
||||||
|
@ -1536,6 +1536,7 @@ size_t ZSTDv01_decodeLiteralsBlock(void* ctx,
|
|||||||
{
|
{
|
||||||
size_t rleSize = litbp.origSize;
|
size_t rleSize = litbp.origSize;
|
||||||
if (rleSize>maxDstSize) return ERROR(dstSize_tooSmall);
|
if (rleSize>maxDstSize) return ERROR(dstSize_tooSmall);
|
||||||
|
if (!srcSize) return ERROR(srcSize_wrong);
|
||||||
memset(oend - rleSize, *ip, rleSize);
|
memset(oend - rleSize, *ip, rleSize);
|
||||||
*litStart = oend - rleSize;
|
*litStart = oend - rleSize;
|
||||||
*litSize = rleSize;
|
*litSize = rleSize;
|
||||||
|
@ -2994,6 +2994,7 @@ size_t ZSTDv05_decodeLiteralsBlock(ZSTDv05_DCtx* dctx,
|
|||||||
lhSize=3;
|
lhSize=3;
|
||||||
litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);
|
litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);
|
||||||
litCSize = ((istart[1] & 3) << 8) + istart[2];
|
litCSize = ((istart[1] & 3) << 8) + istart[2];
|
||||||
|
if (litCSize + litSize > srcSize) return ERROR(corruption_detected);
|
||||||
|
|
||||||
errorCode = HUFv05_decompress1X4_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTableX4);
|
errorCode = HUFv05_decompress1X4_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTableX4);
|
||||||
if (HUFv05_isError(errorCode)) return ERROR(corruption_detected);
|
if (HUFv05_isError(errorCode)) return ERROR(corruption_detected);
|
||||||
@ -3050,6 +3051,7 @@ size_t ZSTDv05_decodeLiteralsBlock(ZSTDv05_DCtx* dctx,
|
|||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];
|
litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];
|
||||||
|
if (srcSize<4) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (litSize > BLOCKSIZE) return ERROR(corruption_detected);
|
if (litSize > BLOCKSIZE) return ERROR(corruption_detected);
|
||||||
@ -3083,17 +3085,22 @@ size_t ZSTDv05_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumps
|
|||||||
/* SeqHead */
|
/* SeqHead */
|
||||||
*nbSeq = *ip++;
|
*nbSeq = *ip++;
|
||||||
if (*nbSeq==0) return 1;
|
if (*nbSeq==0) return 1;
|
||||||
if (*nbSeq >= 128)
|
if (*nbSeq >= 128) {
|
||||||
|
if (ip >= iend) return ERROR(srcSize_wrong);
|
||||||
*nbSeq = ((nbSeq[0]-128)<<8) + *ip++;
|
*nbSeq = ((nbSeq[0]-128)<<8) + *ip++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ip >= iend) return ERROR(srcSize_wrong);
|
||||||
LLtype = *ip >> 6;
|
LLtype = *ip >> 6;
|
||||||
Offtype = (*ip >> 4) & 3;
|
Offtype = (*ip >> 4) & 3;
|
||||||
MLtype = (*ip >> 2) & 3;
|
MLtype = (*ip >> 2) & 3;
|
||||||
if (*ip & 2) {
|
if (*ip & 2) {
|
||||||
|
if (ip+3 > iend) return ERROR(srcSize_wrong);
|
||||||
dumpsLength = ip[2];
|
dumpsLength = ip[2];
|
||||||
dumpsLength += ip[1] << 8;
|
dumpsLength += ip[1] << 8;
|
||||||
ip += 3;
|
ip += 3;
|
||||||
} else {
|
} else {
|
||||||
|
if (ip+2 > iend) return ERROR(srcSize_wrong);
|
||||||
dumpsLength = ip[1];
|
dumpsLength = ip[1];
|
||||||
dumpsLength += (ip[0] & 1) << 8;
|
dumpsLength += (ip[0] & 1) << 8;
|
||||||
ip += 2;
|
ip += 2;
|
||||||
|
@ -3185,6 +3185,7 @@ size_t ZSTDv06_decodeLiteralsBlock(ZSTDv06_DCtx* dctx,
|
|||||||
lhSize=3;
|
lhSize=3;
|
||||||
litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);
|
litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);
|
||||||
litCSize = ((istart[1] & 3) << 8) + istart[2];
|
litCSize = ((istart[1] & 3) << 8) + istart[2];
|
||||||
|
if (litCSize + litSize > srcSize) return ERROR(corruption_detected);
|
||||||
|
|
||||||
{ size_t const errorCode = HUFv06_decompress1X4_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTableX4);
|
{ size_t const errorCode = HUFv06_decompress1X4_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTableX4);
|
||||||
if (HUFv06_isError(errorCode)) return ERROR(corruption_detected);
|
if (HUFv06_isError(errorCode)) return ERROR(corruption_detected);
|
||||||
@ -3304,10 +3305,13 @@ size_t ZSTDv06_decodeSeqHeaders(int* nbSeqPtr,
|
|||||||
{ int nbSeq = *ip++;
|
{ int nbSeq = *ip++;
|
||||||
if (!nbSeq) { *nbSeqPtr=0; return 1; }
|
if (!nbSeq) { *nbSeqPtr=0; return 1; }
|
||||||
if (nbSeq > 0x7F) {
|
if (nbSeq > 0x7F) {
|
||||||
if (nbSeq == 0xFF)
|
if (nbSeq == 0xFF) {
|
||||||
|
if (ip+2 > iend) return ERROR(srcSize_wrong);
|
||||||
nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
|
nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
|
||||||
else
|
} else {
|
||||||
|
if (ip >= iend) return ERROR(srcSize_wrong);
|
||||||
nbSeq = ((nbSeq-0x80)<<8) + *ip++;
|
nbSeq = ((nbSeq-0x80)<<8) + *ip++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*nbSeqPtr = nbSeq;
|
*nbSeqPtr = nbSeq;
|
||||||
}
|
}
|
||||||
|
@ -3531,10 +3531,13 @@ size_t ZSTDv07_decodeSeqHeaders(int* nbSeqPtr,
|
|||||||
{ int nbSeq = *ip++;
|
{ int nbSeq = *ip++;
|
||||||
if (!nbSeq) { *nbSeqPtr=0; return 1; }
|
if (!nbSeq) { *nbSeqPtr=0; return 1; }
|
||||||
if (nbSeq > 0x7F) {
|
if (nbSeq > 0x7F) {
|
||||||
if (nbSeq == 0xFF)
|
if (nbSeq == 0xFF) {
|
||||||
|
if (ip+2 > iend) return ERROR(srcSize_wrong);
|
||||||
nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
|
nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
|
||||||
else
|
} else {
|
||||||
|
if (ip >= iend) return ERROR(srcSize_wrong);
|
||||||
nbSeq = ((nbSeq-0x80)<<8) + *ip++;
|
nbSeq = ((nbSeq-0x80)<<8) + *ip++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*nbSeqPtr = nbSeq;
|
*nbSeqPtr = nbSeq;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user