CVE-2016-10065: Improper Access Control (CWE-284)
value: The ReadVIFFImage function in coders/viff.c in ImageMagick before 7.0.1-0 allows remote attackers to cause a denial of service (application crash) or have other unspecified impact via a crafted file.
CWE description: The product does not restrict or incorrectly restricts access to a resource from an unauthorized actor.
CVSS v3 base score: 7.8
Published: 2017-03-03T17:59Z
Repository: https://github.com/ImageMagick/ImageMagick
Language: C
Files changed: MagickCore/memory.c, MagickCore/quantum-import.c, coders/viff.c
Commit date: 2016-02-14 10:40:47 -0500
Commit message: https://github.com/ImageMagick/ImageMagick/issues/129

Diff: diff --git a/MagickCore/memory.c b/MagickCore/memory.c
index 02bae6a23a..01f8e91428 100644
--- a/MagickCore/memory.c
+++ b/MagickCore/memory.c
@@ -231,10 +231,11 @@ static MagickBooleanType
 %    o count: the number of quantum elements to allocate.
 %
 %    o quantum: the number of bytes in each quantum.
 %
 */
+
 static MagickBooleanType CheckMemoryOverflow(const size_t count,
   const size_t quantum)
 {
   size_t
     size;
diff --git a/MagickCore/quantum-import.c b/MagickCore/quantum-import.c
index a0085f3b73..8aa766e2b5 100644
--- a/MagickCore/quantum-import.c
+++ b/MagickCore/quantum-import.c
@@ -2022,10 +2022,11 @@ static void ImportGrayQuantum(const Image *image,QuantumInfo *quantum_info,
   unsigned int
     pixel;
 
   assert(image != (Image *) NULL);
   assert(image->signature == MagickCoreSignature);
+  pixel=0;
   switch (quantum_info->depth)
   {
     case 1:
     {
       register Quantum
diff --git a/coders/viff.c b/coders/viff.c
index 2c72812280..bb5175ec54 100644
--- a/coders/viff.c
+++ b/coders/viff.c
@@ -135,10 +135,26 @@ static MagickBooleanType IsVIFF(const unsigned char *magick,const size_t length)
 %    o image_info: the image info.
 %
 %    o exception: return any errors or warnings in this structure.
 %
 */
+
+static MagickBooleanType CheckMemoryOverflow(const size_t count,
+  const size_t quantum)
+{
+  size_t
+    size;
+
+  size=count*quantum;
+  if ((count == 0) || (quantum != (size/count)))
+    {
+      errno=ENOMEM;
+      return(MagickTrue);
+    }
+  return(MagickFalse);
+}
+
 static Image *ReadVIFFImage(const ImageInfo *image_info,
   ExceptionInfo *exception)
 {
 #define VFF_CM_genericRGB  15
 #define VFF_CM_ntscRGB  1
@@ -473,11 +489,11 @@ static Image *ReadVIFFImage(const ImageInfo *image_info,
         ThrowReaderException(CoderError,"ColormapTypeNotSupported");
     }
     /*
       Initialize image structure.
     */
-    image->alpha_trait=viff_info.number_data_bands == 4 ? BlendPixelTrait : 
+    image->alpha_trait=viff_info.number_data_bands == 4 ? BlendPixelTrait :
       UndefinedPixelTrait;
     image->storage_class=(viff_info.number_data_bands < 3 ? PseudoClass :
       DirectClass);
     image->columns=viff_info.rows;
     image->rows=viff_info.columns;
@@ -497,13 +513,21 @@ static Image *ReadVIFFImage(const ImageInfo *image_info,
       case VFF_TYP_FLOAT: bytes_per_pixel=4; break;
       case VFF_TYP_DOUBLE: bytes_per_pixel=8; break;
       default: bytes_per_pixel=1; break;
     }
     if (viff_info.data_storage_type == VFF_TYP_BIT)
-      max_packets=((image->columns+7UL) >> 3UL)*image->rows;
+      {
+        if (CheckMemoryOverflow((image->columns+7UL) >> 3UL,image->rows) != MagickFalse)
+          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+        max_packets=((image->columns+7UL) >> 3UL)*image->rows;
+      }
     else
-      max_packets=(size_t) (number_pixels*viff_info.number_data_bands);
+      {
+        if (CheckMemoryOverflow(number_pixels,viff_info.number_data_bands) != MagickFalse)
+          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+        max_packets=(size_t) (number_pixels*viff_info.number_data_bands);
+      }
     pixels=(unsigned char *) AcquireQuantumMemory(MagickMax(number_pixels,
       max_packets),bytes_per_pixel*sizeof(*pixels));
     if (pixels == (unsigned char *) NULL)
       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
     count=ReadBlob(image,bytes_per_pixel*max_packets,pixels);
@@ -693,11 +717,11 @@ static Image *ReadVIFFImage(const ImageInfo *image_info,
               SetPixelBlue(image,ScaleCharToQuantum(*(p+2*number_pixels)),q);
               if (image->colors != 0)
                 {
                   ssize_t
                     index;
-                  
+
                   index=(ssize_t) GetPixelRed(image,q);
                   SetPixelRed(image,image->colormap[
                     ConstrainColormapIndex(image,index,exception)].red,q);
                   index=(ssize_t) GetPixelGreen(image,q);
                   SetPixelGreen(image,image->colormap[

Vulnerable code:     image->alpha_trait=viff_info.number_data_bands == 4 ? BlendPixelTrait : 
      max_packets=((image->columns+7UL) >> 3UL)*image->rows;
      max_packets=(size_t) (number_pixels*viff_info.number_data_bands);
                  
Fixed code: 
  pixel=0;

static MagickBooleanType CheckMemoryOverflow(const size_t count,
  const size_t quantum)
{
  size_t
    size;

  size=count*quantum;
  if ((count == 0) || (quantum != (size/count)))
    {
      errno=ENOMEM;
      return(MagickTrue);
    }
  return(MagickFalse);
}

    image->alpha_trait=viff_info.number_data_bands == 4 ? BlendPixelTrait :
      {
        if (CheckMemoryOverflow((image->columns+7UL) >> 3UL,image->rows) != MagickFalse)
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        max_packets=((image->columns+7UL) >> 3UL)*image->rows;
      }
      {
        if (CheckMemoryOverflow(number_pixels,viff_info.number_data_bands) != MagickFalse)
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        max_packets=(size_t) (number_pixels*viff_info.number_data_bands);
      }