
# HG changeset patch
# User Bob Friesenhahn <bfriesen@GraphicsMagick.org>
# Date 1499006595 18000
# Node ID f10b9bb3ca621ecc51ec9c8a3b0d52e4503bb7e5
# Parent  e5761e3a20128e6d1a3d29904a6e479579306068
DPX: Estimate minimum required file sized based on header, and reject files with insufficient data

Index: GraphicsMagick-1.2.5/coders/dpx.c
===================================================================
--- GraphicsMagick-1.2.5.orig/coders/dpx.c	2017-12-04 14:36:31.398542417 +0100
+++ GraphicsMagick-1.2.5/coders/dpx.c	2017-12-04 14:44:31.870561356 +0100
@@ -404,6 +404,18 @@ typedef struct _DPXHeader
   DPXTVInfo tv_info;               /* Television information header */
 } DPXHeader;
 
+static size_t MagickArraySize(const size_t count, const size_t size)
+{
+  size_t
+    allocation_size;
+
+  allocation_size = size * count;
+  if ((count != 0) && (size != allocation_size/count))
+    allocation_size = 0;
+
+  return allocation_size;
+}
+
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %                                                                             %
@@ -2032,6 +2044,51 @@ STATIC Image *ReadDPXImage(const ImageIn
       return(image);
     }
   /*
+    Validate file size if using a seekable blob
+  */
+  if (BlobIsSeekable(image))
+    {
+      magick_off_t file_size;
+      magick_off_t file_size_estimate = dpx_file_info.image_data_offset;
+
+      /*
+        Verify that file size claimed by header is matched by file size
+      */
+      if ((file_size = GetBlobSize(image)) != 0)
+        {
+          if (file_size < dpx_file_info.file_size)
+            {
+              ThrowDPXReaderException(CorruptImageError,UnexpectedEndOfFile,image);
+            }
+        }
+
+      /*
+        Estimate the required file size and assure that actual file
+        size is at least that size.
+      */
+      for (element=0; element < dpx_image_info.elements; element++)
+        {
+          bits_per_sample=dpx_image_info.element_info[element].bits_per_sample;
+          element_descriptor=(DPXImageElementDescriptor)
+            dpx_image_info.element_info[element].descriptor;
+          transfer_characteristic=
+            (DPXTransferCharacteristic) dpx_image_info.element_info[element].transfer_characteristic;
+          packing_method=(ImageComponentPackingMethod) dpx_image_info.element_info[element].packing;
+          samples_per_pixel=DPXSamplesPerPixel(element_descriptor);
+          samples_per_row=samples_per_pixel*image->columns;
+          element_size=DPXRowOctets(image->rows,samples_per_row,
+                                    bits_per_sample,packing_method);
+          file_size_estimate += element_size;
+        }
+      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                            "File size estimate %" MAGICK_OFF_F
+                            "u bytes (have %" MAGICK_OFF_F "u bytes)",
+                            file_size_estimate, file_size);
+      if ((file_size_estimate <= 0) || (file_size < file_size_estimate))
+        ThrowDPXReaderException(CorruptImageError,InsufficientImageDataInFile,image);
+    }
+
+  /*
     Read remainder of header.
   */
   for ( ; offset < pixels_offset ; offset++ )
@@ -2041,14 +2098,14 @@ STATIC Image *ReadDPXImage(const ImageIn
     Allocate row samples.
   */
   samples=MagickAllocateArray(sample_t *,image->columns,
-                              max_samples_per_pixel*sizeof(sample_t));
+                              MagickArraySize(max_samples_per_pixel,sizeof(sample_t)));
   if (samples == (sample_t *) NULL)
     ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
   /*
     Allocate scanline storage.
   */
   scanline=MagickAllocateArray(unsigned char *,image->columns,
-                               max_samples_per_pixel*sizeof(U32));
+                               MagickArraySize(max_samples_per_pixel,sizeof(U32)));
   if (scanline == (unsigned char *) NULL)
     ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
 
@@ -3871,7 +3928,7 @@ STATIC unsigned int WriteDPXImage(const
     Allocate row samples.
   */
   samples=MagickAllocateArray(sample_t *,image->columns,
-                              max_samples_per_pixel*sizeof(sample_t));
+                              MagickArraySize(max_samples_per_pixel,sizeof(sample_t)));
   if (samples == (sample_t *) NULL)
     ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
   (void) memset((void *) samples,0,max_samples_per_pixel*image->columns*
