Fixed crash with right side up BMP files SDL-1.2
authorSam Lantinga <slouken@libsdl.org>
Sat, 26 Sep 2009 06:01:27 +0000
branchSDL-1.2
changeset 4241 d3a210342761
parent 4240 cb44bf8f8a0f
child 4242 fa62bede8038
Fixed crash with right side up BMP files
src/video/SDL_bmp.c
--- a/src/video/SDL_bmp.c	Wed Sep 23 07:18:02 2009 +0000
+++ b/src/video/SDL_bmp.c	Sat Sep 26 06:01:27 2009 +0000
@@ -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 @@
 	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 @@
 
 	/* 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_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 @@
 		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 @@
 			break;
 		default:
 			SDL_SetError("Compressed BMP files not supported");
-			was_error = 1;
+			was_error = SDL_TRUE;
 			goto done;
 	}
 
@@ -205,7 +213,7 @@
 	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 @@
 	/* 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 @@
 					(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 @@
 					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 @@
 			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_RWread(src, &padbyte, 1, 1);
 			}
 		}
+		if ( topDown ) {
+			bits += surface->pitch;
+		} else {
+			bits -= surface->pitch;
+		}
 	}
 done:
 	if ( was_error ) {