Delphi and C++ Builder VCL Library Buffer Overflow

Abstract: Source code fix to address a potential vulnerability in VCL BMP file processing

Potential security vulnerabilities have been identified in the VCL when processing BMP files. These vulnerabilities could allow an attacker to craft a BMP file that produces a buffer overflow and thereby allowing it to execute arbitrary code.

For users of XE7, XE6, and XE5: a hotfix is available.

  1. Obtain and apply the appropriate hotfix
    1. XE7 users: http://cc.embarcadero.com/item/30010
    2. XE6 users: http://cc.embarcadero.com/item/29913
    3. XE5 users: http://cc.embarcadero.com/item/30014
  2. Rebuild your application

For users of XE4 and prior versions of Delphi and C++Builder: these steps should be followed to modify the VCL source code and add it to your application.

  1. Edit Vcl.Graphics.pas (see steps below)
  2. Add the modified Vcl.Graphics.pas to your project
  3. For C++Builder: Under Project | Options | Packages | Runtime Packages, set “Link with runtime packages” to false
  4. Rebuild your application

Changes to Vcl.Graphics.pas:

Code Change 1

  • Variable names and scoping might be slightly different depending on your product version. The syntax and screenshot below are from XE5.
  • Locate the function PaletteFromDIBColorTable.
  • Add the following code just before the line assigning a value to Pal.palNumEntries when the DIBHandle = 0 (see screenshot below).
  if ColorCount > 256 then
      InvalidGraphic({$IFNDEF CLR}@{$ENDIF}SInvalidBitmap);;

Hide image
Click to see full-sized image

Code Change 2

  • Variable names and scoping might be slightly different depending on your product version. The syntax and screenshot below are from XE7.
  • Locate the function TMetafile.ReadEMFStream.
  • Add the following code as shown in the screenshot below.
  if EnhHeader.nBytes < Sizeof(EnhHeader) then
    InvalidMetafile;

Hide image
Click to see full-sized image

Code Change 3

  • Variable names and scoping might be slightly different depending on your product version. The syntax and screenshot below are from XE7.
  • Locate the function TBitmap.ReadDIB.
  • Add the following code as shown in the screenshot below.
  if (biClrUsed * DIBPalSizes[OS2Format]) > (256 * SizeOf(TRGBQuad)) then
     InvalidGraphic({$IFNDEF CLR}@{$ENDIF}SInvalidBitmap);  

Hide image
Click to see full-sized image