Skip to content

Integer overflow & OutOfBound Write in clear_decompress_residual_data

Moderate
akallabeth published GHSA-q5h8-7j42-j4r9 Apr 22, 2024

Package

FreeRDP (C)

Affected versions

<= 3.4.0, <= 2.11.5

Patched versions

3.5.0, 2.11.6

Description

Impact

  • FreeRDP based clients
static BOOL clear_decompress_residual_data(CLEAR_CONTEXT* clear, wStream* s,
                                           UINT32 residualByteCount, UINT32 nWidth, UINT32 nHeight,
                                           BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep,
                                           UINT32 nXDst, UINT32 nYDst, UINT32 nDstWidth,
                                           UINT32 nDstHeight, const gdiPalette* palette)
{
        UINT32 nSrcStep = 0;
        UINT32 suboffset = 0;
        BYTE* dstBuffer = NULL;
        UINT32 pixelIndex = 0;
        UINT32 pixelCount = 0;

       ...
                Stream_Read_UINT8(s, b);
                Stream_Read_UINT8(s, g);
                Stream_Read_UINT8(s, r);
                Stream_Read_UINT8(s, runLengthFactor);

                suboffset += 4;
                color = FreeRDPGetColor(clear->format, r, g, b, 0xFF);

                if (runLengthFactor >= 0xFF)
                {
                        if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
                                return FALSE;

                        Stream_Read_UINT16(s, runLengthFactor);
                        suboffset += 2;

                        if (runLengthFactor >= 0xFFFF)
                        {
                                if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
                                        return FALSE;

[1]                               Stream_Read_UINT32(s, runLengthFactor);
                                suboffset += 4;
                        }
                }

[2]             if ((pixelIndex + runLengthFactor) > pixelCount)
                {
                        WLog_ERR(TAG,
                                 "pixelIndex %" PRIu32 " + runLengthFactor %" PRIu32 " > pixelCount %" PRIu32
                                 "",
                                 pixelIndex, runLengthFactor, pixelCount);
                        return FALSE;
                }

[3]                for (UINT32 i = 0; i < runLengthFactor; i++)
                {
                        FreeRDPWriteColor(dstBuffer, clear->format, color);
                        dstBuffer += FreeRDPGetBytesPerPixel(clear->format);
                }

                pixelIndex += runLengthFactor;
        }
  1. The variable 'runLengthFactor' is unsigned integer (uint32)
  2. Integer overflow because all variables are of type uint32
  3. This loop writes past the end of 'dstBuffer' buffer

Patches

3.5.0 - 1208f23 (#10077 3a2a241)
2.11.6 - d88ad1a

Workarounds

  • do not use /gfx options (e.g. deactivate with /bpp:32 or /rfx as it is on by default)

References

  • Reported by Evgeny Legerov of Kaspersky Lab.
  • #10077

Severity

Moderate

CVE ID

CVE-2024-32039

Weaknesses

No CWEs