Skip to content

Commit fb0e0cc

Browse files
committed
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
1 parent 5ebbd50 commit fb0e0cc

File tree

6 files changed

+59
-2
lines changed

6 files changed

+59
-2
lines changed

Diff for: src/gd_tga.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,8 @@ int read_image_tga( gdIOCtx *ctx, oTga *tga )
300300
encoded_pixels = ( ( decompression_buffer[ buffer_caret ] & ~TGA_RLE_FLAG ) + 1 );
301301
buffer_caret++;
302302

303-
if ((bitmap_caret + (encoded_pixels * pixel_block_size)) > image_block_size) {
303+
if ((bitmap_caret + (encoded_pixels * pixel_block_size)) > image_block_size
304+
|| buffer_caret + pixel_block_size > rle_size) {
304305
gdFree( decompression_buffer );
305306
gdFree( conversion_buffer );
306307
return -1;
@@ -316,7 +317,8 @@ int read_image_tga( gdIOCtx *ctx, oTga *tga )
316317
encoded_pixels = decompression_buffer[ buffer_caret ] + 1;
317318
buffer_caret++;
318319

319-
if ((bitmap_caret + (encoded_pixels * pixel_block_size)) > image_block_size) {
320+
if ((bitmap_caret + (encoded_pixels * pixel_block_size)) > image_block_size
321+
|| buffer_caret + (encoded_pixels * pixel_block_size) > rle_size) {
320322
gdFree( decompression_buffer );
321323
gdFree( conversion_buffer );
322324
return -1;

Diff for: tests/tga/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
/bug00247a
44
/bug00248
55
/bug00248a
6+
/heap_overflow
67
/tga_null
78
/tga_read

Diff for: tests/tga/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ LIST(APPEND TESTS_FILES
55
bug00247a
66
bug00248
77
bug00248a
8+
heap_overflow
89
tga_read
910
)
1011

Diff for: tests/tga/Makemodule.am

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ libgd_test_programs += \
44
tga/bug00247a \
55
tga/bug00248 \
66
tga/bug00248a \
7+
tga/heap_overflow \
78
tga/tga_null \
89
tga/tga_read
910

@@ -14,6 +15,7 @@ EXTRA_DIST += \
1415
tga/bug00247a.tga \
1516
tga/bug00248.tga \
1617
tga/bug00248a.tga \
18+
tga/heap_overflow.tga \
1719
tga/tga_read_rgb.png \
1820
tga/tga_read_rgb.tga \
1921
tga/tga_read_rgb_rle.tga

Diff for: tests/tga/heap_overflow.c

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* Test that the crafted TGA file doesn't trigger OOB reads.
3+
*/
4+
5+
6+
#include "gd.h"
7+
#include "gdtest.h"
8+
9+
10+
static size_t read_test_file(char **buffer, char *basename);
11+
12+
13+
int main()
14+
{
15+
gdImagePtr im;
16+
char *buffer;
17+
size_t size;
18+
19+
size = read_test_file(&buffer, "heap_overflow.tga");
20+
im = gdImageCreateFromTgaPtr(size, (void *) buffer);
21+
gdTestAssert(im == NULL);
22+
free(buffer);
23+
24+
return gdNumFailures();
25+
}
26+
27+
28+
static size_t read_test_file(char **buffer, char *basename)
29+
{
30+
char *filename;
31+
FILE *fp;
32+
size_t exp_size, act_size;
33+
34+
filename = gdTestFilePath2("tga", basename);
35+
fp = fopen(filename, "rb");
36+
gdTestAssert(fp != NULL);
37+
38+
fseek(fp, 0, SEEK_END);
39+
exp_size = ftell(fp);
40+
fseek(fp, 0, SEEK_SET);
41+
42+
*buffer = malloc(exp_size);
43+
gdTestAssert(*buffer != NULL);
44+
act_size = fread(*buffer, sizeof(**buffer), exp_size, fp);
45+
gdTestAssert(act_size == exp_size);
46+
47+
fclose(fp);
48+
free(filename);
49+
50+
return act_size;
51+
}

Diff for: tests/tga/heap_overflow.tga

605 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)