Fixed endianess issues of zgfx decoder.

This commit is contained in:
Armin Novak 2017-11-21 17:32:54 +01:00
parent a834ef8243
commit dbdc4f4933

View File

@ -110,17 +110,16 @@ static const ZGFX_TOKEN ZGFX_TOKEN_TABLE[] =
_zgfx->bits = _zgfx->BitsCurrent >> _zgfx->cBitsCurrent; \ _zgfx->bits = _zgfx->BitsCurrent >> _zgfx->cBitsCurrent; \
_zgfx->BitsCurrent &= ((1 << _zgfx->cBitsCurrent) - 1); _zgfx->BitsCurrent &= ((1 << _zgfx->cBitsCurrent) - 1);
static void zgfx_history_buffer_ring_write(ZGFX_CONTEXT* zgfx, const BYTE* src, UINT32 count) static void zgfx_history_buffer_ring_write(ZGFX_CONTEXT* zgfx, const BYTE* src, size_t count)
{ {
UINT32 front; UINT32 front;
UINT32 residue;
if (count <= 0) if (count <= 0)
return; return;
if (count > zgfx->HistoryBufferSize) if (count > zgfx->HistoryBufferSize)
{ {
residue = count - zgfx->HistoryBufferSize; const size_t residue = count - zgfx->HistoryBufferSize;
count = zgfx->HistoryBufferSize; count = zgfx->HistoryBufferSize;
src += residue; src += residue;
zgfx->HistoryIndex = (zgfx->HistoryIndex + residue) % zgfx->HistoryBufferSize; zgfx->HistoryIndex = (zgfx->HistoryIndex + residue) % zgfx->HistoryBufferSize;
@ -190,7 +189,7 @@ static void zgfx_history_buffer_ring_read(ZGFX_CONTEXT* zgfx, int offset, BYTE*
while ((bytesLeft -= bytes) > 0); while ((bytesLeft -= bytes) > 0);
} }
static int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, const BYTE* pbSegment, UINT32 cbSegment) static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t segmentSize)
{ {
BYTE c; BYTE c;
BYTE flags; BYTE flags;
@ -200,21 +199,23 @@ static int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, const BYTE* pbSegment, UI
int inPrefix; int inPrefix;
UINT32 count; UINT32 count;
UINT32 distance; UINT32 distance;
BYTE* pbSegment;
size_t cbSegment = segmentSize - 1;
if (cbSegment < 1) if ((Stream_GetRemainingLength(stream) < segmentSize) || (segmentSize < 1))
return -1; return FALSE;
flags = pbSegment[0]; /* header (1 byte) */ Stream_Read_UINT8(stream, flags); /* header (1 byte) */
pbSegment++;
cbSegment--;
zgfx->OutputCount = 0; zgfx->OutputCount = 0;
pbSegment = Stream_Pointer(stream);
Stream_Seek(stream, cbSegment);
if (!(flags & PACKET_COMPRESSED)) if (!(flags & PACKET_COMPRESSED))
{ {
zgfx_history_buffer_ring_write(zgfx, pbSegment, cbSegment); zgfx_history_buffer_ring_write(zgfx, pbSegment, cbSegment);
CopyMemory(zgfx->OutputBuffer, pbSegment, cbSegment); CopyMemory(zgfx->OutputBuffer, pbSegment, cbSegment);
zgfx->OutputCount = cbSegment; zgfx->OutputCount = cbSegment;
return 1; return TRUE;
} }
zgfx->pbInputCurrent = pbSegment; zgfx->pbInputCurrent = pbSegment;
@ -308,31 +309,30 @@ static int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, const BYTE* pbSegment, UI
} }
} }
return 1; return TRUE;
} }
int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData,
UINT32* pDstSize, UINT32 flags) UINT32* pDstSize, UINT32 flags)
{ {
int status; int status = -1;
BYTE descriptor; BYTE descriptor;
wStream* stream = Stream_New((BYTE*)pSrcData, SrcSize);
if (SrcSize < 1) if (Stream_GetRemainingLength(stream) < 1)
return -1; goto fail;
descriptor = pSrcData[0]; /* descriptor (1 byte) */ Stream_Read_UINT8(stream, descriptor); /* descriptor (1 byte) */
if (descriptor == ZGFX_SEGMENTED_SINGLE) if (descriptor == ZGFX_SEGMENTED_SINGLE)
{ {
status = zgfx_decompress_segment(zgfx, &pSrcData[1], SrcSize - 1); if (!zgfx_decompress_segment(zgfx, stream, Stream_GetRemainingLength(stream)))
goto fail;
if (status < 0)
return status;
*ppDstData = (BYTE*) malloc(zgfx->OutputCount); *ppDstData = (BYTE*) malloc(zgfx->OutputCount);
if (!*ppDstData) if (!*ppDstData)
return -1; goto fail;
*pDstSize = zgfx->OutputCount; *pDstSize = zgfx->OutputCount;
CopyMemory(*ppDstData, zgfx->OutputBuffer, zgfx->OutputCount); CopyMemory(*ppDstData, zgfx->OutputBuffer, zgfx->OutputCount);
@ -346,52 +346,63 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
UINT32 uncompressedSize; UINT32 uncompressedSize;
BYTE* pConcatenated; BYTE* pConcatenated;
segmentOffset = 7; segmentOffset = 7;
segmentCount = *((UINT16*) &pSrcData[1]); /* segmentCount (2 bytes) */
uncompressedSize = *((UINT32*) &pSrcData[3]); /* uncompressedSize (4 bytes) */ if (Stream_GetRemainingLength(stream) < 6)
goto fail;
Stream_Read_UINT16(stream, segmentCount); /* segmentCount (2 bytes) */
Stream_Read_UINT32(stream, uncompressedSize); /* uncompressedSize (4 bytes) */
if (Stream_GetRemainingLength(stream) < segmentCount * sizeof(UINT32))
goto fail;
pConcatenated = (BYTE*) malloc(uncompressedSize); pConcatenated = (BYTE*) malloc(uncompressedSize);
if (!pConcatenated) if (!pConcatenated)
return -1; goto fail;
*ppDstData = pConcatenated; *ppDstData = pConcatenated;
*pDstSize = uncompressedSize; *pDstSize = uncompressedSize;
for (segmentNumber = 0; segmentNumber < segmentCount; segmentNumber++) for (segmentNumber = 0; segmentNumber < segmentCount; segmentNumber++)
{ {
segmentSize = *((UINT32*) &pSrcData[segmentOffset]); /* segmentSize (4 bytes) */ if (Stream_GetRemainingLength(stream) < sizeof(UINT32))
segmentOffset += 4; goto fail;
status = zgfx_decompress_segment(zgfx, &pSrcData[segmentOffset], segmentSize);
if (status < 0) Stream_Read_UINT32(stream, segmentSize); /* segmentSize (4 bytes) */
return status;
if (!zgfx_decompress_segment(zgfx, stream, segmentSize))
goto fail;
segmentOffset += segmentSize;
CopyMemory(pConcatenated, zgfx->OutputBuffer, zgfx->OutputCount); CopyMemory(pConcatenated, zgfx->OutputBuffer, zgfx->OutputCount);
pConcatenated += zgfx->OutputCount; pConcatenated += zgfx->OutputCount;
} }
} }
else else
{ {
return -1; goto fail;
} }
return 1; status = 1;
fail:
Stream_Free(stream, FALSE);
return status;
} }
static int zgfx_compress_segment(ZGFX_CONTEXT* zgfx, wStream* s, const BYTE* pSrcData, static BOOL zgfx_compress_segment(ZGFX_CONTEXT* zgfx, wStream* s, const BYTE* pSrcData,
UINT32 SrcSize, UINT32* pFlags) UINT32 SrcSize, UINT32* pFlags)
{ {
/* FIXME: Currently compression not implemented. Just copy the raw source */ /* FIXME: Currently compression not implemented. Just copy the raw source */
if (!Stream_EnsureRemainingCapacity(s, SrcSize + 1)) if (!Stream_EnsureRemainingCapacity(s, SrcSize + 1))
{ {
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
return -1; return FALSE;
} }
(*pFlags) |= ZGFX_PACKET_COMPR_TYPE_RDP8; /* RDP 8.0 compression format */ (*pFlags) |= ZGFX_PACKET_COMPR_TYPE_RDP8; /* RDP 8.0 compression format */
Stream_Write_UINT8(s, (*pFlags)); /* header (1 byte) */ Stream_Write_UINT8(s, (*pFlags)); /* header (1 byte) */
Stream_Write(s, pSrcData, SrcSize); Stream_Write(s, pSrcData, SrcSize);
return 1; return TRUE;
} }
int zgfx_compress_to_stream(ZGFX_CONTEXT* zgfx, wStream* sDst, const BYTE* pUncompressed, int zgfx_compress_to_stream(ZGFX_CONTEXT* zgfx, wStream* sDst, const BYTE* pUncompressed,
@ -448,10 +459,8 @@ int zgfx_compress_to_stream(ZGFX_CONTEXT* zgfx, wStream* sDst, const BYTE* pUnco
posDataStart = Stream_GetPosition(sDst); posDataStart = Stream_GetPosition(sDst);
if ((status = zgfx_compress_segment(zgfx, sDst, pSrcData, SrcSize, pFlags)) < 0) if (!zgfx_compress_segment(zgfx, sDst, pSrcData, SrcSize, pFlags))
{ return -1;
return status;
}
if (posDstSize) if (posDstSize)
{ {