CVE-2016-7514 (published 2017-04-20T18:59Z)

The ReadPSDChannelPixels function in coders/psd.c in ImageMagick allows remote attackers to cause a denial of service (out-of-bounds read) via a crafted PSD file.

Severity: MEDIUM
CVSS v2 base score: 4.3 (AV:N/AC:M/Au:N/C:N/I:N/A:P)
CVSS v3 base score: 6.5, MEDIUM (CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-125
cwe_name: Out-of-bounds Read
description: The product reads data past the end, or before the beginning, of the intended buffer.
extended_description: 
            
            
             
			 
         
         

Fix information:
repo_url: https://github.com/ImageMagick/ImageMagick
commit_details: repo_url: https://github.com/ImageMagick/ImageMagick
author: dirk
author_date: 2016-01-15 01:27:31+01:00
msg: Added missing call to ConstrainColormapIndex.
repository: repo_url: https://github.com/ImageMagick/ImageMagick
repo_name: ImageMagick/ImageMagick
description: 🧙‍♂️ ImageMagick 7
repo_language: C
owner: ImageMagick
file_changes: filename: psd.c
change_type: ModificationType.MODIFY
diff: @@ -835,7 +835,8 @@ static MagickBooleanType ReadPSDChannelPixels(Image *image,
                   SetPixelIndex(image,(((unsigned char) pixel) &
                     (0x01 << (7-bit))) != 0 ? 0 : 255,q);
                   SetPixelViaPixelInfo(image,image->colormap+(ssize_t)
-                    GetPixelIndex(image,q),q);
+                    ConstrainColormapIndex(image,GetPixelIndex(image,q),
+                      exception),q);
                   q+=GetPixelChannels(image);
                   x++;
                 }

programming_language: Objective-C
repo_url: https://github.com/ImageMagick/ImageMagick
commit_details: repo_url: https://github.com/ImageMagick/ImageMagick
author: dirk
author_date: 2016-01-15 01:13:19+01:00
msg: Fixed overflow.
repository: repo_url: https://github.com/ImageMagick/ImageMagick
repo_name: ImageMagick/ImageMagick
description: 🧙‍♂️ ImageMagick 7
repo_language: C
owner: ImageMagick
file_changes: filename: psd.c
change_type: ModificationType.MODIFY
diff: @@ -2363,8 +2363,8 @@ static MagickBooleanType WriteImageChannels(const PSDInfo *psd_info,
   compact_pixels=(unsigned char *) NULL;
   if (next_image->compression == RLECompression)
     {
-      compact_pixels=(unsigned char *) AcquireQuantumMemory(2*channels*
-        next_image->columns,packet_size*sizeof(*compact_pixels));
+      compact_pixels=(unsigned char *) AcquireQuantumMemory((2*channels*
+        next_image->columns)+1,packet_size*sizeof(*compact_pixels));
       if (compact_pixels == (unsigned char *) NULL)
         ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
     }

programming_language: Objective-C
repo_url: https://github.com/ImageMagick/ImageMagick
commit_details: repo_url: https://github.com/ImageMagick/ImageMagick
author: dirk
author_date: 2016-01-16 00:07:51+01:00
msg: Rewrite reading pixel values.
repository: repo_url: https://github.com/ImageMagick/ImageMagick
repo_name: ImageMagick/ImageMagick
description: 🧙‍♂️ ImageMagick 7
repo_language: C
owner: ImageMagick
file_changes: filename: psd.c
change_type: ModificationType.MODIFY
diff: @@ -764,6 +764,72 @@ static inline void ReversePSDString(Image *image,char *p,size_t length)
   }
 }
 
+static inline void SetPSDPixel(Image *image,const size_t channels,
+  const ssize_t type,const size_t packet_size,const Quantum pixel,Quantum *q,
+  ExceptionInfo *exception)
+{
+  if (image->storage_class == PseudoClass)
+    {
+      if (packet_size == 1)
+        SetPixelIndex(image,ScaleQuantumToChar(pixel),q);
+      else
+        SetPixelIndex(image,ScaleQuantumToShort(pixel),q);
+      SetPixelViaPixelInfo(image,image->colormap+(ssize_t)
+        ConstrainColormapIndex(image,GetPixelIndex(image,q),exception),q);
+      return;
+    }
+  switch (type)
+  {
+    case -1:
+    {
+      SetPixelAlpha(image, pixel,q);
+      break;
+    }
+    case -2:
+    case 0:
+    {
+      SetPixelRed(image,pixel,q);
+      if (channels == 1 || type == -2)
+        SetPixelGray(image,pixel,q);
+      break;
+    }
+    case 1:
+    {
+      if (image->storage_class == PseudoClass)
+        SetPixelAlpha(image,pixel,q);
+      else
+        SetPixelGreen(image,pixel,q);
+      break;
+    }
+    case 2:
+    {
+      if (image->storage_class == PseudoClass)
+        SetPixelAlpha(image,pixel,q);
+      else
+        SetPixelBlue(image,pixel,q);
+      break;
+    }
+    case 3:
+    {
+      if (image->colorspace == CMYKColorspace)
+        SetPixelBlack(image,pixel,q);
+      else
+        if (image->alpha_trait != UndefinedPixelTrait)
+          SetPixelAlpha(image,pixel,q);
+      break;
+    }
+    case 4:
+    {
+      if ((IssRGBCompatibleColorspace(image->colorspace) != MagickFalse) &&
+          (channels > 3))
+        break;
+      if (image->alpha_trait != UndefinedPixelTrait)
+        SetPixelAlpha(image,pixel,q);
+      break;
+    }
+  }
+}
+
 static MagickBooleanType ReadPSDChannelPixels(Image *image,
   const size_t channels,const size_t row,const ssize_t type,
   const unsigned char *pixels,ExceptionInfo *exception)
