Index: gdk-pixbuf/io-bmp.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk-pixbuf/io-bmp.c,v
retrieving revision 1.29
diff -u -b -B -p -r1.29 io-bmp.c
--- gdk-pixbuf/io-bmp.c	10 Jun 2002 16:50:10 -0000	1.29
+++ gdk-pixbuf/io-bmp.c	22 Jun 2002 14:32:25 -0000
@@ -250,14 +250,9 @@ lsb_16 (guchar *src)
 	return src[0] | (src[1] << 8);
 }
 
-static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH,
-                             struct bmp_progressive_state *State,
+static gboolean grow_buffer (struct bmp_progressive_state *State,
                              GError **error)
 {
-        /* FIXME this is totally unrobust against bogus image data. */
-
-	if (State->BufferSize < lsb_32 (&BIH[0]) + 14) {
-		State->BufferSize = lsb_32 (&BIH[0]) + 14;
 		State->buff = g_try_realloc (State->buff, State->BufferSize);
 		if (State->buff == NULL) {
 			g_set_error (error,
@@ -268,6 +263,19 @@ static gboolean DecodeHeader(unsigned ch
 			return FALSE;
 		}
 		return TRUE;
+}
+
+static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH,
+                             struct bmp_progressive_state *State,
+                             GError **error)
+{
+        /* FIXME this is totally unrobust against bogus image data. */
+
+	if (State->BufferSize < lsb_32 (&BIH[0]) + 14) {
+		State->BufferSize = lsb_32 (&BIH[0]) + 14;
+		if (!grow_buffer (State, error))
+			return FALSE;
+		return TRUE;
 	}
 
 #if DUMPBIH
@@ -384,8 +392,11 @@ static gboolean DecodeHeader(unsigned ch
 
 	State->BufferDone = 0;
 	if (State->Type <= 8) {
+		int biClrUsed = lsb_32 (&BIH[32]);
+		int n_colors = (biClrUsed ? biClrUsed : (1 << State->Header.depth)); 
 		State->read_state = READ_STATE_PALETTE;
-		State->BufferSize = lsb_32 (&BFH[10]) - 14 - State->Header.size;
+		State->BufferSize = (State->Header.size == 12 ? 3 : 4) * n_colors;
+		/* lsb_32 (&BFH[10]) - 14 - State->Header.size */
 	} else if (State->Compressed == BI_RGB) {
 		State->read_state = READ_STATE_DATA;
 		State->BufferSize = State->LineWidth;
@@ -401,12 +412,13 @@ static gboolean DecodeHeader(unsigned ch
 		return FALSE;
 	}
 
-	State->buff = g_realloc (State->buff, State->BufferSize);
+	if (!grow_buffer (State, error)) 
+		return FALSE;
 
         return TRUE;
 }
 
-static void DecodeColormap (guchar *buff,
+static gboolean DecodeColormap (guchar *buff,
 			    struct bmp_progressive_state *State,
 			    GError **error)
 {
@@ -421,6 +433,12 @@ static void DecodeColormap (guchar *buff
 		State->Colormap[i][0] = buff[i * (State->Header.size == 12 ? 3 : 4)];
 		State->Colormap[i][1] = buff[i * (State->Header.size == 12 ? 3 : 4) + 1];
 		State->Colormap[i][2] = buff[i * (State->Header.size == 12 ? 3 : 4) + 2];
+#ifdef DUMPCMAP
+		g_print ("color %d %x %x %x\n", i,
+			 State->Colormap[i][0],
+			 State->Colormap[i][1],
+			 State->Colormap[i][2]);
+#endif
 	}
 
 	State->read_state = READ_STATE_DATA;
@@ -431,7 +449,10 @@ static void DecodeColormap (guchar *buff
 	else
 		State->BufferSize = State->LineWidth;
 
-	State->buff = g_realloc (State->buff, State->BufferSize);
+	if (!grow_buffer (State, error))
+		return FALSE;
+
+	return TRUE;
 }
 
 /* Finds the lowest set bit and the number of set bits */
@@ -450,8 +471,10 @@ find_bits (int n, int *lowest, int *n_se
 }
 
 /* Decodes the 3 shorts that follow for the bitmasks for BI_BITFIELDS coding */
-static void
-decode_bitmasks (struct bmp_progressive_state *State, guchar *buf)
+static gboolean
+decode_bitmasks (guchar *buf,
+		 struct bmp_progressive_state *State, 
+		 GError **error)
 {
 	State->r_mask = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
 	buf += 4;
@@ -479,7 +502,10 @@ decode_bitmasks (struct bmp_progressive_
 	State->read_state = READ_STATE_DATA;
 	State->BufferDone = 0;
 	State->BufferSize = State->LineWidth;
-	State->buff = g_realloc (State->buff, State->BufferSize);
+	if (!grow_buffer (State, error)) 
+		return FALSE;
+
+	return TRUE;
 }
 
 /*
@@ -818,14 +844,14 @@ static void OneLine(struct bmp_progressi
 					  0,
 					  context->Lines,
 					  context->Header.width,
-					  1,
+					  2,
 					  context->user_data);
 
 	}
 }
 
-static void
-DoCompressed(struct bmp_progressive_state *context)
+static gboolean
+DoCompressed(struct bmp_progressive_state *context, GError **error)
 {
 	gint count, pos;
 	switch (context->compr.phase) {
@@ -898,7 +924,8 @@ DoCompressed(struct bmp_progressive_stat
 				if (context->Type == 8)
 					context->compr.RunCount *= 2;
 				context->BufferSize = (context->compr.RunCount + 3) / 4 * 2;
-				context->buff = g_realloc (context->buff, context->BufferSize);
+				if (!grow_buffer (context, error)) 
+					return FALSE;
 			}
 		}
 		context->BufferDone = 0;
@@ -944,13 +971,16 @@ DoCompressed(struct bmp_progressive_stat
 		}
 		context->compr.phase = 0;
 		context->BufferSize = 2;
-		context->buff = g_realloc (context->buff, context->BufferSize);
+		if (!grow_buffer (context, error)) 
+			return FALSE;
 		context->BufferDone = 0;
 		break;
 	case 2:
 		context->BufferDone = 0;
 		break;
 	}
+	
+	return TRUE;
 }
 
 /*
@@ -1005,18 +1035,20 @@ gdk_pixbuf__bmp_image_load_increment(gpo
 			break;
 
 		case READ_STATE_PALETTE:
-			DecodeColormap (context->buff, context, error);
+			if (!DecodeColormap (context->buff, context, error))
+				return FALSE;
 			break;
 
 		case READ_STATE_BITMASKS:
-			decode_bitmasks (context, context->buff);
+			if (!decode_bitmasks (context->buff, context, error))
+				return FALSE;
 			break;
 
 		case READ_STATE_DATA:
 			if (context->Compressed == BI_RGB || context->Compressed == BI_BITFIELDS)
 				OneLine (context);
-			else
-				DoCompressed (context);
+			else if (!DoCompressed (context, error))
+				return FALSE;
 
 			break;
 
