| 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 |
| |