CVE-2023-34475: Use After Free (CWE-416)
value: A heap use after free issue was discovered in ImageMagick's ReplaceXmpValue() function in MagickCore/profile.c. An attacker could trick user to open a specially crafted file to convert, triggering an heap-use-after-free write error, allowing an application to crash, resulting in a denial of service.
CWE description: The product reuses or references memory after it has been freed. At some point afterward, the memory may be allocated again and saved in another pointer, while the original pointer references a location somewhere within the new allocation. Any operations using the original pointer are no longer valid because the memory "belongs" to the code that operates on the new pointer.
CVSS v3 base score: 5.5
Published: 2023-06-16T20:15Z
Repository: https://github.com/ImageMagick/ImageMagick
Language: C
Files changed: MagickCore/profile.c, coders/tim2.c
Commit date: 2023-05-15 14:22:11 -0400
Commit message: carefully crafted image files (TIM2, JPEG) no longer overflow buffer nor use heap after free (thanks to Juzhi Lu, Zhen Zhou, Likang Luo of NSFOCUS Security Team)

Diff: diff --git a/MagickCore/profile.c b/MagickCore/profile.c
index 57909092d264..382583a52485 100644
--- a/MagickCore/profile.c
+++ b/MagickCore/profile.c
@@ -2456,15 +2456,16 @@ static void ReplaceXmpValue(StringInfo *profile,size_t start,size_t end,
   value_length=strlen(value);
   new_length=length-(end-start)+value_length;
   if (new_length > length)
     SetStringInfoLength(profile,new_length);
   datum=(char *) GetStringInfoDatum(profile);
-  memmove(datum+start+value_length,datum+end,length-end);
-  memcpy(datum+start,value,value_length);
+  (void) memmove(datum+start+value_length,datum+end,length-end);
+  (void) memcpy(datum+start,value,value_length);
   if (new_length < length)
     {
       SetStringInfoLength(profile,new_length);
+      datum=(char *) GetStringInfoDatum(profile);
       *(datum+new_length)='\0';
     }
 }
 
 static MagickBooleanType GetXmpOffsets(const StringInfo *profile,
diff --git a/coders/tim2.c b/coders/tim2.c
index 0445985dcc04..d30afaf05d6b 100644
--- a/coders/tim2.c
+++ b/coders/tim2.c
@@ -515,14 +515,16 @@ static MagickBooleanType ReadTIM2ImageData(const ImageInfo *image_info,
       *clut_data;
 
     /*
       * ### Read CLUT Data ###
       */
-    clut_data=(unsigned char *) AcquireQuantumMemory(1,header->clut_size);
+    clut_data=(unsigned char *) AcquireQuantumMemory(2,
+      MagickMax(header->clut_size,image->colors));
     if (clut_data == (unsigned char *) NULL)
       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
         image_info->filename);
+    (void) memset(clut_data,0,2*MagickMax(header->clut_size,image->colors));
     count=ReadBlob(image,header->clut_size,clut_data);
     if (count != (ssize_t) (header->clut_size))
       {
         clut_data=(unsigned char *) RelinquishMagickMemory(clut_data);
         ThrowBinaryException(CorruptImageError,"InsufficientImageDataInFile",

Vulnerable code:   memmove(datum+start+value_length,datum+end,length-end);
  memcpy(datum+start,value,value_length);
    clut_data=(unsigned char *) AcquireQuantumMemory(1,header->clut_size);
Fixed code:   (void) memmove(datum+start+value_length,datum+end,length-end);
  (void) memcpy(datum+start,value,value_length);
      datum=(char *) GetStringInfoDatum(profile);
    clut_data=(unsigned char *) AcquireQuantumMemory(2,
      MagickMax(header->clut_size,image->colors));
    (void) memset(clut_data,0,2*MagickMax(header->clut_size,image->colors));