diff options
Diffstat (limited to 'libfreerdp/codec')
-rw-r--r-- | libfreerdp/codec/clear.c | 23 | ||||
-rw-r--r-- | libfreerdp/codec/color.c | 91 | ||||
-rw-r--r-- | libfreerdp/codec/h264_ffmpeg.c | 1 | ||||
-rw-r--r-- | libfreerdp/codec/interleaved.c | 11 | ||||
-rw-r--r-- | libfreerdp/codec/nsc.c | 14 | ||||
-rw-r--r-- | libfreerdp/codec/planar.c | 3 | ||||
-rw-r--r-- | libfreerdp/codec/progressive.c | 144 | ||||
-rw-r--r-- | libfreerdp/codec/rfx.c | 3 | ||||
-rw-r--r-- | libfreerdp/codec/test/TestFuzzCodecs.c | 31 | ||||
-rw-r--r-- | libfreerdp/codec/yuv.c | 3 | ||||
-rw-r--r-- | libfreerdp/codec/zgfx.c | 75 |
11 files changed, 225 insertions, 174 deletions
diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c index 512aeae..c9538c8 100644 --- a/libfreerdp/codec/clear.c +++ b/libfreerdp/codec/clear.c @@ -500,12 +500,12 @@ static BOOL clear_decompress_subcodecs_data(CLEAR_CONTEXT* clear, wStream* s, { case 0: /* Uncompressed */ { - UINT32 nSrcStep = width * FreeRDPGetBytesPerPixel(PIXEL_FORMAT_BGR24); - UINT32 nSrcSize = nSrcStep * height; + const UINT32 nSrcStep = width * FreeRDPGetBytesPerPixel(PIXEL_FORMAT_BGR24); + const size_t nSrcSize = 1ull * nSrcStep * height; if (bitmapDataByteCount != nSrcSize) { - WLog_ERR(TAG, "bitmapDataByteCount %" PRIu32 " != nSrcSize %" PRIu32 "", + WLog_ERR(TAG, "bitmapDataByteCount %" PRIu32 " != nSrcSize %" PRIuz "", bitmapDataByteCount, nSrcSize); return FALSE; } @@ -798,10 +798,16 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32 count = (vBarPixelCount > y) ? (vBarPixelCount - y) : 0; if (count > 0) - pSrcPixel = - &vBarShortEntry - ->pixels[(y - vBarYOn) * FreeRDPGetBytesPerPixel(clear->format)]; - + { + const size_t offset = + (1ull * y - vBarYOn) * FreeRDPGetBytesPerPixel(clear->format); + pSrcPixel = &vBarShortEntry->pixels[offset]; + if (offset + count > vBarShortEntry->count) + { + WLog_ERR(TAG, "offset + count > vBarShortEntry->count"); + return FALSE; + } + } for (UINT32 x = 0; x < count; x++) { UINT32 color = 0; @@ -1169,7 +1175,10 @@ CLEAR_CONTEXT* clear_context_new(BOOL Compressor) return clear; error_nsc: + WINPR_PRAGMA_DIAG_PUSH + WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC clear_context_free(clear); + WINPR_PRAGMA_DIAG_POP return NULL; } diff --git a/libfreerdp/codec/color.c b/libfreerdp/codec/color.c index 186d477..2c3d08a 100644 --- a/libfreerdp/codec/color.c +++ b/libfreerdp/codec/color.c @@ -583,16 +583,16 @@ static BOOL freerdp_image_copy_no_overlap(BYTE* WINPR_RESTRICT pDstData, DWORD D UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* WINPR_RESTRICT palette, UINT32 flags) { - const UINT32 dstByte = FreeRDPGetBytesPerPixel(DstFormat); - const UINT32 srcByte = FreeRDPGetBytesPerPixel(SrcFormat); - const UINT32 copyDstWidth = nWidth * dstByte; - const UINT32 xSrcOffset = nXSrc * srcByte; - const UINT32 xDstOffset = nXDst * dstByte; + const SSIZE_T dstByte = FreeRDPGetBytesPerPixel(DstFormat); + const SSIZE_T srcByte = FreeRDPGetBytesPerPixel(SrcFormat); + const SSIZE_T copyDstWidth = nWidth * dstByte; + const SSIZE_T xSrcOffset = nXSrc * srcByte; + const SSIZE_T xDstOffset = nXDst * dstByte; const BOOL vSrcVFlip = (flags & FREERDP_FLIP_VERTICAL) ? TRUE : FALSE; - UINT32 srcVOffset = 0; - INT32 srcVMultiplier = 1; - UINT32 dstVOffset = 0; - INT32 dstVMultiplier = 1; + SSIZE_T srcVOffset = 0; + SSIZE_T srcVMultiplier = 1; + SSIZE_T dstVOffset = 0; + SSIZE_T dstVMultiplier = 1; if ((nHeight > INT32_MAX) || (nWidth > INT32_MAX)) return FALSE; @@ -608,24 +608,24 @@ static BOOL freerdp_image_copy_no_overlap(BYTE* WINPR_RESTRICT pDstData, DWORD D if (vSrcVFlip) { - srcVOffset = (nHeight - 1) * nSrcStep; + srcVOffset = (nHeight - 1ll) * nSrcStep; srcVMultiplier = -1; } if (((flags & FREERDP_KEEP_DST_ALPHA) != 0) && FreeRDPColorHasAlpha(DstFormat)) { - for (UINT32 y = 0; y < nHeight; y++) + for (SSIZE_T y = 0; y < nHeight; y++) { const BYTE* WINPR_RESTRICT srcLine = - &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset]; + &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset]; BYTE* WINPR_RESTRICT dstLine = - &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset]; + &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; UINT32 color = FreeRDPReadColor(&srcLine[nXSrc * srcByte], SrcFormat); UINT32 oldColor = color; UINT32 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette); FreeRDPWriteColorIgnoreAlpha(&dstLine[nXDst * dstByte], DstFormat, dstColor); - for (UINT32 x = 1; x < nWidth; x++) + for (SSIZE_T x = 1; x < nWidth; x++) { color = FreeRDPReadColor(&srcLine[(x + nXSrc) * srcByte], SrcFormat); if (color == oldColor) @@ -645,29 +645,29 @@ static BOOL freerdp_image_copy_no_overlap(BYTE* WINPR_RESTRICT pDstData, DWORD D } else if (FreeRDPAreColorFormatsEqualNoAlpha(SrcFormat, DstFormat)) { - for (UINT32 y = 0; y < nHeight; y++) + for (SSIZE_T y = 0; y < nHeight; y++) { const BYTE* WINPR_RESTRICT srcLine = - &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset]; + &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset]; BYTE* WINPR_RESTRICT dstLine = - &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset]; + &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; memcpy(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth); } } else { - for (UINT32 y = 0; y < nHeight; y++) + for (SSIZE_T y = 0; y < nHeight; y++) { const BYTE* WINPR_RESTRICT srcLine = - &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset]; + &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset]; BYTE* WINPR_RESTRICT dstLine = - &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset]; + &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; UINT32 color = FreeRDPReadColor(&srcLine[nXSrc * srcByte], SrcFormat); UINT32 oldColor = color; UINT32 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette); FreeRDPWriteColor(&dstLine[nXDst * dstByte], DstFormat, dstColor); - for (UINT32 x = 1; x < nWidth; x++) + for (SSIZE_T x = 1; x < nWidth; x++) { color = FreeRDPReadColor(&srcLine[(x + nXSrc) * srcByte], SrcFormat); if (color == oldColor) @@ -699,10 +699,10 @@ static BOOL freerdp_image_copy_overlap(BYTE* pDstData, DWORD DstFormat, UINT32 n const UINT32 xSrcOffset = nXSrc * srcByte; const UINT32 xDstOffset = nXDst * dstByte; const BOOL vSrcVFlip = (flags & FREERDP_FLIP_VERTICAL) ? TRUE : FALSE; - UINT32 srcVOffset = 0; - INT32 srcVMultiplier = 1; - UINT32 dstVOffset = 0; - INT32 dstVMultiplier = 1; + SSIZE_T srcVOffset = 0; + SSIZE_T srcVMultiplier = 1; + SSIZE_T dstVOffset = 0; + SSIZE_T dstVMultiplier = 1; if ((nHeight > INT32_MAX) || (nWidth > INT32_MAX)) return FALSE; @@ -718,16 +718,16 @@ static BOOL freerdp_image_copy_overlap(BYTE* pDstData, DWORD DstFormat, UINT32 n if (vSrcVFlip) { - srcVOffset = (nHeight - 1) * nSrcStep; + srcVOffset = (nHeight - 1ll) * nSrcStep; srcVMultiplier = -1; } if (((flags & FREERDP_KEEP_DST_ALPHA) != 0) && FreeRDPColorHasAlpha(DstFormat)) { - for (UINT32 y = 0; y < nHeight; y++) + for (SSIZE_T y = 0; y < nHeight; y++) { - const BYTE* srcLine = &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset]; - BYTE* dstLine = &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset]; + const BYTE* srcLine = &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset]; + BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; UINT32 color = FreeRDPReadColor(&srcLine[nXSrc * srcByte], SrcFormat); UINT32 oldColor = color; @@ -756,44 +756,44 @@ static BOOL freerdp_image_copy_overlap(BYTE* pDstData, DWORD DstFormat, UINT32 n /* Copy down */ if (nYDst < nYSrc) { - for (INT32 y = 0; y < (INT32)nHeight; y++) + for (SSIZE_T y = 0; y < nHeight; y++) { const BYTE* srcLine = &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset]; - BYTE* dstLine = &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset]; + BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; memcpy(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth); } } /* Copy up */ else if (nYDst > nYSrc) { - for (INT32 y = (INT32)nHeight - 1; y >= 0; y--) + for (SSIZE_T y = nHeight - 1; y >= 0; y--) { const BYTE* srcLine = - &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset]; - BYTE* dstLine = &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset]; + &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset]; + BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; memcpy(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth); } } /* Copy left */ else if (nXSrc > nXDst) { - for (INT32 y = 0; y < (INT32)nHeight; y++) + for (SSIZE_T y = 0; y < nHeight; y++) { const BYTE* srcLine = - &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset]; - BYTE* dstLine = &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset]; + &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset]; + BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; memmove(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth); } } /* Copy right */ else if (nXSrc < nXDst) { - for (INT32 y = (INT32)nHeight - 1; y >= 0; y--) + for (SSIZE_T y = nHeight - 1; y >= 0; y--) { const BYTE* srcLine = - &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset]; - BYTE* dstLine = &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset]; + &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset]; + BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; memmove(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth); } } @@ -804,16 +804,16 @@ static BOOL freerdp_image_copy_overlap(BYTE* pDstData, DWORD DstFormat, UINT32 n } else { - for (UINT32 y = 0; y < nHeight; y++) + for (SSIZE_T y = 0; y < nHeight; y++) { - const BYTE* srcLine = &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset]; - BYTE* dstLine = &pDstData[(y + nYDst) * nDstStep * dstVMultiplier + dstVOffset]; + const BYTE* srcLine = &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset]; + BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset]; UINT32 color = FreeRDPReadColor(&srcLine[nXSrc * srcByte], SrcFormat); UINT32 oldColor = color; UINT32 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette); FreeRDPWriteColor(&dstLine[nXDst * dstByte], DstFormat, dstColor); - for (UINT32 x = 1; x < nWidth; x++) + for (SSIZE_T x = 1; x < nWidth; x++) { color = FreeRDPReadColor(&srcLine[(x + nXSrc) * srcByte], SrcFormat); if (color == oldColor) @@ -847,6 +847,9 @@ BOOL freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 if (!pDstData || !pSrcData) return FALSE; + if ((nWidth == 0) || (nHeight == 0)) + return TRUE; + if (nDstStep == 0) nDstStep = nWidth * FreeRDPGetBytesPerPixel(DstFormat); diff --git a/libfreerdp/codec/h264_ffmpeg.c b/libfreerdp/codec/h264_ffmpeg.c index 54492e1..a2ad12f 100644 --- a/libfreerdp/codec/h264_ffmpeg.c +++ b/libfreerdp/codec/h264_ffmpeg.c @@ -636,6 +636,7 @@ static BOOL libavcodec_init(H264_CONTEXT* h264) goto fail_hwdevice_create; } } + WLog_Print(h264->log, WLOG_INFO, "Using VAAPI for accelerated H264 decoding"); sys->codecDecoderContext->get_format = libavcodec_get_format; sys->hw_pix_fmt = AV_PIX_FMT_VAAPI; diff --git a/libfreerdp/codec/interleaved.c b/libfreerdp/codec/interleaved.c index df148b6..262895d 100644 --- a/libfreerdp/codec/interleaved.c +++ b/libfreerdp/codec/interleaved.c @@ -212,7 +212,7 @@ static UINT ExtractRunLengthRegularFgBg(const BYTE* pbOrderHdr, const BYTE* pbEn runLength = (*pbOrderHdr) & g_MaskRegularRunLength; if (runLength == 0) { - if (!buffer_within_range(pbOrderHdr, 1, pbEnd)) + if (!buffer_within_range(pbOrderHdr, 2, pbEnd)) { *advance = 0; return 0; @@ -262,7 +262,7 @@ static UINT ExtractRunLengthRegular(const BYTE* pbOrderHdr, const BYTE* pbEnd, U runLength = *pbOrderHdr & g_MaskRegularRunLength; if (runLength == 0) { - if (!buffer_within_range(pbOrderHdr, 1, pbEnd)) + if (!buffer_within_range(pbOrderHdr, 2, pbEnd)) { *advance = 0; return 0; @@ -282,7 +282,7 @@ static UINT ExtractRunLengthMegaMega(const BYTE* pbOrderHdr, const BYTE* pbEnd, WINPR_ASSERT(pbEnd); WINPR_ASSERT(advance); - if (!buffer_within_range(pbOrderHdr, 2, pbEnd)) + if (!buffer_within_range(pbOrderHdr, 3, pbEnd)) { *advance = 0; return 0; @@ -305,7 +305,7 @@ static UINT ExtractRunLengthLite(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT runLength = *pbOrderHdr & g_MaskLiteRunLength; if (runLength == 0) { - if (!buffer_within_range(pbOrderHdr, 1, pbEnd)) + if (!buffer_within_range(pbOrderHdr, 2, pbEnd)) { *advance = 0; return 0; @@ -735,7 +735,10 @@ BITMAP_INTERLEAVED_CONTEXT* bitmap_interleaved_context_new(BOOL Compressor) return interleaved; fail: + WINPR_PRAGMA_DIAG_PUSH + WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC bitmap_interleaved_context_free(interleaved); + WINPR_PRAGMA_DIAG_POP return NULL; } diff --git a/libfreerdp/codec/nsc.c b/libfreerdp/codec/nsc.c index 74f4e28..d1b594b 100644 --- a/libfreerdp/codec/nsc.c +++ b/libfreerdp/codec/nsc.c @@ -86,8 +86,8 @@ static BOOL nsc_decode(NSC_CONTEXT* context) for (UINT32 x = 0; x < context->width; x++) { INT16 y_val = (INT16)*yplane; - INT16 co_val = (INT16)(INT8)(*coplane << shift); - INT16 cg_val = (INT16)(INT8)(*cgplane << shift); + INT16 co_val = (INT16)(INT8)(((INT16)*coplane) << shift); + INT16 cg_val = (INT16)(INT8)(((INT16)*cgplane) << shift); INT16 r_val = y_val + co_val - cg_val; INT16 g_val = y_val + cg_val; INT16 b_val = y_val - co_val - cg_val; @@ -250,6 +250,13 @@ static BOOL nsc_stream_initialize(NSC_CONTEXT* context, wStream* s) } Stream_Read_UINT8(s, context->ColorLossLevel); /* ColorLossLevel (1 byte) */ + if ((context->ColorLossLevel < 1) || (context->ColorLossLevel > 7)) + { + WLog_Print(context->priv->log, WLOG_ERROR, + "ColorLossLevel=%" PRIu8 " out of range, must be [1,7] inclusive", + context->ColorLossLevel); + return FALSE; + } Stream_Read_UINT8(s, context->ChromaSubsamplingLevel); /* ChromaSubsamplingLevel (1 byte) */ Stream_Seek(s, 2); /* Reserved (2 bytes) */ context->Planes = Stream_Pointer(s); @@ -363,7 +370,10 @@ NSC_CONTEXT* nsc_context_new(void) NSC_INIT_SIMD(context); return context; error: + WINPR_PRAGMA_DIAG_PUSH + WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC nsc_context_free(context); + WINPR_PRAGMA_DIAG_POP return NULL; } diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c index 4b51a02..e894761 100644 --- a/libfreerdp/codec/planar.c +++ b/libfreerdp/codec/planar.c @@ -1747,7 +1747,10 @@ BITMAP_PLANAR_CONTEXT* freerdp_bitmap_planar_context_new(DWORD flags, UINT32 max if (!freerdp_bitmap_planar_context_reset(context, maxWidth, maxHeight)) { + WINPR_PRAGMA_DIAG_PUSH + WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC freerdp_bitmap_planar_context_free(context); + WINPR_PRAGMA_DIAG_POP return NULL; } diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index df98ad3..3ab84ef 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -2312,67 +2312,11 @@ static SSIZE_T progressive_parse_block(PROGRESSIVE_CONTEXT* progressive, wStream return rc; } -INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData, UINT32 SrcSize, - BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, - UINT32 nYDst, REGION16* invalidRegion, UINT16 surfaceId, - UINT32 frameId) +static BOOL update_tiles(PROGRESSIVE_CONTEXT* progressive, PROGRESSIVE_SURFACE_CONTEXT* surface, + BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, + UINT32 nYDst, PROGRESSIVE_BLOCK_REGION* region, REGION16* invalidRegion) { - INT32 rc = 1; - - WINPR_ASSERT(progressive); - PROGRESSIVE_SURFACE_CONTEXT* surface = progressive_get_surface_data(progressive, surfaceId); - - if (!surface) - { - WLog_Print(progressive->log, WLOG_ERROR, "ProgressiveRegion no surface for %" PRIu16, - surfaceId); - return -1001; - } - - PROGRESSIVE_BLOCK_REGION* region = &progressive->region; - WINPR_ASSERT(region); - - if (surface->frameId != frameId) - { - surface->frameId = frameId; - surface->numUpdatedTiles = 0; - } - - wStream ss = { 0 }; - wStream* s = Stream_StaticConstInit(&ss, pSrcData, SrcSize); - WINPR_ASSERT(s); - - switch (DstFormat) - { - case PIXEL_FORMAT_RGBA32: - case PIXEL_FORMAT_RGBX32: - case PIXEL_FORMAT_BGRA32: - case PIXEL_FORMAT_BGRX32: - progressive->format = DstFormat; - break; - default: - progressive->format = PIXEL_FORMAT_XRGB32; - break; - } - - const size_t start = Stream_GetPosition(s); - progressive->state = 0; /* Set state to not initialized */ - while (Stream_GetRemainingLength(s) > 0) - { - if (progressive_parse_block(progressive, s, surface, region) < 0) - goto fail; - } - - const size_t end = Stream_GetPosition(s); - if ((end - start) != SrcSize) - { - WLog_Print(progressive->log, WLOG_ERROR, - "total block len %" PRIuz " does not match read data %" PRIu32, end - start, - SrcSize); - rc = -1041; - goto fail; - } - + BOOL rc = TRUE; REGION16 clippingRects = { 0 }; region16_init(&clippingRects); @@ -2425,13 +2369,11 @@ INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcD goto fail; if (rect->top + height > surface->height) goto fail; - if (!freerdp_image_copy(pDstData, DstFormat, nDstStep, rect->left, rect->top, width, + rc = freerdp_image_copy(pDstData, DstFormat, nDstStep, rect->left, rect->top, width, height, tile->data, progressive->format, tile->stride, nXSrc, - nYSrc, NULL, FREERDP_KEEP_DST_ALPHA)) - { - rc = -42; + nYSrc, NULL, FREERDP_KEEP_DST_ALPHA); + if (!rc) break; - } if (invalidRegion) region16_union_rect(invalidRegion, invalidRegion, rect); @@ -2441,8 +2383,75 @@ INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcD tile->dirty = FALSE; } +fail: region16_uninit(&clippingRects); - surface->numUpdatedTiles = 0; + return rc; +} + +INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData, UINT32 SrcSize, + BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, + UINT32 nYDst, REGION16* invalidRegion, UINT16 surfaceId, + UINT32 frameId) +{ + INT32 rc = 1; + + WINPR_ASSERT(progressive); + PROGRESSIVE_SURFACE_CONTEXT* surface = progressive_get_surface_data(progressive, surfaceId); + + if (!surface) + { + WLog_Print(progressive->log, WLOG_ERROR, "ProgressiveRegion no surface for %" PRIu16, + surfaceId); + return -1001; + } + + PROGRESSIVE_BLOCK_REGION* region = &progressive->region; + WINPR_ASSERT(region); + + if (surface->frameId != frameId) + { + surface->frameId = frameId; + surface->numUpdatedTiles = 0; + } + + wStream ss = { 0 }; + wStream* s = Stream_StaticConstInit(&ss, pSrcData, SrcSize); + WINPR_ASSERT(s); + + switch (DstFormat) + { + case PIXEL_FORMAT_RGBA32: + case PIXEL_FORMAT_RGBX32: + case PIXEL_FORMAT_BGRA32: + case PIXEL_FORMAT_BGRX32: + progressive->format = DstFormat; + break; + default: + progressive->format = PIXEL_FORMAT_XRGB32; + break; + } + + const size_t start = Stream_GetPosition(s); + progressive->state = 0; /* Set state to not initialized */ + while (Stream_GetRemainingLength(s) > 0) + { + if (progressive_parse_block(progressive, s, surface, region) < 0) + goto fail; + } + + const size_t end = Stream_GetPosition(s); + if ((end - start) != SrcSize) + { + WLog_Print(progressive->log, WLOG_ERROR, + "total block len %" PRIuz " does not match read data %" PRIu32, end - start, + SrcSize); + rc = -1041; + goto fail; + } + + if (!update_tiles(progressive, surface, pDstData, DstFormat, nDstStep, nXDst, nYDst, region, + invalidRegion)) + return -2002; fail: return rc; } @@ -2631,7 +2640,10 @@ PROGRESSIVE_CONTEXT* progressive_context_new_ex(BOOL Compressor, UINT32 Threadin } return progressive; fail: + WINPR_PRAGMA_DIAG_PUSH + WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC progressive_context_free(progressive); + WINPR_PRAGMA_DIAG_POP return NULL; } diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index 66ed1e0..c12f6d4 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -342,7 +342,10 @@ RFX_CONTEXT* rfx_context_new_ex(BOOL encoder, UINT32 ThreadingFlags) context->expectedDataBlockType = WBT_FRAME_BEGIN; return context; fail: + WINPR_PRAGMA_DIAG_PUSH + WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC rfx_context_free(context); + WINPR_PRAGMA_DIAG_POP return NULL; } diff --git a/libfreerdp/codec/test/TestFuzzCodecs.c b/libfreerdp/codec/test/TestFuzzCodecs.c index d83d8d4..f923765 100644 --- a/libfreerdp/codec/test/TestFuzzCodecs.c +++ b/libfreerdp/codec/test/TestFuzzCodecs.c @@ -453,28 +453,15 @@ int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) if (Size < 4) return 0; - int i = 0; - winpr_RAND(&i, sizeof(i)); - i = i % 18; - - if (i < 2) - TestFreeRDPCodecClear(Data, Size); - else if (i < 4) - TestFreeRDPCodecXCrush(Data, Size); - else if (i < 6) - TestFreeRDPCodecZGfx(Data, Size); - else if (i < 8) - TestFreeRDPCodecNCrush(Data, Size); - else if (i < 10) - TestFreeRDPCodecRemoteFX(Data, Size); - else if (i < 12) - TestFreeRDPCodecMppc(Data, Size); - else if (i < 14) - TestFreeRDPCodecProgressive(Data, Size); - else if (i < 16) - TestFreeRDPCodecInterleaved(Data, Size); - else if (i < 18) - TestFreeRDPCodecPlanar(Data, Size); + TestFreeRDPCodecClear(Data, Size); + TestFreeRDPCodecXCrush(Data, Size); + TestFreeRDPCodecZGfx(Data, Size); + TestFreeRDPCodecNCrush(Data, Size); + TestFreeRDPCodecRemoteFX(Data, Size); + TestFreeRDPCodecMppc(Data, Size); + TestFreeRDPCodecProgressive(Data, Size); + TestFreeRDPCodecInterleaved(Data, Size); + TestFreeRDPCodecPlanar(Data, Size); return 0; } diff --git a/libfreerdp/codec/yuv.c b/libfreerdp/codec/yuv.c index c546566..97c2374 100644 --- a/libfreerdp/codec/yuv.c +++ b/libfreerdp/codec/yuv.c @@ -251,7 +251,10 @@ YUV_CONTEXT* yuv_context_new(BOOL encoder, UINT32 ThreadingFlags) return ret; error_threadpool: + WINPR_PRAGMA_DIAG_PUSH + WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC yuv_context_free(ret); + WINPR_PRAGMA_DIAG_POP return NULL; } diff --git a/libfreerdp/codec/zgfx.c b/libfreerdp/codec/zgfx.c index b7ee275..3a9d2e5 100644 --- a/libfreerdp/codec/zgfx.c +++ b/libfreerdp/codec/zgfx.c @@ -382,16 +382,46 @@ static BYTE* aligned_zgfx_malloc(size_t size) return malloc(size + 64); } +static BOOL zgfx_append(ZGFX_CONTEXT* zgfx, BYTE** ppConcatenated, size_t uncompressedSize, + size_t* pUsed) +{ + WINPR_ASSERT(zgfx); + WINPR_ASSERT(ppConcatenated); + WINPR_ASSERT(pUsed); + + const size_t used = *pUsed; + if (zgfx->OutputCount > UINT32_MAX - used) + return FALSE; + + if (used + zgfx->OutputCount > uncompressedSize) + return FALSE; + + BYTE* tmp = realloc(*ppConcatenated, used + zgfx->OutputCount + 64ull); + if (!tmp) + return FALSE; + *ppConcatenated = tmp; + CopyMemory(&tmp[used], zgfx->OutputBuffer, zgfx->OutputCount); + *pUsed = used + zgfx->OutputCount; + return TRUE; +} + int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags) { int status = -1; BYTE descriptor = 0; wStream sbuffer = { 0 }; + size_t used = 0; + BYTE* pConcatenated = NULL; wStream* stream = Stream_StaticConstInit(&sbuffer, pSrcData, SrcSize); WINPR_ASSERT(zgfx); WINPR_ASSERT(stream); + WINPR_ASSERT(ppDstData); + WINPR_ASSERT(pDstSize); + + *ppDstData = NULL; + *pDstSize = 0; if (!Stream_CheckAndLogRequiredLength(TAG, stream, 1)) goto fail; @@ -403,16 +433,15 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY if (!zgfx_decompress_segment(zgfx, stream, Stream_GetRemainingLength(stream))) goto fail; - *ppDstData = NULL; - if (zgfx->OutputCount > 0) - *ppDstData = aligned_zgfx_malloc(zgfx->OutputCount); - - if (!*ppDstData) - goto fail; - - *pDstSize = zgfx->OutputCount; - CopyMemory(*ppDstData, zgfx->OutputBuffer, zgfx->OutputCount); + { + if (!zgfx_append(zgfx, &pConcatenated, zgfx->OutputCount, &used)) + goto fail; + if (used != zgfx->OutputCount) + goto fail; + *ppDstData = pConcatenated; + *pDstSize = zgfx->OutputCount; + } } else if (descriptor == ZGFX_SEGMENTED_MULTIPART) { @@ -420,8 +449,6 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY UINT16 segmentNumber = 0; UINT16 segmentCount = 0; UINT32 uncompressedSize = 0; - BYTE* pConcatenated = NULL; - size_t used = 0; if (!Stream_CheckAndLogRequiredLength(TAG, stream, 6)) goto fail; @@ -429,17 +456,6 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY Stream_Read_UINT16(stream, segmentCount); /* segmentCount (2 bytes) */ Stream_Read_UINT32(stream, uncompressedSize); /* uncompressedSize (4 bytes) */ - if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, stream, segmentCount, sizeof(UINT32))) - goto fail; - - pConcatenated = aligned_zgfx_malloc(uncompressedSize); - - if (!pConcatenated) - goto fail; - - *ppDstData = pConcatenated; - *pDstSize = uncompressedSize; - for (segmentNumber = 0; segmentNumber < segmentCount; segmentNumber++) { if (!Stream_CheckAndLogRequiredLength(TAG, stream, sizeof(UINT32))) @@ -450,16 +466,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) + if (!zgfx_append(zgfx, &pConcatenated, uncompressedSize, &used)) goto fail; + } - if (used + zgfx->OutputCount > uncompressedSize) - goto fail; + if (used != uncompressedSize) + goto fail; - CopyMemory(pConcatenated, zgfx->OutputBuffer, zgfx->OutputCount); - pConcatenated += zgfx->OutputCount; - used += zgfx->OutputCount; - } + *ppDstData = pConcatenated; + *pDstSize = uncompressedSize; } else { @@ -468,6 +483,8 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY status = 1; fail: + if (status < 0) + free(pConcatenated); return status; } |