- in some cases it's possible for giflib/libungif to return color
authorTony Cook <tony@develop=help.com>
Thu, 21 Jun 2007 12:53:47 +0000 (12:53 +0000)
committerTony Cook <tony@develop=help.com>
Thu, 21 Jun 2007 12:53:47 +0000 (12:53 +0000)
   indexes outside the range of colors defined by the image's palette.
   We now expand the palette to match the indexes used.
   Thanks to Gabriel Vasseur for reporting this.

Changes
MANIFEST
gif.c
t/t105gif.t
testimg/badindex.gif [new file with mode: 0644]

diff --git a/Changes b/Changes
index 88d9108..3cf0d0b 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,15 @@
 Imager release history.  Older releases can be found in Changes.old
 
+Imager 0.60
+===========
+
+Bug fixes:
+
+ - in some cases it's possible for giflib/libungif to return color 
+   indexes outside the range of colors defined by the image's palette.
+   We now expand the palette to match the indexes used.
+   Thanks to Gabriel Vasseur for reporting this.
+
 Imager 0.59 - 14 June 2007
 ===========
 
index 17c6325..487e765 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -271,6 +271,7 @@ testimg/bad8wid0.bmp    8-bit/pixel, width 0
 testimg/badbits.bmp     bad bits value in header
 testimg/badcomp1.bmp    bad compression for 1-bit/pixel
 testimg/badcomp4.bmp    bad compression for 4-bit/pixel
+testimg/badindex.gif   GIF with a bad color index
 testimg/badplanes.bmp   bad planes value in header
 testimg/badused1.bmp    1-bit/pixel, out of range colors used value
 testimg/badused4a.bmp   4-bit/pixel, badly out of range used value (SEGV test)
diff --git a/gif.c b/gif.c
index c1a82c9..9d93660 100644 (file)
--- a/gif.c
+++ b/gif.c
@@ -529,6 +529,8 @@ i_img **i_readgif_multi_low(GifFileType *GifFile, int *count, int page) {
   i_img **results = NULL;
   int result_alloc = 0;
   int channels;
+  int image_colors = 0;
+  i_color black = { 0 }; /* used to expand the palette if needed */
   
   *count = 0;
 
@@ -610,6 +612,7 @@ i_img **i_readgif_multi_low(GifFileType *GifFile, int *count, int page) {
          
          i_addcolors(img, &col, 1);
        }
+       image_colors = ColorMapSize;
        ++*count;
        if (*count > result_alloc) {
          if (result_alloc == 0) {
@@ -682,7 +685,19 @@ i_img **i_readgif_multi_low(GifFileType *GifFile, int *count, int page) {
                myfree(GifRow);
                return NULL;
              }
-             
+
+             /* range check the scanline if needed */
+             if (image_colors != 256) {
+               int x;
+               for (x = 0; x < Width; ++x) {
+                 while (GifRow[x] >= image_colors) {
+                   /* expand the palette since a palette index is too big */
+                   i_addcolors(img, &black, 1);
+                   ++image_colors;
+                 }
+               }
+             }
+
              i_ppal(img, 0, Width, j, GifRow);
            }
          }
@@ -698,6 +713,18 @@ i_img **i_readgif_multi_low(GifFileType *GifFile, int *count, int page) {
              return NULL;
            }
            
+           /* range check the scanline if needed */
+           if (image_colors != 256) {
+             int x;
+             for (x = 0; x < Width; ++x) {
+               while (GifRow[x] >= image_colors) {
+                 /* expand the palette since a palette index is too big */
+                 i_addcolors(img, &black, 1);
+                 ++image_colors;
+               }
+             }
+           }
+
            i_ppal(img, 0, Width, i, GifRow);
          }
        }
index 0f5e134..b1c7688 100644 (file)
@@ -12,8 +12,9 @@ UPGRADE.
 
 use strict;
 $|=1;
-use Test::More tests => 125;
+use Test::More tests => 129;
 use Imager qw(:all);
+use Imager::Test qw(is_color3);
 BEGIN { require "t/testtools.pl"; }
 use Carp 'confess';
 $SIG{__DIE__} = sub { confess @_ };
@@ -48,7 +49,7 @@ SKIP:
     $im = Imager->new(xsize=>2, ysize=>2);
     ok(!$im->write(file=>"testout/nogif.gif"), "should fail to write gif");
     is($im->errstr, 'format not supported', "check no gif message");
-    skip("no gif support", 121);
+    skip("no gif support", 124);
   }
     open(FH,">testout/t105.gif") || die "Cannot open testout/t105.gif\n";
     binmode(FH);
@@ -688,6 +689,20 @@ SKIP:
     is($im[1]->tags(name => 'gif_user_input'),      0, "1 - gif_user_input");
     is($im[1]->tags(name => 'gif_loop'),            0, "1 - gif_loop");
   }
+
+  {
+    # manually modified from a small gif, this had the palette
+    # size changed to half the size, leaving an index out of range
+    my $im = Imager->new;
+    ok($im->read(file => 'testimg/badindex.gif', type => 'gif'), 
+       "read bad index gif")
+      or print "# ", $im->errstr, "\n";
+    my @indexes = $im->getscanline('y' => 0, type => 'index');
+    is_deeply(\@indexes, [ 0..4 ], "check for correct indexes");
+    is($im->colorcount, 5, "check the palette was adjusted");
+    is_color3($im->getpixel('y' => 0, x => 4), 0, 0, 0, 
+             "check it was black added");
+  }
 }
 
 sub test_readgif_cb {
diff --git a/testimg/badindex.gif b/testimg/badindex.gif
new file mode 100644 (file)
index 0000000..3591f48
Binary files /dev/null and b/testimg/badindex.gif differ