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