CVE-2016-10052: Improper Restriction of Operations within the Bounds of a Memory Buffer (CWE-119)
value: Buffer overflow in the WriteProfile function in coders/jpeg.c in ImageMagick before 6.9.5-6 allows remote attackers to cause a denial of service (application crash) or have other unspecified impact via a crafted file.
CWE description: The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
CVSS v3 base score: 7.8
Published: 2017-03-23T17:59Z
Repository: https://github.com/ImageMagick/ImageMagick
Language: C
Files changed: coders/jpeg.c, config/english.xml
Commit date: 2016-08-13 09:06:34 +0200
Commit message: Changed the JPEG writer to raise a warning when the exif profile exceeds 65533 bytes and truncate it.

Diff: diff --git a/coders/jpeg.c b/coders/jpeg.c
index 73f6e49d8a..74a180c97f 100644
--- a/coders/jpeg.c
+++ b/coders/jpeg.c
@@ -1906,11 +1906,12 @@ static void TerminateDestination(j_compress_ptr cinfo)
           (MaxBufferExtent-destination->manager.free_in_buffer))
         ERREXIT(cinfo,JERR_FILE_WRITE);
     }
 }
 
-static void WriteProfile(j_compress_ptr jpeg_info,Image *image)
+static void WriteProfile(j_compress_ptr jpeg_info,Image *image,
+  ExceptionInfo *exception)
 {
   const char
     *name;
 
   const StringInfo
@@ -1937,14 +1938,19 @@ static void WriteProfile(j_compress_ptr jpeg_info,Image *image)
   ResetImageProfileIterator(image);
   for (name=GetNextImageProfile(image); name != (const char *) NULL; )
   {
     profile=GetImageProfile(image,name);
     if (LocaleCompare(name,"EXIF") == 0)
-      for (i=0; i < (ssize_t) GetStringInfoLength(profile); i+=65533L)
       {
-        length=MagickMin(GetStringInfoLength(profile)-i,65533L);
-        jpeg_write_marker(jpeg_info,XML_MARKER,GetStringInfoDatum(profile)+i,
+        length=GetStringInfoLength(profile);
+        if (length > 65533L)
+          {
+            (void) ThrowMagickException(exception,GetMagickModule(),
+              CoderWarning,"ExifProfileSizeExceedsLimit",image->filename);
+            length=65533L;
+          }
+        jpeg_write_marker(jpeg_info,XML_MARKER,GetStringInfoDatum(profile),
           (unsigned int) length);
       }
     if (LocaleCompare(name,"ICC") == 0)
       {
         register unsigned char
@@ -2668,11 +2674,11 @@ static MagickBooleanType WriteJPEGImage(const ImageInfo *image_info,
   if (value != (char *) NULL)
     for (i=0; i < (ssize_t) strlen(value); i+=65533L)
       jpeg_write_marker(&jpeg_info,JPEG_COM,(unsigned char *) value+i,
         (unsigned int) MagickMin((size_t) strlen(value+i),65533L));
   if (image->profiles != (void *) NULL)
-    WriteProfile(&jpeg_info,image);
+    WriteProfile(&jpeg_info,image,exception);
   /*
     Convert MIFF to JPEG raster pixels.
   */
   memory_info=AcquireVirtualMemory((size_t) image->columns,
     jpeg_info.input_components*sizeof(*jpeg_pixels));
diff --git a/config/english.xml b/config/english.xml
index 1837fe31b2..dbaa11d800 100644
--- a/config/english.xml
+++ b/config/english.xml
@@ -203,10 +203,13 @@
         <message name="ZIPCompressNotSupported">
           ZIP compression not supported
         </message>
       </error>
       <warning>
+        <message name="ExifProfileSizeExceedsLimit">
+          exif profile size exceeds limit and will be truncated
+        </message>
         <message name="LosslessToLossyJPEGConversion">
           lossless to lossy JPEG conversion
         </message>
       </warning>
     </coder>

Vulnerable code: static void WriteProfile(j_compress_ptr jpeg_info,Image *image)
      for (i=0; i < (ssize_t) GetStringInfoLength(profile); i+=65533L)
        length=MagickMin(GetStringInfoLength(profile)-i,65533L);
        jpeg_write_marker(jpeg_info,XML_MARKER,GetStringInfoDatum(profile)+i,
    WriteProfile(&jpeg_info,image);
Fixed code: static void WriteProfile(j_compress_ptr jpeg_info,Image *image,
  ExceptionInfo *exception)
        length=GetStringInfoLength(profile);
        if (length > 65533L)
          {
            (void) ThrowMagickException(exception,GetMagickModule(),
              CoderWarning,"ExifProfileSizeExceedsLimit",image->filename);
            length=65533L;
          }
        jpeg_write_marker(jpeg_info,XML_MARKER,GetStringInfoDatum(profile),
    WriteProfile(&jpeg_info,image,exception);
        <message name="ExifProfileSizeExceedsLimit">
          exif profile size exceeds limit and will be truncated
        </message>