- the SGI RLE compression code could overflow its compression buffer
authorTony Cook <tony@develop=help.com>
Mon, 29 Oct 2007 11:11:10 +0000 (11:11 +0000)
committerTony Cook <tony@develop=help.com>
Mon, 29 Oct 2007 11:11:10 +0000 (11:11 +0000)
   http://rt.cpan.org/Ticket/Display.html?id=30334

 - the 32-bit output function used by the SGI code only handled values
   under 0x10000.  This was most noticable when writing large RLE images.
   http://rt.cpan.org/Ticket/Display.html?id=30335

Changes
SGI/imsgi.c
SGI/t/20write.t
TODO

diff --git a/Changes b/Changes
index b7735d7..9427270 100644 (file)
--- a/Changes
+++ b/Changes
@@ -33,6 +33,13 @@ Bug fixes:
    Added tests for better code coverage of the ops.
    http://rt.cpan.org/Ticket/Display.html?id=29296
 
+ - the SGI RLE compression code could overflow its compression buffer
+   http://rt.cpan.org/Ticket/Display.html?id=30334
+
+ - the 32-bit output function used by the SGI code only handled values
+   under 0x10000.  This was most noticable when writing large RLE images.
+   http://rt.cpan.org/Ticket/Display.html?id=30335
+
 Imager 0.60 - 30 August 2007
 ===========
 
index 54a2d49..547badc 100644 (file)
@@ -121,7 +121,7 @@ store_16(unsigned char *buf, unsigned short value) {
 }
 
 static void
-store_32(unsigned char *buf, unsigned short value) {
+store_32(unsigned char *buf, unsigned long value) {
   buf[0] = value >> 24;
   buf[1] = (value >> 16) & 0xFF;
   buf[2] = (value >> 8) & 0xFF;
@@ -987,9 +987,8 @@ write_sgi_8_rle(i_img *img, io_glue *ig) {
          
          /* fill out the run if 2 or less samples left and there's space */
          if (in_left - run_length <= 2 
-             && run_length + in_left - run_length <= 127) {
-           run_length += in_left;
-           in_left = 0;
+             && in_left <= 127) {
+           run_length = in_left;
          }
          in_left -= run_length;
          *outp++ = run_length | 0x80;
@@ -1145,9 +1144,8 @@ write_sgi_16_rle(i_img *img, io_glue *ig) {
          
          /* fill out the run if 2 or less samples left and there's space */
          if (in_left - run_length <= 2 
-             && run_length + in_left - run_length <= 127) {
-           run_length += in_left;
-           in_left = 0;
+             && in_left <= 127) {
+           run_length = in_left;
          }
          in_left -= run_length;
          store_16(outp, run_length | 0x80);
index 1ca6aef..879412b 100644 (file)
@@ -1,7 +1,7 @@
 #!perl -w
 use strict;
 use Imager;
-use Test::More tests => 51;
+use Test::More tests => 55;
 use Imager::Test qw(test_image test_image_16 is_image);
 use IO::Seekable;
 
@@ -11,6 +11,7 @@ Imager::init_log('testout/20write.log', 2);
 
 {
   my $im = test_image();
+  $im->line(x1 => 0, y1 => 0, x2 => 150, y2 => 150, color => 'FF0000');
   ok($im->write(file => 'testout/20verb.rgb'), "write 8-bit verbatim")
     or print "# ", $im->errstr, "\n";
   my $im2 = Imager->new;
@@ -36,6 +37,7 @@ Imager::init_log('testout/20write.log', 2);
 
 {
   my $im = test_image_16();
+  $im->line(x1 => 0, y1 => 0, x2 => 150, y2 => 150, color => 'FF0000');
   ok($im->write(file => 'testout/20verb16.rgb'), "write 16-bit verbatim")
     or print "# ", $im->errstr, "\n";
   my $im2 = Imager->new;
@@ -57,6 +59,24 @@ Imager::init_log('testout/20write.log', 2);
   is($im3->tags(name => 'sgi_rle'), 1, "check not rle");
   is($im3->tags(name => 'sgi_bpc'), 2, "check bpc");
   is($im3->tags(name => 'i_comment'), 'test', "check i_comment set");
+
+  my $imbig = Imager->new(xsize => 300, ysize => 300, bits => 16);
+  $imbig->paste(src => $im, tx => 0,   ty => 0);
+  $imbig->paste(src => $im, tx => 150, ty => 0);
+  $imbig->paste(src => $im, tx => 0,   ty => 150);
+  $imbig->paste(src => $im, tx => 150, ty => 150);
+  for my $t (0 .. 74) {
+    $imbig->line(x1 => $t*4, y1 => 0, x2 => 3+$t*4, y2 => 299, 
+                color => [ 255 - $t, 0, 0 ]);
+  }
+  my $data;
+  ok($imbig->write(data => \$data, type => 'sgi', sgi_rle => 1),
+     "write larger image");
+  cmp_ok(length($data), '>', 0x10000, "check output large enough for test");
+  print "# ", length $data, "\n";
+  my $imbigcmp = Imager->new;
+  ok($imbigcmp->read(data => $data), "read larger image");
+  is_image($imbig, $imbigcmp, "check large image matches");
 }
 
 {
diff --git a/TODO b/TODO
index 256fba2..fe2350b 100644 (file)
--- a/TODO
+++ b/TODO
@@ -26,7 +26,7 @@ TIFF improvements (to be detailed) (#20329)
 both contig and non-contiguous
  - possible extra code for handling 8-bit CMYK (#29353)
 
-regmach.c fixes/tests (#29296)
+regmach.c fixes/tests (#29296) (done)
 
 sample: scaling an animated gif (#27591) (done)