Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame^] | 1 | From fb0e0cce0b9f25389ab56604c3547351617e1415 Mon Sep 17 00:00:00 2001 |
| 2 | From: "Christoph M. Becker" <cmbecker69@gmx.de> |
| 3 | Date: Tue, 16 Aug 2016 16:26:19 +0200 |
| 4 | Subject: [PATCH] Fix OOB reads of the TGA decompression buffer |
| 5 | |
| 6 | It is possible to craft TGA files which will overflow the decompression |
| 7 | buffer, but not the image's bitmap. Therefore we augment the check for the |
| 8 | bitmap's overflow with a check for the buffer's overflow. |
| 9 | |
| 10 | This issue had been reported by Ibrahim El-Sayed to security@libgd.org. |
| 11 | |
| 12 | CVE-2016-6906 |
| 13 | |
| 14 | Upstream-Status: Backport |
| 15 | CVE: CVE-2016-6906 |
| 16 | |
| 17 | Signed-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 | |
| 29 | diff --git a/src/gd_tga.c b/src/gd_tga.c |
| 30 | index 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; |
| 53 | diff --git a/tests/tga/.gitignore b/tests/tga/.gitignore |
| 54 | index 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 |
| 64 | diff --git a/tests/tga/CMakeLists.txt b/tests/tga/CMakeLists.txt |
| 65 | index 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 | |
| 76 | diff --git a/tests/tga/Makemodule.am b/tests/tga/Makemodule.am |
| 77 | index 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 |
| 96 | diff --git a/tests/tga/heap_overflow.c b/tests/tga/heap_overflow.c |
| 97 | new file mode 100644 |
| 98 | index 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 | +} |
| 153 | diff --git a/tests/tga/heap_overflow.tga b/tests/tga/heap_overflow.tga |
| 154 | new file mode 100644 |
| 155 | index 0000000000000000000000000000000000000000..e9bc0ecb2a847ac6edba92dd0ff61167b49002cd |
| 156 | GIT binary patch |
| 157 | literal 605 |
| 158 | zcmZQz;9`IQ9tIu;g&7<$F3o7Yg1qzyh6tefy9wZAs2d<Uh*yuz=?XwW4Qvuv#g2nS |
| 159 | zp93+mT0rVR>T&8(2TGy=f_l)@gSap~$FayUFu(!|SyJIFga^{8fGj~vwq8kkVgvv> |
| 160 | Cavop+ |
| 161 | |
| 162 | literal 0 |
| 163 | HcmV?d00001 |
| 164 | |
| 165 | -- |
| 166 | 2.10.2 |
| 167 | |