#790914 libgdiplus: crashes randomly when loading a transparent-only PNG

Package:
libgdiplus
Source:
libgdiplus
Description:
interface library for System.Drawing of Mono
Submitter:
Fabian Pietsch
Date:
2015-07-02 22:33:06 UTC
Severity:
normal
#790914#5
Date:
2015-07-02 22:21:01 UTC
From:
To:
Hi,

there is gdip_load_png_image_from_file_or_stream() in src/pngcodec.c
which calls png_get_PLTE() without initializing the result parameters
before or checking for the 0 (error) return code after. This leads to
png_palette and num_palette being uninitialized when loading certain
images. png_palette is dereferenced, then, in line 378 and following:

                                          set_pixel_bgra(&palette->Entries[i], 0,
                                                          png_palette[i].blue,
                                                          png_palette[i].green,
                                                          png_palette[i].red,
  #if PNG_LIBPNG_VER > 10399
                                                          trans_alpha [i]); /* alpha */
  #else
                                                          info_ptr->trans[i]); /* alpha */
  #endif

Depending on unknown factors, png_palette is sometimes some valid
pointer then, and png_palette[i].blue, .green, .red read from a random
memory location; or in other cases png_palette is 0, 0x2, 0x2c or other
values that are not accessible when interpreted as an address. This
then leads to the Mono application crashing in native code.

I've included a patch that initializes png_palette and num_palette to
zero. If png_get_PLTE() failed, and therefore those variables stay zero,
this should trigger a check in line 337/338 that sets palette_entries to
zero, which will cause the for loop that contains the set_pixel_bgra()
call to be skipped completely.

Note that this only fixes the crashes. It could be the case that a fully
transparent image (consisting of fully transparent pixels only) would be
loaded as, e.g., a completely black image, with this code change. Other
places where libgdiplus crashes on this type of image might exist, too.


To test the crash - although this might not crash even if it is still
buggy - run this:

  $ csharp /r:System.Drawing
  Mono C# Shell, type "help;" for help

  Enter statements below.
  csharp> using System.Drawing;
  csharp> Bitmap bmpTest = new Bitmap("explosion00.png");

After this it might crash if you're (un)lucky.

Regards, Fabian Pietsch