Skip to content
Permalink
Browse files Browse the repository at this point in the history
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
  • Loading branch information
cmb69 committed Dec 13, 2016
1 parent 5ebbd50 commit fb0e0cc
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 2 deletions.
6 changes: 4 additions & 2 deletions src/gd_tga.c
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions tests/tga/.gitignore
Expand Up @@ -3,5 +3,6 @@
/bug00247a
/bug00248
/bug00248a
/heap_overflow
/tga_null
/tga_read
1 change: 1 addition & 0 deletions tests/tga/CMakeLists.txt
Expand Up @@ -5,6 +5,7 @@ LIST(APPEND TESTS_FILES
bug00247a
bug00248
bug00248a
heap_overflow
tga_read
)

Expand Down
2 changes: 2 additions & 0 deletions tests/tga/Makemodule.am
Expand Up @@ -4,6 +4,7 @@ libgd_test_programs += \
tga/bug00247a \
tga/bug00248 \
tga/bug00248a \
tga/heap_overflow \
tga/tga_null \
tga/tga_read

Expand All @@ -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
51 changes: 51 additions & 0 deletions 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;
}
Binary file added tests/tga/heap_overflow.tga
Binary file not shown.

0 comments on commit fb0e0cc

Please sign in to comment.