From 6fad8aaa0f98775df944f1119fa2adf8ebdd13ee Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 26 Sep 2009 06:01:27 +0000 Subject: [PATCH] Fixed crash with right side up BMP files --- src/video/SDL_bmp.c | 46 +++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/src/video/SDL_bmp.c b/src/video/SDL_bmp.c index 4b41f4b3b..c517db666 100644 --- a/src/video/SDL_bmp.c +++ b/src/video/SDL_bmp.c @@ -47,7 +47,7 @@ SDL_Surface * SDL_LoadBMP_RW (SDL_RWops *src, int freesrc) { - int was_error; + SDL_bool was_error; long fp_offset; int bmpPitch; int i, pad; @@ -57,6 +57,8 @@ SDL_Surface * SDL_LoadBMP_RW (SDL_RWops *src, int freesrc) Uint32 Bmask; SDL_Palette *palette; Uint8 *bits; + Uint8 *top, *end; + SDL_bool topDown; int ExpandBMP; /* The Win32 BMP file header (14 bytes) */ @@ -81,9 +83,9 @@ SDL_Surface * SDL_LoadBMP_RW (SDL_RWops *src, int freesrc) /* Make sure we are passed a valid data source */ surface = NULL; - was_error = 0; + was_error = SDL_FALSE; if ( src == NULL ) { - was_error = 1; + was_error = SDL_TRUE; goto done; } @@ -92,12 +94,12 @@ SDL_Surface * SDL_LoadBMP_RW (SDL_RWops *src, int freesrc) SDL_ClearError(); if ( SDL_RWread(src, magic, 1, 2) != 2 ) { SDL_Error(SDL_EFREAD); - was_error = 1; + was_error = SDL_TRUE; goto done; } if ( SDL_strncmp(magic, "BM", 2) != 0 ) { SDL_SetError("File is not a Windows BMP file"); - was_error = 1; + was_error = SDL_TRUE; goto done; } bfSize = SDL_ReadLE32(src); @@ -130,10 +132,16 @@ SDL_Surface * SDL_LoadBMP_RW (SDL_RWops *src, int freesrc) biClrUsed = SDL_ReadLE32(src); biClrImportant = SDL_ReadLE32(src); } + if (biHeight < 0) { + topDown = SDL_TRUE; + biHeight = -biHeight; + } else { + topDown = SDL_FALSE; + } /* Check for read error */ if ( SDL_strcmp(SDL_GetError(), "") != 0 ) { - was_error = 1; + was_error = SDL_TRUE; goto done; } @@ -197,7 +205,7 @@ SDL_Surface * SDL_LoadBMP_RW (SDL_RWops *src, int freesrc) break; default: SDL_SetError("Compressed BMP files not supported"); - was_error = 1; + was_error = SDL_TRUE; goto done; } @@ -205,7 +213,7 @@ SDL_Surface * SDL_LoadBMP_RW (SDL_RWops *src, int freesrc) surface = SDL_CreateRGBSurface(SDL_SWSURFACE, biWidth, biHeight, biBitCount, Rmask, Gmask, Bmask, 0); if ( surface == NULL ) { - was_error = 1; + was_error = SDL_TRUE; goto done; } @@ -236,10 +244,11 @@ SDL_Surface * SDL_LoadBMP_RW (SDL_RWops *src, int freesrc) /* Read the surface pixels. Note that the bmp image is upside down */ if ( SDL_RWseek(src, fp_offset+bfOffBits, RW_SEEK_SET) < 0 ) { SDL_Error(SDL_EFSEEK); - was_error = 1; + was_error = SDL_TRUE; goto done; } - bits = (Uint8 *)surface->pixels+(surface->h*surface->pitch); + top = (Uint8 *)surface->pixels; + end = (Uint8 *)surface->pixels+(surface->h*surface->pitch); switch (ExpandBMP) { case 1: bmpPitch = (biWidth + 7) >> 3; @@ -254,8 +263,12 @@ SDL_Surface * SDL_LoadBMP_RW (SDL_RWops *src, int freesrc) (4-(surface->pitch%4)) : 0); break; } - while ( bits > (Uint8 *)surface->pixels ) { - bits -= surface->pitch; + if ( topDown ) { + bits = top; + } else { + bits = end - surface->pitch; + } + while ( bits >= top && bits < end ) { switch (ExpandBMP) { case 1: case 4: { @@ -266,7 +279,7 @@ SDL_Surface * SDL_LoadBMP_RW (SDL_RWops *src, int freesrc) if ( !SDL_RWread(src, &pixel, 1, 1) ) { SDL_SetError( "Error reading from BMP"); - was_error = 1; + was_error = SDL_TRUE; goto done; } } @@ -279,7 +292,7 @@ SDL_Surface * SDL_LoadBMP_RW (SDL_RWops *src, int freesrc) if ( SDL_RWread(src, bits, 1, surface->pitch) != surface->pitch ) { SDL_Error(SDL_EFREAD); - was_error = 1; + was_error = SDL_TRUE; goto done; } #if SDL_BYTEORDER == SDL_BIG_ENDIAN @@ -311,6 +324,11 @@ SDL_Surface * SDL_LoadBMP_RW (SDL_RWops *src, int freesrc) SDL_RWread(src, &padbyte, 1, 1); } } + if ( topDown ) { + bits += surface->pitch; + } else { + bits -= surface->pitch; + } } done: if ( was_error ) {