diff --git a/include/freerdp/codec/color.h b/include/freerdp/codec/color.h index 79200bee1..c7e6cca3f 100644 --- a/include/freerdp/codec/color.h +++ b/include/freerdp/codec/color.h @@ -288,6 +288,7 @@ typedef struct gdi_palette gdiPalette; return (FreeRDPGetBitsPerPixel(format) + 7) / 8; } +#if !defined(WITHOUT_FREERDP_3x_DEPRECATED) /*** * * @param width width to copy in pixels @@ -297,9 +298,27 @@ typedef struct gdi_palette gdiPalette; * @return A buffer allocated with winpr_aligned_malloc(width * height, 16) * if successful, NULL otherwise. */ + + WINPR_DEPRECATED_VAR("[since 3.21.0] use freerdp_glyph_convert_ex instead", + WINPR_ATTR_MALLOC(winpr_aligned_free, 1) + FREERDP_API BYTE* freerdp_glyph_convert( + UINT32 width, UINT32 height, const BYTE* WINPR_RESTRICT data)); +#endif + + /*** + * + * @param width width to copy in pixels + * @param height height to copy in pixels + * @param data source buffer, must be (nWidth + 7) / 8 bytes long + * @param len the length of \ref data in bytes + * + * @return A buffer allocated with winpr_aligned_malloc(width * height, 16) + * if successful, NULL otherwise. + * @since version 3.21.0 + */ WINPR_ATTR_MALLOC(winpr_aligned_free, 1) - FREERDP_API BYTE* freerdp_glyph_convert(UINT32 width, UINT32 height, - const BYTE* WINPR_RESTRICT data); + FREERDP_API BYTE* freerdp_glyph_convert_ex(UINT32 width, UINT32 height, + const BYTE* WINPR_RESTRICT data, size_t len); /*** * diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c index 0efa89f8d..f9aa4f000 100644 --- a/libfreerdp/codec/clear.c +++ b/libfreerdp/codec/clear.c @@ -1139,8 +1139,54 @@ INT32 clear_decompress(CLEAR_CONTEXT* WINPR_RESTRICT clear, const BYTE* WINPR_RE if (glyphData) { - const uint32_t w = MIN(nWidth, nDstWidth); - const uint32_t h = MIN(nHeight, nDstHeight); + uint32_t w = MIN(nWidth, nDstWidth); + if (nXDst > nDstWidth) + { + WLog_WARN(TAG, "glyphData copy area x exceeds destination: x=%" PRIu32 " > %" PRIu32, + nXDst, nDstWidth); + w = 0; + } + else if (nXDst + w > nDstWidth) + { + WLog_WARN(TAG, + "glyphData copy area x + width exceeds destination: x=%" PRIu32 " + %" PRIu32 + " > %" PRIu32, + nXDst, w, nDstWidth); + w = nDstWidth - nXDst; + } + + if (w != nWidth) + { + WLog_WARN(TAG, + "glyphData copy area width truncated: requested=%" PRIu32 + ", truncated to %" PRIu32, + nWidth, w); + } + + uint32_t h = MIN(nHeight, nDstHeight); + if (nYDst > nDstHeight) + { + WLog_WARN(TAG, "glyphData copy area y exceeds destination: y=%" PRIu32 " > %" PRIu32, + nYDst, nDstHeight); + h = 0; + } + else if (nYDst + h > nDstHeight) + { + WLog_WARN(TAG, + "glyphData copy area y + height exceeds destination: x=%" PRIu32 " + %" PRIu32 + " > %" PRIu32, + nYDst, h, nDstHeight); + h = nDstHeight - nYDst; + } + + if (h != nHeight) + { + WLog_WARN(TAG, + "glyphData copy area height truncated: requested=%" PRIu32 + ", truncated to %" PRIu32, + nHeight, h); + } + if (!freerdp_image_copy_no_overlap(glyphData, clear->format, 0, 0, 0, w, h, pDstData, DstFormat, nDstStep, nXDst, nYDst, palette, FREERDP_KEEP_DST_ALPHA)) diff --git a/libfreerdp/codec/color.c b/libfreerdp/codec/color.c index 2dd33ebc0..2659c92e6 100644 --- a/libfreerdp/codec/color.c +++ b/libfreerdp/codec/color.c @@ -242,14 +242,33 @@ fail: } #endif +#if !defined(WITHOUT_FREERDP_3x_DEPRECATED) BYTE* freerdp_glyph_convert(UINT32 width, UINT32 height, const BYTE* WINPR_RESTRICT data) +{ + const size_t scanline = (width + 7ull) / 8ull; + const size_t required = scanline * height; + return freerdp_glyph_convert_ex(width, height, data, required); +} +#endif + +BYTE* freerdp_glyph_convert_ex(UINT32 width, UINT32 height, const BYTE* WINPR_RESTRICT data, + size_t len) { /* * converts a 1-bit-per-pixel glyph to a one-byte-per-pixel glyph: * this approach uses a little more memory, but provides faster * means of accessing individual pixels in blitting operations */ - const UINT32 scanline = (width + 7) / 8; + const size_t scanline = (width + 7ull) / 8ull; + const size_t required = scanline * height; + if (len < required) + return NULL; + + if ((len == 0) || (width == 0) || (height == 0)) + return NULL; + + WINPR_ASSERT(data); + BYTE* dstData = (BYTE*)winpr_aligned_malloc(1ull * width * height, 16); if (!dstData) diff --git a/libfreerdp/gdi/graphics.c b/libfreerdp/gdi/graphics.c index 2f616148c..1521dbbaf 100644 --- a/libfreerdp/gdi/graphics.c +++ b/libfreerdp/gdi/graphics.c @@ -270,20 +270,17 @@ static BOOL gdi_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, BOOL p /* Glyph Class */ static BOOL gdi_Glyph_New(rdpContext* context, rdpGlyph* glyph) { - BYTE* data = NULL; - gdiGlyph* gdi_glyph = NULL; - if (!context || !glyph) return FALSE; - gdi_glyph = (gdiGlyph*)glyph; + gdiGlyph* gdi_glyph = (gdiGlyph*)glyph; gdi_glyph->hdc = gdi_GetDC(); if (!gdi_glyph->hdc) return FALSE; gdi_glyph->hdc->format = PIXEL_FORMAT_MONO; - data = freerdp_glyph_convert(glyph->cx, glyph->cy, glyph->aj); + BYTE* data = freerdp_glyph_convert_ex(glyph->cx, glyph->cy, glyph->aj, glyph->cb); if (!data) {