libtiff: * tools/tiffcrop.c: Patch from Richard Nolde to avoid a

https://github.com/libsdl-org/libtiff/commit/7ad653ed31f8268fceae5deb6bc47784c613e094

From 7ad653ed31f8268fceae5deb6bc47784c613e094 Mon Sep 17 00:00:00 2001
From: Bob Friesenhahn <[EMAIL REDACTED]>
Date: Tue, 13 Jul 2010 15:52:01 +0000
Subject: [PATCH] * tools/tiffcrop.c: Patch from Richard Nolde to avoid a
 potentially unterminated buffer due to using an exceptionally long file name.

---
 ChangeLog        |  6 ++++++
 tools/tiffcrop.c | 54 +++++++++++++++++++++++++++++++++++-------------
 2 files changed, 46 insertions(+), 14 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b27b4036..0ea8c0cd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2010-07-13  Bob Friesenhahn  <bfriesen@simple.dallas.tx.us>
+
+	* tools/tiffcrop.c: Patch from Richard Nolde to avoid a
+	potentially unterminated buffer due to using an exceptionally long
+	file name.
+
 2010-07-08  Andrey Kiselev  <dron@ak4719.spb.edu>
 
 	* tools/tiff2pdf.c: Fixed ID buffer filling in
diff --git a/tools/tiffcrop.c b/tools/tiffcrop.c
index 69e403d3..8cc0863e 100644
--- a/tools/tiffcrop.c
+++ b/tools/tiffcrop.c
@@ -1,4 +1,4 @@
-/* $Id: tiffcrop.c,v 1.3.2.13 2010-06-16 01:54:25 bfriesen Exp $ */
+/* $Id: tiffcrop.c,v 1.3.2.14 2010-07-13 15:52:01 bfriesen Exp $ */
 
 /* tiffcrop.c -- a port of tiffcp.c extended to include manipulations of
  * the image data through additional options listed below
@@ -6,7 +6,7 @@
  * Original code:
  * Copyright (c) 1988-1997 Sam Leffler
  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
- * Additions (c) Richard Nolde 2006-2009 
+ * Additions (c) Richard Nolde 2006-2010 
  *
  * Permission to use, copy, modify, distribute, and sell this software and 
  * its documentation for any purpose is hereby granted without fee, provided
@@ -108,7 +108,7 @@
  */
 
 static   char tiffcrop_version_id[] = "2.3";
-static   char tiffcrop_rev_date[] = "06-15-2010";
+static   char tiffcrop_rev_date[] = "07-12-2010";
 
 #include "tif_config.h"
 #include "tiffiop.h"
@@ -152,6 +152,11 @@ extern int getopt(int, char**, char*);
 #define	TRUE	1
 #define	FALSE	0
 
+#ifndef TIFFhowmany
+#define TIFFhowmany(x, y) ((((uint32)(x))+(((uint32)(y))-1))/((uint32)(y)))
+#define TIFFhowmany8(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3)
+#endif
+
 /*
  * Definitions and data structures required to support cropping and image
  * manipulations.
@@ -200,6 +205,7 @@ extern int getopt(int, char**, char*);
 #define MAX_IMAGES 2048  /* number of images in descrete list, not in the file */
 #define MAX_SAMPLES   8  /* maximum number of samples per pixel supported */
 #define MAX_BITS_PER_SAMPLE 64 /* maximum bit depth supported */
+#define MAX_EXPORT_PAGES 999999  /* maximum number of export pages per file */
 
 #define DUMP_NONE   0
 #define DUMP_TEXT   1
