- 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 88d91086e97e18a9b71c265075acea15dda1b175..3cf0d0b50befeb6ec56b714e78d0437ab83d9ea4 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 17c63250ddfa6918df9f53100f830701d66e4ae8..487e765c611a77e0ebe26a267c331d69fed988a2 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 c1a82c97cc8deabcf63e9d67c120255b26a8c2fa..9d936602759beae8990d86191dbfc851d8ce501e 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 0f5e1349e08d49fb12899de51d8a44c47ae1b952..b1c7688c834b665dd3f293c11c74a8761a639b83 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