CVE-2019-13454: Divide By Zero (CWE-369)
value: ImageMagick 7.0.8-54 Q16 allows Division by Zero in RemoveDuplicateLayers in MagickCore/layer.c.
CWE description: The product divides a value by zero.
CVSS v3 base score: 6.5
Published: 2019-07-09T17:15Z
Repository: https://github.com/ImageMagick/ImageMagick
Language: C
Files changed: MagickCore/layer.c
Commit date: 2019-07-08 06:15:06 -0400
Commit message: https://github.com/ImageMagick/ImageMagick/issues/1629

Diff: diff --git a/MagickCore/layer.c b/MagickCore/layer.c
index b520e9247dfa..48632885ae80 100644
--- a/MagickCore/layer.c
+++ b/MagickCore/layer.c
@@ -1582,49 +1582,51 @@ MagickExport void OptimizeImageTransparency(const Image *image,
 %    o images: the image list
 %
 %    o exception: return any errors or warnings in this structure.
 %
 */
-MagickExport void RemoveDuplicateLayers(Image **images,
-     ExceptionInfo *exception)
+MagickExport void RemoveDuplicateLayers(Image **images,ExceptionInfo *exception)
 {
-  register Image
-    *curr,
-    *next;
-
   RectangleInfo
     bounds;
 
+  register Image
+    *image,
+    *next;
+
   assert((*images) != (const Image *) NULL);
   assert((*images)->signature == MagickCoreSignature);
   if ((*images)->debug != MagickFalse)
-    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*images)->filename);
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
+      (*images)->filename);
   assert(exception != (ExceptionInfo *) NULL);
   assert(exception->signature == MagickCoreSignature);
-
-  curr=GetFirstImageInList(*images);
-  for (; (next=GetNextImageInList(curr)) != (Image *) NULL; curr=next)
+  image=GetFirstImageInList(*images);
+  for ( ; (next=GetNextImageInList(image)) != (Image *) NULL; image=next)
   {
-    if ( curr->columns != next->columns || curr->rows != next->rows
-         || curr->page.x != next->page.x || curr->page.y != next->page.y )
+    if ((image->columns != next->columns) || (image->rows != next->rows) ||
+        (image->page.x != next->page.x) || (image->page.y != next->page.y))
       continue;
-    bounds=CompareImagesBounds(curr,next,CompareAnyLayer,exception);
-    if ( bounds.x < 0 ) {
-      /*
-        the two images are the same, merge time delays and delete one.
-      */
-      size_t time;
-      time = curr->delay*1000/curr->ticks_per_second;
-      time += next->delay*1000/next->ticks_per_second;
-      next->ticks_per_second = 100L;
-      next->delay = time*curr->ticks_per_second/1000;
-      next->iterations = curr->iterations;
-      *images = curr;
-      (void) DeleteImageFromList(images);
-    }
+    bounds=CompareImagesBounds(image,next,CompareAnyLayer,exception);
+    if (bounds.x < 0)
+      {
+        /*
+          Two images are the same, merge time delays and delete one.
+        */
+        size_t
+          time;
+
+        time=1000*image->delay*PerceptibleReciprocal(image->ticks_per_second);
+        time+=1000*next->delay*PerceptibleReciprocal(next->ticks_per_second);
+        next->ticks_per_second=100L;
+        next->delay=time*image->ticks_per_second/1000;
+        next->iterations=image->iterations;
+        *images=image;
+        (void) DeleteImageFromList(images);
+      }
   }
-  *images = GetFirstImageInList(*images);
+  *images=GetFirstImageInList(*images);
 }
 
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %                                                                             %

Vulnerable code: MagickExport void RemoveDuplicateLayers(Image **images,
     ExceptionInfo *exception)
  register Image
    *curr,
    *next;

    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*images)->filename);

  curr=GetFirstImageInList(*images);
  for (; (next=GetNextImageInList(curr)) != (Image *) NULL; curr=next)
    if ( curr->columns != next->columns || curr->rows != next->rows
         || curr->page.x != next->page.x || curr->page.y != next->page.y )
    bounds=CompareImagesBounds(curr,next,CompareAnyLayer,exception);
    if ( bounds.x < 0 ) {
      /*
        the two images are the same, merge time delays and delete one.
      */
      size_t time;
      time = curr->delay*1000/curr->ticks_per_second;
      time += next->delay*1000/next->ticks_per_second;
      next->ticks_per_second = 100L;
      next->delay = time*curr->ticks_per_second/1000;
      next->iterations = curr->iterations;
      *images = curr;
      (void) DeleteImageFromList(images);
    }
  *images = GetFirstImageInList(*images);
Fixed code: MagickExport void RemoveDuplicateLayers(Image **images,ExceptionInfo *exception)
  register Image
    *image,
    *next;

    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      (*images)->filename);
  image=GetFirstImageInList(*images);
  for ( ; (next=GetNextImageInList(image)) != (Image *) NULL; image=next)
    if ((image->columns != next->columns) || (image->rows != next->rows) ||
        (image->page.x != next->page.x) || (image->page.y != next->page.y))
    bounds=CompareImagesBounds(image,next,CompareAnyLayer,exception);
    if (bounds.x < 0)
      {
        /*
          Two images are the same, merge time delays and delete one.
        */
        size_t
          time;

        time=1000*image->delay*PerceptibleReciprocal(image->ticks_per_second);
        time+=1000*next->delay*PerceptibleReciprocal(next->ticks_per_second);
        next->ticks_per_second=100L;
        next->delay=time*image->ticks_per_second/1000;
        next->iterations=image->iterations;
        *images=image;
        (void) DeleteImageFromList(images);
      }
  *images=GetFirstImageInList(*images);