commit bmp security fixes to HEAD
authorTony Cook <tony@develop=help.com>
Thu, 3 May 2007 10:20:39 +0000 (10:20 +0000)
committerTony Cook <tony@develop=help.com>
Thu, 3 May 2007 10:20:39 +0000 (10:20 +0000)
Changes
bmp.c
t/t107bmp.t

diff --git a/Changes b/Changes
index 159f9ee..8a72769 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,6 +1,6 @@
 Imager release history.  Older releases can be found in Changes.old
 
-Imager 0.57 -
+Imager 0.58 -
 ===========
 
  - added to_rgb16 to produce a 16-bit/sample version of an image
@@ -21,6 +21,16 @@ Bug fixes:
    regenerate Inline code when a new release of Imager is installed.
    http://rt.cpan.org/Ticket/Display.html?id=26278
 
+Imager 0.57 - 30 Apr 2007
+===========
+
+This is a maintenence release fixing a security issue in Imager.
+
+ - CRITICAL: a specially crafted compressed BMP file can cause a buffer
+   overflow in malloced memory.  There will be further discussion of
+   this issue in the ticket below.
+   http://rt.cpan.org/Ticket/Display.html?id=26811
+
 Imager 0.56 - 1 Apr 2007
 ===========
 
diff --git a/bmp.c b/bmp.c
index 7986f26..172b1a3 100644 (file)
--- a/bmp.c
+++ b/bmp.c
@@ -916,6 +916,13 @@ read_4bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
         }
       }
       else if (packed[0]) {
+       if (x + packed[0] > xsize) {
+         /* this file is corrupt */
+         myfree(line);
+         i_push_error(0, "invalid data during decompression");
+         i_img_destroy(im);
+         return NULL;
+       }
         line[0] = packed[1] >> 4;
         line[1] = packed[1] & 0x0F;
         for (i = 0; i < packed[0]; i += 2) {
@@ -958,6 +965,13 @@ read_4bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
 
         default:
           count = packed[1];
+         if (x + count > xsize) {
+           /* this file is corrupt */
+           myfree(line);
+           i_push_error(0, "invalid data during decompression");
+           i_img_destroy(im);
+           return NULL;
+         }
           size = (count + 1) / 2;
           read_size = (size+1) / 2 * 2;
           if (ig->readcb(ig, packed, read_size) != read_size) {
@@ -1113,6 +1127,13 @@ read_8bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
         }
       }
       if (packed[0]) {
+       if (x + packed[0] > xsize) {
+         /* this file isn't incomplete, it's corrupt */
+         myfree(line);
+         i_push_error(0, "invalid data during decompression");
+         i_img_destroy(im);
+         return NULL;
+       }
         memset(line, packed[1], packed[0]);
         i_ppal(im, x, x+packed[0], y, line);
         x += packed[0];
@@ -1147,6 +1168,14 @@ read_8bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
 
         default:
           count = packed[1];
+         if (x + count > xsize) {
+           /* runs shouldn't cross a line boundary */
+           /* this file isn't incomplete, it's corrupt */
+           myfree(line);
+           i_push_error(0, "invalid data during decompression");
+           i_img_destroy(im);
+           return NULL;
+         }
           read_size = (count+1) / 2 * 2;
           if (ig->readcb(ig, line, read_size) != read_size) {
             myfree(line);
index c3e3859..6e77e3b 100644 (file)
@@ -1,6 +1,6 @@
 #!perl -w
 use strict;
-use Test::More tests => 191;
+use Test::More tests => 199;
 use Imager qw(:all);
 use Imager::Test qw(test_image_raw is_image);
 init_log("testout/t107bmp.log",1);
@@ -493,6 +493,32 @@ for my $comp (@comp) {
       "image data offset too small (53)",
       "24-bit, small image offset"
      ],
+     # compression issues
+     [
+      "comp8.bmp",
+      { 0x436 => "97" },
+      "invalid data during decompression",
+      "8bit, RLE run beyond edge of image"
+     ],
+     [
+      # caused glibc malloc or valgrind to complain
+      "comp8.bmp",
+      { 0x436 => "94 00 00 03" },
+      "invalid data during decompression",
+      "8bit, literal run beyond edge of image"
+     ],
+     [
+      "comp4.bmp",
+      { 0x76 => "FF bb FF BB" },
+      "invalid data during decompression",
+      "4bit - RLE run beyond edge of image"
+     ],
+     [
+      "comp4.bmp",
+      { 0x76 => "94 bb 00 FF" },
+      "invalid data during decompression",
+      "4bit - literal run beyond edge of image"
+     ],
     );
   my $test_index = 0;
   for my $test (@tests) {