mirror of https://github.com/FreeRDP/FreeRDP
[codec,ncrush] fix index checks
properly verify all offsets while decoding data.
This commit is contained in:
parent
1bbed81041
commit
16141a30f9
|
@ -2016,15 +2016,9 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSi
|
|||
const BYTE** ppDstData, UINT32* pDstSize, UINT32 flags)
|
||||
{
|
||||
UINT32 index;
|
||||
UINT32 bits;
|
||||
INT32 nbits;
|
||||
const BYTE* SrcPtr;
|
||||
const BYTE* SrcEnd;
|
||||
UINT16 Mask;
|
||||
BYTE Literal;
|
||||
UINT32 IndexLEC;
|
||||
UINT32 BitLength;
|
||||
UINT32 MaskedBits;
|
||||
UINT32 CopyOffset;
|
||||
UINT32 CopyLength;
|
||||
UINT32 OldCopyOffset;
|
||||
|
@ -2032,9 +2026,6 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSi
|
|||
UINT32 LengthOfMatch;
|
||||
UINT32 CopyOffsetIndex;
|
||||
UINT32 OffsetCacheIndex;
|
||||
BYTE* HistoryPtr;
|
||||
BYTE* HistoryBuffer;
|
||||
BYTE* HistoryBufferEnd;
|
||||
UINT32 CopyOffsetBits;
|
||||
UINT32 CopyOffsetBase;
|
||||
UINT32 LengthOfMatchBits;
|
||||
|
@ -2048,8 +2039,8 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSi
|
|||
if (ncrush->HistoryEndOffset != 65535)
|
||||
return -1001;
|
||||
|
||||
HistoryBuffer = ncrush->HistoryBuffer;
|
||||
HistoryBufferEnd = &HistoryBuffer[ncrush->HistoryEndOffset];
|
||||
BYTE* HistoryBuffer = ncrush->HistoryBuffer;
|
||||
const BYTE* HistoryBufferEnd = &HistoryBuffer[ncrush->HistoryEndOffset];
|
||||
|
||||
if (flags & PACKET_AT_FRONT)
|
||||
{
|
||||
|
@ -2068,7 +2059,7 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSi
|
|||
ZeroMemory(&(ncrush->OffsetCache), sizeof(ncrush->OffsetCache));
|
||||
}
|
||||
|
||||
HistoryPtr = ncrush->HistoryPtr;
|
||||
BYTE* HistoryPtr = ncrush->HistoryPtr;
|
||||
|
||||
if (!(flags & PACKET_COMPRESSED))
|
||||
{
|
||||
|
@ -2077,17 +2068,19 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSi
|
|||
return 1;
|
||||
}
|
||||
|
||||
SrcEnd = &pSrcData[SrcSize];
|
||||
nbits = 32;
|
||||
bits = get_dword(pSrcData);
|
||||
SrcPtr = pSrcData + 4;
|
||||
const BYTE* SrcEnd = &pSrcData[SrcSize];
|
||||
const BYTE* SrcPtr = pSrcData + 4;
|
||||
|
||||
INT32 nbits = 32;
|
||||
UINT32 bits = get_dword(pSrcData);
|
||||
while (1)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
Mask = get_word(&HuffTableMask[29]);
|
||||
MaskedBits = bits & Mask;
|
||||
const UINT16 Mask = get_word(&HuffTableMask[29]);
|
||||
const UINT32 MaskedBits = bits & Mask;
|
||||
if (MaskedBits >= ARRAYSIZE(HuffTableLEC))
|
||||
return -1;
|
||||
IndexLEC = HuffTableLEC[MaskedBits] & 0xFFF;
|
||||
BitLength = HuffTableLEC[MaskedBits] >> 12;
|
||||
bits >>= BitLength;
|
||||
|
@ -2123,8 +2116,10 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSi
|
|||
return -1004;
|
||||
|
||||
CopyOffset = ncrush->OffsetCache[OffsetCacheIndex];
|
||||
Mask = get_word(&HuffTableMask[21]);
|
||||
MaskedBits = bits & Mask;
|
||||
const UINT16 Mask = get_word(&HuffTableMask[21]);
|
||||
const UINT32 MaskedBits = bits & Mask;
|
||||
if (MaskedBits > ARRAYSIZE(HuffTableLOM))
|
||||
return -1;
|
||||
LengthOfMatch = HuffTableLOM[MaskedBits] & 0xFFF;
|
||||
BitLength = HuffTableLOM[MaskedBits] >> 12;
|
||||
bits >>= BitLength;
|
||||
|
@ -2133,13 +2128,23 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSi
|
|||
if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits))
|
||||
return -1;
|
||||
|
||||
if (LengthOfMatch >= ARRAYSIZE(LOMBitsLUT))
|
||||
return -1;
|
||||
|
||||
LengthOfMatchBits = LOMBitsLUT[LengthOfMatch];
|
||||
|
||||
if (LengthOfMatch >= ARRAYSIZE(LOMBaseLUT))
|
||||
return -1;
|
||||
LengthOfMatchBase = LOMBaseLUT[LengthOfMatch];
|
||||
|
||||
if (LengthOfMatchBits)
|
||||
{
|
||||
Mask = get_word(&HuffTableMask[(2 * LengthOfMatchBits) + 3]);
|
||||
MaskedBits = bits & Mask;
|
||||
const size_t idx = (2ull * LengthOfMatchBits) + 3ull;
|
||||
if (idx >= ARRAYSIZE(HuffTableMask))
|
||||
return -1;
|
||||
|
||||
const UINT16 Mask = get_word(&HuffTableMask[idx]);
|
||||
const UINT32 MaskedBits = bits & Mask;
|
||||
bits >>= LengthOfMatchBits;
|
||||
nbits -= LengthOfMatchBits;
|
||||
LengthOfMatchBase += MaskedBits;
|
||||
|
@ -2154,15 +2159,28 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSi
|
|||
}
|
||||
else
|
||||
{
|
||||
if (CopyOffsetIndex >= ARRAYSIZE(CopyOffsetBitsLUT))
|
||||
return -1;
|
||||
|
||||
CopyOffsetBits = CopyOffsetBitsLUT[CopyOffsetIndex];
|
||||
|
||||
if (CopyOffsetIndex >= ARRAYSIZE(CopyOffsetBaseLUT))
|
||||
return -1;
|
||||
CopyOffsetBase = CopyOffsetBaseLUT[CopyOffsetIndex];
|
||||
CopyOffset = CopyOffsetBase - 1;
|
||||
|
||||
if (CopyOffsetBits)
|
||||
{
|
||||
Mask = get_word(&HuffTableMask[(2 * CopyOffsetBits) + 3]);
|
||||
MaskedBits = bits & Mask;
|
||||
CopyOffset = CopyOffsetBase + MaskedBits - 1;
|
||||
const size_t idx = (2ull * CopyOffsetBits) + 3ull;
|
||||
if (idx >= ARRAYSIZE(HuffTableMask))
|
||||
return -1;
|
||||
|
||||
const UINT16 Mask = get_word(&HuffTableMask[idx]);
|
||||
const UINT32 MaskedBits = bits & Mask;
|
||||
const UINT32 tmp = CopyOffsetBase + MaskedBits;
|
||||
if (tmp < 1)
|
||||
return -1;
|
||||
CopyOffset = tmp - 1;
|
||||
bits >>= CopyOffsetBits;
|
||||
nbits -= CopyOffsetBits;
|
||||
|
||||
|
@ -2170,8 +2188,11 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSi
|
|||
return -1;
|
||||
}
|
||||
|
||||
Mask = get_word(&HuffTableMask[21]);
|
||||
MaskedBits = bits & Mask;
|
||||
const UINT16 Mask = get_word(&HuffTableMask[21]);
|
||||
const UINT32 MaskedBits = bits & Mask;
|
||||
if (MaskedBits >= ARRAYSIZE(HuffTableLOM))
|
||||
return -1;
|
||||
|
||||
LengthOfMatch = HuffTableLOM[MaskedBits] & 0xFFF;
|
||||
BitLength = HuffTableLOM[MaskedBits] >> 12;
|
||||
bits >>= BitLength;
|
||||
|
@ -2180,13 +2201,23 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSi
|
|||
if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits))
|
||||
return -1;
|
||||
|
||||
if (LengthOfMatch >= ARRAYSIZE(LOMBitsLUT))
|
||||
return -1;
|
||||
|
||||
LengthOfMatchBits = LOMBitsLUT[LengthOfMatch];
|
||||
|
||||
if (LengthOfMatch >= ARRAYSIZE(LOMBaseLUT))
|
||||
return -1;
|
||||
LengthOfMatchBase = LOMBaseLUT[LengthOfMatch];
|
||||
|
||||
if (LengthOfMatchBits)
|
||||
{
|
||||
Mask = get_word(&HuffTableMask[(2 * LengthOfMatchBits) + 3]);
|
||||
MaskedBits = bits & Mask;
|
||||
const size_t idx = (2ull * LengthOfMatchBits) + 3ull;
|
||||
if (idx >= ARRAYSIZE(HuffTableMask))
|
||||
return -1;
|
||||
|
||||
const UINT16 Mask = get_word(&HuffTableMask[idx]);
|
||||
const UINT32 MaskedBits = bits & Mask;
|
||||
bits >>= LengthOfMatchBits;
|
||||
nbits -= LengthOfMatchBits;
|
||||
LengthOfMatchBase += MaskedBits;
|
||||
|
@ -2644,7 +2675,12 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSize
|
|||
}
|
||||
|
||||
IndexLEC = Literal;
|
||||
if (IndexLEC >= ARRAYSIZE(HuffLengthLEC))
|
||||
return -1;
|
||||
BitLength = HuffLengthLEC[IndexLEC];
|
||||
|
||||
if (IndexLEC * 2ull >= ARRAYSIZE(HuffCodeLEC))
|
||||
return -1;
|
||||
CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]);
|
||||
|
||||
if (BitLength > 15)
|
||||
|
@ -2727,9 +2763,18 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSize
|
|||
bits = CopyOffset;
|
||||
|
||||
CopyOffsetIndex = ncrush->HuffTableCopyOffset[bits + 2];
|
||||
|
||||
if (CopyOffsetIndex >= ARRAYSIZE(CopyOffsetBitsLUT))
|
||||
return -1;
|
||||
|
||||
CopyOffsetBits = CopyOffsetBitsLUT[CopyOffsetIndex];
|
||||
IndexLEC = 257 + CopyOffsetIndex;
|
||||
if (IndexLEC >= ARRAYSIZE(HuffLengthLEC))
|
||||
return -1;
|
||||
BitLength = HuffLengthLEC[IndexLEC];
|
||||
|
||||
if (IndexLEC * 2ull >= ARRAYSIZE(HuffCodeLEC))
|
||||
return -1;
|
||||
CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]);
|
||||
|
||||
if (BitLength > 15)
|
||||
|
@ -2748,13 +2793,23 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSize
|
|||
else
|
||||
IndexCO = ncrush->HuffTableLOM[MatchLength];
|
||||
|
||||
if (IndexCO >= ARRAYSIZE(HuffLengthLOM))
|
||||
return -1;
|
||||
BitLength = HuffLengthLOM[IndexCO];
|
||||
|
||||
if (IndexCO >= ARRAYSIZE(LOMBitsLUT))
|
||||
return -1;
|
||||
IndexLOM = LOMBitsLUT[IndexCO];
|
||||
|
||||
if (IndexCO >= ARRAYSIZE(HuffCodeLOM))
|
||||
return -1;
|
||||
NCrushWriteBits(&DstPtr, &accumulator, &offset, HuffCodeLOM[IndexCO], BitLength);
|
||||
Mask = ((1 << IndexLOM) - 1);
|
||||
MaskedBits = (MatchLength - 2) & Mask;
|
||||
NCrushWriteBits(&DstPtr, &accumulator, &offset, MaskedBits, IndexLOM);
|
||||
|
||||
if (IndexCO >= ARRAYSIZE(LOMBaseLUT))
|
||||
return -1;
|
||||
if ((MaskedBits + LOMBaseLUT[IndexCO]) != MatchLength)
|
||||
return -1010;
|
||||
}
|
||||
|
@ -2762,7 +2817,11 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSize
|
|||
{
|
||||
/* CopyOffset in OffsetCache */
|
||||
IndexLEC = 289 + OffsetCacheIndex;
|
||||
if (IndexLEC >= ARRAYSIZE(HuffLengthLEC))
|
||||
return -1;
|
||||
BitLength = HuffLengthLEC[IndexLEC];
|
||||
if (IndexLEC * 2ull >= ARRAYSIZE(HuffCodeLEC))
|
||||
return -1;
|
||||
CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]);
|
||||
|
||||
if (BitLength >= 15)
|
||||
|
@ -2775,13 +2834,24 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSize
|
|||
else
|
||||
IndexCO = ncrush->HuffTableLOM[MatchLength];
|
||||
|
||||
if (IndexCO >= ARRAYSIZE(HuffLengthLOM))
|
||||
return -1;
|
||||
|
||||
BitLength = HuffLengthLOM[IndexCO];
|
||||
|
||||
if (IndexCO >= ARRAYSIZE(LOMBitsLUT))
|
||||
return -1;
|
||||
IndexLOM = LOMBitsLUT[IndexCO];
|
||||
|
||||
if (IndexCO >= ARRAYSIZE(HuffCodeLOM))
|
||||
return -1;
|
||||
NCrushWriteBits(&DstPtr, &accumulator, &offset, HuffCodeLOM[IndexCO], BitLength);
|
||||
Mask = ((1 << IndexLOM) - 1);
|
||||
MaskedBits = (MatchLength - 2) & Mask;
|
||||
NCrushWriteBits(&DstPtr, &accumulator, &offset, MaskedBits, IndexLOM);
|
||||
|
||||
if (IndexCO >= ARRAYSIZE(LOMBaseLUT))
|
||||
return -1;
|
||||
if ((MaskedBits + LOMBaseLUT[IndexCO]) != MatchLength)
|
||||
return -1012;
|
||||
}
|
||||
|
@ -2806,6 +2876,10 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSize
|
|||
Literal = *SrcPtr++;
|
||||
HistoryPtr++;
|
||||
IndexLEC = Literal;
|
||||
if (IndexLEC >= ARRAYSIZE(HuffLengthLEC))
|
||||
return -1;
|
||||
if (IndexLEC * 2ull >= ARRAYSIZE(HuffCodeLEC))
|
||||
return -1;
|
||||
BitLength = HuffLengthLEC[IndexLEC];
|
||||
CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]);
|
||||
|
||||
|
@ -2866,6 +2940,7 @@ static int ncrush_generate_tables(NCRUSH_CONTEXT* context)
|
|||
k = 0;
|
||||
|
||||
WINPR_ASSERT(context);
|
||||
WINPR_ASSERT(28 < ARRAYSIZE(LOMBitsLUT));
|
||||
|
||||
for (i = 0; i < 28; i++)
|
||||
{
|
||||
|
@ -2883,6 +2958,11 @@ static int ncrush_generate_tables(NCRUSH_CONTEXT* context)
|
|||
else
|
||||
i = context->HuffTableLOM[k];
|
||||
|
||||
if (i >= ARRAYSIZE(LOMBitsLUT))
|
||||
return -1;
|
||||
if (i >= ARRAYSIZE(LOMBaseLUT))
|
||||
return -1;
|
||||
|
||||
if (((((1 << LOMBitsLUT[i]) - 1) & (k - 2)) + LOMBaseLUT[i]) != k)
|
||||
return -1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue