We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 3534 - Blitting to a two-colour packed-format surface (8 pixels per byte) may write in wrong format (1 byte per pixel)
Summary: Blitting to a two-colour packed-format surface (8 pixels per byte) may write ...
Status: RESOLVED FIXED
Alias: None
Product: SDL
Classification: Unclassified
Component: video (show other bugs)
Version: 2.0.5
Hardware: x86 Windows (XP)
: P2 normal
Assignee: Sam Lantinga
QA Contact: Sam Lantinga
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-12-29 21:33 UTC by Geoff Pritchard
Modified: 2017-01-02 02:55 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Geoff Pritchard 2016-12-29 21:33:58 UTC
When SDL_BlitSurface has a target with a two-colour (1-bit depth) packed (8 pixels per byte) format, it will in some situations try to write 1 byte per pixel. Since the target doesn't have enough memory space to accommodate this, pixel data may get written to regions in RAM where it has no business being, potentially causing a crash. 

The following program demonstrates the effect.


// Make test surfaces in two formats, 32-bit ARGB and 1-bit two-colour:
SDL_Surface *s32 = SDL_CreateRGBSurface(0, 30, 10, 32, 0xff0000, 0x00ff00,
                                                         0x0000ff, 0xff000000);
SDL_Surface *s01 = SDL_ConvertSurfaceFormat(s32, SDL_PIXELFORMAT_INDEX1LSB, 0);
 
// Set a palette for the indexed surface.
// (It already has a default palette (white, black), but for some reason this
// bug appears only if the palette is first changed to (black, white).
// I've no idea why.)
SDL_Color c[2] = { {0,0,0,0xff}, {0xff,0xff,0xff,0xff} };
SDL_SetPaletteColors(s01->format->palette, c, 0, 2);

// Confirm that these formats are as expected:
printf("s32 pitch = %d bytes per row\n", s32->pitch);   // 120 (4 bytes/pixel)
printf("s01 pitch = %d bytes per row\n", s01->pitch);   //  4  (8 pixels/byte)

// Place a white rectangle on the (default-initialized) transparent background
// of s32:
SDL_Rect rect = { 1, 1, 5, 3 };
SDL_FillRect(s32, &rect, 0xffffffff);
 
// Blit the s32 image to s01:
int result = SDL_BlitSurface(s32, NULL, s01, NULL);
printf("SDL_BlitSurface result = %d\n", result);

// Show the s01 pixel data:
printf("s01: %d x %d surface:\n", s01->w, s01->h);
for(int r = 0; r != s01->h; r++)
{
  for(int b = 0; b != s01->pitch; b++)
    printf("%x ", *((Uint8*)(s01->pixels) + r * s01->pitch + b) );
  printf("\n");
}


The output I get from this is:

s32 pitch = 120 bytes per row
s01 pitch = 4 bytes per row
SDL_BlitSurface result = 0
s01: 30 x 10 surface:
0 0 0 0
0 1 1 1
1 1 1 1
1 1 1 1
1 1 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
Comment 1 Sam Lantinga 2017-01-02 02:55:18 UTC
SDL doesn't currently support blitting to bitmap (< 8 bpp) pixel formats. This is reported as an error instead of corrupting memory in this changeset:
https://hg.libsdl.org/SDL/rev/754cac536474

Thanks!