CVE-2016-10066 (C, published 2017-03-03T17:59Z)
Description: value: 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 v3 base score: 5.5)
Weakness: CWE-120 \u2014 Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')
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.
Repository: https://github.com/ImageMagick/ImageMagick
Files changed:
MagickCore/Makefile.am
MagickCore/exception.c
MagickCore/memory-private.h
MagickCore/memory.c
Makefile.in
coders/label.c
coders/viff.c
configure
Commit message: Suspend exception processing if too many exceptions


Vulnerable code:
	MagickCore/accelerate.h \
	MagickCore/accelerate.h \
  while (p != (const ExceptionInfo *) NULL)
    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);

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);
}

  if (CheckMemoryOverflow(count,quantum) != MagickFalse)
  if (CheckMemoryOverflow(count,quantum) != MagickFalse)
  if (CheckMemoryOverflow(count,quantum) != MagickFalse)
  if (CheckMemoryOverflow(count,quantum) != MagickFalse)
	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.h \
	MagickCore/accelerate.h \
      image->columns=(size_t) (metrics.width+draw_info->stroke_width+0.5);
    image->columns=(size_t) (metrics.width+draw_info->stroke_width+0.5);
    image->columns=(size_t) (draw_info->pointsize+draw_info->stroke_width+0.5);
    image->rows=(size_t) (metrics.ascent-metrics.descent+
    image->rows=(size_t) (draw_info->pointsize+draw_info->stroke_width+0.5);

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);
}

        if (CheckMemoryOverflow((image->columns+7UL) >> 3UL,image->rows) != MagickFalse)
        if (CheckMemoryOverflow(number_pixels,viff_info.number_data_bands) != MagickFalse)
MAGICK_GIT_REVISION=18241:d4f277c:20160521

Fixed code:
#define MaxExceptions  128

/*
  Global declarations.
*/
  ssize_t
    i;

  for (i=0; p != (const ExceptionInfo *) NULL; i++)
    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");
MagickExport MagickBooleanType 
  HeapOverflowSanityCheck(const size_t,const size_t) magick_alloc_sizes(1,2);

  if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
  if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
  if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
+   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);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
  if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
	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 \
      image->columns=(size_t) floor(metrics.width+draw_info->stroke_width+0.5);
    image->columns=(size_t) floor(metrics.width+draw_info->stroke_width+0.5);
    image->columns=(size_t) floor(draw_info->pointsize+draw_info->stroke_width+
      0.5);
    image->rows=(size_t) floor(metrics.ascent-metrics.descent+
    image->rows=(size_t) floor(draw_info->pointsize+draw_info->stroke_width+
      0.5);
        if (HeapOverflowSanityCheck((image->columns+7UL) >> 3UL,image->rows) != MagickFalse)
        if (HeapOverflowSanityCheck(number_pixels,viff_info.number_data_bands) != MagickFalse)
MAGICK_GIT_REVISION=18293:89bfada:20160529