Commit message: https://github.com/ImageMagick/ImageMagick/issues/1199
CVE: CVE-2018-16643
CWE: CWE-20
Vulnerability description: The functions ReadDCMImage in coders/dcm.c, ReadPWPImage in coders/pwp.c, ReadCALSImage in coders/cals.c, and ReadPICTImage in coders/pict.c in ImageMagick 7.0.8-4 do not check the return value of the fputc function, which allows remote attackers to cause a denial of service via a crafted image file.

Project: ImageMagick
File: cals.c

ModuleExport size_t RegisterCALSImage(void)
{
#define CALSDescription  "Continuous Acquisition and Life-cycle Support Type 1"
#define CALSNote  "Specified in MIL-R-28002 and MIL-PRF-28002"

  MagickInfo
    *entry;

  entry=AcquireMagickInfo("CALS","CAL",CALSDescription);
  entry->decoder=(DecodeImageHandler *) ReadCALSImage;
#if defined(MAGICKCORE_TIFF_DELEGATE)
  entry->encoder=(EncodeImageHandler *) WriteCALSImage;
#endif
  entry->flags^=CoderAdjoinFlag;
  entry->magick=(IsImageFormatHandler *) IsCALS;
  entry->note=ConstantString(CALSNote);
  (void) RegisterMagickInfo(entry);
  entry=AcquireMagickInfo("CALS","CALS",CALSDescription);
  entry->decoder=(DecodeImageHandler *) ReadCALSImage;
#if defined(MAGICKCORE_TIFF_DELEGATE)
  entry->encoder=(EncodeImageHandler *) WriteCALSImage;
#endif
  entry->flags^=CoderAdjoinFlag;
  entry->magick=(IsImageFormatHandler *) IsCALS;
  entry->note=ConstantString(CALSNote);
  (void) RegisterMagickInfo(entry);
  return(MagickImageCoderSignature);
}

Project: ImageMagick
File: cals.c

static MagickBooleanType WriteCALSImage(const ImageInfo *image_info,
  Image *image,ExceptionInfo *exception)
{
  char
    header[129];

  Image
    *group4_image;

  ImageInfo
    *write_info;

  MagickBooleanType
    status;

  register ssize_t
    i;

  size_t
    density,
    length,
    orient_x,
    orient_y;

  ssize_t
    count;

  unsigned char
    *group4;

  /*
    Open output image file.
  */
  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);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickCoreSignature);
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
  if (status == MagickFalse)
    return(status);
  /*
    Create standard CALS header.
  */
  count=WriteCALSRecord(image,"srcdocid: NONE");
  (void) count;
  count=WriteCALSRecord(image,"dstdocid: NONE");
  count=WriteCALSRecord(image,"txtfilid: NONE");
  count=WriteCALSRecord(image,"figid: NONE");
  count=WriteCALSRecord(image,"srcgph: NONE");
  count=WriteCALSRecord(image,"doccls: NONE");
  count=WriteCALSRecord(image,"rtype: 1");
  orient_x=0;
  orient_y=0;
  switch (image->orientation)
  {
    case TopRightOrientation:
    {
      orient_x=180;
      orient_y=270;
      break;
    }
    case BottomRightOrientation:
    {
      orient_x=180;
      orient_y=90;
      break;
    }
    case BottomLeftOrientation:
    {
      orient_y=90;
      break;
    }
    case LeftTopOrientation:
    {
      orient_x=270;
      break;
    }
    case RightTopOrientation:
    {
      orient_x=270;
      orient_y=180;
      break;
    }
    case RightBottomOrientation:
    {
      orient_x=90;
      orient_y=180;
      break;
    }
    case LeftBottomOrientation:
    {
      orient_x=90;
      break;
    }
    default:
    {
      orient_y=270;
      break;
    }
  }
  (void) FormatLocaleString(header,sizeof(header),"rorient: %03ld,%03ld",
    (long) orient_x,(long) orient_y);
  count=WriteCALSRecord(image,header);
  (void) FormatLocaleString(header,sizeof(header),"rpelcnt: %06lu,%06lu",
    (unsigned long) image->columns,(unsigned long) image->rows);
  count=WriteCALSRecord(image,header);  
  density=200;
  if (image_info->density != (char *) NULL)
    {
      GeometryInfo
        geometry_info;

      (void) ParseGeometry(image_info->density,&geometry_info);
      density=(size_t) floor(geometry_info.rho+0.5);
    }
  (void) FormatLocaleString(header,sizeof(header),"rdensty: %04lu",
    (unsigned long) density);
  count=WriteCALSRecord(image,header);
  count=WriteCALSRecord(image,"notes: NONE");
  (void) memset(header,' ',128);
  for (i=0; i < 5; i++)
    (void) WriteBlob(image,128,(unsigned char *) header);
  /*
    Write CALS pixels.
  */
  write_info=CloneImageInfo(image_info);
  (void) CopyMagickString(write_info->filename,"GROUP4:",MagickPathExtent);
  (void) CopyMagickString(write_info->magick,"GROUP4",MagickPathExtent);
  group4_image=CloneImage(image,0,0,MagickTrue,exception);
  if (group4_image == (Image *) NULL)
    {
      write_info=DestroyImageInfo(write_info);
      (void) CloseBlob(image);
      return(MagickFalse);
    }
  group4=(unsigned char *) ImageToBlob(write_info,group4_image,&length,
    exception);
  group4_image=DestroyImage(group4_image);
  if (group4 == (unsigned char *) NULL)
    {
      write_info=DestroyImageInfo(write_info);
      (void) CloseBlob(image);
      return(MagickFalse);
    }
  write_info=DestroyImageInfo(write_info);
  if (WriteBlob(image,length,group4) != (ssize_t) length)
    status=MagickFalse;
  group4=(unsigned char *) RelinquishMagickMemory(group4);
  (void) CloseBlob(image);
  return(status);
}

