CVE-2019-13308: Out-of-bounds Write (CWE-787)
value: ImageMagick 7.0.8-50 Q16 has a heap-based buffer overflow in MagickCore/fourier.c in ComplexImage.
CWE description: The product writes data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 8.8
Published: 2019-07-05T01:15Z
Repository: https://github.com/ImageMagick/ImageMagick6
Language: C
Files changed: coders/gif.c, magick/fourier.c
Commit date: 2019-06-17 08:48:42 -0400
Commit message: https://github.com/ImageMagick/ImageMagick/issues/1595

Diff: diff --git a/coders/gif.c b/coders/gif.c
index c101547e9a..9830eb7d30 100644
--- a/coders/gif.c
+++ b/coders/gif.c
@@ -683,17 +683,19 @@ static MagickBooleanType EncodeImage(const ImageInfo *image_info,Image *image,
     for (x=(ssize_t) (y == 0 ? 1 : 0); x < (ssize_t) image->columns; x++)
     {
       /*
         Probe hash table.
       */
+      next_pixel=MagickFalse;
+      displacement=1;
       index=(IndexPacket) ((size_t) GetPixelIndex(indexes+x) & 0xff);
       p++;
       k=(ssize_t) (((size_t) index << (MaxGIFBits-8))+waiting_code);
       if (k >= MaxHashTable)
         k-=MaxHashTable;
-      next_pixel=MagickFalse;
-      displacement=1;
+      if (k < 0)
+        continue;
       if (hash_code[k] > 0)
         {
           if ((hash_prefix[k] == waiting_code) &&
               (hash_suffix[k] == (unsigned char) index))
             {
diff --git a/magick/fourier.c b/magick/fourier.c
index bff711d0f6..83dfcb24ae 100644
--- a/magick/fourier.c
+++ b/magick/fourier.c
@@ -224,13 +224,13 @@ MagickExport Image *ComplexImages(const Image *images,const ComplexOperator op,
   Ci_view=AcquireAuthenticCacheView(Ci_image,exception);
   status=MagickTrue;
   progress=0;
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
   #pragma omp parallel for schedule(static) shared(progress,status) \
-    magick_number_threads(images,complex_images,images->rows,1L)
+    magick_number_threads(Cr_image,complex_images,Cr_image->rows,1L)
 #endif
-  for (y=0; y < (ssize_t) images->rows; y++)
+  for (y=0; y < (ssize_t) Cr_image->rows; y++)
   {
     register const PixelPacket
       *magick_restrict Ai,
       *magick_restrict Ar,
       *magick_restrict Bi,
@@ -243,18 +243,14 @@ MagickExport Image *ComplexImages(const Image *images,const ComplexOperator op,
     register ssize_t
       x;
 
     if (status == MagickFalse)
       continue;
-    Ar=GetCacheViewVirtualPixels(Ar_view,0,y,
-      MagickMax(Ar_image->columns,Cr_image->columns),1,exception);
-    Ai=GetCacheViewVirtualPixels(Ai_view,0,y,
-      MagickMax(Ai_image->columns,Ci_image->columns),1,exception);
-    Br=GetCacheViewVirtualPixels(Br_view,0,y,
-      MagickMax(Br_image->columns,Cr_image->columns),1,exception);
-    Bi=GetCacheViewVirtualPixels(Bi_view,0,y,
-      MagickMax(Bi_image->columns,Ci_image->columns),1,exception);
+    Ar=GetCacheViewVirtualPixels(Ar_view,0,y,Cr_image->columns,1,exception);
+    Ai=GetCacheViewVirtualPixels(Ai_view,0,y,Cr_image->columns,1,exception);
+    Br=GetCacheViewVirtualPixels(Br_view,0,y,Cr_image->columns,1,exception);
+    Bi=GetCacheViewVirtualPixels(Bi_view,0,y,Cr_image->columns,1,exception);
     Cr=QueueCacheViewAuthenticPixels(Cr_view,0,y,Cr_image->columns,1,exception);
     Ci=QueueCacheViewAuthenticPixels(Ci_view,0,y,Ci_image->columns,1,exception);
     if ((Ar == (const PixelPacket *) NULL) ||
         (Ai == (const PixelPacket *) NULL) ||
         (Br == (const PixelPacket *) NULL) ||
@@ -262,11 +258,11 @@ MagickExport Image *ComplexImages(const Image *images,const ComplexOperator op,
         (Cr == (PixelPacket *) NULL) || (Ci == (PixelPacket *) NULL))
       {
         status=MagickFalse;
         continue;
       }
-    for (x=0; x < (ssize_t) images->columns; x++)
+    for (x=0; x < (ssize_t) Cr_image->columns; x++)
     {
       switch (op)
       {
         case AddComplexOperator:
         {
@@ -303,59 +299,74 @@ MagickExport Image *ComplexImages(const Image *images,const ComplexOperator op,
         {
           double
             gamma;
 
           gamma=PerceptibleReciprocal(Br->red*Br->red+Bi->red*Bi->red+snr);
-          Cr->red=gamma*(Ar->red*Br->red+Ai->red*Bi->red);
-          Ci->red=gamma*(Ai->red*Br->red-Ar->red*Bi->red);
-          gamma=PerceptibleReciprocal(Br->green*Br->green+Bi->green*Bi->green+
-            snr);
-          Cr->green=gamma*(Ar->green*Br->green+Ai->green*Bi->green);
-          Ci->green=gamma*(Ai->green*Br->green-Ar->green*Bi->green);
-          gamma=PerceptibleReciprocal(Br->blue*Br->blue+Bi->blue*Bi->blue+snr);
-          Cr->blue=gamma*(Ar->blue*Br->blue+Ai->blue*Bi->blue);
-          Ci->blue=gamma*(Ai->blue*Br->blue-Ar->blue*Bi->blue);
+          Cr->red=gamma*((double) Ar->red*Br->red+(double) Ai->red*Bi->red);
+          Ci->red=gamma*((double) Ai->red*Br->red-(double) Ar->red*Bi->red);
+          gamma=PerceptibleReciprocal((double) Br->green*Br->green+(double)
+            Bi->green*Bi->green+snr);
+          Cr->green=gamma*((double) Ar->green*Br->green+(double)
+            Ai->green*Bi->green);
+          Ci->green=gamma*((double) Ai->green*Br->green-(double)
+            Ar->green*Bi->green);
+          gamma=PerceptibleReciprocal((double) Br->blue*Br->blue+(double)
+            Bi->blue*Bi->blue+snr);
+          Cr->blue=gamma*((double) Ar->blue*Br->blue+(double)
+            Ai->blue*Bi->blue);
+          Ci->blue=gamma*((double) Ai->blue*Br->blue-(double)
+             Ar->blue*Bi->blue);
           if (images->matte != MagickFalse)
             {
-              gamma=PerceptibleReciprocal(Br->opacity*Br->opacity+Bi->opacity*
-                Bi->opacity+snr);
-              Cr->opacity=gamma*(Ar->opacity*Br->opacity+Ai->opacity*
-                Bi->opacity);
-              Ci->opacity=gamma*(Ai->opacity*Br->opacity-Ar->opacity*
-                Bi->opacity);
+              gamma=PerceptibleReciprocal((double) Br->opacity*Br->opacity+
+                (double) Bi->opacity*Bi->opacity+snr);
+              Cr->opacity=gamma*((double) Ar->opacity*Br->opacity+(double)
+                Ai->opacity*Bi->opacity);
+              Ci->opacity=gamma*((double) Ai->opacity*Br->opacity-(double)
+                Ar->opacity*Bi->opacity);
             }
           break;
         }
         case MagnitudePhaseComplexOperator:
         {
-          Cr->red=sqrt(Ar->red*Ar->red+Ai->red*Ai->red);
-          Ci->red=atan2(Ai->red,Ar->red)/(2.0*MagickPI)+0.5;
-          Cr->green=sqrt(Ar->green*Ar->green+Ai->green*Ai->green);
-          Ci->green=atan2(Ai->green,Ar->green)/(2.0*MagickPI)+0.5;
-          Cr->blue=sqrt(Ar->blue*Ar->blue+Ai->blue*Ai->blue);
+          Cr->red=sqrt((double) Ar->red*Ar->red+(double) Ai->red*Ai->red);
+          Ci->red=atan2((double) Ai->red,(double) Ar->red)/(2.0*MagickPI)+0.5;
+          Cr->green=sqrt((double) Ar->green*Ar->green+(double)
+            Ai->green*Ai->green);
+          Ci->green=atan2((double) Ai->green,(double) Ar->green)/
+            (2.0*MagickPI)+0.5;
+          Cr->blue=sqrt((double) Ar->blue*Ar->blue+(double) Ai->blue*Ai->blue);
           Ci->blue=atan2(Ai->blue,Ar->blue)/(2.0*MagickPI)+0.5;
           if (images->matte != MagickFalse)
             {
-              Cr->opacity=sqrt(Ar->opacity*Ar->opacity+Ai->opacity*Ai->opacity);
-              Ci->opacity=atan2(Ai->opacity,Ar->opacity)/(2.0*MagickPI)+0.5;
+              Cr->opacity=sqrt((double) Ar->opacity*Ar->opacity+(double)
+                Ai->opacity*Ai->opacity);
+              Ci->opacity=atan2((double) Ai->opacity,(double) Ar->opacity)/
+                (2.0*MagickPI)+0.5;
             }
           break;
         }
         case MultiplyComplexOperator:
         {
-          Cr->red=QuantumScale*(Ar->red*Br->red-Ai->red*Bi->red);
-          Ci->red=QuantumScale*(Ai->red*Br->red+Ar->red*Bi->red);
-          Cr->green=QuantumScale*(Ar->green*Br->green-Ai->green*Bi->green);
-          Ci->green=QuantumScale*(Ai->green*Br->green+Ar->green*Bi->green);
-          Cr->blue=QuantumScale*(Ar->blue*Br->blue-Ai->blue*Bi->blue);
-          Ci->blue=QuantumScale*(Ai->blue*Br->blue+Ar->blue*Bi->blue);
+          Cr->red=QuantumScale*((double) Ar->red*Br->red-(double)
+            Ai->red*Bi->red);
+          Ci->red=QuantumScale*((double) Ai->red*Br->red+(double)
+            Ar->red*Bi->red);
+          Cr->green=QuantumScale*((double) Ar->green*Br->green-(double)
+            Ai->green*Bi->green);
+          Ci->green=QuantumScale*((double) Ai->green*Br->green+(double)
+            Ar->green*Bi->green);
+          Cr->blue=QuantumScale*((double) Ar->blue*Br->blue-(double)
+            Ai->blue*Bi->blue);
+          Ci->blue=QuantumScale*((double) Ai->blue*Br->blue+(double)
+            Ar->blue*Bi->blue);
           if (images->matte != MagickFalse)
             {
-              Cr->opacity=QuantumScale*(Ar->opacity*Br->opacity-Ai->opacity*
-                Bi->opacity);
-              Ci->opacity=QuantumScale*(Ai->opacity*Br->opacity+Ar->opacity*
-                Bi->opacity);
+              Cr->opacity=QuantumScale*((double) Ar->opacity*Br->opacity-
+                (double) Ai->opacity*Bi->opacity);
+              Ci->opacity=QuantumScale*((double) Ai->opacity*Br->opacity+
+                (double) Ar->opacity*Bi->opacity);
             }
           break;
         }
         case RealImaginaryComplexOperator:
         {
@@ -378,11 +389,11 @@ MagickExport Image *ComplexImages(const Image *images,const ComplexOperator op,
           Ci->red=Ai->red-Bi->red;
           Cr->green=Ar->green-Br->green;
           Ci->green=Ai->green-Bi->green;
           Cr->blue=Ar->blue-Br->blue;
           Ci->blue=Ai->blue-Bi->blue;
-          if (images->matte != MagickFalse)
+          if (Cr_image->matte != MagickFalse)
             {
               Cr->opacity=Ar->opacity-Br->opacity;
               Ci->opacity=Ai->opacity-Bi->opacity;
             }
           break;

Vulnerable code:       next_pixel=MagickFalse;
      displacement=1;
    magick_number_threads(images,complex_images,images->rows,1L)
  for (y=0; y < (ssize_t) images->rows; y++)
    Ar=GetCacheViewVirtualPixels(Ar_view,0,y,
      MagickMax(Ar_image->columns,Cr_image->columns),1,exception);
    Ai=GetCacheViewVirtualPixels(Ai_view,0,y,
      MagickMax(Ai_image->columns,Ci_image->columns),1,exception);
    Br=GetCacheViewVirtualPixels(Br_view,0,y,
      MagickMax(Br_image->columns,Cr_image->columns),1,exception);
    Bi=GetCacheViewVirtualPixels(Bi_view,0,y,
      MagickMax(Bi_image->columns,Ci_image->columns),1,exception);
    for (x=0; x < (ssize_t) images->columns; x++)
          Cr->red=gamma*(Ar->red*Br->red+Ai->red*Bi->red);
          Ci->red=gamma*(Ai->red*Br->red-Ar->red*Bi->red);
          gamma=PerceptibleReciprocal(Br->green*Br->green+Bi->green*Bi->green+
            snr);
          Cr->green=gamma*(Ar->green*Br->green+Ai->green*Bi->green);
          Ci->green=gamma*(Ai->green*Br->green-Ar->green*Bi->green);
          gamma=PerceptibleReciprocal(Br->blue*Br->blue+Bi->blue*Bi->blue+snr);
          Cr->blue=gamma*(Ar->blue*Br->blue+Ai->blue*Bi->blue);
          Ci->blue=gamma*(Ai->blue*Br->blue-Ar->blue*Bi->blue);
              gamma=PerceptibleReciprocal(Br->opacity*Br->opacity+Bi->opacity*
                Bi->opacity+snr);
              Cr->opacity=gamma*(Ar->opacity*Br->opacity+Ai->opacity*
                Bi->opacity);
              Ci->opacity=gamma*(Ai->opacity*Br->opacity-Ar->opacity*
                Bi->opacity);
          Cr->red=sqrt(Ar->red*Ar->red+Ai->red*Ai->red);
          Ci->red=atan2(Ai->red,Ar->red)/(2.0*MagickPI)+0.5;
          Cr->green=sqrt(Ar->green*Ar->green+Ai->green*Ai->green);
          Ci->green=atan2(Ai->green,Ar->green)/(2.0*MagickPI)+0.5;
          Cr->blue=sqrt(Ar->blue*Ar->blue+Ai->blue*Ai->blue);
              Cr->opacity=sqrt(Ar->opacity*Ar->opacity+Ai->opacity*Ai->opacity);
              Ci->opacity=atan2(Ai->opacity,Ar->opacity)/(2.0*MagickPI)+0.5;
          Cr->red=QuantumScale*(Ar->red*Br->red-Ai->red*Bi->red);
          Ci->red=QuantumScale*(Ai->red*Br->red+Ar->red*Bi->red);
          Cr->green=QuantumScale*(Ar->green*Br->green-Ai->green*Bi->green);
          Ci->green=QuantumScale*(Ai->green*Br->green+Ar->green*Bi->green);
          Cr->blue=QuantumScale*(Ar->blue*Br->blue-Ai->blue*Bi->blue);
          Ci->blue=QuantumScale*(Ai->blue*Br->blue+Ar->blue*Bi->blue);
              Cr->opacity=QuantumScale*(Ar->opacity*Br->opacity-Ai->opacity*
                Bi->opacity);
              Ci->opacity=QuantumScale*(Ai->opacity*Br->opacity+Ar->opacity*
                Bi->opacity);
          if (images->matte != MagickFalse)
Fixed code:       next_pixel=MagickFalse;
      displacement=1;
      if (k < 0)
        continue;
    magick_number_threads(Cr_image,complex_images,Cr_image->rows,1L)
  for (y=0; y < (ssize_t) Cr_image->rows; y++)
    Ar=GetCacheViewVirtualPixels(Ar_view,0,y,Cr_image->columns,1,exception);
    Ai=GetCacheViewVirtualPixels(Ai_view,0,y,Cr_image->columns,1,exception);
    Br=GetCacheViewVirtualPixels(Br_view,0,y,Cr_image->columns,1,exception);
    Bi=GetCacheViewVirtualPixels(Bi_view,0,y,Cr_image->columns,1,exception);
    for (x=0; x < (ssize_t) Cr_image->columns; x++)
          Cr->red=gamma*((double) Ar->red*Br->red+(double) Ai->red*Bi->red);
          Ci->red=gamma*((double) Ai->red*Br->red-(double) Ar->red*Bi->red);
          gamma=PerceptibleReciprocal((double) Br->green*Br->green+(double)
            Bi->green*Bi->green+snr);
          Cr->green=gamma*((double) Ar->green*Br->green+(double)
            Ai->green*Bi->green);
          Ci->green=gamma*((double) Ai->green*Br->green-(double)
            Ar->green*Bi->green);
          gamma=PerceptibleReciprocal((double) Br->blue*Br->blue+(double)
            Bi->blue*Bi->blue+snr);
          Cr->blue=gamma*((double) Ar->blue*Br->blue+(double)
            Ai->blue*Bi->blue);
          Ci->blue=gamma*((double) Ai->blue*Br->blue-(double)
             Ar->blue*Bi->blue);
              gamma=PerceptibleReciprocal((double) Br->opacity*Br->opacity+
                (double) Bi->opacity*Bi->opacity+snr);
              Cr->opacity=gamma*((double) Ar->opacity*Br->opacity+(double)
                Ai->opacity*Bi->opacity);
              Ci->opacity=gamma*((double) Ai->opacity*Br->opacity-(double)
                Ar->opacity*Bi->opacity);
          Cr->red=sqrt((double) Ar->red*Ar->red+(double) Ai->red*Ai->red);
          Ci->red=atan2((double) Ai->red,(double) Ar->red)/(2.0*MagickPI)+0.5;
          Cr->green=sqrt((double) Ar->green*Ar->green+(double)
            Ai->green*Ai->green);
          Ci->green=atan2((double) Ai->green,(double) Ar->green)/
            (2.0*MagickPI)+0.5;
          Cr->blue=sqrt((double) Ar->blue*Ar->blue+(double) Ai->blue*Ai->blue);
              Cr->opacity=sqrt((double) Ar->opacity*Ar->opacity+(double)
                Ai->opacity*Ai->opacity);
              Ci->opacity=atan2((double) Ai->opacity,(double) Ar->opacity)/
                (2.0*MagickPI)+0.5;
          Cr->red=QuantumScale*((double) Ar->red*Br->red-(double)
            Ai->red*Bi->red);
          Ci->red=QuantumScale*((double) Ai->red*Br->red+(double)
            Ar->red*Bi->red);
          Cr->green=QuantumScale*((double) Ar->green*Br->green-(double)
            Ai->green*Bi->green);
          Ci->green=QuantumScale*((double) Ai->green*Br->green+(double)
            Ar->green*Bi->green);
          Cr->blue=QuantumScale*((double) Ar->blue*Br->blue-(double)
            Ai->blue*Bi->blue);
          Ci->blue=QuantumScale*((double) Ai->blue*Br->blue+(double)
            Ar->blue*Bi->blue);
              Cr->opacity=QuantumScale*((double) Ar->opacity*Br->opacity-
                (double) Ai->opacity*Bi->opacity);
              Ci->opacity=QuantumScale*((double) Ai->opacity*Br->opacity+
                (double) Ar->opacity*Bi->opacity);
          if (Cr_image->matte != MagickFalse)