CVE-2021-20224: Integer Overflow or Wraparound (CWE-190)
value: An integer overflow issue was discovered in ImageMagick's ExportIndexQuantum() function in MagickCore/quantum-export.c. Function calls to GetPixelIndex() could result in values outside the range of representable for the 'unsigned char'. When ImageMagick processes a crafted pdf file, this could lead to an undefined behaviour or a crash.
CWE description: The product performs a calculation that can
         produce an integer overflow or wraparound when the logic
         assumes that the resulting value will always be larger than
         the original value. This occurs when an integer value is
         incremented to a value that is too large to store in the
         associated representation. When this occurs, the value may
         become a very small or negative number.
CVSS v3 base score: 5.5
Published: 2022-08-25T20:15Z
Repository: https://github.com/ImageMagick/ImageMagick
Language: C
Files changed: MagickCore/quantum-export.c
Commit date: 2021-01-06 18:15:12 -0500
Commit message: outside the range of representable values of type 'unsigned char' (#3083)

Co-authored-by: Zhang Xiaohui <ruc_zhangxiaohui@163.com>
Diff: diff --git a/MagickCore/quantum-export.c b/MagickCore/quantum-export.c
index 3ab71bf8db9a..4f08939e0d18 100644
--- a/MagickCore/quantum-export.c
+++ b/MagickCore/quantum-export.c
@@ -2528,42 +2528,42 @@ static void ExportIndexQuantum(const Image *image,QuantumInfo *quantum_info,
       unsigned char
         pixel;
 
       for (x=((ssize_t) number_pixels-7); x > 0; x-=8)
       {
-        pixel=(unsigned char) GetPixelIndex(image,p);
+        pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
         *q=((pixel & 0x01) << 7);
         p+=GetPixelChannels(image);
-        pixel=(unsigned char) GetPixelIndex(image,p);
+        pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
         *q|=((pixel & 0x01) << 6);
         p+=GetPixelChannels(image);
-        pixel=(unsigned char) GetPixelIndex(image,p);
+        pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
         *q|=((pixel & 0x01) << 5);
         p+=GetPixelChannels(image);
-        pixel=(unsigned char) GetPixelIndex(image,p);
+        pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
         *q|=((pixel & 0x01) << 4);
         p+=GetPixelChannels(image);
-        pixel=(unsigned char) GetPixelIndex(image,p);
+        pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
         *q|=((pixel & 0x01) << 3);
         p+=GetPixelChannels(image);
-        pixel=(unsigned char) GetPixelIndex(image,p);
+        pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
         *q|=((pixel & 0x01) << 2);
         p+=GetPixelChannels(image);
-        pixel=(unsigned char) GetPixelIndex(image,p);
+        pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
         *q|=((pixel & 0x01) << 1);
         p+=GetPixelChannels(image);
-        pixel=(unsigned char) GetPixelIndex(image,p);
+        pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
         *q|=((pixel & 0x01) << 0);
         p+=GetPixelChannels(image);
         q++;
       }
       if ((number_pixels % 8) != 0)
         {
           *q='\0';
           for (bit=7; bit >= (ssize_t) (8-(number_pixels % 8)); bit--)
           {
-            pixel=(unsigned char) GetPixelIndex(image,p);
+            pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
             *q|=((pixel & 0x01) << (unsigned char) bit);
             p+=GetPixelChannels(image);
           }
           q++;
         }
@@ -2574,32 +2574,32 @@ static void ExportIndexQuantum(const Image *image,QuantumInfo *quantum_info,
       unsigned char
         pixel;
 
       for (x=0; x < (ssize_t) (number_pixels-1) ; x+=2)
       {
-        pixel=(unsigned char) GetPixelIndex(image,p);
+        pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
         *q=((pixel & 0xf) << 4);
         p+=GetPixelChannels(image);
-        pixel=(unsigned char) GetPixelIndex(image,p);
+        pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
         *q|=((pixel & 0xf) << 0);
         p+=GetPixelChannels(image);
         q++;
       }
       if ((number_pixels % 2) != 0)
         {
-          pixel=(unsigned char) GetPixelIndex(image,p);
+          pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
           *q=((pixel & 0xf) << 4);
           p+=GetPixelChannels(image);
           q++;
         }
       break;
     }
     case 8:
     {
       for (x=0; x < (ssize_t) number_pixels; x++)
       {
-        q=PopCharPixel((unsigned char) GetPixelIndex(image,p),q);
+        q=PopCharPixel((unsigned char) ((ssize_t) GetPixelIndex(image,p)),q);
         p+=GetPixelChannels(image);
         q+=quantum_info->pad;
       }
       break;
     }

Vulnerable code:         pixel=(unsigned char) GetPixelIndex(image,p);
        pixel=(unsigned char) GetPixelIndex(image,p);
        pixel=(unsigned char) GetPixelIndex(image,p);
        pixel=(unsigned char) GetPixelIndex(image,p);
        pixel=(unsigned char) GetPixelIndex(image,p);
        pixel=(unsigned char) GetPixelIndex(image,p);
        pixel=(unsigned char) GetPixelIndex(image,p);
        pixel=(unsigned char) GetPixelIndex(image,p);
            pixel=(unsigned char) GetPixelIndex(image,p);
        pixel=(unsigned char) GetPixelIndex(image,p);
        pixel=(unsigned char) GetPixelIndex(image,p);
          pixel=(unsigned char) GetPixelIndex(image,p);
        q=PopCharPixel((unsigned char) GetPixelIndex(image,p),q);
Fixed code:         pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
        pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
        pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
        pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
        pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
        pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
        pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
        pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
            pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
        pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
        pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
          pixel=(unsigned char) ((ssize_t) GetPixelIndex(image,p));
        q=PopCharPixel((unsigned char) ((ssize_t) GetPixelIndex(image,p)),q);