CVE-2016-10066 (published 2017-03-03T17:59Z)

Buffer overflow in the ReadVIFFImage function in coders/viff.c in ImageMagick before 6.9.4-5 allows remote attackers to cause a denial of service (application crash) via a crafted 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: 5.5, MEDIUM (CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-120
cwe_name: Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')
description: The product copies an input buffer to an output buffer without verifying that the size of the input buffer is less than the size of the output buffer, leading to a buffer overflow.
extended_description: A buffer overflow condition exists when a product attempts to put more data in a buffer than it can hold, or when it attempts to put data in a memory area outside of the boundaries of a buffer. The simplest type of error, and the most common cause of buffer overflows, is the "classic" case in which the product copies the buffer without restricting how much is copied. Other variants exist, but the existence of a classic overflow strongly suggests that the programmer is not considering even the most basic of security protections.
         

Fix information:
repo_url: https://github.com/ImageMagick/ImageMagick
commit_details: repo_url: https://github.com/ImageMagick/ImageMagick
author: Cristy
author_date: 2016-05-29 11:36:47-04:00
msg: Suspend exception processing if too many exceptions
repository: repo_url: https://github.com/ImageMagick/ImageMagick
repo_name: ImageMagick/ImageMagick
description: 🧙‍♂️ ImageMagick 7
repo_language: C
owner: ImageMagick
file_changes: filename: Makefile.am
change_type: ModificationType.MODIFY
diff: @@ -65,7 +65,6 @@ MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la_DEPENDENC
 MAGICKCORE_BASE_SRCS = \
 	MagickCore/MagickCore.h \
 	MagickCore/accelerate.c \
-	MagickCore/accelerate.h \
 	MagickCore/accelerate-private.h \
 	MagickCore/animate.c \
 	MagickCore/animate.h \
@@ -313,7 +312,6 @@ endif # if WIN32_NATIVE_BUILD
 
 MAGICKCORE_INCLUDE_HDRS = \
 	MagickCore/MagickCore.h \
-	MagickCore/accelerate.h \
 	MagickCore/animate.h \
 	MagickCore/annotate.h \
 	MagickCore/artifact.h \

programming_language: Go
filename: exception.c
change_type: ModificationType.MODIFY
diff: @@ -72,6 +72,11 @@ static void
 /*
   Global declarations.
 */
+#define MaxExceptions  128
+
+/*
+  Global declarations.
+*/
 static ErrorHandler
   error_handler = DefaultErrorHandler;
 
@@ -194,6 +199,9 @@ MagickExport void CatchException(ExceptionInfo *exception)
   register const ExceptionInfo
     *p;
 
+  ssize_t
+    i;
+
   assert(exception != (ExceptionInfo *) NULL);
   assert(exception->signature == MagickCoreSignature);
   if (exception->exceptions  == (void *) NULL)
@@ -202,12 +210,20 @@ MagickExport void CatchException(ExceptionInfo *exception)
   ResetLinkedListIterator((LinkedListInfo *) exception->exceptions);
   p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
     exception->exceptions);
-  while (p != (const ExceptionInfo *) NULL)
+  for (i=0; p != (const ExceptionInfo *) NULL; i++)
   {
-    if ((p->severity >= WarningException) && (p->severity < ErrorException))
-      MagickWarning(p->severity,p->reason,p->description);
-    if ((p->severity >= ErrorException) && (p->severity < FatalErrorException))
-      MagickError(p->severity,p->reason,p->description);
+    if (i < MaxExceptions)
+      {
+        if ((p->severity >= WarningException) && (p->severity < ErrorException))
+          MagickWarning(p->severity,p->reason,p->description);
+        if ((p->severity >= ErrorException) &&
+            (p->severity < FatalErrorException))
+          MagickError(p->severity,p->reason,p->description);
+      }
+    else
+      if (i == MaxExceptions)
+        MagickError(ResourceLimitError,"too many exceptions",
+          "exception processing is suspended");
     if (p->severity >= FatalErrorException)
       MagickFatalError(p->severity,p->reason,p->description);
     p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)

