diff --git a/libfreerdp/codec/bitmap_decode.c b/libfreerdp/codec/bitmap_decode.c index 72386fa99..2330872c9 100644 --- a/libfreerdp/codec/bitmap_decode.c +++ b/libfreerdp/codec/bitmap_decode.c @@ -271,7 +271,7 @@ BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int } else if (srcBpp == 32 && dstBpp == 32) { - if (!freerdp_bitmap_planar_decompress(srcData, dstData, width, height, size)) + if (freerdp_bitmap_planar_decompress(srcData, dstData, width, height, size) < 0) return FALSE; } else if (srcBpp == 15 && dstBpp == 15) diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c index 42bbe3fdb..dbcf61f29 100644 --- a/libfreerdp/codec/planar.c +++ b/libfreerdp/codec/planar.c @@ -28,8 +28,9 @@ #include "planar.h" -static int freerdp_bitmap_planar_decompress_plane_rle(BYTE* inPlane, int width, int height, BYTE* outPlane, int size) +static int freerdp_bitmap_planar_decompress_plane_rle(BYTE* inPlane, int width, int height, BYTE* outPlane, int srcSize) { + int k; int x, y; BYTE* srcp; BYTE* dstp; @@ -42,6 +43,8 @@ static int freerdp_bitmap_planar_decompress_plane_rle(BYTE* inPlane, int width, BYTE* currentScanline; BYTE* previousScanline; + k = 0; + srcp = inPlane; dstp = outPlane; scanline = width * 4; @@ -62,9 +65,17 @@ static int freerdp_bitmap_planar_decompress_plane_rle(BYTE* inPlane, int width, controlByte = *srcp; srcp++; + if ((srcp - inPlane) > srcSize) + { + printf("freerdp_bitmap_planar_decompress_plane_rle: error reading input buffer\n"); + return -1; + } + nRunLength = PLANAR_CONTROL_BYTE_RUN_LENGTH(controlByte); cRawBytes = PLANAR_CONTROL_BYTE_RAW_BYTES(controlByte); + //printf("CONTROL(%d, %d)\n", cRawBytes, nRunLength); + if (nRunLength == 1) { nRunLength = cRawBytes + 16; @@ -76,6 +87,26 @@ static int freerdp_bitmap_planar_decompress_plane_rle(BYTE* inPlane, int width, cRawBytes = 0; } +#if 0 + printf("y: %d cRawBytes: %d nRunLength: %d\n", y, cRawBytes, nRunLength); + + printf("RAW["); + + for (k = 0; k < cRawBytes; k++) + { + printf("0x%02X%s", srcp[k], + ((k + 1) == cRawBytes) ? "" : ", "); + } + + printf("] RUN[%d]\n", nRunLength); +#endif + + if (((dstp + (cRawBytes + nRunLength)) - currentScanline) > width * 4) + { + printf("freerdp_bitmap_planar_decompress_plane_rle: too many pixels in scanline\n"); + return -1; + } + if (!previousScanline) { /* first scanline, absolute values */ @@ -176,6 +207,10 @@ int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, in if (FormatHeader & PLANAR_FORMAT_HEADER_RLE) { dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 3, size - (srcp - srcData)); + + if (dstSize < 0) + return -1; + srcp += dstSize; } else @@ -188,12 +223,24 @@ int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, in if (FormatHeader & PLANAR_FORMAT_HEADER_RLE) { dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 2, size - (srcp - srcData)); + + if (dstSize < 0) + return -1; + srcp += dstSize; dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 1, size - (srcp - srcData)); + + if (dstSize < 0) + return -1; + srcp += dstSize; dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 0, size - (srcp - srcData)); + + if (dstSize < 0) + return -1; + srcp += dstSize; } else @@ -209,7 +256,7 @@ int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, in srcp++; } - return (size == (srcp - srcData)) ? 1 : 0; + return (size == (srcp - srcData)) ? 0 : -1; } int freerdp_split_color_planes(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* planes[5]) @@ -525,21 +572,23 @@ BYTE* freerdp_bitmap_planar_compress_plane_rle(BYTE* inPlane, int width, int hei continue; } + rle->cRawBytes++; + if (rle->nRunLength < 3) - { - rle->cRawBytes++; continue; - } if (freerdp_bitmap_planar_compress_plane_rle_segment(rle, (j == 1) ? -1 : 0) < 0) return NULL; } - if ((rle->cRawBytes != 0) || (rle->nRunLength != 0)) + if (rle->nRunLength < 3) { - if (freerdp_bitmap_planar_compress_plane_rle_segment(rle, 1) < 0) - return NULL; + rle->cRawBytes += rle->nRunLength; + rle->nRunLength = 0; } + + if (freerdp_bitmap_planar_compress_plane_rle_segment(rle, 1) < 0) + return NULL; } *dstSize = (rle->output - outPlane); diff --git a/libfreerdp/codec/test/TestFreeRDPCodecPlanar.c b/libfreerdp/codec/test/TestFreeRDPCodecPlanar.c index 274a649eb..81276eada 100644 --- a/libfreerdp/codec/test/TestFreeRDPCodecPlanar.c +++ b/libfreerdp/codec/test/TestFreeRDPCodecPlanar.c @@ -1306,6 +1306,7 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[]) freerdp_bitmap_planar_compress_plane_rle((BYTE*) TEST_RDP6_SCANLINES_DELTA_2C_ENCODED_UNSIGNED, 6, 3, NULL, &dstSize); #endif +#if 1 for (i = 4; i < 64; i += 4) { width = i; @@ -1345,6 +1346,7 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[]) free(compressedBitmap); free(decompressedBitmap); } +#endif #if 1 for (i = 4; i < 64; i += 4)