Vulnerability: The SpliceImage function in MagickCore/transform.c in ImageMagick before 6.9.2-4 allows remote attackers to cause a denial of service (application crash) via a crafted png file.
Vulnerability ID: CVE-2015-8897
CWE: CWE-125
Severity score: 2.9
Project: https://github.com/ImageMagick/ImageMagick
Published: 2017-03-15
File: MagickCore/transform.c
Commit message: Fixed out of bounds error in SpliceImage.
Commit author: dirk

Vulnerable version (before fix):
 MagickExport Image *SpliceImage(const Image *image,     splice_geometry;    ssize_t     y;    /* MagickExport Image *SpliceImage(const Image *image,   */   status=MagickTrue;   progress=0;   image_view=AcquireVirtualCacheView(image,exception);   splice_view=AcquireAuthenticCacheView(splice_image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) MagickExport Image *SpliceImage(const Image *image,      if (status == MagickFalse)       continue;     p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);     q=QueueCacheViewAuthenticPixels(splice_view,0,y,splice_image->columns,1,       exception);     if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))       {         status=MagickFalse;         continue;       }     for (x=0; x < splice_geometry.x; x++)     {       register ssize_t         i; MagickExport Image *SpliceImage(const Image *image,      if (status == MagickFalse)       continue;     p=GetCacheViewVirtualPixels(image_view,0,y-(ssize_t) splice_geometry.height,       image->columns,1,exception);     if ((y < 0) || (y >= (ssize_t) splice_image->rows))       continue;     q=QueueCacheViewAuthenticPixels(splice_view,0,y,splice_image->columns,1,       exception);     if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))       {         status=MagickFalse;         continue;       }     for (x=0; x < splice_geometry.x; x++)     {       register ssize_t         i;

Fixed version (after fix):
 MagickExport Image *SpliceImage(const Image *image,     splice_geometry;    ssize_t     columns,     y;    /* MagickExport Image *SpliceImage(const Image *image,   */   status=MagickTrue;   progress=0;   columns=MagickMin(splice_geometry.x,(ssize_t) splice_image->columns);   image_view=AcquireVirtualCacheView(image,exception);   splice_view=AcquireAuthenticCacheView(splice_image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) MagickExport Image *SpliceImage(const Image *image,      if (status == MagickFalse)       continue;     p=GetCacheViewVirtualPixels(image_view,0,y,splice_image->columns,1,       exception);     q=QueueCacheViewAuthenticPixels(splice_view,0,y,splice_image->columns,1,       exception);     if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))       {         status=MagickFalse;         continue;       }     for (x=0; x < columns; x++)     {       register ssize_t         i; MagickExport Image *SpliceImage(const Image *image,      if (status == MagickFalse)       continue;     if ((y < 0) || (y >= (ssize_t)splice_image->rows))       continue;     p=GetCacheViewVirtualPixels(image_view,0,y-(ssize_t) splice_geometry.height,       splice_image->columns,1,exception);     q=QueueCacheViewAuthenticPixels(splice_view,0,y,splice_image->columns,1,       exception);     if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))       {         status=MagickFalse;         continue;       }     for (x=0; x < columns; x++)     {       register ssize_t         i;

Patch:
patch: @@ -1722,6 +1722,7 @@ MagickExport Image *SpliceImage(const Image *image,
     splice_geometry;
 
   ssize_t
+    columns,
     y;
 
   /*
@@ -1810,6 +1811,7 @@ MagickExport Image *SpliceImage(const Image *image,
   */
   status=MagickTrue;
   progress=0;
+  columns=MagickMin(splice_geometry.x,(ssize_t) splice_image->columns);
   image_view=AcquireVirtualCacheView(image,exception);
   splice_view=AcquireAuthenticCacheView(splice_image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
@@ -1829,15 +1831,16 @@ MagickExport Image *SpliceImage(const Image *image,
 
     if (status == MagickFalse)
       continue;
-    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
+    p=GetCacheViewVirtualPixels(image_view,0,y,splice_image->columns,1,
+      exception);
     q=QueueCacheViewAuthenticPixels(splice_view,0,y,splice_image->columns,1,
       exception);
     if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
       {
         status=MagickFalse;
         continue;
       }
-    for (x=0; x < splice_geometry.x; x++)
+    for (x=0; x < columns; x++)
     {
       register ssize_t
         i;
@@ -1931,18 +1934,18 @@ MagickExport Image *SpliceImage(const Image *image,
 
     if (status == MagickFalse)
       continue;
-    p=GetCacheViewVirtualPixels(image_view,0,y-(ssize_t) splice_geometry.height,
-      image->columns,1,exception);
-    if ((y < 0) || (y >= (ssize_t) splice_image->rows))
+    if ((y < 0) || (y >= (ssize_t)splice_image->rows))
       continue;
+    p=GetCacheViewVirtualPixels(image_view,0,y-(ssize_t) splice_geometry.height,
+      splice_image->columns,1,exception);
     q=QueueCacheViewAuthenticPixels(splice_view,0,y,splice_image->columns,1,
       exception);
     if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
       {
         status=MagickFalse;
         continue;
       }
-    for (x=0; x < splice_geometry.x; x++)
+    for (x=0; x < columns; x++)
     {
       register ssize_t
         i;
path: MagickCore/transform.c