Commit message: https://github.com/ImageMagick/ImageMagick/issues/636
CVE: CVE-2017-12427
CWE: CWE-772
Vulnerability description: The ProcessMSLScript function in coders/msl.c in ImageMagick before 6.9.9-5 and 7.x before 7.0.6-5 allows remote attackers to cause a denial of service (memory leak) via a crafted file, related to the WriteMSLImage function.

Project: ImageMagick
File: msl.c

static void MSLUnparsedEntityDeclaration(void *context,const xmlChar *name,
  const xmlChar *public_id,const xmlChar *system_id,const xmlChar *notation)
{
  MSLInfo
    *msl_info;

  /*
    What to do when an unparsed entity declaration is parsed.
  */
  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
    "  SAX.unparsedEntityDecl(%s, %s, %s, %s)",name,
    public_id != (const xmlChar *) NULL ? (const char *) public_id : "none",
    system_id != (const xmlChar *) NULL ? (const char *) system_id : "none",
    notation);
  msl_info=(MSLInfo *) context;
  (void) xmlAddDocEntity(msl_info->document,name,
    XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,public_id,system_id,notation);

}

Project: ImageMagick
File: msl.c

static void MSLWarning(void *context,const char *format,...)
{
  char
    *message,
    reason[MagickPathExtent];

  MSLInfo
    *msl_info;

  va_list
    operands;

  /**
    Display and format a warning messages, gives file, line, position and
    extra parameters.
  */
  va_start(operands,format);
  (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  SAX.warning: ");
  (void) LogMagickEvent(CoderEvent,GetMagickModule(),format,operands);
  msl_info=(MSLInfo *) context;
  (void) msl_info;
#if !defined(MAGICKCORE_HAVE_VSNPRINTF)
  (void) vsprintf(reason,format,operands);
#else
  (void) vsnprintf(reason,MagickPathExtent,format,operands);
#endif
  message=GetExceptionMessage(errno);
  ThrowMSLException(CoderError,reason,message);
  message=DestroyString(message);
  va_end(operands);
}

Project: ImageMagick
File: msl.c

static Image *ReadMSLImage(const ImageInfo *image_info,ExceptionInfo *exception)
{
  Image
    *image;

  /*
    Open image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickCoreSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickCoreSignature);
  image=(Image *) NULL;
  (void) ProcessMSLScript(image_info,&image,exception);
  return(GetFirstImageInList(image));
}

Project: ImageMagick
File: msl.c

ModuleExport size_t RegisterMSLImage(void)
{
  MagickInfo
    *entry;

#if defined(MAGICKCORE_XML_DELEGATE)
  xmlInitParser();
#endif
  entry=AcquireMagickInfo("MSL","MSL","Magick Scripting Language");
#if defined(MAGICKCORE_XML_DELEGATE)
  entry->decoder=(DecodeImageHandler *) ReadMSLImage;
  entry->encoder=(EncodeImageHandler *) WriteMSLImage;
#endif
  entry->format_type=ImplicitFormatType;
  (void) RegisterMagickInfo(entry);
  return(MagickImageCoderSignature);
}

Project: ImageMagick
File: msl.c

static MagickBooleanType SetMSLAttributes(MSLInfo *msl_info,const char *keyword,
  const char *value)
{
  Image
    *attributes;

  DrawInfo
    *draw_info;

  ExceptionInfo
    *exception;

  GeometryInfo
    geometry_info;

  Image
    *image;

  ImageInfo
    *image_info;

  int
    flags;

  ssize_t
    n;

  assert(msl_info != (MSLInfo *) NULL);
  if (keyword == (const char *) NULL)
    return(MagickTrue);
  if (value == (const char *) NULL)
    return(MagickTrue);
  exception=msl_info->exception;
  n=msl_info->n;
  attributes=msl_info->attributes[n];
  image_info=msl_info->image_info[n];
  draw_info=msl_info->draw_info[n];
  image=msl_info->image[n];
  switch (*keyword)
  {
    case 'A':
    case 'a':
    {
      if (LocaleCompare(keyword,"adjoin") == 0)
        {
          ssize_t
            adjoin;

          adjoin=ParseCommandOption(MagickBooleanOptions,MagickFalse,value);
          if (adjoin < 0)
            ThrowMSLException(OptionError,"UnrecognizedType",value);
          image_info->adjoin=(MagickBooleanType) adjoin;
          break;
        }
      if (LocaleCompare(keyword,"alpha") == 0)
        {
          ssize_t
            alpha;

          alpha=ParseCommandOption(MagickAlphaChannelOptions,MagickFalse,value);
          if (alpha < 0)
            ThrowMSLException(OptionError,"UnrecognizedType",value);
          if (image != (Image *) NULL)
            (void) SetImageAlphaChannel(image,(AlphaChannelOption) alpha,
              exception);
          break;
        }
      if (LocaleCompare(keyword,"antialias") == 0)
        {
          ssize_t
            antialias;

          antialias=ParseCommandOption(MagickBooleanOptions,MagickFalse,value);
          if (antialias < 0)
            ThrowMSLException(OptionError,"UnrecognizedGravityType",value);
          image_info->antialias=(MagickBooleanType) antialias;
          break;
        }
      if (LocaleCompare(keyword,"area-limit") == 0)
        {
          MagickSizeType
            limit;

          limit=MagickResourceInfinity;
          if (LocaleCompare(value,"unlimited") != 0)
            limit=(MagickSizeType) StringToDoubleInterval(value,100.0);
          (void) SetMagickResourceLimit(AreaResource,limit);
          break;
        }
      if (LocaleCompare(keyword,"attenuate") == 0)
        {
          (void) SetImageOption(image_info,keyword,value);
          break;
        }
      if (LocaleCompare(keyword,"authenticate") == 0)
        {
          (void) CloneString(&image_info->density,value);
          break;
        }
      ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
      break;
    }
    case 'B':
    case 'b':
    {
      if (LocaleCompare(keyword,"background") == 0)
        {
          (void) QueryColorCompliance(value,AllCompliance,
            &image_info->background_color,exception);
          break;
        }
      if (LocaleCompare(keyword,"blue-primary") == 0)
        {
          if (image == (Image *) NULL)
            break;
          flags=ParseGeometry(value,&geometry_info);
          image->chromaticity.blue_primary.x=geometry_info.rho;
          image->chromaticity.blue_primary.y=geometry_info.sigma;
          if ((flags & SigmaValue) == 0)
            image->chromaticity.blue_primary.y=
              image->chromaticity.blue_primary.x;
          break;
        }
      if (LocaleCompare(keyword,"bordercolor") == 0)
        {
          (void) QueryColorCompliance(value,AllCompliance,
            &image_info->border_color,exception);
          break;
        }
      ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
      break;
    }
    case 'D':
    case 'd':
    {
      if (LocaleCompare(keyword,"density") == 0)
        {
          (void) CloneString(&image_info->density,value);
          (void) CloneString(&draw_info->density,value);
          break;
        }
      ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
      break;
    }
    case 'F':
    case 'f':
    {
      if (LocaleCompare(keyword,"fill") == 0)
        {
          (void) QueryColorCompliance(value,AllCompliance,&draw_info->fill,
            exception);
          (void) SetImageOption(image_info,keyword,value);
          break;
        }
      if (LocaleCompare(keyword,"filename") == 0)
        {
          (void) CopyMagickString(image_info->filename,value,MagickPathExtent);
          break;
        }
      ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
      break;
    }
    case 'G':
    case 'g':
    {
      if (LocaleCompare(keyword,"gravity") == 0)
        {
          ssize_t
            gravity;

          gravity=ParseCommandOption(MagickGravityOptions,MagickFalse,value);
          if (gravity < 0)
            ThrowMSLException(OptionError,"UnrecognizedGravityType",value);
          (void) SetImageOption(image_info,keyword,value);
          break;
        }
      ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
      break;
    }
    case 'I':
    case 'i':
    {
      if (LocaleCompare(keyword,"id") == 0)
        {
          (void) SetImageProperty(attributes,keyword,value,exception);
          break;
        }
      ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
      break;
    }
    case 'M':
    case 'm':
    {
      if (LocaleCompare(keyword,"magick") == 0)
        {
          (void) CopyMagickString(image_info->magick,value,MagickPathExtent);
          break;
        }
      if (LocaleCompare(keyword,"mattecolor") == 0)
        {
          (void) QueryColorCompliance(value,AllCompliance,
            &image_info->matte_color,exception);
          break;
        }
      ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
      break;
    }
    case 'P':
    case 'p':
    {
      if (LocaleCompare(keyword,"pointsize") == 0)
        {
          image_info->pointsize=StringToDouble(value,(char **) NULL);
          draw_info->pointsize=StringToDouble(value,(char **) NULL);
          break;
        }
      ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
      break;
    }
    case 'Q':
    case 'q':
    {
      if (LocaleCompare(keyword,"quality") == 0)
        {
          image_info->quality=StringToLong(value);
          if (image == (Image *) NULL)
            break;
          image->quality=StringToLong(value);
          break;
        }
      break;
    }
    case 'S':
    case 's':
    {
      if (LocaleCompare(keyword,"size") == 0)
        {
          (void) CloneString(&image_info->size,value);
          break;
        }
      if (LocaleCompare(keyword,"stroke") == 0)
        {
          (void) QueryColorCompliance(value,AllCompliance,&draw_info->stroke,
            exception);
          (void) SetImageOption(image_info,keyword,value);
          break;
        }
      ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
      break;
    }
    default:
    {
      ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
      break;
    }
  }
  return(MagickTrue);
}

Project: ImageMagick
File: msl.c

ModuleExport void UnregisterMSLImage(void)
{
  (void) UnregisterMagickInfo("MSL");
#if defined(MAGICKCORE_XML_DELEGATE)
  xmlCleanupParser();
#endif
}

Project: ImageMagick
File: msl.c

static MagickBooleanType WriteMSLImage(const ImageInfo *image_info,Image *image,
  ExceptionInfo *exception)
{
  Image
    *msl_image;

  MagickBooleanType
    status;

  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickCoreSignature);
  assert(image != (Image *) NULL);
  assert(image->signature == MagickCoreSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  msl_image=CloneImage(image,0,0,MagickTrue,exception);
  status=ProcessMSLScript(image_info,&msl_image,exception);
  if (msl_image != (Image *) NULL)
    msl_image=DestroyImage(msl_image);
  return(status);
}