AWARE [SYSTEMS] Imaging expertise for the Delphi developer
AWare Systems, Imaging expertise for the Delphi developer, Home TIFF and LibTiff Mailing List Archive

LibTiff Mailing List

TIFF and LibTiff Mailing List Archive
March 2006

Previous Thread
Next Thread

Previous by Thread
Next by Thread

Previous by Date
Next by Date

Contact

The TIFF Mailing List Homepage
This list is run by Frank Warmerdam
Archive maintained by AWare Systems



Valid HTML 4.01!



Thread

2006.03.10 16:06 "LibTIFF 3.8.0 crash bug (patch included)", by Holger Schemel
2006.03.13 08:01 "Re: LibTIFF 3.8.0 crash bug (patch included)", by Andrey Kiselev
2006.03.13 08:24 "Re: LibTIFF 3.8.0 crash bug (patch included)", by Holger Schemel

2006.03.10 16:06 "LibTIFF 3.8.0 crash bug (patch included)", by Holger Schemel

Hello,

I have encountered a TIFF file that crashes the current stable
version 3.8.0 of LibTIFF; as this TIFF file is rather large
(about 10 MB), I haven't attached it to this mail, but you can
get it at "http://artsoft.org/stuff/this_crashes_libtiff.tif".

For example, a simple "identify this_crashes_libtiff.tif" with
ImageMagick crashes in LibTIFF, as shown by a "gdb" backtrace.

The reason for this crash on this particular image file is the
following LibTIFF change (from the "ChangeLog" in version 3.8.0):

----- snip -----
2005-12-24  Andrey Kiselev  <dron@remotesensing.org>

        * libtiff/{tif_aux.c, tif_dir.c, tif_dir.h, tif_dirwrite.c,
        tif_print.c, tif_getimage.c}: Make InkSet, NumberOfInks, DotRange and
        StoNits tags custom.
----- snip -----

So when using ImageMagick with LibTIFF 3.7.4, everything works
just fine.

After diving a bit into the LibTIFF code, the reason for this
crash seems to be the following: While the tags "InkSet",
"NumberOfInks" and "StoNits" are defined to be one single data
of the type TIFF_SHORT or TIFF_DOUBLE, "DotRange" are two data
values of the type TIFF_BYTE or TIFF_SHORT, which are put onto
the stack as two separate values in "_TIFFVSetField()" in the
source file "libtiff/tif_dir.c". When falling through to the
"default:" switch label, the code reaches the following part
(around line 480):

----- snip -----
                if (fip->field_passcount
                    || fip->field_writecount == TIFF_VARIABLE
                    || fip->field_writecount == TIFF_VARIABLE2
                    || fip->field_writecount == TIFF_SPP
                    || tv->count > 1) {
                    _TIFFmemcpy(tv->value, va_arg(ap, void *),
                                tv->count * tv_size);
----- snip -----

The problem here is "tv->count > 1", which is true here because
tv->count is "2", but there's no pointer on the stack, but two
8 or 16 bit values (which are furthermore propagated to "int").

So LibTIFF crashes in "_TIFFmemcpy()". :-(

(All other custom tags mentioned above that were removed in
favor of the more generic code above are handled correctly,
because their "field_writecount" is always "1" according to
"tiffFieldInfo[]", so the code reaches the switch statement
directly after the above code segment. But I'm not sure if it
may also crash for the other custom tags that were handled
explicitly in version 3.7.4 and that have more than one "simple"
data value (SHORT etc.), like "TIFFTAG_DNGVERSION" or others.)

The attached very small patch is nothing else than the behaviour
of the previous version 3.7.4, just put back into 3.8.0 again.

With this little change, processing the above TIFF image works
just fine! :-)

Best regards,
		Holger
-- 
holger.schemel@artsoft.org

diff -r -c tiff-3.8.0.orig/libtiff/tif_dir.c tiff-3.8.0.fixed/libtiff/tif_dir.c
*** tiff-3.8.0.orig/libtiff/tif_dir.c	2005-12-29 22:46:38.000000000 +0100
--- tiff-3.8.0.fixed/libtiff/tif_dir.c	2006-03-03 14:33:41.000000000 +0100
***************
*** 363,368 ****
--- 363,373 ----
  			_TIFFsetShortArray(&td->td_transferfunction[i],
  			    va_arg(ap, uint16*), 1L<<td->td_bitspersample);
  		break;
+         case TIFFTAG_DOTRANGE:
+ 		/* XXX should check for null range */
+ 		td->td_dotrange[0] = (uint16) va_arg(ap, int);
+ 		td->td_dotrange[1] = (uint16) va_arg(ap, int);
+ 		break;
  	case TIFFTAG_INKNAMES:
  		v = va_arg(ap, uint32);
  		s = va_arg(ap, char*);
***************
*** 777,782 ****
--- 782,791 ----
                  *va_arg(ap, uint16**) = td->td_transferfunction[2];
              }
              break;
+ 	case TIFFTAG_DOTRANGE:
+             *va_arg(ap, uint16*) = td->td_dotrange[0];
+             *va_arg(ap, uint16*) = td->td_dotrange[1];
+             break;
  	case TIFFTAG_INKNAMES:
              *va_arg(ap, char**) = td->td_inknames;
              break;
diff -r -c tiff-3.8.0.orig/libtiff/tif_dir.h tiff-3.8.0.fixed/libtiff/tif_dir.h
*** tiff-3.8.0.orig/libtiff/tif_dir.h	2005-12-29 22:46:38.000000000 +0100
--- tiff-3.8.0.fixed/libtiff/tif_dir.h	2006-03-03 14:33:45.000000000 +0100
***************
*** 74,79 ****
--- 74,80 ----
  	/* Colorimetry parameters */
  	uint16*	td_transferfunction[3];
  	/* CMYK parameters */
+ 	uint16  td_dotrange[2];
  	int	td_inknameslen;
  	char*	td_inknames;