Version in base suite: 7.1.1.43+dfsg1-1+deb13u12 Base version: imagemagick_7.1.1.43+dfsg1-1+deb13u12 Target version: imagemagick_7.1.1.43+dfsg1-1+deb13u13 Base file: /srv/ftp-master.debian.org/ftp/pool/main/i/imagemagick/imagemagick_7.1.1.43+dfsg1-1+deb13u12.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/i/imagemagick/imagemagick_7.1.1.43+dfsg1-1+deb13u13.dsc changelog | 154 +++ patches/CVE-2026-102635_1.patch | 207 ++++ patches/CVE-2026-102635_2.patch | 225 ++++ patches/CVE-2026-102635_3.patch | 40 patches/CVE-2026-106564.patch | 49 + patches/CVE-2026-106565.patch | 39 patches/CVE-2026-106566.patch | 28 patches/CVE-2026-106567.patch | 54 + patches/CVE-2026-106568.patch | 76 + patches/CVE-2026-106571-pre1.patch | 74 + patches/CVE-2026-106571.patch | 66 + patches/CVE-2026-106572.patch | 29 patches/CVE-2026-106573.patch | 95 ++ patches/CVE-2026-106574.patch | 37 patches/CVE-2026-106575.patch | 37 patches/CVE-2026-106576.patch | 120 ++ patches/CVE-2026-106577_1.patch | 38 patches/CVE-2026-106577_2.patch | 102 ++ patches/CVE-2026-106577_pre1.patch | 219 ++++ patches/CVE-2026-106578.patch | 27 patches/CVE-2026-106579-pre1.patch | 101 ++ patches/CVE-2026-106579_1.patch | 24 patches/CVE-2026-106579_2.patch | 33 patches/CVE-2026-106580_1.patch | 59 + patches/CVE-2026-106580_2.patch | 180 +++ patches/CVE-2026-107208_1.patch | 799 +++++++++++++++++ patches/CVE-2026-107208_2.patch | 24 patches/CVE-2026-107209.patch | 36 patches/CVE-2026-107210-pre1.patch | 51 + patches/CVE-2026-107210.patch | 179 +++ patches/CVE-2026-109261.patch | 32 patches/CVE-2026-25971-post1.patch | 47 + patches/CVE-2026-62343.patch | 239 +++++ patches/CVE-2026-62363_1.patch | 98 ++ patches/CVE-2026-62363_2.patch | 97 ++ patches/CVE-2026-62946.patch | 29 patches/CVE-2026-64685.patch | 56 + patches/CVE-2026-86420.patch | 27 patches/CVE-2026-86421.patch | 27 patches/CVE-2026-86423.patch | 144 +++ patches/CVE-2026-86424.patch | 117 ++ patches/CVE-2026-86424_pre1.patch | 29 patches/CVE-2026-86424_pre2.patch | 487 ++++++++++ patches/CVE-2026-86424_pre3.patch | 385 ++++++++ patches/CVE-2026-86424_pre4.patch | 26 patches/CVE-2026-86424_pre5.patch | 278 ++++++ patches/CVE-2026-86424_pre6.patch | 74 + patches/CVE-2026-86425.patch | 40 patches/CVE-2026-93586_1.patch | 140 +++ patches/CVE-2026-93586_2.patch | 165 +++ patches/CVE-2026-93587_1.patch | 31 patches/CVE-2026-93587_2.patch | 50 + patches/CVE-2026-93588.patch | 43 patches/CVE-2026-93589.patch | 29 patches/CVE-2026-93590.patch | 26 patches/GHSA-83w9-w85j-h9jc-1.patch | 28 patches/GHSA-83w9-w85j-h9jc.patch | 31 patches/coders-mat-c-7.1.2.33.patch | 109 ++ patches/port-distribute-cache-7.1.2.33.patch | 1226 +++++++++++++++++++++++++++ patches/series | 58 + 60 files changed, 7370 insertions(+) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpdbzs0ugk/imagemagick_7.1.1.43+dfsg1-1+deb13u12.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpdbzs0ugk/imagemagick_7.1.1.43+dfsg1-1+deb13u13.dsc: no acceptable signature found diff -Nru imagemagick-7.1.1.43+dfsg1/debian/changelog imagemagick-7.1.1.43+dfsg1/debian/changelog --- imagemagick-7.1.1.43+dfsg1/debian/changelog 2026-07-21 07:55:59.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/changelog 2026-10-23 19:46:42.000000000 +0000 @@ -1,3 +1,157 @@ +imagemagick (8:7.1.1.43+dfsg1-1+deb13u13) trixie-security; urgency=medium + + * Security fixes (Closes: #1147176, #1149974, #1150337) + * Fix regression of CVE-2026-25971: + SVG with data: URI fails ("unable to open image") + (Closes: #1150224) + * Port distribute cache to 7.1.2.33 + * Port coders/mat.c to 7.1.2.33 + * Fix CVE-2026-62343: + An invalid kernel can cause a heap buffer over-write + when performing a morphology operation with a user supplied kernel. + * Fix CVE-2026-62946: + Processing an extremely large JNX file on 32-bit platforms + can cause an integer overflow, leading to a heap buffer over-write. + * Fix CVE-2026-62363: + A heap buffer over-write can occur in the fx operation by + passing a crafted argument. + * Fix CVE-2026-64685: + The BGR decoder does not check for an end-of-file in every location + so a crafted image could result in an heap buffer over-read. + * Fix CVE-2026-86420: + Imagemagick fails to properly lower the memory budget when + an operation inside OpenPixelCache fails. Repeated triggering + of such failures can exhaust the process memory budget and + result in a denial of service. + * Fix CVE-2026-86421 + Fix a memory leak in the MSL image decoder. + A crafted MSL image triggers memory allocation + without proper deallocation, allowing an attacker to + exhaust memory and cause a denial of service. + * Fix CVE-2026-86423: + a heap-use-after-free vulnerability in the GetList method + of PerlMagick. A crafted call to the GetList method can + trigger the use-after-free, resulting in a crash + (denial of service). + * Fix CVE-2026-86424: + A time-of-check-time-of-use (TOCTOU) vulnerability in the video + decoder that allows attackers to bypass path policy write + restrictions via symlink swaps + * Fix CVE-2026-86425: + A heap-use-after-free vulnerability in the Layer method of PerlMagick. + * Fix CVE-2026-93586: + A use-after-free vulnerability in the ImagesToBlob method, caused by a + pointer that is not updated correctly. Exploitation may result in + a limited availability impact (e.g., a crash of the affected process). + * Fix CVE-2026-93587: + A policy bypass in the PCD (and, per the upstream advisory, CUBE and HALD) + coder: when a specific command line option is supplied, the decoder + does not check a configured resource limit, which can result + in extra memory allocation. + * Fix CVE-2026-93588: + a NULL pointer dereference in the PNM coder. When the coder reaches + a memory (resource) limit at a specific point during processing, + the failed allocation is not handled and a NULL pointer is dereferenced, + which can lead to a denial of service (application crash) when + processing a specially crafted or sufficiently large PNM image. + * Fix CVE-2026-93589: + A division-by-zero flaw in the FLIF encoder. An incorrect value for + ticks per second in the image being encoded causes a divide-by-zero + and crashes the encoder, resulting in a denial of service. + * Fix CVE-2026-93590: + a policy bypass vulnerability in the UHDR encoder that fails + to perform policy checks during buffer allocation for image pixels. + Attackers can bypass resource policies by processing specially crafted + UHDR images, potentially causing denial of service through + excessive memory allocation. + * Fix CVE-2026-102635: + imagemagick contain uninitialized heap memory disclosure in the GIF + decoder's application extension handler in coders/gif.c. + Attackers can craft malicious GIF files that cause the number + parser to read uninitialized heap memory and store contents + as image metadata, disclosing sensitive heap information. + * Fix CVE-2026-106564: + A crafted EXR image can cause the EXR decoder to write beyond a + heap buffer, causing the process to crash. + * Fix CVE-2026-106565: + A missing end-of-file check while reading bzip2-compressed + image data can cause an infinite loop and exhaust processing resources. + * Fix CVE-2026-106566: + Delegate symlink cleanup does not check the MAGICK_SHRED_PASSES + environment variable, allowing a local privileged workflow to + overwrite a file with random data. + * Fix CVE-2026-106567: + A crafted PSD file can trigger an integer-conversion error + in the PSD decoder on 32-bit builds, causing an infinite + loop and denial of service. + * Fix CVE-2026-106568: + A crafted XMP profile embedded in an image can cause + the profile parser to enter an infinite loop, preventing image + processing from completing. + * Fix CVE-2026-106570: + An unauthenticated adjacent-network client can repeatedly connect + to the distributed pixel cache server and exhaust its available + connections, causing denial of service. + * Fix CVE-2026-106571: + A crafted local call to the GetVirtualPixels API can trigger + an integer calculation error and write beyond a heap buffer, + crashing the server process. + * Fix CVE-2026-106572: + A missing recursion-depth check in the CALS decoder + allows a crafted CALS image to exhaust the call stack + and terminate the process. + * Fix CVE-2026-106573: + a missing limit check in the MVG decoder allows a crafted MVG + image to trigger an excessively long-running operation. + * Fix CVE-2026-106574: + A client connected to the distributed pixel cache server + can send crafted pixel data that triggers an integer-size + calculation error and a heap buffer overwrite, crashing the server. + * Fix CVE-2026-106575: + A crafted Magick script can cause an opened file pointer + to remain unclosed, allowing repeated processing to exhaust + available file descriptors + * Fix CVE-2026-106576: + A crafted XMP profile can trigger excessive work while the + parser determines a rational value's numerator and denominator, + causing denial of service + * Fix CVE-2026-106577: + Unescaped or untrimmed values can inject code into output + generated by PostScript coders. + * Fix CVE-2026-106578: + A crafted image can cause an invalid memory free in the + MVG decoder and crash the process + * Fix CVE-2026-106579: + a crafted image can bypass an ImageMagick security policy that + uses coder as its domain, potentially allowing data prohibited + by the policy to be read. + * Fix CVE-2026-106580: + a missing security-policy check in the CUT encoder allows a + crafted local encoding operation to read data that policy should + deny and can also cause a crash. + * Fix CVE-2026-107208: + Denial of service with crafted XMP profile + * Fix CVE-2026-107209: + when ImageMagick is built without Cairo support, a crafted + RSVG image that reaches a resource limit can cause the + RSVG decoder to free image state twice and then use freed memory, + crashing the process + * Fix CVE-2026-107210: + A crafted highly compressed MAT image can make the MAT decoder + create temporary files larger than the configured security-policy + limit, bypassing resource restrictions and consuming excessive + disk space. + * Fix CVE-2026-109261: + imagemagick contains a memory leak in the GIF encoder + because allocated memory is not released when color quantization + fails during encoding. Attackers can supply images whose + GIF conversion causes quantization to fail, leaking memory + with each attempt and degrading availability. + * Fix GHSA-83w9-w85j-h9jc: + Memory Leak in MAT decoder in an error path. + + -- Bastien Roucariès Fri, 23 Oct 2026 21:46:42 +0200 + imagemagick (8:7.1.1.43+dfsg1-1+deb13u12) trixie; urgency=medium * Fix CVE-2026-56362: diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-102635_1.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-102635_1.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-102635_1.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-102635_1.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,207 @@ +From: Cristy +Date: Fri, 18 Sep 2026 10:22:15 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-rvv7-5mh8-vcfc + +(cherry picked from commit a0ca2c739c0216ff4efbd631d1ba7fd54dba1ff4) +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-rvv7-5mh8-vcfc +origin: https://github.com/ImageMagick/ImageMagick/commit/a0ca2c739c0216ff4efbd631d1ba7fd54dba1ff4 +--- + coders/gif.c | 168 +++++++++++++++++++++++++++++++---------------------------- + 1 file changed, 89 insertions(+), 79 deletions(-) + +diff --git a/coders/gif.c b/coders/gif.c +index 7cc2af9..7bfae65 100644 +--- a/coders/gif.c ++++ b/coders/gif.c +@@ -1118,101 +1118,111 @@ static Image *ReadGIFImage(const ImageInfo *image_info,ExceptionInfo *exception) + } + case 0xff: + { ++ char ++ name[MagickPathExtent]; ++ + MagickBooleanType +- loop; ++ magick = MagickFalse; ++ ++ size_t ++ block_length, ++ info_length, ++ reserved_length; ++ ++ unsigned char ++ *info; + + /* +- Read Netscape Loop extension. ++ Store GIF application extension as a generic profile. + */ +- loop=MagickFalse; +- if (ReadBlobBlock(image,buffer) != 0) +- loop=LocaleNCompare((char *) buffer,"NETSCAPE2.0",11) == 0 ? +- MagickTrue : MagickFalse; +- if (loop != MagickFalse) +- while (ReadBlobBlock(image,buffer) != 0) +- { +- meta_image->iterations=((size_t) buffer[2] << 8) | buffer[1]; +- if (meta_image->iterations != 0) +- meta_image->iterations++; +- } ++ if (LocaleNCompare((char *) buffer,"ImageMagick",11) == 0) ++ magick=MagickTrue; ++ else if (LocaleNCompare((char *) buffer,"ICCRGBG1012",11) == 0) ++ (void) CopyMagickString(name,"icc",sizeof(name)); ++ else if (LocaleNCompare((char *) buffer,"MGK8BIM0000",11) == 0) ++ (void) CopyMagickString(name,"8bim",sizeof(name)); ++ else if (LocaleNCompare((char *) buffer,"MGKIPTC0000",11) == 0) ++ (void) CopyMagickString(name,"iptc",sizeof(name)); + else +- { +- char +- name[MagickPathExtent]; +- +- int +- block_length, +- info_length, +- reserved_length; +- +- MagickBooleanType +- magick = MagickFalse; +- +- unsigned char +- *info; ++ (void) FormatLocaleString(name,sizeof(name),"gif:%.11s", ++ buffer); ++ reserved_length=256; ++ info=(unsigned char *) AcquireQuantumMemory(reserved_length, ++ sizeof(*info)); ++ if (info == (unsigned char *) NULL) ++ ThrowGIFException(ResourceLimitError,"MemoryAllocationFailed"); ++ info[0]='\0'; ++ info_length=0; ++ for ( ; ; ) ++ { ++ unsigned char ++ *new_info; + +- /* +- Store GIF application extension as a generic profile. +- */ +- if (LocaleNCompare((char *) buffer,"ImageMagick",11) == 0) +- magick=MagickTrue; +- else if (LocaleNCompare((char *) buffer,"ICCRGBG1012",11) == 0) +- (void) CopyMagickString(name,"icc",sizeof(name)); +- else if (LocaleNCompare((char *) buffer,"MGK8BIM0000",11) == 0) +- (void) CopyMagickString(name,"8bim",sizeof(name)); +- else if (LocaleNCompare((char *) buffer,"MGKIPTC0000",11) == 0) +- (void) CopyMagickString(name,"iptc",sizeof(name)); +- else +- (void) FormatLocaleString(name,sizeof(name),"gif:%.11s", +- buffer); +- reserved_length=255; +- info=(unsigned char *) AcquireQuantumMemory((size_t) +- reserved_length,sizeof(*info)); +- if (info == (unsigned char *) NULL) ++ /* ++ Read into a fixed-size scratch buffer first. This prevents ++ ReadBlobBlock() from writing beyond the current allocation. ++ */ ++ count=ReadBlobBlock(image,buffer); ++ if (count <= 0) ++ break; ++ block_length=(size_t) count; ++ if (block_length > (SIZE_MAX-info_length-1)) ++ { ++ info=(unsigned char *) ++ RelinquishMagickMemory(info); + ThrowGIFException(ResourceLimitError, + "MemoryAllocationFailed"); +- (void) memset(info,0,(size_t) reserved_length*sizeof(*info)); +- for (info_length=0; ; ) ++ } ++ if ((info_length+block_length+1) > reserved_length) + { +- block_length=(int) ReadBlobBlock(image,info+info_length); +- if (block_length == 0) +- break; +- info_length+=block_length; +- if (info_length > (reserved_length-255)) ++ size_t ++ new_length; ++ new_length=info_length+block_length+1; ++ if (new_length <= (SIZE_MAX-4095)) ++ new_length=(new_length+4095) & ~((size_t) 4095); ++ new_info=(unsigned char *) ResizeQuantumMemory(info, ++ new_length,sizeof(*info)); ++ if (new_info == (unsigned char *) NULL) + { +- reserved_length+=4096; +- info=(unsigned char *) ResizeQuantumMemory(info,(size_t) +- reserved_length,sizeof(*info)); +- if (info == (unsigned char *) NULL) +- { +- info=(unsigned char *) RelinquishMagickMemory(info); +- ThrowGIFException(ResourceLimitError, +- "MemoryAllocationFailed"); +- } ++ info=(unsigned char *) ++ RelinquishMagickMemory(info); ++ ThrowGIFException(ResourceLimitError, ++ "MemoryAllocationFailed"); + } ++ info=new_info; ++ reserved_length=new_length; + } +- if (magick != MagickFalse) ++ (void) memcpy(info+info_length,buffer,block_length); ++ info_length+=block_length; ++ info[info_length]='\0'; ++ } ++ if (magick != MagickFalse) ++ { ++ /* ++ ImageMagick writes this extension as "gamma=". ++ Require that prefix and a nonempty, bounded value. ++ */ ++ if ((info_length > 6) && ++ (LocaleNCompare((char *) info,"gamma=",6) == 0)) + meta_image->gamma=StringToDouble((char *) info+6, +- (char **) NULL); +- else ++ (char **) NULL); ++ } ++ else ++ { ++ StringInfo ++ *profile; ++ (void) LogMagickEvent(CoderEvent,GetMagickModule(), ++ " profile name=%s",name); ++ profile=BlobToProfileStringInfo(name,info,info_length, ++ exception); ++ if (profile != (StringInfo *) NULL) + { +- StringInfo +- *profile; +- +- (void) LogMagickEvent(CoderEvent,GetMagickModule(), +- " profile name=%s",name); +- profile=BlobToProfileStringInfo(name,info,(size_t) info_length, +- exception); +- if (profile != (StringInfo *) NULL) +- { +- if (profiles == (LinkedListInfo *) NULL) +- profiles=NewLinkedList(0); +- (void) AppendValueToLinkedList(profiles,profile); +- } ++ if (profiles == (LinkedListInfo *) NULL) ++ profiles=NewLinkedList(0); ++ (void) AppendValueToLinkedList(profiles,profile); + } +- info=(unsigned char *) RelinquishMagickMemory(info); + } +- break; ++ info=(unsigned char *) RelinquishMagickMemory(info); + } + default: + { diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-102635_2.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-102635_2.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-102635_2.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-102635_2.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,225 @@ +From: Cristy +Date: Fri, 18 Sep 2026 13:54:55 -0400 +Subject: revert + +(cherry picked from commit 87d251de1664c5ba71064912fd4cc419a983d105) + +[debian] +this a partial revert resulting is: +# diff --git a/coders/gif.c b/coders/gif.c +# index 7cc2af9403..ca0bf0ed2f 100644 +# --- a/coders/gif.c +# +++ b/coders/gif.c +# @@ -1165,7 +1165,7 @@ static Image *ReadGIFImage(const ImageInfo *image_info,ExceptionInfo *exception) +# else +# (void) FormatLocaleString(name,sizeof(name),"gif:%.11s", +# buffer); +# - reserved_length=255; +# + reserved_length=256; +# info=(unsigned char *) AcquireQuantumMemory((size_t) +# reserved_length,sizeof(*info)); +# if (info == (unsigned char *) NULL) + +see https://github.com/ImageMagick/ImageMagick/issues/9043 + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-rvv7-5mh8-vcfc +origin: https://github.com/ImageMagick/ImageMagick/commit/a0ca2c739c0216ff4efbd631d1ba7fd54dba1ff4 +--- + coders/gif.c | 168 ++++++++++++++++++++++++++++------------------------------- + 1 file changed, 79 insertions(+), 89 deletions(-) + +diff --git a/coders/gif.c b/coders/gif.c +index 7bfae65..ca0bf0e 100644 +--- a/coders/gif.c ++++ b/coders/gif.c +@@ -1118,111 +1118,101 @@ static Image *ReadGIFImage(const ImageInfo *image_info,ExceptionInfo *exception) + } + case 0xff: + { +- char +- name[MagickPathExtent]; +- + MagickBooleanType +- magick = MagickFalse; +- +- size_t +- block_length, +- info_length, +- reserved_length; +- +- unsigned char +- *info; ++ loop; + + /* +- Store GIF application extension as a generic profile. ++ Read Netscape Loop extension. + */ +- if (LocaleNCompare((char *) buffer,"ImageMagick",11) == 0) +- magick=MagickTrue; +- else if (LocaleNCompare((char *) buffer,"ICCRGBG1012",11) == 0) +- (void) CopyMagickString(name,"icc",sizeof(name)); +- else if (LocaleNCompare((char *) buffer,"MGK8BIM0000",11) == 0) +- (void) CopyMagickString(name,"8bim",sizeof(name)); +- else if (LocaleNCompare((char *) buffer,"MGKIPTC0000",11) == 0) +- (void) CopyMagickString(name,"iptc",sizeof(name)); ++ loop=MagickFalse; ++ if (ReadBlobBlock(image,buffer) != 0) ++ loop=LocaleNCompare((char *) buffer,"NETSCAPE2.0",11) == 0 ? ++ MagickTrue : MagickFalse; ++ if (loop != MagickFalse) ++ while (ReadBlobBlock(image,buffer) != 0) ++ { ++ meta_image->iterations=((size_t) buffer[2] << 8) | buffer[1]; ++ if (meta_image->iterations != 0) ++ meta_image->iterations++; ++ } + else +- (void) FormatLocaleString(name,sizeof(name),"gif:%.11s", +- buffer); +- reserved_length=256; +- info=(unsigned char *) AcquireQuantumMemory(reserved_length, +- sizeof(*info)); +- if (info == (unsigned char *) NULL) +- ThrowGIFException(ResourceLimitError,"MemoryAllocationFailed"); +- info[0]='\0'; +- info_length=0; +- for ( ; ; ) +- { +- unsigned char +- *new_info; ++ { ++ char ++ name[MagickPathExtent]; + +- /* +- Read into a fixed-size scratch buffer first. This prevents +- ReadBlobBlock() from writing beyond the current allocation. +- */ +- count=ReadBlobBlock(image,buffer); +- if (count <= 0) +- break; +- block_length=(size_t) count; +- if (block_length > (SIZE_MAX-info_length-1)) +- { +- info=(unsigned char *) +- RelinquishMagickMemory(info); ++ int ++ block_length, ++ info_length, ++ reserved_length; ++ ++ MagickBooleanType ++ magick = MagickFalse; ++ ++ unsigned char ++ *info; ++ ++ /* ++ Store GIF application extension as a generic profile. ++ */ ++ if (LocaleNCompare((char *) buffer,"ImageMagick",11) == 0) ++ magick=MagickTrue; ++ else if (LocaleNCompare((char *) buffer,"ICCRGBG1012",11) == 0) ++ (void) CopyMagickString(name,"icc",sizeof(name)); ++ else if (LocaleNCompare((char *) buffer,"MGK8BIM0000",11) == 0) ++ (void) CopyMagickString(name,"8bim",sizeof(name)); ++ else if (LocaleNCompare((char *) buffer,"MGKIPTC0000",11) == 0) ++ (void) CopyMagickString(name,"iptc",sizeof(name)); ++ else ++ (void) FormatLocaleString(name,sizeof(name),"gif:%.11s", ++ buffer); ++ reserved_length=256; ++ info=(unsigned char *) AcquireQuantumMemory((size_t) ++ reserved_length,sizeof(*info)); ++ if (info == (unsigned char *) NULL) + ThrowGIFException(ResourceLimitError, + "MemoryAllocationFailed"); +- } +- if ((info_length+block_length+1) > reserved_length) ++ (void) memset(info,0,(size_t) reserved_length*sizeof(*info)); ++ for (info_length=0; ; ) + { +- size_t +- new_length; +- new_length=info_length+block_length+1; +- if (new_length <= (SIZE_MAX-4095)) +- new_length=(new_length+4095) & ~((size_t) 4095); +- new_info=(unsigned char *) ResizeQuantumMemory(info, +- new_length,sizeof(*info)); +- if (new_info == (unsigned char *) NULL) ++ block_length=(int) ReadBlobBlock(image,info+info_length); ++ if (block_length == 0) ++ break; ++ info_length+=block_length; ++ if (info_length > (reserved_length-255)) + { +- info=(unsigned char *) +- RelinquishMagickMemory(info); +- ThrowGIFException(ResourceLimitError, +- "MemoryAllocationFailed"); ++ reserved_length+=4096; ++ info=(unsigned char *) ResizeQuantumMemory(info,(size_t) ++ reserved_length,sizeof(*info)); ++ if (info == (unsigned char *) NULL) ++ { ++ info=(unsigned char *) RelinquishMagickMemory(info); ++ ThrowGIFException(ResourceLimitError, ++ "MemoryAllocationFailed"); ++ } + } +- info=new_info; +- reserved_length=new_length; + } +- (void) memcpy(info+info_length,buffer,block_length); +- info_length+=block_length; +- info[info_length]='\0'; +- } +- if (magick != MagickFalse) +- { +- /* +- ImageMagick writes this extension as "gamma=". +- Require that prefix and a nonempty, bounded value. +- */ +- if ((info_length > 6) && +- (LocaleNCompare((char *) info,"gamma=",6) == 0)) ++ if (magick != MagickFalse) + meta_image->gamma=StringToDouble((char *) info+6, +- (char **) NULL); +- } +- else +- { +- StringInfo +- *profile; +- (void) LogMagickEvent(CoderEvent,GetMagickModule(), +- " profile name=%s",name); +- profile=BlobToProfileStringInfo(name,info,info_length, +- exception); +- if (profile != (StringInfo *) NULL) ++ (char **) NULL); ++ else + { +- if (profiles == (LinkedListInfo *) NULL) +- profiles=NewLinkedList(0); +- (void) AppendValueToLinkedList(profiles,profile); ++ StringInfo ++ *profile; ++ ++ (void) LogMagickEvent(CoderEvent,GetMagickModule(), ++ " profile name=%s",name); ++ profile=BlobToProfileStringInfo(name,info,(size_t) info_length, ++ exception); ++ if (profile != (StringInfo *) NULL) ++ { ++ if (profiles == (LinkedListInfo *) NULL) ++ profiles=NewLinkedList(0); ++ (void) AppendValueToLinkedList(profiles,profile); ++ } + } ++ info=(unsigned char *) RelinquishMagickMemory(info); + } +- info=(unsigned char *) RelinquishMagickMemory(info); ++ break; + } + default: + { diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-102635_3.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-102635_3.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-102635_3.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-102635_3.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,40 @@ +From: Cristy +Date: Sat, 19 Sep 2026 09:40:16 -0400 +Subject: https://github.com/ImageMagick/ImageMagick/issues/8969 + +(cherry picked from commit ba4723adf2f8a29bf9372ed2c837cf678d3c13f9) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-rvv7-5mh8-vcfc +origin: https://github.com/ImageMagick/ImageMagick/commit/ba4723adf2f8a29bf9372ed2c837cf678d3c13f9 +--- + coders/gif.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/coders/gif.c b/coders/gif.c +index ca0bf0e..762f8fc 100644 +--- a/coders/gif.c ++++ b/coders/gif.c +@@ -1192,8 +1192,11 @@ static Image *ReadGIFImage(const ImageInfo *image_info,ExceptionInfo *exception) + } + } + if (magick != MagickFalse) +- meta_image->gamma=StringToDouble((char *) info+6, ++ { ++ info[info_length]='\0'; ++ meta_image->gamma=StringToDouble((char *) info+6, + (char **) NULL); ++ } + else + { + StringInfo +@@ -1201,8 +1204,8 @@ static Image *ReadGIFImage(const ImageInfo *image_info,ExceptionInfo *exception) + + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + " profile name=%s",name); +- profile=BlobToProfileStringInfo(name,info,(size_t) info_length, +- exception); ++ profile=BlobToProfileStringInfo(name,info,(size_t) ++ info_length,exception); + if (profile != (StringInfo *) NULL) + { + if (profiles == (LinkedListInfo *) NULL) diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106564.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106564.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106564.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106564.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,49 @@ +From: Cristy +Date: Tue, 22 Sep 2026 19:57:16 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-54rx-5x9g-g465 + +a crafted EXR image can cause the EXR decoder to write beyond a heap buffer, causing the process to crash. + +(cherry picked from commit f7437ebafcd92d6959eca4086d80b150d52bdb7c) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-54rx-5x9g-g465 +origin: https://github.com/ImageMagick/ImageMagick/commit/f7437ebafcd92d6959eca4086d80b150d52bdb7c +--- + coders/exr.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/coders/exr.c b/coders/exr.c +index eae2c82..6c28da7 100644 +--- a/coders/exr.c ++++ b/coders/exr.c +@@ -665,17 +665,24 @@ static Image *ReadEXRImage(const ImageInfo *image_info,ExceptionInfo *exception) + switch (storage_type) + { + case EXR_STORAGE_SCANLINE: +- case EXR_STORAGE_DEEP_SCANLINE: + status=ReadEXRScanlineImage(ctxt,part_index,data_window,image,exception); + break; ++ case EXR_STORAGE_DEEP_SCANLINE: ++ (void) ThrowMagickException(exception,GetMagickModule(),CoderError, ++ "ImageTypeNotSupported","`%s'",image->filename); ++ status=MagickFalse; ++ break; + case EXR_STORAGE_TILED: +- case EXR_STORAGE_DEEP_TILED: + status=ReadEXRTiledImage(ctxt,part_index,image,exception); + break; ++ case EXR_STORAGE_DEEP_TILED: ++ (void) ThrowMagickException(exception,GetMagickModule(),CoderError, ++ "ImageTypeNotSupported","`%s'",image->filename); ++ status=MagickFalse; ++ break; + default: +- (void) ThrowMagickException(exception,GetMagickModule(), +- CorruptImageError,"Unsupported storage type","`%d'", +- (int) storage_type); ++ (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError, ++ "Unsupported storage type","`%d'",(int) storage_type); + status=MagickFalse; + break; + } diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106565.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106565.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106565.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106565.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,39 @@ +From: Cristy +Date: Fri, 18 Sep 2026 09:22:13 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-m9c7-gf3j-hx6h + +A missing end-of-file check while reading bzip2-compressed image data +can cause an infinite loop and exhaust processing resources. + +(cherry picked from commit e9872c4a165d869e75d10799c47195725ebf4132) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-m9c7-gf3j-hx6h +origin: https://github.com/ImageMagick/ImageMagick/commit/e9872c4a165d869e75d10799c47195725ebf4132 +--- + MagickCore/blob.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/MagickCore/blob.c b/MagickCore/blob.c +index f36a624..e6e48fd 100644 +--- a/MagickCore/blob.c ++++ b/MagickCore/blob.c +@@ -1296,7 +1296,8 @@ MagickExport int EOFBlob(const Image *image) + + status=0; + (void) BZ2_bzerror(blob_info->file_info.bzfile,&status); +- blob_info->eof=status == BZ_UNEXPECTED_EOF ? MagickTrue : MagickFalse; ++ if (status == BZ_UNEXPECTED_EOF) ++ blob_info->eof=MagickTrue; + #endif + break; + } +@@ -4073,6 +4074,8 @@ MagickExport ssize_t ReadBlob(Image *image,const size_t length,void *data) + (void) BZ2_bzerror(blob_info->file_info.bzfile,&status); + if ((count != (ssize_t) length) && (status != BZ_OK)) + ThrowBlobException(blob_info); ++ if ((count != (ssize_t) length) && (status == BZ_OK)) ++ blob_info->eof=MagickTrue; + #endif + break; + } diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106566.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106566.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106566.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106566.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,28 @@ +From: Cristy +Date: Thu, 17 Sep 2026 14:47:57 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-54hm-vrmh-75qj + +Delegate symlink cleanup does not check the MAGICK_SHRED_PASSES environment variable, allowing a local privileged workflow to overwrite a file with random data + +(cherry picked from commit 48e5ce1779fc640a389f0020fd7d965d0c08236e) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-54hm-vrmh-75qj +origin: https://github.com/ImageMagick/ImageMagick/commit/48e5ce1779fc640a389f0020fd7d965d0c08236e +--- + MagickCore/utility.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/MagickCore/utility.c b/MagickCore/utility.c +index addb979..314c562 100644 +--- a/MagickCore/utility.c ++++ b/MagickCore/utility.c +@@ -186,6 +186,8 @@ MagickExport MagickBooleanType AcquireUniqueSymbolicLink(const char *source, + status=IsRightsAuthorized(SystemPolicyDomain,ReadPolicyRights | + WritePolicyRights,"follow"); + passes=GetPolicyValue("system:shred"); ++ if (passes == (char *) NULL) ++ passes=GetEnvironmentValue("MAGICK_SHRED_PASSES"); + if ((passes != (char *) NULL) || (status == MagickFalse)) + passes=DestroyString(passes); + else diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106567.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106567.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106567.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106567.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,54 @@ +From: Cristy +Date: Tue, 15 Sep 2026 12:44:39 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-g6p6-3ggg-3w7j + +a crafted PSD file can trigger an integer-conversion error in the PSD decoder on 32-bit builds, causing an infinite loop and denial of service. + +(cherry picked from commit f053f778409932d55b95758c4b1516b63191d1eb) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-g6p6-3ggg-3w7j +origin: https://github.com/ImageMagick/ImageMagick/commit/f053f778409932d55b95758c4b1516b63191d1eb +--- + coders/psd.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/coders/psd.c b/coders/psd.c +index 61803b0..73a5504 100644 +--- a/coders/psd.c ++++ b/coders/psd.c +@@ -765,7 +765,7 @@ static MagickBooleanType NegateCMYK(Image *image,ExceptionInfo *exception) + } + + static StringInfo *ParseImageResourceBlocks(PSDInfo *psd_info,Image *image, +- const unsigned char *blocks,size_t length) ++ const unsigned char *blocks,size_t length,ExceptionInfo *exception) + { + const unsigned char + *p; +@@ -805,8 +805,14 @@ static StringInfo *ParseImageResourceBlocks(PSDInfo *psd_info,Image *image, + break; + p=PushLongPixel(MSBEndian,p,&count); + offset=(ssize_t) count; +- if (((p+offset) < blocks) || ((p+offset) > (blocks+length))) +- break; ++ if ((offset <= 0) || ((p+offset) > (blocks+length)) || ++ (((size_t) (p-blocks)+(size_t) offset) > (size_t) length)) ++ { ++ (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError, ++ "Invalid PSD resource block offset","`%s'",image->filename); ++ profile=DestroyStringInfo(profile); ++ break; ++ } + switch (id) + { + case 0x03ed: +@@ -2601,7 +2607,7 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) + blocks=(unsigned char *) RelinquishMagickMemory(blocks); + ThrowReaderException(CorruptImageError,"ImproperImageHeader"); + } +- profile=ParseImageResourceBlocks(&psd_info,image,blocks,(size_t) length); ++ profile=ParseImageResourceBlocks(&psd_info,image,blocks,(size_t) length,exception); + blocks=(unsigned char *) RelinquishMagickMemory(blocks); + } + /* diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106568.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106568.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106568.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106568.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,76 @@ +From: Cristy +Date: Sat, 12 Sep 2026 06:47:47 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-9p7q-63hw-mcr4 + +a crafted XMP profile embedded in an image can cause the profile parser to enter an infinite loop, preventing image processing from completing + +(cherry picked from commit e4f7ad983df6c831832eba3689f96b75f8b67051) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-9p7q-63hw-mcr4 +origin: https://github.com/ImageMagick/ImageMagick/commit/e4f7ad983df6c831832eba3689f96b75f8b67051 +--- + MagickCore/xml-tree.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/MagickCore/xml-tree.c b/MagickCore/xml-tree.c +index 1313677..077daca 100644 +--- a/MagickCore/xml-tree.c ++++ b/MagickCore/xml-tree.c +@@ -1085,9 +1085,9 @@ static char *ParseEntities(char *xml,char **entities,int state) + Character reference. + */ + if (xml[2] != 'x') +- c=strtol(xml+2,&entity,10); /* base 10 */ ++ c=(int) strtol(xml+2,&entity,10); /* base 10 */ + else +- c=strtol(xml+3,&entity,16); /* base 16 */ ++ c=(int) strtol(xml+3,&entity,16); /* base 16 */ + if ((c == 0) || (*entity != ';')) + { + /* +@@ -1250,7 +1250,7 @@ static XMLTreeInfo *ParseCloseTag(XMLTreeRoot *root,char *tag, + } + + static MagickBooleanType ValidateEntities(char *tag,char *xml, +- const size_t depth,char **entities) ++ const int delimiter,const size_t depth,char **entities) + { + ssize_t + i; +@@ -1262,7 +1262,7 @@ static MagickBooleanType ValidateEntities(char *tag,char *xml, + return(MagickFalse); + for ( ; ; xml++) + { +- while ((*xml != '\0') && (*xml != '&')) ++ while ((*xml != '\0') && (*xml != delimiter)) + xml++; + if (*xml == '\0') + return(MagickTrue); +@@ -1273,7 +1273,7 @@ static MagickBooleanType ValidateEntities(char *tag,char *xml, + (strncmp(entities[i],xml+1,strlen(entities[i])) == 0)) + i+=2; + if ((entities[i] != (char *) NULL) && +- (ValidateEntities(tag,entities[i+1],depth+1,entities) == 0)) ++ (ValidateEntities(tag,entities[i+1],delimiter,depth+1,entities) == MagickFalse)) + return(MagickFalse); + } + } +@@ -1425,14 +1425,15 @@ static MagickBooleanType ParseInternalDoctype(XMLTreeRoot *root,char *xml, + } + entities[i+1]=ParseEntities(v,predefined_entities,'%'); + entities[i+2]=(char *) NULL; +- if (ValidateEntities(n,entities[i+1],0,entities) != MagickFalse) ++ if ((ValidateEntities(n,entities[i+1],'%',0,entities) != MagickFalse) && ++ (ValidateEntities(n,entities[i+1],'&',0,entities) != MagickFalse)) + entities[i]=n; + else + { + if (entities[i+1] != v) + entities[i+1]=DestroyString(entities[i+1]); + (void) ThrowMagickException(exception,GetMagickModule(), +- OptionWarning,"ParseError","circular entity declaration &%s",n); ++ OptionWarning,"ParseError","circular entity declaration %s",n); + predefined_entities=(char **) RelinquishMagickMemory( + predefined_entities); + return(MagickFalse); diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106571-pre1.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106571-pre1.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106571-pre1.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106571-pre1.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,74 @@ +From: Cristy +Date: Tue, 30 Jun 2026 19:53:49 -0400 +Subject: move add check to private header + +(cherry picked from commit b3b8d209e1daee47600cac62510c4b1e6d7380ba) + +origin: https://github.com/ImageMagick/ImageMagick/commit/b3b8d209e1daee47600cac62510c4b1e6d7380ba + +[backport] +- use SIZE_MAX instead of alias MAGICK_SIZE_MAX defined in image-private.h in order to avoid header breakage +--- + MagickCore/memory-private.h | 12 ++++++++++++ + coders/ept.c | 5 +++++ + 2 files changed, 17 insertions(+) + +diff --git a/MagickCore/memory-private.h b/MagickCore/memory-private.h +index a85effb..0947b1e 100644 +--- a/MagickCore/memory-private.h ++++ b/MagickCore/memory-private.h +@@ -19,6 +19,7 @@ + #define MAGICKCORE_MEMORY_PRIVATE_H + + #include "MagickCore/magick-config.h" ++#include + + #if defined(__cplusplus) || defined(c_plusplus) + extern "C" { +@@ -43,6 +44,17 @@ extern "C" { + #define MagickAssumeAligned(address) (address) + #endif + ++static inline MagickBooleanType HeapOverflowCheckAdd(const size_t size, ++ const size_t increment) ++{ ++ if (size > (SIZE_MAX-increment)) ++ { ++ errno=ENOMEM; ++ return(MagickTrue); ++ } ++ return(MagickFalse); ++} ++ + static inline size_t OverAllocateMemory(const size_t length) + { + size_t +diff --git a/coders/ept.c b/coders/ept.c +index 13f53bd..93978bb 100644 +--- a/coders/ept.c ++++ b/coders/ept.c +@@ -55,6 +55,7 @@ + #include "MagickCore/list.h" + #include "MagickCore/magick.h" + #include "MagickCore/memory_.h" ++#include "MagickCore/memory-private.h" + #include "MagickCore/monitor.h" + #include "MagickCore/monitor-private.h" + #include "MagickCore/quantize.h" +@@ -201,12 +202,16 @@ static Image *ReadEPTImage(const ImageInfo *image_info,ExceptionInfo *exception) + ThrowReaderException(CorruptImageError,"ImproperImageHeader"); + ept_info.postscript_offset=(MagickOffsetType) ReadBlobLSBLong(image); + ept_info.postscript_length=ReadBlobLSBLong(image); ++ if (HeapOverflowCheckAdd(ept_info.postscript_length,1) != MagickFalse) ++ ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); + if ((MagickSizeType) ept_info.postscript_length > GetBlobSize(image)) + ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile"); + (void) ReadBlobLSBLong(image); + (void) ReadBlobLSBLong(image); + ept_info.tiff_offset=(MagickOffsetType) ReadBlobLSBLong(image); + ept_info.tiff_length=ReadBlobLSBLong(image); ++ if (HeapOverflowCheckAdd(ept_info.tiff_length,1) != MagickFalse) ++ ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); + if ((ept_info.postscript_length+ept_info.tiff_length) == 0) + ThrowReaderException(CorruptImageError,"ImproperImageHeader"); + if ((MagickSizeType) ept_info.tiff_length > GetBlobSize(image)) diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106571.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106571.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106571.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106571.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,66 @@ +From: Cristy +Date: Wed, 2 Sep 2026 19:46:28 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-jvjm-9f73-fhpq + +a crafted local call to the GetVirtualPixels API can trigger an integer calculation error and write beyond a heap buffer, crashing the server process + +(cherry picked from commit 8f3a15e60b723bfe3e80bd1b5e4bee88397467f7) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-jvjm-9f73-fhpq +origin: https://github.com/ImageMagick/ImageMagick/commit/8f3a15e60b723bfe3e80bd1b5e4bee88397467f7 +--- + MagickCore/cache.c | 40 +++++++++++++++++++++++++++++++++++----- + 1 file changed, 35 insertions(+), 5 deletions(-) + +diff --git a/MagickCore/cache.c b/MagickCore/cache.c +index 5194098..fbff44c 100644 +--- a/MagickCore/cache.c ++++ b/MagickCore/cache.c +@@ -5194,11 +5194,41 @@ static Quantum *SetPixelCacheNexusPixels( + /* + Pixels are stored in a staging region until they are synced to the cache. + */ +- number_pixels=(MagickSizeType) width*height; +- length=MagickMax(number_pixels,MagickMax(cache_info->columns, +- cache_info->rows))*cache_info->number_channels*sizeof(*nexus_info->pixels); +- if (cache_info->metacontent_extent != 0) +- length+=number_pixels*cache_info->metacontent_extent; ++ if (CacheOverflowSanityCheckGetSize((MagickSizeType) width,height,&number_pixels) != MagickFalse) ++ { ++ (void) ThrowMagickException(exception,GetMagickModule(), ++ ResourceLimitError,"MemoryAllocationFailed","`%s'", ++ cache_info->filename); ++ return((Quantum *) NULL); ++ } ++ { ++ MagickSizeType ++ extent, ++ packets; ++ ++ packets=MagickMax(number_pixels,MagickMax(cache_info->columns, ++ cache_info->rows)); ++ if ((CacheOverflowSanityCheckGetSize(packets,cache_info->number_channels,&length) != MagickFalse) || ++ (CacheOverflowSanityCheckGetSize(length,sizeof(*nexus_info->pixels),&length) != MagickFalse)) ++ { ++ (void) ThrowMagickException(exception,GetMagickModule(), ++ ResourceLimitError,"MemoryAllocationFailed","`%s'", ++ cache_info->filename); ++ return((Quantum *) NULL); ++ } ++ if (cache_info->metacontent_extent != 0) ++ { ++ if ((CacheOverflowSanityCheckGetSize(number_pixels,cache_info->metacontent_extent,&extent) != MagickFalse) || ++ (extent > (MagickSizeType) (~((MagickSizeType) 0))-length)) ++ { ++ (void) ThrowMagickException(exception,GetMagickModule(), ++ ResourceLimitError,"MemoryAllocationFailed","`%s'", ++ cache_info->filename); ++ return((Quantum *) NULL); ++ } ++ length+=extent; ++ } ++ } + status=MagickTrue; + if (nexus_info->cache == (Quantum *) NULL) + status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception); diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106572.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106572.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106572.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106572.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,29 @@ +From: Cristy +Date: Mon, 3 Aug 2026 18:31:02 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-wxw6-98rj-hjfr + +a missing recursion-depth check in the CALS decoder allows a crafted CALS image to exhaust the call stack and terminate the process + +(cherry picked from commit 19bce64e3667ff0348d559e2526c850f8fbe2b5a) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-wxw6-98rj-hjfr +origin: https://github.com/ImageMagick/ImageMagick/commit/19bce64e3667ff0348d559e2526c850f8fbe2b5a +--- + coders/cals.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/coders/cals.c b/coders/cals.c +index c9a9e79..eb8f29d 100644 +--- a/coders/cals.c ++++ b/coders/cals.c +@@ -247,6 +247,9 @@ static Image *ReadCALSImage(const ImageInfo *image_info, + } + } + } ++ if ((width == 0) || (height == 0) || (type != 1) || ++ (orientation == 0) || (density == 0)) ++ ThrowReaderException(CorruptImageError,"ImproperImageHeader"); + /* + Read CALS pixels. + */ diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106573.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106573.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106573.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106573.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,95 @@ +From: Cristy +Date: Thu, 27 Aug 2026 20:46:16 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-qr53-hc3p-fc62 + +a missing limit check in the MVG decoder allows a crafted MVG image to trigger an excessively long-running operation + +(cherry picked from commit c311471c4e4978494834c707b417bc033d95cc48) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-qr53-hc3p-fc62 +origin: https://github.com/ImageMagick/ImageMagick/commit/c311471c4e4978494834c707b417bc033d95cc48 +--- + MagickCore/draw.c | 26 +++++++++++++++++++++++++- + MagickCore/draw.h | 3 +++ + 2 files changed, 28 insertions(+), 1 deletion(-) + +diff --git a/MagickCore/draw.c b/MagickCore/draw.c +index 22db50c..eca2427 100644 +--- a/MagickCore/draw.c ++++ b/MagickCore/draw.c +@@ -94,6 +94,7 @@ + #define BezierQuantum 200 + #define PrimitiveExtentPad 4296.0 + #define MaxBezierCoordinates 67108864 ++#define MacroExpansionLimit 262144 + #define ThrowPointExpectedException(token,exception) \ + { \ + (void) ThrowMagickException(exception,GetMagickModule(),DrawError, \ +@@ -387,6 +388,7 @@ MagickExport DrawInfo *CloneDrawInfo(const ImageInfo *image_info, + MagickTrue,exception); + clone_info->render=draw_info->render; + clone_info->debug=draw_info->debug; ++ clone_info->macro_expansion=draw_info->macro_expansion; + exception=DestroyExceptionInfo(exception); + return(clone_info); + } +@@ -4035,6 +4037,18 @@ static MagickBooleanType RenderMVGContent(Image *image, + if (use != (const char *) NULL) + { + clone_info=CloneDrawInfo((ImageInfo *) NULL,graphic_context[n]); ++ if (draw_info->macro_expansion != (size_t *) NULL) ++ { ++ if (*draw_info->macro_expansion >= MacroExpansionLimit) ++ { ++ (void) ThrowMagickException(exception,GetMagickModule(), ++ DrawError,"NonconformingDrawingPrimitiveDefinition", ++ "`%s'",token); ++ clone_info=DestroyDrawInfo(clone_info); ++ return(MagickFalse); ++ } ++ (*draw_info->macro_expansion)++; ++ } + (void) CloneString(&clone_info->primitive,use); + status=RenderMVGContent(image,clone_info,depth+1,exception); + clone_info=DestroyDrawInfo(clone_info); +@@ -4670,7 +4684,16 @@ static MagickBooleanType RenderMVGContent(Image *image, + MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info, + ExceptionInfo *exception) + { +- return(RenderMVGContent(image,draw_info,0,exception)); ++ MagickBooleanType ++ status; ++ ++ size_t ++ macro_expansion = 0; ++ ++ ((DrawInfo *) draw_info)->macro_expansion=(¯o_expansion); ++ status=RenderMVGContent(image,draw_info,0,exception); ++ ((DrawInfo *) draw_info)->macro_expansion=(size_t *) NULL; ++ return(status); + } + + /* +@@ -6184,6 +6207,7 @@ MagickExport void GetDrawInfo(const ImageInfo *image_info,DrawInfo *draw_info) + draw_info->clip_path=MagickFalse; + draw_info->debug=(GetLogEventMask() & (DrawEvent | AnnotateEvent)) != 0 ? + MagickTrue : MagickFalse; ++ draw_info->macro_expansion=(size_t *) NULL; + if (draw_info->image_info->font != (char *) NULL) + draw_info->font=AcquireString(draw_info->image_info->font); + if (draw_info->image_info->density != (char *) NULL) +diff --git a/MagickCore/draw.h b/MagickCore/draw.h +index f8a1319..8839f30 100644 +--- a/MagickCore/draw.h ++++ b/MagickCore/draw.h +@@ -354,6 +354,9 @@ typedef struct _DrawInfo + + ImageInfo + *image_info; ++ ++ size_t ++ *macro_expansion; + } DrawInfo; + + typedef struct _PrimitiveInfo diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106574.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106574.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106574.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106574.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,37 @@ +From: Cristy +Date: Thu, 27 Aug 2026 18:21:58 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-4fq9-vrx7-gv92 + +(cherry picked from commit c69f54e1c8660e45f2ff83c354bf924a946d9356) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-4fq9-vrx7-gv92 +origin: https://github.com/ImageMagick/ImageMagick/commit/c69f54e1c8660e45f2ff83c354bf924a946d9356 +--- + MagickCore/cache.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/MagickCore/cache.c b/MagickCore/cache.c +index fbff44c..161ee72 100644 +--- a/MagickCore/cache.c ++++ b/MagickCore/cache.c +@@ -3740,8 +3740,17 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode, + cache_info->mode=mode; + number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows; + packet_size=MagickMax(cache_info->number_channels,1)*sizeof(Quantum); +- if (image->metacontent_extent != 0) +- packet_size+=cache_info->metacontent_extent; ++ if (cache_info->metacontent_extent != 0) ++ { ++ if (HeapOverflowCheckAdd(packet_size,cache_info->metacontent_extent) != MagickFalse) ++ { ++ cache_info->storage_class=UndefinedClass; ++ cache_info->length=0; ++ ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed", ++ image->filename); ++ } ++ packet_size+=cache_info->metacontent_extent; ++ } + if (CacheOverflowSanityCheckGetSize(number_pixels,packet_size,&length) != MagickFalse) + { + cache_info->storage_class=UndefinedClass; diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106575.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106575.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106575.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106575.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,37 @@ +From: Cristy +Date: Thu, 27 Aug 2026 19:11:52 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-2w4h-697j-4vrm + +a crafted Magick script can cause an opened file pointer to remain unclosed, allowing repeated processing to exhaust available file descriptors. + +(cherry picked from commit 86672a16cedbf5a06d64e629e058310d683bb48e) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-2w4h-697j-4vrm +origin: https://github.com/ImageMagick/ImageMagick/commit/86672a16cedbf5a06d64e629e058310d683bb48e +--- + MagickWand/script-token.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/MagickWand/script-token.c b/MagickWand/script-token.c +index 73b2bf9..b78344f 100644 +--- a/MagickWand/script-token.c ++++ b/MagickWand/script-token.c +@@ -229,10 +229,13 @@ WandExport ScriptTokenInfo *AcquireScriptTokenInfo(const char *filename) + else { + token_info->stream=fopen_utf8(filename, "r"); + } +- if ( token_info->stream == (FILE *) NULL ) { +- token_info=(ScriptTokenInfo *) RelinquishMagickMemory(token_info); +- return(token_info); +- } ++ if ( token_info->stream != (FILE *) NULL ) ++ token_info->opened=MagickTrue; ++ else ++ { ++ token_info=(ScriptTokenInfo *) RelinquishMagickMemory(token_info); ++ return(token_info); ++ } + + token_info->curr_line=1; + token_info->length=INITAL_TOKEN_LENGTH; diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106576.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106576.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106576.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106576.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,120 @@ +From: Dirk Lemstra +Date: Fri, 28 Aug 2026 13:16:22 +0200 +Subject: Use a better algorithm to determine the numerator and denominator + (GHSA-v45j-x8p4-3mh4) + +(cherry picked from commit f491576297141ff685dc4460d811986f5b6b6cec) +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-v45j-x8p4-3mh4 +origin: https://github.com/ImageMagick/ImageMagick/commit/f491576297141ff685dc4460d811986f5b6b6cec +--- + MagickCore/profile.c | 78 +++++++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 62 insertions(+), 16 deletions(-) + +diff --git a/MagickCore/profile.c b/MagickCore/profile.c +index a68e54f..d70a07e 100644 +--- a/MagickCore/profile.c ++++ b/MagickCore/profile.c +@@ -2561,11 +2561,39 @@ static MagickBooleanType GetXmpOffsets(const StringInfo *profile, + return(MagickTrue); + } + ++static MagickBooleanType TryAccumulate(const double term, ++ const unsigned long previous,const unsigned long before_previous, ++ unsigned long *result) ++{ ++ double ++ accumulated; ++ ++ *result=0; ++ if (term > (double) MAGICK_ULONG_MAX) ++ return(MagickFalse); ++ accumulated=(term*previous)+before_previous; ++ if ((accumulated < 0.0) || (accumulated > (double) MAGICK_ULONG_MAX)) ++ return(MagickFalse); ++ *result=(unsigned long) accumulated; ++ return(MagickTrue); ++} ++ + static void GetXmpNumeratorAndDenominator(double value, + unsigned long *numerator,unsigned long *denominator) + { + double +- df; ++ remainder; ++ ++ unsigned long ++ den, ++ new_den, ++ new_num, ++ num, ++ prev_den, ++ prev_num; ++ ++ ssize_t ++ i; + + *numerator=0; + *denominator=1; +@@ -2573,29 +2601,47 @@ static void GetXmpNumeratorAndDenominator(double value, + return; + if (value > (double) MAGICK_ULONG_MAX) + { +- *numerator = MAGICK_ULONG_MAX; +- *denominator = 1; ++ *numerator=MAGICK_ULONG_MAX; ++ *denominator=1; + return; + } + if (floor(value) == value) + { +- *numerator = (unsigned long) value; +- *denominator = 1; ++ *numerator=(unsigned long) value; ++ *denominator=1; + return; + } +- *numerator=1; +- df=1.0; +- while(fabs(df - value) > MagickEpsilon) ++ num=1; ++ prev_num=0; ++ den=0; ++ prev_den=1; ++ remainder=value; ++ for (i=0; i < 128; i++) + { +- if (df < value) +- (*numerator)++; +- else +- { +- (*denominator)++; +- *numerator=(unsigned long) (value*(*denominator)); +- } +- df=*numerator/(double)*denominator; ++ double ++ approximation, ++ fraction, ++ term; ++ ++ term=floor(remainder); ++ if ((TryAccumulate(term,num,prev_num,&new_num) == MagickFalse) || ++ (TryAccumulate(term,den,prev_den,&new_den) == MagickFalse) || ++ (new_den == 0)) ++ break; ++ prev_num=num; ++ num=new_num; ++ prev_den=den; ++ den=new_den; ++ approximation=num/(double) den; ++ if (fabs(approximation-value) <= MagickEpsilon) ++ break; ++ fraction=remainder-term; ++ if (fraction <= 0.0) ++ break; ++ remainder=1.0/fraction; + } ++ *numerator=num; ++ *denominator=(den == 0 ? 1 : den); + } + + static void SyncXmpProfile(const Image *image,StringInfo *profile) diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106577_1.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106577_1.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106577_1.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106577_1.patch 2026-10-23 19:46:42.000000000 +0000 @@ -0,0 +1,38 @@ +From: Dirk Lemstra +Date: Tue, 1 Sep 2026 21:01:20 +0200 +Subject: More fixes for GHSA-5rg6-j44q-q892. + +(cherry picked from commit 2ba2edfd04a1ab3d45af4a0dc1e640dde7020192) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-5rg6-j44q-q892 +origin: https://github.com/ImageMagick/ImageMagick/commit/2ba2edfd04a1ab3d45af4a0dc1e640dde7020192 +--- + coders/pdf.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/coders/pdf.c b/coders/pdf.c +index fc3392c..e0006eb 100644 +--- a/coders/pdf.c ++++ b/coders/pdf.c +@@ -1954,6 +1954,9 @@ static MagickBooleanType WritePDFImage(const ImageInfo *image_info,Image *image, + if (labels != (char **) NULL) + for (i=0; labels[i] != (char *) NULL; i++) + { ++ char ++ *escape; ++ + (void) WriteBlobString(image,"BT\n"); + (void) FormatLocaleString(buffer,MagickPathExtent,"/F%.20g %g Tf\n", + (double) image->scene,pointsize); +@@ -1962,8 +1965,9 @@ static MagickBooleanType WritePDFImage(const ImageInfo *image_info,Image *image, + (double) geometry.x,(double) (geometry.y+(ssize_t) geometry.height+ + i*pointsize+12)); + (void) WriteBlobString(image,buffer); +- (void) FormatLocaleString(buffer,MagickPathExtent,"(%s) Tj\n", +- labels[i]); ++ escape=EscapeParenthesis(labels[i]); ++ (void) FormatLocaleString(buffer,MagickPathExtent,"(%s) Tj\n",escape); ++ escape=DestroyString(escape); + (void) WriteBlobString(image,buffer); + (void) WriteBlobString(image,"ET\n"); + labels[i]=DestroyString(labels[i]); diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106577_2.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106577_2.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106577_2.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106577_2.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,102 @@ +From: Dirk Lemstra +Date: Thu, 27 Aug 2026 22:16:47 +0200 +Subject: Escape the labels to prevent code injection (GHSA-5rg6-j44q-q892) + +(cherry picked from commit 78378cd623468760bee82a5930cb3011725916f8) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-5rg6-j44q-q892 +origin: https://github.com/ImageMagick/ImageMagick/commit/78378cd623468760bee82a5930cb3011725916f8 +--- + coders/ps.c | 8 ++++++-- + coders/ps2.c | 9 +++++++-- + coders/ps3.c | 14 ++++++++++---- + 3 files changed, 23 insertions(+), 8 deletions(-) + +diff --git a/coders/ps.c b/coders/ps.c +index 0ec61d7..5f988f2 100644 +--- a/coders/ps.c ++++ b/coders/ps.c +@@ -1855,8 +1855,12 @@ static MagickBooleanType WritePSImage(const ImageInfo *image_info,Image *image, + { + for (i=0; labels[i] != (char *) NULL; i++) + { +- (void) FormatLocaleString(buffer,MagickPathExtent,"%s \n", +- labels[i]); ++ char ++ *escape; ++ ++ escape=EscapeParenthesis(labels[i]); ++ (void) FormatLocaleString(buffer,MagickPathExtent,"%s \n",escape); ++ escape=DestroyString(escape); + (void) WriteBlobString(image,buffer); + labels[i]=DestroyString(labels[i]); + } +diff --git a/coders/ps2.c b/coders/ps2.c +index 10670a7..f897946 100644 +--- a/coders/ps2.c ++++ b/coders/ps2.c +@@ -72,6 +72,7 @@ + #include "MagickCore/timer-private.h" + #include "MagickCore/utility.h" + #include "coders/coders-private.h" ++#include "coders/ghostscript-private.h" + + /* + Define declarations. +@@ -789,8 +790,12 @@ static MagickBooleanType WritePS2Image(const ImageInfo *image_info,Image *image, + { + for (i=0; labels[i] != (char *) NULL; i++) + { +- (void) FormatLocaleString(buffer,MagickPathExtent,"%s \n", +- labels[i]); ++ char ++ *escape; ++ ++ escape=EscapeParenthesis(labels[i]); ++ (void) FormatLocaleString(buffer,MagickPathExtent,"%s \n",escape); ++ escape=DestroyString(escape); + (void) WriteBlobString(image,buffer); + labels[i]=DestroyString(labels[i]); + } +diff --git a/coders/ps3.c b/coders/ps3.c +index b135b46..dda4da6 100644 +--- a/coders/ps3.c ++++ b/coders/ps3.c +@@ -76,6 +76,7 @@ + #include "MagickCore/token.h" + #include "MagickCore/utility.h" + #include "coders/coders-private.h" ++#include "coders/ghostscript-private.h" + + /* + Define declarations. +@@ -1287,20 +1288,25 @@ static MagickBooleanType WritePS3Image(const ImageInfo *image_info,Image *image, + { + for (i=0; labels[i] != (char *) NULL; i++) + { ++ char ++ *escape; ++ ++ escape=EscapeParenthesis(labels[i]); + if (compression != NoCompression) + { +- for (j=0; labels[i][j] != '\0'; j++) +- (void) WriteBlobByte(image,(unsigned char) labels[i][j]); ++ for (j=0; escape[j] != '\0'; j++) ++ (void) WriteBlobByte(image,(unsigned char) escape[j]); + (void) WriteBlobByte(image,'\n'); + } + else + { + (void) WriteBlobString(image,"<~"); + Ascii85Initialize(image); +- for (j=0; labels[i][j] != '\0'; j++) +- Ascii85Encode(image,(unsigned char) labels[i][j]); ++ for (j=0; escape[j] != '\0'; j++) ++ Ascii85Encode(image,(unsigned char) escape[j]); + Ascii85Flush(image); + } ++ escape=DestroyString(escape); + labels[i]=DestroyString(labels[i]); + } + labels=(char **) RelinquishMagickMemory(labels); diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106577_pre1.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106577_pre1.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106577_pre1.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106577_pre1.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,219 @@ +From: Dirk Lemstra +Date: Thu, 27 Aug 2026 22:09:55 +0200 +Subject: Moved EscapeParenthesis to the ghostscript-private.h header file. + +(cherry picked from commit e2bd884c19c50b21458833a9e7a2f8528a683d25) + +origin: https://github.com/ImageMagick/ImageMagick/commit/e2bd884c19c50b21458833a9e7a2f8528a683d25 +--- + MagickCore/annotate.c | 45 +---------------------------------------- + coders/ghostscript-private.h | 48 +++++++++++++++++++++++++++++++++++++++++++- + coders/pdf.c | 47 ------------------------------------------- + 3 files changed, 48 insertions(+), 92 deletions(-) + +diff --git a/MagickCore/annotate.c b/MagickCore/annotate.c +index a396c86..de1018b 100644 +--- a/MagickCore/annotate.c ++++ b/MagickCore/annotate.c +@@ -83,6 +83,7 @@ + #include "MagickCore/utility-private.h" + #include "MagickCore/xwindow.h" + #include "MagickCore/xwindow-private.h" ++#include "coders/ghostscript-private.h" + #if defined(MAGICKCORE_FREETYPE_DELEGATE) + #if defined(__MINGW32__) + # undef interface +@@ -2159,50 +2160,6 @@ static MagickBooleanType RenderFreetype(Image *image,const DrawInfo *draw_info, + % + */ + +-static char *EscapeParenthesis(const char *source) +-{ +- char +- *destination; +- +- char +- *q; +- +- const char +- *p; +- +- size_t +- length; +- +- assert(source != (const char *) NULL); +- length=0; +- for (p=source; *p != '\0'; p++) +- { +- if ((*p == '\\') || (*p == '(') || (*p == ')')) +- { +- if (~length < 1) +- ThrowFatalException(ResourceLimitFatalError,"UnableToEscapeString"); +- length++; +- } +- length++; +- } +- destination=(char *) NULL; +- if (~length >= (MagickPathExtent-1)) +- destination=(char *) AcquireQuantumMemory(length+MagickPathExtent, +- sizeof(*destination)); +- if (destination == (char *) NULL) +- ThrowFatalException(ResourceLimitFatalError,"UnableToEscapeString"); +- *destination='\0'; +- q=destination; +- for (p=source; *p != '\0'; p++) +- { +- if ((*p == '\\') || (*p == '(') || (*p == ')')) +- *q++='\\'; +- *q++=(*p); +- } +- *q='\0'; +- return(destination); +-} +- + static MagickBooleanType RenderPostscript(Image *image, + const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics, + ExceptionInfo *exception) +diff --git a/coders/ghostscript-private.h b/coders/ghostscript-private.h +index 3b9e77f..e542fd58 100644 +--- a/coders/ghostscript-private.h ++++ b/coders/ghostscript-private.h +@@ -16,6 +16,8 @@ + #ifndef MAGICK_GHOSTSCRIPT_BUFFER_PRIVATE_H + #define MAGICK_GHOSTSCRIPT_BUFFER_PRIVATE_H + ++#include "MagickCore/delegate.h" ++#include "MagickCore/delegate-private.h" + #include "MagickCore/profile-private.h" + #include "coders/bytebuffer-private.h" + +@@ -201,7 +203,7 @@ static inline MagickBooleanType InvokeGhostscriptDelegate( + #endif + } + +-static MagickBooleanType IsGhostscriptRendered(const char *path) ++static inline MagickBooleanType IsGhostscriptRendered(const char *path) + { + MagickBooleanType + status; +@@ -275,4 +277,48 @@ static inline void ReadGhostScriptXMPProfile(MagickByteBuffer *buffer, + SetStringInfoLength(*profile,(size_t) count); + } + ++static inline char *EscapeParenthesis(const char *source) ++{ ++ char ++ *destination; ++ ++ char ++ *q; ++ ++ const char ++ *p; ++ ++ size_t ++ length; ++ ++ assert(source != (const char *) NULL); ++ length=0; ++ for (p=source; *p != '\0'; p++) ++ { ++ if ((*p == '\\') || (*p == '(') || (*p == ')')) ++ { ++ if (~length < 1) ++ ThrowFatalException(ResourceLimitFatalError,"UnableToEscapeString"); ++ length++; ++ } ++ length++; ++ } ++ destination=(char *) NULL; ++ if (~length >= (MagickPathExtent-1)) ++ destination=(char *) AcquireQuantumMemory(length+MagickPathExtent, ++ sizeof(*destination)); ++ if (destination == (char *) NULL) ++ ThrowFatalException(ResourceLimitFatalError,"UnableToEscapeString"); ++ *destination='\0'; ++ q=destination; ++ for (p=source; *p != '\0'; p++) ++ { ++ if ((*p == '\\') || (*p == '(') || (*p == ')')) ++ *q++='\\'; ++ *q++=(*p); ++ } ++ *q='\0'; ++ return(destination); ++} ++ + #endif +diff --git a/coders/pdf.c b/coders/pdf.c +index fc3392c..13899a0 100644 +--- a/coders/pdf.c ++++ b/coders/pdf.c +@@ -52,8 +52,6 @@ + #include "MagickCore/colorspace-private.h" + #include "MagickCore/compress.h" + #include "MagickCore/constitute.h" +-#include "MagickCore/delegate.h" +-#include "MagickCore/delegate-private.h" + #include "MagickCore/distort.h" + #include "MagickCore/draw.h" + #include "MagickCore/exception.h" +@@ -86,7 +84,6 @@ + #include "MagickCore/utility.h" + #include "MagickCore/utility-private.h" + #include "MagickCore/xml-tree-private.h" +-#include "coders/bytebuffer-private.h" + #include "coders/coders-private.h" + #include "coders/ghostscript-private.h" + +@@ -915,50 +912,6 @@ ModuleExport void UnregisterPDFImage(void) + % + */ + +-static char *EscapeParenthesis(const char *source) +-{ +- char +- *destination; +- +- char +- *q; +- +- const char +- *p; +- +- size_t +- length; +- +- assert(source != (const char *) NULL); +- length=0; +- for (p=source; *p != '\0'; p++) +- { +- if ((*p == '\\') || (*p == '(') || (*p == ')')) +- { +- if (~length < 1) +- ThrowFatalException(ResourceLimitFatalError,"UnableToEscapeString"); +- length++; +- } +- length++; +- } +- destination=(char *) NULL; +- if (~length >= (MagickPathExtent-1)) +- destination=(char *) AcquireQuantumMemory(length+MagickPathExtent, +- sizeof(*destination)); +- if (destination == (char *) NULL) +- ThrowFatalException(ResourceLimitFatalError,"UnableToEscapeString"); +- *destination='\0'; +- q=destination; +- for (p=source; *p != '\0'; p++) +- { +- if ((*p == '\\') || (*p == '(') || (*p == ')')) +- *q++='\\'; +- *q++=(*p); +- } +- *q='\0'; +- return(destination); +-} +- + static size_t UTF8ToUTF16(const unsigned char *utf8,wchar_t *utf16) + { + const unsigned char diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106578.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106578.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106578.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106578.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,27 @@ +From: Dirk Lemstra +Date: Thu, 27 Aug 2026 21:37:42 +0200 +Subject: Corrected the call to CheckPrimitiveExtent to fix the use of + uninitialized heap memory (GHSA-6xf5-c3jx-rp39) + +(cherry picked from commit 5d29c094020612dc8fb471b10fc1d1cc6e9e4378) +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-6xf5-c3jx-rp39 +origin: https://github.com/ImageMagick/ImageMagick/commit/5d29c094020612dc8fb471b10fc1d1cc6e9e4378 +--- + MagickCore/draw.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/MagickCore/draw.c b/MagickCore/draw.c +index eca2427..21f225a 100644 +--- a/MagickCore/draw.c ++++ b/MagickCore/draw.c +@@ -4318,8 +4318,8 @@ static MagickBooleanType RenderMVGContent(Image *image, + break; + } + mvg_info.offset=i; +- status&=(MagickStatusType) CheckPrimitiveExtent(&mvg_info,(double) +- number_points); ++ status&=CheckPrimitiveExtent(&mvg_info,(double) number_points+ ++ (double) coordinates+1.0); + primitive_info=(*mvg_info.primitive_info); + if (status == MagickFalse) + break; diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106579-pre1.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106579-pre1.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106579-pre1.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106579-pre1.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,101 @@ +From: Dirk Lemstra +Date: Fri, 28 Nov 2025 12:50:46 +0100 +Subject: Disabling a module will now also disable all the coders in that + module. + +(cherry picked from commit 061b7b28d807d9295ddf2bf12b2eaa63f53a015c) + +origin: https://github.com/ImageMagick/ImageMagick/commit/061b7b28d807d9295ddf2bf12b2eaa63f53a015c +--- + MagickCore/constitute.c | 36 +++++++++++++++++++++--------------- + 1 file changed, 21 insertions(+), 15 deletions(-) + +diff --git a/MagickCore/constitute.c b/MagickCore/constitute.c +index c1ef780..86fe7cf 100644 +--- a/MagickCore/constitute.c ++++ b/MagickCore/constitute.c +@@ -445,8 +445,8 @@ MagickExport Image *PingImages(ImageInfo *image_info,const char *filename, + % + */ + +-static MagickBooleanType IsCoderAuthorized(const char *coder, +- const PolicyRights rights,ExceptionInfo *exception) ++static MagickBooleanType IsCoderAuthorized(const char *module, ++ const char *coder,const PolicyRights rights,ExceptionInfo *exception) + { + if (IsRightsAuthorized(CoderPolicyDomain,rights,coder) == MagickFalse) + { +@@ -455,6 +455,13 @@ static MagickBooleanType IsCoderAuthorized(const char *coder, + "NotAuthorized","`%s'",coder); + return(MagickFalse); + } ++ if (IsRightsAuthorized(ModulePolicyDomain,rights,module) == MagickFalse) ++ { ++ errno=EPERM; ++ (void) ThrowMagickException(exception,GetMagickModule(),PolicyError, ++ "NotAuthorized","`%s'",module); ++ return(MagickFalse); ++ } + return(MagickTrue); + } + +@@ -727,15 +734,14 @@ MagickExport Image *ReadImage(const ImageInfo *image_info, + /* + Call appropriate image reader based on image type. + */ +- if ((magick_info != (const MagickInfo *) NULL) && +- (GetMagickDecoderThreadSupport(magick_info) == MagickFalse)) ++ if (GetMagickDecoderThreadSupport(magick_info) == MagickFalse) + LockSemaphoreInfo(magick_info->semaphore); +- status=IsCoderAuthorized(read_info->magick,ReadPolicyRights,exception); ++ status=IsCoderAuthorized(magick_info->magick_module,read_info->magick, ++ ReadPolicyRights,exception); + image=(Image *) NULL; + if (status != MagickFalse) + image=decoder(read_info,exception); +- if ((magick_info != (const MagickInfo *) NULL) && +- (GetMagickDecoderThreadSupport(magick_info) == MagickFalse)) ++ if (GetMagickDecoderThreadSupport(magick_info) == MagickFalse) + UnlockSemaphoreInfo(magick_info->semaphore); + } + else +@@ -792,7 +798,8 @@ MagickExport Image *ReadImage(const ImageInfo *image_info, + */ + if (GetMagickDecoderThreadSupport(magick_info) == MagickFalse) + LockSemaphoreInfo(magick_info->semaphore); +- status=IsCoderAuthorized(read_info->magick,ReadPolicyRights,exception); ++ status=IsCoderAuthorized(magick_info->magick_module,read_info->magick, ++ ReadPolicyRights,exception); + image=(Image *) NULL; + if (status != MagickFalse) + image=(decoder)(read_info,exception); +@@ -1345,14 +1352,13 @@ MagickExport MagickBooleanType WriteImage(const ImageInfo *image_info, + /* + Call appropriate image writer based on image type. + */ +- if ((magick_info != (const MagickInfo *) NULL) && +- (GetMagickEncoderThreadSupport(magick_info) == MagickFalse)) ++ if (GetMagickEncoderThreadSupport(magick_info) == MagickFalse) + LockSemaphoreInfo(magick_info->semaphore); +- status=IsCoderAuthorized(write_info->magick,WritePolicyRights,exception); ++ status=IsCoderAuthorized(magick_info->magick_module,write_info->magick, ++ WritePolicyRights,exception); + if (status != MagickFalse) + status=encoder(write_info,image,exception); +- if ((magick_info != (const MagickInfo *) NULL) && +- (GetMagickEncoderThreadSupport(magick_info) == MagickFalse)) ++ if (GetMagickEncoderThreadSupport(magick_info) == MagickFalse) + UnlockSemaphoreInfo(magick_info->semaphore); + } + else +@@ -1420,8 +1426,8 @@ MagickExport MagickBooleanType WriteImage(const ImageInfo *image_info, + */ + if (GetMagickEncoderThreadSupport(magick_info) == MagickFalse) + LockSemaphoreInfo(magick_info->semaphore); +- status=IsCoderAuthorized(write_info->magick,WritePolicyRights, +- exception); ++ status=IsCoderAuthorized(magick_info->magick_module,write_info->magick, ++ WritePolicyRights,exception); + if (status != MagickFalse) + status=encoder(write_info,image,exception); + if (GetMagickEncoderThreadSupport(magick_info) == MagickFalse) diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106579_1.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106579_1.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106579_1.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106579_1.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,24 @@ +From: Dirk Lemstra +Date: Thu, 27 Aug 2026 20:24:46 +0200 +Subject: Fixed the policy check for coders (GHSA-vcjj-32hg-qpx5) + +(cherry picked from commit 82f373fedb3425c83a239103ab86f4fa86fd49ac) + +origin: https://github.com/ImageMagick/ImageMagick/commit/82f373fedb3425c83a239103ab86f4fa86fd49ac +--- + MagickCore/constitute.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/MagickCore/constitute.c b/MagickCore/constitute.c +index 86fe7cf..2351f87 100644 +--- a/MagickCore/constitute.c ++++ b/MagickCore/constitute.c +@@ -736,7 +736,7 @@ MagickExport Image *ReadImage(const ImageInfo *image_info, + */ + if (GetMagickDecoderThreadSupport(magick_info) == MagickFalse) + LockSemaphoreInfo(magick_info->semaphore); +- status=IsCoderAuthorized(magick_info->magick_module,read_info->magick, ++ status=IsCoderAuthorized(magick_info->magick_module,magick_info->name, + ReadPolicyRights,exception); + image=(Image *) NULL; + if (status != MagickFalse) diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106579_2.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106579_2.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106579_2.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106579_2.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,33 @@ +From: Dirk Lemstra +Date: Thu, 27 Aug 2026 20:32:18 +0200 +Subject: More fixes for GHSA-vcjj-32hg-qpx5. + +(cherry picked from commit dcdbbf4278fab20a32a4ad80e64cb95c368ca8dd) + +origin: https://github.com/ImageMagick/ImageMagick/commit/dcdbbf4278fab20a32a4ad80e64cb95c368ca8dd +--- + MagickCore/constitute.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/MagickCore/constitute.c b/MagickCore/constitute.c +index 2351f87..44ab832 100644 +--- a/MagickCore/constitute.c ++++ b/MagickCore/constitute.c +@@ -798,7 +798,7 @@ MagickExport Image *ReadImage(const ImageInfo *image_info, + */ + if (GetMagickDecoderThreadSupport(magick_info) == MagickFalse) + LockSemaphoreInfo(magick_info->semaphore); +- status=IsCoderAuthorized(magick_info->magick_module,read_info->magick, ++ status=IsCoderAuthorized(magick_info->magick_module,magick_info->name, + ReadPolicyRights,exception); + image=(Image *) NULL; + if (status != MagickFalse) +@@ -1354,7 +1354,7 @@ MagickExport MagickBooleanType WriteImage(const ImageInfo *image_info, + */ + if (GetMagickEncoderThreadSupport(magick_info) == MagickFalse) + LockSemaphoreInfo(magick_info->semaphore); +- status=IsCoderAuthorized(magick_info->magick_module,write_info->magick, ++ status=IsCoderAuthorized(magick_info->magick_module,magick_info->name, + WritePolicyRights,exception); + if (status != MagickFalse) + status=encoder(write_info,image,exception); diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106580_1.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106580_1.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106580_1.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106580_1.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,59 @@ +From: Cristy +Date: Fri, 19 Jun 2026 17:45:27 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-75mw-9cc9-fqx9 + +(cherry picked from commit 95348072e253fd101050b493ae70ba0ec253aefc) + +origin: https://github.com/ImageMagick/ImageMagick/commit/95348072e253fd101050b493ae70ba0ec253aefc +--- + coders/cut.c | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/coders/cut.c b/coders/cut.c +index b3b315a..4471721 100644 +--- a/coders/cut.c ++++ b/coders/cut.c +@@ -56,6 +56,8 @@ + #include "MagickCore/magick.h" + #include "MagickCore/memory_.h" + #include "MagickCore/pixel-accessor.h" ++#include "MagickCore/policy.h" ++#include "MagickCore/policy-private.h" + #include "MagickCore/quantum-private.h" + #include "MagickCore/static.h" + #include "MagickCore/string_.h" +@@ -328,6 +330,7 @@ static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception) + Image *image,*palette; + ImageInfo *clone_info; + MagickBooleanType status; ++ MagickBooleanType authorized; + + MagickOffsetType + offset; +@@ -429,6 +432,9 @@ static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception) + } + } + ++ authorized=IsPathAuthorized(ReadPolicyRights,clone_info->filename); ++ if (authorized == MagickFalse) ++ ThrowCUTReaderException(PolicyError,"NotAuthorized"); + (void) CopyMagickString(clone_info->filename+i,".PAL",(size_t) + (MagickPathExtent-i)); + if((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL) +@@ -437,8 +443,14 @@ static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception) + (MagickPathExtent-i)); + if((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL) + { ++ authorized=IsPathAuthorized(ReadPolicyRights,clone_info->filename); ++ if (authorized == MagickFalse) ++ ThrowCUTReaderException(PolicyError,"NotAuthorized"); + clone_info->filename[i]='\0'; +- if((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL) ++ authorized=IsPathAuthorized(ReadPolicyRights,clone_info->filename); ++ if (authorized == MagickFalse) ++ ThrowCUTReaderException(PolicyError,"NotAuthorized"); ++ if ((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL) + { + clone_info=DestroyImageInfo(clone_info); + clone_info=NULL; diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106580_2.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106580_2.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106580_2.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-106580_2.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,180 @@ +From: Cristy +Date: Mon, 24 Aug 2026 11:42:39 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-r868-pmwh-fv2c + +(cherry picked from commit 768bdd0dbb9a9ad743b6a6e557126b788b325970) +origin: https://github.com/ImageMagick/ImageMagick/commit/768bdd0dbb9a9ad743b6a6e557126b788b325970 +--- + coders/cut.c | 62 ++++++++++++++++++++++++++++++------------------------------ + 1 file changed, 31 insertions(+), 31 deletions(-) + +diff --git a/coders/cut.c b/coders/cut.c +index 4471721..2a6ecf9 100644 +--- a/coders/cut.c ++++ b/coders/cut.c +@@ -382,24 +382,24 @@ static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception) + while((int) RunCountMasked!=0) /*end of line?*/ + { + i=1; +- if((int) RunCount<0x80) i=(ssize_t) RunCountMasked; ++ if ((int) RunCount<0x80) i=(ssize_t) RunCountMasked; + offset=SeekBlob(image,TellBlob(image)+i,SEEK_SET); + if (offset < 0) + ThrowCUTReaderException(CorruptImageError,"ImproperImageHeader"); +- if(EOFBlob(image) != MagickFalse) goto CUT_KO; /*wrong data*/ ++ if (EOFBlob(image) != MagickFalse) goto CUT_KO; /*wrong data*/ + EncodedByte-=(size_t)(i+1); + ldblk+=(ssize_t) RunCountMasked; + + RunCount=(unsigned char) ReadBlobByte(image); +- if(EOFBlob(image) != MagickFalse) goto CUT_KO; /*wrong data: unexpected eof in line*/ ++ if (EOFBlob(image) != MagickFalse) goto CUT_KO; /*wrong data: unexpected eof in line*/ + RunCountMasked=RunCount & 0x7F; + } +- if(EncodedByte!=1) goto CUT_KO; /*wrong data: size incorrect*/ ++ if (EncodedByte!=1) goto CUT_KO; /*wrong data: size incorrect*/ + i=0; /*guess a number of bit planes*/ +- if(ldblk==(int) Header.Width) i=8; +- if(2*ldblk==(int) Header.Width) i=4; +- if(8*ldblk==(int) Header.Width) i=1; +- if(i==0) goto CUT_KO; /*wrong data: incorrect bit planes*/ ++ if (ldblk==(int) Header.Width) i=8; ++ if (2*ldblk==(int) Header.Width) i=4; ++ if (8*ldblk==(int) Header.Width) i=1; ++ if (i==0) goto CUT_KO; /*wrong data: incorrect bit planes*/ + depth=i; + + image->columns=Header.Width; +@@ -420,11 +420,11 @@ static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception) + j=i; + while(--i>0) + { +- if(clone_info->filename[i]=='.') ++ if (clone_info->filename[i]=='.') + { + break; + } +- if(clone_info->filename[i]=='/' || clone_info->filename[i]=='\\' || ++ if (clone_info->filename[i]=='/' || clone_info->filename[i]=='\\' || + clone_info->filename[i]==':' ) + { + i=j; +@@ -432,25 +432,25 @@ static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception) + } + } + ++ (void) CopyMagickString(clone_info->filename+i,".PAL",(size_t) ++ (MagickPathExtent-i)); + authorized=IsPathAuthorized(ReadPolicyRights,clone_info->filename); + if (authorized == MagickFalse) + ThrowCUTReaderException(PolicyError,"NotAuthorized"); +- (void) CopyMagickString(clone_info->filename+i,".PAL",(size_t) +- (MagickPathExtent-i)); +- if((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL) ++ if ((clone_info->file=fopen_utf8(clone_info->filename,"rb")) == NULL) + { + (void) CopyMagickString(clone_info->filename+i,".pal",(size_t) + (MagickPathExtent-i)); +- if((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL) ++ authorized=IsPathAuthorized(ReadPolicyRights,clone_info->filename); ++ if (authorized == MagickFalse) ++ ThrowCUTReaderException(PolicyError,"NotAuthorized"); ++ if ((clone_info->file=fopen_utf8(clone_info->filename,"rb")) == NULL) + { +- authorized=IsPathAuthorized(ReadPolicyRights,clone_info->filename); +- if (authorized == MagickFalse) +- ThrowCUTReaderException(PolicyError,"NotAuthorized"); + clone_info->filename[i]='\0'; + authorized=IsPathAuthorized(ReadPolicyRights,clone_info->filename); + if (authorized == MagickFalse) + ThrowCUTReaderException(PolicyError,"NotAuthorized"); +- if ((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL) ++ if ((clone_info->file=fopen_utf8(clone_info->filename,"rb")) == NULL) + { + clone_info=DestroyImageInfo(clone_info); + clone_info=NULL; +@@ -459,7 +459,7 @@ static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception) + } + } + +- if( (palette=AcquireImage(clone_info,exception))==NULL ) goto NoPalette; ++ if ( (palette=AcquireImage(clone_info,exception)) == NULL ) goto NoPalette; + status=OpenBlob(clone_info,palette,ReadBinaryBlobMode,exception); + if (status == MagickFalse) + { +@@ -470,10 +470,10 @@ static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception) + } + + +- if(palette!=NULL) ++ if (palette!=NULL) + { + (void) ReadBlob(palette,2,(unsigned char *) PalHeader.FileId); +- if(strncmp(PalHeader.FileId,"AH",2) != 0) goto ErasePalette; ++ if (strncmp(PalHeader.FileId,"AH",2) != 0) goto ErasePalette; + PalHeader.Version=ReadBlobLSBShort(palette); + PalHeader.Size=ReadBlobLSBShort(palette); + PalHeader.FileType=(char) ReadBlobByte(palette); +@@ -488,18 +488,18 @@ static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception) + if (EOFBlob(image)) + ThrowCUTReaderException(CorruptImageError,"UnexpectedEndOfFile"); + +- if(PalHeader.MaxIndex<1) goto ErasePalette; ++ if (PalHeader.MaxIndex<1) goto ErasePalette; + image->colors=PalHeader.MaxIndex+1; + if (AcquireImageColormap(image,image->colors,exception) == MagickFalse) goto NoMemory; + +- if(PalHeader.MaxRed==0) PalHeader.MaxRed=(unsigned int) QuantumRange; /*avoid division by 0*/ +- if(PalHeader.MaxGreen==0) PalHeader.MaxGreen=(unsigned int) QuantumRange; +- if(PalHeader.MaxBlue==0) PalHeader.MaxBlue=(unsigned int) QuantumRange; ++ if (PalHeader.MaxRed==0) PalHeader.MaxRed=(unsigned int) QuantumRange; /*avoid division by 0*/ ++ if (PalHeader.MaxGreen==0) PalHeader.MaxGreen=(unsigned int) QuantumRange; ++ if (PalHeader.MaxBlue==0) PalHeader.MaxBlue=(unsigned int) QuantumRange; + + for(i=0;i<=(int) PalHeader.MaxIndex;i++) + { /*this may be wrong- I don't know why is palette such strange*/ + j=(ssize_t) TellBlob(palette); +- if((j % 512)>512-6) ++ if ((j % 512)>512-6) + { + j=((j / 512)+1)*512; + offset=SeekBlob(palette,j,SEEK_SET); +@@ -536,7 +536,7 @@ static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception) + + + NoPalette: +- if(palette==NULL) ++ if (palette == NULL) + { + + image->colors=256; +@@ -558,7 +558,7 @@ static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception) + /* ----- Load RLE compressed raster ----- */ + BImgBuff=(unsigned char *) AcquireQuantumMemory((size_t) ldblk, + sizeof(*BImgBuff)); /*Ldblk was set in the check phase*/ +- if(BImgBuff==NULL) goto NoMemory; ++ if (BImgBuff == NULL) goto NoMemory; + (void) memset(BImgBuff,0,(size_t) ldblk*sizeof(*BImgBuff)); + + offset=SeekBlob(image,6 /*sizeof(Header)*/,SEEK_SET); +@@ -583,16 +583,16 @@ static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception) + + while ((int) RunCountMasked != 0) + { +- if((ssize_t) RunCountMasked>j) ++ if ((ssize_t) RunCountMasked>j) + { /*Wrong Data*/ + RunCountMasked=(unsigned char) j; +- if(j==0) ++ if (j==0) + { + break; + } + } + +- if((int) RunCount>0x80) ++ if ((int) RunCount>0x80) + { + RunValue=(unsigned char) ReadBlobByte(image); + (void) memset(ptrB,(int) RunValue,(size_t) RunCountMasked); diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-107208_1.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-107208_1.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-107208_1.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-107208_1.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,799 @@ +From: Dirk Lemstra +Date: Fri, 21 Aug 2026 16:05:18 +0200 +Subject: Removed unused code. + +(cherry picked from commit 35318d3493de2db106506ae08c8d41c2aa544c49) + +[backport] +Remove private code and first patch in serie to fix xml parsing +--- + MagickCore/methods.h | 8 - + MagickCore/xml-tree-private.h | 16 -- + MagickCore/xml-tree.c | 647 ++++++++---------------------------------- + 3 files changed, 112 insertions(+), 559 deletions(-) + +diff --git a/MagickCore/methods.h b/MagickCore/methods.h +index 9c9b5d8..5b3b2fa 100644 +--- a/MagickCore/methods.h ++++ b/MagickCore/methods.h +@@ -123,7 +123,6 @@ extern "C" { + #define CacheComponentGenesis PrependMagickMethod(CacheComponentGenesis) + #define CacheComponentTerminus PrependMagickMethod(CacheComponentTerminus) + #define CannyEdgeImage PrependMagickMethod(CannyEdgeImage) +-#define CanonicalXMLContent PrependMagickMethod(CanonicalXMLContent) + #define CatchException PrependMagickMethod(CatchException) + #define CatchImageException PrependMagickMethod(CatchImageException) + #define ChannelFxImage PrependMagickMethod(ChannelFxImage) +@@ -629,12 +628,8 @@ extern "C" { + #define GetVirtualPixelsNexus PrependMagickMethod(GetVirtualPixelsNexus) + #define GetVirtualPixels PrependMagickMethod(GetVirtualPixels) + #define GetXMLTreeAttribute PrependMagickMethod(GetXMLTreeAttribute) +-#define GetXMLTreeAttributes PrependMagickMethod(GetXMLTreeAttributes) + #define GetXMLTreeChild PrependMagickMethod(GetXMLTreeChild) + #define GetXMLTreeContent PrependMagickMethod(GetXMLTreeContent) +-#define GetXMLTreeOrdered PrependMagickMethod(GetXMLTreeOrdered) +-#define GetXMLTreePath PrependMagickMethod(GetXMLTreePath) +-#define GetXMLTreeProcessingInstructions PrependMagickMethod(GetXMLTreeProcessingInstructions) + #define GetXMLTreeSibling PrependMagickMethod(GetXMLTreeSibling) + #define GetXMLTreeTag PrependMagickMethod(GetXMLTreeTag) + #define GlobExpression PrependMagickMethod(GlobExpression) +@@ -665,7 +660,6 @@ extern "C" { + #define InitializeSignature PrependMagickMethod(InitializeSignature) + #define InjectImageBlob PrependMagickMethod(InjectImageBlob) + #define InsertImageInList PrependMagickMethod(InsertImageInList) +-#define InsertTagIntoXMLTree PrependMagickMethod(InsertTagIntoXMLTree) + #define InsertValueInLinkedList PrependMagickMethod(InsertValueInLinkedList) + #define InsertValueInSortedLinkedList PrependMagickMethod(InsertValueInSortedLinkedList) + #define IntegralImage PrependMagickMethod(IntegralImage) +@@ -834,7 +828,6 @@ extern "C" { + #define PrintStringInfo PrependMagickMethod(PrintStringInfo) + #define process_message PrependMagickMethod(process_message) + #define ProfileImage PrependMagickMethod(ProfileImage) +-#define PruneTagFromXMLTree PrependMagickMethod(PruneTagFromXMLTree) + #define QuantizeImage PrependMagickMethod(QuantizeImage) + #define QuantizeImages PrependMagickMethod(QuantizeImages) + #define QueryColorCompliance PrependMagickMethod(QueryColorCompliance) +@@ -1184,7 +1177,6 @@ extern "C" { + #define SetStringInfoPath PrependMagickMethod(SetStringInfoPath) + #define SetStringInfo PrependMagickMethod(SetStringInfo) + #define SetWarningHandler PrependMagickMethod(SetWarningHandler) +-#define SetXMLTreeAttribute PrependMagickMethod(SetXMLTreeAttribute) + #define SetXMLTreeContent PrependMagickMethod(SetXMLTreeContent) + #define ShadeImage PrependMagickMethod(ShadeImage) + #define ShadowImage PrependMagickMethod(ShadowImage) +diff --git a/MagickCore/xml-tree-private.h b/MagickCore/xml-tree-private.h +index cd2875a..88c80c5 100644 +--- a/MagickCore/xml-tree-private.h ++++ b/MagickCore/xml-tree-private.h +@@ -118,24 +118,8 @@ static inline char *SubstituteXMLEntities(const char *content, + } + + extern MagickPrivate char +- *CanonicalXMLContent(const char *,const MagickBooleanType), + *FileToXML(const char *,const size_t); + +-extern MagickPrivate const char +- **GetXMLTreeProcessingInstructions(XMLTreeInfo *,const char *); +- +-extern MagickPrivate MagickBooleanType +- GetXMLTreeAttributes(const XMLTreeInfo *,SplayTreeInfo *); +- +-extern MagickPrivate XMLTreeInfo +- *AddPathToXMLTree(XMLTreeInfo *,const char *,const size_t), +- *GetXMLTreeOrdered(XMLTreeInfo *), +- *GetXMLTreePath(XMLTreeInfo *,const char *), +- *InsertTagIntoXMLTree(XMLTreeInfo *,XMLTreeInfo *,const size_t), +- *ParseTagFromXMLTree(XMLTreeInfo *), +- *PruneTagFromXMLTree(XMLTreeInfo *), +- *SetXMLTreeAttribute(XMLTreeInfo *,const char *,const char *); +- + #if defined(__cplusplus) || defined(c_plusplus) + } + #endif +diff --git a/MagickCore/xml-tree.c b/MagickCore/xml-tree.c +index f4358a5..d74487a 100644 +--- a/MagickCore/xml-tree.c ++++ b/MagickCore/xml-tree.c +@@ -164,6 +164,74 @@ static char + % o offset: the tag offset. + % + */ ++ ++static XMLTreeInfo *InsertTagIntoXMLTree(XMLTreeInfo *xml_info, ++ XMLTreeInfo *child,const size_t offset) ++{ ++ XMLTreeInfo ++ *head, ++ *node, ++ *previous; ++ ++ child->ordered=(XMLTreeInfo *) NULL; ++ child->sibling=(XMLTreeInfo *) NULL; ++ child->next=(XMLTreeInfo *) NULL; ++ child->offset=offset; ++ child->parent=xml_info; ++ if (xml_info->child == (XMLTreeInfo *) NULL) ++ { ++ xml_info->child=child; ++ return(child); ++ } ++ head=xml_info->child; ++ if (head->offset > offset) ++ { ++ child->ordered=head; ++ xml_info->child=child; ++ } ++ else ++ { ++ node=head; ++ while ((node->ordered != (XMLTreeInfo *) NULL) && ++ (node->ordered->offset <= offset)) ++ node=node->ordered; ++ child->ordered=node->ordered; ++ node->ordered=child; ++ } ++ previous=(XMLTreeInfo *) NULL; ++ node=head; ++ while ((node != (XMLTreeInfo *) NULL) && (strcmp(node->tag,child->tag) != 0)) ++ { ++ previous=node; ++ node=node->sibling; ++ } ++ if ((node != (XMLTreeInfo *) NULL) && (node->offset <= offset)) ++ { ++ while ((node->next != (XMLTreeInfo *) NULL) && ++ (node->next->offset <= offset)) ++ node=node->next; ++ child->next=node->next; ++ node->next=child; ++ } ++ else ++ { ++ if ((previous != (XMLTreeInfo *) NULL) && (node != (XMLTreeInfo *) NULL)) ++ previous->sibling=node->sibling; ++ child->next=node; ++ previous=(XMLTreeInfo *) NULL; ++ node=head; ++ while ((node != (XMLTreeInfo *) NULL) && (node->offset <= offset)) ++ { ++ previous=node; ++ node=node->sibling; ++ } ++ child->sibling=node; ++ if (previous != (XMLTreeInfo *) NULL) ++ previous->sibling=child; ++ } ++ return(child); ++} ++ + MagickExport XMLTreeInfo *AddChildToXMLTree(XMLTreeInfo *xml_info, + const char *tag,const size_t offset) + { +@@ -212,6 +280,49 @@ MagickExport XMLTreeInfo *AddChildToXMLTree(XMLTreeInfo *xml_info, + % o offset: the tag offset. + % + */ ++ ++static char *CanonicalXMLContent(const char *content, ++ const MagickBooleanType pedantic) ++{ ++ char ++ *base64, ++ *canonical_content; ++ ++ const unsigned char ++ *p; ++ ++ size_t ++ length; ++ ++ unsigned char ++ *utf8; ++ ++ utf8=ConvertLatin1ToUTF8((const unsigned char *) content); ++ if (utf8 == (unsigned char *) NULL) ++ return((char *) NULL); ++ for (p=utf8; *p != '\0'; p++) ++ if ((*p < 0x20) && (*p != 0x09) && (*p != 0x0a) && (*p != 0x0d)) ++ break; ++ if (*p != '\0') ++ { ++ /* ++ String is binary, base64-encode it. ++ */ ++ base64=Base64Encode(utf8,strlen((char *) utf8),&length); ++ utf8=(unsigned char *) RelinquishMagickMemory(utf8); ++ if (base64 == (char *) NULL) ++ return((char *) NULL); ++ canonical_content=AcquireString(""); ++ (void) ConcatenateString(&canonical_content,base64); ++ base64=DestroyString(base64); ++ (void) ConcatenateString(&canonical_content,""); ++ return(canonical_content); ++ } ++ canonical_content=SubstituteXMLEntities((const char *) utf8,pedantic); ++ utf8=(unsigned char *) RelinquishMagickMemory(utf8); ++ return(canonical_content); ++} ++ + MagickPrivate XMLTreeInfo *AddPathToXMLTree(XMLTreeInfo *xml_info, + const char *path,const size_t offset) + { +@@ -252,7 +363,7 @@ MagickPrivate XMLTreeInfo *AddPathToXMLTree(XMLTreeInfo *xml_info, + break; + for (j=(ssize_t) StringToLong(subnode)-1; j > 0; j--) + { +- node=GetXMLTreeOrdered(node); ++ node=node->ordered; + if (node == (XMLTreeInfo *) NULL) + break; + } +@@ -271,76 +382,6 @@ MagickPrivate XMLTreeInfo *AddPathToXMLTree(XMLTreeInfo *xml_info, + % % + % % + % % +-% C a n o n i c a l X M L C o n t e n t % +-% % +-% % +-% % +-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-% +-% CanonicalXMLContent() converts text to canonical XML content by converting +-% to UTF-8, substituting predefined entities, wrapping as CDATA, or encoding +-% as base-64 as required. +-% +-% The format of the CanonicalXMLContent method is: +-% +-% char *CanonicalXMLContent(const char *content, +-% const MagickBooleanType pedantic) +-% +-% A description of each parameter follows: +-% +-% o content: the content. +-% +-% o pedantic: if true, replace newlines and tabs with their respective +-% entities. +-% +-*/ +-MagickPrivate char *CanonicalXMLContent(const char *content, +- const MagickBooleanType pedantic) +-{ +- char +- *base64, +- *canonical_content; +- +- const unsigned char +- *p; +- +- size_t +- length; +- +- unsigned char +- *utf8; +- +- utf8=ConvertLatin1ToUTF8((const unsigned char *) content); +- if (utf8 == (unsigned char *) NULL) +- return((char *) NULL); +- for (p=utf8; *p != '\0'; p++) +- if ((*p < 0x20) && (*p != 0x09) && (*p != 0x0a) && (*p != 0x0d)) +- break; +- if (*p != '\0') +- { +- /* +- String is binary, base64-encode it. +- */ +- base64=Base64Encode(utf8,strlen((char *) utf8),&length); +- utf8=(unsigned char *) RelinquishMagickMemory(utf8); +- if (base64 == (char *) NULL) +- return((char *) NULL); +- canonical_content=AcquireString(""); +- (void) ConcatenateString(&canonical_content,base64); +- base64=DestroyString(base64); +- (void) ConcatenateString(&canonical_content,""); +- return(canonical_content); +- } +- canonical_content=SubstituteXMLEntities((const char *) utf8,pedantic); +- utf8=(unsigned char *) RelinquishMagickMemory(utf8); +- return(canonical_content); +-} +- +-/* +-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-% % +-% % +-% % + % D e s t r o y X M L T r e e % + % % + % % +@@ -756,57 +797,6 @@ MagickExport const char *GetXMLTreeAttribute(XMLTreeInfo *xml_info, + % % + % % + % % +-% G e t X M L T r e e A t t r i b u t e s % +-% % +-% % +-% % +-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-% +-% GetXMLTreeAttributes() injects all attributes associated with the current +-% tag in the specified splay-tree. +-% +-% The format of the GetXMLTreeAttributes method is: +-% +-% MagickBooleanType GetXMLTreeAttributes(const XMLTreeInfo *xml_info, +-% SplayTreeInfo *attributes) +-% +-% A description of each parameter follows: +-% +-% o xml_info: the xml info. +-% +-% o attributes: the attribute splay-tree. +-% +-*/ +-MagickPrivate MagickBooleanType GetXMLTreeAttributes( +- const XMLTreeInfo *xml_info,SplayTreeInfo *attributes) +-{ +- ssize_t +- i; +- +- assert(xml_info != (XMLTreeInfo *) NULL); +- assert((xml_info->signature == MagickCoreSignature) || +- (((const XMLTreeRoot *) xml_info)->signature == MagickCoreSignature)); +- assert(attributes != (SplayTreeInfo *) NULL); +- if (IsEventLogging() != MagickFalse) +- (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); +- if (xml_info->attributes == (char **) NULL) +- return(MagickTrue); +- i=0; +- while (xml_info->attributes[i] != (char *) NULL) +- { +- (void) AddValueToSplayTree(attributes, +- ConstantString(xml_info->attributes[i]), +- ConstantString(xml_info->attributes[i+1])); +- i+=2; +- } +- return(MagickTrue); +-} +- +-/* +-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-% % +-% % +-% % + % G e t X M L T r e e C h i l d % + % % + % % +@@ -880,163 +870,6 @@ MagickExport const char *GetXMLTreeContent(XMLTreeInfo *xml_info) + % % + % % + % % +-% G e t X M L T r e e O r d e r e d % +-% % +-% % +-% % +-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-% +-% GetXMLTreeOrdered() returns the next ordered node if found, otherwise NULL. +-% +-% The format of the GetXMLTreeOrdered method is: +-% +-% XMLTreeInfo *GetXMLTreeOrdered(XMLTreeInfo *xml_info) +-% +-% A description of each parameter follows: +-% +-% o xml_info: the xml info. +-% +-*/ +-MagickPrivate XMLTreeInfo *GetXMLTreeOrdered(XMLTreeInfo *xml_info) +-{ +- assert(xml_info != (XMLTreeInfo *) NULL); +- assert((xml_info->signature == MagickCoreSignature) || +- (((XMLTreeRoot *) xml_info)->signature == MagickCoreSignature)); +- if (IsEventLogging() != MagickFalse) +- (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); +- return(xml_info->ordered); +-} +- +-/* +-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-% % +-% % +-% % +-% G e t X M L T r e e P a t h % +-% % +-% % +-% % +-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-% +-% GetXMLTreePath() traverses the XML-tree as defined by the specified path +-% and returns the node if found, otherwise NULL. +-% +-% The format of the GetXMLTreePath method is: +-% +-% XMLTreeInfo *GetXMLTreePath(XMLTreeInfo *xml_info,const char *path) +-% +-% A description of each parameter follows: +-% +-% o xml_info: the xml info. +-% +-% o path: the path (e.g. property/elapsed-time). +-% +-*/ +-MagickPrivate XMLTreeInfo *GetXMLTreePath(XMLTreeInfo *xml_info, +- const char *path) +-{ +- char +- **components, +- subnode[MagickPathExtent], +- tag[MagickPathExtent]; +- +- size_t +- number_components; +- +- ssize_t +- i, +- j; +- +- XMLTreeInfo +- *node; +- +- assert(xml_info != (XMLTreeInfo *) NULL); +- assert((xml_info->signature == MagickCoreSignature) || +- (((XMLTreeRoot *) xml_info)->signature == MagickCoreSignature)); +- if (IsEventLogging() != MagickFalse) +- (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); +- node=xml_info; +- components=GetPathComponents(path,&number_components); +- if (components == (char **) NULL) +- return((XMLTreeInfo *) NULL); +- for (i=0; i < (ssize_t) number_components; i++) +- { +- GetPathComponent(components[i],SubimagePath,subnode); +- GetPathComponent(components[i],CanonicalPath,tag); +- node=GetXMLTreeChild(node,tag); +- if (node == (XMLTreeInfo *) NULL) +- break; +- for (j=(ssize_t) StringToLong(subnode)-1; j > 0; j--) +- { +- node=GetXMLTreeOrdered(node); +- if (node == (XMLTreeInfo *) NULL) +- break; +- } +- if (node == (XMLTreeInfo *) NULL) +- break; +- components[i]=DestroyString(components[i]); +- } +- for ( ; i < (ssize_t) number_components; i++) +- components[i]=DestroyString(components[i]); +- components=(char **) RelinquishMagickMemory(components); +- return(node); +-} +- +-/* +-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-% % +-% % +-% % +-% G e t X M L T r e e P r o c e s s i n g I n s t r u c t i o n s % +-% % +-% % +-% % +-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-% +-% GetXMLTreeProcessingInstructions() returns a null terminated array of +-% processing instructions for the given target. +-% +-% The format of the GetXMLTreeProcessingInstructions method is: +-% +-% const char **GetXMLTreeProcessingInstructions(XMLTreeInfo *xml_info, +-% const char *target) +-% +-% A description of each parameter follows: +-% +-% o xml_info: the xml info. +-% +-*/ +-MagickPrivate const char **GetXMLTreeProcessingInstructions( +- XMLTreeInfo *xml_info,const char *target) +-{ +- ssize_t +- i; +- +- XMLTreeRoot +- *root; +- +- assert(xml_info != (XMLTreeInfo *) NULL); +- assert((xml_info->signature == MagickCoreSignature) || +- (((XMLTreeRoot *) xml_info)->signature == MagickCoreSignature)); +- if (IsEventLogging() != MagickFalse) +- (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); +- root=(XMLTreeRoot *) xml_info; +- while (root->root.parent != (XMLTreeInfo *) NULL) +- root=(XMLTreeRoot *) root->root.parent; +- i=0; +- while ((root->processing_instructions[i] != (char **) NULL) && +- (strcmp(root->processing_instructions[i][0],target) != 0)) +- i++; +- if (root->processing_instructions[i] == (char **) NULL) +- return((const char **) sentinel); +- return((const char **) (root->processing_instructions[i]+1)); +-} +- +-/* +-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-% % +-% % +-% % + % G e t X M L T r e e S i b l i n g % + % % + % % +@@ -1101,101 +934,6 @@ MagickExport const char *GetXMLTreeTag(XMLTreeInfo *xml_info) + % % + % % + % % +-% I n s e r t I n t o T a g X M L T r e e % +-% % +-% % +-% % +-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-% +-% InsertTagIntoXMLTree() inserts a tag at an offset relative to the start of +-% the parent tag's character content. This method returns the child tag. +-% +-% The format of the InsertTagIntoXMLTree method is: +-% +-% XMLTreeInfo *InsertTagIntoXMLTree(XMLTreeInfo *xml_info, +-% XMLTreeInfo *child,const size_t offset) +-% +-% A description of each parameter follows: +-% +-% o xml_info: the xml info. +-% +-% o child: the child tag. +-% +-% o offset: the tag offset. +-% +-*/ +-MagickPrivate XMLTreeInfo *InsertTagIntoXMLTree(XMLTreeInfo *xml_info, +- XMLTreeInfo *child,const size_t offset) +-{ +- XMLTreeInfo +- *head, +- *node, +- *previous; +- +- child->ordered=(XMLTreeInfo *) NULL; +- child->sibling=(XMLTreeInfo *) NULL; +- child->next=(XMLTreeInfo *) NULL; +- child->offset=offset; +- child->parent=xml_info; +- if (xml_info->child == (XMLTreeInfo *) NULL) +- { +- xml_info->child=child; +- return(child); +- } +- head=xml_info->child; +- if (head->offset > offset) +- { +- child->ordered=head; +- xml_info->child=child; +- } +- else +- { +- node=head; +- while ((node->ordered != (XMLTreeInfo *) NULL) && +- (node->ordered->offset <= offset)) +- node=node->ordered; +- child->ordered=node->ordered; +- node->ordered=child; +- } +- previous=(XMLTreeInfo *) NULL; +- node=head; +- while ((node != (XMLTreeInfo *) NULL) && (strcmp(node->tag,child->tag) != 0)) +- { +- previous=node; +- node=node->sibling; +- } +- if ((node != (XMLTreeInfo *) NULL) && (node->offset <= offset)) +- { +- while ((node->next != (XMLTreeInfo *) NULL) && +- (node->next->offset <= offset)) +- node=node->next; +- child->next=node->next; +- node->next=child; +- } +- else +- { +- if ((previous != (XMLTreeInfo *) NULL) && (node != (XMLTreeInfo *) NULL)) +- previous->sibling=node->sibling; +- child->next=node; +- previous=(XMLTreeInfo *) NULL; +- node=head; +- while ((node != (XMLTreeInfo *) NULL) && (node->offset <= offset)) +- { +- previous=node; +- node=node->sibling; +- } +- child->sibling=node; +- if (previous != (XMLTreeInfo *) NULL) +- previous->sibling=child; +- } +- return(child); +-} +- +-/* +-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-% % +-% % +-% % + % N e w X M L T r e e % + % % + % % +@@ -2316,167 +2054,6 @@ MagickExport XMLTreeInfo *NewXMLTreeTag(const char *tag) + % % + % % + % % +-% P r u n e T a g F r o m X M L T r e e % +-% % +-% % +-% % +-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-% +-% PruneTagFromXMLTree() prunes a tag from the xml-tree along with all its +-% subtags. +-% +-% The format of the PruneTagFromXMLTree method is: +-% +-% XMLTreeInfo *PruneTagFromXMLTree(XMLTreeInfo *xml_info) +-% +-% A description of each parameter follows: +-% +-% o xml_info: the xml info. +-% +-*/ +-MagickPrivate XMLTreeInfo *PruneTagFromXMLTree(XMLTreeInfo *xml_info) +-{ +- XMLTreeInfo +- *node; +- +- assert(xml_info != (XMLTreeInfo *) NULL); +- assert((xml_info->signature == MagickCoreSignature) || +- (((XMLTreeRoot *) xml_info)->signature == MagickCoreSignature)); +- if (IsEventLogging() != MagickFalse) +- (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); +- if (xml_info->next != (XMLTreeInfo *) NULL) +- xml_info->next->sibling=xml_info->sibling; +- if (xml_info->parent != (XMLTreeInfo *) NULL) +- { +- node=xml_info->parent->child; +- if (node == xml_info) +- xml_info->parent->child=xml_info->ordered; +- else +- { +- while (node->ordered != xml_info) +- node=node->ordered; +- node->ordered=node->ordered->ordered; +- node=xml_info->parent->child; +- if (strcmp(node->tag,xml_info->tag) != 0) +- { +- while (strcmp(node->sibling->tag,xml_info->tag) != 0) +- node=node->sibling; +- if (node->sibling != xml_info) +- node=node->sibling; +- else +- node->sibling=(xml_info->next != (XMLTreeInfo *) NULL) ? +- xml_info->next : node->sibling->sibling; +- } +- while ((node->next != (XMLTreeInfo *) NULL) && +- (node->next != xml_info)) +- node=node->next; +- if (node->next != (XMLTreeInfo *) NULL) +- node->next=node->next->next; +- } +- } +- xml_info->ordered=(XMLTreeInfo *) NULL; +- xml_info->sibling=(XMLTreeInfo *) NULL; +- xml_info->next=(XMLTreeInfo *) NULL; +- return(xml_info); +-} +- +-/* +-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-% % +-% % +-% % +-% S e t X M L T r e e A t t r i b u t e % +-% % +-% % +-% % +-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-% +-% SetXMLTreeAttribute() sets the tag attributes or adds a new attribute if not +-% found. A value of NULL removes the specified attribute. +-% +-% The format of the SetXMLTreeAttribute method is: +-% +-% XMLTreeInfo *SetXMLTreeAttribute(XMLTreeInfo *xml_info,const char *tag, +-% const char *value) +-% +-% A description of each parameter follows: +-% +-% o xml_info: the xml info. +-% +-% o tag: The attribute tag. +-% +-% o value: The attribute value. +-% +-*/ +-MagickPrivate XMLTreeInfo *SetXMLTreeAttribute(XMLTreeInfo *xml_info, +- const char *tag,const char *value) +-{ +- ssize_t +- i, +- j; +- +- assert(xml_info != (XMLTreeInfo *) NULL); +- assert((xml_info->signature == MagickCoreSignature) || +- (((XMLTreeRoot *) xml_info)->signature == MagickCoreSignature)); +- if (IsEventLogging() != MagickFalse) +- (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); +- i=0; +- while ((xml_info->attributes[i] != (char *) NULL) && +- (strcmp(xml_info->attributes[i],tag) != 0)) +- i+=2; +- if (xml_info->attributes[i] == (char *) NULL) +- { +- /* +- Add new attribute tag. +- */ +- if (value == (const char *) NULL) +- return(xml_info); +- if (xml_info->attributes != sentinel) +- xml_info->attributes=(char **) ResizeQuantumMemory( +- xml_info->attributes,(size_t) (i+4),sizeof(*xml_info->attributes)); +- else +- { +- xml_info->attributes=(char **) AcquireQuantumMemory(4, +- sizeof(*xml_info->attributes)); +- if (xml_info->attributes != (char **) NULL) +- xml_info->attributes[1]=ConstantString(""); +- } +- if (xml_info->attributes == (char **) NULL) +- ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString"); +- xml_info->attributes[i]=ConstantString(tag); +- xml_info->attributes[i+2]=(char *) NULL; +- (void) strlen(xml_info->attributes[i+1]); +- } +- /* +- Add new value to an existing attribute. +- */ +- for (j=i; xml_info->attributes[j] != (char *) NULL; j+=2) ; +- if (xml_info->attributes[i+1] != (char *) NULL) +- xml_info->attributes[i+1]=DestroyString(xml_info->attributes[i+1]); +- if (value != (const char *) NULL) +- { +- xml_info->attributes[i+1]=ConstantString(value); +- return(xml_info); +- } +- if (xml_info->attributes[i] != (char *) NULL) +- xml_info->attributes[i]=DestroyString(xml_info->attributes[i]); +- (void) memmove(xml_info->attributes+i,xml_info->attributes+i+2,(size_t) +- (j-i)*sizeof(*xml_info->attributes)); +- xml_info->attributes=(char **) ResizeQuantumMemory(xml_info->attributes, +- (size_t) (j+2),sizeof(*xml_info->attributes)); +- if (xml_info->attributes == (char **) NULL) +- ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString"); +- j-=2; +- (void) memmove(xml_info->attributes[j+1]+(i/2),xml_info->attributes[j+1]+ +- (i/2)+1,(size_t) (((j+2)/2)-(i/2))*sizeof(**xml_info->attributes)); +- return(xml_info); +-} +- +-/* +-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-% % +-% % +-% % + % S e t X M L T r e e C o n t e n t % + % % + % % diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-107208_2.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-107208_2.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-107208_2.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-107208_2.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,24 @@ +From: Dirk Lemstra +Date: Fri, 21 Aug 2026 22:20:24 +0200 +Subject: Don't throw a fatal exception when hitting a recursion depth + (GHSA-27m9-54jx-fgvq). + +(cherry picked from commit 907b74817836b4f88e7453f0e95c849a1c5311aa) +--- + MagickCore/xml-tree.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/MagickCore/xml-tree.c b/MagickCore/xml-tree.c +index d74487a..1313677 100644 +--- a/MagickCore/xml-tree.c ++++ b/MagickCore/xml-tree.c +@@ -531,8 +531,7 @@ static XMLTreeInfo *DestroyXMLTree_(XMLTreeInfo *xml_info, + if (IsEventLogging() != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); + if (depth > MagickMaxRecursionDepth) +- ThrowFatalException(ResourceLimitFatalError, +- "MemoryAllocationFailed"); ++ return((XMLTreeInfo *) NULL); + DestroyXMLTreeChild(xml_info,depth+1); + DestroyXMLTreeOrdered(xml_info,depth+1); + DestroyXMLTreeRoot(xml_info); diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-107209.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-107209.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-107209.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-107209.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,36 @@ +From: Dirk Lemstra +Date: Fri, 21 Aug 2026 11:20:57 +0200 +Subject: Fixed double free in non cairo builds + (https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-f2r2-qw7g-3c8x) + +(cherry picked from commit 326451aae51ac2dabc99fe66e063de6ec14cf8c8) + +origin: https://github.com/ImageMagick/ImageMagick/commit/326451aae51ac2dabc99fe66e063de6ec14cf8c8 +--- + coders/svg.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/coders/svg.c b/coders/svg.c +index 07b8416..d4ab405 100644 +--- a/coders/svg.c ++++ b/coders/svg.c +@@ -522,7 +522,7 @@ static Image *RenderRSVGImage(const ImageInfo *image_info,Image *image, + pixel_info=(MemoryInfo *) NULL; + #else + pixel_buffer=rsvg_handle_get_pixbuf(svg_handle); +- rsvg_handle_free(svg_handle); ++ g_object_unref(svg_handle); + image->columns=gdk_pixbuf_get_width(pixel_buffer); + image->rows=gdk_pixbuf_get_height(pixel_buffer); + #endif +@@ -539,8 +539,9 @@ static Image *RenderRSVGImage(const ImageInfo *image_info,Image *image, + { + #if !defined(MAGICKCORE_CAIRO_DELEGATE) + g_object_unref(G_OBJECT(pixel_buffer)); +-#endif ++#else + g_object_unref(svg_handle); ++#endif + ThrowReaderException(MissingDelegateError, + "NoDecodeDelegateForThisImageFormat"); + } diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-107210-pre1.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-107210-pre1.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-107210-pre1.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-107210-pre1.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,51 @@ +From: Cristy +Date: Sun, 5 Jul 2026 09:24:29 -0400 +Subject: check for insufficient image data + +(cherry picked from commit 62c229bb8ffbb0a8e42c3654298494b4b16b39a2) + +origin: https://github.com/ImageMagick/ImageMagick/commit/62c229bb8ffbb0a8e42c3654298494b4b16b39a2 +--- + coders/mat.c | 6 ++++++ + coders/wpg.c | 4 ++++ + 2 files changed, 10 insertions(+) + +diff --git a/coders/mat.c b/coders/mat.c +index 19f48ee..0947d36 100644 +--- a/coders/mat.c ++++ b/coders/mat.c +@@ -713,6 +713,9 @@ static Image *ReadMATImageV4(const ImageInfo *image_info,Image *image, + : image); + goto skip_reading_current; + } ++ if ((image->columns > GetBlobSize(image)) || ++ (image->rows > GetBlobSize(image))) ++ ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile"); + status=SetImageExtent(image,image->columns,image->rows,exception); + if (status == MagickFalse) + return(DestroyImageList(image)); +@@ -1237,6 +1240,9 @@ RestoreMSCWarning + image->rows = temp; + goto done_reading; /* !!!!!! BAD !!!! */ + } ++ if ((image->columns > GetBlobSize(image)) || ++ (image->rows > GetBlobSize(image))) ++ ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile"); + status=SetImageExtent(image,image->columns,image->rows,exception); + if (status == MagickFalse) + { +diff --git a/coders/wpg.c b/coders/wpg.c +index 57a59f2..358d81e 100644 +--- a/coders/wpg.c ++++ b/coders/wpg.c +@@ -1235,6 +1235,10 @@ static Image *ReadWPGImage(const ImageInfo *image_info,ExceptionInfo *exception) + bpp=(int) BitmapHeader2.Depth; + + UnpackRaster: ++ if ((image->columns > GetBlobSize(image)) || ++ (image->rows > GetBlobSize(image))) ++ ThrowReaderException(CorruptImageError, ++ "InsufficientImageDataInFile"); + status=SetImageExtent(image,image->columns,image->rows,exception); + if (status == MagickFalse) + break; diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-107210.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-107210.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-107210.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-107210.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,179 @@ +From: Cristy +Date: Mon, 17 Aug 2026 20:17:17 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-3j4w-pvxj-fpjc + +(cherry picked from commit ae2ed8c81d8fad1f186e7f2bc0837b46a1c7be61) + +origin: backport, https://github.com/ImageMagick/ImageMagick/commit/ae2ed8c81d8fad1f186e7f2bc0837b46a1c7be61 +--- + coders/mat.c | 107 +++++++++++++++++++++++++++++++++++------------------------ + 1 file changed, 63 insertions(+), 44 deletions(-) + +diff --git a/coders/mat.c b/coders/mat.c +index 0947d36..69f0df0 100644 +--- a/coders/mat.c ++++ b/coders/mat.c +@@ -484,7 +484,8 @@ static void RelinquishZIPMemory(voidpf context,voidpf memory) + + #if defined(MAGICKCORE_ZLIB_DELEGATE) + /** This procedure decompreses an image block for a new MATLAB format. */ +-static Image *decompress_block(Image *orig, unsigned int *Size, ImageInfo *clone_info, ExceptionInfo *exception) ++static Image *decompress_block(Image *orig,unsigned int *Size, ++ ImageInfo *clone_info,ExceptionInfo *exception) + { + + Image *image2; +@@ -497,27 +498,33 @@ int file; + + MagickBooleanType status; + int zip_status; +-ssize_t TotalSize = 0; ++ssize_t total_size = 0; ++size_t compressed_total = 0; ++static const size_t MAX_ABSOLUTE_SIZE = 512UL * 1024UL * 1024UL; /* 512 MB */ ++static const size_t MAX_EXPANSION_RATIO = 64; /* 64x expansion allowed */ + +- if(clone_info==NULL) return NULL; +- if(clone_info->file) /* Close file opened from previous transaction. */ +- { +- fclose(clone_info->file); +- clone_info->file = NULL; +- (void) remove_utf8(clone_info->filename); +- } +- +- cache_block = AcquireQuantumMemory((size_t)(*Size < MagickMinBufferExtent) ? *Size: MagickMinBufferExtent,sizeof(unsigned char *)); +- if(cache_block==NULL) return NULL; +- decompress_block = AcquireQuantumMemory((size_t)(4096),sizeof(unsigned char *)); +- if(decompress_block==NULL) +- { +- RelinquishMagickMemory(cache_block); ++ if (clone_info == NULL) + return NULL; +- } ++ if (clone_info->file) /* Close file opened from previous transaction. */ ++ { ++ fclose(clone_info->file); ++ clone_info->file = NULL; ++ (void) remove_utf8(clone_info->filename); ++ } + ++ cache_block=AcquireQuantumMemory((size_t) (*Size < MagickMinBufferExtent) ? ++ *Size: MagickMinBufferExtent,sizeof(unsigned char *)); ++ if (cache_block == NULL) ++ return NULL; ++ decompress_block=AcquireQuantumMemory((size_t) (4096), ++ sizeof(unsigned char *)); ++ if (decompress_block == NULL) ++ { ++ RelinquishMagickMemory(cache_block); ++ return NULL; ++ } + mat_file=0; +- file = AcquireUniqueFileResource(clone_info->filename); ++ file=AcquireUniqueFileResource(clone_info->filename); + if (file != -1) + mat_file = fdopen(file,"ab+"); + if(!mat_file) +@@ -531,8 +538,8 @@ ssize_t TotalSize = 0; + (void) memset(&zip_info,0,sizeof(zip_info)); + zip_info.zalloc=AcquireZIPMemory; + zip_info.zfree=RelinquishZIPMemory; +- zip_info.opaque = (voidpf) NULL; +- zip_status = inflateInit(&zip_info); ++ zip_info.opaque=(voidpf) NULL; ++ zip_status=inflateInit(&zip_info); + if (zip_status != Z_OK) + { + RelinquishMagickMemory(cache_block); +@@ -541,37 +548,50 @@ ssize_t TotalSize = 0; + "UnableToUncompressImage","`%s'",clone_info->filename); + (void) fclose(mat_file); + RelinquishUniqueFileResource(clone_info->filename); +- return NULL; ++ return(NULL); + } +- /* zip_info.next_out = 8*4;*/ +- +- zip_info.avail_in = 0; +- zip_info.total_out = 0; +- while(*Size>0 && !EOFBlob(orig)) ++ zip_info.avail_in=0; ++ zip_info.total_out=0; ++ while ((*Size > 0) && (EOFBlob(orig) == 0)) + { +- magick_size = ReadBlob(orig, (*Size < MagickMinBufferExtent) ? *Size : MagickMinBufferExtent, (unsigned char *) cache_block); ++ magick_size=ReadBlob(orig,(*Size < MagickMinBufferExtent) ? *Size : ++ MagickMinBufferExtent,(unsigned char *) cache_block); + if (magick_size == 0) + break; +- zip_info.next_in = (Bytef *) cache_block; +- zip_info.avail_in = (uInt) magick_size; +- +- while(zip_info.avail_in>0) ++ zip_info.next_in=(Bytef *) cache_block; ++ zip_info.avail_in=(uInt) magick_size; ++ compressed_total+=magick_size; ++ while (zip_info.avail_in > 0) + { +- zip_info.avail_out = 4096; +- zip_info.next_out = (Bytef *) decompress_block; +- zip_status = inflate(&zip_info,Z_NO_FLUSH); ++ size_t chunk_size = 0; ++ zip_info.avail_out=4096; ++ zip_info.next_out=(Bytef *) decompress_block; ++ zip_status=inflate(&zip_info,Z_NO_FLUSH); + if ((zip_status != Z_OK) && (zip_status != Z_STREAM_END)) + break; +- extent=fwrite(decompress_block,1,4096-zip_info.avail_out,mat_file); +- (void) extent; +- TotalSize += 4096-zip_info.avail_out; +- +- if(zip_status == Z_STREAM_END) goto DblBreak; ++ chunk_size=4096-zip_info.avail_out; ++ extent=fwrite(decompress_block,1,chunk_size,mat_file); ++ if (extent != chunk_size) ++ { ++ zip_status=Z_DATA_ERROR; ++ break; ++ } ++ total_size+=chunk_size; ++ if (compressed_total > 0) ++ { ++ if ((total_size > (ssize_t) MAX_ABSOLUTE_SIZE) || ++ (total_size > (ssize_t) (compressed_total*MAX_EXPANSION_RATIO))) ++ { ++ zip_status=Z_DATA_ERROR; ++ break; ++ } ++ } ++ if (zip_status == Z_STREAM_END) ++ goto DblBreak; + } + if ((zip_status != Z_OK) && (zip_status != Z_STREAM_END)) + break; +- +- *Size -= (unsigned int) magick_size; ++ *Size-=(unsigned int) magick_size; + } + DblBreak: + +@@ -581,7 +601,7 @@ DblBreak: + "UnableToCreateTemporaryFile","`%s'",clone_info->filename); + RelinquishMagickMemory(cache_block); + RelinquishMagickMemory(decompress_block); +- *Size = TotalSize; ++ *Size = (unsigned int) total_size; + + clone_info->file=mat_file; + if( (image2 = AcquireImage(clone_info,exception))==NULL ) goto EraseFile; +@@ -597,8 +617,7 @@ EraseFile: + RelinquishUniqueFileResource(clone_info->filename); + return NULL; + } +- +- return image2; ++ return(image2); + } + #endif + diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-109261.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-109261.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-109261.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-109261.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,32 @@ +From: Cristy +Date: Tue, 22 Sep 2026 07:05:21 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-w68r-6fmr-cvg4 + +(cherry picked from commit 1c7763266cfedc635005a965169bc2ddcc650221) + +origin: https://github.com/ImageMagick/ImageMagick/commit/1c7763266cfedc635005a965169bc2ddcc650221 +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-w68r-6fmr-cvg4 +--- + coders/gif.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/coders/gif.c b/coders/gif.c +index 762f8fc..8cd7f54 100644 +--- a/coders/gif.c ++++ b/coders/gif.c +@@ -1653,7 +1653,13 @@ static MagickBooleanType WriteGIFImage(const ImageInfo *image_info,Image *image, + } + } + if ((image->storage_class == DirectClass) || (image->colors > 256)) +- ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); ++ { ++ global_colormap=(unsigned char *) RelinquishMagickMemory( ++ global_colormap); ++ colormap=(unsigned char *) RelinquishMagickMemory(colormap); ++ write_info=DestroyImageInfo(write_info); ++ ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); ++ } + for (bits_per_pixel=1; bits_per_pixel < 8; bits_per_pixel++) + if ((one << bits_per_pixel) >= image->colors) + break; diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-25971-post1.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-25971-post1.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-25971-post1.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-25971-post1.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,47 @@ +From: Cristy +Date: Wed, 17 Jun 2026 20:09:00 -0400 +Subject: https://github.com/ImageMagick/ImageMagick/issues/8803 Fix + regression in svg base64 + +origin: https://github.com/ImageMagick/ImageMagick/commit/c0a724bbbd2c131ca6e2b79e67cd245e5150a19a +bug-debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1150224 +--- + coders/svg.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/coders/svg.c b/coders/svg.c +index d74ef6b..07b8416 100644 +--- a/coders/svg.c ++++ b/coders/svg.c +@@ -2692,7 +2692,7 @@ static void SVGEndElement(void *context,const xmlChar *name) + thread_filename[MagickPathExtent]; + + Image +- *image; ++ *image = (Image *) NULL; + + ImageInfo + *image_info = AcquireImageInfo(); +@@ -2715,7 +2715,21 @@ static void SVGEndElement(void *context,const xmlChar *name) + (void *) 1); + (void) CopyMagickString(image_info->filename,svg_info->url, + MagickPathExtent); +- image=ReadImage(image_info,svg_info->exception); ++ if (LocaleNCompare(image_info->filename,"data:",5) == 0) ++ image=ReadInlineImage(image_info,svg_info->url,svg_info->exception); ++ else ++ { ++ char ++ magic[MagickPathExtent] = { '\0' }; ++ ++ GetPathComponent(image_info->filename,MagickPath,magic); ++ if (*magic == '\0') ++ image=ReadImage(image_info,svg_info->exception); ++ else ++ (void) ThrowMagickException(svg_info->exception, ++ GetMagickModule(),FileOpenError,"UnableToOpenFile","`%s'", ++ image_info->filename); ++ } + image_info=DestroyImageInfo(image_info); + if (image != (Image *) NULL) + image=DestroyImage(image); diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-62343.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-62343.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-62343.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-62343.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,239 @@ +From: Dirk Lemstra +Date: Sun, 21 Jun 2026 10:03:27 +0200 +Subject: Added extra checks when acquiring the values of a kernel + (GHSA-f5m7-cqgw-8hm7) + +(cherry picked from commit 9acf93f66b0f8495fa222e1a27c3db534cd78864) + +origin: https://github.com/ImageMagick/ImageMagick/commit/9acf93f66b0f8495fa222e1a27c3db534cd78864 +bug: https://github.com/advisories/GHSA-f5m7-cqgw-8hm7 +--- + MagickCore/morphology.c | 96 ++++++++++++++++--------------------------------- + 1 file changed, 30 insertions(+), 66 deletions(-) + +diff --git a/MagickCore/morphology.c b/MagickCore/morphology.c +index f4799a6..18a5938 100644 +--- a/MagickCore/morphology.c ++++ b/MagickCore/morphology.c +@@ -200,6 +200,19 @@ static inline KernelInfo *LastKernelInfo(KernelInfo *kernel) + % + */ + ++static inline MagickBooleanType AcquireKernelValues(KernelInfo *kernel) ++{ ++ size_t ++ elements; ++ ++ kernel->values=(MagickRealType *) NULL; ++ if (HeapOverflowSanityCheckGetSize(kernel->width,kernel->height,&elements) != MagickFalse) ++ return(MagickFalse); ++ kernel->values=(MagickRealType *) MagickAssumeAligned(AcquireAlignedMemory( ++ elements,sizeof(*kernel->values))); ++ return(kernel->values == (MagickRealType *) NULL ? MagickFalse : MagickTrue); ++} ++ + /* This was separated so that it could be used as a separate + ** array input handling function, such as for -color-matrix + */ +@@ -307,9 +320,7 @@ static KernelInfo *ParseKernelArray(const char *kernel_string) + } + + /* Read in the kernel values from rest of input string argument */ +- kernel->values=(MagickRealType *) MagickAssumeAligned(AcquireAlignedMemory( +- kernel->width,kernel->height*sizeof(*kernel->values))); +- if (kernel->values == (MagickRealType *) NULL) ++ if (AcquireKernelValues(kernel) == MagickFalse) + return(DestroyKernelInfo(kernel)); + kernel->minimum=MagickMaximumValue; + kernel->maximum=(-MagickMaximumValue); +@@ -1059,10 +1070,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + kernel->width = GetOptimalKernelWidth2D(args->rho,sigma2); + kernel->height = kernel->width; + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; +- kernel->values=(MagickRealType *) MagickAssumeAligned( +- AcquireAlignedMemory(kernel->width,kernel->height* +- sizeof(*kernel->values))); +- if (kernel->values == (MagickRealType *) NULL) ++ if (AcquireKernelValues(kernel) == MagickFalse) + return(DestroyKernelInfo(kernel)); + + /* WARNING: The following generates a 'sampled gaussian' kernel. +@@ -1151,10 +1159,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + kernel->x = (ssize_t) (kernel->width-1)/2; + kernel->y = 0; + kernel->negative_range = kernel->positive_range = 0.0; +- kernel->values=(MagickRealType *) MagickAssumeAligned( +- AcquireAlignedMemory(kernel->width,kernel->height* +- sizeof(*kernel->values))); +- if (kernel->values == (MagickRealType *) NULL) ++ if (AcquireKernelValues(kernel) == MagickFalse) + return(DestroyKernelInfo(kernel)); + + #if 1 +@@ -1238,10 +1243,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + kernel->x = kernel->y = 0; + kernel->height = 1; + kernel->negative_range = kernel->positive_range = 0.0; +- kernel->values=(MagickRealType *) MagickAssumeAligned( +- AcquireAlignedMemory(kernel->width,kernel->height* +- sizeof(*kernel->values))); +- if (kernel->values == (MagickRealType *) NULL) ++ if (AcquireKernelValues(kernel) == MagickFalse) + return(DestroyKernelInfo(kernel)); + + /* A comet blur is half a 1D gaussian curve, so that the object is +@@ -1315,10 +1317,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + + order_f = fact(kernel->width-1); + +- kernel->values=(MagickRealType *) MagickAssumeAligned( +- AcquireAlignedMemory(kernel->width,kernel->height* +- sizeof(*kernel->values))); +- if (kernel->values == (MagickRealType *) NULL) ++ if (AcquireKernelValues(kernel) == MagickFalse) + return(DestroyKernelInfo(kernel)); + + /* set all kernel values within diamond area to scale given */ +@@ -1550,10 +1549,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + kernel->width = kernel->height = ((size_t)args->rho)*2+1; + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + +- kernel->values=(MagickRealType *) MagickAssumeAligned( +- AcquireAlignedMemory(kernel->width,kernel->height* +- sizeof(*kernel->values))); +- if (kernel->values == (MagickRealType *) NULL) ++ if (AcquireKernelValues(kernel) == MagickFalse) + return(DestroyKernelInfo(kernel)); + + /* set all kernel values within diamond area to scale given */ +@@ -1592,10 +1588,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + kernel->y = (ssize_t) args->psi; + scale = 1.0; + } +- kernel->values=(MagickRealType *) MagickAssumeAligned( +- AcquireAlignedMemory(kernel->width,kernel->height* +- sizeof(*kernel->values))); +- if (kernel->values == (MagickRealType *) NULL) ++ if (AcquireKernelValues(kernel) == MagickFalse) + return(DestroyKernelInfo(kernel)); + + /* set all kernel values to scale given */ +@@ -1614,10 +1607,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + kernel->width = kernel->height = ((size_t)args->rho)*2+1; + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + +- kernel->values=(MagickRealType *) MagickAssumeAligned( +- AcquireAlignedMemory(kernel->width,kernel->height* +- sizeof(*kernel->values))); +- if (kernel->values == (MagickRealType *) NULL) ++ if (AcquireKernelValues(kernel) == MagickFalse) + return(DestroyKernelInfo(kernel)); + + for ( i=0, v=-kernel->y; v <= (ssize_t)kernel->y; v++) +@@ -1641,10 +1631,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + kernel->width = kernel->height = (size_t)fabs(args->rho)*2+1; + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + +- kernel->values=(MagickRealType *) MagickAssumeAligned( +- AcquireAlignedMemory(kernel->width,kernel->height* +- sizeof(*kernel->values))); +- if (kernel->values == (MagickRealType *) NULL) ++ if (AcquireKernelValues(kernel) == MagickFalse) + return(DestroyKernelInfo(kernel)); + + for ( i=0, v=-kernel->y; v <= (ssize_t)kernel->y; v++) +@@ -1664,10 +1651,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + kernel->width = kernel->height = ((size_t)args->rho)*2+1; + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + +- kernel->values=(MagickRealType *) MagickAssumeAligned( +- AcquireAlignedMemory(kernel->width,kernel->height* +- sizeof(*kernel->values))); +- if (kernel->values == (MagickRealType *) NULL) ++ if (AcquireKernelValues(kernel) == MagickFalse) + return(DestroyKernelInfo(kernel)); + + /* set all kernel values along axises to given scale */ +@@ -1686,10 +1670,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + kernel->width = kernel->height = ((size_t)args->rho)*2+1; + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + +- kernel->values=(MagickRealType *) MagickAssumeAligned( +- AcquireAlignedMemory(kernel->width,kernel->height* +- sizeof(*kernel->values))); +- if (kernel->values == (MagickRealType *) NULL) ++ if (AcquireKernelValues(kernel) == MagickFalse) + return(DestroyKernelInfo(kernel)); + + /* set all kernel values along axises to given scale */ +@@ -1728,10 +1709,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + + kernel->height = kernel->width; + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; +- kernel->values=(MagickRealType *) MagickAssumeAligned( +- AcquireAlignedMemory(kernel->width,kernel->height* +- sizeof(*kernel->values))); +- if (kernel->values == (MagickRealType *) NULL) ++ if (AcquireKernelValues(kernel) == MagickFalse) + return(DestroyKernelInfo(kernel)); + + /* set a ring of points of 'scale' ( 0.0 for PeaksKernel ) */ +@@ -2103,10 +2081,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + kernel->width = kernel->height = ((size_t)args->rho)*2+1; + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + +- kernel->values=(MagickRealType *) MagickAssumeAligned( +- AcquireAlignedMemory(kernel->width,kernel->height* +- sizeof(*kernel->values))); +- if (kernel->values == (MagickRealType *) NULL) ++ if (AcquireKernelValues(kernel) == MagickFalse) + return(DestroyKernelInfo(kernel)); + + for ( i=0, v=-kernel->y; v <= (ssize_t)kernel->y; v++) +@@ -2124,10 +2099,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + kernel->width = kernel->height = ((size_t)args->rho)*2+1; + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + +- kernel->values=(MagickRealType *) MagickAssumeAligned( +- AcquireAlignedMemory(kernel->width,kernel->height* +- sizeof(*kernel->values))); +- if (kernel->values == (MagickRealType *) NULL) ++ if (AcquireKernelValues(kernel) == MagickFalse) + return(DestroyKernelInfo(kernel)); + + for ( i=0, v=-kernel->y; v <= (ssize_t)kernel->y; v++) +@@ -2145,10 +2117,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + kernel->width = kernel->height = ((size_t)args->rho)*2+1; + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + +- kernel->values=(MagickRealType *) MagickAssumeAligned( +- AcquireAlignedMemory(kernel->width,kernel->height* +- sizeof(*kernel->values))); +- if (kernel->values == (MagickRealType *) NULL) ++ if (AcquireKernelValues(kernel) == MagickFalse) + return(DestroyKernelInfo(kernel)); + + for ( i=0, v=-kernel->y; v <= (ssize_t)kernel->y; v++) +@@ -2171,10 +2140,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + kernel->width = kernel->height = ((size_t)args->rho)*2+1; + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + +- kernel->values=(MagickRealType *) MagickAssumeAligned( +- AcquireAlignedMemory(kernel->width,kernel->height* +- sizeof(*kernel->values))); +- if (kernel->values == (MagickRealType *) NULL) ++ if (AcquireKernelValues(kernel) == MagickFalse) + return(DestroyKernelInfo(kernel)); + + for ( i=0, v=-kernel->y; v <= (ssize_t)kernel->y; v++) +@@ -2237,9 +2203,7 @@ MagickExport KernelInfo *CloneKernelInfo(const KernelInfo *kernel) + *new_kernel=(*kernel); /* copy values in structure */ + + /* replace the values with a copy of the values */ +- new_kernel->values=(MagickRealType *) MagickAssumeAligned( +- AcquireAlignedMemory(kernel->width,kernel->height*sizeof(*kernel->values))); +- if (new_kernel->values == (MagickRealType *) NULL) ++ if (AcquireKernelValues(new_kernel) == MagickFalse) + return(DestroyKernelInfo(new_kernel)); + for (i=0; i < (ssize_t) (kernel->width*kernel->height); i++) + new_kernel->values[i]=kernel->values[i]; diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-62363_1.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-62363_1.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-62363_1.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-62363_1.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,98 @@ +From: Cristy +Date: Mon, 22 Jun 2026 06:54:13 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-422r-8c97-xcg4 + +a heap buffer over-write can occur in the fx operation by passing a crafted argument. + +(cherry picked from commit be99ffaa57c8f91ed8897c2221ff0940c561a368) + +origin: https://github.com/ImageMagick/ImageMagick/commit/be99ffaa57c8f91ed8897c2221ff0940c561a368 +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-422r-8c97-xcg4 +--- + MagickCore/fx.c | 67 ++++++++++++++++++++++++++++++++++++++++++++------------- + 1 file changed, 52 insertions(+), 15 deletions(-) + +diff --git a/MagickCore/fx.c b/MagickCore/fx.c +index 42d6d8e..e2ccb9e 100644 +--- a/MagickCore/fx.c ++++ b/MagickCore/fx.c +@@ -861,26 +861,63 @@ static ElementTypeE TypeOfOpr (int op) + return (ElementTypeE) 0; + } + +-static char * SetPtrShortExp (FxInfo * pfx, char * pExp, size_t len) ++static char *SetPtrShortExp(FxInfo *pfx, const char *pExp, size_t len) + { +- #define MaxLen 20 ++#define MaxLen 20 + +- size_t slen; +- char * p; ++ char *dst = pfx->ShortExp; ++ size_t dst_size = MagickPathExtent; // actual buffer size ++ size_t copy_len; ++ ++ if (dst_size == 0) ++ return dst; ++ ++ dst[0] = '\0'; + +- *pfx->ShortExp = '\0'; ++ if (pExp && len) ++ { ++ /* Clamp to buffer size - 1 */ ++ copy_len = len; ++ if (copy_len > dst_size - 1) ++ copy_len = dst_size - 1; ++ ++ memcpy(dst, pExp, copy_len); ++ dst[copy_len] = '\0'; + +- if (pExp && len) { +- slen = CopyMagickString (pfx->ShortExp, pExp, len); +- if (slen > MaxLen) { +- (void) CopyMagickString (pfx->ShortExp+MaxLen, "...", 4); ++ /* Logical truncation to MaxLen */ ++ if (copy_len > MaxLen) ++ { ++ if (MaxLen + 3 < dst_size) ++ { ++ memcpy(dst + MaxLen, "...", 3); ++ dst[MaxLen + 3] = '\0'; ++ } ++ else ++ { ++ dst[dst_size - 1] = '\0'; ++ } ++ } ++ ++ /* Replace newline / carriage return safely */ ++ char *p; ++ ++ if ((p = strchr(dst, '\n')) != NULL || ++ (p = strchr(dst, '\r')) != NULL) ++ { ++ size_t offset = (size_t)(p - dst); ++ if (offset + 3 < dst_size) ++ { ++ memcpy(p, "...", 3); ++ dst[offset + 3] = '\0'; ++ } ++ else ++ { ++ dst[dst_size - 1] = '\0'; ++ } ++ } + } +- p = strchr (pfx->ShortExp, '\n'); +- if (p) (void) CopyMagickString (p, "...", 4); +- p = strchr (pfx->ShortExp, '\r'); +- if (p) (void) CopyMagickString (p, "...", 4); +- } +- return pfx->ShortExp; ++ ++ return dst; + } + + static char * SetShortExp (FxInfo * pfx) diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-62363_2.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-62363_2.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-62363_2.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-62363_2.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,97 @@ +From: Cristy +Date: Mon, 22 Jun 2026 18:26:31 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-422r-8c97-xcg4 + +(cherry picked from commit 0bbf7e48f5dd0ef540d3ae1ae8dfc6cd036fb640) + +origin: https://github.com/ImageMagick/ImageMagick/commit/0bbf7e48f5dd0ef540d3ae1ae8dfc6cd036fb640 +Bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-422r-8c97-xcg4 +--- + MagickCore/fx.c | 65 ++++++++++++++------------------------------------------- + 1 file changed, 16 insertions(+), 49 deletions(-) + +diff --git a/MagickCore/fx.c b/MagickCore/fx.c +index e2ccb9e..1f3b36b 100644 +--- a/MagickCore/fx.c ++++ b/MagickCore/fx.c +@@ -861,63 +861,30 @@ static ElementTypeE TypeOfOpr (int op) + return (ElementTypeE) 0; + } + +-static char *SetPtrShortExp(FxInfo *pfx, const char *pExp, size_t len) ++static char * SetPtrShortExp (FxInfo *pfx, char *pExp, size_t len) + { +-#define MaxLen 20 ++ #define MaxLen 20 + +- char *dst = pfx->ShortExp; +- size_t dst_size = MagickPathExtent; // actual buffer size +- size_t copy_len; ++ size_t slen; ++ char *p; + +- if (dst_size == 0) +- return dst; ++ *pfx->ShortExp = '\0'; + +- dst[0] = '\0'; ++ if (pExp && len) { ++ slen = CopyMagickString(pfx->ShortExp, pExp, MagickPathExtent); + +- if (pExp && len) +- { +- /* Clamp to buffer size - 1 */ +- copy_len = len; +- if (copy_len > dst_size - 1) +- copy_len = dst_size - 1; +- +- memcpy(dst, pExp, copy_len); +- dst[copy_len] = '\0'; +- +- /* Logical truncation to MaxLen */ +- if (copy_len > MaxLen) +- { +- if (MaxLen + 3 < dst_size) +- { +- memcpy(dst + MaxLen, "...", 3); +- dst[MaxLen + 3] = '\0'; +- } +- else +- { +- dst[dst_size - 1] = '\0'; +- } +- } ++ if (slen > MaxLen) { ++ (void) CopyMagickString(pfx->ShortExp + MaxLen, "...", 4); ++ } + +- /* Replace newline / carriage return safely */ +- char *p; ++ p = strchr(pfx->ShortExp, '\n'); ++ if (p) (void) CopyMagickString(p, "...", 4); + +- if ((p = strchr(dst, '\n')) != NULL || +- (p = strchr(dst, '\r')) != NULL) +- { +- size_t offset = (size_t)(p - dst); +- if (offset + 3 < dst_size) +- { +- memcpy(p, "...", 3); +- dst[offset + 3] = '\0'; +- } +- else +- { +- dst[dst_size - 1] = '\0'; +- } +- } +- } ++ p = strchr(pfx->ShortExp, '\r'); ++ if (p) (void) CopyMagickString(p, "...", 4); ++ } + +- return dst; ++ return pfx->ShortExp; + } + + static char * SetShortExp (FxInfo * pfx) diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-62946.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-62946.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-62946.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-62946.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,29 @@ +From: Cristy +Date: Sat, 27 Jun 2026 12:11:40 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-h22j-f9xw-xjjm + +processing an extremely large JNX file on 32-bit platforms can cause an integer overflow, leading to a heap buffer over-write. + +origin: https://github.com/ImageMagick/ImageMagick/commit/538ad18f3a421d1dd9629baa747eebc137c32b67 +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-h22j-f9xw-xjjm +--- + coders/jnx.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/coders/jnx.c b/coders/jnx.c +index da4d44b..a372a00 100644 +--- a/coders/jnx.c ++++ b/coders/jnx.c +@@ -284,6 +284,11 @@ static Image *ReadJNXImage(const ImageInfo *image_info,ExceptionInfo *exception) + images=DestroyImageList(images); + ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile"); + } ++ if (tile_length > (UINT_MAX-2)) ++ { ++ images=DestroyImageList(images); ++ ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); ++ } + blob=(unsigned char *) AcquireQuantumMemory((size_t) tile_length+2, + sizeof(*blob)); + if (blob == (unsigned char *) NULL) diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-64685.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-64685.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-64685.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-64685.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,56 @@ +From: Dirk Lemstra +Date: Thu, 2 Jul 2026 16:17:23 +0200 +Subject: Make sure we check the length after each read (GHSA-7rgw-xg25-prjm) + +(cherry picked from commit 093f476e985d61557ea75ad0ef30d491dff816f3) + +origin: https://github.com/ImageMagick/ImageMagick/commit/093f476e985d61557ea75ad0ef30d491dff816f3 +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-7rgw-xg25-prjm +--- + coders/bgr.c | 30 +++++++++++++++--------------- + 1 file changed, 15 insertions(+), 15 deletions(-) + +diff --git a/coders/bgr.c b/coders/bgr.c +index 98a2ed7..1caf567 100644 +--- a/coders/bgr.c ++++ b/coders/bgr.c +@@ -312,24 +312,24 @@ static Image *ReadBGRImage(const ImageInfo *image_info,ExceptionInfo *exception) + } + for (y=0; y < (ssize_t) image->extract_info.height; y++) + { +- const Quantum +- *magick_restrict p; ++ for (i=0; i < (ssize_t) (image->alpha_trait != UndefinedPixelTrait ? 4 : 3); i++) ++ { ++ const Quantum ++ *magick_restrict p; + +- Quantum +- *magick_restrict q; ++ Quantum ++ *magick_restrict q; + +- ssize_t +- x; ++ ssize_t ++ x; + +- if (count != (ssize_t) length) +- { +- status=MagickFalse; +- ThrowFileException(exception,CorruptImageError, +- "UnexpectedEndOfFile",image->filename); +- break; +- } +- for (i=0; i < (ssize_t) (image->alpha_trait != UndefinedPixelTrait ? 4 : 3); i++) +- { ++ if (count != (ssize_t) length) ++ { ++ status=MagickFalse; ++ ThrowFileException(exception,CorruptImageError, ++ "UnexpectedEndOfFile",image->filename); ++ break; ++ } + quantum_type=quantum_types[i]; + q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1, + exception); diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86420.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86420.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86420.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86420.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,27 @@ +From: Cristy +Date: Fri, 21 Aug 2026 12:52:43 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-4mwf-mggw-29vp + +(cherry picked from commit 6ac07556a93b2de00c845cd535ca256f45a47154) + +Imagemagick fails to properly lower the memory budget when an operation inside OpenPixelCache fails. Repeated triggering of such failures can exhaust the process memory budget and result in a denial of service. + +origin: https://github.com/ImageMagick/ImageMagick/commit/6ac07556a93b2de00c845cd535ca256f45a47154 +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-4mwf-mggw-29vp +--- + MagickCore/cache.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/MagickCore/cache.c b/MagickCore/cache.c +index e09ba91..5194098 100644 +--- a/MagickCore/cache.c ++++ b/MagickCore/cache.c +@@ -3793,6 +3793,7 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode, + } + if (cache_info->pixels == (Quantum *) NULL) + { ++ RelinquishMagickResource(MemoryResource,cache_info->length); + cache_info->mapped=source_info.mapped; + cache_info->pixels=source_info.pixels; + } diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86421.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86421.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86421.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86421.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,27 @@ +From: Cristy +Date: Fri, 21 Aug 2026 22:07:26 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-4jv7-q6xw-6f4x + +A memory leak in the MSL image decoder. A crafted MSL image triggers memory allocation without proper deallocation, allowing an attacker to exhaust memory and cause a denial of service. + +(cherry picked from commit c83153dfc128de8e7c538f879c532c7d36a75abb) +origin: https://github.com/ImageMagick/ImageMagick/commit/c83153dfc128de8e7c538f879c532c7d36a75abb +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-4jv7-q6xw-6f4x +--- + coders/msl.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/coders/msl.c b/coders/msl.c +index 340fd2e..450f55a 100644 +--- a/coders/msl.c ++++ b/coders/msl.c +@@ -7169,6 +7169,8 @@ static void MSLEndElement(void *context,const xmlChar *tag) + msl_info->image[msl_info->n]); + msl_info->attributes[msl_info->n]=DestroyImage( + msl_info->attributes[msl_info->n]); ++ msl_info->draw_info[msl_info->n]=DestroyDrawInfo( ++ msl_info->draw_info[msl_info->n]); + msl_info->image_info[msl_info->n]=DestroyImageInfo( + msl_info->image_info[msl_info->n]); + msl_info->n--; diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86423.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86423.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86423.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86423.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,144 @@ +From: Cristy +Date: Sat, 15 Aug 2026 15:10:11 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-5m9j-96ff-j6qc + +Fix a heap-use-after-free vulnerability in the GetList method of PerlMagick. A crafted call to the GetList method can trigger the use-after-free, resulting in a crash (denial of service). + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-5m9j-96ff-j6qc +origin: https://github.com/ImageMagick/ImageMagick/commit/1d3e98913f6a8fa34b5a4180eadb9ed195b918a8 +--- + PerlMagick/quantum/quantum.xs | 38 +++++++++++++++++++++++++++++++++----- + PerlMagick/quantum/quantum.xs.in | 38 +++++++++++++++++++++++++++++++++----- + 2 files changed, 66 insertions(+), 10 deletions(-) + +diff --git a/PerlMagick/quantum/quantum.xs b/PerlMagick/quantum/quantum.xs +index 7b23be0..9adf8c9 100644 +--- a/PerlMagick/quantum/quantum.xs ++++ b/PerlMagick/quantum/quantum.xs +@@ -906,9 +906,11 @@ static Image *GetList(pTHX_ SV *reference,SV ***reference_vector, + + Image + *head, +- *previous; ++ *previous, ++ **seen = (Image **) NULL; + + ssize_t ++ count = 0, + i, + n; + +@@ -931,17 +933,43 @@ static Image *GetList(pTHX_ SV *reference,SV ***reference_vector, + exception); + if (image == (Image *) NULL) + continue; +- if (image == previous) ++ { ++ MagickBooleanType duplicate = MagickFalse; ++ ssize_t j = 0; ++ for (j=0; j < count; j++) + { +- image=CloneImage(image,0,0,MagickTrue,exception); +- if (image == (Image *) NULL) +- return(NULL); ++ if (seen[j] == image) ++ { ++ duplicate=MagickTrue; ++ break; ++ } + } ++ if (duplicate != MagickFalse) ++ { ++ /* ++ Clone if already seen (adjacent or non-adjacent). ++ */ ++ Image *clone = CloneImage(image,0,0,MagickTrue,exception); ++ if (clone == (Image *) NULL) ++ { ++ if (seen != (Image **) NULL) ++ free(seen); ++ return(NULL); ++ } ++ image=clone; ++ } ++ seen=(Image **) realloc(seen,(count+1)*sizeof(Image *)); ++ if (seen == (Image **) NULL) ++ return((Image *) NULL); ++ seen[count++]=image; ++ } + image->previous=previous; + *(previous ? &previous->next : &head)=image; + for (previous=image; previous->next; previous=previous->next) ; + } + } ++ if (seen != (Image **) NULL) ++ free(seen); + return(head); + } + case SVt_PVMG: +diff --git a/PerlMagick/quantum/quantum.xs.in b/PerlMagick/quantum/quantum.xs.in +index 0d131c1..bfcf7ba 100644 +--- a/PerlMagick/quantum/quantum.xs.in ++++ b/PerlMagick/quantum/quantum.xs.in +@@ -906,9 +906,11 @@ static Image *GetList(pTHX_ SV *reference,SV ***reference_vector, + + Image + *head, +- *previous; ++ *previous, ++ **seen = (Image **) NULL; + + ssize_t ++ count = 0, + i, + n; + +@@ -931,17 +933,43 @@ static Image *GetList(pTHX_ SV *reference,SV ***reference_vector, + exception); + if (image == (Image *) NULL) + continue; +- if (image == previous) ++ { ++ MagickBooleanType duplicate = MagickFalse; ++ ssize_t j = 0; ++ for (j=0; j < count; j++) + { +- image=CloneImage(image,0,0,MagickTrue,exception); +- if (image == (Image *) NULL) +- return(NULL); ++ if (seen[j] == image) ++ { ++ duplicate=MagickTrue; ++ break; ++ } + } ++ if (duplicate != MagickFalse) ++ { ++ /* ++ Clone if already seen (adjacent or non-adjacent). ++ */ ++ Image *clone = CloneImage(image,0,0,MagickTrue,exception); ++ if (clone == (Image *) NULL) ++ { ++ if (seen != (Image **) NULL) ++ free(seen); ++ return(NULL); ++ } ++ image=clone; ++ } ++ seen=(Image **) realloc(seen,(count+1)*sizeof(Image *)); ++ if (seen == (Image **) NULL) ++ return((Image *) NULL); ++ seen[count++]=image; ++ } + image->previous=previous; + *(previous ? &previous->next : &head)=image; + for (previous=image; previous->next; previous=previous->next) ; + } + } ++ if (seen != (Image **) NULL) ++ free(seen); + return(head); + } + case SVt_PVMG: diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,117 @@ +From: Cristy +Date: Fri, 14 Aug 2026 14:25:12 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-9x6f-98x9-rx6g + +(cherry picked from commit a44ef50cc494253f7d9f0229bb25c064a8e2ae69) +origin: backport, https://github.com/ImageMagick/ImageMagick/commit/a44ef50cc494253f7d9f0229bb25c064a8e2ae69 +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-9x6f-98x9-rx6g +--- + MagickCore/delegate.c | 36 ++++++++++++++++++++++-------------- + MagickCore/policy.c | 6 +++--- + 2 files changed, 25 insertions(+), 17 deletions(-) + +diff --git a/MagickCore/delegate.c b/MagickCore/delegate.c +index 6df2682..d9cebc9 100644 +--- a/MagickCore/delegate.c ++++ b/MagickCore/delegate.c +@@ -1627,6 +1627,9 @@ static MagickBooleanType CopyDelegateFile(const char *source, + const char *destination,const MagickBooleanType overwrite, + ExceptionInfo *exception) + { ++ char ++ filename[MagickPathExtent]; ++ + int + destination_file, + source_file; +@@ -1659,11 +1662,14 @@ static MagickBooleanType CopyDelegateFile(const char *source, + if (status != MagickFalse) + return(MagickTrue); + } +- if (IsPathAuthorized(WritePolicyRights,destination) == MagickFalse) +- ThrowPolicyException(destination,MagickFalse); +- destination_file=open_utf8(destination,O_WRONLY | O_BINARY | O_CREAT,S_MODE); ++ destination_file=AcquireUniqueFileResource(filename); + if (destination_file == -1) + return(MagickFalse); ++ if (IsPathAuthorized(ReadPolicyRights,source) == MagickFalse) ++ { ++ (void) close_utf8(destination_file); ++ ThrowPolicyException(source,MagickFalse); ++ } + source_file=open_utf8(source,O_RDONLY | O_BINARY,0); + if (source_file == -1) + { +@@ -1694,6 +1700,10 @@ static MagickBooleanType CopyDelegateFile(const char *source, + (void) close_utf8(destination_file); + (void) close_utf8(source_file); + buffer=(unsigned char *) RelinquishMagickMemory(buffer); ++ if (IsPathAuthorized(WritePolicyRights,destination) == MagickFalse) ++ ThrowPolicyException(destination,MagickFalse); ++ if (rename_utf8(filename,destination) != 0) ++ return(MagickFalse); + return(i != 0 ? MagickTrue : MagickFalse); + } + +@@ -1864,13 +1874,6 @@ MagickExport MagickBooleanType InvokeDelegate(ImageInfo *image_info, + (void) CopyMagickString(input_filename,image->filename,MagickPathExtent); + for (i=0; commands[i] != (char *) NULL; i++) + { +- if (IsPathAuthorized(WritePolicyRights,output_filename) == MagickFalse) +- { +- errno=EPERM; +- (void) ThrowMagickException(exception,GetMagickModule(),PolicyError, \ +- "NotAuthorized","`%s'",output_filename); +- break; +- } + (void) AcquireUniqueSymbolicLink(output_filename,image_info->filename); + if (AcquireUniqueFilename(image_info->unique) == MagickFalse) + { +@@ -1895,8 +1898,7 @@ MagickExport MagickBooleanType InvokeDelegate(ImageInfo *image_info, + /* + Execute delegate. + */ +- if (ExternalDelegateCommand(delegate_info->spawn,image_info->verbose, +- command,(char *) NULL,exception) != 0) ++ if (ExternalDelegateCommand(delegate_info->spawn,image_info->verbose,command,(char *) NULL,exception) != 0) + status=MagickFalse; + if (delegate_info->spawn != MagickFalse) + { +@@ -1915,11 +1917,17 @@ MagickExport MagickBooleanType InvokeDelegate(ImageInfo *image_info, + if (LocaleCompare(decode,"SCAN") != 0) + { + if (CopyDelegateFile(image->filename,input_filename,MagickFalse,exception) == MagickFalse) +- (void) RelinquishUniqueFileResource(input_filename); ++ { ++ (void) RelinquishUniqueFileResource(input_filename); ++ status=MagickFalse; ++ } + } + if ((strcmp(input_filename,output_filename) != 0) && + (CopyDelegateFile(image_info->filename,output_filename,MagickTrue,exception) == MagickFalse)) +- (void) RelinquishUniqueFileResource(output_filename); ++ { ++ (void) RelinquishUniqueFileResource(output_filename); ++ status=MagickFalse; ++ } + if (image_info->temporary != MagickFalse) + (void) RelinquishUniqueFileResource(image_info->filename); + (void) RelinquishUniqueFileResource(image_info->unique); +diff --git a/MagickCore/policy.c b/MagickCore/policy.c +index 0a5224c..a0745b1 100644 +--- a/MagickCore/policy.c ++++ b/MagickCore/policy.c +@@ -687,9 +687,9 @@ MagickExport MagickBooleanType IsPathAuthorized(const PolicyRights rights, + MagickBooleanType symlink_follow_allowed = IsRightsAuthorizedByName( + SystemPolicyDomain,"symlink",rights,"follow"); + MagickBooleanType status = +- ((IsRightsAuthorized(PathPolicyDomain,rights,path) != MagickFalse) && +- ((symlink_follow_allowed != MagickFalse) || +- (is_symlink_utf8(path) == MagickFalse))) ? MagickTrue : MagickFalse; ++ ((IsRightsAuthorized(PathPolicyDomain,rights,path) != MagickFalse) && ++ ((symlink_follow_allowed != MagickFalse) || ++ (is_symlink_utf8(path) == MagickFalse))) ? MagickTrue : MagickFalse; + if ((status != MagickFalse) && (symlink_follow_allowed == MagickFalse)) + { + if ((is_symlink_utf8(path) != MagickFalse) || diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre1.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre1.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre1.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre1.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,29 @@ +From: Cristy +Date: Sun, 14 Jun 2026 07:00:41 -0400 +Subject: export IsRightsAuthorizedByName() + +(cherry picked from commit 6c64b58815de0b18608214981bd94d1db16f0ec8) + +origin: https://github.com/ImageMagick/ImageMagick/commit/6c64b58815de0b18608214981bd94d1db16f0ec8 +--- + MagickCore/policy-private.h | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/MagickCore/policy-private.h b/MagickCore/policy-private.h +index 27e1dc4..901ad41 100644 +--- a/MagickCore/policy-private.h ++++ b/MagickCore/policy-private.h +@@ -35,9 +35,11 @@ static const char + "; + #endif + +-extern MagickPrivate MagickBooleanType ++extern MagickExport MagickBooleanType + IsRightsAuthorizedByName(const PolicyDomain,const char *,const PolicyRights, +- const char *), ++ const char *); ++ ++extern MagickPrivate MagickBooleanType + PolicyComponentGenesis(void); + + extern MagickPrivate void diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre2.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre2.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre2.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre2.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,487 @@ +From: Cristy +Date: Sun, 5 Jul 2026 15:57:00 -0400 +Subject: address remote TOCTOU issues + +[backport] +- drop unrelated compare change (format change) + +(cherry picked from commit 99d821db45ed03afc80925ce11eff62abe80484a) +origin: backport, https://github.com/ImageMagick/ImageMagick/commit/99d821db45ed03afc80925ce11eff62abe80484a +--- + MagickCore/policy-private.h | 94 +++++++++++++++++++++++++++++++++++++++++++- + MagickCore/policy.c | 39 ++++++++++++++++-- + MagickCore/utility-private.h | 43 ++++++++++++++++++++ + coders/mat.c | 9 +++-- + coders/ora.c | 9 +++-- + coders/pwp.c | 6 ++- + coders/sfw.c | 5 ++- + coders/svg.c | 11 ++++-- + coders/wmf.c | 6 ++- + 9 files changed, 203 insertions(+), 19 deletions(-) + +diff --git a/MagickCore/policy-private.h b/MagickCore/policy-private.h +index 901ad41..9d01e0f 100644 +--- a/MagickCore/policy-private.h ++++ b/MagickCore/policy-private.h +@@ -45,13 +45,105 @@ extern MagickPrivate MagickBooleanType + extern MagickPrivate void + PolicyComponentTerminus(void); + ++static inline MagickBooleanType IsPathContainsSymlink(const char *path) ++{ ++ char ++ partial[MagickPathExtent]; ++ ++ const char ++ *p; ++ ++ ssize_t ++ offset = 0; ++ ++ if (path == (const char *) NULL) ++ return(MagickFalse); ++ *partial='\0'; ++ p=path; ++ if (*p == *DirectorySeparator) ++ { ++ /* ++ Path starts with a directory separator, include it. ++ */ ++ if ((offset+1) >= (ssize_t) sizeof(partial)) ++ return(MagickFalse); ++ partial[offset++]=(*p++); ++ partial[offset]='\0'; ++ } ++ while (*p != '\0') ++ { ++ char ++ component[MagickPathExtent]; ++ ++ ssize_t ++ i = 0; ++ ++ /* ++ Copy next component into a temporary buffer. ++ */ ++ while ((*p != '\0') && (*p != *DirectorySeparator) && ++ ((i+1) < (ssize_t) sizeof(component))) ++ component[i++]=(*p++); ++ component[i]='\0'; ++ if (i == 0) ++ { ++ /* ++ skip repeated separators. ++ */ ++ if (*p == *DirectorySeparator) ++ p++; ++ continue; ++ } ++ if ((offset > 0) && (partial[offset-1] != *DirectorySeparator)) ++ { ++ /* ++ Append separator if needed. ++ */ ++ if ((offset+1) >= (ssize_t) sizeof(partial)) ++ return MagickFalse; ++ partial[offset++]=(*DirectorySeparator); ++ partial[offset]='\0'; ++ } ++ /* ++ Append component. ++ */ ++ if ((offset+i) >= (ssize_t) sizeof(partial)) ++ return(MagickFalse); ++ (void) memcpy(partial+offset,component,i); ++ offset+=i; ++ partial[offset]='\0'; ++ if (*p != '\0') ++ { ++ /* ++ Check whether this prefix is a symlink. ++ */ ++ if (is_symlink_utf8(partial) != MagickFalse) ++ return(MagickTrue); ++ } ++ /* ++ Skip separator. ++ */ ++ if (*p == *DirectorySeparator) ++ p++; ++ } ++ return(MagickFalse); ++} ++ + static inline MagickBooleanType IsPathAuthorized(const PolicyRights rights, + const char *filename) + { ++ MagickBooleanType symlink_follow_allowed = IsRightsAuthorizedByName( ++ SystemPolicyDomain,"symlink",rights,"follow"); + MagickBooleanType status = + ((IsRightsAuthorized(PathPolicyDomain,rights,filename) != MagickFalse) && +- ((IsRightsAuthorizedByName(SystemPolicyDomain,"symlink",rights,"follow") != MagickFalse) || ++ ((symlink_follow_allowed != MagickFalse) || + (is_symlink_utf8(filename) == MagickFalse))) ? MagickTrue : MagickFalse; ++ if ((status != MagickFalse) && (symlink_follow_allowed == MagickFalse)) ++ { ++ if ((is_symlink_utf8(filename) != MagickFalse) || ++ (IsPathContainsSymlink(filename) != MagickFalse)) ++ status=MagickFalse; ++ } + return(status); + } + +diff --git a/MagickCore/policy.c b/MagickCore/policy.c +index 5855579..282b053 100644 +--- a/MagickCore/policy.c ++++ b/MagickCore/policy.c +@@ -661,12 +661,14 @@ MagickExport MagickBooleanType IsRightsAuthorizedByName( + *exception; + + MagickBooleanType ++ canonical_matched_any = MagickFalse, + matched_any = MagickFalse, + paths_provisioned = MagickFalse, + status; + + PolicyRights +- effective_rights = AllPolicyRights; /* rights authorized unless denied */ ++ canonical_allowed_accumulator = AllPolicyRights, ++ effective_rights = AllPolicyRights; + + /* + Load policies. +@@ -689,7 +691,8 @@ MagickExport MagickBooleanType IsRightsAuthorizedByName( + return(MagickTrue); + } + /* +- Evaluate policies in order; last match wins. ++ Evaluate policies in order; last match wins, however, canonical denies are ++ enforced after evaluation. + */ + LockSemaphoreInfo(policy_semaphore); + ResetLinkedListIterator(policy_cache); +@@ -700,7 +703,8 @@ MagickExport MagickBooleanType IsRightsAuthorizedByName( + *policy = (PolicyInfo *) p->value; + + MagickBooleanType +- match = MagickFalse; ++ match = MagickFalse, ++ matched_canonical = MagickFalse; + + if (policy->domain != domain) + continue; +@@ -741,11 +745,30 @@ MagickExport MagickBooleanType IsRightsAuthorizedByName( + match=GlobExpression(canonical_candidate,policy->pattern,MagickFalse); + if ((canonical_path != (char *) NULL) && (match == MagickFalse)) + match=GlobExpression(canonical_path,policy->pattern,MagickFalse); ++ if ((canonical_path != (char *) NULL) && ++ (GlobExpression(canonical_path,policy->pattern,MagickFalse) != MagickFalse)) ++ matched_canonical=MagickTrue; ++ else ++ if ((canonical_candidate != (char *) NULL) && ++ (GlobExpression(canonical_candidate,policy->pattern,MagickFalse) != MagickFalse)) ++ matched_canonical=MagickTrue; ++ else ++ if ((canonical_directory != (char *) NULL) && ++ (GlobExpression(canonical_directory,policy->pattern,MagickFalse) != MagickFalse)) ++ matched_canonical=MagickTrue; + } + if (match == MagickFalse) + continue; + matched_any=MagickTrue; + effective_rights=policy->rights; ++ if (matched_canonical != MagickFalse) ++ { ++ /* ++ If this match was against a canonical form, accumulate allowed rights. ++ */ ++ canonical_matched_any=MagickTrue; ++ canonical_allowed_accumulator&=policy->rights; ++ } + } + UnlockSemaphoreInfo(policy_semaphore); + if (canonical_directory != (char *) NULL) +@@ -770,6 +793,16 @@ MagickExport MagickBooleanType IsRightsAuthorizedByName( + ((effective_rights & ExecutePolicyRights) == 0)) + status=MagickFalse; + } ++ /* ++ Enforce sticky canonical denies. ++ */ ++ if (canonical_matched_any != MagickFalse) ++ { ++ PolicyRights canonical_denied_mask = (AllPolicyRights & ++ ~canonical_allowed_accumulator); ++ if ((canonical_denied_mask & rights) != 0) ++ status=MagickFalse; ++ } + if ((GetLogEventMask() & PolicyEvent) != 0) + (void) LogMagickEvent(PolicyEvent,GetMagickModule(), + " authorized: %s",status == MagickFalse ? "false" : "true"); +diff --git a/MagickCore/utility-private.h b/MagickCore/utility-private.h +index ab6bf6e..3ae2a37 100644 +--- a/MagickCore/utility-private.h ++++ b/MagickCore/utility-private.h +@@ -44,6 +44,49 @@ extern MagickPrivate void + ChopPathComponents(char *,const size_t), + ExpandFilename(char *); + ++static inline MagickBooleanType GetPathSignature(int file,char signature[33]) ++{ ++ char ++ *p = signature; ++ ++ ssize_t ++ i; ++ ++ static const char ++ hex[] = "0123456789abcdef"; ++ ++ uint64_t ++ file_identity[2]; ++ ++#if defined(MAGICKCORE_WINDOWS_SUPPORT) ++ BY_HANDLE_FILE_INFORMATION file_info; ++ HANDLE handle = (HANDLE) _get_osfhandle(file); ++ if (handle == INVALID_HANDLE_VALUE) ++ return(MagickFalse); ++ if (GetFileInformationByHandle(handle,&file_info) == 0) ++ return(MagickFalse); ++ file_identity[0]=(uint64_t) file_info.dwVolumeSerialNumber; ++ file_identity[1]=((uint64_t) file_info.nFileIndexHigh << 32) | ++ (uint64_t) file_info.nFileIndexLow; ++#else ++ struct stat file_attributes; ++ if (fstat(file, &file_attributes) != 0) ++ return(MagickFalse); ++ file_identity[0]=(uint64_t) file_attributes.st_dev; ++ file_identity[1]=(uint64_t) file_attributes.st_ino; ++#endif ++ for (i=0; i < 2; i++) ++ { ++ ssize_t ++ shift; ++ ++ for (shift=60; shift >= 0; shift-=4) ++ *p++=hex[(file_identity[i] >> shift) & 0xF]; ++ } ++ *p='\0'; ++ return(MagickTrue); ++} ++ + static inline int MagickReadDirectory(DIR *directory,struct dirent *entry, + struct dirent **result) + { +diff --git a/coders/mat.c b/coders/mat.c +index fdbfb23..19f48ee 100644 +--- a/coders/mat.c ++++ b/coders/mat.c +@@ -519,7 +519,7 @@ ssize_t TotalSize = 0; + mat_file=0; + file = AcquireUniqueFileResource(clone_info->filename); + if (file != -1) +- mat_file = fdopen(file,"w"); ++ mat_file = fdopen(file,"ab+"); + if(!mat_file) + { + RelinquishMagickMemory(cache_block); +@@ -576,12 +576,14 @@ ssize_t TotalSize = 0; + DblBreak: + + inflateEnd(&zip_info); +- (void)fclose(mat_file); ++ if (fseek(mat_file,0,SEEK_SET) != 0) ++ (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError, ++ "UnableToCreateTemporaryFile","`%s'",clone_info->filename); + RelinquishMagickMemory(cache_block); + RelinquishMagickMemory(decompress_block); + *Size = TotalSize; + +- if((clone_info->file=fopen(clone_info->filename,"rb"))==NULL) goto UnlinkFile; ++ clone_info->file=mat_file; + if( (image2 = AcquireImage(clone_info,exception))==NULL ) goto EraseFile; + image2->columns=0; + image2->rows=0; +@@ -592,7 +594,6 @@ DblBreak: + EraseFile: + fclose(clone_info->file); + clone_info->file = NULL; +-UnlinkFile: + RelinquishUniqueFileResource(clone_info->filename); + return NULL; + } +diff --git a/coders/ora.c b/coders/ora.c +index 42a9dbf..d2c6789 100644 +--- a/coders/ora.c ++++ b/coders/ora.c +@@ -173,7 +173,7 @@ static Image *ReadORAImage(const ImageInfo *image_info, + MagickPathExtent); + file=(FILE *) NULL; + if (unique_file != -1) +- file=fdopen(unique_file,"wb"); ++ file=fdopen(unique_file,"rb+"); + if ((unique_file == -1) || (file == (FILE *) NULL)) + { + ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile", +@@ -213,19 +213,22 @@ static Image *ReadORAImage(const ImageInfo *image_info, + else + offset+=(zip_uint64_t) read_bytes; + } +- (void) fclose(file); ++ if (fseek(file,0,SEEK_SET) != 0) ++ status=MagickFalse; + (void) zip_fclose(merged_image_file); + (void) zip_discard(zip_archive); + if (status == MagickFalse) + { + ThrowFileException(exception,CoderError,"UnableToReadImageData", +- read_info->filename); ++ read_info->filename); + (void) RelinquishUniqueFileResource(read_info->filename); ++ (void) fclose(file); + read_info=DestroyImageInfo(read_info); + image_metadata=DestroyImage(image_metadata); + return((Image *) NULL); + } + /* Delegate to ReadImage to read mergedimage.png */ ++ read_info->file=file; + out_image=ReadImage(read_info,exception); + (void) RelinquishUniqueFileResource(read_info->filename); + read_info=DestroyImageInfo(read_info); +diff --git a/coders/pwp.c b/coders/pwp.c +index 00bd812..ba06e38 100644 +--- a/coders/pwp.c ++++ b/coders/pwp.c +@@ -216,7 +216,7 @@ static Image *ReadPWPImage(const ImageInfo *image_info,ExceptionInfo *exception) + */ + file=(FILE *) NULL; + if (unique_file != -1) +- file=fdopen(unique_file,"wb"); ++ file=fdopen(unique_file,"rb+"); + if ((unique_file == -1) || (file == (FILE *) NULL)) + { + (void) RelinquishUniqueFileResource(filename); +@@ -237,13 +237,15 @@ static Image *ReadPWPImage(const ImageInfo *image_info,ExceptionInfo *exception) + if (fputc(c,file) != c) + break; + } +- (void) fclose(file); ++ if (fseek(file,0,SEEK_SET) != 0) ++ ThrowReaderException(FileOpenError,"UnableToCreateTemporaryFile"); + if (c == EOF) + { + (void) RelinquishUniqueFileResource(filename); + read_info=DestroyImageInfo(read_info); + ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile"); + } ++ read_info->file=file; + next_image=ReadImage(read_info,exception); + if (next_image == (Image *) NULL) + break; +diff --git a/coders/sfw.c b/coders/sfw.c +index 6efc0c8..d95e76d 100644 +--- a/coders/sfw.c ++++ b/coders/sfw.c +@@ -330,7 +330,8 @@ static Image *ReadSFWImage(const ImageInfo *image_info,ExceptionInfo *exception) + extent=fwrite(HuffmanTable,1,sizeof(HuffmanTable)/sizeof(*HuffmanTable),file); + extent=fwrite(offset+1,1,(size_t) (data-offset),file); + status=ferror(file) != 0 ? MagickFalse : MagickTrue; +- (void) fclose(file); ++ if (fseek(file,0,SEEK_SET) != 0) ++ ThrowReaderException(FileOpenError,"UnableToCreateTemporaryFile"); + (void) close_utf8(unique_file); + buffer=(unsigned char *) RelinquishMagickMemory(buffer); + if (status == MagickFalse) +@@ -338,6 +339,7 @@ static Image *ReadSFWImage(const ImageInfo *image_info,ExceptionInfo *exception) + char + *message; + ++ (void) fclose(file); + (void) remove_utf8(read_info->filename); + read_info=DestroyImageInfo(read_info); + message=GetExceptionMessage(errno); +@@ -351,6 +353,7 @@ static Image *ReadSFWImage(const ImageInfo *image_info,ExceptionInfo *exception) + Read JPEG image. + */ + (void) CopyMagickString(read_info->magick,"JPEG",MagickPathExtent); ++ read_info->file=file; + jpeg_image=ReadImage(read_info,exception); + (void) RelinquishUniqueFileResource(read_info->filename); + read_info=DestroyImageInfo(read_info); +diff --git a/coders/svg.c b/coders/svg.c +index d4b17d1..d74ef6b 100644 +--- a/coders/svg.c ++++ b/coders/svg.c +@@ -3128,7 +3128,7 @@ static Image *RenderMSVGImage(const ImageInfo *image_info,Image *image, + file=(FILE *) NULL; + unique_file=AcquireUniqueFileResource(filename); + if (unique_file != -1) +- file=fdopen(unique_file,"w"); ++ file=fdopen(unique_file,"rb+"); + if ((unique_file == -1) || (file == (FILE *) NULL)) + { + (void) CopyMagickString(image->filename,filename,MagickPathExtent); +@@ -3220,7 +3220,8 @@ static Image *RenderMSVGImage(const ImageInfo *image_info,Image *image, + xmlFreeParserCtxt(parser); + if (image->debug != MagickFalse) + (void) LogMagickEvent(CoderEvent,GetMagickModule(),"end SAX"); +- (void) fclose(file); ++ if (fseek(file,0,SEEK_SET) != 0) ++ ThrowReaderException(FileOpenError,"UnableToCreateTemporaryFile"); + (void) CloseBlob(image); + image->columns=svg_info->width; + image->rows=svg_info->height; +@@ -3228,10 +3229,13 @@ static Image *RenderMSVGImage(const ImageInfo *image_info,Image *image, + { + svg_info=DestroySVGInfo(svg_info); + (void) RelinquishUniqueFileResource(filename); ++ (void) fclose(file); + image=DestroyImage(image); + return((Image *) NULL); + } +- if (image_info->ping == MagickFalse) ++ if (image_info->ping != MagickFalse) ++ (void) fclose(file); ++ else + { + ImageInfo + *read_info; +@@ -3243,6 +3247,7 @@ static Image *RenderMSVGImage(const ImageInfo *image_info,Image *image, + image=(Image *) NULL; + read_info=CloneImageInfo(image_info); + SetImageInfoBlob(read_info,(void *) NULL,0); ++ read_info->file=file; + (void) FormatLocaleString(read_info->filename,MagickPathExtent,"mvg:%s", + filename); + image=ReadImage(read_info,exception); +diff --git a/coders/wmf.c b/coders/wmf.c +index 5610bcf..eb6febf 100644 +--- a/coders/wmf.c ++++ b/coders/wmf.c +@@ -197,7 +197,7 @@ static Image *ReadWMFImage(const ImageInfo *image_info,ExceptionInfo *exception) + file=(FILE *) NULL; + unique_file=AcquireUniqueFileResource(filename); + if (unique_file != -1) +- file=fdopen(unique_file,"wb"); ++ file=fdopen(unique_file,"rb+"); + if ((unique_file == -1) || (file == (FILE *) NULL)) + { + ipa_device_close(wmf_info); +@@ -213,7 +213,8 @@ static Image *ReadWMFImage(const ImageInfo *image_info,ExceptionInfo *exception) + wmf_api_destroy(wmf_info); + ThrowReaderException(DelegateError,"FailedToRenderFile"); + } +- (void) fclose(file); ++ if (fseek(file,0,SEEK_SET) != 0) ++ ThrowImageException(FileOpenError,"UnableToCreateTemporaryFile"); + wmf_api_destroy(wmf_info); + (void) CloseBlob(image); + image=DestroyImage(image); +@@ -221,6 +222,7 @@ static Image *ReadWMFImage(const ImageInfo *image_info,ExceptionInfo *exception) + Read EPS image. + */ + read_info=CloneImageInfo(image_info); ++ read_info->file=file; + SetImageInfoBlob(read_info,(void *) NULL,0); + (void) FormatLocaleString(read_info->filename,MagickPathExtent,"eps:%s", + filename); diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre3.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre3.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre3.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre3.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,385 @@ +From: Cristy +Date: Wed, 8 Jul 2026 20:22:02 -0400 +Subject: ensure file resource identify is valid + +origin: backport, https://github.com/ImageMagick/ImageMagick/commit/bbbf79e33935be36890707a49103b0e66698b82 +--- + MagickCore/policy-private.h | 13 ++-- + MagickCore/resource-private.h | 3 + + MagickCore/resource.c | 135 ++++++++++++++++-------------------------- + MagickCore/resource_.h | 1 - + MagickCore/utility-private.h | 2 + + MagickCore/utility.c | 108 +++++++++++++++++++++++++++++++++ + MagickCore/utility.h | 1 + + 7 files changed, 173 insertions(+), 90 deletions(-) + +diff --git a/MagickCore/policy-private.h b/MagickCore/policy-private.h +index 9d01e0f..d262879 100644 +--- a/MagickCore/policy-private.h ++++ b/MagickCore/policy-private.h +@@ -22,6 +22,7 @@ + extern "C" { + #endif + ++#include "MagickCore/resource-private.h" + #include "MagickCore/utility-private.h" + + #if MAGICKCORE_ZERO_CONFIGURATION_SUPPORT +@@ -130,20 +131,22 @@ static inline MagickBooleanType IsPathContainsSymlink(const char *path) + } + + static inline MagickBooleanType IsPathAuthorized(const PolicyRights rights, +- const char *filename) ++ const char *path) + { + MagickBooleanType symlink_follow_allowed = IsRightsAuthorizedByName( + SystemPolicyDomain,"symlink",rights,"follow"); + MagickBooleanType status = +- ((IsRightsAuthorized(PathPolicyDomain,rights,filename) != MagickFalse) && ++ ((IsRightsAuthorized(PathPolicyDomain,rights,path) != MagickFalse) && + ((symlink_follow_allowed != MagickFalse) || +- (is_symlink_utf8(filename) == MagickFalse))) ? MagickTrue : MagickFalse; ++ (is_symlink_utf8(path) == MagickFalse))) ? MagickTrue : MagickFalse; + if ((status != MagickFalse) && (symlink_follow_allowed == MagickFalse)) + { +- if ((is_symlink_utf8(filename) != MagickFalse) || +- (IsPathContainsSymlink(filename) != MagickFalse)) ++ if ((is_symlink_utf8(path) != MagickFalse) || ++ (IsPathContainsSymlink(path) != MagickFalse)) + status=MagickFalse; + } ++ if (status != MagickFalse) ++ status=IsFileResourceIdentityValid(path); + return(status); + } + +diff --git a/MagickCore/resource-private.h b/MagickCore/resource-private.h +index b568462..ee7d6ae 100644 +--- a/MagickCore/resource-private.h ++++ b/MagickCore/resource-private.h +@@ -26,6 +26,9 @@ extern "C" { + # define MagickFormatExtent 64 + #endif + ++extern MagickExport MagickBooleanType ++ IsFileResourceIdentityValid(const char *); ++ + extern MagickPrivate MagickBooleanType + ResourceComponentGenesis(void); + +diff --git a/MagickCore/resource.c b/MagickCore/resource.c +index 148ee56..05ce5eb 100644 +--- a/MagickCore/resource.c ++++ b/MagickCore/resource.c +@@ -70,7 +70,6 @@ + /* + Define declarations. + */ +-#define MagickPathTemplate "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" /* min 6 X's */ + #define NumberOfResourceTypes \ + (sizeof(resource_semaphore)/sizeof(*resource_semaphore)) + +@@ -461,89 +460,6 @@ static void *DestroyTemporaryResources(void *temporary_resource) + return((void *) NULL); + } + +-MagickExport MagickBooleanType GetPathTemplate(char *path) +-{ +- char +- *directory, +- *value; +- +- ExceptionInfo +- *exception; +- +- MagickBooleanType +- status; +- +- struct stat +- attributes; +- +- (void) FormatLocaleString(path,MagickPathExtent,"magick-" MagickPathTemplate); +- exception=AcquireExceptionInfo(); +- directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path", +- exception); +- exception=DestroyExceptionInfo(exception); +- if (directory == (char *) NULL) +- directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH"); +- if (directory == (char *) NULL) +- directory=GetEnvironmentValue("MAGICK_TMPDIR"); +- if (directory == (char *) NULL) +- directory=GetEnvironmentValue("TMPDIR"); +-#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__) || defined(__CYGWIN__) +- if (directory == (char *) NULL) +- directory=GetEnvironmentValue("TMP"); +- if (directory == (char *) NULL) +- directory=GetEnvironmentValue("TEMP"); +-#endif +-#if defined(__VMS) +- if (directory == (char *) NULL) +- directory=GetEnvironmentValue("MTMPDIR"); +-#endif +-#if defined(P_tmpdir) +- if (directory == (char *) NULL) +- directory=ConstantString(P_tmpdir); +-#endif +- if (directory == (char *) NULL) +- return(MagickTrue); +- value=GetPolicyValue("resource:temporary-path"); +- if (value != (char *) NULL) +- { +- (void) CloneString(&directory,value); +- value=DestroyString(value); +- } +- if (strlen(directory) > (MagickPathExtent-25)) +- { +- directory=DestroyString(directory); +- return(MagickFalse); +- } +- status=GetPathAttributes(directory,&attributes); +- if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode)) +- { +- directory=DestroyString(directory); +- return(MagickFalse); +- } +- if (directory[strlen(directory)-1] == *DirectorySeparator) +- (void) FormatLocaleString(path,MagickPathExtent,"%smagick-" +- MagickPathTemplate,directory); +- else +- (void) FormatLocaleString(path,MagickPathExtent, +- "%s%smagick-" MagickPathTemplate,directory,DirectorySeparator); +- directory=DestroyString(directory); +-#if defined(MAGICKCORE_WINDOWS_SUPPORT) +- { +- char +- *p; +- +- /* +- Ghostscript does not like backslashes so we need to replace them. The +- forward slash also works under Windows. +- */ +- for (p=(path[1] == *DirectorySeparator ? path+2 : path); *p != '\0'; p++) +- if (*p == *DirectorySeparator) +- *p='/'; +- } +-#endif +- return(MagickTrue); +-} +- + MagickExport int AcquireUniqueFileResource(char *path) + { + #if !defined(O_NOFOLLOW) +@@ -771,6 +687,57 @@ MagickExport MagickSizeType GetMagickResource(const ResourceType type) + % % + % % + % % ++% I s F i l e R e s o u r c e I d e n t i t y V a l i d % ++% % ++% % ++% % ++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ++% ++% IsFileResourceIdentityValid() returns MagickTrue if the file resource ++% identity is valid. ++% ++% The format of the IsFileResourceIdentityValid() method is: ++% ++% MagickBooleanType IsFileResourceIdentityValid(const char *path) ++% ++% A description of each parameter follows: ++% ++% o path: the file resource path. ++% ++*/ ++MagickExport MagickBooleanType IsFileResourceIdentityValid(const char *path) ++{ ++ const struct stat ++ *temporary_attributes; ++ ++ MagickBooleanType ++ status = MagickTrue; ++ ++ struct stat ++ attributes; ++ ++ if (temporary_resources == (SplayTreeInfo *) NULL) ++ return(MagickTrue); ++ LockSemaphoreInfo(resource_semaphore[FileResource]); ++ temporary_attributes=(const struct stat *) GetValueFromSplayTree( ++ temporary_resources,(const void *) path); ++ if (temporary_attributes != (const struct stat *) NULL) ++ { ++ status=GetPathAttributes(path,&attributes); ++ if (status != MagickFalse) ++ if ((attributes.st_dev != temporary_attributes->st_dev) || ++ (attributes.st_ino != temporary_attributes->st_ino)) ++ status=MagickFalse; ++ } ++ UnlockSemaphoreInfo(resource_semaphore[FileResource]); ++ return(status); ++} ++ ++/* ++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ++% % ++% % ++% % + % G e t M a g i c k R e s o u r c e L i m i t % + % % + % % +diff --git a/MagickCore/resource_.h b/MagickCore/resource_.h +index bb058ed..ffe0891 100644 +--- a/MagickCore/resource_.h ++++ b/MagickCore/resource_.h +@@ -45,7 +45,6 @@ extern MagickExport int + + extern MagickExport MagickBooleanType + AcquireMagickResource(const ResourceType,const MagickSizeType), +- GetPathTemplate(char *), + ListMagickResourceInfo(FILE *,ExceptionInfo *), + RelinquishUniqueFileResource(const char *), + SetMagickResourceLimit(const ResourceType,const MagickSizeType); +diff --git a/MagickCore/utility-private.h b/MagickCore/utility-private.h +index 3ae2a37..ea809c7 100644 +--- a/MagickCore/utility-private.h ++++ b/MagickCore/utility-private.h +@@ -29,6 +29,8 @@ + extern "C" { + #endif + ++#define MagickPathTemplate "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" /* min 6 X's */ ++ + extern MagickPrivate char + **GetPathComponents(const char *,size_t *), + **ListFiles(const char *,const char *,size_t *); +diff --git a/MagickCore/utility.c b/MagickCore/utility.c +index 64fad00..addb979 100644 +--- a/MagickCore/utility.c ++++ b/MagickCore/utility.c +@@ -1497,6 +1497,114 @@ MagickPrivate char **GetPathComponents(const char *path, + % % + % % + % % ++% G e t P a t h T e m p l a t e % ++% % ++% % ++% % ++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ++% ++% GetPathTemplate() constructs a template for a temporary filename. ++% ++% The format of the GetPathComponent function is: ++% ++% MagickBooleanType GetPathComponent(const char *path) ++% ++% A description of each parameter follows: ++% ++% o path: Specifies a pointer to a character array populated with the ++% file path template. ++% ++% ++*/ ++MagickExport MagickBooleanType GetPathTemplate(char *path) ++{ ++ char ++ *directory, ++ *value; ++ ++ ExceptionInfo ++ *exception; ++ ++ MagickBooleanType ++ status; ++ ++ struct stat ++ attributes; ++ ++ (void) FormatLocaleString(path,MagickPathExtent,"magick-" ++ MagickPathTemplate); ++ exception=AcquireExceptionInfo(); ++ directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path", ++ exception); ++ exception=DestroyExceptionInfo(exception); ++ if (directory == (char *) NULL) ++ directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH"); ++ if (directory == (char *) NULL) ++ directory=GetEnvironmentValue("MAGICK_TMPDIR"); ++ if (directory == (char *) NULL) ++ directory=GetEnvironmentValue("TMPDIR"); ++#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__) || defined(__CYGWIN__) ++ if (directory == (char *) NULL) ++ directory=GetEnvironmentValue("TMP"); ++ if (directory == (char *) NULL) ++ directory=GetEnvironmentValue("TEMP"); ++#endif ++#if defined(__VMS) ++ if (directory == (char *) NULL) ++ directory=GetEnvironmentValue("MTMPDIR"); ++#endif ++#if defined(P_tmpdir) ++ if (directory == (char *) NULL) ++ directory=ConstantString(P_tmpdir); ++#endif ++ if (directory == (char *) NULL) ++ return(MagickFalse); ++ value=GetPolicyValue("resource:temporary-path"); ++ if (value != (char *) NULL) ++ { ++ (void) CloneString(&directory,value); ++ value=DestroyString(value); ++ } ++ if (strlen(directory) > (MagickPathExtent-25)) ++ { ++ directory=DestroyString(directory); ++ return(MagickFalse); ++ } ++ status=GetPathAttributes(directory,&attributes); ++ if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode)) ++ { ++ directory=DestroyString(directory); ++ return(MagickFalse); ++ } ++ if (directory[strlen(directory)-1] == *DirectorySeparator) ++ (void) FormatLocaleString(path,MagickPathExtent,"%smagick-" ++ MagickPathTemplate,directory); ++ else ++ (void) FormatLocaleString(path,MagickPathExtent, ++ "%s%smagick-" MagickPathTemplate,directory,DirectorySeparator); ++ directory=DestroyString(directory); ++#if defined(MAGICKCORE_WINDOWS_SUPPORT) ++ { ++ char ++ *p; ++ ++ /* ++ Ghostscript does not like backslashes so we need to replace them. The ++ forward slash also works under Windows. ++ */ ++ for (p=(path[1] == *DirectorySeparator ? path+2 : path); *p != '\0'; p++) ++ if (*p == *DirectorySeparator) ++ *p='/'; ++ } ++#endif ++ return(MagickTrue); ++} ++ ++/* ++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ++% % ++% % ++% % + % I s P a t h A c c e s s i b l e % + % % + % % +diff --git a/MagickCore/utility.h b/MagickCore/utility.h +index ac8afc8..a4d962d 100644 +--- a/MagickCore/utility.h ++++ b/MagickCore/utility.h +@@ -45,6 +45,7 @@ extern MagickExport MagickBooleanType + AcquireUniqueSymbolicLink(const char *,char *), + ExpandFilenames(int *,char ***), + GetPathAttributes(const char *,void *), ++ GetPathTemplate(char *), + IsPathAccessible(const char *); + + extern MagickExport size_t diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre4.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre4.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre4.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre4.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,26 @@ +From: Cristy +Date: Sat, 11 Jul 2026 09:54:37 -0400 +Subject: include file mode when validating file identity + +[backport] +- drop nt-base change not compiled on debian + +origin: backport, https://github.com/ImageMagick/ImageMagick/commit/c081559f9bf32c2613c2b46e2f469593a12dab26 +--- + MagickCore/resource.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/MagickCore/resource.c b/MagickCore/resource.c +index 05ce5eb..47e1a1e 100644 +--- a/MagickCore/resource.c ++++ b/MagickCore/resource.c +@@ -726,7 +726,8 @@ MagickExport MagickBooleanType IsFileResourceIdentityValid(const char *path) + status=GetPathAttributes(path,&attributes); + if (status != MagickFalse) + if ((attributes.st_dev != temporary_attributes->st_dev) || +- (attributes.st_ino != temporary_attributes->st_ino)) ++ (attributes.st_ino != temporary_attributes->st_ino) || ++ (attributes.st_mode != temporary_attributes->st_mode)) + status=MagickFalse; + } + UnlockSemaphoreInfo(resource_semaphore[FileResource]); diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre5.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre5.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre5.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre5.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,278 @@ +From: Dirk Lemstra +Date: Thu, 16 Jul 2026 14:48:21 +0200 +Subject: No longer inline the method to reduce the local stack size. + +(cherry picked from commit d53e028a3d4e01705c36d2ebaf14e095488ebaa6) + +origin: https://github.com/ImageMagick/ImageMagick/commit/d53e028a3d4e01705c36d2ebaf14e095488ebaa6 +--- + MagickCore/policy-private.h | 107 +----------------------------------- + MagickCore/policy.c | 130 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 131 insertions(+), 106 deletions(-) + +diff --git a/MagickCore/policy-private.h b/MagickCore/policy-private.h +index d262879..bf115fb 100644 +--- a/MagickCore/policy-private.h ++++ b/MagickCore/policy-private.h +@@ -37,8 +37,7 @@ static const char + #endif + + extern MagickExport MagickBooleanType +- IsRightsAuthorizedByName(const PolicyDomain,const char *,const PolicyRights, +- const char *); ++ IsPathAuthorized(const PolicyRights,const char *); + + extern MagickPrivate MagickBooleanType + PolicyComponentGenesis(void); +@@ -46,110 +45,6 @@ extern MagickPrivate MagickBooleanType + extern MagickPrivate void + PolicyComponentTerminus(void); + +-static inline MagickBooleanType IsPathContainsSymlink(const char *path) +-{ +- char +- partial[MagickPathExtent]; +- +- const char +- *p; +- +- ssize_t +- offset = 0; +- +- if (path == (const char *) NULL) +- return(MagickFalse); +- *partial='\0'; +- p=path; +- if (*p == *DirectorySeparator) +- { +- /* +- Path starts with a directory separator, include it. +- */ +- if ((offset+1) >= (ssize_t) sizeof(partial)) +- return(MagickFalse); +- partial[offset++]=(*p++); +- partial[offset]='\0'; +- } +- while (*p != '\0') +- { +- char +- component[MagickPathExtent]; +- +- ssize_t +- i = 0; +- +- /* +- Copy next component into a temporary buffer. +- */ +- while ((*p != '\0') && (*p != *DirectorySeparator) && +- ((i+1) < (ssize_t) sizeof(component))) +- component[i++]=(*p++); +- component[i]='\0'; +- if (i == 0) +- { +- /* +- skip repeated separators. +- */ +- if (*p == *DirectorySeparator) +- p++; +- continue; +- } +- if ((offset > 0) && (partial[offset-1] != *DirectorySeparator)) +- { +- /* +- Append separator if needed. +- */ +- if ((offset+1) >= (ssize_t) sizeof(partial)) +- return MagickFalse; +- partial[offset++]=(*DirectorySeparator); +- partial[offset]='\0'; +- } +- /* +- Append component. +- */ +- if ((offset+i) >= (ssize_t) sizeof(partial)) +- return(MagickFalse); +- (void) memcpy(partial+offset,component,i); +- offset+=i; +- partial[offset]='\0'; +- if (*p != '\0') +- { +- /* +- Check whether this prefix is a symlink. +- */ +- if (is_symlink_utf8(partial) != MagickFalse) +- return(MagickTrue); +- } +- /* +- Skip separator. +- */ +- if (*p == *DirectorySeparator) +- p++; +- } +- return(MagickFalse); +-} +- +-static inline MagickBooleanType IsPathAuthorized(const PolicyRights rights, +- const char *path) +-{ +- MagickBooleanType symlink_follow_allowed = IsRightsAuthorizedByName( +- SystemPolicyDomain,"symlink",rights,"follow"); +- MagickBooleanType status = +- ((IsRightsAuthorized(PathPolicyDomain,rights,path) != MagickFalse) && +- ((symlink_follow_allowed != MagickFalse) || +- (is_symlink_utf8(path) == MagickFalse))) ? MagickTrue : MagickFalse; +- if ((status != MagickFalse) && (symlink_follow_allowed == MagickFalse)) +- { +- if ((is_symlink_utf8(path) != MagickFalse) || +- (IsPathContainsSymlink(path) != MagickFalse)) +- status=MagickFalse; +- } +- if (status != MagickFalse) +- status=IsFileResourceIdentityValid(path); +- return(status); +-} +- + #if defined(__cplusplus) || defined(c_plusplus) + } + #endif +diff --git a/MagickCore/policy.c b/MagickCore/policy.c +index 282b053..0a5224c 100644 +--- a/MagickCore/policy.c ++++ b/MagickCore/policy.c +@@ -576,6 +576,136 @@ MagickExport char *GetPolicyValue(const char *name) + % % + % % + % % +++ I s P a t h A u t h o r i z e d % ++% % ++% % ++% % ++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ++% ++% IsPathAuthorized() determines if the specified path is authorized based on ++% the current policy settings. ++% ++% The format of the IsPathAuthorized method is: ++% ++% MagickBooleanType IsPathAuthorized(const PolicyRights rights, ++% const char *path) ++% ++% A description of each parameter follows. ++% ++% o rights: The policy rights to check. ++% ++% o path: The path to check. ++% ++*/ ++static inline MagickBooleanType IsPathContainsSymlink(const char *path) ++{ ++ char ++ partial[MagickPathExtent]; ++ ++ const char ++ *p; ++ ++ ssize_t ++ offset = 0; ++ ++ if (path == (const char *) NULL) ++ return(MagickFalse); ++ *partial='\0'; ++ p=path; ++ if (*p == *DirectorySeparator) ++ { ++ /* ++ Path starts with a directory separator, include it. ++ */ ++ if ((offset+1) >= (ssize_t) sizeof(partial)) ++ return(MagickFalse); ++ partial[offset++]=(*p++); ++ partial[offset]='\0'; ++ } ++ while (*p != '\0') ++ { ++ char ++ component[MagickPathExtent]; ++ ++ ssize_t ++ i = 0; ++ ++ /* ++ Copy next component into a temporary buffer. ++ */ ++ while ((*p != '\0') && (*p != *DirectorySeparator) && ++ ((i+1) < (ssize_t) sizeof(component))) ++ component[i++]=(*p++); ++ component[i]='\0'; ++ if (i == 0) ++ { ++ /* ++ skip repeated separators. ++ */ ++ if (*p == *DirectorySeparator) ++ p++; ++ continue; ++ } ++ if ((offset > 0) && (partial[offset-1] != *DirectorySeparator)) ++ { ++ /* ++ Append separator if needed. ++ */ ++ if ((offset+1) >= (ssize_t) sizeof(partial)) ++ return MagickFalse; ++ partial[offset++]=(*DirectorySeparator); ++ partial[offset]='\0'; ++ } ++ /* ++ Append component. ++ */ ++ if ((offset+i) >= (ssize_t) sizeof(partial)) ++ return(MagickFalse); ++ (void) memcpy(partial+offset,component,i); ++ offset+=i; ++ partial[offset]='\0'; ++ if (*p != '\0') ++ { ++ /* ++ Check whether this prefix is a symlink. ++ */ ++ if (is_symlink_utf8(partial) != MagickFalse) ++ return(MagickTrue); ++ } ++ /* ++ Skip separator. ++ */ ++ if (*p == *DirectorySeparator) ++ p++; ++ } ++ return(MagickFalse); ++} ++ ++MagickExport MagickBooleanType IsPathAuthorized(const PolicyRights rights, ++ const char *path) ++{ ++ MagickBooleanType symlink_follow_allowed = IsRightsAuthorizedByName( ++ SystemPolicyDomain,"symlink",rights,"follow"); ++ MagickBooleanType status = ++ ((IsRightsAuthorized(PathPolicyDomain,rights,path) != MagickFalse) && ++ ((symlink_follow_allowed != MagickFalse) || ++ (is_symlink_utf8(path) == MagickFalse))) ? MagickTrue : MagickFalse; ++ if ((status != MagickFalse) && (symlink_follow_allowed == MagickFalse)) ++ { ++ if ((is_symlink_utf8(path) != MagickFalse) || ++ (IsPathContainsSymlink(path) != MagickFalse)) ++ status=MagickFalse; ++ } ++ if (status != MagickFalse) ++ status=IsFileResourceIdentityValid(path); ++ return(status); ++} ++ ++/* ++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ++% % ++% % ++% % + + I s P o l i c y C a c h e I n s t a n t i a t e d % + % % + % % diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre6.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre6.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre6.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86424_pre6.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,74 @@ +From: Cristy +Date: Sun, 14 Jun 2026 08:47:22 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-jxqv-9g3j-9jh6 + +(cherry picked from commit 166fdea9c39b5b21415e326f579947f80f1afbe7) + +[debian] +- prepare CVE-2026-86424 patch by raising exception if needed + +origin: https://github.com/ImageMagick/ImageMagick/commit/166fdea9c39b5b21415e326f579947f80f1afbe7 +--- + MagickCore/delegate.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/MagickCore/delegate.c b/MagickCore/delegate.c +index a50b204..6df2682 100644 +--- a/MagickCore/delegate.c ++++ b/MagickCore/delegate.c +@@ -66,6 +66,7 @@ + #include "MagickCore/nt-base-private.h" + #include "MagickCore/option.h" + #include "MagickCore/policy.h" ++#include "MagickCore/policy-private.h" + #include "MagickCore/property.h" + #include "MagickCore/resource_.h" + #include "MagickCore/semaphore.h" +@@ -1623,7 +1624,8 @@ static MagickBooleanType IsDelegateCacheInstantiated(ExceptionInfo *exception) + */ + + static MagickBooleanType CopyDelegateFile(const char *source, +- const char *destination,const MagickBooleanType overwrite) ++ const char *destination,const MagickBooleanType overwrite, ++ ExceptionInfo *exception) + { + int + destination_file, +@@ -1657,6 +1659,8 @@ static MagickBooleanType CopyDelegateFile(const char *source, + if (status != MagickFalse) + return(MagickTrue); + } ++ if (IsPathAuthorized(WritePolicyRights,destination) == MagickFalse) ++ ThrowPolicyException(destination,MagickFalse); + destination_file=open_utf8(destination,O_WRONLY | O_BINARY | O_CREAT,S_MODE); + if (destination_file == -1) + return(MagickFalse); +@@ -1860,6 +1864,13 @@ MagickExport MagickBooleanType InvokeDelegate(ImageInfo *image_info, + (void) CopyMagickString(input_filename,image->filename,MagickPathExtent); + for (i=0; commands[i] != (char *) NULL; i++) + { ++ if (IsPathAuthorized(WritePolicyRights,output_filename) == MagickFalse) ++ { ++ errno=EPERM; ++ (void) ThrowMagickException(exception,GetMagickModule(),PolicyError, \ ++ "NotAuthorized","`%s'",output_filename); ++ break; ++ } + (void) AcquireUniqueSymbolicLink(output_filename,image_info->filename); + if (AcquireUniqueFilename(image_info->unique) == MagickFalse) + { +@@ -1903,11 +1914,11 @@ MagickExport MagickBooleanType InvokeDelegate(ImageInfo *image_info, + } + if (LocaleCompare(decode,"SCAN") != 0) + { +- if (CopyDelegateFile(image->filename,input_filename,MagickFalse) == MagickFalse) ++ if (CopyDelegateFile(image->filename,input_filename,MagickFalse,exception) == MagickFalse) + (void) RelinquishUniqueFileResource(input_filename); + } + if ((strcmp(input_filename,output_filename) != 0) && +- (CopyDelegateFile(image_info->filename,output_filename,MagickTrue) == MagickFalse)) ++ (CopyDelegateFile(image_info->filename,output_filename,MagickTrue,exception) == MagickFalse)) + (void) RelinquishUniqueFileResource(output_filename); + if (image_info->temporary != MagickFalse) + (void) RelinquishUniqueFileResource(image_info->filename); diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86425.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86425.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86425.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-86425.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,40 @@ +From: Cristy +Date: Tue, 4 Aug 2026 18:46:51 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-chf5-8rv9-gjqr + +(cherry picked from commit 5bff96a5c8d0b3dafa4ad4fa7916db4cae72a11d) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-chf5-8rv9-gjqr +origin: https://github.com/ImageMagick/ImageMagick/commit/5bff96a5c8d0b3dafa4ad4fa7916db4cae72a11d +--- + PerlMagick/quantum/quantum.xs | 2 +- + PerlMagick/quantum/quantum.xs.in | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/PerlMagick/quantum/quantum.xs b/PerlMagick/quantum/quantum.xs +index 9adf8c9..e2cc444 100644 +--- a/PerlMagick/quantum/quantum.xs ++++ b/PerlMagick/quantum/quantum.xs +@@ -7315,7 +7315,7 @@ Layers(ref,...) + /* + Split image sequence at the first 'NULL:' image. + */ +- source=image; ++ source=CloneImageList(image,exception); + while (source != (Image *) NULL) + { + source=GetNextImageInList(source); +diff --git a/PerlMagick/quantum/quantum.xs.in b/PerlMagick/quantum/quantum.xs.in +index bfcf7ba..9156820 100644 +--- a/PerlMagick/quantum/quantum.xs.in ++++ b/PerlMagick/quantum/quantum.xs.in +@@ -7315,7 +7315,7 @@ Layers(ref,...) + /* + Split image sequence at the first 'NULL:' image. + */ +- source=image; ++ source=CloneImageList(image,exception); + while (source != (Image *) NULL) + { + source=GetNextImageInList(source); diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93586_1.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93586_1.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93586_1.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93586_1.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,140 @@ +From: Cristy +Date: Sat, 29 Aug 2026 11:54:46 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-3rjr-534c-8v67 + +(cherry picked from commit 282f455de5c80a7a0d1a713087db9c8fce344141) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-3rjr-534c-8v67 +origin: https://github.com/ImageMagick/ImageMagick/commit/282f455de5c80a7a0d1a713087db9c8fce344141 +--- + MagickCore/blob-private.h | 3 ++ + MagickCore/blob.c | 73 +++++++++++++++++++++++++++++++++++++++++++++-- + MagickCore/constitute.c | 2 ++ + 3 files changed, 76 insertions(+), 2 deletions(-) + +diff --git a/MagickCore/blob-private.h b/MagickCore/blob-private.h +index b977166..96fa45c 100644 +--- a/MagickCore/blob-private.h ++++ b/MagickCore/blob-private.h +@@ -148,6 +148,9 @@ extern MagickExport void + MSBOrderLong(unsigned char *,const size_t), + MSBOrderShort(unsigned char *,const size_t); + ++extern MagickPrivate void ++ SyncImagesBlob(ImageInfo *,const Image *,Image *); ++ + #if defined(__cplusplus) || defined(c_plusplus) + } + #endif +diff --git a/MagickCore/blob.c b/MagickCore/blob.c +index 5f1adf5..e7b803a 100644 +--- a/MagickCore/blob.c ++++ b/MagickCore/blob.c +@@ -2154,8 +2154,9 @@ MagickExport void *ImageToBlob(const ImageInfo *image_info, + else + blob=ResizeQuantumMemory(blob,*length+1,sizeof(unsigned char)); + } +- else if ((status == MagickFalse) && (image->blob->extent == 0)) +- blob_info->blob=RelinquishMagickMemory(blob_info->blob); ++ else ++ if ((status == MagickFalse) && (image->blob->extent == 0)) ++ blob_info->blob=RelinquishMagickMemory(blob_info->blob); + } + } + else +@@ -2553,6 +2554,7 @@ MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images, + images->blob->extent=0; + *images->filename='\0'; + status=WriteImages(blob_info,images,images->filename,exception); ++ SyncImagesBlob(blob_info,images,images); + *length=images->blob->length; + blob=DetachBlob(images->blob); + if (blob != (void *) NULL) +@@ -5689,6 +5691,73 @@ static int SyncBlob(const Image *image) + % % + % % + % % +++ S y n c I m a g e s B l o b % ++% % ++% % ++% % ++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ++% ++% SyncImagesBlob() re-synchronizes the in-memory blob stream that is shared ++% by an image list. An encoder may grow the blob with SetBlobExtent(), which ++% reallocates (and therefore frees) the buffer that AttachBlob() previously ++% handed to the other images of the list and to image_info->blob. This method ++% replaces every stale reference to that buffer with the current one so that a ++% subsequent AttachBlob(), write, or free never touches freed memory. ++% ++% The format of the SyncImagesBlob method is: ++% ++% void SyncImagesBlob(ImageInfo *image,const Image *image,Image *images) ++% ++% A description of each parameter follows: ++% ++% o image_info: the image info whose blob member is updated; may be NULL. ++% ++% o image: the image that was just written (owner of the live blob). ++% ++% o images: the head of the image list that is being synchronized. ++% ++*/ ++MagickPrivate void SyncImagesBlob(ImageInfo *image_info,const Image *image, ++ Image *images) ++{ ++ Image ++ *p; ++ ++ unsigned char ++ *current, ++ *stale; ++ ++ assert(image != (const Image *) NULL); ++ assert(image->signature == MagickCoreSignature); ++ if ((image->blob == (BlobInfo *) NULL) || (image->blob->type != BlobStream)) ++ return; ++ current=image->blob->data; ++ stale=(unsigned char *) (image_info != (ImageInfo *) NULL ? ++ image_info->blob : (void *) NULL); ++ if (image_info != (ImageInfo *) NULL) ++ { ++ image_info->blob=(void *) current; ++ image_info->length=image->blob->length; ++ } ++ if ((stale == (unsigned char *) NULL) || (stale == current)) ++ return; /* nothing was reallocated */ ++ for (p=images; p != (Image *) NULL; p=GetNextImageInList(p)) ++ { ++ if ((p == image) || (p->blob == (BlobInfo *) NULL)) ++ continue; ++ if ((p->blob->type != BlobStream) || (p->blob->data != stale)) ++ continue; ++ p->blob->data=current; ++ p->blob->extent=image->blob->extent; ++ p->blob->length=image->blob->length; ++ } ++} ++ ++/* ++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ++% % ++% % ++% % + + T e l l B l o b % + % % + % % +diff --git a/MagickCore/constitute.c b/MagickCore/constitute.c +index 03fd3ef..d3e43a5 100644 +--- a/MagickCore/constitute.c ++++ b/MagickCore/constitute.c +@@ -1573,6 +1573,8 @@ MagickExport MagickBooleanType WriteImages(const ImageInfo *image_info, + progress_monitor=SetImageProgressMonitor(p,(MagickProgressMonitor) NULL, + p->client_data); + status&=(MagickStatusType) WriteImage(write_info,p,exception); ++ if (write_info->blob != (void *) NULL) ++ SyncImagesBlob(write_info,p,images); + if (number_images != 1) + (void) SetImageProgressMonitor(p,progress_monitor,p->client_data); + if (write_info->adjoin != MagickFalse) diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93586_2.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93586_2.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93586_2.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93586_2.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,165 @@ +From: Cristy +Date: Sat, 29 Aug 2026 14:14:25 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-3rjr-534c-8v67 + +(cherry picked from commit 4fe31106f41fa114945ceaf93226fb151ada0d19) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-3rjr-534c-8v67 +origin: https://github.com/ImageMagick/ImageMagick/commit/4fe31106f41fa114945ceaf93226fb151ada0d19 +--- + MagickCore/blob-private.h | 2 +- + MagickCore/blob.c | 78 +++++++++++++++++++++++------------------------ + MagickCore/constitute.c | 2 +- + 3 files changed, 40 insertions(+), 42 deletions(-) + +diff --git a/MagickCore/blob-private.h b/MagickCore/blob-private.h +index 96fa45c..fdd3d5b 100644 +--- a/MagickCore/blob-private.h ++++ b/MagickCore/blob-private.h +@@ -149,7 +149,7 @@ extern MagickExport void + MSBOrderShort(unsigned char *,const size_t); + + extern MagickPrivate void +- SyncImagesBlob(ImageInfo *,const Image *,Image *); ++ SyncBlobStream(ImageInfo *,Image *,Image *); + + #if defined(__cplusplus) || defined(c_plusplus) + } +diff --git a/MagickCore/blob.c b/MagickCore/blob.c +index e7b803a..f36a624 100644 +--- a/MagickCore/blob.c ++++ b/MagickCore/blob.c +@@ -2145,6 +2145,7 @@ MagickExport void *ImageToBlob(const ImageInfo *image_info, + image->blob->extent=0; + *image->filename='\0'; + status=WriteImage(blob_info,image,exception); ++ SyncBlobStream(blob_info,image,image); + *length=image->blob->length; + blob=DetachBlob(image->blob); + if (blob != (void *) NULL) +@@ -2554,7 +2555,7 @@ MagickExport void *ImagesToBlob(const ImageInfo *image_info,Image *images, + images->blob->extent=0; + *images->filename='\0'; + status=WriteImages(blob_info,images,images->filename,exception); +- SyncImagesBlob(blob_info,images,images); ++ SyncBlobStream(blob_info,images,images); + *length=images->blob->length; + blob=DetachBlob(images->blob); + if (blob != (void *) NULL) +@@ -5691,66 +5692,63 @@ static int SyncBlob(const Image *image) + % % + % % + % % +-+ S y n c I m a g e s B l o b % +++ S y n c B l o b S t r e a m % + % % + % % + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % +-% SyncImagesBlob() re-synchronizes the in-memory blob stream that is shared +-% by an image list. An encoder may grow the blob with SetBlobExtent(), which +-% reallocates (and therefore frees) the buffer that AttachBlob() previously +-% handed to the other images of the list and to image_info->blob. This method +-% replaces every stale reference to that buffer with the current one so that a +-% subsequent AttachBlob(), write, or free never touches freed memory. ++% SyncBlobStream() transfers ownership of an in-memory blob stream from the ++% image that has just been written back to the owner image and to image info. ++% The method copies the current buffer state onto the owner, refreshes ++% image info, and detaches the borrower so exactly one object owns the memory. + % +-% The format of the SyncImagesBlob method is: ++% The format of the SyncBlobStream method is: + % +-% void SyncImagesBlob(ImageInfo *image,const Image *image,Image *images) ++% void SyncBlobStream(ImageInfo *image,const Image *image,Image *owner) + % + % A description of each parameter follows: + % +-% o image_info: the image info whose blob member is updated; may be NULL. ++% o image_info: image info whose blob/length members are refreshed; may be ++% NULL. + % +-% o image: the image that was just written (owner of the live blob). ++% o owner: the image ImagesToBlob()/ImageToBlob() harvests the blob from ++% (the head of the list). + % +-% o images: the head of the image list that is being synchronized. ++% o image: the image that was just written; may be the owner. + % + */ +-MagickPrivate void SyncImagesBlob(ImageInfo *image_info,const Image *image, +- Image *images) ++MagickPrivate void SyncBlobStream(ImageInfo *image_info,Image *image, ++ Image *owner) + { +- Image +- *p; +- +- unsigned char +- *current, +- *stale; +- +- assert(image != (const Image *) NULL); ++ assert(owner != (Image *) NULL); ++ assert(image != (Image *) NULL); + assert(image->signature == MagickCoreSignature); +- if ((image->blob == (BlobInfo *) NULL) || (image->blob->type != BlobStream)) ++ if (image->blob == (BlobInfo *) NULL) ++ return; ++ if (image->blob->data == (unsigned char *) NULL) + return; +- current=image->blob->data; +- stale=(unsigned char *) (image_info != (ImageInfo *) NULL ? +- image_info->blob : (void *) NULL); + if (image_info != (ImageInfo *) NULL) + { +- image_info->blob=(void *) current; ++ image_info->blob=(void *) image->blob->data; + image_info->length=image->blob->length; + } +- if ((stale == (unsigned char *) NULL) || (stale == current)) +- return; /* nothing was reallocated */ +- for (p=images; p != (Image *) NULL; p=GetNextImageInList(p)) +- { +- if ((p == image) || (p->blob == (BlobInfo *) NULL)) +- continue; +- if ((p->blob->type != BlobStream) || (p->blob->data != stale)) +- continue; +- p->blob->data=current; +- p->blob->extent=image->blob->extent; +- p->blob->length=image->blob->length; +- } ++ if ((image == owner) || (owner->blob == (BlobInfo *) NULL)) ++ return; ++ if (owner->blob == (BlobInfo *) NULL) ++ return; ++ /* ++ Promote the live buffer onto the owner before detaching the borrower; ++ DetachBlob() clears image->blob->data. ++ */ ++ owner->blob->data=image->blob->data; ++ owner->blob->extent=image->blob->extent; ++ owner->blob->length=image->blob->length; ++ owner->blob->offset=image->blob->offset; ++ owner->blob->quantum=image->blob->quantum; ++ owner->blob->type=BlobStream; ++ owner->blob->exempt=MagickTrue; ++ (void) DetachBlob(image->blob); + } + + /* +diff --git a/MagickCore/constitute.c b/MagickCore/constitute.c +index d3e43a5..c1ef780 100644 +--- a/MagickCore/constitute.c ++++ b/MagickCore/constitute.c +@@ -1574,7 +1574,7 @@ MagickExport MagickBooleanType WriteImages(const ImageInfo *image_info, + p->client_data); + status&=(MagickStatusType) WriteImage(write_info,p,exception); + if (write_info->blob != (void *) NULL) +- SyncImagesBlob(write_info,p,images); ++ SyncBlobStream(write_info,p,images); + if (number_images != 1) + (void) SetImageProgressMonitor(p,progress_monitor,p->client_data); + if (write_info->adjoin != MagickFalse) diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93587_1.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93587_1.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93587_1.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93587_1.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,31 @@ +From: Cristy +Date: Fri, 28 Aug 2026 11:44:50 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-89wq-f8f6-2j2v + +(cherry picked from commit d779ac52f92c3045ced59362b483bee25a3fc784) +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-89wq-f8f6-2j2v +origin: https://github.com/ImageMagick/ImageMagick/commit/d779ac52f92c3045ced59362b483bee25a3fc784 +--- + coders/pcd.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/coders/pcd.c b/coders/pcd.c +index b8d1764..db34d9b 100644 +--- a/coders/pcd.c ++++ b/coders/pcd.c +@@ -881,8 +881,12 @@ static Image *ReadPCDImage(const ImageInfo *image_info,ExceptionInfo *exception) + if (LocaleCompare(image_info->magick,"PCDS") == 0) + (void) SetImageColorspace(image,sRGBColorspace,exception); + if (image_info->scene != 0) +- for (i=0; i < (ssize_t) image_info->scene; i++) +- AppendImageToList(&image,CloneImage(image,0,0,MagickTrue,exception)); ++ { ++ if (AcquireMagickResource(ListLengthResource,image_info->scene) == MagickFalse) ++ ThrowPCDException(ResourceLimitError,"ListLengthExceedsLimit"); ++ for (i=0; i < (ssize_t) image_info->scene; i++) ++ AppendImageToList(&image,CloneImage(image,0,0,MagickTrue,exception)); ++ } + if (status == MagickFalse) + return(image=DestroyImageList(image)); + return(GetFirstImageInList(image)); diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93587_2.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93587_2.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93587_2.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93587_2.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,50 @@ +From: Dirk Lemstra +Date: Tue, 1 Sep 2026 20:53:38 +0200 +Subject: More fixes for GHSA-89wq-f8f6-2j2v + +(cherry picked from commit b5da5eac006bae77c587a7c238e346c90ea52acd) +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-89wq-f8f6-2j2v +origin: https://github.com/ImageMagick/ImageMagick/commit/b5da5eac006bae77c587a7c238e346c90ea52acd +--- + coders/cube.c | 8 ++++++-- + coders/hald.c | 8 ++++++-- + 2 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/coders/cube.c b/coders/cube.c +index f36c1e8..8bae297 100644 +--- a/coders/cube.c ++++ b/coders/cube.c +@@ -317,8 +317,12 @@ static Image *ReadCUBEImage(const ImageInfo *image_info, + if (status == MagickFalse) + return(DestroyImageList(image)); + if (image_info->scene != 0) +- for (i=0; i < (ssize_t) image_info->scene; i++) +- AppendImageToList(&image,CloneImage(image,0,0,MagickTrue,exception)); ++ { ++ if (AcquireMagickResource(ListLengthResource,image_info->scene) == MagickFalse) ++ ThrowReaderException(ResourceLimitError,"ListLengthExceedsLimit"); ++ for (i=0; i < (ssize_t) image_info->scene; i++) ++ AppendImageToList(&image,CloneImage(image,0,0,MagickTrue,exception)); ++ } + return(GetFirstImageInList(image)); + } + +diff --git a/coders/hald.c b/coders/hald.c +index ed18464..433d02c 100644 +--- a/coders/hald.c ++++ b/coders/hald.c +@@ -189,8 +189,12 @@ static Image *ReadHALDImage(const ImageInfo *image_info, + if (status == MagickFalse) + return(DestroyImageList(image)); + if (image_info->scene != 0) +- for (i=0; i < (ssize_t) image_info->scene; i++) +- AppendImageToList(&image,CloneImage(image,0,0,MagickTrue,exception)); ++ { ++ if (AcquireMagickResource(ListLengthResource,image_info->scene) == MagickFalse) ++ ThrowReaderException(ResourceLimitError,"ListLengthExceedsLimit"); ++ for (i=0; i < (ssize_t) image_info->scene; i++) ++ AppendImageToList(&image,CloneImage(image,0,0,MagickTrue,exception)); ++ } + return(GetFirstImageInList(image)); + } + diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93588.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93588.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93588.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93588.patch 2026-10-23 19:43:56.000000000 +0000 @@ -0,0 +1,43 @@ +From: Dirk Lemstra +Date: Sat, 29 Aug 2026 12:45:35 +0200 +Subject: Added missing null check to avoid a null pointer dereference + (GHSA-92rw-c5mw-27v4) + +(cherry picked from commit c4b3c9039a1509e3e7869331773865b521a62f93) +[bookworm] - imagemagick (Minor issue) +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-92rw-c5mw-27v4 +origin: backport, https://github.com/ImageMagick/ImageMagick/commit/c4b3c9039a1509e3e7869331773865b521a62f93 +--- + coders/pnm.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/coders/pnm.c b/coders/pnm.c +index fe44903..b530458 100644 +--- a/coders/pnm.c ++++ b/coders/pnm.c +@@ -162,7 +162,8 @@ static int PNMComment(Image *image,CommentInfo *comment_info, + /* + Read comment. + */ +- (void) exception; ++ if (comment_info->comment == (char *) NULL) ++ return(-1); + p=comment_info->comment+strlen(comment_info->comment); + for (c='#'; (c != EOF) && (c != (int) '\n') && (c != (int) '\r'); p++) + { +@@ -1584,9 +1585,12 @@ static Image *ReadPNMImage(const ImageInfo *image_info,ExceptionInfo *exception) + default: + ThrowPNMException(CorruptImageError,"ImproperImageHeader"); + } +- if (*comment_info.comment != '\0') +- (void) SetImageProperty(image,"comment",comment_info.comment,exception); +- comment_info.comment=DestroyString(comment_info.comment); ++ if (comment_info.comment != (char*)NULL) ++ { ++ if (*comment_info.comment != '\0') ++ (void) SetImageProperty(image,"comment",comment_info.comment,exception); ++ comment_info.comment=DestroyString(comment_info.comment); ++ } + if (y < (ssize_t) image->rows) + ThrowPNMException(CorruptImageError,"UnableToReadImageData"); + if (EOFBlob(image) != MagickFalse) diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93589.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93589.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93589.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93589.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,29 @@ +From: Cristy +Date: Mon, 24 Aug 2026 09:42:51 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-4gg2-hfgh-6f5c + +(cherry picked from commit 8f620237fe341e814430fe3621b867b0b615f446) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-4gg2-hfgh-6f5c +origin: backport, https://github.com/ImageMagick/ImageMagick/commit/8f620237fe341e814430fe3621b867b0b615f446 +--- + coders/flif.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/coders/flif.c b/coders/flif.c +index 4c39fda..b780c32 100644 +--- a/coders/flif.c ++++ b/coders/flif.c +@@ -508,8 +508,9 @@ static MagickBooleanType WriteFLIFImage(const ImageInfo *image_info, + flif_image_write_row_RGBA8(flifimage,y,pixels,length); + } + } +- flif_image_set_frame_delay(flifimage,(uint32_t) image->delay*100/ +- image->ticks_per_second); ++ if (image->ticks_per_second != 0) ++ flif_image_set_frame_delay(flifimage,(uint32_t) (100*image->delay/ ++ image->ticks_per_second)); + flif_encoder_add_image(flifenc,flifimage); + if (GetNextImageInList(image) == (Image *) NULL) + break; diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93590.patch imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93590.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93590.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/CVE-2026-93590.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,26 @@ +From: Cristy +Date: Mon, 24 Aug 2026 09:49:50 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-7hjx-392p-f8cm + +(cherry picked from commit 59046410c17e9421f0ad7b4bec478a892cf30c12) + +bug; https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-7hjx-392p-f8cm +origin: https://github.com/ImageMagick/ImageMagick/commit/59046410c17e9421f0ad7b4bec478a892cf30c12 +--- + coders/uhdr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/coders/uhdr.c b/coders/uhdr.c +index 2cc3966..4d30a3c 100644 +--- a/coders/uhdr.c ++++ b/coders/uhdr.c +@@ -709,7 +709,7 @@ static MagickBooleanType WriteUHDRImage(const ImageInfo *image_info, + sdrImgDescriptor.planes[UHDR_PLANE_Y] = NULL; + } + +- yBuffer = AcquireMagickMemory(picSize); ++ yBuffer = AcquireQuantumMemory(picSize,1); + if (yBuffer == NULL) + { + status = MagickFalse; diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/GHSA-83w9-w85j-h9jc-1.patch imagemagick-7.1.1.43+dfsg1/debian/patches/GHSA-83w9-w85j-h9jc-1.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/GHSA-83w9-w85j-h9jc-1.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/GHSA-83w9-w85j-h9jc-1.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,28 @@ +From: Cristy +Date: Tue, 29 Sep 2026 07:46:36 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-83w9-w85j-h9jc + +(cherry picked from commit af510e976301c2516aaa26ea8f88318450eeece2) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-83w9-w85j-h9jc +origin: https://github.com/ImageMagick/ImageMagick/commit/af510e976301c2516aaa26ea8f88318450eeece2 +--- + coders/mat.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/coders/mat.c b/coders/mat.c +index 47b3297..af9c250 100644 +--- a/coders/mat.c ++++ b/coders/mat.c +@@ -1237,7 +1237,9 @@ RestoreMSCWarning + image->colors = GetQuantumRange(image->depth); + if (image->columns == 0 || image->rows == 0) + goto MATLAB_KO; +- if((size_t)ldblk*MATLAB_HDR.SizeY > MATLAB_HDR.ObjectSize) ++ if ((ldblk < 0) || ++ ((size_t) ldblk > ((size_t) ~0)/MATLAB_HDR.SizeY) || ++ (((size_t) ldblk*MATLAB_HDR.SizeY) > MATLAB_HDR.ObjectSize)) + goto MATLAB_KO; + /* Image is gray when no complex flag is set and 2D Matrix */ + if ((MATLAB_HDR.DimFlag == 8) && diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/GHSA-83w9-w85j-h9jc.patch imagemagick-7.1.1.43+dfsg1/debian/patches/GHSA-83w9-w85j-h9jc.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/GHSA-83w9-w85j-h9jc.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/GHSA-83w9-w85j-h9jc.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,31 @@ +From: Dirk Lemstra +Date: Tue, 29 Sep 2026 06:33:24 +0200 +Subject: Added missing cleanup in error path of the MAT decoder + (GHSA-83w9-w85j-h9jc) + +(cherry picked from commit 62c7876c37347dee0be1872e623650ba59f8a541) + +origin: https://github.com/ImageMagick/ImageMagick/commit/62c7876c37347dee0be1872e623650ba59f8a541 +--- + coders/mat.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/coders/mat.c b/coders/mat.c +index 69f0df0..47b3297 100644 +--- a/coders/mat.c ++++ b/coders/mat.c +@@ -1261,7 +1261,13 @@ RestoreMSCWarning + } + if ((image->columns > GetBlobSize(image)) || + (image->rows > GetBlobSize(image))) +- ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile"); ++ { ++ if (clone_info != (ImageInfo *) NULL) ++ clone_info=DestroyImageInfo(clone_info); ++ if ((image != image2) && (image2 != (Image *) NULL)) ++ image2=DestroyImage(image2); ++ ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile"); ++ } + status=SetImageExtent(image,image->columns,image->rows,exception); + if (status == MagickFalse) + { diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/coders-mat-c-7.1.2.33.patch imagemagick-7.1.1.43+dfsg1/debian/patches/coders-mat-c-7.1.2.33.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/coders-mat-c-7.1.2.33.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/coders-mat-c-7.1.2.33.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,109 @@ +From: =?utf-8?q?Bastien_Roucari=C3=A8s?= +Date: Fri, 23 Oct 2026 21:43:14 +0200 +Subject: Port coders/mat.c to 7.1.2.33 + +--- + coders/mat.c | 26 +++++++++++++------------- + 1 file changed, 13 insertions(+), 13 deletions(-) + +diff --git a/coders/mat.c b/coders/mat.c +index af9c250..a833fb6 100644 +--- a/coders/mat.c ++++ b/coders/mat.c +@@ -22,7 +22,7 @@ + % You may not use this file except in compliance with the License. You may % + % obtain a copy of the License at % + % % +-% https://imagemagick.org/script/license.php % ++% https://imagemagick.org/license/ % + % % + % Unless required by applicable law or agreed to in writing, software % + % distributed under the License is distributed on an "AS IS" BASIS, % +@@ -201,7 +201,7 @@ static void InsertComplexDoubleRow(Image *image,double *p,int y,double MinVal, + if ((f+(double) GetPixelRed(image,q)) >= (double) QuantumRange) + SetPixelRed(image,QuantumRange,q); + else +- SetPixelRed(image,(double) GetPixelRed(image,q)+ClampToQuantum(f),q); ++ SetPixelRed(image,GetPixelRed(image,q)+ClampToQuantum(f),q); + f=(double) GetPixelGreen(image,q)-f/2.0; + if (IsNaN(f) != 0) + f=0.0; +@@ -821,9 +821,9 @@ static Image *ReadMATImageV4(const ImageInfo *image_info,Image *image, + if (count == -1) + break; + if (HDR.Type[1] == 0) +- InsertComplexDoubleRow(image,(double *) pixels,y,0,0,exception); ++ InsertComplexDoubleRow(image,(double *) pixels,(int) y,0,0,exception); + else +- InsertComplexFloatRow(image,(float *) pixels,y,0,0,exception); ++ InsertComplexFloatRow(image,(float *) pixels,(int) y,0,0,exception); + } + quantum_info=DestroyQuantumInfo(quantum_info); + if (EOFBlob(image) != MagickFalse) +@@ -1049,7 +1049,7 @@ MATLAB_KO: + MATLAB_HDR.unknown1 = ReadBlobXXXLong(image2); + MATLAB_HDR.unknown2 = ReadBlobXXXLong(image2); + +- MATLAB_HDR.unknown5 = ReadBlobXXXLong(image2); ++ MATLAB_HDR.unknown5 = (unsigned short) ReadBlobXXXLong(image2); + MATLAB_HDR.StructureClass = MATLAB_HDR.unknown5 & 0xFF; + MATLAB_HDR.StructureFlag = (MATLAB_HDR.unknown5>>8) & 0xFF; + +@@ -1160,7 +1160,7 @@ MATLAB_KO: + CellType = ReadBlobXXXLong(image2); /* Additional object type */ + if (logging) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), +- "MATLAB_HDR.CellType: %.20g",(double) CellType); ++ "MATLAB_HDR.CellType: %.17g",(double) CellType); + + /* data size */ + if (ReadBlob(image2, 4, (unsigned char *) &size) != 4) +@@ -1234,7 +1234,7 @@ RestoreMSCWarning + (void) sample_size; + image->columns = MATLAB_HDR.SizeX; + image->rows = MATLAB_HDR.SizeY; +- image->colors = GetQuantumRange(image->depth); ++ image->colors = (size_t) GetQuantumRange(image->depth); + if (image->columns == 0 || image->rows == 0) + goto MATLAB_KO; + if ((ldblk < 0) || +@@ -1309,8 +1309,8 @@ RestoreMSCWarning + if (CellType==miDOUBLE || CellType==miSINGLE) /* Find Min and Max Values for floats */ + { + CalcMinMax(image2,(int) image_info->endian,MATLAB_HDR.SizeX, +- MATLAB_HDR.SizeY,CellType,ldblk,BImgBuff,&quantum_info->minimum, +- &quantum_info->maximum); ++ MATLAB_HDR.SizeY,CellType,(unsigned int) ldblk,BImgBuff, ++ &quantum_info->minimum,&quantum_info->maximum); + } + + /* Main loop for reading all scanlines */ +@@ -1382,8 +1382,8 @@ ExitLoop: + + if (CellType==miDOUBLE || CellType==miSINGLE) + { +- CalcMinMax(image2, (int) image_info->endian, MATLAB_HDR.SizeX, +- MATLAB_HDR.SizeY, CellType, ldblk, BImgBuff, &MinVal, &MaxVal); ++ CalcMinMax(image2,(int) image_info->endian,MATLAB_HDR.SizeX, ++ MATLAB_HDR.SizeY,CellType,(unsigned int) ldblk,BImgBuff,&MinVal,&MaxVal); + } + + if (CellType==miDOUBLE) +@@ -1392,7 +1392,7 @@ ExitLoop: + ReadBlobDoublesXXX(image2, (size_t) ldblk, (double *)BImgBuff); + if (EOFBlob(image) != MagickFalse) + break; +- InsertComplexDoubleRow(image, (double *)BImgBuff, i, MinVal, MaxVal, ++ InsertComplexDoubleRow(image,(double *)BImgBuff,(int) i,MinVal,MaxVal, + exception); + } + +@@ -1402,7 +1402,7 @@ ExitLoop: + ReadBlobFloatsXXX(image2, (size_t) ldblk, (float *)BImgBuff); + if (EOFBlob(image) != MagickFalse) + break; +- InsertComplexFloatRow(image,(float *)BImgBuff,i,MinVal,MaxVal, ++ InsertComplexFloatRow(image,(float *)BImgBuff,(int) i,MinVal,MaxVal, + exception); + } + } diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/port-distribute-cache-7.1.2.33.patch imagemagick-7.1.1.43+dfsg1/debian/patches/port-distribute-cache-7.1.2.33.patch --- imagemagick-7.1.1.43+dfsg1/debian/patches/port-distribute-cache-7.1.2.33.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/port-distribute-cache-7.1.2.33.patch 2026-10-23 19:43:57.000000000 +0000 @@ -0,0 +1,1226 @@ +From: =?utf-8?q?Bastien_Roucari=C3=A8s?= +Date: Sun, 18 Oct 2026 22:23:40 +0200 +Subject: Port distribute-cache to 7.1.2.33 + +--- + MagickCore/distribute-cache-private.h | 4 +- + MagickCore/distribute-cache.c | 679 +++++++++++++++++++++++++++------- + MagickCore/distribute-cache.h | 2 +- + 3 files changed, 551 insertions(+), 134 deletions(-) + +diff --git a/MagickCore/distribute-cache-private.h b/MagickCore/distribute-cache-private.h +index 3772b25..4b602a4 100644 +--- a/MagickCore/distribute-cache-private.h ++++ b/MagickCore/distribute-cache-private.h +@@ -5,7 +5,7 @@ + You may not use this file except in compliance with the License. You may + obtain a copy of the License at + +- https://imagemagick.org/script/license.php ++ https://imagemagick.org/license/ + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, +@@ -30,7 +30,7 @@ typedef struct _DistributeCacheInfo + int + file; + +- size_t ++ uint64_t + session_key; + + char +diff --git a/MagickCore/distribute-cache.c b/MagickCore/distribute-cache.c +index 112a7f9..c0dc2b4 100644 +--- a/MagickCore/distribute-cache.c ++++ b/MagickCore/distribute-cache.c +@@ -28,7 +28,7 @@ + % You may not use this file except in compliance with the License. You may % + % obtain a copy of the License at % + % % +-% https://imagemagick.org/script/license.php % ++% https://imagemagick.org/license/ % + % % + % Unless required by applicable law or agreed to in writing, software % + % distributed under the License is distributed on an "AS IS" BASIS, % +@@ -75,6 +75,7 @@ + #include "MagickCore/utility-private.h" + #include "MagickCore/version.h" + #include "MagickCore/version-private.h" ++#define SOCKET_TYPE int + #undef MAGICKCORE_HAVE_DISTRIBUTE_CACHE + #if defined(MAGICKCORE_DPC_SUPPORT) + #if defined(MAGICKCORE_HAVE_SOCKET) && defined(MAGICKCORE_THREAD_SUPPORT) +@@ -92,7 +93,6 @@ + #define CLOSE_SOCKET(socket) (void) closesocket(socket) + #define HANDLER_RETURN_TYPE DWORD WINAPI + #define HANDLER_RETURN_VALUE 0 +-#define SOCKET_TYPE SOCKET + #define LENGTH_TYPE int + #define MAGICKCORE_HAVE_DISTRIBUTE_CACHE 1 + #define MAGICKCORE_HAVE_WINSOCK2 1 +@@ -103,9 +103,11 @@ + Define declarations. + */ + #define DPCHostname "127.0.0.1" ++#define DPCMaxClientWorkers 128 ++#define DPCMaxUnauthenticatedClientWorkers 16 + #define DPCPendingConnections 10 + #define DPCPort 6668 +-#define DPCSessionKeyLength 8 ++#define DPCSessionKeyLength 16 + #ifndef MSG_NOSIGNAL + # define MSG_NOSIGNAL 0 + #endif +@@ -115,11 +117,23 @@ + */ + #ifdef MAGICKCORE_HAVE_WINSOCK2 + static SemaphoreInfo +- *winsock2_semaphore = (SemaphoreInfo *) NULL; ++ *winsock_semaphore = (SemaphoreInfo *) NULL; + + static WSADATA + *wsaData = (WSADATA*) NULL; + #endif ++ ++#if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) ++static SemaphoreInfo ++ *dpc_semaphore = (SemaphoreInfo *) NULL; ++ ++static char ++ *dpc_shared_secret = (char *) NULL; ++ ++static size_t ++ dpc_clients = 0, ++ dpc_unauthenticated_clients = 0; ++#endif + + /* + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@@ -145,7 +159,7 @@ static WSADATA + */ + + #if !defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) +-static inline MagickOffsetType dpc_read(int magick_unused(file), ++static inline MagickOffsetType dpc_receive(SOCKET_TYPE magick_unused(file), + const MagickSizeType magick_unused(length), + unsigned char *magick_restrict magick_unused(message)) + { +@@ -154,29 +168,124 @@ static inline MagickOffsetType dpc_read(int magick_unused(file), + magick_unreferenced(message); + return(-1); + } ++ ++static inline MagickOffsetType dpc_receive_deadline(SOCKET_TYPE ++ magick_unused(file),const MagickSizeType magick_unused(length), ++ unsigned char *magick_restrict magick_unused(message), ++ double magick_unused(deadline)) ++{ ++ magick_unreferenced(file); ++ magick_unreferenced(length); ++ magick_unreferenced(message); ++ magick_unreferenced(deadline); ++ return(-1); ++} + #else +-static inline MagickOffsetType dpc_read(int file,const MagickSizeType length, +- unsigned char *magick_restrict message) ++static void SetSocketReceiveTimeout(SOCKET_TYPE file,double seconds) + { +- MagickOffsetType +- i; ++ /* ++ Set a receive timeout. ++ */ ++#if defined(MAGICKCORE_HAVE_WINSOCK2) ++ { ++ DWORD timeout = (DWORD) (seconds*1000.0); ++ (void) setsockopt(file,SOL_SOCKET,SO_RCVTIMEO, ++ (const char *) &timeout,sizeof(timeout)); ++ } ++#else ++ { ++ struct timeval tv; ++ tv.tv_sec=(int) seconds; ++ tv.tv_usec=(int) ((seconds-(double) tv.tv_sec)*1000000.0); ++ (void) setsockopt(file,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)); ++ } ++#endif ++} + +- ssize_t +- count; ++static inline MagickOffsetType dpc_receive(SOCKET_TYPE file, ++ const MagickSizeType length,unsigned char *magick_restrict message) ++{ ++ MagickOffsetType offset = 0; ++ while (offset < (MagickOffsetType) length) ++ { ++ MagickSizeType chunk = MagickMin(length-offset,(MagickSizeType) ++ MagickMaxBufferExtent); ++ ssize_t count = recv(file,(char *) message+offset,(LENGTH_TYPE) chunk,0); ++ if (count > 0) ++ offset+=(MagickOffsetType) count; ++ else ++ if (count == 0) ++ return(0); ++ else ++ { ++#ifdef MAGICKCORE_HAVE_WINSOCK2 ++ int wsa_err = WSAGetLastError(); ++ if ((wsa_err == WSAEINTR) || (wsa_err == WSAEWOULDBLOCK)) ++ continue; ++ if (wsa_err == WSAECONNRESET) ++ return(-2); ++#else ++ if ((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK)) ++ continue; ++ if (errno == ECONNRESET) ++ return(-2); ++#endif ++ return(-1); ++ } ++ } ++ return(offset); ++} + +- count=0; +- for (i=0; i < (MagickOffsetType) length; i+=count) ++static inline MagickOffsetType dpc_receive_deadline(SOCKET_TYPE file, ++ MagickSizeType length,unsigned char *message,double deadline) ++{ ++ /* ++ Enforce an absolute deadline for authentication and command reads. ++ */ ++ MagickOffsetType offset = 0; ++ while (offset < (MagickOffsetType) length) + { +- count=recv(file,(char *) message+i,(LENGTH_TYPE) MagickMin(length- +- (MagickSizeType) i,(MagickSizeType) MagickMaxBufferExtent),0); +- if (count <= 0) +- { +- count=0; +- if (errno != EINTR) +- break; +- } ++ double ++ now = (double) time((time_t *) NULL), ++ remaining = deadline-now; ++ ++ MagickSizeType ++ chunk; ++ ++ ssize_t ++ count; ++ ++ if (now >= deadline) ++ return(-1); ++ if (remaining < 0.001) ++ remaining=0.001; ++ SetSocketReceiveTimeout(file,remaining); ++ chunk=MagickMin(length-offset,(MagickSizeType) MagickMaxBufferExtent); ++ count=recv(file,(char *) message+offset,(LENGTH_TYPE) chunk,0); ++ if (count > 0) ++ offset+=(MagickOffsetType) count; ++ else ++ if (count == 0) ++ return(0); ++ else ++ { ++#ifdef MAGICKCORE_HAVE_WINSOCK2 ++ int wsa_err = WSAGetLastError(); ++ if ((wsa_err == WSAEINTR) || (wsa_err == WSAEWOULDBLOCK)) ++ continue; ++ if (wsa_err == WSAECONNRESET) ++ return(-2); ++ return(-1); ++#else ++ if ((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK)) ++ continue; ++ if (errno == ECONNRESET) ++ return(-2); ++ return(-1); ++#endif ++ } + } +- return(i); ++ return(offset); + } + #endif + +@@ -185,9 +294,9 @@ static void InitializeWinsock2(MagickBooleanType use_lock) + { + if (use_lock != MagickFalse) + { +- if (winsock2_semaphore == (SemaphoreInfo *) NULL) +- ActivateSemaphoreInfo(&winsock2_semaphore); +- LockSemaphoreInfo(winsock2_semaphore); ++ if (winsock_semaphore == (SemaphoreInfo *) NULL) ++ ActivateSemaphoreInfo(&winsock_semaphore); ++ LockSemaphoreInfo(winsock_semaphore); + } + if (wsaData == (WSADATA *) NULL) + { +@@ -196,13 +305,13 @@ static void InitializeWinsock2(MagickBooleanType use_lock) + ThrowFatalException(CacheFatalError,"WSAStartup failed"); + } + if (use_lock != MagickFalse) +- UnlockSemaphoreInfo(winsock2_semaphore); ++ UnlockSemaphoreInfo(winsock_semaphore); + } + #endif + + #if !defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) + static int ConnectPixelCacheServer(const char *magick_unused(hostname), +- const int magick_unused(port),size_t *magick_unused(session_key), ++ const int magick_unused(port),uint64_t *magick_unused(session_key), + ExceptionInfo *exception) + { + magick_unreferenced(hostname); +@@ -213,10 +322,124 @@ static int ConnectPixelCacheServer(const char *magick_unused(hostname), + return(MagickFalse); + } + #else ++static inline uint64_t ROTL(uint64_t x,int b) ++{ ++ return((x << b) | (x >> (64-b))); ++} ++ ++static inline uint64_t U8TO64_LE(const uint8_t *p) ++{ ++ return(((uint64_t) p[0] << 0) | ((uint64_t) p[1] << 8) | ++ ((uint64_t) p[2] << 16) | ((uint64_t) p[3] << 24) | ++ ((uint64_t) p[4] << 32) | ((uint64_t) p[5] << 40) | ++ ((uint64_t) p[6] << 48) | ((uint64_t) p[7] << 56)); ++} ++ ++static inline uint64_t SIPHash24(const uint8_t key[16],const uint8_t *message, ++ const size_t length) ++{ ++ const uint8_t ++ *end = message+length-(length % 8); ++ ++ size_t ++ i; ++ ++ uint64_t ++ b = ((uint64_t) length) << 56, ++ k0 = U8TO64_LE(key), ++ k1 = U8TO64_LE(key+8), ++ m, ++ v0 = 0x736f6d6570736575ULL ^ k0, ++ v1 = 0x646f72616e646f6dULL ^ k1, ++ v2 = 0x6c7967656e657261ULL ^ k0, ++ v3 = 0x7465646279746573ULL ^ k1; ++ ++ for ( ; message != end; message+=8) ++ { ++ m=U8TO64_LE(message); ++ v3^=m; ++ for (i=0; i < 2; i++) ++ { ++ v0+=v1; v1=ROTL(v1,13); v1^=v0; v0=ROTL(v0,32); ++ v2+=v3; v3=ROTL(v3,16); v3^=v2; ++ v0+=v3; v3=ROTL(v3,21); v3^=v0; ++ v2+=v1; v1=ROTL(v1,17); v1^=v2; v2=ROTL(v2,32); ++ } ++ v0^=m; ++ } ++ switch (length & 0x07) ++ { ++ case 7: b|=((uint64_t) message[6]) << 48; magick_fallthrough; ++ case 6: b|=((uint64_t) message[5]) << 40; magick_fallthrough; ++ case 5: b|=((uint64_t) message[4]) << 32; magick_fallthrough; ++ case 4: b|=((uint64_t) message[3]) << 24; magick_fallthrough; ++ case 3: b|=((uint64_t) message[2]) << 16; magick_fallthrough; ++ case 2: b|=((uint64_t) message[1]) << 8; magick_fallthrough; ++ case 1: b|=((uint64_t) message[0]); magick_fallthrough; ++ default: break; ++ } ++ v3^=b; ++ for (i=0; i < 2; i++) ++ { ++ v0+=v1; v1=ROTL(v1,13); v1^=v0; v0=ROTL(v0,32); ++ v2+=v3; v3=ROTL(v3,16); v3^=v2; ++ v0+=v3; v3=ROTL(v3,21); v3^=v0; ++ v2+=v1; v1=ROTL(v1,17); v1^=v2; v2=ROTL(v2,32); ++ } ++ v0^=b; ++ v2^=0xff; ++ for (i=0; i < 4; i++) ++ { ++ v0+=v1; v1=ROTL(v1,13); v1^=v0; v0=ROTL(v0,32); ++ v2+=v3; v3=ROTL(v3,16); v3^=v2; ++ v0+=v3; v3=ROTL(v3,21); v3^=v0; ++ v2+=v1; v1=ROTL(v1,17); v1^=v2; v2=ROTL(v2,32); ++ } ++ return(v0^v1^v2^v3); ++} ++ ++static inline void DeriveSIPKeyFromSecret(const char *shared_secret, ++ uint8_t key[16]) ++{ ++ size_t ++ i, ++ length; ++ ++ uint64_t ++ k0 = 0x0706050403020100ULL, ++ k1 = 0x0f0e0d0c0b0a0908ULL; ++ ++ length=strlen(shared_secret); ++ for (i=0; i < length; i++) ++ { ++ uint8_t ++ b = (uint8_t) shared_secret[i]; ++ ++ k0^=b; ++ k0*=0x100000001b3ULL; ++ k1^=(uint64_t) b << ((i & 7)*8); ++ k1=(k1 << 5) | (k1 >> (64-5)); ++ } ++ (void) memcpy(key,&k0,8); ++ (void) memcpy(key+8,&k1,8); ++} ++ ++static inline uint64_t GenerateSessionKey(const char *shared_secret, ++ const unsigned char *nonce,size_t length) ++{ ++ uint8_t ++ key[16]; ++ ++ DeriveSIPKeyFromSecret(shared_secret,key); ++ return(SIPHash24(key,nonce,length)); ++} ++ + static int ConnectPixelCacheServer(const char *hostname,const int port, +- size_t *session_key,ExceptionInfo *exception) ++ uint64_t *session_key,ExceptionInfo *exception) + { ++#if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) + char ++ *message, + service[MagickPathExtent], + *shared_secret; + +@@ -226,42 +449,44 @@ static int ConnectPixelCacheServer(const char *hostname,const int port, + SOCKET_TYPE + client_socket; + +- StringInfo +- *nonce; +- + ssize_t + count; + + struct addrinfo +- hint, ++ hints, + *result; + ++ unsigned char ++ nonce[DPCSessionKeyLength]; ++ + /* +- Connect to distributed pixel cache and get session key. ++ Connect to distributed pixel cache server and get session key. + */ + *session_key=0; + #if defined(MAGICKCORE_HAVE_WINSOCK2) + InitializeWinsock2(MagickTrue); + #endif +- (void) memset(&hint,0,sizeof(hint)); +- hint.ai_family=AF_INET; +- hint.ai_socktype=SOCK_STREAM; +- hint.ai_flags=AI_PASSIVE; ++ (void) memset(&hints,0,sizeof(hints)); ++ hints.ai_family=AF_INET; ++ hints.ai_socktype=SOCK_STREAM; ++ hints.ai_flags=AI_PASSIVE; + (void) FormatLocaleString(service,MagickPathExtent,"%d",port); +- status=getaddrinfo(hostname,service,&hint,&result); ++ status=getaddrinfo(hostname,service,&hints,&result); + if (status != 0) + { + (void) ThrowMagickException(exception,GetMagickModule(),CacheError, +- "DistributedPixelCache","'%s': %s",hostname,GetExceptionMessage(errno)); ++ "DistributedPixelCache","'%s': %s",hostname,gai_strerror(status)); + return(-1); + } +- client_socket=socket(result->ai_family,result->ai_socktype, ++ client_socket=(SOCKET_TYPE) socket(result->ai_family,result->ai_socktype, + result->ai_protocol); + if (client_socket == -1) + { + freeaddrinfo(result); ++ message=GetExceptionMessage(errno); + (void) ThrowMagickException(exception,GetMagickModule(),CacheError, +- "DistributedPixelCache","'%s': %s",hostname,GetExceptionMessage(errno)); ++ "DistributedPixelCache","'%s': %s",hostname,message); ++ message=DestroyString(message); + return(-1); + } + status=connect(client_socket,result->ai_addr,(socklen_t) result->ai_addrlen); +@@ -269,40 +494,56 @@ static int ConnectPixelCacheServer(const char *hostname,const int port, + if (status == -1) + { + CLOSE_SOCKET(client_socket); ++ message=GetExceptionMessage(errno); + (void) ThrowMagickException(exception,GetMagickModule(),CacheError, +- "DistributedPixelCache","'%s': %s",hostname,GetExceptionMessage(errno)); ++ "DistributedPixelCache","'%s': %s",hostname,message); ++ message=DestroyString(message); + return(-1); + } +- count=recv(client_socket,(char *) session_key,sizeof(*session_key),0); +- if (count == -1) ++ /* ++ Receive server nonce. ++ */ ++ count=recv(client_socket,(char *) nonce,sizeof(nonce),0); ++ if (count != (ssize_t) sizeof(nonce)) + { + CLOSE_SOCKET(client_socket); ++ message=GetExceptionMessage(errno); + (void) ThrowMagickException(exception,GetMagickModule(),CacheError, +- "DistributedPixelCache","'%s': %s",hostname,GetExceptionMessage(errno)); ++ "DistributedPixelCache","'%s': %s",hostname,message); ++ message=DestroyString(message); + return(-1); + } + /* +- Authenticate client session key to server session key. ++ Compute keyed hash(shared_secret,nonce). + */ + shared_secret=GetPolicyValue("cache:shared-secret"); +- if (shared_secret == (char *) NULL) ++ if (shared_secret == (const char *) NULL) + { + CLOSE_SOCKET(client_socket); + (void) ThrowMagickException(exception,GetMagickModule(),CacheError, + "DistributedPixelCache","'%s': shared secret required",hostname); + return(-1); + } +- nonce=StringToStringInfo(shared_secret); +- if (GetMagickSignature(nonce) != *session_key) ++ *session_key=GenerateSessionKey(shared_secret,nonce,sizeof(nonce)); ++ shared_secret=DestroyString(shared_secret); ++ /* ++ Send keyed hash back to client. ++ */ ++ count=send(client_socket,(char *) session_key,sizeof(*session_key), ++ MSG_NOSIGNAL); ++ if (count != (ssize_t) sizeof(*session_key)) + { + CLOSE_SOCKET(client_socket); + (void) ThrowMagickException(exception,GetMagickModule(),CacheError, +- "DistributedPixelCache","'%s' authentication failed",hostname); ++ "DistributedPixelCache","'%s': authentication failed",hostname); + return(-1); + } +- shared_secret=DestroyString(shared_secret); +- nonce=DestroyStringInfo(nonce); +- return(client_socket); ++ return((int) client_socket); ++#else ++ (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError, ++ "DelegateLibrarySupportNotBuiltIn","distributed pixel cache"); ++ return(-1); ++#endif + } + #endif + +@@ -334,12 +575,16 @@ static char *GetHostname(int *port,ExceptionInfo *exception) + (void) SubstituteString(&hosts,","," "); + hostlist=StringToArgv(hosts,&argc); + hosts=DestroyString(hosts); +- if (hostlist == (char **) NULL) ++ if ((hostlist == (char **) NULL) || ((argc-1) == 0)) + { + *port=DPCPort; + return(AcquireString(DPCHostname)); + } +- hosts=AcquireString(hostlist[(id++ % ((size_t) argc-1))+1]); ++ { ++ size_t host_count = (size_t) argc-1; ++ size_t index = (id++ % host_count)+1; ++ hosts=AcquireString(hostlist[index]); ++ } + for (i=0; i < (ssize_t) argc; i++) + hostlist[i]=DestroyString(hostlist[i]); + hostlist=(char **) RelinquishMagickMemory(hostlist); +@@ -354,7 +599,7 @@ static char *GetHostname(int *port,ExceptionInfo *exception) + if (hostlist[2] == (char *) NULL) + *port=DPCPort; + else +- *port=StringToLong(hostlist[2]); ++ *port=(int) StringToLong(hostlist[2]); + for (i=0; i < (ssize_t) argc; i++) + hostlist[i]=DestroyString(hostlist[i]); + hostlist=(char **) RelinquishMagickMemory(hostlist); +@@ -370,7 +615,7 @@ MagickPrivate DistributeCacheInfo *AcquireDistributeCacheInfo( + DistributeCacheInfo + *server_info; + +- size_t ++ uint64_t + session_key; + + /* +@@ -428,7 +673,7 @@ MagickPrivate DistributeCacheInfo *DestroyDistributeCacheInfo( + assert(server_info != (DistributeCacheInfo *) NULL); + assert(server_info->signature == MagickCoreSignature); + #if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) +- if (server_info->file > 0) ++ if (server_info->file >= 0) + CLOSE_SOCKET(server_info->file); + #endif + server_info->signature=(~MagickCoreSignature); +@@ -463,7 +708,7 @@ MagickPrivate DistributeCacheInfo *DestroyDistributeCacheInfo( + */ + + #if !defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) +-static inline MagickOffsetType dpc_send(int magick_unused(file), ++static inline MagickOffsetType dpc_send(SOCKET_TYPE magick_unused(file), + const MagickSizeType magick_unused(length), + const void *magick_restrict magick_unused(message)) + { +@@ -473,8 +718,8 @@ static inline MagickOffsetType dpc_send(int magick_unused(file), + return(-1); + } + #else +-static inline MagickOffsetType dpc_send(int file,const MagickSizeType length, +- const void *magick_restrict message) ++static inline MagickOffsetType dpc_send(SOCKET_TYPE file, ++ const MagickSizeType length,const void *magick_restrict message) + { + MagickOffsetType + i; +@@ -488,8 +733,8 @@ static inline MagickOffsetType dpc_send(int file,const MagickSizeType length, + count=0; + for (i=0; i < (MagickOffsetType) length; i+=count) + { +- count=(MagickOffsetType) send(file,(char *) message+i,(LENGTH_TYPE) +- MagickMin(length-(MagickSizeType) i,(MagickSizeType) MagickMaxBufferExtent), ++ count=(ssize_t) send(file,(const char *) message+i,(LENGTH_TYPE) MagickMin( ++ length-(MagickSizeType) i,(MagickSizeType) MagickMaxBufferExtent), + MSG_NOSIGNAL); + if (count <= 0) + { +@@ -512,7 +757,7 @@ MagickExport void DistributePixelCacheServer(const int magick_unused(port), + } + #else + static MagickBooleanType DestroyDistributeCache(SplayTreeInfo *registry, +- const size_t session_key) ++ const uint64_t session_key) + { + MagickAddressType + key = (MagickAddressType) session_key; +@@ -523,8 +768,8 @@ static MagickBooleanType DestroyDistributeCache(SplayTreeInfo *registry, + return(DeleteNodeFromSplayTree(registry,(const void *) key)); + } + +-static MagickBooleanType OpenDistributeCache(SplayTreeInfo *registry,int file, +- const size_t session_key,ExceptionInfo *exception) ++static MagickBooleanType OpenDistributeCache(SplayTreeInfo *registry, ++ SOCKET_TYPE file,const uint64_t session_key,ExceptionInfo *exception) + { + Image + *image; +@@ -555,9 +800,12 @@ static MagickBooleanType OpenDistributeCache(SplayTreeInfo *registry,int file, + sizeof(image->alpha_trait)+sizeof(image->channels)+sizeof(image->columns)+ + sizeof(image->rows)+sizeof(image->number_channels)+MaxPixelChannels* + sizeof(*image->channel_map)+sizeof(image->metacontent_extent); +- count=dpc_read(file,length,message); ++ count=dpc_receive(file,length,message); + if (count != (MagickOffsetType) length) +- return(MagickFalse); ++ { ++ image=DestroyImage(image); ++ return(MagickFalse); ++ } + /* + Deserialize the image attributes. + */ +@@ -582,8 +830,16 @@ static MagickBooleanType OpenDistributeCache(SplayTreeInfo *registry,int file, + (void) memcpy(&image->metacontent_extent,p,sizeof(image->metacontent_extent)); + p+=(ptrdiff_t) sizeof(image->metacontent_extent); + if (SyncImagePixelCache(image,exception) == MagickFalse) +- return(MagickFalse); ++ { ++ image=DestroyImage(image); ++ return(MagickFalse); ++ } + status=AddValueToSplayTree(registry,(const void *) key,image); ++ if (status == MagickFalse) ++ { ++ image=DestroyImage(image); ++ return(MagickFalse); ++ } + return(status); + } + +@@ -605,7 +861,7 @@ static inline MagickBooleanType ValidateDistributedPixelCache( + } + + static MagickBooleanType ReadDistributeCacheMetacontent(SplayTreeInfo *registry, +- int file,const size_t session_key,ExceptionInfo *exception) ++ SOCKET_TYPE file,const uint64_t session_key,ExceptionInfo *exception) + { + const Quantum + *p; +@@ -643,7 +899,7 @@ static MagickBooleanType ReadDistributeCacheMetacontent(SplayTreeInfo *registry, + return(MagickFalse); + length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+ + sizeof(region.y)+sizeof(length); +- count=dpc_read(file,length,message); ++ count=dpc_receive(file,length,message); + if (count != (MagickOffsetType) length) + return(MagickFalse); + q=message; +@@ -672,7 +928,7 @@ static MagickBooleanType ReadDistributeCacheMetacontent(SplayTreeInfo *registry, + } + + static MagickBooleanType ReadDistributeCachePixels(SplayTreeInfo *registry, +- int file,const size_t session_key,ExceptionInfo *exception) ++ SOCKET_TYPE file,const uint64_t session_key,ExceptionInfo *exception) + { + const Quantum + *p; +@@ -707,7 +963,7 @@ static MagickBooleanType ReadDistributeCachePixels(SplayTreeInfo *registry, + return(MagickFalse); + length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+ + sizeof(region.y)+sizeof(length); +- count=dpc_read(file,length,message); ++ count=dpc_receive(file,length,message); + if (count != (MagickOffsetType) length) + return(MagickFalse); + q=message; +@@ -740,7 +996,7 @@ static void *RelinquishImageRegistry(void *image) + } + + static MagickBooleanType WriteDistributeCacheMetacontent( +- SplayTreeInfo *registry,int file,const size_t session_key, ++ SplayTreeInfo *registry,SOCKET_TYPE file,const uint64_t session_key, + ExceptionInfo *exception) + { + Image +@@ -753,7 +1009,6 @@ static MagickBooleanType WriteDistributeCacheMetacontent( + count; + + MagickSizeType +- extent, + length; + + Quantum +@@ -762,6 +1017,9 @@ static MagickBooleanType WriteDistributeCacheMetacontent( + RectangleInfo + region; + ++ size_t ++ per_pixel; ++ + unsigned char + message[MagickPathExtent], + *metacontent, +@@ -770,13 +1028,12 @@ static MagickBooleanType WriteDistributeCacheMetacontent( + /* + Write distributed pixel cache metacontent. + */ +- key=session_key; + image=(Image *) GetValueFromSplayTree(registry,(const void *) key); + if (image == (Image *) NULL) + return(MagickFalse); + length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+ + sizeof(region.y)+sizeof(length); +- count=dpc_read(file,length,message); ++ count=dpc_receive(file,length,message); + if (count != (MagickOffsetType) length) + return(MagickFalse); + p=message; +@@ -789,8 +1046,8 @@ static MagickBooleanType WriteDistributeCacheMetacontent( + (void) memcpy(®ion.y,p,sizeof(region.y)); + p+=(ptrdiff_t) sizeof(region.y); + (void) memcpy(&length,p,sizeof(length)); +- extent=((MagickSizeType) region.width*region.height*sizeof(Quantum)); +- if (length > extent) ++ per_pixel=image->number_meta_channels*sizeof(Quantum); ++ if (ValidateDistributedPixelCache(®ion,per_pixel,length) == MagickFalse) + return(MagickFalse); + p+=(ptrdiff_t) sizeof(length); + q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height, +@@ -798,14 +1055,14 @@ static MagickBooleanType WriteDistributeCacheMetacontent( + if (q == (Quantum *) NULL) + return(MagickFalse); + metacontent=(unsigned char *) GetAuthenticMetacontent(image); +- count=dpc_read(file,length,metacontent); ++ count=dpc_receive(file,length,metacontent); + if (count != (MagickOffsetType) length) + return(MagickFalse); + return(SyncAuthenticPixels(image,exception)); + } + + static MagickBooleanType WriteDistributeCachePixels(SplayTreeInfo *registry, +- int file,const size_t session_key,ExceptionInfo *exception) ++ SOCKET_TYPE file,const uint64_t session_key,ExceptionInfo *exception) + { + Image + *image; +@@ -817,7 +1074,6 @@ static MagickBooleanType WriteDistributeCachePixels(SplayTreeInfo *registry, + count; + + MagickSizeType +- extent, + length; + + Quantum +@@ -826,6 +1082,9 @@ static MagickBooleanType WriteDistributeCachePixels(SplayTreeInfo *registry, + RectangleInfo + region; + ++ size_t ++ per_pixel; ++ + unsigned char + message[MagickPathExtent], + *p; +@@ -838,7 +1097,7 @@ static MagickBooleanType WriteDistributeCachePixels(SplayTreeInfo *registry, + return(MagickFalse); + length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+ + sizeof(region.y)+sizeof(length); +- count=dpc_read(file,length,message); ++ count=dpc_receive(file,length,message); + if (count != (MagickOffsetType) length) + return(MagickFalse); + p=message; +@@ -851,37 +1110,59 @@ static MagickBooleanType WriteDistributeCachePixels(SplayTreeInfo *registry, + (void) memcpy(®ion.y,p,sizeof(region.y)); + p+=(ptrdiff_t) sizeof(region.y); + (void) memcpy(&length,p,sizeof(length)); +- extent=((MagickSizeType) region.width*region.height*image->number_channels* +- sizeof(Quantum)); +- if (length > extent) ++ per_pixel=image->number_channels*sizeof(Quantum); ++ if (ValidateDistributedPixelCache(®ion,per_pixel,length) == MagickFalse) + return(MagickFalse); + p+=(ptrdiff_t) sizeof(length); + q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height, + exception); + if (q == (Quantum *) NULL) + return(MagickFalse); +- count=dpc_read(file,length,(unsigned char *) q); ++ count=dpc_receive(file,length,(unsigned char *) q); + if (count != (MagickOffsetType) length) + return(MagickFalse); + return(SyncAuthenticPixels(image,exception)); + } +-static HANDLER_RETURN_TYPE DistributePixelCacheClient(void *socket_arg) ++ ++static void LockDPCSemaphore(void) + { +- char +- *shared_secret; ++ if (dpc_semaphore == (SemaphoreInfo *) NULL) ++ ActivateSemaphoreInfo(&dpc_semaphore); ++ LockSemaphoreInfo(dpc_semaphore); ++} + ++static void AuthenticateDPCClient(void) ++{ ++ LockDPCSemaphore(); ++ if (dpc_unauthenticated_clients != 0) ++ dpc_unauthenticated_clients--; ++ UnlockSemaphoreInfo(dpc_semaphore); ++} ++ ++static void RelinquishDPCClient(const MagickBooleanType unauthenticated) ++{ ++ LockDPCSemaphore(); ++ if ((unauthenticated != MagickFalse) && (dpc_unauthenticated_clients != 0)) ++ dpc_unauthenticated_clients--; ++ if (dpc_clients != 0) ++ dpc_clients--; ++ UnlockSemaphoreInfo(dpc_semaphore); ++} ++ ++static HANDLER_RETURN_TYPE DistributePixelCacheConnectionHandler(void *socket_arg) ++{ + ExceptionInfo + *exception; +- ++ + MagickBooleanType ++ authenticated = MagickFalse, + status = MagickFalse; + + MagickOffsetType + count; + +- size_t +- key, +- session_key; ++ RandomInfo ++ *random_info; + + SOCKET_TYPE + client_socket, +@@ -891,36 +1172,70 @@ static HANDLER_RETURN_TYPE DistributePixelCacheClient(void *socket_arg) + *registry; + + StringInfo +- *nonce; ++ *entropy; ++ ++ uint64_t ++ key, ++ session_key; + + unsigned char +- command; ++ command, ++ nonce[DPCSessionKeyLength]; + +- /* +- Generate session key. +- */ + client_socket=(*client_socket_ptr); + client_socket_ptr=(SOCKET_TYPE *) RelinquishMagickMemory(client_socket_ptr); +- shared_secret = GetPolicyValue("cache:shared-secret"); +- if (shared_secret == (char *) NULL) +- ThrowFatalException(CacheFatalError,"shared secret required"); +- nonce=StringToStringInfo(shared_secret); +- shared_secret=DestroyString(shared_secret); +- session_key=GetMagickSignature(nonce); +- nonce=DestroyStringInfo(nonce); +- exception=AcquireExceptionInfo(); + /* +- Process client commands. ++ Generate random nonce. ++ */ ++ random_info=AcquireRandomInfo(); ++ entropy=GetRandomKey(random_info,sizeof(nonce)); ++ (void) memcpy(nonce,GetStringInfoDatum(entropy),sizeof(nonce)); ++ entropy=DestroyStringInfo(entropy); ++ random_info=DestroyRandomInfo(random_info); ++ /* ++ Derive session key. ++ */ ++ session_key=GenerateSessionKey(dpc_shared_secret,nonce,sizeof(nonce)); ++ /* ++ Send nonce to client. + */ ++ count=dpc_send(client_socket,sizeof(nonce),nonce); ++ if (count != (MagickOffsetType) sizeof(nonce)) ++ { ++ CLOSE_SOCKET(client_socket); ++ RelinquishDPCClient(MagickTrue); ++ return(HANDLER_RETURN_VALUE); ++ } ++ /* ++ Receive client's keyed hash. ++ */ ++ count=dpc_receive_deadline(client_socket,sizeof(key),(unsigned char *) &key, ++ (double) time((time_t *) NULL)+5.0); ++ if ((count != (MagickOffsetType) sizeof(key)) || (key != session_key)) ++ { ++ CLOSE_SOCKET(client_socket); ++ RelinquishDPCClient(MagickTrue); ++ return(HANDLER_RETURN_VALUE); ++ } ++ AuthenticateDPCClient(); ++ authenticated=MagickTrue; ++ exception=AcquireExceptionInfo(); + registry=NewSplayTree((int (*)(const void *,const void *)) NULL, + (void *(*)(void *)) NULL,RelinquishImageRegistry); +- count=dpc_send(client_socket,sizeof(session_key),&session_key); ++ /* ++ Command loop. ++ */ + for (status=MagickFalse; ; ) + { +- count=dpc_read(client_socket,1,(unsigned char *) &command); ++ /* ++ Each command must echo the authenticated session key. ++ */ ++ count=dpc_receive_deadline(client_socket,1,(unsigned char *) &command, ++ (double) time((time_t *) NULL)+5.0); + if (count <= 0) + break; +- count=dpc_read(client_socket,sizeof(key),(unsigned char *) &key); ++ count=dpc_receive_deadline(client_socket,sizeof(key),(unsigned char *) &key, ++ (double) time((time_t *) NULL)+5.0); + if ((count != (MagickOffsetType) sizeof(key)) || (key != session_key)) + break; + switch (command) +@@ -929,7 +1244,7 @@ static HANDLER_RETURN_TYPE DistributePixelCacheClient(void *socket_arg) + { + status=OpenDistributeCache(registry,client_socket,session_key, + exception); +- count=dpc_send(client_socket,sizeof(status),&status); ++ dpc_send(client_socket,sizeof(status),&status); + break; + } + case 'r': +@@ -971,9 +1286,81 @@ static HANDLER_RETURN_TYPE DistributePixelCacheClient(void *socket_arg) + CLOSE_SOCKET(client_socket); + exception=DestroyExceptionInfo(exception); + registry=DestroySplayTree(registry); ++ RelinquishDPCClient(authenticated == MagickFalse ? MagickTrue : ++ MagickFalse); + return(HANDLER_RETURN_VALUE); + } + ++static size_t GetDPCPolicyLimit(const char *name,const size_t default_limit) ++{ ++ char ++ policy_name[MagickPathExtent], ++ *policy_value; ++ ++ size_t ++ limit; ++ ++ limit=default_limit; ++ (void) FormatLocaleString(policy_name,MagickPathExtent,"cache:%s",name); ++ policy_value=GetPolicyValue(policy_name); ++ if (policy_value != (char *) NULL) ++ { ++ char ++ *q; ++ ++ unsigned long ++ policy_limit; ++ ++ errno=0; ++ policy_limit=strtoul(policy_value,&q,10); ++ if ((errno == 0) && (q != policy_value) && (policy_limit != 0)) ++ limit=(size_t) policy_limit; ++ policy_value=DestroyString(policy_value); ++ } ++ return(limit); ++} ++ ++static size_t GetMaxDPCClients(void) ++{ ++ return(GetDPCPolicyLimit("max-dpc-clients",DPCMaxClientWorkers)); ++} ++ ++static size_t GetMaxDPCUnauthenticatedClients(void) ++{ ++ size_t ++ client_workers, ++ unauthenticated_workers; ++ ++ client_workers=GetMaxDPCClients(); ++ unauthenticated_workers=GetDPCPolicyLimit("max-dpc-unauthenticated-clients", ++ DPCMaxUnauthenticatedClientWorkers); ++ return(MagickMin(unauthenticated_workers,client_workers)); ++} ++ ++static MagickBooleanType AcquireDPCClientWorker(void) ++{ ++ MagickBooleanType ++ status; ++ ++ size_t ++ max_dpc_clients, ++ unauthenticated_worker_limit; ++ ++ status=MagickFalse; ++ max_dpc_clients=GetMaxDPCClients(); ++ unauthenticated_worker_limit=GetMaxDPCUnauthenticatedClients(); ++ LockDPCSemaphore(); ++ if ((dpc_clients < max_dpc_clients) && ++ (dpc_unauthenticated_clients < unauthenticated_worker_limit)) ++ { ++ dpc_clients++; ++ dpc_unauthenticated_clients++; ++ status=MagickTrue; ++ } ++ UnlockSemaphoreInfo(dpc_semaphore); ++ return(status); ++} ++ + MagickExport void DistributePixelCacheServer(const int port, + ExceptionInfo *exception) + { +@@ -1015,24 +1402,28 @@ MagickExport void DistributePixelCacheServer(const int port, + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickCoreSignature); + magick_unreferenced(exception); ++ dpc_shared_secret=GetPolicyValue("cache:shared-secret"); ++ if (dpc_shared_secret == (char *) NULL) ++ ThrowFatalException(CacheFatalError,"no shared secret"); + #if defined(MAGICKCORE_HAVE_WINSOCK2) + InitializeWinsock2(MagickFalse); + #endif +- memset(&hint,0,sizeof(hint)); ++ (void) memset(&hint,0,sizeof(hint)); + hint.ai_family=AF_INET; + hint.ai_socktype=SOCK_STREAM; + hint.ai_flags=AI_PASSIVE; + FormatLocaleString(service,MagickPathExtent,"%d",port); + status=getaddrinfo(NULL,service,&hint,&result); + if (status != 0) +- ThrowFatalException(CacheFatalError, "UnableToListen"); ++ ThrowFatalException(CacheFatalError,"UnableToListen"); + server_socket=(SOCKET_TYPE) 0; + for (p=result; p != NULL; p=p->ai_next) + { + int + one = 1; + +- server_socket=socket(p->ai_family,p->ai_socktype,p->ai_protocol); ++ server_socket=(SOCKET_TYPE) socket(p->ai_family,p->ai_socktype, ++ p->ai_protocol); + if (server_socket == -1) + continue; + status=setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,(char *) &one, +@@ -1042,6 +1433,7 @@ MagickExport void DistributePixelCacheServer(const int port, + CLOSE_SOCKET(server_socket); + continue; + } ++ SetSocketReceiveTimeout(server_socket,5.0); + status=bind(server_socket,p->ai_addr,(socklen_t) p->ai_addrlen); + if (status == -1) + { +@@ -1063,7 +1455,7 @@ MagickExport void DistributePixelCacheServer(const int port, + for ( ; ; ) + { + SOCKET_TYPE +- *client_socket_ptr; ++ *client_socket_ptr; + + socklen_t + length = (socklen_t) sizeof(address); +@@ -1071,29 +1463,48 @@ MagickExport void DistributePixelCacheServer(const int port, + client_socket_ptr=(SOCKET_TYPE *) AcquireMagickMemory(sizeof(SOCKET_TYPE)); + if (client_socket_ptr == NULL) + continue; /* skip connection */ +- *client_socket_ptr=accept(server_socket,(struct sockaddr *) &address, +- &length); ++ *client_socket_ptr=(SOCKET_TYPE) accept(server_socket,(struct sockaddr *) ++ &address,&length); + if (*client_socket_ptr == -1) + { + client_socket_ptr=(SOCKET_TYPE *) RelinquishMagickMemory( + client_socket_ptr); + continue; + } ++ if (AcquireDPCClientWorker() == MagickFalse) ++ { ++ CLOSE_SOCKET(*client_socket_ptr); ++ client_socket_ptr=(SOCKET_TYPE *) RelinquishMagickMemory( ++ client_socket_ptr); ++ continue; ++ } ++ SetSocketReceiveTimeout(*client_socket_ptr,5.0); ++ if (status == -1) ++ { ++ CLOSE_SOCKET(*client_socket_ptr); ++ RelinquishDPCClient(MagickTrue); ++ client_socket_ptr=(SOCKET_TYPE *) RelinquishMagickMemory( ++ client_socket_ptr); ++ continue; ++ } + #if defined(MAGICKCORE_THREAD_SUPPORT) +- status=pthread_create(&thread_id, &attributes,DistributePixelCacheClient, ++ status=pthread_create(&thread_id,&attributes,DistributePixelCacheConnectionHandler, + (void *) client_socket_ptr); + if (status != 0) + { + CLOSE_SOCKET(*client_socket_ptr); ++ RelinquishDPCClient(MagickTrue); + RelinquishMagickMemory(client_socket_ptr); +- ThrowFatalException(CacheFatalError,"UnableToCreateClientThread"); ++ continue; + } + #elif defined(_MSC_VER) +- if (CreateThread(0,0,DistributePixelCacheClient,(void*) client_socket_ptr,0,&threadID) == (HANDLE) NULL) ++ if (CreateThread(0,0,DistributePixelCacheConnectionHandler,(void*) client_socket_ptr, ++ 0,&threadID) == (HANDLE) NULL) + { + CLOSE_SOCKET(*client_socket_ptr); ++ RelinquishDPCClient(MagickTrue); + RelinquishMagickMemory(client_socket_ptr); +- ThrowFatalException(CacheFatalError,"UnableToCreateClientThread"); ++ continue; + } + #else + Not implemented! +@@ -1119,16 +1530,22 @@ MagickExport void DistributePixelCacheServer(const int port, + MagickPrivate void DistributeCacheTerminus(void) + { + #ifdef MAGICKCORE_HAVE_WINSOCK2 +- if (winsock2_semaphore == (SemaphoreInfo *) NULL) +- ActivateSemaphoreInfo(&winsock2_semaphore); +- LockSemaphoreInfo(winsock2_semaphore); ++ if (winsock_semaphore == (SemaphoreInfo *) NULL) ++ ActivateSemaphoreInfo(&winsock_semaphore); ++ LockSemaphoreInfo(winsock_semaphore); + if (wsaData != (WSADATA *) NULL) + { + WSACleanup(); + wsaData=(WSADATA *) RelinquishMagickMemory((void *) wsaData); + } +- UnlockSemaphoreInfo(winsock2_semaphore); +- RelinquishSemaphoreInfo(&winsock2_semaphore); ++ UnlockSemaphoreInfo(winsock_semaphore); ++ RelinquishSemaphoreInfo(&winsock_semaphore); ++#endif ++#if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) ++ if (dpc_shared_secret != (char *) NULL) ++ dpc_shared_secret=DestroyString(dpc_shared_secret); ++ if (dpc_semaphore != (SemaphoreInfo *) NULL) ++ RelinquishSemaphoreInfo(&dpc_semaphore); + #endif + } + +@@ -1299,7 +1716,7 @@ MagickPrivate MagickBooleanType OpenDistributePixelCache( + if (count != (MagickOffsetType) (p-message)) + return(MagickFalse); + status=MagickFalse; +- count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status); ++ count=dpc_receive(server_info->file,sizeof(status),(unsigned char *) &status); + if (count != (MagickOffsetType) sizeof(status)) + return(MagickFalse); + return(status); +@@ -1375,7 +1792,7 @@ MagickPrivate MagickOffsetType ReadDistributePixelCacheMetacontent( + count=dpc_send(server_info->file,(MagickSizeType) (p-message),message); + if (count != (MagickOffsetType) (p-message)) + return(-1); +- return(dpc_read(server_info->file,length,metacontent)); ++ return(dpc_receive(server_info->file,length,metacontent)); + } + + /* +@@ -1448,7 +1865,7 @@ MagickPrivate MagickOffsetType ReadDistributePixelCachePixels( + count=dpc_send(server_info->file,(MagickSizeType) (p-message),message); + if (count != (MagickOffsetType) (p-message)) + return(-1); +- return(dpc_read(server_info->file,length,pixels)); ++ return(dpc_receive(server_info->file,length,pixels)); + } + + /* +@@ -1501,7 +1918,7 @@ MagickPrivate MagickBooleanType RelinquishDistributePixelCache( + if (count != (MagickOffsetType) (p-message)) + return(MagickFalse); + status=MagickFalse; +- count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status); ++ count=dpc_receive(server_info->file,sizeof(status),(unsigned char *) &status); + if (count != (MagickOffsetType) sizeof(status)) + return(MagickFalse); + return(status); +diff --git a/MagickCore/distribute-cache.h b/MagickCore/distribute-cache.h +index c6ffb1f..ac1b4af 100644 +--- a/MagickCore/distribute-cache.h ++++ b/MagickCore/distribute-cache.h +@@ -5,7 +5,7 @@ + You may not use this file except in compliance with the License. You may + obtain a copy of the License at + +- https://imagemagick.org/script/license.php ++ https://imagemagick.org/license/ + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, diff -Nru imagemagick-7.1.1.43+dfsg1/debian/patches/series imagemagick-7.1.1.43+dfsg1/debian/patches/series --- imagemagick-7.1.1.43+dfsg1/debian/patches/series 2026-07-21 07:55:59.000000000 +0000 +++ imagemagick-7.1.1.43+dfsg1/debian/patches/series 2026-10-23 19:43:57.000000000 +0000 @@ -232,3 +232,61 @@ CVE-2026-61870.patch CVE-2026-61871.patch CVE-2026-61872.patch +CVE-2026-62343.patch +CVE-2026-62946.patch +CVE-2026-64685.patch +CVE-2026-62363_1.patch +CVE-2026-62363_2.patch +CVE-2026-86420.patch +CVE-2026-86421.patch +CVE-2026-86423.patch +CVE-2026-86424_pre1.patch +CVE-2026-86424_pre2.patch +CVE-2026-86424_pre3.patch +CVE-2026-86424_pre4.patch +CVE-2026-86424_pre5.patch +CVE-2026-86424_pre6.patch +CVE-2026-86424.patch +CVE-2026-86425.patch +CVE-2026-93586_1.patch +CVE-2026-93586_2.patch +CVE-2026-93587_1.patch +CVE-2026-93587_2.patch +CVE-2026-93588.patch +CVE-2026-93589.patch +CVE-2026-93590.patch +CVE-2026-102635_1.patch +CVE-2026-102635_2.patch +CVE-2026-102635_3.patch +CVE-2026-109261.patch +CVE-2026-107208_1.patch +CVE-2026-107208_2.patch +CVE-2026-106564.patch +CVE-2026-106565.patch +CVE-2026-106566.patch +CVE-2026-106567.patch +CVE-2026-106568.patch +port-distribute-cache-7.1.2.33.patch +CVE-2026-106571-pre1.patch +CVE-2026-106571.patch +CVE-2026-106572.patch +CVE-2026-106573.patch +CVE-2026-106574.patch +CVE-2026-106575.patch +CVE-2026-106576.patch +CVE-2026-106577_pre1.patch +CVE-2026-106577_1.patch +CVE-2026-106577_2.patch +CVE-2026-106578.patch +CVE-2026-25971-post1.patch +CVE-2026-106579-pre1.patch +CVE-2026-106579_1.patch +CVE-2026-106579_2.patch +CVE-2026-106580_1.patch +CVE-2026-106580_2.patch +CVE-2026-107209.patch +CVE-2026-107210-pre1.patch +CVE-2026-107210.patch +GHSA-83w9-w85j-h9jc.patch +GHSA-83w9-w85j-h9jc-1.patch +coders-mat-c-7.1.2.33.patch