[Image-SIG] Patch for PNG reading bug

Bernhard Herzog bh@intevation.de
25 Jul 2001 11:59:21 +0200


We've run into the problem again that PIL can't read PNG files
sometimes, even though they're perfectly valid and don't use any
features that PIL doesn't support (like e.g. interlacing). I've posted
this problem at least twice before.

Well, I looked into it a bit more and found a fix, see the patch below.
As it turns out, in lines 101--108 in ZipDecode.c, n can in fact be
non-zero and less than state->bytes + context->prefix. The patch is
probably not the best fix, but it solves the problem.


  Bernhard


*** Zip.h.orig	Thu May  3 12:57:38 2001
--- Zip.h	Wed Jul 25 11:24:49 2001
***************
*** 38,43 ****
--- 38,45 ----
  
      UINT8* previous;		/* previous line (allocated) */
  
+     int last_output;		/* # bytes last output by inflate */
+ 
      /* Compressor specific stuff */
      UINT8* prior;		/* filter storage (allocated) */
      UINT8* up;
*** ZipDecode.c.orig	Thu May  3 12:57:38 2001
--- ZipDecode.c	Wed Jul 25 11:24:49 2001
***************
*** 51,56 ****
--- 51,58 ----
  	    return -1;
  	}
  
+ 	context->last_output = 0;
+ 
  	/* Initialize to black */
  	memset(context->previous, 0, state->bytes+1);
  
***************
*** 77,84 ****
      /* Decompress what we've got this far */
      while (context->z_stream.avail_in > 0) {
  
! 	context->z_stream.next_out = state->buffer;
! 	context->z_stream.avail_out = state->bytes + context->prefix;
  
  	err = inflate(&context->z_stream, Z_NO_FLUSH);
  
--- 79,87 ----
      /* Decompress what we've got this far */
      while (context->z_stream.avail_in > 0) {
  
! 	context->z_stream.next_out = state->buffer + context->last_output;
! 	context->z_stream.avail_out =
! 	    state->bytes + context->prefix - context->last_output;
  
  	err = inflate(&context->z_stream, Z_NO_FLUSH);
  
***************
*** 100,105 ****
--- 103,109 ----
  	if (n < state->bytes + context->prefix) {
  	    /* FIXME: if n is not zero, we're in trouble.  But can
  	       that really happen?  My tests say it cannot... */
+ 	    context->last_output = n;
  	    break; /* need more input data */
  	}
  
***************
*** 175,180 ****
--- 179,187 ----
  		       state->xsize);
  
  	state->y++;
+ 
+ 	/* all inflate output has been consumed */
+ 	context->last_output = 0;
  
  	if (state->y >= state->ysize || err == Z_STREAM_END) {
  


-- 
Intevation GmbH                                 http://intevation.de/
Sketch                                 http://sketch.sourceforge.net/
MapIt!                                               http://mapit.de/