programming_language: Matlab
filename: memory-private.h
change_type: ModificationType.MODIFY
diff: @@ -42,6 +42,9 @@ extern "C" {
 #define MagickAssumeAligned(address)  (address)
 #endif
 
+MagickExport MagickBooleanType 
+  HeapOverflowSanityCheck(const size_t,const size_t) magick_alloc_sizes(1,2);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif

programming_language: C++
filename: memory.c
change_type: ModificationType.MODIFY
diff: @@ -233,22 +233,6 @@ static MagickBooleanType
 %    o quantum: the number of bytes in each quantum.
 %
 */
-
-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);
-}
-
 MagickExport void *AcquireAlignedMemory(const size_t count,const size_t quantum)
 {
 #define AlignedExtent(size,alignment) \
@@ -262,7 +246,7 @@ MagickExport void *AcquireAlignedMemory(const size_t count,const size_t quantum)
   void
     *memory;
 
-  if (CheckMemoryOverflow(count,quantum) != MagickFalse)
+  if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
     return((void *) NULL);
   memory=NULL;
   alignment=CACHE_LINE_SIZE;
@@ -543,7 +527,7 @@ MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
   size_t
     extent;
 
-  if (CheckMemoryOverflow(count,quantum) != MagickFalse)
+  if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
     return((void *) NULL);
   extent=count*quantum;
   return(AcquireMagickMemory(extent));
@@ -583,7 +567,7 @@ MagickExport MemoryInfo *AcquireVirtualMemory(const size_t count,
   size_t
     extent;
 
-  if (CheckMemoryOverflow(count,quantum) != MagickFalse)
+  if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
     return((MemoryInfo *) NULL);
   memory_info=(MemoryInfo *) MagickAssumeAligned(AcquireAlignedMemory(1,
     sizeof(*memory_info)));
@@ -916,6 +900,45 @@ MagickExport void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
 %                                                                             %
 %                                                                             %
 %                                                                             %
++   H e a p O v e r f l o w S a n i t y C h e c k                             %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  HeapOverflowSanityCheck() returns MagickTrue if the heap allocation request
+%  does not exceed the maximum limits of a size_t otherwise MagickFalse.
+%
+%  The format of the HeapOverflowSanityCheck method is:
+%
+%      MagickBooleanType HeapOverflowSanityCheck(const size_t count,
+%        const size_t quantum)
+%
+%  A description of each parameter follows:
+%
+%    o size: the size of the memory in bytes we require.
+%
+*/
+MagickExport MagickBooleanType HeapOverflowSanityCheck(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);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %   R e l i n q u i s h A l i g n e d M e m o r y                             %
 %                                                                             %
 %                                                                             %
@@ -1221,7 +1244,7 @@ MagickExport void *ResizeQuantumMemory(void *memory,const size_t count,
   size_t
     extent;
 
-  if (CheckMemoryOverflow(count,quantum) != MagickFalse)
+  if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
     {
       memory=RelinquishMagickMemory(memory);
       return((void *) NULL);

programming_language: Objective-C
filename: Makefile.in
change_type: ModificationType.MODIFY
diff: @@ -391,35 +391,34 @@ Magick___lib_libMagick___@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la_LINK =  \
 am__DEPENDENCIES_1 =
 am__MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la_SOURCES_DIST =  \
 	MagickCore/MagickCore.h MagickCore/accelerate.c \
-	MagickCore/accelerate.h MagickCore/accelerate-private.h \
-	MagickCore/animate.c MagickCore/animate.h \
-	MagickCore/animate-private.h MagickCore/annotate.c \
-	MagickCore/annotate.h MagickCore/artifact.c \
-	MagickCore/artifact.h MagickCore/attribute.c \
-	MagickCore/attribute.h MagickCore/blob.c MagickCore/blob.h \
-	MagickCore/blob-private.h MagickCore/cache.c \
-	MagickCore/cache.h MagickCore/cache-private.h \
-	MagickCore/cache-view.c MagickCore/cache-view.h \
-	MagickCore/channel.c MagickCore/channel.h MagickCore/cipher.c \
-	MagickCore/cipher.h MagickCore/client.c MagickCore/client.h \
-	MagickCore/coder.c MagickCore/coder.h MagickCore/color.c \
-	MagickCore/color.h MagickCore/color-private.h \
-	MagickCore/colormap.c MagickCore/colormap.h \
-	MagickCore/colormap-private.h MagickCore/colorspace.c \
-	MagickCore/colorspace.h MagickCore/colorspace-private.h \
-	MagickCore/compare.c MagickCore/compare.h \
-	MagickCore/composite.c MagickCore/composite.h \
-	MagickCore/composite-private.h MagickCore/compress.c \
-	MagickCore/compress.h MagickCore/configure.c \
-	MagickCore/configure.h MagickCore/constitute.c \
-	MagickCore/constitute.h MagickCore/decorate.c \
-	MagickCore/decorate.h MagickCore/delegate.c \
-	MagickCore/delegate.h MagickCore/delegate-private.h \
-	MagickCore/deprecate.c MagickCore/deprecate.h \
-	MagickCore/display.c MagickCore/display.h \
-	MagickCore/display-private.h MagickCore/distort.c \
-	MagickCore/distort.h MagickCore/distribute-cache.c \
-	MagickCore/distribute-cache.h \
+	MagickCore/accelerate-private.h MagickCore/animate.c \
+	MagickCore/animate.h MagickCore/animate-private.h \
+	MagickCore/annotate.c MagickCore/annotate.h \
+	MagickCore/artifact.c MagickCore/artifact.h \
+	MagickCore/attribute.c MagickCore/attribute.h \
+	MagickCore/blob.c MagickCore/blob.h MagickCore/blob-private.h \
+	MagickCore/cache.c MagickCore/cache.h \
+	MagickCore/cache-private.h MagickCore/cache-view.c \
+	MagickCore/cache-view.h MagickCore/channel.c \
+	MagickCore/channel.h MagickCore/cipher.c MagickCore/cipher.h \
+	MagickCore/client.c MagickCore/client.h MagickCore/coder.c \
+	MagickCore/coder.h MagickCore/color.c MagickCore/color.h \
+	MagickCore/color-private.h MagickCore/colormap.c \
+	MagickCore/colormap.h MagickCore/colormap-private.h \
+	MagickCore/colorspace.c MagickCore/colorspace.h \
+	MagickCore/colorspace-private.h MagickCore/compare.c \
+	MagickCore/compare.h MagickCore/composite.c \
+	MagickCore/composite.h MagickCore/composite-private.h \
+	MagickCore/compress.c MagickCore/compress.h \
+	MagickCore/configure.c MagickCore/configure.h \
+	MagickCore/constitute.c MagickCore/constitute.h \
+	MagickCore/decorate.c MagickCore/decorate.h \
+	MagickCore/delegate.c MagickCore/delegate.h \
+	MagickCore/delegate-private.h MagickCore/deprecate.c \
+	MagickCore/deprecate.h MagickCore/display.c \
+	MagickCore/display.h MagickCore/display-private.h \
+	MagickCore/distort.c MagickCore/distort.h \
+	MagickCore/distribute-cache.c MagickCore/distribute-cache.h \
 	MagickCore/distribute-cache-private.h MagickCore/draw.c \
 	MagickCore/draw.h MagickCore/draw-private.h \
 	MagickCore/effect.c MagickCore/effect.h MagickCore/enhance.c \
@@ -4141,7 +4140,6 @@ MagickCore_libMagickCore_@MAGICK_MAJOR_VERSION@_@MAGICK_ABI_SUFFIX@_la_DEPENDENC
 MAGICKCORE_BASE_SRCS = \
 	MagickCore/MagickCore.h \
 	MagickCore/accelerate.c \
-	MagickCore/accelerate.h \
 	MagickCore/accelerate-private.h \
 	MagickCore/animate.c \
 	MagickCore/animate.h \
@@ -4384,7 +4382,6 @@ MAGICKCORE_BASE_SRCS = \
 
 MAGICKCORE_INCLUDE_HDRS = \
 	MagickCore/MagickCore.h \
-	MagickCore/accelerate.h \
 	MagickCore/animate.h \
 	MagickCore/annotate.h \
 	MagickCore/artifact.h \

programming_language: Shell
filename: label.c
change_type: ModificationType.MODIFY
diff: @@ -136,7 +136,7 @@ static Image *ReadLABELImage(const ImageInfo *image_info,
   status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
   if ((image->columns == 0) && (image->rows == 0))
     {
-      image->columns=(size_t) (metrics.width+draw_info->stroke_width+0.5);
+      image->columns=(size_t) floor(metrics.width+draw_info->stroke_width+0.5);
       image->rows=(size_t) floor(metrics.height+draw_info->stroke_width+0.5);
     }
   else
@@ -204,14 +204,16 @@ static Image *ReadLABELImage(const ImageInfo *image_info,
        return((Image *) NULL);
      }
   if (image->columns == 0)
-    image->columns=(size_t) (metrics.width+draw_info->stroke_width+0.5);
+    image->columns=(size_t) floor(metrics.width+draw_info->stroke_width+0.5);
   if (image->columns == 0)
-    image->columns=(size_t) (draw_info->pointsize+draw_info->stroke_width+0.5);
+    image->columns=(size_t) floor(draw_info->pointsize+draw_info->stroke_width+
+      0.5);
   if (image->rows == 0)
-    image->rows=(size_t) (metrics.ascent-metrics.descent+
+    image->rows=(size_t) floor(metrics.ascent-metrics.descent+
       draw_info->stroke_width+0.5);
   if (image->rows == 0)
-    image->rows=(size_t) (draw_info->pointsize+draw_info->stroke_width+0.5);
+    image->rows=(size_t) floor(draw_info->pointsize+draw_info->stroke_width+
+      0.5);
   status=SetImageExtent(image,image->columns,image->rows,exception);
   if (status == MagickFalse)
     {

programming_language: Objective-C
filename: viff.c
change_type: ModificationType.MODIFY
diff: @@ -137,22 +137,6 @@ static MagickBooleanType IsVIFF(const unsigned char *magick,const size_t length)
 %    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)
 {
@@ -516,13 +500,13 @@ static Image *ReadVIFFImage(const ImageInfo *image_info,
     }
     if (viff_info.data_storage_type == VFF_TYP_BIT)
       {
-        if (CheckMemoryOverflow((image->columns+7UL) >> 3UL,image->rows) != MagickFalse)
+        if (HeapOverflowSanityCheck((image->columns+7UL) >> 3UL,image->rows) != MagickFalse)
           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
         max_packets=((image->columns+7UL) >> 3UL)*image->rows;
       }
     else
       {
-        if (CheckMemoryOverflow(number_pixels,viff_info.number_data_bands) != MagickFalse)
+        if (HeapOverflowSanityCheck(number_pixels,viff_info.number_data_bands) != MagickFalse)
           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
         max_packets=(size_t) (number_pixels*viff_info.number_data_bands);
       }

programming_language: Objective-C
filename: configure
change_type: ModificationType.MODIFY
diff: @@ -4515,7 +4515,7 @@ MAGICK_PATCHLEVEL_VERSION=7
 
 MAGICK_VERSION=7.0.1-7
 
-MAGICK_GIT_REVISION=18241:d4f277c:20160521
+MAGICK_GIT_REVISION=18293:89bfada:20160529
 
 
 # Substitute library versioning

programming_language: Shell