@@ -800,90 +866,31 @@ static MagickBooleanType ReadPSDChannelPixels(Image *image,
         p=PushShortPixel(MSBEndian,p,&nibble);
         pixel=ScaleShortToQuantum(nibble);
       }
-    switch (type)
-    {
-      case -1:
+    if (image->depth > 1)
       {
-        SetPixelAlpha(image,pixel,q);
-        break;
+        SetPSDPixel(image,channels,type,packet_size,pixel,q,exception);
+        q+=GetPixelChannels(image);
       }
-      case -2:
-      case 0:
-      {
-        SetPixelRed(image,pixel,q);
-        if (channels == 1 || type == -2)
-          SetPixelGray(image,pixel,q);
-        if (image->storage_class == PseudoClass)
-          {
-            if (packet_size == 1)
-              SetPixelIndex(image,ScaleQuantumToChar(pixel),q);
-            else
-              SetPixelIndex(image,ScaleQuantumToShort(pixel),q);
-            SetPixelViaPixelInfo(image,image->colormap+(ssize_t)
-              ConstrainColormapIndex(image,GetPixelIndex(image,q),exception),q);
-            if (image->depth == 1)
-              {
-                ssize_t
-                  bit,
-                  number_bits;
-  
-                number_bits=image->columns-x;
-                if (number_bits > 8)
-                  number_bits=8;
-                for (bit=0; bit < number_bits; bit++)
-                {
-                  SetPixelIndex(image,(((unsigned char) pixel) &
-                    (0x01 << (7-bit))) != 0 ? 0 : 255,q);
-                  SetPixelViaPixelInfo(image,image->colormap+(ssize_t)
-                    ConstrainColormapIndex(image,GetPixelIndex(image,q),
-                      exception),q);
-                  q+=GetPixelChannels(image);
-                  x++;
-                }
-                x--;
-                continue;
-              }
-          }
-        break;
-      }
-      case 1:
-      {
-        if (image->storage_class == PseudoClass)
-          SetPixelAlpha(image,pixel,q);
-        else
-          SetPixelGreen(image,pixel,q);
-        break;
-      }
-      case 2:
-      {
-        if (image->storage_class == PseudoClass)
-          SetPixelAlpha(image,pixel,q);
-        else
-          SetPixelBlue(image,pixel,q);
-        break;
-      }
-      case 3:
-      {
-        if (image->colorspace == CMYKColorspace)
-          SetPixelBlack(image,pixel,q);
-        else
-          if (image->alpha_trait != UndefinedPixelTrait)
-            SetPixelAlpha(image,pixel,q);
-        break;
-      }
-      case 4:
+    else
       {
-        if ((IssRGBCompatibleColorspace(image->colorspace) != MagickFalse) &&
-            (channels > 3))
-          break;
-        if (image->alpha_trait != UndefinedPixelTrait)
-          SetPixelAlpha(image,pixel,q);
-        break;
+        ssize_t
+          bit,
+          number_bits;
+      
+        number_bits=image->columns-x;
+        if (number_bits > 8)
+          number_bits=8;
+        for (bit = 0; bit < number_bits; bit++)
+        {
+          SetPSDPixel(image,channels,type,packet_size,(((unsigned char) pixel)
+            & (0x01 << (7-bit))) != 0 ? 0 : 255,q,exception);
+          q+=GetPixelChannels(image);
+          x++;
+        }
+        if (x != image->columns)
+          x--;
+        continue;
       }
-      default:
-        break;
-    }
-    q+=GetPixelChannels(image);
   }
   return(SyncAuthenticPixels(image,exception));
 }

programming_language: Objective-C
repo_url: https://github.com/ImageMagick/ImageMagick
commit_details: repo_url: https://github.com/ImageMagick/ImageMagick
author: dirk
author_date: 2016-01-15 11:17:30+01:00
msg: Added check for bit depth 1.
repository: repo_url: https://github.com/ImageMagick/ImageMagick
repo_name: ImageMagick/ImageMagick
description: 🧙‍♂️ ImageMagick 7
repo_language: C
owner: ImageMagick
file_changes: filename: psd.c
change_type: ModificationType.MODIFY
diff: @@ -1908,6 +1908,8 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception)
           image->alpha_trait=UndefinedPixelTrait;
         }
     }
+  if ((image->depth == 1) && (image->storage_class != PseudoClass))
+    ThrowReaderException(CorruptImageError, "ImproperImageHeader");
   has_merged_image=MagickTrue;
   length=ReadBlobMSBLong(image);
   if (length != 0)

programming_language: Objective-C