Description: fix out of bounds read in TGA file parsing
Origin: backport, https://github.com/libgd/libgd/commit/ead349e99868303b37f5e6e9d9d680c9dc71ff8d
Origin: backport, https://github.com/libgd/libgd/commit/981060efd6415ed9a08a6aa343e6e195bf65fb47
Origin: backport, https://github.com/libgd/libgd/commit/ff0234f4da6d1116c0baa66eebd8497526f7a5d9
Bug: https://github.com/libgd/libgd/issues/247
Bug: https://github.com/libgd/libgd/issues/248
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=829694

Index: libgd2-2.1.1/src/gd_tga.c
===================================================================
--- libgd2-2.1.1.orig/src/gd_tga.c	2016-08-09 09:32:01.411252965 -0400
+++ libgd2-2.1.1/src/gd_tga.c	2016-08-09 09:33:30.128462897 -0400
@@ -200,7 +200,6 @@
 	int buffer_caret = 0;
 	int bitmap_caret = 0;
 	int i = 0;
-	int j = 0;
 	uint8_t encoded_pixels;
 
 	if(overflow2(tga->width, tga->height)) {
@@ -247,7 +246,11 @@
 			return -1;
 		}
 
-		gdGetBuf(conversion_buffer, image_block_size, ctx);
+		if (gdGetBuf(conversion_buffer, image_block_size, ctx) != image_block_size) {
+			gd_error("gd-tga: premature end of image data\n");
+			gdFree(conversion_buffer);
+			return -1;
+		}
 
 		while (buffer_caret < image_block_size) {
 			tga->bitmap[buffer_caret] = (int) conversion_buffer[buffer_caret];
@@ -268,12 +271,17 @@
 		}
 		conversion_buffer = (unsigned char *) gdMalloc(image_block_size * sizeof(unsigned char));
 		if (conversion_buffer == NULL) {
+			gd_error("gd-tga: premature end of image data\n");
 			gdFree( decompression_buffer );
 			gdFree( conversion_buffer );
 			return -1;
 		}
 
-		gdGetBuf( conversion_buffer, image_block_size, ctx );
+		if (gdGetBuf(conversion_buffer, image_block_size, ctx) != image_block_size) {
+			gdFree(conversion_buffer);
+			gdFree(decompression_buffer);
+			return -1;
+		}
 
 		buffer_caret = 0;
 
@@ -285,27 +293,36 @@
 		buffer_caret = 0;
 
 		while( bitmap_caret < image_block_size ) {
-
+			
 			if ((decompression_buffer[buffer_caret] & TGA_RLE_FLAG) == TGA_RLE_FLAG) {
-				encoded_pixels = ( ( decompression_buffer[ buffer_caret ] & 127 ) + 1 );
+				encoded_pixels = ( ( decompression_buffer[ buffer_caret ] & !TGA_RLE_FLAG ) + 1 );
 				buffer_caret++;
 
+				if ((bitmap_caret + (encoded_pixels * pixel_block_size)) >= image_block_size) {
+					gdFree( decompression_buffer );
+					gdFree( conversion_buffer );
+					return -1;
+				}
+
 				for (i = 0; i < encoded_pixels; i++) {
-					for (j = 0; j < pixel_block_size; j++, bitmap_caret++) {
-						tga->bitmap[ bitmap_caret ] = decompression_buffer[ buffer_caret + j ];
-					}
+					memcpy(tga->bitmap + bitmap_caret, decompression_buffer + buffer_caret, pixel_block_size);
+					bitmap_caret += pixel_block_size;
 				}
 				buffer_caret += pixel_block_size;
+
 			} else {
 				encoded_pixels = decompression_buffer[ buffer_caret ] + 1;
 				buffer_caret++;
 
-				for (i = 0; i < encoded_pixels; i++) {
-					for( j = 0; j < pixel_block_size; j++, bitmap_caret++ ) {
-						tga->bitmap[ bitmap_caret ] = decompression_buffer[ buffer_caret + j ];
-					}
-					buffer_caret += pixel_block_size;
+				if ((bitmap_caret + (encoded_pixels * pixel_block_size)) >= image_block_size) {
+					gdFree( decompression_buffer );
+					gdFree( conversion_buffer );
+					return -1;
 				}
+
+				memcpy(tga->bitmap + bitmap_caret, decompression_buffer + buffer_caret, encoded_pixels * pixel_block_size);
+				bitmap_caret += (encoded_pixels * pixel_block_size);
+				buffer_caret += (encoded_pixels * pixel_block_size);
 			}
 		}
 
