Commit 046b7a91b for imagemagick.org

commit 046b7a91b3b903f6a09f3b74286a9d7f3a1feefa
Author: Dirk Lemstra <dirk@lemstra.org>
Date:   Mon Oct 5 22:52:26 2026 +0200

    Fix duplicate post-processing in redirected image reads (#9000).

diff --git a/MagickCore/constitute-private.h b/MagickCore/constitute-private.h
index 98b858a26..30e501da9 100644
--- a/MagickCore/constitute-private.h
+++ b/MagickCore/constitute-private.h
@@ -29,6 +29,9 @@ extern "C" {
 #include "MagickCore/magick-private.h"
 #include "MagickCore/utility.h"

+extern MagickExport Image
+  *ReadImageWithoutPostProcessing(const ImageInfo *,ExceptionInfo *);
+
 static inline Image *StrictReadImage(ImageInfo *image_info,
   ExceptionInfo *exception)
 {
diff --git a/MagickCore/constitute.c b/MagickCore/constitute.c
index 2993213a5..4d6f4d532 100644
--- a/MagickCore/constitute.c
+++ b/MagickCore/constitute.c
@@ -605,8 +605,8 @@ static void SyncResolutionFromProperties(Image *image,
     }
 }

-MagickExport Image *ReadImage(const ImageInfo *image_info,
-  ExceptionInfo *exception)
+static Image *ReadImageInternal(const ImageInfo *image_info,
+  const MagickBooleanType postprocess,ExceptionInfo *exception)
 {
   char
     filename[MagickPathExtent],
@@ -822,7 +822,8 @@ MagickExport Image *ReadImage(const ImageInfo *image_info,
           }
       }
     }
-  if ((IsSceneGeometry(read_info->scenes,MagickFalse) != MagickFalse) &&
+  if ((postprocess != MagickFalse) &&
+      (IsSceneGeometry(read_info->scenes,MagickFalse) != MagickFalse) &&
       (GetImageListLength(image) != 1))
     {
       Image
@@ -860,6 +861,11 @@ MagickExport Image *ReadImage(const ImageInfo *image_info,
       next->magick_columns=next->columns;
     if (next->magick_rows == 0)
       next->magick_rows=next->rows;
+    if (postprocess == MagickFalse)
+      {
+        image=next;
+        continue;
+      }
     (void) GetImageProperty(next,"exif:*",exception);
     (void) GetImageProperty(next,"icc:*",exception);
     (void) GetImageProperty(next,"iptc:*",exception);
@@ -985,6 +991,47 @@ MagickExport Image *ReadImage(const ImageInfo *image_info,
     ThrowReaderException(CorruptImageError,"UnableToReadImageData");
   return(GetFirstImageInList(image));
 }
+
+MagickExport Image *ReadImage(const ImageInfo *image_info,
+  ExceptionInfo *exception)
+{
+  return(ReadImageInternal(image_info,MagickTrue,exception));
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   R e a d I m a g e W i t h o u t P o s t P r o c e s s i n g               %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ReadImageWithoutPostProcessing() reads an intermediate image with format
+%  and source-dimension bookkeeping, leaving scene selection and final
+%  post-processing to the enclosing ReadImage() call.  On failure, a NULL
+%  image is returned and exception describes the reason for the failure.
+%
+%  The format of the ReadImageWithoutPostProcessing method is:
+%
+%      Image *ReadImageWithoutPostProcessing(const ImageInfo *image_info,
+%        ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o image_info: Read the image defined by the file or filename members of
+%      this structure.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport Image *ReadImageWithoutPostProcessing(const ImageInfo *image_info,
+  ExceptionInfo *exception)
+{
+  return(ReadImageInternal(image_info,MagickFalse,exception));
+}

 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/coders/c2pa.c b/coders/c2pa.c
index 923211ad5..87fd2b51d 100644
--- a/coders/c2pa.c
+++ b/coders/c2pa.c
@@ -44,6 +44,7 @@
 #include "MagickCore/blob.h"
 #include "MagickCore/blob-private.h"
 #include "MagickCore/constitute.h"
+#include "MagickCore/constitute-private.h"
 #include "MagickCore/delegate.h"
 #include "MagickCore/exception.h"
 #include "MagickCore/exception-private.h"
@@ -153,7 +154,7 @@ static Image *ReadC2PAImage(const ImageInfo *image_info,
   read_info=CloneImageInfo(image_info);
   SetImageInfoBlob(read_info,(void *) NULL,0);
   *read_info->magick='\0';
-  image=ReadImage(read_info,exception);
+  image=ReadImageWithoutPostProcessing(read_info,exception);
   read_info=DestroyImageInfo(read_info);
   if (image == (Image *) NULL)
     {
diff --git a/coders/cals.c b/coders/cals.c
index 1350b43d3..416d71b57 100644
--- a/coders/cals.c
+++ b/coders/cals.c
@@ -50,6 +50,7 @@
 #include "MagickCore/cache.h"
 #include "MagickCore/colorspace.h"
 #include "MagickCore/constitute.h"
+#include "MagickCore/constitute-private.h"
 #include "MagickCore/exception.h"
 #include "MagickCore/exception-private.h"
 #include "MagickCore/geometry.h"
@@ -278,7 +279,7 @@ static Image *ReadCALSImage(const ImageInfo *image_info,
   (void) FormatLocaleString(message,MagickPathExtent,"%lu",density);
   (void) CloneString(&read_info->density,message);
   read_info->orientation=(OrientationType) orientation;
-  image=ReadImage(read_info,exception);
+  image=ReadImageWithoutPostProcessing(read_info,exception);
   read_info->file=(FILE *) NULL;
   if (image != (Image *) NULL)
     {
diff --git a/coders/dng.c b/coders/dng.c
index a2ba28ef2..037307e78 100644
--- a/coders/dng.c
+++ b/coders/dng.c
@@ -43,6 +43,7 @@
 #include "MagickCore/blob.h"
 #include "MagickCore/blob-private.h"
 #include "MagickCore/constitute.h"
+#include "MagickCore/constitute-private.h"
 #include "MagickCore/delegate.h"
 #include "MagickCore/exception.h"
 #include "MagickCore/exception-private.h"
@@ -257,7 +258,7 @@ static Image *InvokeDNGDelegate(const ImageInfo *image_info,Image *image,
   (void) FormatLocaleString(read_info->filename,MagickPathExtent,"%s.tif",
     read_info->unique);
   sans_exception=AcquireExceptionInfo();
-  image=ReadImage(read_info,sans_exception);
+  image=ReadImageWithoutPostProcessing(read_info,sans_exception);
   sans_exception=DestroyExceptionInfo(sans_exception);
   if (image != (Image *) NULL)
     (void) CopyMagickString(image->magick,read_info->magick,MagickPathExtent);
diff --git a/coders/dot.c b/coders/dot.c
index 9b4e50fd0..5dcd7504e 100644
--- a/coders/dot.c
+++ b/coders/dot.c
@@ -44,6 +44,7 @@
 #include "MagickCore/blob-private.h"
 #include "MagickCore/client.h"
 #include "MagickCore/constitute.h"
+#include "MagickCore/constitute-private.h"
 #include "MagickCore/exception.h"
 #include "MagickCore/exception-private.h"
 #include "MagickCore/image.h"
@@ -160,7 +161,7 @@ static Image *ReadDOTImage(const ImageInfo *image_info,ExceptionInfo *exception)
     Read SVG graph.
   */
   (void) CopyMagickString(read_info->magick,"SVG",MagickPathExtent);
-  image=ReadImage(read_info,exception);
+  image=ReadImageWithoutPostProcessing(read_info,exception);
   (void) RelinquishUniqueFileResource(read_info->filename);
   read_info=DestroyImageInfo(read_info);
   if (image == (Image *) NULL)
diff --git a/coders/fax.c b/coders/fax.c
index 50ce57a4a..30f2d16a3 100644
--- a/coders/fax.c
+++ b/coders/fax.c
@@ -47,6 +47,7 @@
 #include "MagickCore/colorspace.h"
 #include "MagickCore/colorspace-private.h"
 #include "MagickCore/constitute.h"
+#include "MagickCore/constitute-private.h"
 #include "MagickCore/exception.h"
 #include "MagickCore/exception-private.h"
 #include "MagickCore/compress.h"
@@ -168,7 +169,7 @@ static Image* FaxReadG4(Image *image,const ImageInfo *image_info,
   (void) FormatLocaleString(read_info->filename,MagickPathExtent,"group4:%s",
     filename);
   read_info->orientation=TopLeftOrientation;
-  image=ReadImage(read_info,exception);
+  image=ReadImageWithoutPostProcessing(read_info,exception);
   if (image != (Image *) NULL)
     {
       (void) CopyMagickString(image->filename,image_info->filename,
diff --git a/coders/jpeg.c b/coders/jpeg.c
index d47da2f0e..177166e37 100644
--- a/coders/jpeg.c
+++ b/coders/jpeg.c
@@ -56,6 +56,7 @@
 #include "MagickCore/colorspace.h"
 #include "MagickCore/colorspace-private.h"
 #include "MagickCore/constitute.h"
+#include "MagickCore/constitute-private.h"
 #include "MagickCore/exception.h"
 #include "MagickCore/exception-private.h"
 #include "MagickCore/geometry.h"
@@ -439,7 +440,7 @@ static Image *ReadUltraHDRJPEGImage(const ImageInfo *image_info,
   uhdr_info=CloneImageInfo(image_info);
   SetUltraHDRCoderFilename(uhdr_info,image_info->filename);
   (void) SetImageOption(uhdr_info,"jpeg:detect-uhdr","false");
-  images=ReadImage(uhdr_info,exception);
+  images=ReadImageWithoutPostProcessing(uhdr_info,exception);
   uhdr_info=DestroyImageInfo(uhdr_info);
   return(images);
 }
diff --git a/coders/ora.c b/coders/ora.c
index 50c6dd001..1f38ceac2 100644
--- a/coders/ora.c
+++ b/coders/ora.c
@@ -46,6 +46,7 @@
 #include "MagickCore/blob.h"
 #include "MagickCore/blob-private.h"
 #include "MagickCore/constitute.h"
+#include "MagickCore/constitute-private.h"
 #include "MagickCore/exception.h"
 #include "MagickCore/exception-private.h"
 #include "MagickCore/image.h"
@@ -228,9 +229,9 @@ static Image *ReadORAImage(const ImageInfo *image_info,
       image_metadata=DestroyImage(image_metadata);
       return((Image *) NULL);
     }
-  /* Delegate to ReadImage to read mergedimage.png */
+  /* Read mergedimage.png without applying the caller's options yet. */
   read_info->file=file;
-  out_image=ReadImage(read_info,exception);
+  out_image=ReadImageWithoutPostProcessing(read_info,exception);
   (void) RelinquishUniqueFileResource(read_info->filename);
   read_info=DestroyImageInfo(read_info);
   /* Update fields of image from fields of png_image */
diff --git a/coders/pcl.c b/coders/pcl.c
index 10c8b7271..9ccd7b15a 100644
--- a/coders/pcl.c
+++ b/coders/pcl.c
@@ -50,6 +50,7 @@
 #include "MagickCore/colorspace.h"
 #include "MagickCore/colorspace-private.h"
 #include "MagickCore/constitute.h"
+#include "MagickCore/constitute-private.h"
 #include "MagickCore/delegate.h"
 #include "MagickCore/draw.h"
 #include "MagickCore/exception.h"
@@ -374,7 +375,7 @@ static Image *ReadPCLImage(const ImageInfo *image_info,ExceptionInfo *exception)
       read_info=DestroyImageInfo(read_info);
       ThrowReaderException(DelegateError,"PCLDelegateFailed");
     }
-  image=ReadImage(read_info,exception);
+  image=ReadImageWithoutPostProcessing(read_info,exception);
   (void) RelinquishUniqueFileResource(read_info->filename);
   (void) RelinquishUniqueFileResource(input_filename);
   read_info=DestroyImageInfo(read_info);
diff --git a/coders/pdf.c b/coders/pdf.c
index bf71dc47f..480d445a2 100644
--- a/coders/pdf.c
+++ b/coders/pdf.c
@@ -52,6 +52,7 @@
 #include "MagickCore/colorspace-private.h"
 #include "MagickCore/compress.h"
 #include "MagickCore/constitute.h"
+#include "MagickCore/constitute-private.h"
 #include "MagickCore/distort.h"
 #include "MagickCore/draw.h"
 #include "MagickCore/exception.h"
@@ -681,7 +682,7 @@ static Image *ReadPDFImage(const ImageInfo *image_info,ExceptionInfo *exception)
           break;
         read_info->blob=NULL;
         read_info->length=0;
-        next=ReadImage(read_info,exception);
+        next=ReadImageWithoutPostProcessing(read_info,exception);
         (void) RelinquishUniqueFileResource(read_info->filename);
         if (next == (Image *) NULL)
           break;
diff --git a/coders/ps.c b/coders/ps.c
index aee6cda33..2b36cceab 100644
--- a/coders/ps.c
+++ b/coders/ps.c
@@ -50,6 +50,7 @@
 #include "MagickCore/colorspace.h"
 #include "MagickCore/colorspace-private.h"
 #include "MagickCore/constitute.h"
+#include "MagickCore/constitute-private.h"
 #include "MagickCore/delegate.h"
 #include "MagickCore/delegate-private.h"
 #include "MagickCore/draw.h"
@@ -854,7 +855,7 @@ static Image *ReadPSImage(const ImageInfo *image_info,ExceptionInfo *exception)
         break;
       read_info->blob=NULL;
       read_info->length=0;
-      next=ReadImage(read_info,exception);
+      next=ReadImageWithoutPostProcessing(read_info,exception);
       (void) RelinquishUniqueFileResource(read_info->filename);
       if (next == (Image *) NULL)
         break;
diff --git a/coders/svg.c b/coders/svg.c
index 174d4755d..9b84bb269 100644
--- a/coders/svg.c
+++ b/coders/svg.c
@@ -337,7 +337,7 @@ static Image *RenderSVGImage(const ImageInfo *image_info,Image *image,
       read_info=CloneImageInfo(image_info);
       (void) CopyMagickString(read_info->filename,output_filename,
         MagickPathExtent);
-      svg_image=ReadImage(read_info,exception);
+      svg_image=ReadImageWithoutPostProcessing(read_info,exception);
       read_info=DestroyImageInfo(read_info);
       if (svg_image != (Image *) NULL)
         {
@@ -3278,7 +3278,7 @@ static Image *RenderMSVGImage(const ImageInfo *image_info,Image *image,
       read_info->file=file;
       (void) FormatLocaleString(read_info->filename,MagickPathExtent,"mvg:%s",
         filename);
-      image=ReadImage(read_info,exception);
+      image=ReadImageWithoutPostProcessing(read_info,exception);
       read_info=DestroyImageInfo(read_info);
       if (image != (Image *) NULL)
         (void) CopyMagickString(image->filename,image_info->filename,
diff --git a/coders/tiff.c b/coders/tiff.c
index f0d9d22b9..318e16567 100644
--- a/coders/tiff.c
+++ b/coders/tiff.c
@@ -55,6 +55,7 @@
 #include "MagickCore/colorspace.h"
 #include "MagickCore/colorspace-private.h"
 #include "MagickCore/constitute.h"
+#include "MagickCore/constitute-private.h"
 #include "MagickCore/enhance.h"
 #include "MagickCore/exception.h"
 #include "MagickCore/exception-private.h"
@@ -1270,7 +1271,7 @@ static Image *ReadTIFFImage(const ImageInfo *image_info,
       (void) CopyMagickString(read_info->magick,"DNG",MagickPathExtent);
       TIFFClose(tiff);
       if (*read_info->filename != '\0')
-        dng_image=ReadImage(read_info,exception);
+        dng_image=ReadImageWithoutPostProcessing(read_info,exception);
       else
         {
           status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
@@ -1278,7 +1279,7 @@ static Image *ReadTIFFImage(const ImageInfo *image_info,
             {
               status=ImageToFile(image,read_info->filename,exception);
               if (status != MagickFalse)
-                dng_image=ReadImage(read_info,exception);
+                dng_image=ReadImageWithoutPostProcessing(read_info,exception);
               (void) RelinquishUniqueFileResource(read_info->filename);
             }
         }
diff --git a/coders/url.c b/coders/url.c
index 1a3df6975..1c6951bb9 100644
--- a/coders/url.c
+++ b/coders/url.c
@@ -44,6 +44,7 @@
 #include "MagickCore/blob.h"
 #include "MagickCore/blob-private.h"
 #include "MagickCore/constitute.h"
+#include "MagickCore/constitute-private.h"
 #include "MagickCore/delegate.h"
 #include "MagickCore/exception.h"
 #include "MagickCore/exception-private.h"
@@ -112,7 +113,7 @@ static Image *InvokeURLDelegate(ImageInfo *read_info,Image *image,
       (void) FormatLocaleString(read_info->filename,MagickPathExtent,
         "%s.dat",read_info->unique);
       *read_info->magick='\0';
-      images=ReadImage(read_info,exception);
+      images=ReadImageWithoutPostProcessing(read_info,exception);
       (void) RelinquishUniqueFileResource(read_info->filename);
       if (images != (Image *) NULL)
         for (next=images; next != (Image *) NULL; next=next->next)
@@ -167,7 +168,7 @@ static Image *ReadURLImage(const ImageInfo *image_info,ExceptionInfo *exception)
       (void) CopyMagickString(read_info->filename,image_info->filename+2,
         MagickPathExtent);
       *read_info->magick='\0';
-      images=ReadImage(read_info,exception);
+      images=ReadImageWithoutPostProcessing(read_info,exception);
       read_info=DestroyImageInfo(read_info);
       image=DestroyImage(image);
       return(GetFirstImageInList(images));
@@ -204,7 +205,7 @@ static Image *ReadURLImage(const ImageInfo *image_info,ExceptionInfo *exception)
   (void) fclose(file);
 #endif
   *read_info->magick='\0';
-  images=ReadImage(read_info,exception);
+  images=ReadImageWithoutPostProcessing(read_info,exception);
   (void) RelinquishUniqueFileResource(read_info->filename);
   if (images != (Image *) NULL)
     for (next=images; next != (Image *) NULL; next=next->next)
diff --git a/coders/video.c b/coders/video.c
index 59d366953..b924cf0a1 100644
--- a/coders/video.c
+++ b/coders/video.c
@@ -42,6 +42,7 @@
 #include "MagickCore/blob.h"
 #include "MagickCore/blob-private.h"
 #include "MagickCore/constitute.h"
+#include "MagickCore/constitute-private.h"
 #include "MagickCore/delegate.h"
 #include "MagickCore/exception.h"
 #include "MagickCore/exception-private.h"
@@ -270,7 +271,7 @@ static Image *ReadVIDEOImage(const ImageInfo *image_info,
             MagickPathExtent);
           (void) CopyMagickString(read_info->filename,read_info->unique,
             MagickPathExtent);
-          images=ReadImage(read_info,exception);
+          images=ReadImageWithoutPostProcessing(read_info,exception);
         }
       else
         if (*message != '\0')
diff --git a/coders/wmf.c b/coders/wmf.c
index 23a0500c1..906072bea 100644
--- a/coders/wmf.c
+++ b/coders/wmf.c
@@ -44,6 +44,7 @@
 #include "MagickCore/color.h"
 #include "MagickCore/color-private.h"
 #include "MagickCore/constitute.h"
+#include "MagickCore/constitute-private.h"
 #include "MagickCore/exception.h"
 #include "MagickCore/exception-private.h"
 #include "MagickCore/image.h"
@@ -226,7 +227,7 @@ static Image *ReadWMFImage(const ImageInfo *image_info,ExceptionInfo *exception)
   SetImageInfoBlob(read_info,(void *) NULL,0);
   (void) FormatLocaleString(read_info->filename,MagickPathExtent,"eps:%s",
     filename);
-  image=ReadImage(read_info,exception);
+  image=ReadImageWithoutPostProcessing(read_info,exception);
   read_info=DestroyImageInfo(read_info);
   if (image != (Image *) NULL)
     {
diff --git a/coders/xps.c b/coders/xps.c
index 35f16cd9a..6ea7b425c 100644
--- a/coders/xps.c
+++ b/coders/xps.c
@@ -50,6 +50,7 @@
 #include "MagickCore/colorspace.h"
 #include "MagickCore/colorspace-private.h"
 #include "MagickCore/constitute.h"
+#include "MagickCore/constitute-private.h"
 #include "MagickCore/delegate.h"
 #include "MagickCore/delegate-private.h"
 #include "MagickCore/draw.h"
@@ -325,7 +326,7 @@ static Image *ReadXPSImage(const ImageInfo *image_info,ExceptionInfo *exception)
         break;
       read_info->blob=NULL;
       read_info->length=0;
-      next=ReadImage(read_info,exception);
+      next=ReadImageWithoutPostProcessing(read_info,exception);
       (void) RelinquishUniqueFileResource(read_info->filename);
       if (next == (Image *) NULL)
         break;