Permalink
Browse files

Fixed CVE-2018-8785

Thanks to Eyal Itkin from Check Point Software Technologies.
  • Loading branch information...
akallabeth committed Oct 22, 2018
1 parent 2ee663f commit 602f4a2e14b41703b5f431de3154cd46a5750a2d
Showing with 61 additions and 39 deletions.
  1. +7 −23 include/freerdp/codec/zgfx.h
  2. +54 −16 libfreerdp/codec/zgfx.c
@@ -32,34 +32,18 @@
#define ZGFX_SEGMENTED_MAXSIZE 65535
struct _ZGFX_CONTEXT
{
BOOL Compressor;
const BYTE* pbInputCurrent;
const BYTE* pbInputEnd;
UINT32 bits;
UINT32 cBitsRemaining;
UINT32 BitsCurrent;
UINT32 cBitsCurrent;
BYTE OutputBuffer[65536];
UINT32 OutputCount;
BYTE HistoryBuffer[2500000];
UINT32 HistoryIndex;
UINT32 HistoryBufferSize;
};
typedef struct _ZGFX_CONTEXT ZGFX_CONTEXT;
#ifdef __cplusplus
extern "C" {
#endif
FREERDP_API int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags);
FREERDP_API int zgfx_compress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags);
FREERDP_API int zgfx_compress_to_stream(ZGFX_CONTEXT* zgfx, wStream* sDst, const BYTE* pUncompressed, UINT32 uncompressedSize, UINT32* pFlags);
FREERDP_API int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize,
BYTE** ppDstData, UINT32* pDstSize, UINT32 flags);
FREERDP_API int zgfx_compress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize,
BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags);
FREERDP_API int zgfx_compress_to_stream(ZGFX_CONTEXT* zgfx, wStream* sDst,
const BYTE* pUncompressed, UINT32 uncompressedSize, UINT32* pFlags);
FREERDP_API void zgfx_context_reset(ZGFX_CONTEXT* zgfx, BOOL flush);
@@ -71,4 +55,4 @@ FREERDP_API void zgfx_context_free(ZGFX_CONTEXT* zgfx);
#endif
#endif /* FREERDP_CODEC_ZGFX_H */
@@ -44,14 +44,34 @@
struct _ZGFX_TOKEN
{
int prefixLength;
int prefixCode;
int valueBits;
int tokenType;
UINT32 prefixLength;
UINT32 prefixCode;
UINT32 valueBits;
UINT32 tokenType;
UINT32 valueBase;
};
typedef struct _ZGFX_TOKEN ZGFX_TOKEN;
struct _ZGFX_CONTEXT
{
BOOL Compressor;
const BYTE* pbInputCurrent;
const BYTE* pbInputEnd;
UINT32 bits;
UINT32 cBitsRemaining;
UINT32 BitsCurrent;
UINT32 cBitsCurrent;
BYTE OutputBuffer[65536];
UINT32 OutputCount;
BYTE HistoryBuffer[2500000];
UINT32 HistoryIndex;
UINT32 HistoryBufferSize;
};
static const ZGFX_TOKEN ZGFX_TOKEN_TABLE[] =
{
// len code vbits type vbase
@@ -98,17 +118,26 @@ static const ZGFX_TOKEN ZGFX_TOKEN_TABLE[] =
{ 0 }
};
#define zgfx_GetBits(_zgfx, _nbits) \
while (_zgfx->cBitsCurrent < _nbits) { \
_zgfx->BitsCurrent <<= 8; \
if (_zgfx->pbInputCurrent < _zgfx->pbInputEnd) \
_zgfx->BitsCurrent += *(_zgfx->pbInputCurrent)++; \
_zgfx->cBitsCurrent += 8; \
} \
_zgfx->cBitsRemaining -= _nbits; \
_zgfx->cBitsCurrent -= _nbits; \
_zgfx->bits = _zgfx->BitsCurrent >> _zgfx->cBitsCurrent; \
static INLINE BOOL zgfx_GetBits(ZGFX_CONTEXT* _zgfx, UINT32 _nbits)
{
if (!_zgfx)
return FALSE;
while (_zgfx->cBitsCurrent < _nbits)
{
_zgfx->BitsCurrent <<= 8;
if (_zgfx->pbInputCurrent < _zgfx->pbInputEnd)
_zgfx->BitsCurrent += *(_zgfx->pbInputCurrent)++;
_zgfx->cBitsCurrent += 8;
}
_zgfx->cBitsRemaining -= _nbits;
_zgfx->cBitsCurrent -= _nbits;
_zgfx->bits = _zgfx->BitsCurrent >> _zgfx->cBitsCurrent;
_zgfx->BitsCurrent &= ((1 << _zgfx->cBitsCurrent) - 1);
}
static void zgfx_history_buffer_ring_write(ZGFX_CONTEXT* zgfx, const BYTE* src, size_t count)
{
@@ -193,7 +222,7 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
{
BYTE c;
BYTE flags;
int extra;
UINT32 extra = 0;
int opIndex;
int haveBits;
int inPrefix;
@@ -317,8 +346,8 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
{
int status = -1;
BYTE descriptor;
wStream* stream = Stream_New((BYTE*)pSrcData, SrcSize);
if (!stream)
return -1;
@@ -333,6 +362,7 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
goto fail;
*ppDstData = NULL;
if (zgfx->OutputCount > 0)
*ppDstData = (BYTE*) malloc(zgfx->OutputCount);
@@ -349,6 +379,7 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
UINT16 segmentCount;
UINT32 uncompressedSize;
BYTE* pConcatenated;
size_t used = 0;
if (Stream_GetRemainingLength(stream) < 6)
goto fail;
@@ -377,8 +408,15 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
if (!zgfx_decompress_segment(zgfx, stream, segmentSize))
goto fail;
if (zgfx->OutputCount > UINT32_MAX - used)
goto fail;
if (used + zgfx->OutputCount > uncompressedSize)
goto fail;
CopyMemory(pConcatenated, zgfx->OutputBuffer, zgfx->OutputCount);
pConcatenated += zgfx->OutputCount;
used += zgfx->OutputCount;
}
}
else

0 comments on commit 602f4a2

Please sign in to comment.