Project: ImageMagick
File: cals.c

static ssize_t WriteCALSRecord(Image *image,const char *data)
{
  char
    pad[128];

  register const char
    *p;

  register ssize_t
    i;

  ssize_t
    count;

  i=0;
  count=0;
  if (data != (const char *) NULL)
    {
      p=data;
      for (i=0; (i < 128) && (p[i] != '\0'); i++);
      count=WriteBlob(image,(size_t) i,(const unsigned char *) data);
    }
  if (i < 128)
    {
      i=128-i;
      (void) memset(pad,' ',(size_t) i);
      count=WriteBlob(image,(size_t) i,(const unsigned char *) pad);
    }
  return(count);
}

Project: ImageMagick
File: dcm.c

static MagickBooleanType ReadDCMPixels(Image *image,DCMInfo *info,
  DCMStreamInfo *stream_info,MagickBooleanType first_segment,
  ExceptionInfo *exception)
{
  int
    byte,
    index;

  MagickBooleanType
    status;

  PixelPacket
    pixel;

  register ssize_t
    i,
    x;

  register Quantum
    *q;

  ssize_t
    y;

  /*
    Convert DCM Medical image to pixel packets.
  */
  byte=0;
  i=0;
  status=MagickTrue;
  (void) memset(&pixel,0,sizeof(pixel));
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
    if (q == (Quantum *) NULL)
      break;
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      if (info->samples_per_pixel == 1)
        {
          int
            pixel_value;

          if (info->bytes_per_pixel == 1)
            pixel_value=info->polarity != MagickFalse ?
              ((int) info->max_value-ReadDCMByte(stream_info,image)) :
              ReadDCMByte(stream_info,image);
          else
            if ((info->bits_allocated != 12) || (info->significant_bits != 12))
              {
                if (info->signed_data)
                  pixel_value=ReadDCMSignedShort(stream_info,image);
                else
                  pixel_value=(int) ReadDCMShort(stream_info,image);
                if (info->polarity != MagickFalse)
                  pixel_value=(int)info->max_value-pixel_value;
              }
            else
              {
                if ((i & 0x01) != 0)
                  pixel_value=(ReadDCMByte(stream_info,image) << 8) |
                    byte;
                else
                  {
                    pixel_value=ReadDCMSignedShort(stream_info,image);
                    byte=(int) (pixel_value & 0x0f);
                    pixel_value>>=4;
                  }
                i++;
              }
          if (info->signed_data == 1)
            pixel_value-=32767;
          index=pixel_value;
          if (info->rescale != MagickFalse)
            {
              double
                scaled_value;

              scaled_value=pixel_value*info->rescale_slope+
                info->rescale_intercept;
              index=(int) scaled_value;
              if (info->window_width != 0)
                {
                  double
                    window_max,
                    window_min;

                  window_min=ceil(info->window_center-
                    (info->window_width-1.0)/2.0-0.5);
                  window_max=floor(info->window_center+
                    (info->window_width-1.0)/2.0+0.5);
                  if (scaled_value <= window_min)
                    index=0;
                  else
                    if (scaled_value > window_max)
                      index=(int) info->max_value;
                    else
                      index=(int) (info->max_value*(((scaled_value-
                        info->window_center-0.5)/(info->window_width-1))+0.5));
                }
            }
          index&=info->mask;
          index=(int) ConstrainColormapIndex(image,(ssize_t) index,exception);
          if (first_segment)
            SetPixelIndex(image,(Quantum) index,q);
          else
            SetPixelIndex(image,(Quantum) (((size_t) index) |
              (((size_t) GetPixelIndex(image,q)) << 8)),q);
          pixel.red=(unsigned int) image->colormap[index].red;
          pixel.green=(unsigned int) image->colormap[index].green;
          pixel.blue=(unsigned int) image->colormap[index].blue;
        }
      else
        {
          if (info->bytes_per_pixel == 1)
            {
              pixel.red=(unsigned int) ReadDCMByte(stream_info,image);
              pixel.green=(unsigned int) ReadDCMByte(stream_info,image);
              pixel.blue=(unsigned int) ReadDCMByte(stream_info,image);
            }
          else
            {
              pixel.red=ReadDCMShort(stream_info,image);
              pixel.green=ReadDCMShort(stream_info,image);
              pixel.blue=ReadDCMShort(stream_info,image);
            }
          pixel.red&=info->mask;
          pixel.green&=info->mask;
          pixel.blue&=info->mask;
          if (info->scale != (Quantum *) NULL)
            {
              if ((MagickSizeType) pixel.red <= GetQuantumRange(info->depth))
                pixel.red=info->scale[pixel.red];
              if ((MagickSizeType) pixel.green <= GetQuantumRange(info->depth))
                pixel.green=info->scale[pixel.green];
              if ((MagickSizeType) pixel.blue <= GetQuantumRange(info->depth))
                pixel.blue=info->scale[pixel.blue];
            }
        }
      if (first_segment != MagickFalse)
        {
          SetPixelRed(image,(Quantum) pixel.red,q);
          SetPixelGreen(image,(Quantum) pixel.green,q);
          SetPixelBlue(image,(Quantum) pixel.blue,q);
        }
      else
        {
          SetPixelRed(image,(Quantum) (((size_t) pixel.red) |
            (((size_t) GetPixelRed(image,q)) << 8)),q);
          SetPixelGreen(image,(Quantum) (((size_t) pixel.green) |
            (((size_t) GetPixelGreen(image,q)) << 8)),q);
          SetPixelBlue(image,(Quantum) (((size_t) pixel.blue) |
            (((size_t) GetPixelBlue(image,q)) << 8)),q);
        }
      q+=GetPixelChannels(image);
    }
    if (SyncAuthenticPixels(image,exception) == MagickFalse)
      break;
    if (image->previous == (Image *) NULL)
      {
        status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
          image->rows);
        if (status == MagickFalse)
          break;
      }
  }
  return(status);
}

Project: ImageMagick
File: dcm.c

static unsigned short ReadDCMShort(DCMStreamInfo *stream_info,Image *image)
{
  int
    shift,
    byte;

  unsigned short
    value;

  if (image->compression != RLECompression)
    return(ReadBlobLSBShort(image));
  shift=image->depth < 16 ? 4 : 8;
  value=(unsigned short) ReadDCMByte(stream_info,image);
  byte=ReadDCMByte(stream_info,image);
  if (byte < 0)
    return(0);
  value|=(unsigned short) (byte << shift);
  return(value);
}