Ozkan Sezer
As for the issue: This bmp reports bpp=0, therefore SDL_CalculatePitch()
returns pitch==0, which is then fed to SDL_malloc() (which is malloc())
and malloc(0) returns _something_ which is not NULL but not someting
that we expect.. Then testsprite.c:LoadSprite() accesses the pixels
as *(Uint8*)pixels which valrind reports as:
==15533== Invalid read of size 1
==15533== at 0x8048C08: LoadSprite (testsprite.c:45)
==15533== by 0x80492FC: main (testsprite.c:224)
==15533== Address 0x449e588 is 0 bytes after a block of size 0 alloc'd
==15533== at 0x40072B2: malloc (vg_replace_malloc.c:270)
==15533== by 0x4045719: SDL_CreateRGBSurface (SDL_surface.c:126)
==15533== by 0x40403C1: SDL_LoadBMP_RW (SDL_bmp.c:237)
==15533== by 0x8048BB2: LoadSprite (testsprite.c:36)
==15533== by 0x80492FC: main (testsprite.c:224)
Besides, valrind also reports this:
==15533== Conditional jump or move depends on uninitialised value(s)
==15533== at 0x40403F3: SDL_LoadBMP_RW (SDL_bmp.c:247)
==15533== by 0x8048BB2: LoadSprite (testsprite.c:36)
==15533== by 0x80492FC: main (testsprite.c:224)
Easy/quick solution would be early-rejecting a bmp with 0 bpp from SDL_bmp.c:SDL_LoadBMP_RW()
Petr Pisar
The root cause is that the POC BMP file declares 3 colors used and 4 bpp palette, but pixel at line 28 and column 1 (counted from 0) has color number 3. Then when the image loaded into a surface is passed to SDL_DisplayFormat(), in order to convert it to a video format, a used bliting function looks up a color number 3 in a 3-element long color bliting map. (The map obviously has the same number entries as the surface format has colors.)
Proper fix should refuse broken BMP images that have a pixel with a color index higher than declared number of "used" colors. Possibly more advanced fix could try to relocate the out-of-range color index into a vacant index (if such exists).
Petr Pisar
The reproducer has these data in BITMAPINFOHEADER:
biSize = 40
biBitCount = 8
biClrUsed = 131075
SDL_LoadBMP_RW() function passes biBitCount as a color depth to SDL_CreateRGBSurface(), thus 256-color pallete is allocated. But then biClrUsed colors are read from a file and stored into the palette. SDL_LoadBMP_RW should report an error if biClrUsed is greater than 2^biBitCount.
Daniel Gibson
Ok, I followed the simple approach of just making SDL_PIXELFORMAT_RGBA32 an alias of SDL_PIXELFORMAT_RGBA8888/SDL_PIXELFORMAT_ABGR8888, depending on endianess. And I did the same for SDL_PIXELFORMAT_ARGB32, .._BGRA, .._ABGR.
SDL_GetPixelFormatName() will of course return SDL_PIXELFORMAT_RGBA8888 (or SDL_PIXELFORMAT_ABGR8888) instead of SDL_PIXELFORMAT_RGBA32, but as long as that's mentioned in the docs it shouldn't be a problem.
Simon Hug
The current SDL_SaveBMP_RW function that saves surfaces to a BMP uses an old bitmap header which doesn't officially support alpha channels. Applications just ignore the byte where the alpha is stored. This can easily be extended by using a newer header version and setting the alpha mask.
The attached patch has these changes:
- Extending the description of the function in the SDL_surface.h header with the supported formats.
- Refining when surfaces get stored to a 32-bit BMP. (Must have bit depth of 8 or higher and must have an alpha mask or colorkey.)
- Fixing a small bug that saves 24-bit BGR surfaces with a colorkey in a 24-bit BMP.
- Adding code that switches to the bitmap header version 4 if the surface has an alpha mask or colorkey. (I chose version 4 because Microsoft didn't lose its documentation behind a file cabinet like they did with version 3.)
- Adding a hint that can disable the use of the version 4 header. This is for people that need the legacy header or like the old behavior better. (I'm not sure about the hint name, though. May need changing if there are any rules to that.)
The internal function SDL_EGL_LoadLibrary() did not delete and remove a mostly
uninitialized data structure if loading the library first failed. A later try to
use EGL then skipped initialization and assumed it was previously successful
because the data structure now already existed. This led to at least one crash
in the internal function SDL_EGL_ChooseConfig() because a NULL pointer was
dereferenced to make a call to eglBindAPI().