blob: 97b7f72498b9ef55ae79efb5041e5cc04f3dee20 [file] [log] [blame]
From fb0e0cce0b9f25389ab56604c3547351617e1415 Mon Sep 17 00:00:00 2001
From: "Christoph M. Becker" <cmbecker69@gmx.de>
Date: Tue, 16 Aug 2016 16:26:19 +0200
Subject: [PATCH] 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
Upstream-Status: Backport
CVE: CVE-2016-6906
Signed-off-by: Catalin Enache <catalin.enache@windriver.com>
---
src/gd_tga.c | 6 ++++--
tests/tga/.gitignore | 1 +
tests/tga/CMakeLists.txt | 1 +
tests/tga/Makemodule.am | 2 ++
tests/tga/heap_overflow.c | 51 ++++++++++++++++++++++++++++++++++++++++++++
tests/tga/heap_overflow.tga | Bin 0 -> 605 bytes
6 files changed, 59 insertions(+), 2 deletions(-)
create mode 100644 tests/tga/heap_overflow.c
create mode 100644 tests/tga/heap_overflow.tga
diff --git a/src/gd_tga.c b/src/gd_tga.c
index 8737b04..68e4b17 100644
--- a/src/gd_tga.c
+++ b/src/gd_tga.c
@@ -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;
diff --git a/tests/tga/.gitignore b/tests/tga/.gitignore
index 7a659b1..cf0556b 100644
--- a/tests/tga/.gitignore
+++ b/tests/tga/.gitignore
@@ -3,5 +3,6 @@
/bug00247a
/bug00248
/bug00248a
+/heap_overflow
/tga_null
/tga_read
diff --git a/tests/tga/CMakeLists.txt b/tests/tga/CMakeLists.txt
index 789fb14..11542a0 100644
--- a/tests/tga/CMakeLists.txt
+++ b/tests/tga/CMakeLists.txt
@@ -5,6 +5,7 @@ LIST(APPEND TESTS_FILES
bug00247a
bug00248
bug00248a
+ heap_overflow
tga_read
)
diff --git a/tests/tga/Makemodule.am b/tests/tga/Makemodule.am
index a1e6af6..916d707 100644
--- a/tests/tga/Makemodule.am
+++ b/tests/tga/Makemodule.am
@@ -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
diff --git a/tests/tga/heap_overflow.c b/tests/tga/heap_overflow.c
new file mode 100644
index 0000000..0e9a2d0
--- /dev/null
+++ b/tests/tga/heap_overflow.c
@@ -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;
+}
diff --git a/tests/tga/heap_overflow.tga b/tests/tga/heap_overflow.tga
new file mode 100644
index 0000000000000000000000000000000000000000..e9bc0ecb2a847ac6edba92dd0ff61167b49002cd
GIT binary patch
literal 605
zcmZQz;9`IQ9tIu;g&7<$F3o7Yg1qzyh6tefy9wZAs2d<Uh*yuz=?XwW4Qvuv#g2nS
zp93+mT0rVR>T&8(2TGy=f_l)@gSap~$FayUFu(!|SyJIFga^{8fGj~vwq8kkVgvv>
Cavop+
literal 0
HcmV?d00001
--
2.10.2