Skip to content

integer underflow in nsc_rle_decode

Low
akallabeth published GHSA-23c5-cp23-h2h5 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 are affected
  • Only connections to servers using the NSC codec are affected
static BOOL nsc_rle_decode(const BYTE* in, size_t inSize, BYTE* out, UINT32 outSize,
                           UINT32 originalSize)
{
        UINT32 left = originalSize;
 
        while (left > 4)
        {
                if (inSize < 1)
                        return FALSE;
                inSize--;
 
                const BYTE value = *in++;
                UINT32 len = 0;
 
                if (left == 5)
                {
                        if (outSize < 1)
                                return FALSE;
 
                        outSize--;
                        *out++ = value;
                        left--;
                }
              else if (inSize < 1)
                        return FALSE;
                else if (value == *in)
                {
                        inSize--;
                        in++;
 
                        if (inSize < 1)
                                return FALSE;
                        else if (*in < 0xFF)
                        {
                                inSize--;
                                len = (UINT32)*in++;
                                len += 2;
                        }
                        else
                        {
                                if (inSize < 5)
                                        return FALSE;
                                inSize -= 5;
                                in++;
                                len = ((UINT32)(*in++));
                                len |= ((UINT32)(*in++)) << 8U;
                                len |= ((UINT32)(*in++)) << 16U;
                                len |= ((UINT32)(*in++)) << 24U;
                        }
[1]                        if (outSize < len)
                                return FALSE;
 
                        outSize -= len;
                        FillMemory(out, len, value);
                        out += len;
[2]                        left -= len;
                }
                else
                {
                        if (outSize < 1)
                                return FALSE;

                        outSize--;
                        *out++ = value;
                        left--;
                }
        }
       ...
}
  1. Suppose that 'len' is large integer and it is less than 'outSize', thus we can pass this check
  2. There is not check to ensure that 'left' is be greater than 'len'.
    As a result 'left' will be a large positive value.

Patches

Workarounds

  • do not use NSC codec (e.g. use -nsc)

References

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

Severity

Low

CVE ID

CVE-2024-32040

Weaknesses

No CWEs