@@ -1670,9 +1676,6 @@ void  process_command_opts (int argc, char *argv[], char *mp, char *mode, uint32
                     (opt_ptr = strtok (NULL, ",")), i++)
                     {
 		    opt_offset = strpbrk(opt_ptr, ":=");
-		    /*
-		    opt_offset = strchr(opt_ptr, ':');
-		    */
                     if (opt_offset == NULL)
                       {
                       TIFFError("Invalid dump option", "%s", optarg);
@@ -1717,12 +1720,18 @@ void  process_command_opts (int argc, char *argv[], char *mp, char *mode, uint32
                       { /* Look for dump level specification */
                       if (strncmp (opt_ptr, "lev", 3) == 0)
                         dump->level = atoi(opt_offset + 1);
-                      /* Look for input data dump file name */
+                        /* Look for input data dump file name */
                       if (strncmp (opt_ptr, "in", 2) == 0)
+		        {
                         strncpy (dump->infilename, opt_offset + 1, PATH_MAX - 20);
-                       /* Look for output data dump file name */
+                        dump->infilename[PATH_MAX - 20] = '\0';
+                        }
+                        /* Look for output data dump file name */
                       if (strncmp (opt_ptr, "out", 3) == 0)
-                          strncpy (dump->outfilename, opt_offset + 1, PATH_MAX - 20);
+			{
+                        strncpy (dump->outfilename, opt_offset + 1, PATH_MAX - 20);
+                        dump->outfilename[PATH_MAX - 20] = '\0';
+                        }
                       if (strncmp (opt_ptr, "deb", 3) == 0)
 			dump->debug = atoi(opt_offset + 1);
 		      }
@@ -2031,7 +2040,6 @@ update_output_file (TIFF **tiffout, char *mode, int autoindex,
   char   export_ext[16];
   char   exportname[PATH_MAX];
 
-  strcpy (export_ext, ".tiff");
   if (autoindex && (*tiffout != NULL))
     {   
     /* Close any export file that was previously opened */
@@ -2039,7 +2047,11 @@ update_output_file (TIFF **tiffout, char *mode, int autoindex,
     *tiffout = NULL;
     }
 
-  strncpy (exportname, outname, PATH_MAX - 15);
+  strcpy (export_ext, ".tiff");
+  memset (exportname, '\0', PATH_MAX);
+
+  /* Leave room for page number portion of the new filename */
+  strncpy (exportname, outname, PATH_MAX - 16);
   if (*tiffout == NULL)   /* This is a new export file */
     {
     if (autoindex)
@@ -2054,10 +2066,18 @@ update_output_file (TIFF **tiffout, char *mode, int autoindex,
         strncpy (export_ext, ".tiff", 5);
       export_ext[5] = '\0';
 
+      /* MAX_EXPORT_PAGES limited to 6 digits to prevent string overflow of pathname */
+      if (findex > MAX_EXPORT_PAGES)
+	{
+	TIFFError("update_output_file", "Maximum of %d pages per file exceeded.\n", MAX_EXPORT_PAGES);
+        return 1;
+        }
+
       sprintf (filenum, "-%03d%s", findex, export_ext);
-      filenum[15] = '\0';
-      strncat (exportname, filenum, 14);
+      filenum[14] = '\0';
+      strncat (exportname, filenum, 15);
       }
+    exportname[PATH_MAX - 1] = '\0';
 
     *tiffout = TIFFOpen(exportname, mode);
     if (*tiffout == NULL)
@@ -2113,7 +2133,7 @@ main(int argc, char* argv[])
   unsigned int  end_of_input = FALSE;
   int    seg, length;
   char   temp_filename[PATH_MAX + 1];
-  memset (temp_filename, '\0', PATH_MAX + 1);              
+
   little_endian = *((unsigned char *)&little_endian) & '1';
 
   initImageData(&image);
@@ -2204,6 +2224,9 @@ main(int argc, char* argv[])
           if (dump.infile != NULL)
             fclose (dump.infile);
 
+          /* dump.infilename is guaranteed to be NUL termimated and have 20 bytes 
+             fewer than PATH_MAX */ 
+          memset (temp_filename, '\0', PATH_MAX + 1);              
           sprintf (temp_filename, "%s-read-%03d.%s", dump.infilename, dump_images,
                   (dump.format == DUMP_TEXT) ? "txt" : "raw");
           if ((dump.infile = fopen(temp_filename, dump.mode)) == NULL)
@@ -2220,6 +2243,9 @@ main(int argc, char* argv[])
           if (dump.outfile != NULL)
             fclose (dump.outfile);
 
+          /* dump.outfilename is guaranteed to be NUL termimated and have 20 bytes 
+             fewer than PATH_MAX */ 
+          memset (temp_filename, '\0', PATH_MAX + 1);              
           sprintf (temp_filename, "%s-write-%03d.%s", dump.outfilename, dump_images,
                   (dump.format == DUMP_TEXT) ? "txt" : "raw");
           if ((dump.outfile = fopen(temp_filename, dump.mode)) == NULL)