Return-Path: <tiff-bounces@lists.maptools.org>
X-Original-To: info@awaresystems.be
Delivered-To: info@awaresystems.be
Received: from mx-e.b-one.net (mx-e.one.com [91.198.169.52])
	by mail9.b-one.net (Postfix) with ESMTP id B9D5940013D
	for <info@awaresystems.be>; Tue, 19 May 2009 14:50:12 +0200 (CEST)
X-Virus-Scanned: by one.com
X-Spam-Score: 0
X-Spam-Level: 
X-Spam-Status: No, score=0 tagged_above=0 required=6 tests=[none]
X-Greylist: domain auto-whitelisted by SQLgrey-1.7.4
Received: from lists.maptools.org (lists.maptools.org [65.39.174.144])
	by mx-e.b-one.net (Postfix) with ESMTP id D02D9C2DE21
	for <info@awaresystems.be>; Tue, 19 May 2009 14:50:11 +0200 (CEST)
Received: from localhost.localdomain (localhost.localdomain [127.0.0.1])
	by lists.maptools.org (Postfix) with ESMTP id 270621D1AEE2A;
	Tue, 19 May 2009 07:47:37 -0500 (EST)
Received: from fmmailgate02.web.de (fmmailgate02.web.de [217.72.192.227])
	by lists.maptools.org (Postfix) with ESMTP id C7B1B1D18B104
	for <tiff@lists.maptools.org>; Tue, 19 May 2009 07:32:57 -0500 (EST)
Received: from smtp06.web.de (fmsmtp06.dlan.cinetic.de [172.20.5.172])
	by fmmailgate02.web.de (Postfix) with ESMTP id 62E87FF9393C
	for <tiff@lists.maptools.org>; Tue, 19 May 2009 14:32:56 +0200 (CEST)
Received: from [217.228.239.91] (helo=[172.16.99.2])
	by smtp06.web.de with asmtp (TLSv1:AES256-SHA:256)
	(WEB.DE 4.110 #277) id 1M6OV4-0002Gv-00
	for tiff@lists.maptools.org; Tue, 19 May 2009 14:32:54 +0200
Message-ID: <4A12A6F6.5010000@magic.ms>
Date: Tue, 19 May 2009 14:32:54 +0200
From: emagick@magic.ms
User-Agent: Thunderbird 2.0.0.21 (X11/20090302)
MIME-Version: 1.0
To: tiff@lists.maptools.org
X-Sender: eberhard.mattes@web.de
X-Provags-ID: V01U2FsdGVkX1+DVRl8PpZmZiF0uQ7i1wz5//MhJdfLIEW8UCV6
	Z5u9ZJ43UGr99VVkxGt2IUrOFGXVwRAjVqsGjDoa4MXDOonnyw
	wAlhBDO3233ziqepDl3g==
Subject: [Tiff] Heap corruption caused by TIFFRGBAImageGet() +
 TIFFSetDirectory() + TIFFRewriteDirectory()
X-BeenThere: tiff@lists.maptools.org
X-Mailman-Version: 2.1.9
Precedence: list
List-Id: TIFF and libtiff discussion <tiff.lists.maptools.org>
List-Unsubscribe: <http://lists.maptools.org/mailman/listinfo/tiff>,
	<mailto:tiff-request@lists.maptools.org?subject=unsubscribe>
List-Archive: <http://lists.maptools.org/mailman/private/tiff>
List-Post: <mailto:tiff@lists.maptools.org>
List-Help: <mailto:tiff-request@lists.maptools.org?subject=help>
List-Subscribe: <http://lists.maptools.org/mailman/listinfo/tiff>,
	<mailto:tiff-request@lists.maptools.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: tiff-bounces@lists.maptools.org
Errors-To: tiff-bounces@lists.maptools.org

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;
}

_______________________________________________
Tiff mailing list: Tiff@lists.maptools.org
http://lists.maptools.org/mailman/listinfo/tiff
http://www.remotesensing.org/libtiff/
