CVE-2016-6906 (published 2017-03-15T14:59Z)

The read_image_tga function in gd_tga.c in the GD Graphics Library (aka libgd) before 2.2.4 allows remote attackers to cause a denial of service (out-of-bounds read) via a crafted TGA file, related to the decompression buffer.

Severity: MEDIUM
CVSS v2 base score: 4.3 (AV:N/AC:M/Au:N/C:N/I:N/A:P)
CVSS v3 base score: 5.5, MEDIUM (CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-125
cwe_name: Out-of-bounds Read
description: The product reads data past the end, or before the beginning, of the intended buffer.
extended_description: 
            
            
             
			 
         
         

Fix information:
repo_url: https://github.com/libgd/libgd
commit_details: repo_url: https://github.com/libgd/libgd
author: Christoph M. Becker
author_date: 2016-08-16 16:26:19+02:00
msg: Fix OOB reads of the TGA decompression buffer

It is possible to craft TGA files which will overflow the decompression
buffer, but not the image's bitmap. Therefore we augment the check for the
bitmap's overflow with a check for the buffer's overflow.

This issue had been reported by Ibrahim El-Sayed to security@libgd.org.

CVE-2016-6906
repository: repo_url: https://github.com/libgd/libgd
repo_name: libgd/libgd
description: GD Graphics Library
repo_language: C
owner: libgd
file_changes: filename: gd_tga.c
change_type: ModificationType.MODIFY
diff: @@ -300,7 +300,8 @@ int read_image_tga( gdIOCtx *ctx, oTga *tga )
 				encoded_pixels = ( ( decompression_buffer[ buffer_caret ] & ~TGA_RLE_FLAG ) + 1 );
 				buffer_caret++;
 
-				if ((bitmap_caret + (encoded_pixels * pixel_block_size)) > image_block_size) {
+				if ((bitmap_caret + (encoded_pixels * pixel_block_size)) > image_block_size
+						|| buffer_caret + pixel_block_size > rle_size) {
 					gdFree( decompression_buffer );
 					gdFree( conversion_buffer );
 					return -1;
@@ -316,7 +317,8 @@ int read_image_tga( gdIOCtx *ctx, oTga *tga )
 				encoded_pixels = decompression_buffer[ buffer_caret ] + 1;
 				buffer_caret++;
 
-				if ((bitmap_caret + (encoded_pixels * pixel_block_size)) > image_block_size) {
+				if ((bitmap_caret + (encoded_pixels * pixel_block_size)) > image_block_size
+						|| buffer_caret + (encoded_pixels * pixel_block_size) > rle_size) {
 					gdFree( decompression_buffer );
 					gdFree( conversion_buffer );
 					return -1;

programming_language: C
filename: .gitignore
change_type: ModificationType.MODIFY
diff: @@ -3,5 +3,6 @@
 /bug00247a
 /bug00248
 /bug00248a
+/heap_overflow
 /tga_null
 /tga_read

programming_language: Shell
filename: CMakeLists.txt
change_type: ModificationType.MODIFY
diff: @@ -5,6 +5,7 @@ LIST(APPEND TESTS_FILES
 	bug00247a
 	bug00248
 	bug00248a
+	heap_overflow
 	tga_read
 )
 

programming_language: Batchfile
filename: Makemodule.am
change_type: ModificationType.MODIFY
diff: @@ -4,6 +4,7 @@ libgd_test_programs += \
 	tga/bug00247a \
 	tga/bug00248 \
 	tga/bug00248a \
+	tga/heap_overflow \
 	tga/tga_null \
 	tga/tga_read
 
@@ -14,6 +15,7 @@ EXTRA_DIST += \
 	tga/bug00247a.tga \
 	tga/bug00248.tga \
 	tga/bug00248a.tga \
+	tga/heap_overflow.tga \
 	tga/tga_read_rgb.png \
 	tga/tga_read_rgb.tga \
 	tga/tga_read_rgb_rle.tga

programming_language: Shell
filename: heap_overflow.c
change_type: ModificationType.ADD
diff: @@ -0,0 +1,51 @@
+/**
+ * Test that the crafted TGA file doesn't trigger OOB reads.
+ */
+
+
+#include "gd.h"
+#include "gdtest.h"
+
+
+static size_t read_test_file(char **buffer, char *basename);
+
+
+int main()
+{
+    gdImagePtr im;
+    char *buffer;
+    size_t size;
+
+    size = read_test_file(&buffer, "heap_overflow.tga");
+    im = gdImageCreateFromTgaPtr(size, (void *) buffer);
+    gdTestAssert(im == NULL);
+    free(buffer);
+
+    return gdNumFailures();
+}
+
+
+static size_t read_test_file(char **buffer, char *basename)
+{
+    char *filename;
+    FILE *fp;
+    size_t exp_size, act_size;
+
+    filename = gdTestFilePath2("tga", basename);
+    fp = fopen(filename, "rb");
+    gdTestAssert(fp != NULL);
+
+	fseek(fp, 0, SEEK_END);
+	exp_size = ftell(fp);
+	fseek(fp, 0, SEEK_SET);
+
+    *buffer = malloc(exp_size);
+    gdTestAssert(*buffer != NULL);
+    act_size = fread(*buffer, sizeof(**buffer), exp_size, fp);
+    gdTestAssert(act_size == exp_size);
+
+    fclose(fp);
+    free(filename);
+
+    return act_size;
+}

programming_language: C
repo_url: https://github.com/libgd/libgd
commit_details: repo_url: https://github.com/libgd/libgd
author: Christoph M. Becker
author_date: 2016-08-16 16:26:19+02:00
msg: Fix OOB reads of the TGA decompression buffer

It is possible to craft TGA files which will overflow the decompression
buffer, but not the image's bitmap. Therefore we also have to check for
potential decompression buffer overflows.

This issue had been reported by Ibrahim El-Sayed to security@libgd.org;
a modified case exposing an off-by-one error of the first patch had been
provided by Konrad Beckmann.

This commit is an amendment to commit fb0e0cce, so we use CVE-2016-6906
as well.
repository: repo_url: https://github.com/libgd/libgd
repo_name: libgd/libgd
description: GD Graphics Library
repo_language: C
owner: libgd
file_changes: filename: gd_tga.c
change_type: ModificationType.MODIFY
diff: @@ -295,7 +295,13 @@ int read_image_tga( gdIOCtx *ctx, oTga *tga )
 		buffer_caret = 0;
 
 		while( bitmap_caret < image_block_size ) {
-			
+
+			if (buffer_caret + pixel_block_size > rle_size) {
+				gdFree( decompression_buffer );
+				gdFree( conversion_buffer );
+				return -1;
+			}
+
 			if ((decompression_buffer[buffer_caret] & TGA_RLE_FLAG) == TGA_RLE_FLAG) {
 				encoded_pixels = ( ( decompression_buffer[ buffer_caret ] & ~TGA_RLE_FLAG ) + 1 );
 				buffer_caret++;

programming_language: C
filename: Makemodule.am
change_type: ModificationType.MODIFY
diff: @@ -15,7 +15,8 @@ EXTRA_DIST += \
 	tga/bug00247a.tga \
 	tga/bug00248.tga \
 	tga/bug00248a.tga \
-	tga/heap_overflow.tga \
+	tga/heap_overflow_1.tga \
+	tga/heap_overflow_2.tga \
 	tga/tga_read_rgb.png \
 	tga/tga_read_rgb.tga \
 	tga/tga_read_rgb_rle.tga

programming_language: Shell
filename: heap_overflow.c
change_type: ModificationType.MODIFY
diff: @@ -1,5 +1,5 @@
 /**
- * Test that the crafted TGA file doesn't trigger OOB reads.
+ * Test that crafted TGA files don't trigger OOB reads.
  */
 
 
@@ -7,21 +7,29 @@
 #include "gdtest.h"
 
 
+static void check_file(char *basename);
 static size_t read_test_file(char **buffer, char *basename);
 
 
 int main()
+{
+    check_file("heap_overflow_1.tga");
+    check_file("heap_overflow_2.tga");
+
+    return gdNumFailures();
+}
+
+
+static void check_file(char *basename)
 {
     gdImagePtr im;
     char *buffer;
     size_t size;
 
-    size = read_test_file(&buffer, "heap_overflow.tga");
+    size = read_test_file(&buffer, basename);
     im = gdImageCreateFromTgaPtr(size, (void *) buffer);
     gdTestAssert(im == NULL);
     free(buffer);
-
-    return gdNumFailures();
 }
 
 

programming_language: C