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
May 2009

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!



2009.05.19 12:32 "Heap corruption caused by TIFFRGBAImageGet() + TIFFSetDirectory() + TIFFRewriteDirectory()", by <emagick@magic.ms>

TIFFStartStrip() uses the raw buffer for *reading* data and sets tif_rawcc
to a positive value:

	tif->tif_rawcc = td->td_stripbytecount[strip];

TIFFReadDirectory() resets tif_curstrip to -1, but doesn't reset tif_rawcc
to 0:

	tif->tif_curstrip = (tstrip_t) -1;

In consequence, the next call to _TIFFWriteDirectory() thinks there is
pending data to *write*:

	    if (tif->tif_rawcc > 0 && !TIFFFlushData1(tif)) {

and TIFFAppendToStrip() will modify td_stripoffset[-1] (as strip =
tif->tif_curstrip = (tstrip_t)-1):

					td->td_stripoffset[strip] =
						TIFFSeekFile(tif, (toff_t)0,
							     SEEK_END);

Probably ditto for tiled images. There seems to be no way to reset tif_rawcc
to 0 with the official
API except for reopening the image.

When built with dmalloc, the program below will result in this output:

   libtiff version: LIBTIFF, Version 3.8.2
   Copyright (c) 1988-1996 Sam Leffler
   Copyright (c) 1991-1996 Silicon Graphics, Inc.
   tif_rawcc=115
   tif_curtile=-1
   tif_curstrip=2338

   tif_rawcc=115
   tif_curtile=-1
   tif_curstrip=-1

   debug-malloc library: dumping program, fatal error
      Error: failed UNDER picket-fence magic-number check (err 26)
   Aborted

Here's the program:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "tiffio.h"
#ifdef HAVE_TIFFIOP_H
#include "tiffiop.h"
#endif

static void show (TIFF *tif)
{
#ifdef HAVE_TIFFIOP_H
   printf ("tif_rawcc=%ld\n", (long)tif->tif_rawcc);
   printf ("tif_curtile=%ld\n", (long)tif->tif_curtile);
   printf ("tif_curstrip=%ld\n", (long)tif->tif_curstrip);
   printf ("\n");
#endif
}

int main (int argc, char *argv[])
{
   const char *path;
   TIFF *tif;
   uint32 width, height;
   TIFFRGBAImage img;
   size_t size;
   uint32 *raster;
   char msg[1024];

   printf ("libtiff version: %s\n", TIFFGetVersion ());
   if (argc != 2)
     {
       fprintf (stderr, "Usage: %s TIFF_FILE\n", argv[0]);
       exit (1);
     }
   path = argv[1];
   tif = TIFFOpen (path, "r+");
   if (tif == NULL)
     {
       perror (path);
       exit (2);
     }

   if (TIFFRGBAImageOK (tif, msg) != 1)
     {
       fprintf (stderr, "Cannot process image as RGBA (%s)\n", msg);
       exit (2);
     }
   if (TIFFRGBAImageBegin (&img, tif, 1, msg) != 1)
     {
       fprintf (stderr, "TIFFRGBAImageBegin failed (%s)\n", msg);
       exit (2);
     }
   TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &width);
   TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &height);
   size = (size_t)-1;
   if (width > size / height / sizeof (uint32))
     {
       fprintf (stderr, "Image too big\n");
       exit (2);
     }
   size = width * height * sizeof (uint32);
   raster = (uint32 *)malloc (size);
   if (raster == NULL)
     {
       fprintf (stderr, "Out of memory\n");
       exit (2);
     }
   if (TIFFRGBAImageGet (&img, raster, width, height) != 1)
     {
       fprintf (stderr, "TIFFRGBAImageGet failed\n");
       exit (2);
     }
   TIFFRGBAImageEnd (&img);

   show (tif);

   if (TIFFSetDirectory (tif, 0) != 1)
     {
       fprintf (stderr, "TIFFSetDirectory failed\n");
       exit (2);
     }

   show (tif);

   /* ... set some fields here... */

   if (TIFFRewriteDirectory (tif) != 1)
     {
       fprintf (stderr, "TIFFRewriteDirectory failed\n");
       exit (2);
     }

   TIFFClose (tif);
   return 0;
}