CVE-2017-15033: Missing Release of Resource after Effective Lifetime (CWE-772)
value: ImageMagick version 7.0.7-2 contains a memory leak in ReadYUVImage in coders/yuv.c.
CWE description: The product does not release a resource after its effective lifetime has ended, i.e., after the resource is no longer needed.
CVSS v3 base score: 7.5
Published: 2017-10-05T07:29Z
Repository: https://github.com/ImageMagick/ImageMagick
Language: C
Files changed: coders/yuv.c
Commit date: 2017-09-14 16:29:21 +0200
Commit message: fix multiple memory leak in ReadYUVImage

Diff: diff --git a/coders/yuv.c b/coders/yuv.c
index a203ea76819..6eeac3d557f 100644
--- a/coders/yuv.c
+++ b/coders/yuv.c
@@ -209,11 +209,14 @@ static Image *ReadYUVImage(const ImageInfo *image_info,ExceptionInfo *exception)
   {
     chroma_image=CloneImage(image,(image->columns+horizontal_factor-1)/
       horizontal_factor,(image->rows+vertical_factor-1)/vertical_factor,
       MagickTrue,exception);
     if (chroma_image == (Image *) NULL)
-      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+      {
+        scanline=(unsigned char *) RelinquishMagickMemory(scanline); 
+        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+      }
     /*
       Convert raster image to pixel packets.
     */
     if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
@@ -225,10 +228,11 @@ static Image *ReadYUVImage(const ImageInfo *image_info,ExceptionInfo *exception)
       {
         AppendImageFormat("Y",image->filename);
         status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
         if (status == MagickFalse)
           {
+            scanline=(unsigned char *) RelinquishMagickMemory(scanline); 
             image=DestroyImageList(image);
             return((Image *) NULL);
           }
       }
     for (y=0; y < (ssize_t) image->rows; y++)
@@ -351,10 +355,11 @@ static Image *ReadYUVImage(const ImageInfo *image_info,ExceptionInfo *exception)
         (void) CloseBlob(image);
         AppendImageFormat("U",image->filename);
         status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
         if (status == MagickFalse)
           {
+            scanline=(unsigned char *) RelinquishMagickMemory(scanline); 
             image=DestroyImageList(image);
             return((Image *) NULL);
           }
       }
     if (interlace != NoInterlace)
@@ -397,10 +402,11 @@ static Image *ReadYUVImage(const ImageInfo *image_info,ExceptionInfo *exception)
           (void) CloseBlob(image);
           AppendImageFormat("V",image->filename);
           status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
           if (status == MagickFalse)
             {
+              scanline=(unsigned char *) RelinquishMagickMemory(scanline); 
               image=DestroyImageList(image);
               return((Image *) NULL);
             }
         }
       for (y=0; y < (ssize_t) chroma_image->rows; y++)
@@ -440,11 +446,14 @@ static Image *ReadYUVImage(const ImageInfo *image_info,ExceptionInfo *exception)
     */
     resize_image=ResizeImage(chroma_image,image->columns,image->rows,
       TriangleFilter,exception);
     chroma_image=DestroyImage(chroma_image);
     if (resize_image == (Image *) NULL)
-      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+      {
+        scanline=(unsigned char *) RelinquishMagickMemory(scanline);   
+        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+      }
     for (y=0; y < (ssize_t) image->rows; y++)
     {
       q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
       chroma_pixels=GetVirtualPixels(resize_image,0,y,resize_image->columns,1,
         exception);
@@ -489,10 +498,11 @@ static Image *ReadYUVImage(const ImageInfo *image_info,ExceptionInfo *exception)
           Allocate next image structure.
         */
         AcquireNextImage(image_info,image,exception);
         if (GetNextImageInList(image) == (Image *) NULL)
           {
+            scanline=(unsigned char *) RelinquishMagickMemory(scanline); 
             image=DestroyImageList(image);
             return((Image *) NULL);
           }
         image=SyncNextImageInList(image);
         status=SetImageProgress(image,LoadImagesTag,TellBlob(image),

Vulnerable code:       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
Fixed code:       {
        scanline=(unsigned char *) RelinquishMagickMemory(scanline); 
        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
      }
            scanline=(unsigned char *) RelinquishMagickMemory(scanline); 
            scanline=(unsigned char *) RelinquishMagickMemory(scanline); 
              scanline=(unsigned char *) RelinquishMagickMemory(scanline); 
      {
        scanline=(unsigned char *) RelinquishMagickMemory(scanline);   
        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
      }
            scanline=(unsigned char *) RelinquishMagickMemory(scanline);