blob: 97b7f72498b9ef55ae79efb5041e5cc04f3dee20 [file] [log] [blame]
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001From fb0e0cce0b9f25389ab56604c3547351617e1415 Mon Sep 17 00:00:00 2001
2From: "Christoph M. Becker" <cmbecker69@gmx.de>
3Date: Tue, 16 Aug 2016 16:26:19 +0200
4Subject: [PATCH] Fix OOB reads of the TGA decompression buffer
5
6It is possible to craft TGA files which will overflow the decompression
7buffer, but not the image's bitmap. Therefore we augment the check for the
8bitmap's overflow with a check for the buffer's overflow.
9
10This issue had been reported by Ibrahim El-Sayed to security@libgd.org.
11
12CVE-2016-6906
13
14Upstream-Status: Backport
15CVE: CVE-2016-6906
16
17Signed-off-by: Catalin Enache <catalin.enache@windriver.com>
18---
19 src/gd_tga.c | 6 ++++--
20 tests/tga/.gitignore | 1 +
21 tests/tga/CMakeLists.txt | 1 +
22 tests/tga/Makemodule.am | 2 ++
23 tests/tga/heap_overflow.c | 51 ++++++++++++++++++++++++++++++++++++++++++++
24 tests/tga/heap_overflow.tga | Bin 0 -> 605 bytes
25 6 files changed, 59 insertions(+), 2 deletions(-)
26 create mode 100644 tests/tga/heap_overflow.c
27 create mode 100644 tests/tga/heap_overflow.tga
28
29diff --git a/src/gd_tga.c b/src/gd_tga.c
30index 8737b04..68e4b17 100644
31--- a/src/gd_tga.c
32+++ b/src/gd_tga.c
33@@ -300,7 +300,8 @@ int read_image_tga( gdIOCtx *ctx, oTga *tga )
34 encoded_pixels = ( ( decompression_buffer[ buffer_caret ] & ~TGA_RLE_FLAG ) + 1 );
35 buffer_caret++;
36
37- if ((bitmap_caret + (encoded_pixels * pixel_block_size)) > image_block_size) {
38+ if ((bitmap_caret + (encoded_pixels * pixel_block_size)) > image_block_size
39+ || buffer_caret + pixel_block_size > rle_size) {
40 gdFree( decompression_buffer );
41 gdFree( conversion_buffer );
42 return -1;
43@@ -316,7 +317,8 @@ int read_image_tga( gdIOCtx *ctx, oTga *tga )
44 encoded_pixels = decompression_buffer[ buffer_caret ] + 1;
45 buffer_caret++;
46
47- if ((bitmap_caret + (encoded_pixels * pixel_block_size)) > image_block_size) {
48+ if ((bitmap_caret + (encoded_pixels * pixel_block_size)) > image_block_size
49+ || buffer_caret + (encoded_pixels * pixel_block_size) > rle_size) {
50 gdFree( decompression_buffer );
51 gdFree( conversion_buffer );
52 return -1;
53diff --git a/tests/tga/.gitignore b/tests/tga/.gitignore
54index 7a659b1..cf0556b 100644
55--- a/tests/tga/.gitignore
56+++ b/tests/tga/.gitignore
57@@ -3,5 +3,6 @@
58 /bug00247a
59 /bug00248
60 /bug00248a
61+/heap_overflow
62 /tga_null
63 /tga_read
64diff --git a/tests/tga/CMakeLists.txt b/tests/tga/CMakeLists.txt
65index 789fb14..11542a0 100644
66--- a/tests/tga/CMakeLists.txt
67+++ b/tests/tga/CMakeLists.txt
68@@ -5,6 +5,7 @@ LIST(APPEND TESTS_FILES
69 bug00247a
70 bug00248
71 bug00248a
72+ heap_overflow
73 tga_read
74 )
75
76diff --git a/tests/tga/Makemodule.am b/tests/tga/Makemodule.am
77index a1e6af6..916d707 100644
78--- a/tests/tga/Makemodule.am
79+++ b/tests/tga/Makemodule.am
80@@ -4,6 +4,7 @@ libgd_test_programs += \
81 tga/bug00247a \
82 tga/bug00248 \
83 tga/bug00248a \
84+ tga/heap_overflow \
85 tga/tga_null \
86 tga/tga_read
87
88@@ -14,6 +15,7 @@ EXTRA_DIST += \
89 tga/bug00247a.tga \
90 tga/bug00248.tga \
91 tga/bug00248a.tga \
92+ tga/heap_overflow.tga \
93 tga/tga_read_rgb.png \
94 tga/tga_read_rgb.tga \
95 tga/tga_read_rgb_rle.tga
96diff --git a/tests/tga/heap_overflow.c b/tests/tga/heap_overflow.c
97new file mode 100644
98index 0000000..0e9a2d0
99--- /dev/null
100+++ b/tests/tga/heap_overflow.c
101@@ -0,0 +1,51 @@
102+/**
103+ * Test that the crafted TGA file doesn't trigger OOB reads.
104+ */
105+
106+
107+#include "gd.h"
108+#include "gdtest.h"
109+
110+
111+static size_t read_test_file(char **buffer, char *basename);
112+
113+
114+int main()
115+{
116+ gdImagePtr im;
117+ char *buffer;
118+ size_t size;
119+
120+ size = read_test_file(&buffer, "heap_overflow.tga");
121+ im = gdImageCreateFromTgaPtr(size, (void *) buffer);
122+ gdTestAssert(im == NULL);
123+ free(buffer);
124+
125+ return gdNumFailures();
126+}
127+
128+
129+static size_t read_test_file(char **buffer, char *basename)
130+{
131+ char *filename;
132+ FILE *fp;
133+ size_t exp_size, act_size;
134+
135+ filename = gdTestFilePath2("tga", basename);
136+ fp = fopen(filename, "rb");
137+ gdTestAssert(fp != NULL);
138+
139+ fseek(fp, 0, SEEK_END);
140+ exp_size = ftell(fp);
141+ fseek(fp, 0, SEEK_SET);
142+
143+ *buffer = malloc(exp_size);
144+ gdTestAssert(*buffer != NULL);
145+ act_size = fread(*buffer, sizeof(**buffer), exp_size, fp);
146+ gdTestAssert(act_size == exp_size);
147+
148+ fclose(fp);
149+ free(filename);
150+
151+ return act_size;
152+}
153diff --git a/tests/tga/heap_overflow.tga b/tests/tga/heap_overflow.tga
154new file mode 100644
155index 0000000000000000000000000000000000000000..e9bc0ecb2a847ac6edba92dd0ff61167b49002cd
156GIT binary patch
157literal 605
158zcmZQz;9`IQ9tIu;g&7<$F3o7Yg1qzyh6tefy9wZAs2d<Uh*yuz=?XwW4Qvuv#g2nS
159zp93+mT0rVR>T&8(2TGy=f_l)@gSap~$FayUFu(!|SyJIFga^{8fGj~vwq8kkVgvv>
160Cavop+
161
162literal 0
163HcmV?d00001
164
165--
1662.10.2
167