Version in base suite: 6.9.11.60+dfsg-1.6+deb12u5 Version in overlay suite: 6.9.11.60+dfsg-1.6+deb12u7 Base version: imagemagick_6.9.11.60+dfsg-1.6+deb12u7 Target version: imagemagick_6.9.11.60+dfsg-1.6+deb12u8 Base file: /srv/ftp-master.debian.org/ftp/pool/main/i/imagemagick/imagemagick_6.9.11.60+dfsg-1.6+deb12u7.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/i/imagemagick/imagemagick_6.9.11.60+dfsg-1.6+deb12u8.dsc changelog | 76 patches/CVE-2026-25796_post1.patch | 27 patches/CVE-2026-25985.patch | 65 patches/CVE-2026-25985_post1.patch | 49 patches/CVE-2026-26284.patch | 26 patches/CVE-2026-26284_pre1.patch | 86 patches/CVE-2026-26983.patch | 36 patches/CVE-2026-28494.patch | 59 patches/CVE-2026-28686_28687_28688_28689_28690_28692.patch | 819 ++++ patches/CVE-2026-28693_1.patch | 100 patches/CVE-2026-28693_2.patch | 26 patches/CVE-2026-28693_pre1.patch | 49 patches/CVE-2026-30883.patch | 43 patches/CVE-2026-30936.patch | 45 patches/CVE-2026-30937.patch | 27 patches/CVE-2026-31853.patch | 33 patches/CVE-2026-32259.patch | 45 patches/CVE-2026-32636.patch | 589 +++ patches/CVE-2026-33535.patch | 40 patches/CVE-2026-33536.patch | 42 patches/GetMagickThreadFilename.patch | 45 patches/i386-fix.patch | 29 patches/port-msl-svg-to-6.9.13-41.patch | 2270 +++++++++++++ patches/revert-delegate-change.patch | 39 patches/series | 23 rules | 2 26 files changed, 4689 insertions(+), 1 deletion(-) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp2jgtmdiy/imagemagick_6.9.11.60+dfsg-1.6+deb12u7.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp2jgtmdiy/imagemagick_6.9.11.60+dfsg-1.6+deb12u8.dsc: no acceptable signature found diff -Nru imagemagick-6.9.11.60+dfsg/debian/changelog imagemagick-6.9.11.60+dfsg/debian/changelog --- imagemagick-6.9.11.60+dfsg/debian/changelog 2026-03-06 16:54:58.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/changelog 2026-04-12 19:57:53.000000000 +0000 @@ -1,3 +1,79 @@ +imagemagick (8:6.9.11.60+dfsg-1.6+deb12u8) bookworm-security; urgency=high + + * Fix a regression for CVE-2026-25796 + * Fix CVE-2026-25985: + A crafted SVG file containing an malicious element causes ImageMagick + to attempt to allocate ~674 GB of memory, leading to an out-of-memory abort. + * Fix CVE-2026-26284: + ImageMagick lacks proper boundary checking when processing Huffman-coded + data from PCD (Photo CD) files. The decoder contains an function that + has an incorrect initialization that could cause an out of bounds read. + * Fix CVE-2026-26983: + The MSL interpreter crashes when processing a invalid `` + element that causes it to use an image after it has been freed. + * Fix CVE-2026-28494: + A stack buffer overflow exists in ImageMagick's morphology kernel + parsing functions. User-controlled kernel strings exceeding a buffer + are copied into fixed-size stack buffers via memcpy without bounds + checking, resulting in stack corruption. + * Fix CVE-2026-28686: + A heap-buffer-overflow vulnerability exists in the PCL encode due to + an undersized output buffer allocation. + * Fix CVE-2026-28687: + A heap use-after-free vulnerability in ImageMagick's MSL decoder + allows an attacker to trigger access to freed memory by crafting + an MSL file + * Fix CVE-2026-28688: + A heap-use-after-free vulnerability exists in the MSL encoder, + where a cloned image is destroyed twice. The MSL coder does not + support writing MSL so the write capability has been removed + * Fix CVE-2026-28689: + domain="path" authorization is checked before final file open/use. + A symlink swap between check-time and use-time bypasses + policy-denied read/write + * Fix CVE-2026-28690: + A stack buffer overflow vulnerability exists in the MNG encoder. + There is a bounds checks missing that could corrupting the stack + with attacker-controlled data. + * Fix CVE-2026-28691: + An uninitialized pointer dereference vulnerability exists + in the JBIG decoder due to a missing check. + * Fix CVE-2026-28692: + MAT decoder uses 32-bit arithmetic due to incorrect parenthesization + resulting in a heap over-read. + * Fix CVE-2026-28693: + An integer overflow in DIB coder can result in out of bounds + read or write. + * Fix CVE-2026-30883: + An extremely large image profile could result in a heap overflow + when encoding a PNG image + * Fix CVE-2026-30936: + A crafted image could cause an out of bounds heap write inside the + WaveletDenoiseImage method. When processing a crafted image with the + -wavelet-denoise operation an out of bounds write can occur. + * Fix CVE-2026-30937: + A 32-bit unsigned integer overflow in the XWD (X Windows) encoder + can cause an undersized heap buffer allocation. When writing + a extremely large image an out of bounds heap write can occur. + * Fix CVE-2026-31853: + An overflow on 32-bit systems can cause a crash in the SFW decoder + when processing extremely large images. + * Fix CVE-2026-32259: + When a memory allocation fails in the sixel encoder it would be + possible to write past the end of a buffer on the stack. + * Fix CVE-2026-32636: + The NewXMLTree method contains a bug that could result + in a crash due to an out of write bounds of a single zero byte + * Fix CVE-2026-33535: + An out-of-bounds write of a zero byte exists in the X11 `display` + interaction path that could lead to a crash. + * Fix CVE-2026-33536: + Due to an incorrect return value on certain platforms a pointer is + incremented past the end of a buffer that is on the stack and + that could result in an out of bounds write + + -- Bastien Roucariès Sun, 12 Apr 2026 21:57:53 +0200 + imagemagick (8:6.9.11.60+dfsg-1.6+deb12u7) bookworm-security; urgency=high * Fix CVE-2026-24481: diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-25796_post1.patch imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-25796_post1.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-25796_post1.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-25796_post1.patch 2026-04-12 19:56:19.000000000 +0000 @@ -0,0 +1,27 @@ +From: Ian Constantin +Date: Thu, 26 Feb 2026 19:16:22 +0200 +Subject: coders/stegano.c: destroy watermark image prior to throwing + exception (#398) + +(cherry picked from commit 2024ae1d10a7481d04fb717b3fa9170fd294a8f3) + +origin: https://github.com/ImageMagick/ImageMagick6/commit/2024ae1d10a7481d04fb717b3fa9170fd294a8f3 +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-g2pr-qxjg-7r2w +--- + coders/stegano.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/coders/stegano.c b/coders/stegano.c +index f92fb5a..ed756ef 100644 +--- a/coders/stegano.c ++++ b/coders/stegano.c +@@ -154,8 +154,8 @@ static Image *ReadSTEGANOImage(const ImageInfo *image_info, + watermark->depth=MAGICKCORE_QUANTUM_DEPTH; + if (AcquireImageColormap(image,MaxColormapSize) == MagickFalse) + { +- ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); + watermark=DestroyImage(watermark); ++ ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); + } + if (image_info->ping != MagickFalse) + { diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-25985.patch imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-25985.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-25985.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-25985.patch 2026-04-12 19:56:19.000000000 +0000 @@ -0,0 +1,65 @@ +From: Cristy +Date: Sat, 7 Feb 2026 22:31:01 -0500 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-v7g2-m8c5-mf84 + +a crafted SVG file containing an malicious element causes ImageMagick to attempt to allocate ~674 GB of memory, leading to an out-of-memory abort. + +(cherry picked from commit d186398f2c2f06692dc18eaf781042368c6659a5) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-v7g2-m8c5-mf84 +origin: https://github.com/ImageMagick/ImageMagick6/commit/d186398f2c2f06692dc18eaf781042368c6659a5 +--- + magick/draw.c | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +diff --git a/magick/draw.c b/magick/draw.c +index 72ad60c..a65776a 100644 +--- a/magick/draw.c ++++ b/magick/draw.c +@@ -2257,6 +2257,8 @@ static MagickBooleanType CheckPrimitiveExtent(MVGInfo *mvg_info, + */ + extent=(double) mvg_info->offset+pad+PrimitiveExtentPad+1.0; + quantum=sizeof(**mvg_info->primitive_info); ++ if ((extent >= (double) GetMaxMemoryRequest()) || (IsNaN(extent) != 0)) ++ return(MagickFalse); + if (extent <= (double) *mvg_info->extent) + return(MagickTrue); + if (extent == (double) CastDoubleToLong(extent)) +@@ -6222,7 +6224,7 @@ static MagickBooleanType TraceBezier(MVGInfo *mvg_info, + for (j=i+1; j < (ssize_t) number_coordinates; j++) + { + alpha=fabs(primitive_info[j].point.x-primitive_info[i].point.x); +- if (alpha > (double) MAGICK_SSIZE_MAX) ++ if (alpha > (double) GetMaxMemoryRequest()) + { + (void) ThrowMagickException(mvg_info->exception,GetMagickModule(), + ResourceLimitError,"MemoryAllocationFailed","`%s'",""); +@@ -6231,19 +6233,20 @@ static MagickBooleanType TraceBezier(MVGInfo *mvg_info, + if (alpha > (double) quantum) + quantum=(size_t) alpha; + alpha=fabs(primitive_info[j].point.y-primitive_info[i].point.y); +- if (alpha > (double) MAGICK_SSIZE_MAX) +- { +- (void) ThrowMagickException(mvg_info->exception,GetMagickModule(), +- ResourceLimitError,"MemoryAllocationFailed","`%s'",""); +- return(MagickFalse); +- } + if (alpha > (double) quantum) + quantum=(size_t) alpha; + } + } ++ primitive_info=(*mvg_info->primitive_info)+mvg_info->offset; ++ quantum=MagickMin(quantum/number_coordinates,BezierQuantum); ++ if (quantum > (double) GetMaxMemoryRequest()) ++ { ++ (void) ThrowMagickException(mvg_info->exception,GetMagickModule(), ++ ResourceLimitError,"MemoryAllocationFailed","`%s'",""); ++ return(MagickFalse); ++ } + coefficients=(double *) AcquireQuantumMemory(number_coordinates, + sizeof(*coefficients)); +- quantum=MagickMin(quantum/number_coordinates,BezierQuantum); + points=(PointInfo *) AcquireQuantumMemory(quantum,number_coordinates* + sizeof(*points)); + if ((coefficients == (double *) NULL) || (points == (PointInfo *) NULL)) diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-25985_post1.patch imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-25985_post1.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-25985_post1.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-25985_post1.patch 2026-04-12 19:56:19.000000000 +0000 @@ -0,0 +1,49 @@ +From: Dirk Lemstra +Date: Fri, 6 Mar 2026 12:51:12 +0100 +Subject: Set status to false to make sure the rest of the content is no + longer parsed. + +(cherry picked from commit f089279cf9cb5bbc0532078aa3aaf7d7625307d1) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-v7g2-m8c5-mf84 +origin: https://github.com/ImageMagick/ImageMagick6/commit/f089279cf9cb5bbc0532078aa3aaf7d7625307d1 +--- + magick/draw.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/magick/draw.c b/magick/draw.c +index a65776a..642c9d4 100644 +--- a/magick/draw.c ++++ b/magick/draw.c +@@ -3420,6 +3420,7 @@ static MagickBooleanType RenderMVGContent(Image *image, + (void) ThrowMagickException(&image->exception, + GetMagickModule(),ResourceLimitError, + "MemoryAllocationFailed","`%s'",image->filename); ++ status=MagickFalse; + break; + } + graphic_context[n]=CloneDrawInfo((ImageInfo *) NULL, +@@ -3430,9 +3431,12 @@ static MagickBooleanType RenderMVGContent(Image *image, + (void) CloneString(&graphic_context[n]->id,token); + } + if (n > MagickMaxRecursionDepth) +- (void) ThrowMagickException(&image->exception, +- GetMagickModule(),DrawError,"VectorGraphicsNestedTooDeeply", +- "`%s'",image->filename); ++ { ++ (void) ThrowMagickException(&image->exception, ++ GetMagickModule(),DrawError,"VectorGraphicsNestedTooDeeply", ++ "`%s'",image->filename); ++ status=MagickFalse; ++ } + break; + } + if (LocaleCompare("mask",token) == 0) +@@ -4081,6 +4085,7 @@ static MagickBooleanType RenderMVGContent(Image *image, + (void) ThrowMagickException(&image->exception,GetMagickModule(), + ResourceLimitError,"MemoryAllocationFailed","`%s'", + image->filename); ++ status=MagickFalse; + break; + } + mvg_info.offset=i; diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-26284.patch imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-26284.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-26284.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-26284.patch 2026-04-12 19:56:19.000000000 +0000 @@ -0,0 +1,26 @@ +From: Dirk Lemstra +Date: Tue, 27 Jan 2026 21:45:05 +0100 +Subject: Corrected loop initialization to prevent out of bounds read + (https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-wrhr-rf8j-r842) + +(cherry picked from commit 5204a166fd2463905025378303c7e3715163d0e7) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-wrhr-rf8j-r842 +origin: https://github.com/ImageMagick/ImageMagick6/commit/5204a166fd2463905025378303c7e3715163d0e7 +--- + coders/pcd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/coders/pcd.c b/coders/pcd.c +index f53c3ba..e70671c 100644 +--- a/coders/pcd.c ++++ b/coders/pcd.c +@@ -313,7 +313,7 @@ static MagickBooleanType DecodeImage(Image *image,unsigned char *luma, + Decode luminance or chrominance deltas. + */ + r=pcd_table[plane]; +- for (i=0; ((i < pcd_length[plane]) && ((sum & r->mask) != r->sequence)); i++) ++ for (i=1; ((i < pcd_length[plane]) && ((sum & r->mask) != r->sequence)); i++) + r++; + if ((row > image->rows) || (r == (PCDTable *) NULL)) + { diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-26284_pre1.patch imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-26284_pre1.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-26284_pre1.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-26284_pre1.patch 2026-04-12 19:56:19.000000000 +0000 @@ -0,0 +1,86 @@ +From: Dirk Lemstra +Date: Tue, 27 Jan 2026 21:28:11 +0100 +Subject: More changes to improve the readability. + +(cherry picked from commit 621b8d831aa2922c6237cde35f86df78807494dc) + +origin: https://github.com/ImageMagick/ImageMagick6/commit/621b8d831aa2922c6237cde35f86df78807494dc +--- + coders/pcd.c | 15 ++++++--------- + 1 file changed, 6 insertions(+), 9 deletions(-) + +diff --git a/coders/pcd.c b/coders/pcd.c +index 730aa69..f53c3ba 100644 +--- a/coders/pcd.c ++++ b/coders/pcd.c +@@ -168,9 +168,7 @@ static MagickBooleanType DecodeImage(Image *image,unsigned char *luma, + + size_t + bits, +- length, + plane, +- pcd_length[3], + row, + sum; + +@@ -178,6 +176,8 @@ static MagickBooleanType DecodeImage(Image *image,unsigned char *luma, + count, + i, + j, ++ pcd_count, ++ pcd_length[3], + quantum; + + unsigned char +@@ -211,8 +211,8 @@ static MagickBooleanType DecodeImage(Image *image,unsigned char *luma, + for (i=0; i < (ssize_t) (image->columns > 1536 ? 3 : 1); i++) + { + PCDGetBits(8); +- length=(sum & 0xff)+1; +- pcd_table[i]=(PCDTable *) AcquireQuantumMemory(length, ++ pcd_length[i]=(ssize_t) (sum & 0xff)+1; ++ pcd_table[i]=(PCDTable *) AcquireQuantumMemory((size_t) pcd_length[i], + sizeof(*pcd_table[i])); + if (pcd_table[i] == (PCDTable *) NULL) + { +@@ -223,7 +223,7 @@ static MagickBooleanType DecodeImage(Image *image,unsigned char *luma, + image->filename); + } + r=pcd_table[i]; +- for (j=0; j < (ssize_t) length; j++) ++ for (j=0; j < pcd_length[i]; j++) + { + PCDGetBits(8); + r->length=(unsigned int) (sum & 0xff)+1; +@@ -241,7 +241,6 @@ static MagickBooleanType DecodeImage(Image *image,unsigned char *luma, + r->mask=(~((1U << (32-r->length))-1)); + r++; + } +- pcd_length[i]=(size_t) length; + } + if (EOFBlob(image) == MagickFalse) + { +@@ -261,7 +260,6 @@ static MagickBooleanType DecodeImage(Image *image,unsigned char *luma, + Recover the Huffman encoded luminance and chrominance deltas. + */ + count=0; +- length=0; + plane=0; + row=0; + for (q=luma; EOFBlob(image) == MagickFalse; ) +@@ -309,14 +307,13 @@ static MagickBooleanType DecodeImage(Image *image,unsigned char *luma, + image->filename); + } + } +- length=pcd_length[plane]; + continue; + } + /* + Decode luminance or chrominance deltas. + */ + r=pcd_table[plane]; +- for (i=0; ((i < (ssize_t) length) && ((sum & r->mask) != r->sequence)); i++) ++ for (i=0; ((i < pcd_length[plane]) && ((sum & r->mask) != r->sequence)); i++) + r++; + if ((row > image->rows) || (r == (PCDTable *) NULL)) + { diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-26983.patch imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-26983.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-26983.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-26983.patch 2026-04-12 19:56:19.000000000 +0000 @@ -0,0 +1,36 @@ +From: Cristy +Date: Mon, 16 Feb 2026 10:01:13 -0500 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-w8mw-frc6-r7m8 + +The MSL interpreter crashes when processing a invalid `` element that causes it to use an image after it has been freed + +(cherry picked from commit b34591e9067df9cd6fe73b71b1f0d20b3c2bbbc0) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-w8mw-frc6-r7m8 +origin: https://github.com/ImageMagick/ImageMagick6/commit/b34591e9067df9cd6fe73b71b1f0d20b3c2bbbc0 +--- + coders/msl.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/coders/msl.c b/coders/msl.c +index 0bc1ded..786d19a 100644 +--- a/coders/msl.c ++++ b/coders/msl.c +@@ -3694,10 +3694,13 @@ static void MSLStartElement(void *context,const xmlChar *tag, + } + quantize_info=AcquireQuantizeInfo(msl_info->image_info[n]); + quantize_info->dither=dither; +- (void) RemapImages(quantize_info,msl_info->image[n], +- affinity_image); ++ if (affinity_image != (Image *) NULL) ++ { ++ (void) RemapImages(quantize_info,msl_info->image[n], ++ affinity_image); ++ affinity_image=DestroyImage(affinity_image); ++ } + quantize_info=DestroyQuantizeInfo(quantize_info); +- affinity_image=DestroyImage(affinity_image); + break; + } + if (LocaleCompare((const char *) tag,"matte-floodfill") == 0) diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-28494.patch imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-28494.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-28494.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-28494.patch 2026-04-12 19:56:19.000000000 +0000 @@ -0,0 +1,59 @@ +From: Dirk Lemstra +Date: Sat, 28 Feb 2026 11:31:22 +0100 +Subject: Added checks to avoid possible stack corruption + (https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-932h-jw47-73jm) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-932h-jw47-73jm +origin: https://github.com/ImageMagick/ImageMagick6/commit/f6cd30e0493635eb0b8a4e3dd93c1ac14a35a7e9 +--- + magick/morphology.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/magick/morphology.c b/magick/morphology.c +index 6161399..d44c649 100644 +--- a/magick/morphology.c ++++ b/magick/morphology.c +@@ -234,6 +234,9 @@ static KernelInfo *ParseKernelArray(const char *kernel_string) + GeometryInfo + args; + ++ size_t ++ length; ++ + kernel=(KernelInfo *) AcquireMagickMemory(sizeof(*kernel)); + if (kernel == (KernelInfo *) NULL) + return(kernel); +@@ -261,8 +264,9 @@ static KernelInfo *ParseKernelArray(const char *kernel_string) + if ( p != (char *) NULL && p < end) + { + /* ParseGeometry() needs the geometry separated! -- Arrgghh */ +- memcpy(token, kernel_string, (size_t) (p-kernel_string)); +- token[p-kernel_string] = '\0'; ++ length=MagickMin((size_t) (p-kernel_string),sizeof(token)-1); ++ (void) memcpy(token, kernel_string, length); ++ token[length] = '\0'; + SetGeometryInfo(&args); + flags = ParseGeometry(token, &args); + +@@ -387,6 +391,9 @@ static KernelInfo *ParseKernelName(const char *kernel_string) + MagickStatusType + flags; + ++ size_t ++ length; ++ + ssize_t + type; + +@@ -405,8 +412,9 @@ static KernelInfo *ParseKernelName(const char *kernel_string) + end = strchr(p, '\0'); + + /* ParseGeometry() needs the geometry separated! -- Arrgghh */ +- memcpy(token, p, (size_t) (end-p)); +- token[end-p] = '\0'; ++ length=MagickMin((size_t) (end-p),sizeof(token)-1); ++ (void) memcpy(token, p, length); ++ token[length] = '\0'; + SetGeometryInfo(&args); + flags = ParseGeometry(token, &args); + diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-28686_28687_28688_28689_28690_28692.patch imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-28686_28687_28688_28689_28690_28692.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-28686_28687_28688_28689_28690_28692.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-28686_28687_28688_28689_28690_28692.patch 2026-04-12 19:57:53.000000000 +0000 @@ -0,0 +1,819 @@ +From: Cristy +Date: Sun, 22 Feb 2026 18:57:47 -0500 +Subject: jumbo security patch + +(cherry picked from commit 6a602fb36f181a0089848344a3b0d79fc6155a2b) + +Fix CVE-2026-28686, CVE-2026-28688, CVE-2026-28689, CVE-2026-28690, CVE-2026-28691, CVE-2026-28692 + +This fix supersed fixes for CVE-2026-28687 + +origin: backport, https://github.com/ImageMagick/ImageMagick6/commit/6a602fb36f181a0089848344a3b0d79fc6155a2b +--- + coders/jbig.c | 6 ++ + coders/mat.c | 10 +-- + coders/msl.c | 57 +++-------------- + coders/pcl.c | 6 +- + coders/pdf.c | 5 +- + coders/png.c | 24 ++++++- + coders/ps.c | 3 +- + coders/video.c | 4 +- + magick/blob.c | 160 ++++++++++++++++++++++++++++++++++++++++------- + magick/cache.c | 2 +- + magick/display.c | 2 +- + magick/effect.c | 3 +- + magick/opencl.c | 2 +- + magick/string.c | 8 +-- + magick/utility-private.h | 6 ++ + magick/utility.c | 14 ++++- + magick/xml-tree.c | 8 +-- + 17 files changed, 217 insertions(+), 103 deletions(-) + +Index: imagemagick/coders/jbig.c +=================================================================== +--- imagemagick.orig/coders/jbig.c 2026-03-17 13:55:37.897254293 +0100 ++++ imagemagick/coders/jbig.c 2026-03-17 13:55:37.887456653 +0100 +@@ -204,6 +204,12 @@ + length-=(ssize_t) count; + } + } while ((status == JBG_EAGAIN) || (status == JBG_EOK)); ++ if (status != JBG_EOK) ++ { ++ jbg_dec_free(&jbig_info); ++ buffer=(unsigned char *) RelinquishMagickMemory(buffer); ++ ThrowReaderException(CorruptImageError,"UnableToReadImageData"); ++ } + /* + Create colormap. + */ +Index: imagemagick/coders/mat.c +=================================================================== +--- imagemagick.orig/coders/mat.c 2026-03-17 13:55:37.897254293 +0100 ++++ imagemagick/coders/mat.c 2026-03-17 13:55:37.887806472 +0100 +@@ -1156,19 +1156,19 @@ + case miUINT16: + sample_size = 16; + image->depth = 16; /* Word type cell */ +- ldblk = (ssize_t) (2 * MATLAB_HDR.SizeX); ++ ldblk = (2 * (ssize_t) MATLAB_HDR.SizeX); + break; + case miINT32: + case miUINT32: + sample_size = 32; + image->depth = 32; /* Dword type cell */ +- ldblk = (ssize_t) (4 * MATLAB_HDR.SizeX); ++ ldblk = (4 * (ssize_t) MATLAB_HDR.SizeX); + break; + case miINT64: + case miUINT64: + sample_size = 64; + image->depth = 64; /* Qword type cell */ +- ldblk = (ssize_t) (8 * MATLAB_HDR.SizeX); ++ ldblk = (8 * (ssize_t) MATLAB_HDR.SizeX); + break; + case miSINGLE: + sample_size = 32; +@@ -1177,7 +1177,7 @@ + if (MATLAB_HDR.StructureFlag & FLAG_COMPLEX) + { /* complex float type cell */ + } +- ldblk = (ssize_t) (4 * MATLAB_HDR.SizeX); ++ ldblk = (4 * (ssize_t) MATLAB_HDR.SizeX); + break; + case miDOUBLE: + sample_size = 64; +@@ -1196,7 +1196,7 @@ + if (MATLAB_HDR.StructureFlag & FLAG_COMPLEX) + { /* complex double type cell */ + } +- ldblk = (ssize_t) (8 * MATLAB_HDR.SizeX); ++ ldblk = (8 * (ssize_t) MATLAB_HDR.SizeX); + break; + default: + if ((image != image2) && (image2 != (Image *) NULL)) +Index: imagemagick/coders/msl.c +=================================================================== +--- imagemagick.orig/coders/msl.c 2026-03-17 13:55:37.897254293 +0100 ++++ imagemagick/coders/msl.c 2026-03-17 13:55:37.888347983 +0100 +@@ -159,9 +159,6 @@ + */ + #if defined(MAGICKCORE_XML_DELEGATE) + static MagickBooleanType +- WriteMSLImage(const ImageInfo *,Image *); +- +-static MagickBooleanType + SetMSLAttributes(MSLInfo *,const char *,const char *); + #endif + +@@ -3368,6 +3365,13 @@ + msl_info->group_info=(MSLGroupInfo *) ResizeQuantumMemory( + msl_info->group_info,msl_info->number_groups+1UL, + sizeof(*msl_info->group_info)); ++ if (msl_info->group_info == (MSLGroupInfo *) NULL) ++ { ++ ThrowMSLException(ResourceLimitFatalError, ++ "UnableToInterpretMSLImage",tag); ++ break; ++ } ++ msl_info->group_info[msl_info->number_groups-1].numImages=0; + break; + } + ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag); +@@ -7985,7 +7989,6 @@ + entry=SetMagickInfo("MSL"); + #if defined(MAGICKCORE_XML_DELEGATE) + entry->decoder=(DecodeImageHandler *) ReadMSLImage; +- entry->encoder=(EncodeImageHandler *) WriteMSLImage; + #endif + entry->format_type=ImplicitFormatType; + entry->description=ConstantString("Magick Scripting Language"); +@@ -8309,49 +8312,3 @@ + { + (void) UnregisterMagickInfo("MSL"); + } +- +-#if defined(MAGICKCORE_XML_DELEGATE) +-/* +-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-% % +-% % +-% % +-% W r i t e M S L I m a g e % +-% % +-% % +-% % +-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-% +-% WriteMSLImage() writes an image to a file in MVG image format. +-% +-% The format of the WriteMSLImage method is: +-% +-% MagickBooleanType WriteMSLImage(const ImageInfo *image_info,Image *image) +-% +-% A description of each parameter follows. +-% +-% o image_info: the image info. +-% +-% o image: The image. +-% +-*/ +-static MagickBooleanType WriteMSLImage(const ImageInfo *image_info,Image *image) +-{ +- Image +- *msl_image; +- +- MagickBooleanType +- status; +- +- assert(image_info != (const ImageInfo *) NULL); +- assert(image_info->signature == MagickCoreSignature); +- assert(image != (Image *) NULL); +- assert(image->signature == MagickCoreSignature); +- if (image->debug != MagickFalse) +- (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); +- msl_image=CloneImage(image,0,0,MagickTrue,&image->exception); +- status=ProcessMSLScript(image_info,&msl_image,&image->exception); +- msl_image=DestroyImage(msl_image); +- return(status); +-} +-#endif +Index: imagemagick/coders/pcl.c +=================================================================== +--- imagemagick.orig/coders/pcl.c 2026-03-17 13:55:37.897254293 +0100 ++++ imagemagick/coders/pcl.c 2026-03-17 13:55:37.888809999 +0100 +@@ -829,14 +829,14 @@ + } + case RLECompression: + { +- compress_pixels=(unsigned char *) AcquireQuantumMemory(length+256, +- sizeof(*compress_pixels)); ++ compress_pixels=(unsigned char *) AcquireQuantumMemory(length+ ++ (length/127)+256,sizeof(*compress_pixels)); + if (compress_pixels == (unsigned char *) NULL) + { + pixels=(unsigned char *) RelinquishMagickMemory(pixels); + ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); + } +- (void) memset(compress_pixels,0,(length+256)* ++ (void) memset(compress_pixels,0,(length+(length/127)+256)* + sizeof(*compress_pixels)); + (void) FormatLocaleString(buffer,MaxTextExtent,"\033*b2M"); + (void) WriteBlobString(image,buffer); +Index: imagemagick/coders/pdf.c +=================================================================== +--- imagemagick.orig/coders/pdf.c 2026-03-17 13:55:37.897254293 +0100 ++++ imagemagick/coders/pdf.c 2026-03-17 13:55:37.889070166 +0100 +@@ -84,6 +84,7 @@ + #include "magick/token.h" + #include "magick/transform.h" + #include "magick/utility.h" ++#include "magick/utility-private.h" + #include "coders/bytebuffer-private.h" + #include "coders/ghostscript-private.h" + +@@ -550,8 +551,8 @@ + return((Image *) NULL); + } + if (write(file," ",1) != 1) +- ; +- file=close(file)-1; ++ { }; ++ file=close_utf8(file)-1; + /* + Render Postscript with the Ghostscript delegate. + */ +Index: imagemagick/coders/png.c +=================================================================== +--- imagemagick.orig/coders/png.c 2026-03-17 13:55:37.897254293 +0100 ++++ imagemagick/coders/png.c 2026-03-17 13:55:37.889254260 +0100 +@@ -12732,9 +12732,16 @@ + /* Exclude all ancillary chunks */ + (void) SetImageArtifact(jpeg_image,"png:exclude-chunks","all"); + +- blob=ImageToBlob(jpeg_image_info,jpeg_image,&length, ++ blob=(unsigned char *) ImageToBlob(jpeg_image_info,jpeg_image,&length, + &image->exception); + ++ if (blob == (unsigned char *) NULL) ++ { ++ jpeg_image=DestroyImage(jpeg_image); ++ jpeg_image_info=DestroyImageInfo(jpeg_image_info); ++ return(MagickFalse); ++ } ++ + /* Retrieve sample depth used */ + value=GetImageProperty(jpeg_image,"png:bit-depth-written"); + if (value != (char *) NULL) +@@ -13102,7 +13109,17 @@ + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + " Creating blob."); + +- blob=ImageToBlob(jpeg_image_info,jpeg_image,&length,&image->exception); ++ blob=(unsigned char *) ImageToBlob(jpeg_image_info,jpeg_image,&length, ++ &image->exception); ++ ++ if (blob == (unsigned char *) NULL) ++ { ++ if (jpeg_image != (Image *)NULL) ++ jpeg_image=DestroyImage(jpeg_image); ++ if (jpeg_image_info != (ImageInfo *)NULL) ++ jpeg_image_info=DestroyImageInfo(jpeg_image_info); ++ return(MagickFalse); ++ } + + if (logging != MagickFalse) + { +@@ -13302,6 +13319,9 @@ + (void) memset(mng_info,0,sizeof(MngInfo)); + mng_info->image=image; + write_mng=LocaleCompare(image_info->magick,"MNG") == 0; ++ if ((write_mng != MagickFalse) && (image->storage_class == PseudoClass) && ++ (image->colors > 256)) ++ (void) SetImageStorageClass(image,DirectClass); + + /* + * See if user has requested a specific PNG subformat to be used +Index: imagemagick/coders/ps.c +=================================================================== +--- imagemagick.orig/coders/ps.c 2026-03-17 13:55:37.897254293 +0100 ++++ imagemagick/coders/ps.c 2026-03-17 13:55:37.890574090 +0100 +@@ -79,6 +79,7 @@ + #include "magick/token.h" + #include "magick/transform.h" + #include "magick/utility.h" ++#include "magick/utility-private.h" + #include "coders/bytebuffer-private.h" + #include "coders/ghostscript-private.h" + +@@ -717,7 +718,7 @@ + strlen(translate_geometry)); + } + (void) count; +- file=close(file)-1; ++ file=close_utf8(file)-1; + /* + Render Postscript with the Ghostscript delegate. + */ +Index: imagemagick/coders/video.c +=================================================================== +--- imagemagick.orig/coders/video.c 2026-03-17 13:55:37.897254293 +0100 ++++ imagemagick/coders/video.c 2026-03-17 13:56:39.585239580 +0100 +@@ -555,7 +555,7 @@ + return(MagickFalse); + file=AcquireUniqueFileResource(basename); + if (file != -1) +- file=close(file)-1; ++ file=close_utf8(file)-1; + (void) FormatLocaleString(coalesce_image->filename,MaxTextExtent,"%s", + basename); + count=0; +Index: imagemagick/magick/blob.c +=================================================================== +--- imagemagick.orig/magick/blob.c 2026-03-17 13:55:37.897254293 +0100 ++++ imagemagick/magick/blob.c 2026-03-17 13:55:37.890989803 +0100 +@@ -284,7 +284,7 @@ + break; + } + } +- file=close(file); ++ file=close_utf8(file); + if ((file == -1) || (i < length)) + { + ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename); +@@ -1132,19 +1132,36 @@ + file=fileno(stdin); + if (LocaleCompare(filename,"-") != 0) + { ++ int ++ flags = O_RDONLY | O_BINARY; ++ + status=GetPathAttributes(filename,&attributes); + if ((status == MagickFalse) || (S_ISDIR(attributes.st_mode) != 0)) + { + ThrowFileException(exception,BlobError,"UnableToReadBlob",filename); + return(NULL); + } +- file=open_utf8(filename,O_RDONLY | O_BINARY,0); ++#if defined(O_NOFOLLOW) ++ status=IsRightsAuthorized(SystemPolicyDomain,ReadPolicyRights,"follow"); ++ if (status == MagickFalse) ++ flags|=O_NOFOLLOW; ++#endif ++ file=open_utf8(filename,flags,0); + } + if (file == -1) + { + ThrowFileException(exception,BlobError,"UnableToOpenFile",filename); + return((unsigned char *) NULL); + } ++ status=IsRightsAuthorized(PathPolicyDomain,ReadPolicyRights,filename); ++ if (status == MagickFalse) ++ { ++ file=close_utf8(file)-1; ++ errno=EPERM; ++ (void) ThrowMagickException(exception,GetMagickModule(),PolicyError, ++ "NotAuthorized","`%s'",filename); ++ return(NULL); ++ } + offset=(MagickOffsetType) lseek(file,0,SEEK_END); + count=0; + if ((file == fileno(stdin)) || (offset < 0) || +@@ -1184,7 +1201,7 @@ + break; + } + if (LocaleCompare(filename,"-") != 0) +- file=close(file); ++ file=close_utf8(file); + if (blob == (unsigned char *) NULL) + { + (void) ThrowMagickException(exception,GetMagickModule(), +@@ -1209,7 +1226,7 @@ + sizeof(*blob)); + if (blob == (unsigned char *) NULL) + { +- file=close(file); ++ file=close_utf8(file); + (void) ThrowMagickException(exception,GetMagickModule(), + ResourceLimitError,"MemoryAllocationFailed","`%s'",filename); + return((unsigned char *) NULL); +@@ -1235,7 +1252,7 @@ + } + if (i < *length) + { +- file=close(file)-1; ++ file=close_utf8(file)-1; + blob=(unsigned char *) RelinquishMagickMemory(blob); + ThrowFileException(exception,BlobError,"UnableToReadBlob",filename); + return((unsigned char *) NULL); +@@ -1243,7 +1260,7 @@ + } + blob[*length]='\0'; + if (LocaleCompare(filename,"-") != 0) +- file=close(file); ++ file=close_utf8(file); + if (file == -1) + { + blob=(unsigned char *) RelinquishMagickMemory(blob); +@@ -1336,7 +1353,7 @@ + assert(image->signature == MagickCoreSignature); + assert(filename != (const char *) NULL); + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename); +- status=IsRightsAuthorized(PathPolicyDomain,WritePolicyRights,filename); ++ status=IsRightsAuthorized(PathPolicyDomain,ReadPolicyRights,filename); + if (status == MagickFalse) + { + errno=EPERM; +@@ -1346,20 +1363,38 @@ + } + file=fileno(stdin); + if (LocaleCompare(filename,"-") != 0) +- file=open_utf8(filename,O_RDONLY | O_BINARY,0); ++ { ++ int ++ flags = O_RDONLY | O_BINARY; ++ ++#if defined(O_NOFOLLOW) ++ status=IsRightsAuthorized(SystemPolicyDomain,ReadPolicyRights,"follow"); ++ if (status == MagickFalse) ++ flags|=O_NOFOLLOW; ++#endif ++ file=open_utf8(filename,flags,0); ++ } + if (file == -1) + { + ThrowFileException(&image->exception,BlobError,"UnableToOpenBlob", + filename); + return(MagickFalse); + } ++ status=IsRightsAuthorized(PathPolicyDomain,ReadPolicyRights,filename); ++ if (status == MagickFalse) ++ { ++ errno=EPERM; ++ (void) ThrowMagickException(&image->exception,GetMagickModule(), ++ PolicyError,"NotAuthorized","`%s'",filename); ++ return(MagickFalse); ++ } + quantum=(size_t) MagickMaxBufferExtent; + if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0)) + quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent); + blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob)); + if (blob == (unsigned char *) NULL) + { +- file=close(file); ++ file=close_utf8(file); + ThrowFileException(&image->exception,ResourceLimitError, + "MemoryAllocationFailed",filename); + return(MagickFalse); +@@ -1382,7 +1417,7 @@ + break; + } + } +- file=close(file); ++ file=close_utf8(file); + if (file == -1) + ThrowFileException(&image->exception,BlobError,"UnableToWriteBlob", + filename); +@@ -1887,7 +1922,7 @@ + buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer)); + if (buffer == (unsigned char *) NULL) + { +- file=close(file)-1; ++ file=close_utf8(file)-1; + (void) ThrowMagickException(exception,GetMagickModule(), + ResourceLimitError,"MemoryAllocationError","`%s'",filename); + return(MagickFalse); +@@ -1912,10 +1947,12 @@ + p=(const unsigned char *) ReadBlobStream(image,quantum,buffer,&count); + } + if (LocaleCompare(filename,"-") != 0) +- file=close(file); ++ file=close_utf8(file); + buffer=(unsigned char *) RelinquishMagickMemory(buffer); + if ((file == -1) || (i < length)) + { ++ if (file != -1) ++ file=close_utf8(file); + ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename); + return(MagickFalse); + } +@@ -2202,7 +2239,7 @@ + if (buffer == (unsigned char *) NULL) + { + (void) RelinquishUniqueFileResource(filename); +- file=close(file); ++ file=close_utf8(file); + ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", + image->filename); + } +@@ -2218,7 +2255,7 @@ + status=WriteBlobStream(image,(size_t) count,buffer) == count ? MagickTrue : + MagickFalse; + } +- file=close(file); ++ file=close_utf8(file); + if (file == -1) + ThrowFileException(exception,FileOpenError,"UnableToWriteBlob",filename); + (void) RelinquishUniqueFileResource(filename); +@@ -2613,6 +2650,9 @@ + const char + *type; + ++ int ++ flags = O_RDONLY; ++ + MagickBooleanType + status; + +@@ -2638,13 +2678,48 @@ + blob_info->mode=mode; + switch (mode) + { +- default: type="r"; break; +- case ReadBlobMode: type="r"; break; +- case ReadBinaryBlobMode: type="rb"; break; +- case WriteBlobMode: type="w"; break; +- case WriteBinaryBlobMode: type="w+b"; break; +- case AppendBlobMode: type="a"; break; +- case AppendBinaryBlobMode: type="a+b"; break; ++ case ReadBlobMode: ++ { ++ flags=O_RDONLY; ++ type="r"; ++ break; ++ } ++ case ReadBinaryBlobMode: ++ { ++ flags=O_RDONLY | O_BINARY; ++ type="rb"; ++ break; ++ } ++ case WriteBlobMode: ++ { ++ flags=O_WRONLY | O_CREAT | O_TRUNC; ++ type="w"; ++ break; ++ } ++ case WriteBinaryBlobMode: ++ { ++ flags=O_RDWR | O_CREAT | O_TRUNC | O_BINARY; ++ type="w+b"; ++ break; ++ } ++ case AppendBlobMode: ++ { ++ flags=O_WRONLY | O_CREAT | O_APPEND; ++ type="a"; ++ break; ++ } ++ case AppendBinaryBlobMode: ++ { ++ flags=O_RDWR | O_CREAT | O_APPEND | O_BINARY; ++ type="a+b"; ++ break; ++ } ++ default: ++ { ++ flags=O_RDONLY; ++ type="r"; ++ break; ++ } + } + if (*type != 'r') + blob_info->synchronize=image_info->synchronize; +@@ -2793,7 +2868,18 @@ + else + if (*type == 'r') + { +- blob_info->file_info.file=(FILE *) fopen_utf8(filename,type); ++ int ++ file; ++ ++ blob_info->file_info.file=(FILE *) NULL; ++#if defined(O_NOFOLLOW) ++ status=IsRightsAuthorized(SystemPolicyDomain,ReadPolicyRights,"follow"); ++ if (status == MagickFalse) ++ flags|=O_NOFOLLOW; ++#endif ++ file=open_utf8(filename,flags,0); ++ if (file >= 0) ++ blob_info->file_info.file=fdopen(file,type); + if (blob_info->file_info.file != (FILE *) NULL) + { + size_t +@@ -2908,14 +2994,33 @@ + else + #endif + { +- blob_info->file_info.file=(FILE *) fopen_utf8(filename,type); ++ int ++ file; ++ ++ blob_info->file_info.file=(FILE *) NULL; ++#if defined(O_NOFOLLOW) ++ status=IsRightsAuthorized(SystemPolicyDomain,WritePolicyRights, ++ "follow"); ++ if (status == MagickFalse) ++ flags|=O_NOFOLLOW; ++#endif ++ file=open_utf8(filename,flags,0666); ++ if (file >= 0) ++ blob_info->file_info.file=fdopen(file,type); + if (blob_info->file_info.file != (FILE *) NULL) + { + blob_info->type=FileStream; + (void) SetStreamBuffering(image_info,image); + } + } +- blob_info->status=MagickFalse; ++ if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse) ++ { ++ errno=EPERM; ++ (void) ThrowMagickException(exception,GetMagickModule(),PolicyError, ++ "NotAuthorized","`%s'",filename); ++ return(MagickFalse); ++ } ++ blob_info->status=0; + blob_info->error_number=0; + if (blob_info->type != UndefinedStream) + blob_info->size=GetBlobSize(image); +Index: imagemagick/magick/cache.c +=================================================================== +--- imagemagick.orig/magick/cache.c 2026-03-17 13:55:37.897254293 +0100 ++++ imagemagick/magick/cache.c 2026-03-17 13:55:37.891491539 +0100 +@@ -1100,7 +1100,7 @@ + status=(-1); + if (cache_info->file != -1) + { +- status=close(cache_info->file); ++ status=close_utf8(cache_info->file); + cache_info->file=(-1); + RelinquishMagickResource(FileResource,1); + } +Index: imagemagick/magick/display.c +=================================================================== +--- imagemagick.orig/magick/display.c 2026-03-17 13:55:37.897254293 +0100 ++++ imagemagick/magick/display.c 2026-03-17 13:55:37.892467154 +0100 +@@ -8858,7 +8858,7 @@ + image_info->filename); + value=GetImageProperty(*image,"comment"); + if (value == (char *) NULL) +- unique_file=close(unique_file)-1; ++ unique_file=close_utf8(unique_file)-1; + else + { + const char +Index: imagemagick/magick/effect.c +=================================================================== +--- imagemagick.orig/magick/effect.c 2026-03-17 13:55:37.897254293 +0100 ++++ imagemagick/magick/effect.c 2026-03-17 13:55:37.893301748 +0100 +@@ -90,6 +90,7 @@ + #include "magick/thread-private.h" + #include "magick/transform.h" + #include "magick/threshold.h" ++#include "magick/utility-private.h" + + #ifdef MAGICKCORE_CLPERFMARKER + #include "CLPerfMarker.h" +@@ -3200,7 +3201,7 @@ + preview_info->quality); + file=AcquireUniqueFileResource(filename); + if (file != -1) +- file=close(file)-1; ++ file=close_utf8(file)-1; + (void) FormatLocaleString(preview_image->filename,MaxTextExtent, + "jpeg:%s",filename); + status=WriteImage(preview_info,preview_image); +Index: imagemagick/magick/opencl.c +=================================================================== +--- imagemagick.orig/magick/opencl.c 2026-03-17 13:55:37.897254293 +0100 ++++ imagemagick/magick/opencl.c 2026-03-17 13:55:37.893957460 +0100 +@@ -935,7 +935,7 @@ + if (file != -1) + { + write(file,binary_program[i],program_size); +- file=close(file); ++ file=close_utf8(file); + } + else + (void) ThrowMagickException(exception,GetMagickModule(), +Index: imagemagick/magick/string.c +=================================================================== +--- imagemagick.orig/magick/string.c 2026-03-17 13:55:37.897254293 +0100 ++++ imagemagick/magick/string.c 2026-03-17 13:55:37.894338597 +0100 +@@ -615,7 +615,7 @@ + offset=(MagickOffsetType) lseek(file,0,SEEK_END); + if ((offset < 0) || (offset != (MagickOffsetType) ((ssize_t) offset))) + { +- file=close(file)-1; ++ file=close_utf8(file)-1; + return((StringInfo *) NULL); + } + length=(size_t) offset; +@@ -624,7 +624,7 @@ + string=(char *) AcquireQuantumMemory(length+MaxTextExtent,sizeof(*string)); + if (string == (char *) NULL) + { +- file=close(file)-1; ++ file=close_utf8(file)-1; + return((StringInfo *) NULL); + } + map=MapBlob(file,ReadMode,0,length); +@@ -655,13 +655,13 @@ + } + if (i < length) + { +- file=close(file)-1; ++ file=close_utf8(file)-1; + string=DestroyString(string); + return((StringInfo *) NULL); + } + } + string[length]='\0'; +- file=close(file)-1; ++ file=close_utf8(file)-1; + string_info=AcquireStringInfoContainer(); + (void) CopyMagickString(string_info->path,filename,MaxTextExtent); + string_info->length=length; +Index: imagemagick/magick/utility-private.h +=================================================================== +--- imagemagick.orig/magick/utility-private.h 2026-03-17 13:55:37.897254293 +0100 ++++ imagemagick/magick/utility-private.h 2026-03-17 13:55:37.894603935 +0100 +@@ -113,6 +113,12 @@ + #endif + } + ++#if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__CYGWIN__) ++#define close_utf8 _close ++#else ++#define close_utf8 close ++#endif ++ + static inline FILE *fopen_utf8(const char *path,const char *mode) + { + #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__) +Index: imagemagick/magick/utility.c +=================================================================== +--- imagemagick.orig/magick/utility.c 2026-03-17 13:55:37.897254293 +0100 ++++ imagemagick/magick/utility.c 2026-03-17 13:55:37.894800399 +0100 +@@ -114,7 +114,7 @@ + file=AcquireUniqueFileResource(path); + if (file == -1) + return(MagickFalse); +- file=close(file)-1; ++ file=close_utf8(file)-1; + return(MagickTrue); + } + +@@ -180,8 +180,13 @@ + + (void) AcquireUniqueFilename(destination); + (void) RelinquishUniqueFileResource(destination); ++ /* ++ Does policy permit symbolic links? ++ */ ++ status=IsRightsAuthorized(SystemPolicyDomain,ReadPolicyRights | ++ WritePolicyRights,"follow"); + passes=GetPolicyValue("system:shred"); +- if (passes != (char *) NULL) ++ if ((passes != (char *) NULL) || (status == MagickFalse)) + passes=DestroyString(passes); + else + { +@@ -207,6 +212,9 @@ + } + } + #endif ++ /* ++ Copy file from source to destination. ++ */ + destination_file=AcquireUniqueFileResource(destination); + if (destination_file == -1) + return(MagickFalse); +@@ -1930,7 +1938,7 @@ + if (j < (MagickOffsetType) length) + break; + } +- status=close(file); ++ status=close_utf8(file); + status=remove_utf8(path); + if (status != -1) + status=StringToInteger(passes); +Index: imagemagick/magick/xml-tree.c +=================================================================== +--- imagemagick.orig/magick/xml-tree.c 2026-03-17 13:55:37.897254293 +0100 ++++ imagemagick/magick/xml-tree.c 2026-03-17 13:55:37.895121869 +0100 +@@ -662,7 +662,7 @@ + break; + } + if (LocaleCompare(filename,"-") != 0) +- file=close(file); ++ file=close_utf8(file); + if (xml == (char *) NULL) + return((char *) NULL); + if (file == -1) +@@ -680,7 +680,7 @@ + xml=(char *) AcquireQuantumMemory(length+MaxTextExtent,sizeof(*xml)); + if (xml == (char *) NULL) + { +- file=close(file); ++ file=close_utf8(file); + return((char *) NULL); + } + map=MapBlob(file,ReadMode,0,length); +@@ -704,14 +704,14 @@ + } + if (i < length) + { +- file=close(file)-1; ++ file=close_utf8(file)-1; + xml=(char *) RelinquishMagickMemory(xml); + return((char *) NULL); + } + } + xml[length]='\0'; + if (LocaleCompare(filename,"-") != 0) +- file=close(file); ++ file=close_utf8(file); + if (file == -1) + xml=(char *) RelinquishMagickMemory(xml); + return(xml); diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-28693_1.patch imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-28693_1.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-28693_1.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-28693_1.patch 2026-04-12 19:56:20.000000000 +0000 @@ -0,0 +1,100 @@ +From: Cristy +Date: Sat, 28 Feb 2026 10:43:30 -0500 +Subject: https://github.com/ImageMagick/ImageMagick/pull/8573 + +(cherry picked from commit c54e9b365118972f939b0efcdd5087e106eb8945) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-hffp-q43q-qq76 +origin: backport, https://github.com/ImageMagick/ImageMagick6/commit/c54e9b365118972f939b0efcdd5087e106eb8945 +--- + coders/bmp.c | 3 +++ + coders/dib.c | 28 +++++++++++++++++++++------- + 2 files changed, 24 insertions(+), 7 deletions(-) + +diff --git a/coders/bmp.c b/coders/bmp.c +index 35930a9..3f447ab 100644 +--- a/coders/bmp.c ++++ b/coders/bmp.c +@@ -1870,6 +1870,9 @@ static MagickBooleanType WriteBMPImage(const ImageInfo *image_info,Image *image) + } + } + } ++ if (BMPOverflowCheck(image->columns,(size_t) bmp_info.bits_per_pixel) != ++ MagickFalse) ++ ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit"); + extent=image->columns*(size_t) bmp_info.bits_per_pixel; + bytes_per_line=4*((extent+31)/32); + if (BMPOverflowCheck(bytes_per_line,image->rows) != MagickFalse) +diff --git a/coders/dib.c b/coders/dib.c +index 45f2f1c..dda7c1b 100644 +--- a/coders/dib.c ++++ b/coders/dib.c +@@ -494,6 +494,7 @@ static Image *ReadDIBImage(const ImageInfo *image_info,ExceptionInfo *exception) + + size_t + bytes_per_line, ++ extent, + length; + + ssize_t +@@ -670,9 +671,14 @@ static Image *ReadDIBImage(const ImageInfo *image_info,ExceptionInfo *exception) + */ + if (dib_info.compression == BI_RLE4) + dib_info.bits_per_pixel<<=1; +- bytes_per_line=4*((image->columns*dib_info.bits_per_pixel+31)/32); +- length=bytes_per_line*image->rows; +- if ((MagickSizeType) length > (256*GetBlobSize(image))) ++ if (HeapOverflowSanityCheckGetSize(image->columns, ++ (size_t) dib_info.bits_per_pixel,&extent) != MagickFalse) ++ ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); ++ bytes_per_line=4*((extent+31)/32); ++ if (HeapOverflowSanityCheckGetSize(bytes_per_line,image->rows, ++ &length) != MagickFalse) ++ ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile"); ++ if ((MagickSizeType) (length/256) > GetBlobSize(image)) + ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile"); + pixel_info=AcquireVirtualMemory(image->rows,MagickMax(bytes_per_line, + image->columns+256UL)*sizeof(*pixels)); +@@ -1121,7 +1127,9 @@ static MagickBooleanType WriteDIBImage(const ImageInfo *image_info,Image *image) + *q; + + size_t +- bytes_per_line; ++ bytes_per_line, ++ extent, ++ length; + + ssize_t + y; +@@ -1170,14 +1178,20 @@ static MagickBooleanType WriteDIBImage(const ImageInfo *image_info,Image *image) + dib_info.number_colors=(unsigned int) (dib_info.bits_per_pixel == 16 ? 0 : + (1UL << dib_info.bits_per_pixel)); + } +- bytes_per_line=4*((image->columns*dib_info.bits_per_pixel+31)/32); ++ if (HeapOverflowSanityCheckGetSize(image->columns, ++ (size_t) dib_info.bits_per_pixel,&extent) != MagickFalse) ++ ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit"); ++ bytes_per_line=4*((extent+31)/32); ++ if (HeapOverflowSanityCheckGetSize(bytes_per_line,image->rows, ++ &length) != MagickFalse) ++ ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit"); + dib_info.size=40; + dib_info.width=(int) image->columns; + dib_info.height=(int) image->rows; + dib_info.planes=1; + dib_info.compression=(unsigned int) (dib_info.bits_per_pixel == 16 ? + BI_BITFIELDS : BI_RGB); +- dib_info.image_size=(unsigned int) (bytes_per_line*image->rows); ++ dib_info.image_size=(unsigned int) length; + dib_info.x_pixels=75*39; + dib_info.y_pixels=75*39; + switch (image->units) +@@ -1204,7 +1218,7 @@ static MagickBooleanType WriteDIBImage(const ImageInfo *image_info,Image *image) + bytes_per_line,image->columns+256UL)*sizeof(*pixels)); + if (pixels == (unsigned char *) NULL) + ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); +- (void) memset(pixels,0,dib_info.image_size); ++ (void) memset(pixels,0,length); + switch (dib_info.bits_per_pixel) + { + case 1: diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-28693_2.patch imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-28693_2.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-28693_2.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-28693_2.patch 2026-04-12 19:56:20.000000000 +0000 @@ -0,0 +1,26 @@ +From: Dirk Lemstra +Date: Sun, 1 Mar 2026 17:32:19 +0100 +Subject: Added extra check. + +(cherry picked from commit b13562f805d36de13c7c66c5fca6a6505495aae1) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-hffp-q43q-qq76 +origin: https://github.com/ImageMagick/ImageMagick6/commit/b13562f805d36de13c7c66c5fca6a6505495aae1 +--- + coders/dib.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/coders/dib.c b/coders/dib.c +index dda7c1b..2f0e2d1 100644 +--- a/coders/dib.c ++++ b/coders/dib.c +@@ -674,7 +674,8 @@ static Image *ReadDIBImage(const ImageInfo *image_info,ExceptionInfo *exception) + if (HeapOverflowSanityCheckGetSize(image->columns, + (size_t) dib_info.bits_per_pixel,&extent) != MagickFalse) + ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); +- bytes_per_line=4*((extent+31)/32); ++ if (HeapOverflowSanityCheckGetSize(4,((extent+31)/32),&bytes_per_line) != MagickFalse) ++ ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); + if (HeapOverflowSanityCheckGetSize(bytes_per_line,image->rows, + &length) != MagickFalse) + ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile"); diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-28693_pre1.patch imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-28693_pre1.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-28693_pre1.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-28693_pre1.patch 2026-04-12 19:56:20.000000000 +0000 @@ -0,0 +1,49 @@ +From: Cristy +Date: Sat, 23 Aug 2025 11:10:52 -0400 +Subject: https://gist.github.com/mescuwa/9197f4317a69559cdf87d0bfab6fa473 + +(cherry picked from commit 98b5af39db1a18153abf0b2ad604dc112de94fba) + +origin: backport, https://github.com/ImageMagick/ImageMagick6/commit/98b5af39db1a18153abf0b2ad604dc112de94fba +--- + coders/bmp.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/coders/bmp.c b/coders/bmp.c +index d509bd6..35930a9 100644 +--- a/coders/bmp.c ++++ b/coders/bmp.c +@@ -1697,6 +1697,7 @@ static MagickBooleanType WriteBMPImage(const ImageInfo *image_info,Image *image) + + size_t + bytes_per_line, ++ extent, + imageListLength, + type; + +@@ -1869,7 +1870,10 @@ static MagickBooleanType WriteBMPImage(const ImageInfo *image_info,Image *image) + } + } + } +- bytes_per_line=4*((image->columns*bmp_info.bits_per_pixel+31)/32); ++ extent=image->columns*(size_t) bmp_info.bits_per_pixel; ++ bytes_per_line=4*((extent+31)/32); ++ if (BMPOverflowCheck(bytes_per_line,image->rows) != MagickFalse) ++ ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit"); + bmp_info.ba_offset=0; + profile=GetImageProfile(image,"icc"); + have_color_info=(image->rendering_intent != UndefinedIntent) || +@@ -1930,8 +1934,11 @@ static MagickBooleanType WriteBMPImage(const ImageInfo *image_info,Image *image) + /* + Convert MIFF to BMP raster pixels. + */ +- pixel_info=AcquireVirtualMemory(image->rows,MagickMax(bytes_per_line, +- image->columns+256UL)*sizeof(*pixels)); ++ extent=4*MagickMax(bytes_per_line,image->columns+1UL); ++ if ((BMPOverflowCheck(image->rows,extent) != MagickFalse) || ++ (BMPOverflowCheck(extent,sizeof(*pixels)) != MagickFalse)) ++ ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit"); ++ pixel_info=AcquireVirtualMemory(image->rows,extent*sizeof(*pixels)); + if (pixel_info == (MemoryInfo *) NULL) + ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); + pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-30883.patch imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-30883.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-30883.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-30883.patch 2026-04-12 19:56:20.000000000 +0000 @@ -0,0 +1,43 @@ +From: Dirk Lemstra +Date: Fri, 6 Mar 2026 13:14:19 +0100 +Subject: Added extra check to prevent overflow that could result in a heap + over-write + (https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-qmw5-2p58-xvrc) + +(cherry picked from commit 3875619331d2c7c74a80d34665cbc06e6ed4359a) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-qmw5-2p58-xvrc +origin: https://github.com/ImageMagick/ImageMagick6/commit/3875619331d2c7c74a80d34665cbc06e6ed4359a +--- + coders/png.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/coders/png.c b/coders/png.c +index 309e900..1c6e5b1 100644 +--- a/coders/png.c ++++ b/coders/png.c +@@ -7940,11 +7940,10 @@ ModuleExport void UnregisterPNGImage(void) + % transparent region at the top and/or left. + */ + +-static void +-Magick_png_write_raw_profile(const ImageInfo *image_info,png_struct *ping, +- png_info *ping_info, unsigned char *profile_type, unsigned char +- *profile_description, unsigned char *profile_data, png_uint_32 length, +- ExceptionInfo *exception) ++static void Magick_png_write_raw_profile(const ImageInfo *image_info, ++ png_struct *ping,png_info *ping_info,unsigned char *profile_type, ++ unsigned char *profile_description,unsigned char *profile_data, ++ png_uint_32 length,ExceptionInfo *exception) + { + png_textp + text; +@@ -7978,7 +7977,7 @@ Magick_png_write_raw_profile(const ImageInfo *image_info,png_struct *ping, + description_length=(png_uint_32) strlen((const char *) profile_description); + allocated_length=(png_uint_32) (2*length+(length >> 5)+description_length+ + 20); +- if (allocated_length < length) ++ if ((allocated_length < length) || (length >= (PNG_UINT_31_MAX / 2))) + { + (void) ThrowMagickException(exception,GetMagickModule(),CoderError, + "maximum profile length exceeded","`%s'",image_info->filename); diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-30936.patch imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-30936.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-30936.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-30936.patch 2026-04-12 19:56:20.000000000 +0000 @@ -0,0 +1,45 @@ +From: =?utf-8?q?Bastien_Roucari=C3=A8s?= +Date: Tue, 17 Mar 2026 19:48:13 +0100 +Subject: CVE-2026-30936 + +a crafted image could cause an out of bounds heap write inside the WaveletDenoiseImage method. When processing a crafted image with the -wavelet-denoise operation an out of bounds write can occur + +origin: backport, https://github.com/ImageMagick/ImageMagick/commit/ffbbd7201e0ba08707849c0053aa703e076bf86e +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-5ggv-92r5-cp4p +--- + magick/visual-effects.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/magick/visual-effects.c b/magick/visual-effects.c +index 2e78057..e5668ff 100644 +--- a/magick/visual-effects.c ++++ b/magick/visual-effects.c +@@ -3500,6 +3500,9 @@ MagickExport Image *WaveletDenoiseImage(const Image *image, + size_t + max_channels; + ++ size_t ++ number_levels = 5; ++ + ssize_t + channel; + +@@ -3548,6 +3551,9 @@ MagickExport Image *WaveletDenoiseImage(const Image *image, + status=MagickTrue; + number_pixels=image->columns*image->rows; + max_channels=(size_t) (image->colorspace == CMYKColorspace ? 4 : 3); ++ while ((number_levels > 0) && ++ ((1UL << (number_levels-1)) >= MagickMin(image->columns,image->rows))) ++ number_levels--; + image_view=AcquireAuthenticCacheView(image,exception); + noise_view=AcquireAuthenticCacheView(noise_image,exception); + for (channel=0; channel < (ssize_t) max_channels; channel++) +@@ -3607,7 +3613,7 @@ MagickExport Image *WaveletDenoiseImage(const Image *image, + have high values in the noisy parts of the signal. + */ + high_pass=0; +- for (level=0; level < 5; level++) ++ for (level=0; level < (ssize_t) number_levels; level++) + { + double + magnitude; diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-30937.patch imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-30937.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-30937.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-30937.patch 2026-04-12 19:56:20.000000000 +0000 @@ -0,0 +1,27 @@ +From: Cristy +Date: Sat, 28 Feb 2026 10:22:34 -0500 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-qpg4-j99f-8xcg + +(cherry picked from commit 42e5a37eeb60ca4fdede5060c0aa60802c2dc701) + +origin: https://github.com/ImageMagick/ImageMagick6/commit/42e5a37eeb60ca4fdede5060c0aa60802c2dc701 +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-qpg4-j99f-8xcg +--- + coders/xwd.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/coders/xwd.c b/coders/xwd.c +index 79a3e99..17e2921 100644 +--- a/coders/xwd.c ++++ b/coders/xwd.c +@@ -801,8 +801,7 @@ static MagickBooleanType WriteXWDImage(const ImageInfo *image_info,Image *image) + status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); + if (status == MagickFalse) + return(status); +- if ((image->columns != (CARD32) image->columns) || +- (image->rows != (CARD32) image->rows)) ++ if ((image->columns > 65535UL) || (image->rows > 65535UL)) + ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit"); + if ((image->storage_class == PseudoClass) && (image->colors > 256)) + (void) SetImageType(image,TrueColorType); diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-31853.patch imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-31853.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-31853.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-31853.patch 2026-04-12 19:56:20.000000000 +0000 @@ -0,0 +1,33 @@ +From: Dirk Lemstra +Date: Mon, 2 Mar 2026 20:31:40 +0100 +Subject: Corrected the overflow check that can cause issues on 32-bit systems + (https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-56jp-jfqg-f8f4) + +(cherry picked from commit fa85920aa28ee1887cc3c5d7d5272b3650d3b168) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-56jp-jfqg-f8f4 +origin: https://github.com/ImageMagick/ImageMagick6/commit/fa85920aa28ee1887cc3c5d7d5272b3650d3b168 +--- + coders/sfw.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/coders/sfw.c b/coders/sfw.c +index 8070df3..d43e589 100644 +--- a/coders/sfw.c ++++ b/coders/sfw.c +@@ -251,12 +251,12 @@ static Image *ReadSFWImage(const ImageInfo *image_info,ExceptionInfo *exception) + /* + Read image into a buffer. + */ +- if (GetBlobSize(image) != (size_t) GetBlobSize(image)) ++ extent=(size_t) GetBlobSize(image)+MagickPathExtent; ++ if (GetBlobSize(image) != extent) + ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); + if (GetBlobSize(image) < 141) + ThrowReaderException(CorruptImageError,"ImproperImageHeader"); +- buffer=(unsigned char *) AcquireQuantumMemory((size_t) GetBlobSize(image)+ +- MaxTextExtent,sizeof(*buffer)); ++ buffer=(unsigned char *) AcquireQuantumMemory(extent,sizeof(*buffer)); + if (buffer == (unsigned char *) NULL) + ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); + count=ReadBlob(image,(size_t) GetBlobSize(image),buffer); diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-32259.patch imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-32259.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-32259.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-32259.patch 2026-04-12 19:56:20.000000000 +0000 @@ -0,0 +1,45 @@ +From: Dirk Lemstra +Date: Sat, 7 Mar 2026 10:15:11 +0100 +Subject: Added extra check to prevent out of bounds write when color + reduction fails + (https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-49hx-7656-jpg3) + +(cherry picked from commit 812ff3ef91967d367aa7a087a31b94f3b2a267ee) + +bug: https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-49hx-7656-jpg3 +origin: https://github.com/ImageMagick/ImageMagick6/commit/812ff3ef91967d367aa7a087a31b94f3b2a267ee +--- + coders/sixel.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/coders/sixel.c b/coders/sixel.c +index adcd205..0d903bc 100644 +--- a/coders/sixel.c ++++ b/coders/sixel.c +@@ -1265,7 +1265,7 @@ static MagickBooleanType WriteSIXELImage(const ImageInfo *image_info, + opacity=(-1); + if (image->matte == MagickFalse) + { +- if ((image->storage_class == DirectClass) || (image->colors > 256)) ++ if ((image->storage_class == DirectClass) || (image->colors > SIXEL_PALETTE_MAX)) + (void) SetImageType(image,PaletteType); + } + else +@@ -1277,7 +1277,7 @@ static MagickBooleanType WriteSIXELImage(const ImageInfo *image_info, + /* + Identify transparent colormap index. + */ +- if ((image->storage_class == DirectClass) || (image->colors > 256)) ++ if ((image->storage_class == DirectClass) || (image->colors > SIXEL_PALETTE_MAX)) + (void) SetImageType(image,PaletteBilevelMatteType); + for (i=0; i < (ssize_t) image->colors; i++) + if (image->colormap[i].opacity != OpaqueOpacity) +@@ -1316,6 +1316,8 @@ static MagickBooleanType WriteSIXELImage(const ImageInfo *image_info, + image->colormap[opacity].blue=image->transparent_color.blue; + } + } ++ if (image->colors > SIXEL_PALETTE_MAX) ++ return(MagickFalse); + /* + SIXEL header. + */ diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-32636.patch imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-32636.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-32636.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-32636.patch 2026-04-12 19:56:20.000000000 +0000 @@ -0,0 +1,589 @@ +From: Cristy +Date: Thu, 12 Mar 2026 19:05:20 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-354p-2qx7-jg9g + +(cherry picked from commit a04a9a514c70c9533ccb9f6ff80102a1b9a6445b) + +The NewXMLTree method contains a bug that could result in a crash due to an out of write bounds of a single zero byte + +origin: https://github.com/ImageMagick/ImageMagick6/commit/a04a9a514c70c9533ccb9f6ff80102a1b9a6445b +--- + magick/distort.c | 36 +++++++++---------- + magick/fx.c | 28 +++++++-------- + magick/image-private.h | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++ + magick/morphology.c | 46 ++++++++++++------------ + magick/resample.c | 4 +-- + magick/resource.c | 2 ++ + magick/xml-tree.c | 2 +- + 7 files changed, 158 insertions(+), 58 deletions(-) + +diff --git a/magick/distort.c b/magick/distort.c +index 460e8cd..15d1a58 100644 +--- a/magick/distort.c ++++ b/magick/distort.c +@@ -149,7 +149,7 @@ static size_t poly_number_terms(double order) + if ( order < 1 || order > 5 || + ( order != floor(order) && (order-1.5) > MagickEpsilon) ) + return 0; /* invalid polynomial order */ +- return((size_t) floor((order+1)*(order+2)/2)); ++ return(CastDoubleToSizeT(floor((order+1.0)*(order+2.0)/2.0))); + } + + static double poly_basis_fn(ssize_t n, double x, double y) +@@ -1050,7 +1050,7 @@ static double *GenerateCoefficients(const Image *image, + /* first two coefficients hold polynomial order information */ + coeff[0] = arguments[0]; + coeff[1] = (double) poly_number_terms(arguments[0]); +- nterms = (size_t) coeff[1]; ++ nterms = CastDoubleToSizeT(coeff[1]); + + /* create matrix, a fake vectors matrix, and least sqs terms */ + matrix = AcquireMagickMatrix(nterms,nterms); +@@ -1714,8 +1714,8 @@ MagickExport Image *DistortImage(const Image *image,DistortImageMethod method, + "Invalid number of args: 2 only"); + return((Image *) NULL); + } +- distort_image=DistortResizeImage(image,(size_t) arguments[0], +- (size_t) arguments[1],exception); ++ distort_image=DistortResizeImage(image,CastDoubleToSizeT(arguments[0]), ++ CastDoubleToSizeT(arguments[1]),exception); + return(distort_image); + } + +@@ -1884,9 +1884,9 @@ MagickExport Image *DistortImage(const Image *image,DistortImageMethod method, + * for reversibility in a DePolar-Polar cycle */ + fix_bounds = MagickFalse; + geometry.x = geometry.y = 0; +- geometry.height = (size_t) ceil(coeff[0]-coeff[1]); +- geometry.width = (size_t) +- ceil((coeff[0]-coeff[1])*(coeff[5]-coeff[4])*0.5); ++ geometry.height = CastDoubleToSizeT(ceil(coeff[0]-coeff[1])); ++ geometry.width = CastDoubleToSizeT(ceil((coeff[0]-coeff[1])* ++ (coeff[5]-coeff[4])*0.5)); + /* correct scaling factors relative to new size */ + coeff[6]=(coeff[5]-coeff[4])/geometry.width; /* changed width */ + coeff[7]=(coeff[0]-coeff[1])/geometry.height; /* should be about 1.0 */ +@@ -1898,8 +1898,8 @@ MagickExport Image *DistortImage(const Image *image,DistortImageMethod method, + * center, or pixel edge. This allows for reversibility of the + * distortion */ + geometry.x = geometry.y = 0; +- geometry.width = (size_t) ceil( 2.0*coeff[1]*tan(coeff[0]/2.0) ); +- geometry.height = (size_t) ceil( 2.0*coeff[3]/cos(coeff[0]/2.0) ); ++ geometry.width = CastDoubleToSizeT(ceil( 2.0*coeff[1]*tan(coeff[0]/2.0) )); ++ geometry.height = CastDoubleToSizeT(ceil( 2.0*coeff[3]/cos(coeff[0]/2.0) )); + /* correct center of distortion relative to new size */ + coeff[4] = (double) geometry.width/2.0; + coeff[5] = (double) geometry.height/2.0; +@@ -1911,8 +1911,8 @@ MagickExport Image *DistortImage(const Image *image,DistortImageMethod method, + /* direct calculation center is either pixel center, or pixel edge + * so as to allow reversibility of the image distortion */ + geometry.x = geometry.y = 0; +- geometry.width = (size_t) ceil(coeff[0]*coeff[1]); /* FOV * radius */ +- geometry.height = (size_t) (2*coeff[3]); /* input image height */ ++ geometry.width = CastDoubleToSizeT(ceil(coeff[0]*coeff[1])); /* FOV * radius */ ++ geometry.height = CastDoubleToSizeT(2.0*coeff[3]); /* input image height */ + /* correct center of distortion relative to new size */ + coeff[4] = (double) geometry.width/2.0; + coeff[5] = (double) geometry.height/2.0; +@@ -1943,8 +1943,8 @@ MagickExport Image *DistortImage(const Image *image,DistortImageMethod method, + if ( fix_bounds ) { + geometry.x = (ssize_t) floor(min.x-0.5); + geometry.y = (ssize_t) floor(min.y-0.5); +- geometry.width=(size_t) ceil(max.x-geometry.x+0.5); +- geometry.height=(size_t) ceil(max.y-geometry.y+0.5); ++ geometry.width=CastDoubleToSizeT(ceil(max.x-geometry.x+0.5)); ++ geometry.height=CastDoubleToSizeT(ceil(max.y-geometry.y+0.5)); + } + + } /* end bestfit destination image calculations */ +@@ -2135,7 +2135,7 @@ MagickExport Image *DistortImage(const Image *image,DistortImageMethod method, + } + case PolynomialDistortion: + { +- size_t nterms = (size_t) coeff[1]; ++ size_t nterms = CastDoubleToSizeT(coeff[1]); + (void) FormatLocaleFile(stderr, + "Polynomial (order %lg, terms %lu), FX Equivelent\n",coeff[0], + (unsigned long) nterms); +@@ -2304,10 +2304,10 @@ MagickExport Image *DistortImage(const Image *image,DistortImageMethod method, + output_scaling = 1.0; + if (artifact != (const char *) NULL) { + output_scaling = fabs(StringToDouble(artifact,(char **) NULL)); +- geometry.width=(size_t) (output_scaling*geometry.width+0.5); +- geometry.height=(size_t) (output_scaling*geometry.height+0.5); +- geometry.x=(ssize_t) (output_scaling*geometry.x+0.5); +- geometry.y=(ssize_t) (output_scaling*geometry.y+0.5); ++ geometry.width=CastDoubleToSizeT(output_scaling*geometry.width+0.5); ++ geometry.height=CastDoubleToSizeT(output_scaling*geometry.height+0.5); ++ geometry.x=CastDoubleToSsizeT(output_scaling*geometry.x+0.5); ++ geometry.y=CastDoubleToSsizeT(output_scaling*geometry.y+0.5); + if ( output_scaling < 0.1 ) { + coeff = (double *) RelinquishMagickMemory(coeff); + (void) ThrowMagickException(exception,GetMagickModule(), +diff --git a/magick/fx.c b/magick/fx.c +index 094a44b..b7942e9 100644 +--- a/magick/fx.c ++++ b/magick/fx.c +@@ -1485,7 +1485,7 @@ static double FxEvaluateSubexpression(FxInfo *fx_info,const ChannelType channel, + { + *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta, + exception); +- *beta=(double) (~(size_t) *beta); ++ *beta=(double) (~CastDoubleToSizeT(*beta)); + FxReturn(*beta); + } + case '!': +@@ -1545,7 +1545,7 @@ static double FxEvaluateSubexpression(FxInfo *fx_info,const ChannelType channel, + ClearMagickException(exception); + *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta, + exception); +- value=(double) ((size_t) (alpha+0.5) & (size_t) (*beta+0.5)); ++ value=(double) (CastDoubleToSizeT(alpha+0.5) & CastDoubleToSizeT(*beta+0.5)); + if (SetFxSymbolValue(fx_info,subexpression,value) == MagickFalse) + return(0.0); + FxReturn(*beta); +@@ -1564,7 +1564,7 @@ static double FxEvaluateSubexpression(FxInfo *fx_info,const ChannelType channel, + ClearMagickException(exception); + *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta, + exception); +- value=(double) ((size_t) (alpha+0.5) | (size_t) (*beta+0.5)); ++ value=(double) (CastDoubleToSizeT(alpha+0.5) | CastDoubleToSizeT(*beta+0.5)); + if (SetFxSymbolValue(fx_info,subexpression,value) == MagickFalse) + return(0.0); + FxReturn(*beta); +@@ -1583,13 +1583,13 @@ static double FxEvaluateSubexpression(FxInfo *fx_info,const ChannelType channel, + ClearMagickException(exception); + *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta, + exception); +- if ((size_t) (*beta+0.5) >= (8*sizeof(size_t))) ++ if (CastDoubleToSizeT(*beta+0.5) >= (8*sizeof(size_t))) + { + (void) ThrowMagickException(exception,GetMagickModule(), + OptionError,"ShiftCountOverflow","`%s'",subexpression); + FxReturn(0.0); + } +- value=(double) ((size_t) (alpha+0.5) << (size_t) (*beta+0.5)); ++ value=(double) (CastDoubleToSizeT(alpha+0.5) << CastDoubleToSizeT(*beta+0.5)); + if (SetFxSymbolValue(fx_info,subexpression,value) == MagickFalse) + return(0.0); + FxReturn(*beta); +@@ -1608,13 +1608,13 @@ static double FxEvaluateSubexpression(FxInfo *fx_info,const ChannelType channel, + ClearMagickException(exception); + *beta=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta, + exception); +- if ((size_t) (*beta+0.5) >= (8*sizeof(size_t))) ++ if (CastDoubleToSizeT(*beta+0.5) >= (8*sizeof(size_t))) + { + (void) ThrowMagickException(exception,GetMagickModule(), + OptionError,"ShiftCountOverflow","`%s'",subexpression); + FxReturn(0.0); + } +- value=(double) ((size_t) (alpha+0.5) >> (size_t) (*beta+0.5)); ++ value=(double) (CastDoubleToSizeT(alpha+0.5) >> CastDoubleToSizeT(*beta+0.5)); + if (SetFxSymbolValue(fx_info,subexpression,value) == MagickFalse) + return(0.0); + FxReturn(*beta); +@@ -1769,26 +1769,26 @@ static double FxEvaluateSubexpression(FxInfo *fx_info,const ChannelType channel, + { + gamma=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta, + exception); +- if ((size_t) (gamma+0.5) >= (8*sizeof(size_t))) ++ if (CastDoubleToSizeT(gamma+0.5) >= (8*sizeof(size_t))) + { + (void) ThrowMagickException(exception,GetMagickModule(), + OptionError,"ShiftCountOverflow","`%s'",subexpression); + FxReturn(0.0); + } +- *beta=(double) ((size_t) (alpha+0.5) << (size_t) (gamma+0.5)); ++ *beta=(double) (CastDoubleToSizeT(alpha+0.5) << CastDoubleToSizeT(gamma+0.5)); + FxReturn(*beta); + } + case RightShiftOperator: + { + gamma=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta, + exception); +- if ((size_t) (gamma+0.5) >= (8*sizeof(size_t))) ++ if (CastDoubleToSizeT(gamma+0.5) >= (8*sizeof(size_t))) + { + (void) ThrowMagickException(exception,GetMagickModule(), + OptionError,"ShiftCountOverflow","`%s'",subexpression); + FxReturn(0.0); + } +- *beta=(double) ((size_t) (alpha+0.5) >> (size_t) (gamma+0.5)); ++ *beta=(double) (CastDoubleToSizeT(alpha+0.5) >> CastDoubleToSizeT(gamma+0.5)); + FxReturn(*beta); + } + case '<': +@@ -1831,14 +1831,14 @@ static double FxEvaluateSubexpression(FxInfo *fx_info,const ChannelType channel, + { + gamma=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta, + exception); +- *beta=(double) ((size_t) (alpha+0.5) & (size_t) (gamma+0.5)); ++ *beta=(double) (CastDoubleToSizeT(alpha+0.5) & CastDoubleToSizeT(gamma+0.5)); + FxReturn(*beta); + } + case '|': + { + gamma=FxEvaluateSubexpression(fx_info,channel,x,y,++p,depth+1,beta, + exception); +- *beta=(double) ((size_t) (alpha+0.5) | (size_t) (gamma+0.5)); ++ *beta=(double) (CastDoubleToSizeT(alpha+0.5) | CastDoubleToSizeT(gamma+0.5)); + FxReturn(*beta); + } + case LogicalAndOperator: +@@ -1954,7 +1954,7 @@ static double FxEvaluateSubexpression(FxInfo *fx_info,const ChannelType channel, + { + gamma=FxEvaluateSubexpression(fx_info,channel,x,y,expression+1,depth+1, + beta,exception); +- FxReturn((double) (~(size_t) (gamma+0.5))); ++ FxReturn((double) (~CastDoubleToSizeT(gamma+0.5))); + } + case 'A': + case 'a': +diff --git a/magick/image-private.h b/magick/image-private.h +index 3ba4383..0521409 100644 +--- a/magick/image-private.h ++++ b/magick/image-private.h +@@ -47,6 +47,8 @@ extern "C" { + #define MAGICK_SIZE_MAX (SIZE_MAX) + #define MAGICK_SSIZE_MAX (SSIZE_MAX) + #define MAGICK_SSIZE_MIN (-(SSIZE_MAX)-1) ++#define MAGICK_UCHAR_MAX (UCHAR_MAX) ++#define MAGICK_USHORT_MAX (USHRT_MAX) + #define MatteColor "#bdbdbd" /* gray */ + #define PSDensityGeometry "72.0x72.0" + #define PSPageGeometry "612x792" +@@ -128,6 +130,102 @@ static inline QuantumAny CastDoubleToQuantumAny(const double x) + return((QuantumAny) value); + } + ++static inline size_t CastDoubleToSizeT(const double x) ++{ ++ double ++ value; ++ ++ if (IsNaN(x) != 0) ++ { ++ errno=ERANGE; ++ return(0); ++ } ++ value=(x < 0.0) ? ceil(x) : floor(x); ++ if (value < 0.0) ++ { ++ errno=ERANGE; ++ return(0); ++ } ++ if (value >= ((double) MAGICK_SIZE_MAX)) ++ { ++ errno=ERANGE; ++ return(MAGICK_SIZE_MAX); ++ } ++ return((size_t) value); ++} ++ ++static inline ssize_t CastDoubleToSsizeT(const double x) ++{ ++ double ++ value; ++ ++ if (IsNaN(x) != 0) ++ { ++ errno=ERANGE; ++ return(0); ++ } ++ value=(x < 0.0) ? ceil(x) : floor(x); ++ if (value < ((double) MAGICK_SSIZE_MIN)) ++ { ++ errno=ERANGE; ++ return(MAGICK_SSIZE_MIN); ++ } ++ if (value >= ((double) MAGICK_SSIZE_MAX)) ++ { ++ errno=ERANGE; ++ return(MAGICK_SSIZE_MAX); ++ } ++ return((ssize_t) value); ++} ++ ++static inline unsigned char CastDoubleToUChar(const double x) ++{ ++ double ++ value; ++ ++ if (IsNaN(x) != 0) ++ { ++ errno=ERANGE; ++ return(0); ++ } ++ value=(x < 0.0) ? ceil(x) : floor(x); ++ if (value < 0.0) ++ { ++ errno=ERANGE; ++ return(0); ++ } ++ if (value >= ((double) MAGICK_UCHAR_MAX)) ++ { ++ errno=ERANGE; ++ return(MAGICK_UCHAR_MAX); ++ } ++ return((unsigned char) value); ++} ++ ++static inline unsigned short CastDoubleToUShort(const double x) ++{ ++ double ++ value; ++ ++ if (IsNaN(x) != 0) ++ { ++ errno=ERANGE; ++ return(0); ++ } ++ value=(x < 0.0) ? ceil(x) : floor(x); ++ if (value < 0.0) ++ { ++ errno=ERANGE; ++ return(0); ++ } ++ if (value >= ((double) MAGICK_USHORT_MAX)) ++ { ++ errno=ERANGE; ++ return(MAGICK_USHORT_MAX); ++ } ++ return((unsigned short) value); ++} ++ + static inline size_t CastDoubleToUnsigned(const double x) + { + double +diff --git a/magick/morphology.c b/magick/morphology.c +index d44c649..66957ee 100644 +--- a/magick/morphology.c ++++ b/magick/morphology.c +@@ -100,9 +100,9 @@ static inline size_t fact(size_t n) + return(f); + } + #elif 1 /* glibc floating point alternatives */ +-#define fact(n) ((size_t)tgamma((double)n+1)) ++#define fact(n) (CastDoubleToSizeT(tgamma((double)n+1.0))) + #else +-#define fact(n) ((size_t)lgamma((double)n+1)) ++#define fact(n) (CastDoubleToSizeT(lgamma((double)n+1))) + #endif + + /* Currently these are only internal to this module */ +@@ -277,8 +277,8 @@ static KernelInfo *ParseKernelArray(const char *kernel_string) + args.rho = 1.0; /* then width = 1 */ + if ( args.sigma < 1.0 ) /* if height too small */ + args.sigma = args.rho; /* then height = width */ +- kernel->width = (size_t)args.rho; +- kernel->height = (size_t)args.sigma; ++ kernel->width = CastDoubleToSizeT(args.rho); ++ kernel->height = CastDoubleToSizeT(args.sigma); + + /* Offset Handling and Checks */ + if ( args.xi < 0.0 || args.psi < 0.0 ) +@@ -306,7 +306,7 @@ static KernelInfo *ParseKernelArray(const char *kernel_string) + (void) GetNextToken(p,&p,MaxTextExtent,token); + } + /* set the size of the kernel - old sized square */ +- kernel->width = kernel->height= (size_t) sqrt((double) i+1.0); ++ kernel->width = kernel->height= CastDoubleToSizeT(sqrt((double) i+1.0)); + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + p=(const char *) kernel_string; + while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == '\'')) +@@ -1058,7 +1058,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + A, B, R; + + if ( args->rho >= 1.0 ) +- kernel->width = (size_t)args->rho*2+1; ++ kernel->width = CastDoubleToSizeT(args->rho*2.0+1.0); + else if ( (type != DoGKernel) || (sigma >= sigma2) ) + kernel->width = GetOptimalKernelWidth2D(args->rho,sigma); + else +@@ -1149,7 +1149,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + alpha, beta; + + if ( args->rho >= 1.0 ) +- kernel->width = (size_t)args->rho*2+1; ++ kernel->width = CastDoubleToSizeT(args->rho*2.0+1.0); + else + kernel->width = GetOptimalKernelWidth1D(args->rho,sigma); + kernel->height = 1; +@@ -1238,7 +1238,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + if ( args->rho < 1.0 ) + kernel->width = (GetOptimalKernelWidth1D(args->rho,sigma)-1)/2+1; + else +- kernel->width = (size_t)args->rho; ++ kernel->width = CastDoubleToSizeT(args->rho); + kernel->x = kernel->y = 0; + kernel->height = 1; + kernel->negative_range = kernel->positive_range = 0.0; +@@ -1306,7 +1306,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + if (args->rho < 1.0) + kernel->width = kernel->height = 3; /* default radius = 1 */ + else +- kernel->width = kernel->height = ((size_t)args->rho)*2+1; ++ kernel->width = kernel->height = (CastDoubleToSizeT(args->rho)*2.0+1.0); + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + + order_f = fact(kernel->width-1); +@@ -1540,7 +1540,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + if (args->rho < 1.0) + kernel->width = kernel->height = 3; /* default radius = 1 */ + else +- kernel->width = kernel->height = ((size_t)args->rho)*2+1; ++ kernel->width = kernel->height = CastDoubleToSizeT(args->rho*2.0+1.0); + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + + kernel->values=(double *) AcquireAlignedMemory(kernel->width, +@@ -1567,7 +1567,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + if (args->rho < 1.0) + kernel->width = kernel->height = 3; /* default radius = 1 */ + else +- kernel->width = kernel->height = (size_t) (2*args->rho+1); ++ kernel->width = kernel->height = CastDoubleToSizeT(2.0*args->rho+1.0); + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + scale = args->sigma; + } +@@ -1575,8 +1575,8 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + /* NOTE: user defaults set in "AcquireKernelInfo()" */ + if ( args->rho < 1.0 || args->sigma < 1.0 ) + return(DestroyKernelInfo(kernel)); /* invalid args given */ +- kernel->width = (size_t)args->rho; +- kernel->height = (size_t)args->sigma; ++ kernel->width = CastDoubleToSizeT(args->rho); ++ kernel->height = CastDoubleToSizeT(args->sigma); + if ( args->xi < 0.0 || args->xi > (double)kernel->width || + args->psi < 0.0 || args->psi > (double)kernel->height ) + return(DestroyKernelInfo(kernel)); /* invalid args given */ +@@ -1602,7 +1602,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + if (args->rho < 1.0) + kernel->width = kernel->height = 5; /* default radius = 2 */ + else +- kernel->width = kernel->height = ((size_t)args->rho)*2+1; ++ kernel->width = kernel->height = CastDoubleToSizeT(args->rho*2.0+1.0); + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + + kernel->values=(double *) AcquireAlignedMemory(kernel->width, +@@ -1628,7 +1628,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + if (args->rho < 0.4) /* default radius approx 4.3 */ + kernel->width = kernel->height = 9L, limit = 18L; + else +- kernel->width = kernel->height = (size_t)fabs(args->rho)*2+1; ++ kernel->width = kernel->height = CastDoubleToSizeT(fabs(args->rho)*2.0+1.0); + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + + kernel->values=(double *) AcquireAlignedMemory(kernel->width, +@@ -1650,7 +1650,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + if (args->rho < 1.0) + kernel->width = kernel->height = 5; /* default radius 2 */ + else +- kernel->width = kernel->height = ((size_t)args->rho)*2+1; ++ kernel->width = kernel->height = CastDoubleToSizeT(args->rho*2.0+1.0); + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + + kernel->values=(double *) AcquireAlignedMemory(kernel->width, +@@ -1671,7 +1671,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + if (args->rho < 1.0) + kernel->width = kernel->height = 5; /* default radius 2 */ + else +- kernel->width = kernel->height = ((size_t)args->rho)*2+1; ++ kernel->width = kernel->height = CastDoubleToSizeT(args->rho*2.0+1.0); + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + + kernel->values=(double *) AcquireAlignedMemory(kernel->width, +@@ -1700,13 +1700,13 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + + if (args->rho < args->sigma) + { +- kernel->width = ((size_t)args->sigma)*2+1; ++ kernel->width = CastDoubleToSizeT(args->sigma*2.0+1.0); + limit1 = (ssize_t)(args->rho*args->rho); + limit2 = (ssize_t)(args->sigma*args->sigma); + } + else + { +- kernel->width = ((size_t)args->rho)*2+1; ++ kernel->width = CastDoubleToSizeT(args->rho*2.0+1.0); + limit1 = (ssize_t)(args->sigma*args->sigma); + limit2 = (ssize_t)(args->rho*args->rho); + } +@@ -2082,7 +2082,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + if (args->rho < 1.0) + kernel->width = kernel->height = 3; /* default radius = 1 */ + else +- kernel->width = kernel->height = ((size_t)args->rho)*2+1; ++ kernel->width = kernel->height = CastDoubleToSizeT(args->rho*2.0+1.0); + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + + kernel->values=(double *) AcquireAlignedMemory(kernel->width, +@@ -2102,7 +2102,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + if (args->rho < 1.0) + kernel->width = kernel->height = 3; /* default radius = 1 */ + else +- kernel->width = kernel->height = ((size_t)args->rho)*2+1; ++ kernel->width = kernel->height = CastDoubleToSizeT(args->rho*2.0+1.0); + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + + kernel->values=(double *) AcquireAlignedMemory(kernel->width, +@@ -2122,7 +2122,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + if (args->rho < 2.0) + kernel->width = kernel->height = 5; /* default/minimum radius = 2 */ + else +- kernel->width = kernel->height = ((size_t)args->rho)*2+1; ++ kernel->width = kernel->height = CastDoubleToSizeT(args->rho*2.0+1.0); + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + + kernel->values=(double *) AcquireAlignedMemory(kernel->width, +@@ -2147,7 +2147,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type, + if (args->rho < 1.0) + kernel->width = kernel->height = 3; /* default radius = 1 */ + else +- kernel->width = kernel->height = ((size_t)args->rho)*2+1; ++ kernel->width = kernel->height = CastDoubleToSizeT(args->rho*2.0+1.0); + kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2; + + kernel->values=(double *) AcquireAlignedMemory(kernel->width, +diff --git a/magick/resample.c b/magick/resample.c +index d5c7225..68b1131 100644 +--- a/magick/resample.c ++++ b/magick/resample.c +@@ -559,8 +559,8 @@ MagickExport MagickBooleanType ResamplePixelColor( + Determine the parellelogram bounding box fitted to the ellipse + centered at u0,v0. This area is bounding by the lines... + */ +- v1 = (ssize_t)ceil(v0 - resample_filter->Vlimit); /* range of scan lines */ +- v2 = (ssize_t)floor(v0 + resample_filter->Vlimit); ++ v1 = CastDoubleToSsizeT(ceil(v0 - resample_filter->Vlimit)); /* range of scan lines */ ++ v2 = CastDoubleToSsizeT(floor(v0 + resample_filter->Vlimit)); + + /* scan line start and width accross the parallelogram */ + u1 = u0 + (v1-v0)*resample_filter->slope - resample_filter->Uwidth; +diff --git a/magick/resource.c b/magick/resource.c +index 5c62c7b..7fd4226 100644 +--- a/magick/resource.c ++++ b/magick/resource.c +@@ -845,6 +845,8 @@ MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type) + resource; + + resource=0; ++ if (type >= NumberOfResourceTypes) ++ return(resource); + if (resource_semaphore[type] == (SemaphoreInfo *) NULL) + ActivateSemaphoreInfo(&resource_semaphore[type]); + LockSemaphoreInfo(resource_semaphore[type]); +diff --git a/magick/xml-tree.c b/magick/xml-tree.c +index 4de9b40..ddf594c 100644 +--- a/magick/xml-tree.c ++++ b/magick/xml-tree.c +@@ -1359,7 +1359,7 @@ static char *ConvertUTF16ToUTF8(const char *content,size_t *length) + } + } + *length=(size_t) j; +- utf8=(char *) ResizeQuantumMemory(utf8,*length,sizeof(*utf8)); ++ utf8=(char *) ResizeQuantumMemory(utf8,(*length+1),sizeof(*utf8)); + if (utf8 != (char *) NULL) + utf8[*length]='\0'; + return(utf8); diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-33535.patch imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-33535.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-33535.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-33535.patch 2026-04-12 19:56:20.000000000 +0000 @@ -0,0 +1,40 @@ +From: Cristy +Date: Sat, 21 Mar 2026 12:09:36 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-mw3m-pqr2-qv7c + +(cherry picked from commit 3bdfa6a73a6c0ba5f2d0986cd2a1892c37f796f3) + +origin: https://github.com/ImageMagick/ImageMagick6/commit/3bdfa6a73a6c0ba5f2d0986cd2a1892c37f796f3 +--- + magick/display.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/magick/display.c b/magick/display.c +index 55d648f..54bc39f 100644 +--- a/magick/display.c ++++ b/magick/display.c +@@ -6643,14 +6643,21 @@ static CommandType XImageWindowCommand(Display *display, + + if ((key_symbol >= XK_0) && (key_symbol <= XK_9)) + { ++ size_t ++ length; ++ + if (((last_symbol < XK_0) || (last_symbol > XK_9))) + { + *delta='\0'; + resource_info->quantum=1; + } + last_symbol=key_symbol; +- delta[strlen(delta)+1]='\0'; +- delta[strlen(delta)]=Digits[key_symbol-XK_0]; ++ length=strlen(delta); ++ if (length < MagickPathExtent) ++ { ++ delta[length]=Digits[key_symbol-XK_0]; ++ delta[length+1]='\0'; ++ } + resource_info->quantum=StringToLong(delta); + return(NullCommand); + } diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-33536.patch imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-33536.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-33536.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/CVE-2026-33536.patch 2026-04-12 19:56:20.000000000 +0000 @@ -0,0 +1,42 @@ +From: Cristy +Date: Fri, 20 Mar 2026 21:53:12 -0400 +Subject: + https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-8793-7xv6-82cf + +(cherry picked from commit 3ed2120f70ee9ff0c6cac2375e5821c52c381b4c) + +origin: https://github.com/ImageMagick/ImageMagick6/commit/3ed2120f70ee9ff0c6cac2375e5821c52c381b4c +--- + magick/image.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/magick/image.c b/magick/image.c +index 67050d2..296ad74 100644 +--- a/magick/image.c ++++ b/magick/image.c +@@ -1740,7 +1740,8 @@ MagickExport size_t InterpretImageFilename(const ImageInfo *image_info, + format_specifier[MagickPathExtent]; + + size_t +- length = cursor-specifier_start; ++ length = cursor-specifier_start, ++ pattern_length; + + ssize_t + count; +@@ -1749,10 +1750,13 @@ MagickExport size_t InterpretImageFilename(const ImageInfo *image_info, + "%%%.*s%c",(int) length,specifier_start,*cursor); + count=FormatLocaleString(pattern,sizeof(pattern),format_specifier, + value); +- if ((count <= 0) || ((p-filename+count) >= MagickPathExtent)) ++ pattern_length=strlen(pattern); ++ if ((count <= 0) || ((size_t) count != pattern_length)) ++ return(0); ++ if ((p-filename+pattern_length) >= MagickPathExtent) + return(0); + (void) CopyMagickString(p,pattern,MagickPathExtent-(p-filename)); +- p+=strlen(pattern); ++ p+=pattern_length; + cursor++; + continue; + } diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/GetMagickThreadFilename.patch imagemagick-6.9.11.60+dfsg/debian/patches/GetMagickThreadFilename.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/GetMagickThreadFilename.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/GetMagickThreadFilename.patch 2026-04-12 19:56:20.000000000 +0000 @@ -0,0 +1,45 @@ +From: =?utf-8?q?Bastien_Roucari=C3=A8s?= +Date: Tue, 17 Mar 2026 23:40:21 +0100 +Subject: Add GetMagickThreadFilename + +Extract GetMagickThreadFilename from 6.9.13-41 +--- + magick/thread-private.h | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/magick/thread-private.h b/magick/thread-private.h +index 70034db..c6a4ef2 100644 +--- a/magick/thread-private.h ++++ b/magick/thread-private.h +@@ -66,6 +66,31 @@ static inline MagickThreadType GetMagickThreadId(void) + #endif + } + ++ ++static inline void GetMagickThreadFilename(const char *filename, ++ char *thread_filename) ++{ ++ MagickThreadType ++ id; ++ ++ char ++ thread_id[2*sizeof(id)+1]; ++ ++ ssize_t ++ i; ++ ++ unsigned char ++ bytes[sizeof(id)]; ++ ++ id=GetMagickThreadId(); ++ (void) memcpy(bytes,&id,sizeof(id)); ++ for (i=0; i < (ssize_t) sizeof(bytes); i++) ++ (void) FormatLocaleString(thread_id+2*i,MagickPathExtent,"%02x",bytes[i]); ++ thread_id[sizeof(thread_id)-1]='\0'; ++ (void) FormatLocaleString(thread_filename,MagickPathExtent,"%s|%s",thread_id, ++ filename); ++} ++ + static inline size_t GetMagickThreadSignature(void) + { + #if defined(MAGICKCORE_THREAD_SUPPORT) diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/i386-fix.patch imagemagick-6.9.11.60+dfsg/debian/patches/i386-fix.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/i386-fix.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/i386-fix.patch 2026-04-12 19:56:20.000000000 +0000 @@ -0,0 +1,29 @@ +From: =?utf-8?q?Bastien_Roucari=C3=A8s?= +Date: Tue, 31 Mar 2026 23:26:29 +0200 +Subject: Fix failure to convert for i386 + +forwarded: mail to upstream +--- + coders/svg.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/coders/svg.c b/coders/svg.c +index 7d1c40f..ca51674 100644 +--- a/coders/svg.c ++++ b/coders/svg.c +@@ -320,11 +320,11 @@ static Image *RenderSVGImage(const ImageInfo *image_info,Image *image, + sqrt(image->x_resolution*image->y_resolution)); + (void) FormatLocaleString(background,MagickPathExtent, + "rgb(%.20g%%,%.20g%%,%.20g%%)", +- 100.0*QuantumScale*(MagickRealType) image->background_color.red, +- 100.0*QuantumScale*(MagickRealType) image->background_color.green, +- 100.0*QuantumScale*(MagickRealType) image->background_color.blue); ++ 100.0*QuantumScale*(double) image->background_color.red, ++ 100.0*QuantumScale*(double) image->background_color.green, ++ 100.0*QuantumScale*(double) image->background_color.blue); + (void) FormatLocaleString(opacity,MagickPathExtent,"%.20g",QuantumScale* +- ((MagickRealType) QuantumRange-(MagickRealType) ++ ((double) QuantumRange-(double) + image->background_color.opacity)); + (void) FormatLocaleString(command,MagickPathExtent, + GetDelegateCommands(delegate_info),input_filename,output_filename,density, diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/port-msl-svg-to-6.9.13-41.patch imagemagick-6.9.11.60+dfsg/debian/patches/port-msl-svg-to-6.9.13-41.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/port-msl-svg-to-6.9.13-41.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/port-msl-svg-to-6.9.13-41.patch 2026-04-12 19:56:20.000000000 +0000 @@ -0,0 +1,2270 @@ +From: =?utf-8?q?Bastien_Roucari=C3=A8s?= +Date: Tue, 17 Mar 2026 23:36:51 +0100 +Subject: port coders/msl.c coders/svg.c to 6.9.13-41 + +--- + coders/msl.c | 179 +++++++--- + coders/svg.c | 1060 ++++++++++++++++++++++++++++++++-------------------------- + 2 files changed, 713 insertions(+), 526 deletions(-) + +diff --git a/coders/msl.c b/coders/msl.c +index fe36f12..27f24a9 100644 +--- a/coders/msl.c ++++ b/coders/msl.c +@@ -19,13 +19,13 @@ + % December 2001 % + % % + % % +-% Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization % ++% Copyright 1999 ImageMagick Studio LLC, a non-profit organization % + % dedicated to making software imaging solutions freely available. % + % % + % 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, % +@@ -89,29 +89,25 @@ + #include "magick/string_.h" + #include "magick/string-private.h" + #include "magick/transform.h" ++#include "magick/thread-private.h" + #include "magick/threshold.h" + #include "magick/utility.h" + #include "magick/visual-effects.h" + #if defined(MAGICKCORE_XML_DELEGATE) +-# if defined(MAGICKCORE_WINDOWS_SUPPORT) +-# if !defined(__MINGW32__) +-# include +-# endif +-# endif + # include + # include + # include + #endif + + /* +- Define Declatations. ++ Define Declarations. + */ + #define ThrowMSLException(severity,tag,reason) \ + (void) ThrowMagickException(msl_info->exception,GetMagickModule(),severity, \ + tag,"`%s'",reason); + + /* +- Typedef declaractions. ++ Typedef declarations. + */ + typedef struct _MSLGroupInfo + { +@@ -153,6 +149,11 @@ typedef struct _MSLInfo + document; + #endif + } MSLInfo; ++/* ++ Global declarations. ++*/ ++static SplayTreeInfo ++ *msl_tree = (SplayTreeInfo *) NULL; + + /* + Forward declarations. +@@ -354,12 +355,18 @@ static xmlEntityPtr MSLGetParameterEntity(void *context,const xmlChar *name) + return(xmlGetParameterEntity(msl_info->document,name)); + } + ++static void MSLError(void *,const char *,...) ++ magick_attribute((__format__ (__printf__,2,3))); ++ + static void MSLEntityDeclaration(void *context,const xmlChar *name,int type, + const xmlChar *public_id,const xmlChar *system_id,xmlChar *content) + { + MSLInfo + *msl_info; + ++ xmlEntityPtr ++ entity; ++ + /* + An entity definition has been parsed. + */ +@@ -370,12 +377,16 @@ static void MSLEntityDeclaration(void *context,const xmlChar *name,int type, + content); + msl_info=(MSLInfo *) context; + if (msl_info->parser->inSubset == 1) +- (void) xmlAddDocEntity(msl_info->document,name,type,public_id,system_id, ++ entity=xmlAddDocEntity(msl_info->document,name,type,public_id,system_id, + content); + else + if (msl_info->parser->inSubset == 2) +- (void) xmlAddDtdEntity(msl_info->document,name,type,public_id,system_id, ++ entity=xmlAddDtdEntity(msl_info->document,name,type,public_id,system_id, + content); ++ else ++ return; ++ if (entity == (xmlEntityPtr) NULL) ++ MSLError(msl_info,"NULL entity"); + } + + static void MSLAttributeDeclaration(void *context,const xmlChar *element, +@@ -556,7 +567,7 @@ static ssize_t MSLPushImage(MSLInfo *msl_info,Image *image) + ssize_t + n; + +- if (image != (Image *) NULL) ++ if ((IsEventLogging() != MagickFalse) && (image != (Image *) NULL)) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); + assert(msl_info != (MSLInfo *) NULL); + msl_info->n++; +@@ -577,10 +588,8 @@ static ssize_t MSLPushImage(MSLInfo *msl_info,Image *image) + msl_info->image_info[n]=CloneImageInfo(msl_info->image_info[n-1]); + msl_info->draw_info[n]=CloneDrawInfo(msl_info->image_info[n-1], + msl_info->draw_info[n-1]); +- if (image == (Image *) NULL) +- msl_info->attributes[n]=AcquireImage(msl_info->image_info[n]); +- else +- msl_info->attributes[n]=CloneImage(image,0,0,MagickTrue,&image->exception); ++ msl_info->attributes[n]=CloneImage(msl_info->attributes[n-1],0,0,MagickTrue, ++ &image->exception); + msl_info->image[n]=(Image *) image; + if ((msl_info->image_info[n] == (ImageInfo *) NULL) || + (msl_info->attributes[n] == (Image *) NULL)) +@@ -664,7 +673,6 @@ static void MSLStartElement(void *context,const xmlChar *tag, + */ + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + " SAX.startElement(%s",tag); +- exception=AcquireExceptionInfo(); + msl_info=(MSLInfo *) context; + if (msl_info->depth++ > MagickMaxRecursionDepth) + { +@@ -673,6 +681,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + xmlStopParser((xmlParserCtxtPtr) context); + return; + } ++ exception=AcquireExceptionInfo(); + n=msl_info->n; + keyword=(const char *) NULL; + value=(char *) NULL; +@@ -1367,6 +1376,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + break; + } + ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag); ++ break; + } + case 'C': + case 'c': +@@ -1917,7 +1927,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + + attribute=GetImageProperty(msl_info->attributes[j],"id"); + if ((attribute != (const char *) NULL) && +- (LocaleCompare(value,value) == 0)) ++ (LocaleCompare(attribute,value) == 0)) + { + SetImageType(composite_image,TrueColorMatteType); + (void) CompositeImage(composite_image, +@@ -2300,6 +2310,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + break; + } + ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag); ++ break; + } + case 'D': + case 'd': +@@ -2723,6 +2734,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + break; + } + ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag); ++ break; + } + case 'E': + case 'e': +@@ -2938,6 +2950,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + break; + } + ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag); ++ break; + } + case 'F': + case 'f': +@@ -3178,6 +3191,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + break; + } + ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag); ++ break; + } + case 'G': + case 'g': +@@ -3337,6 +3351,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + break; + } + ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword); ++ break; + } + case 'W': + case 'w': +@@ -3349,6 +3364,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + break; + } + ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword); ++ break; + } + default: + { +@@ -3375,6 +3391,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + break; + } + ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag); ++ break; + } + case 'I': + case 'i': +@@ -3507,6 +3524,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + break; + } + ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag); ++ break; + } + case 'L': + case 'l': +@@ -3583,6 +3601,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + break; + } + } ++ break; + } + case 'M': + case 'm': +@@ -4066,6 +4085,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + break; + } + ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag); ++ break; + } + case 'N': + case 'n': +@@ -4188,6 +4208,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + break; + } + ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag); ++ break; + } + case 'O': + case 'o': +@@ -4333,6 +4354,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + break; + } + ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag); ++ break; + } + case 'P': + case 'p': +@@ -4473,6 +4495,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + break; + } + ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag); ++ break; + } + case 'Q': + case 'q': +@@ -4950,6 +4973,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + break; + } + ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag); ++ break; + } + case 'R': + case 'r': +@@ -5065,22 +5089,28 @@ static void MSLStartElement(void *context,const xmlChar *tag, + { + if (LocaleCompare(keyword,"filename") == 0) + { ++ char ++ thread_filename[MagickPathExtent]; ++ + Image + *next = (Image *) NULL; + + if (value == (char *) NULL) + break; ++ GetMagickThreadFilename(value,thread_filename); ++ if (GetValueFromSplayTree(msl_tree,thread_filename) != (const char *) NULL) ++ { ++ (void) ThrowMagickException(msl_info->exception, ++ GetMagickModule(),DrawError, ++ "VectorGraphicsNestedTooDeeply","`%s'",value); ++ break; ++ } ++ (void) AddValueToSplayTree(msl_tree,ConstantString( ++ thread_filename),(void *) 1); + *msl_info->image_info[n]->magick='\0'; + (void) CopyMagickString(msl_info->image_info[n]->filename, + value,MagickPathExtent); +- (void) SetImageInfo(msl_info->image_info[n],1,exception); +- if (LocaleCompare(msl_info->image_info[n]->magick,"msl") != 0) +- next=ReadImage(msl_info->image_info[n],exception); +- else +- (void) ThrowMagickException(msl_info->exception, +- GetMagickModule(),DrawError, +- "VectorGraphicsNestedTooDeeply","`%s'", +- msl_info->image_info[n]->filename); ++ next=ReadImage(msl_info->image_info[n],exception); + CatchException(exception); + if (next == (Image *) NULL) + continue; +@@ -5806,6 +5836,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + break; + } + ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag); ++ break; + } + case 'S': + case 's': +@@ -6070,6 +6101,11 @@ static void MSLStartElement(void *context,const xmlChar *tag, + for (i=0; (attributes[i] != (const xmlChar *) NULL); i++) + { + keyword=(const char *) attributes[i++]; ++ if (msl_info->attributes[n] == (Image *) NULL) ++ { ++ ThrowMSLException(OptionError,"NoImagesDefined",keyword); ++ break; ++ } + attribute=InterpretImageProperties(msl_info->image_info[n], + msl_info->attributes[n],(const char *) attributes[i]); + CloneString(&value,attribute); +@@ -6707,7 +6743,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + (const char *) tag); + break; + } +- geometry_info.rho=QuantumRange/2.0; ++ geometry_info.rho=(MagickRealType) QuantumRange/2.0; + if (attributes != (const xmlChar **) NULL) + for (i=0; (attributes[i] != (const xmlChar *) NULL); i++) + { +@@ -7146,6 +7182,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + break; + } + ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag); ++ break; + } + case 'T': + case 't': +@@ -7330,6 +7367,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + } + } + ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag); ++ break; + } + case 'W': + case 'w': +@@ -7363,6 +7401,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + break; + } + (void) SetMSLAttributes(msl_info,keyword,value); ++ break; + } + default: + { +@@ -7391,6 +7430,7 @@ static void MSLStartElement(void *context,const xmlChar *tag, + } + } + ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag); ++ break; + } + default: + { +@@ -7447,16 +7487,21 @@ static void MSLEndElement(void *context,const xmlChar *tag) + { + if (LocaleCompare((const char *) tag, "group") == 0 ) + { +- if (msl_info->group_info[msl_info->number_groups-1].numImages > 0 ) ++ if ((msl_info->number_groups > 0) && ++ (msl_info->group_info[msl_info->number_groups-1].numImages > 0)) + { + ssize_t i = (ssize_t) + (msl_info->group_info[msl_info->number_groups-1].numImages); +- while ( i-- ) ++ ++ while ((i--) && (msl_info->n > 0)) + { + if (msl_info->image[msl_info->n] != (Image *) NULL) +- msl_info->image[msl_info->n]=DestroyImage(msl_info->image[msl_info->n]); +- msl_info->attributes[msl_info->n]=DestroyImage(msl_info->attributes[msl_info->n]); +- msl_info->image_info[msl_info->n]=DestroyImageInfo(msl_info->image_info[msl_info->n]); ++ msl_info->image[msl_info->n]=DestroyImage( ++ msl_info->image[msl_info->n]); ++ msl_info->attributes[msl_info->n]=DestroyImage( ++ msl_info->attributes[msl_info->n]); ++ msl_info->image_info[msl_info->n]=DestroyImageInfo( ++ msl_info->image_info[msl_info->n]); + msl_info->n--; + } + } +@@ -7468,8 +7513,19 @@ static void MSLEndElement(void *context,const xmlChar *tag) + case 'i': + { + if (LocaleCompare((const char *) tag, "image") == 0) +- MSLPopImage(msl_info); +- break; ++ { ++ if (msl_info->image_info[msl_info->n] != (ImageInfo *) NULL) ++ { ++ char ++ thread_filename[MagickPathExtent]; ++ ++ GetMagickThreadFilename( ++ msl_info->image_info[msl_info->n]->filename,thread_filename); ++ (void) DeleteNodeFromSplayTree(msl_tree,thread_filename); ++ } ++ MSLPopImage(msl_info); ++ } ++ break; + } + case 'L': + case 'l': +@@ -7566,6 +7622,10 @@ static void MSLReference(void *context,const xmlChar *name) + " SAX.reference(%s)",name); + msl_info=(MSLInfo *) context; + parser=msl_info->parser; ++ if (parser == (xmlParserCtxtPtr) NULL) ++ return; ++ if (parser->node == (xmlNodePtr) NULL) ++ return; + if (*name == '#') + (void) xmlAddChild(parser->node,xmlNewCharRef(msl_info->document,name)); + else +@@ -7681,6 +7741,7 @@ static void MSLError(void *context,const char *format,...) + #endif + ThrowMSLException(DelegateFatalError,reason,"SAX error"); + va_end(operands); ++ xmlStopParser(msl_info->parser); + } + + static void MSLCDataBlock(void *context,const xmlChar *value,int length) +@@ -7796,12 +7857,12 @@ static MagickBooleanType ProcessMSLScript(const ImageInfo *image_info, + int + status; + +- ssize_t +- n; +- + MSLInfo + msl_info; + ++ ssize_t ++ n; ++ + xmlSAXHandler + sax_modules; + +@@ -7813,10 +7874,10 @@ static MagickBooleanType ProcessMSLScript(const ImageInfo *image_info, + */ + assert(image_info != (const ImageInfo *) NULL); + assert(image_info->signature == MagickCoreSignature); +- if (image_info->debug != MagickFalse) ++ assert(image != (Image **) NULL); ++ if (IsEventLogging() != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", + image_info->filename); +- assert(image != (Image **) NULL); + msl_image=AcquireImage(image_info); + status=OpenBlob(image_info,msl_image,ReadBinaryBlobMode,exception); + if (status == MagickFalse) +@@ -7852,14 +7913,13 @@ static MagickBooleanType ProcessMSLScript(const ImageInfo *image_info, + *msl_info.image_info=CloneImageInfo(image_info); + *msl_info.draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL); + *msl_info.attributes=AcquireImage(image_info); ++ (void) SetImageExtent(*msl_info.attributes,1,1); + msl_info.group_info[0].numImages=0; + /* the first slot is used to point to the MSL file image */ + *msl_info.image=msl_image; + if (*image != (Image *) NULL) +- MSLPushImage(&msl_info,CloneImage(*image,0,0,MagickTrue,exception)); +- *image=(Image *) NULL; ++ MSLPushImage(&msl_info,*image); + xmlInitParser(); +- (void) xmlSubstituteEntitiesDefault(1); + (void) memset(&sax_modules,0,sizeof(sax_modules)); + sax_modules.internalSubset=MSLInternalSubset; + sax_modules.isStandalone=MSLIsStandalone; +@@ -7891,6 +7951,15 @@ static MagickBooleanType ProcessMSLScript(const ImageInfo *image_info, + sax_handler=(&sax_modules); + msl_info.parser=xmlCreatePushParserCtxt(sax_handler,&msl_info,(char *) NULL,0, + msl_image->filename); ++ if (msl_info.parser != (xmlParserCtxtPtr) NULL) ++ { ++ const char *option = GetImageOption(image_info,"msl:parse-huge"); ++ if ((option != (char *) NULL) && (IsStringTrue(option) != MagickFalse)) ++ (void) xmlCtxtUseOptions(msl_info.parser,XML_PARSE_HUGE); ++ option=GetImageOption(image_info,"msl:substitute-entities"); ++ if ((option != (char *) NULL) && (IsStringTrue(option) != MagickFalse)) ++ (void) xmlCtxtUseOptions(msl_info.parser,XML_PARSE_NOENT); ++ } + while (ReadBlobString(msl_image,message) != (char *) NULL) + { + n=(ssize_t) strlen(message); +@@ -7899,7 +7968,9 @@ static MagickBooleanType ProcessMSLScript(const ImageInfo *image_info, + status=xmlParseChunk(msl_info.parser,message,(int) n,MagickFalse); + if (status != 0) + break; +- (void) xmlParseChunk(msl_info.parser," ",1,MagickFalse); ++ status=xmlParseChunk(msl_info.parser," ",1,MagickFalse); ++ if (status != 0) ++ break; + if (msl_info.exception->severity >= ErrorException) + break; + } +@@ -7908,15 +7979,22 @@ static MagickBooleanType ProcessMSLScript(const ImageInfo *image_info, + /* + Free resources. + */ ++ MSLEndDocument(&msl_info); + if (msl_info.parser->myDoc != (xmlDocPtr) NULL) +- xmlFreeDoc(msl_info.parser->myDoc); ++ { ++ xmlFreeDoc(msl_info.parser->myDoc); ++ msl_info.parser->myDoc=(xmlDocPtr) NULL; ++ } + xmlFreeParserCtxt(msl_info.parser); ++ xmlFreeDoc(msl_info.document); ++ msl_info.document=(xmlDocPtr) NULL; + (void) LogMagickEvent(CoderEvent,GetMagickModule(),"end SAX"); + if (*image == (Image *) NULL) + *image=CloneImage(*msl_info.image,0,0,MagickTrue,exception); + while (msl_info.n >= 0) + { +- msl_info.image[msl_info.n]=DestroyImage(msl_info.image[msl_info.n]); ++ if (msl_info.image[msl_info.n] != (Image *) NULL) ++ msl_info.image[msl_info.n]=DestroyImage(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( +@@ -7947,11 +8025,11 @@ static Image *ReadMSLImage(const ImageInfo *image_info,ExceptionInfo *exception) + */ + assert(image_info != (const ImageInfo *) NULL); + assert(image_info->signature == MagickCoreSignature); +- if (image_info->debug != MagickFalse) +- (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", +- image_info->filename); + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickCoreSignature); ++ if (IsEventLogging() != MagickFalse) ++ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", ++ image_info->filename); + image=(Image *) NULL; + (void) ProcessMSLScript(image_info,&image,exception); + return(GetFirstImageInList(image)); +@@ -7986,6 +8064,9 @@ ModuleExport size_t RegisterMSLImage(void) + MagickInfo + *entry; + ++ if (msl_tree == (SplayTreeInfo *) NULL) ++ msl_tree=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory, ++ (void *(*)(void *)) NULL); + entry=SetMagickInfo("MSL"); + #if defined(MAGICKCORE_XML_DELEGATE) + entry->decoder=(DecodeImageHandler *) ReadMSLImage; +@@ -8311,4 +8392,6 @@ static MagickBooleanType SetMSLAttributes(MSLInfo *msl_info,const char *keyword, + ModuleExport void UnregisterMSLImage(void) + { + (void) UnregisterMagickInfo("MSL"); ++ if (msl_tree != (SplayTreeInfo *) NULL) ++ msl_tree=DestroySplayTree(msl_tree); + } +diff --git a/coders/svg.c b/coders/svg.c +index 011417d..cf85539 100644 +--- a/coders/svg.c ++++ b/coders/svg.c +@@ -18,13 +18,13 @@ + % March 2000 % + % % + % % +-% Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization % ++% Copyright 1999 ImageMagick Studio LLC, a non-profit organization % + % dedicated to making software imaging solutions freely available. % + % % + % 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, % +@@ -68,20 +68,18 @@ + #include "magick/option.h" + #include "magick/pixel-accessor.h" + #include "magick/pixel-private.h" ++#include "magick/policy.h" + #include "magick/property.h" + #include "magick/quantum-private.h" + #include "magick/resource_.h" + #include "magick/static.h" + #include "magick/string_.h" + #include "magick/string-private.h" ++#include "magick/thread-private.h" + #include "magick/token.h" + #include "magick/utility.h" ++ + #if defined(MAGICKCORE_XML_DELEGATE) +-# if defined(MAGICKCORE_WINDOWS_SUPPORT) +-# if !defined(__MINGW32__) +-# include +-# endif +-# endif + # include + # include + # include +@@ -195,6 +193,17 @@ typedef struct _SVGInfo + svgDepth; + } SVGInfo; + ++/* ++ Global declarations. ++*/ ++#if defined(MAGICKCORE_RSVG_DELEGATE) ++static SemaphoreInfo ++ *rsvg_semaphore = (SemaphoreInfo *) NULL; ++#endif ++ ++static SplayTreeInfo ++ *svg_tree = (SplayTreeInfo *) NULL; ++ + /* + Static declarations. + */ +@@ -256,7 +265,7 @@ static MagickBooleanType IsSVG(const unsigned char *magick,const size_t length) + % % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % +-% ReadSVGImage() reads a Scalable Vector Gaphics file and returns it. It ++% ReadSVGImage() reads a Scalable Vector Graphics file and returns it. It + % allocates the memory necessary for the new Image structure and returns a + % pointer to the new image. + % +@@ -302,28 +311,29 @@ static Image *RenderSVGImage(const ImageInfo *image_info,Image *image, + delegate_info=GetDelegateInfo("svg:decode",(char *) NULL,exception); + if (delegate_info == (const DelegateInfo *) NULL) + return((Image *) NULL); +- status=AcquireUniqueSymbolicLink(image->filename,input_filename); ++ if (AcquireUniqueSymbolicLink(image->filename,input_filename) == MagickFalse) ++ return((Image *) NULL); + (void) AcquireUniqueFilename(unique); + (void) FormatLocaleString(output_filename,MagickPathExtent,"%s.png",unique); +- (void) AcquireUniqueFilename(unique); ++ (void) RelinquishUniqueFileResource(unique); + density=AcquireString(""); + (void) FormatLocaleString(density,MagickPathExtent,"%.20g", +- ceil(sqrt(image->x_resolution*image->y_resolution)-0.5)); ++ sqrt(image->x_resolution*image->y_resolution)); + (void) FormatLocaleString(background,MagickPathExtent, + "rgb(%.20g%%,%.20g%%,%.20g%%)", +- 100.0*QuantumScale*image->background_color.red, +- 100.0*QuantumScale*image->background_color.green, +- 100.0*QuantumScale*image->background_color.blue); ++ 100.0*QuantumScale*(MagickRealType) image->background_color.red, ++ 100.0*QuantumScale*(MagickRealType) image->background_color.green, ++ 100.0*QuantumScale*(MagickRealType) image->background_color.blue); + (void) FormatLocaleString(opacity,MagickPathExtent,"%.20g",QuantumScale* +- (QuantumRange-image->background_color.opacity)-MagickEpsilon); ++ ((MagickRealType) QuantumRange-(MagickRealType) ++ image->background_color.opacity)); + (void) FormatLocaleString(command,MagickPathExtent, + GetDelegateCommands(delegate_info),input_filename,output_filename,density, +- background,opacity,unique); ++ background,opacity); + density=DestroyString(density); + status=ExternalDelegateCommand(MagickFalse,image_info->verbose,command, + (char *) NULL,exception); +- (void) RelinquishUniqueFileResource(unique); +- (void) RelinquishUniqueFileResource(input_filename); ++ (void) (unique); + if ((status == 0) && (stat(output_filename,&attributes) == 0) && + (attributes.st_size > 0)) + { +@@ -355,6 +365,299 @@ static Image *RenderSVGImage(const ImageInfo *image_info,Image *image, + return((Image *) NULL); + } + ++#if defined(MAGICKCORE_RSVG_DELEGATE) ++static Image *RenderRSVGImage(const ImageInfo *image_info,Image *image, ++ ExceptionInfo *exception) ++{ ++#if defined(MAGICKCORE_CAIRO_DELEGATE) ++ cairo_surface_t ++ *cairo_surface; ++ ++ cairo_t ++ *cairo_image; ++ ++ MagickBooleanType ++ apply_density; ++ ++ MemoryInfo ++ *pixel_info; ++ ++ unsigned char ++ *p; ++ ++ RsvgDimensionData ++ dimension_info; ++ ++ unsigned char ++ *pixels; ++ ++#else ++ GdkPixbuf ++ *pixel_buffer; ++ ++ const guchar ++ *p; ++#endif ++ ++ GError ++ *error; ++ ++ Image ++ *next; ++ ++ MagickBooleanType ++ status; ++ ++ PixelPacket ++ fill_color; ++ ++ PixelPacket ++ *q; ++ ++ RsvgHandle ++ *svg_handle; ++ ++ ssize_t ++ n, ++ x, ++ y; ++ ++ unsigned char ++ *buffer; ++ ++ buffer=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent, ++ sizeof(*buffer)); ++ if (buffer == (unsigned char *) NULL) ++ ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); ++ { ++#if LIBRSVG_CHECK_VERSION(2,40,3) ++ const char *option = GetImageOption(image_info,"svg:parse-huge"); ++ if (option == (char *) NULL) ++ option=GetImageOption(image_info,"svg:xml-parse-huge"); ++ if ((option != (char *) NULL) && (IsStringTrue(option) != MagickFalse)) ++ svg_handle=rsvg_handle_new_with_flags(RSVG_HANDLE_FLAG_UNLIMITED); ++ else ++#endif ++ svg_handle=rsvg_handle_new(); ++ } ++ if (svg_handle == (RsvgHandle *) NULL) ++ { ++ buffer=(unsigned char *) RelinquishMagickMemory(buffer); ++ ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); ++ } ++ rsvg_handle_set_base_uri(svg_handle,image_info->filename); ++ if ((fabs(image->x_resolution) > MagickEpsilon) && ++ (fabs(image->y_resolution) > MagickEpsilon)) ++ rsvg_handle_set_dpi_x_y(svg_handle,image->x_resolution,image->y_resolution); ++ while ((n=ReadBlob(image,MagickMaxBufferExtent-1,buffer)) != 0) ++ { ++ buffer[n]='\0'; ++ error=(GError *) NULL; ++ (void) rsvg_handle_write(svg_handle,buffer,n,&error); ++ if (error != (GError *) NULL) ++ { ++ g_error_free(error); ++ break; ++ } ++ } ++ buffer=(unsigned char *) RelinquishMagickMemory(buffer); ++ error=(GError *) NULL; ++ rsvg_handle_close(svg_handle,&error); ++ if (error != (GError *) NULL) ++ { ++ g_error_free(error); ++ g_object_unref(svg_handle); ++ ThrowReaderException(CorruptImageError,"UnableToReadImageData"); ++ } ++#if defined(MAGICKCORE_CAIRO_DELEGATE) ++ apply_density=MagickTrue; ++ rsvg_handle_get_dimensions(svg_handle,&dimension_info); ++ if ((image->x_resolution > 0.0) && (image->y_resolution > 0.0)) ++ { ++ RsvgDimensionData ++ dpi_dimension_info; ++ ++ /* ++ We should not apply the density when the internal 'factor' is 'i'. ++ This can be checked by using the trick below. ++ */ ++ rsvg_handle_set_dpi_x_y(svg_handle,image->x_resolution*256, ++ image->y_resolution*256.0); ++ rsvg_handle_get_dimensions(svg_handle,&dpi_dimension_info); ++ if ((fabs((double) dpi_dimension_info.width-dimension_info.width) >= MagickEpsilon) || ++ (fabs((double) dpi_dimension_info.height-dimension_info.height) >= MagickEpsilon)) ++ apply_density=MagickFalse; ++ rsvg_handle_set_dpi_x_y(svg_handle,image->x_resolution, ++ image->y_resolution); ++ } ++ if (image_info->size != (char *) NULL) ++ { ++ (void) GetGeometry(image_info->size,(ssize_t *) NULL, ++ (ssize_t *) NULL,&image->columns,&image->rows); ++ if ((image->columns != 0) || (image->rows != 0)) ++ { ++ image->x_resolution=DefaultSVGDensity*image->columns/ ++ dimension_info.width; ++ image->y_resolution=DefaultSVGDensity*image->rows/ ++ dimension_info.height; ++ if (fabs(image->x_resolution) < MagickEpsilon) ++ image->x_resolution=image->y_resolution; ++ else ++ if (fabs(image->y_resolution) < MagickEpsilon) ++ image->y_resolution=image->x_resolution; ++ else ++ image->x_resolution=image->y_resolution=MagickMin( ++ image->x_resolution,image->y_resolution); ++ apply_density=MagickTrue; ++ } ++ } ++ if (apply_density != MagickFalse) ++ { ++ image->columns=image->x_resolution*dimension_info.width/ ++ DefaultSVGDensity; ++ image->rows=image->y_resolution*dimension_info.height/ ++ DefaultSVGDensity; ++ } ++ else ++ { ++ image->columns=dimension_info.width; ++ image->rows=dimension_info.height; ++ } ++ pixel_info=(MemoryInfo *) NULL; ++#else ++ pixel_buffer=rsvg_handle_get_pixbuf(svg_handle); ++ rsvg_handle_free(svg_handle); ++ image->columns=gdk_pixbuf_get_width(pixel_buffer); ++ image->rows=gdk_pixbuf_get_height(pixel_buffer); ++#endif ++ image->matte=MagickTrue; ++ if (image_info->ping == MagickFalse) ++ { ++#if defined(MAGICKCORE_CAIRO_DELEGATE) ++ size_t ++ stride; ++#endif ++ ++ status=SetImageExtent(image,image->columns,image->rows); ++ if (status == MagickFalse) ++ { ++#if !defined(MAGICKCORE_CAIRO_DELEGATE) ++ g_object_unref(G_OBJECT(pixel_buffer)); ++#endif ++ g_object_unref(svg_handle); ++ InheritException(exception,&image->exception); ++ ThrowReaderException(MissingDelegateError, ++ "NoDecodeDelegateForThisImageFormat"); ++ } ++ ++#if defined(MAGICKCORE_CAIRO_DELEGATE) ++ stride=4*image->columns; ++#if defined(MAGICKCORE_PANGOCAIRO_DELEGATE) ++ stride=(size_t) cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, ++ (int) image->columns); ++#endif ++ pixel_info=AcquireVirtualMemory(stride,image->rows*sizeof(*pixels)); ++ if (pixel_info == (MemoryInfo *) NULL) ++ { ++ g_object_unref(svg_handle); ++ ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); ++ } ++ pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); ++#endif ++ (void) SetImageBackgroundColor(image); ++#if defined(MAGICKCORE_CAIRO_DELEGATE) ++ cairo_surface=cairo_image_surface_create_for_data(pixels, ++ CAIRO_FORMAT_ARGB32,(int) image->columns,(int) image->rows,(int) ++ stride); ++ if ((cairo_surface == (cairo_surface_t *) NULL) || ++ (cairo_surface_status(cairo_surface) != CAIRO_STATUS_SUCCESS)) ++ { ++ if (cairo_surface != (cairo_surface_t *) NULL) ++ cairo_surface_destroy(cairo_surface); ++ pixel_info=RelinquishVirtualMemory(pixel_info); ++ g_object_unref(svg_handle); ++ ThrowReaderException(ResourceLimitError, ++ "MemoryAllocationFailed"); ++ } ++ cairo_image=cairo_create(cairo_surface); ++ cairo_set_operator(cairo_image,CAIRO_OPERATOR_CLEAR); ++ cairo_paint(cairo_image); ++ cairo_set_operator(cairo_image,CAIRO_OPERATOR_OVER); ++ if (apply_density != MagickFalse) ++ cairo_scale(cairo_image,image->x_resolution/DefaultSVGDensity, ++ image->y_resolution/DefaultSVGDensity); ++ rsvg_handle_render_cairo(svg_handle,cairo_image); ++ cairo_destroy(cairo_image); ++ cairo_surface_destroy(cairo_surface); ++ g_object_unref(svg_handle); ++ p=pixels; ++#else ++ p=gdk_pixbuf_get_pixels(pixel_buffer); ++#endif ++ for (y=0; y < (ssize_t) image->rows; y++) ++ { ++ q=GetAuthenticPixels(image,0,y,image->columns,1,exception); ++ if (q == (PixelPacket *) NULL) ++ break; ++ for (x=0; x < (ssize_t) image->columns; x++) ++ { ++#if defined(MAGICKCORE_CAIRO_DELEGATE) ++ fill_color.blue=ScaleCharToQuantum(*p++); ++ fill_color.green=ScaleCharToQuantum(*p++); ++ fill_color.red=ScaleCharToQuantum(*p++); ++#else ++ fill_color.red=ScaleCharToQuantum(*p++); ++ fill_color.green=ScaleCharToQuantum(*p++); ++ fill_color.blue=ScaleCharToQuantum(*p++); ++#endif ++ fill_color.opacity=QuantumRange-ScaleCharToQuantum(*p++); ++#if defined(MAGICKCORE_CAIRO_DELEGATE) ++ { ++ double ++ gamma; ++ ++ gamma=1.0-QuantumScale*(MagickRealType) fill_color.opacity; ++ gamma=MagickSafeReciprocal(gamma); ++ fill_color.red=(Quantum) ((MagickRealType) fill_color.red*gamma); ++ fill_color.green=(Quantum) ((MagickRealType) fill_color.green* ++ gamma); ++ fill_color.blue=(Quantum) ((MagickRealType) fill_color.blue*gamma); ++ } ++#endif ++ MagickCompositeOver(&fill_color,fill_color.opacity,q, ++ (MagickRealType) q->opacity,q); ++ q++; ++ } ++ if (SyncAuthenticPixels(image,exception) == MagickFalse) ++ break; ++ if (image->previous == (Image *) NULL) ++ { ++ status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) ++ y,image->rows); ++ if (status == MagickFalse) ++ break; ++ } ++ } ++ } ++#if defined(MAGICKCORE_CAIRO_DELEGATE) ++ else ++ g_object_unref(svg_handle); ++ if (pixel_info != (MemoryInfo *) NULL) ++ pixel_info=RelinquishVirtualMemory(pixel_info); ++#else ++ g_object_unref(G_OBJECT(pixel_buffer)); ++#endif ++ (void) CloseBlob(image); ++ for (next=GetFirstImageInList(image); next != (Image *) NULL; ) ++ { ++ (void) CopyMagickString(next->filename,image->filename,MaxTextExtent); ++ (void) CopyMagickString(next->magick,image->magick,MaxTextExtent); ++ next=GetNextImageInList(next); ++ } ++ return(GetFirstImageInList(image)); ++} ++#endif ++ + #if defined(MAGICKCORE_XML_DELEGATE) + static SVGInfo *AcquireSVGInfo(void) + { +@@ -400,8 +703,9 @@ static double GetUserSpaceCoordinateValue(const SVGInfo *svg_info,int type, + double + value; + +- (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",string); + assert(string != (const char *) NULL); ++ if (IsEventLogging() != MagickFalse) ++ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",string); + p=(const char *) string; + (void) GetNextToken(p,&p,MaxTextExtent,token); + value=StringToDouble(token,&next_token); +@@ -413,13 +717,13 @@ static double GetUserSpaceCoordinateValue(const SVGInfo *svg_info,int type, + + if (type > 0) + { +- if (svg_info->view_box.width == 0.0) ++ if (svg_info->view_box.width < MagickEpsilon) + return(0.0); + return(svg_info->view_box.width*value/100.0); + } + if (type < 0) + { +- if (svg_info->view_box.height == 0.0) ++ if (svg_info->view_box.height < MagickEpsilon) + return(0.0); + return(svg_info->view_box.height*value/100.0); + } +@@ -562,12 +866,18 @@ static xmlEntityPtr SVGGetParameterEntity(void *context,const xmlChar *name) + return(xmlGetParameterEntity(svg_info->document,name)); + } + ++static void SVGError(void *,const char *,...) ++ magick_attribute((__format__ (__printf__,2,3))); ++ + static void SVGEntityDeclaration(void *context,const xmlChar *name,int type, + const xmlChar *public_id,const xmlChar *system_id,xmlChar *content) + { + SVGInfo + *svg_info; + ++ xmlEntityPtr ++ entity; ++ + /* + An entity definition has been parsed. + */ +@@ -577,12 +887,16 @@ static void SVGEntityDeclaration(void *context,const xmlChar *name,int type, + system_id != (xmlChar *) NULL ? (const char *) system_id : "none",content); + svg_info=(SVGInfo *) context; + if (svg_info->parser->inSubset == 1) +- (void) xmlAddDocEntity(svg_info->document,name,type,public_id,system_id, ++ entity=xmlAddDocEntity(svg_info->document,name,type,public_id,system_id, + content); + else + if (svg_info->parser->inSubset == 2) +- (void) xmlAddDtdEntity(svg_info->document,name,type,public_id,system_id, ++ entity=xmlAddDtdEntity(svg_info->document,name,type,public_id,system_id, + content); ++ else ++ return; ++ if (entity == (xmlEntityPtr) NULL) ++ SVGError(svg_info,"NULL entity"); + } + + static void SVGAttributeDeclaration(void *context,const xmlChar *element, +@@ -673,7 +987,7 @@ static void SVGStripString(const MagickBooleanType trim,char *message) + for ( ; *p != '\0'; p++) + if ((*p == '*') && (*(p+1) == '/')) + { +- p+=2; ++ p+=(ptrdiff_t) 2; + break; + } + if (*p == '\0') +@@ -706,7 +1020,7 @@ static void SVGStripString(const MagickBooleanType trim,char *message) + Convert newlines to a space. + */ + for (p=message; *p != '\0'; p++) +- if (*p == '\n') ++ if ((*p == '\n') || (*p == '\r')) + *p=' '; + } + +@@ -761,15 +1075,27 @@ static char **SVGKeyValuePairs(void *context,const int key_sentinel, + return((char **) NULL); + } + } +- tokens[i]=AcquireString(p); ++ tokens[i]=(char *) AcquireMagickMemory((size_t) (q-p+2)); ++ if (tokens[i] == (char *) NULL) ++ { ++ (void) ThrowMagickException(svg_info->exception,GetMagickModule(), ++ ResourceLimitError,"MemoryAllocationFailed","`%s'",text); ++ break; ++ } + (void) CopyMagickString(tokens[i],p,(size_t) (q-p+1)); + SVGStripString(MagickTrue,tokens[i]); + i++; + p=q+1; + } +- tokens[i]=AcquireString(p); +- (void) CopyMagickString(tokens[i],p,(size_t) (q-p+1)); +- SVGStripString(MagickTrue,tokens[i++]); ++ tokens[i]=(char *) AcquireMagickMemory((size_t) (q-p+2)); ++ if (tokens[i] == (char *) NULL) ++ (void) ThrowMagickException(svg_info->exception,GetMagickModule(), ++ ResourceLimitError,"MemoryAllocationFailed","`%s'",text); ++ else ++ { ++ (void) CopyMagickString(tokens[i],p,(size_t) (q-p+1)); ++ SVGStripString(MagickTrue,tokens[i++]); ++ } + tokens[i]=(char *) NULL; + *number_tokens=(size_t) i; + return(tokens); +@@ -802,6 +1128,19 @@ static void SVGNotationDeclaration(void *context,const xmlChar *name, + name,public_id,system_id); + } + ++static inline char *SVGEscapeString(const char* value) ++{ ++ char ++ *escaped_value, ++ *p; ++ ++ escaped_value=EscapeString(value,'\"'); ++ for (p=escaped_value; *p != '\0'; p++) ++ if ((*p == '\n') || (*p == '\r')) ++ *p=' '; ++ return(escaped_value); ++} ++ + static void SVGProcessStyleElement(void *context,const xmlChar *name, + const char *style) + { +@@ -809,8 +1148,7 @@ static void SVGProcessStyleElement(void *context,const xmlChar *name, + background[MagickPathExtent], + *color, + *keyword, +- *units, +- *value; ++ *units; + + char + **tokens; +@@ -829,22 +1167,25 @@ static void SVGProcessStyleElement(void *context,const xmlChar *name, + tokens=SVGKeyValuePairs(context,':',';',style,&number_tokens); + if (tokens == (char **) NULL) + return; +- for (i=0; i < (ssize_t) (number_tokens-1); i+=2) ++ for (i=0; i < ((ssize_t) number_tokens-1); i+=2) + { + keyword=(char *) tokens[i]; +- value=(char *) tokens[i+1]; + if (LocaleCompare(keyword,"font-size") != 0) + continue; +- svg_info->pointsize=GetUserSpaceCoordinateValue(svg_info,0,value); ++ svg_info->pointsize=GetUserSpaceCoordinateValue(svg_info,0, ++ (char *) tokens[i+1]); + (void) FormatLocaleFile(svg_info->file,"font-size %g\n", + svg_info->pointsize); + } + color=AcquireString("none"); + units=AcquireString("userSpaceOnUse"); +- for (i=0; i < (ssize_t) (number_tokens-1); i+=2) ++ for (i=0; i < ((ssize_t) number_tokens-1); i+=2) + { ++ char ++ *value; ++ + keyword=(char *) tokens[i]; +- value=(char *) tokens[i+1]; ++ value=SVGEscapeString((const char *) tokens[i+1]); + (void) LogMagickEvent(CoderEvent,GetMagickModule()," %s: %s",keyword, + value); + switch (*keyword) +@@ -1127,6 +1468,7 @@ static void SVGProcessStyleElement(void *context,const xmlChar *name, + default: + break; + } ++ value=DestroyString(value); + } + if (units != (char *) NULL) + units=DestroyString(units); +@@ -1189,7 +1531,7 @@ static void SVGStartDocument(void *context) + if (svg_info->document == (xmlDocPtr) NULL) + return; + if (parser->encoding == NULL) +- svg_info->document->encoding=(const xmlChar *) NULL; ++ svg_info->document->encoding=NULL; + else + svg_info->document->encoding=xmlStrdup(parser->encoding); + svg_info->document->standalone=parser->standalone; +@@ -1249,8 +1591,7 @@ static void SVGStartElement(void *context,const xmlChar *name, + + const char + *keyword, +- *p, +- *value; ++ *p; + + size_t + number_tokens; +@@ -1290,7 +1631,6 @@ static void SVGStartElement(void *context,const xmlChar *name, + *id='\0'; + *token='\0'; + *background='\0'; +- value=(const char *) NULL; + if ((LocaleCompare((char *) name,"image") == 0) || + (LocaleCompare((char *) name,"pattern") == 0) || + (LocaleCompare((char *) name,"rect") == 0) || +@@ -1303,8 +1643,11 @@ static void SVGStartElement(void *context,const xmlChar *name, + if (attributes != (const xmlChar **) NULL) + for (i=0; (attributes[i] != (const xmlChar *) NULL); i+=2) + { ++ char ++ *value; ++ + keyword=(const char *) attributes[i]; +- value=(const char *) attributes[i+1]; ++ value=SVGEscapeString((const char *) attributes[i+1]); + switch (*keyword) + { + case 'C': +@@ -1431,6 +1774,7 @@ static void SVGStartElement(void *context,const xmlChar *name, + default: + break; + } ++ value=DestroyString(value); + } + if (strchr((char *) name,':') != (char *) NULL) + { +@@ -1596,7 +1940,7 @@ static void SVGStartElement(void *context,const xmlChar *name, + (void) FormatLocaleFile(svg_info->file,"fill-opacity 1\n"); + (void) FormatLocaleFile(svg_info->file,"stroke \"none\"\n"); + (void) FormatLocaleFile(svg_info->file,"stroke-width 1\n"); +- (void) FormatLocaleFile(svg_info->file,"stroke-opacity 1\n"); ++ (void) FormatLocaleFile(svg_info->file,"stroke-opacity 0\n"); + (void) FormatLocaleFile(svg_info->file,"fill-rule nonzero\n"); + break; + } +@@ -1655,8 +1999,11 @@ static void SVGStartElement(void *context,const xmlChar *name, + if (attributes != (const xmlChar **) NULL) + for (i=0; (attributes[i] != (const xmlChar *) NULL); i+=2) + { ++ char ++ *value; ++ + keyword=(const char *) attributes[i]; +- value=(const char *) attributes[i+1]; ++ value=SVGEscapeString((const char *) attributes[i+1]); + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + " %s = %s",keyword,value); + switch (*keyword) +@@ -1856,14 +2203,17 @@ static void SVGStartElement(void *context,const xmlChar *name, + tokens=SVGKeyValuePairs(context,'(',')',value,&number_tokens); + if (tokens == (char **) NULL) + break; +- for (j=0; j < (ssize_t) (number_tokens-1); j+=2) ++ for (j=0; j < ((ssize_t) number_tokens-1); j+=2) + { ++ char ++ *token_value; ++ + keyword=(char *) tokens[j]; + if (keyword == (char *) NULL) + continue; +- value=(char *) tokens[j+1]; ++ token_value=(char *) tokens[j+1]; + (void) LogMagickEvent(CoderEvent,GetMagickModule(), +- " %s: %s",keyword,value); ++ " %s: %s",keyword,token_value); + current=transform; + GetAffineMatrix(&affine); + switch (*keyword) +@@ -1873,9 +2223,9 @@ static void SVGStartElement(void *context,const xmlChar *name, + { + if (LocaleCompare(keyword,"matrix") == 0) + { +- p=(const char *) value; ++ p=(const char *) token_value; + (void) GetNextToken(p,&p,MaxTextExtent,token); +- affine.sx=StringToDouble(value,(char **) NULL); ++ affine.sx=StringToDouble(token_value,(char **) NULL); + (void) GetNextToken(p,&p,MaxTextExtent,token); + if (*token == ',') + (void) GetNextToken(p,&p,MaxTextExtent,token); +@@ -1908,7 +2258,8 @@ static void SVGStartElement(void *context,const xmlChar *name, + double + angle; + +- angle=GetUserSpaceCoordinateValue(svg_info,0,value); ++ angle=GetUserSpaceCoordinateValue(svg_info,0, ++ token_value); + affine.sx=cos(DegreesToRadians(fmod(angle,360.0))); + affine.rx=sin(DegreesToRadians(fmod(angle,360.0))); + affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0)))); +@@ -1922,11 +2273,12 @@ static void SVGStartElement(void *context,const xmlChar *name, + { + if (LocaleCompare(keyword,"scale") == 0) + { +- for (p=(const char *) value; *p != '\0'; p++) ++ for (p=(const char *) token_value; *p != '\0'; p++) + if ((isspace((int) ((unsigned char) *p)) != 0) || + (*p == ',')) + break; +- affine.sx=GetUserSpaceCoordinateValue(svg_info,1,value); ++ affine.sx=GetUserSpaceCoordinateValue(svg_info,1, ++ token_value); + affine.sy=affine.sx; + if (*p != '\0') + affine.sy= +@@ -1938,7 +2290,7 @@ static void SVGStartElement(void *context,const xmlChar *name, + { + affine.sx=svg_info->affine.sx; + affine.ry=tan(DegreesToRadians(fmod( +- GetUserSpaceCoordinateValue(svg_info,1,value), ++ GetUserSpaceCoordinateValue(svg_info,1,token_value), + 360.0))); + affine.sy=svg_info->affine.sy; + break; +@@ -1947,7 +2299,7 @@ static void SVGStartElement(void *context,const xmlChar *name, + { + affine.sx=svg_info->affine.sx; + affine.rx=tan(DegreesToRadians(fmod( +- GetUserSpaceCoordinateValue(svg_info,-1,value), ++ GetUserSpaceCoordinateValue(svg_info,-1,token_value), + 360.0))); + affine.sy=svg_info->affine.sy; + break; +@@ -1959,11 +2311,12 @@ static void SVGStartElement(void *context,const xmlChar *name, + { + if (LocaleCompare(keyword,"translate") == 0) + { +- for (p=(const char *) value; *p != '\0'; p++) ++ for (p=(const char *) token_value; *p != '\0'; p++) + if ((isspace((int) ((unsigned char) *p)) != 0) || + (*p == ',')) + break; +- affine.tx=GetUserSpaceCoordinateValue(svg_info,1,value); ++ affine.tx=GetUserSpaceCoordinateValue(svg_info,1, ++ token_value); + affine.ty=0.0; + if (*p != '\0') + affine.ty=GetUserSpaceCoordinateValue(svg_info,-1, +@@ -2255,12 +2608,15 @@ static void SVGStartElement(void *context,const xmlChar *name, + tokens=SVGKeyValuePairs(context,'(',')',value,&number_tokens); + if (tokens == (char **) NULL) + break; +- for (j=0; j < (ssize_t) (number_tokens-1); j+=2) ++ for (j=0; j < ((ssize_t) number_tokens-1); j+=2) + { ++ char ++ *token_value; ++ + keyword=(char *) tokens[j]; +- value=(char *) tokens[j+1]; ++ token_value=(char *) tokens[j+1]; + (void) LogMagickEvent(CoderEvent,GetMagickModule(), +- " %s: %s",keyword,value); ++ " %s: %s",keyword,token_value); + current=transform; + GetAffineMatrix(&affine); + switch (*keyword) +@@ -2270,9 +2626,9 @@ static void SVGStartElement(void *context,const xmlChar *name, + { + if (LocaleCompare(keyword,"matrix") == 0) + { +- p=(const char *) value; ++ p=(const char *) token_value; + (void) GetNextToken(p,&p,MaxTextExtent,token); +- affine.sx=StringToDouble(value,(char **) NULL); ++ affine.sx=StringToDouble(token_value,(char **) NULL); + (void) GetNextToken(p,&p,MaxTextExtent,token); + if (*token == ',') + (void) GetNextToken(p,&p,MaxTextExtent,token); +@@ -2307,9 +2663,9 @@ static void SVGStartElement(void *context,const xmlChar *name, + x, + y; + +- p=(const char *) value; ++ p=(const char *) token_value; + (void) GetNextToken(p,&p,MagickPathExtent,token); +- angle=StringToDouble(value,(char **) NULL); ++ angle=StringToDouble(token_value,(char **) NULL); + affine.sx=cos(DegreesToRadians(fmod(angle,360.0))); + affine.rx=sin(DegreesToRadians(fmod(angle,360.0))); + affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0)))); +@@ -2337,11 +2693,12 @@ static void SVGStartElement(void *context,const xmlChar *name, + { + if (LocaleCompare(keyword,"scale") == 0) + { +- for (p=(const char *) value; *p != '\0'; p++) ++ for (p=(const char *) token_value; *p != '\0'; p++) + if ((isspace((int) ((unsigned char) *p)) != 0) || + (*p == ',')) + break; +- affine.sx=GetUserSpaceCoordinateValue(svg_info,1,value); ++ affine.sx=GetUserSpaceCoordinateValue(svg_info,1, ++ token_value); + affine.sy=affine.sx; + if (*p != '\0') + affine.sy=GetUserSpaceCoordinateValue(svg_info,-1, +@@ -2353,7 +2710,7 @@ static void SVGStartElement(void *context,const xmlChar *name, + { + affine.sx=svg_info->affine.sx; + affine.ry=tan(DegreesToRadians(fmod( +- GetUserSpaceCoordinateValue(svg_info,1,value), ++ GetUserSpaceCoordinateValue(svg_info,1,token_value), + 360.0))); + affine.sy=svg_info->affine.sy; + break; +@@ -2362,7 +2719,7 @@ static void SVGStartElement(void *context,const xmlChar *name, + { + affine.sx=svg_info->affine.sx; + affine.rx=tan(DegreesToRadians(fmod( +- GetUserSpaceCoordinateValue(svg_info,-1,value), ++ GetUserSpaceCoordinateValue(svg_info,-1,token_value), + 360.0))); + affine.sy=svg_info->affine.sy; + break; +@@ -2374,11 +2731,12 @@ static void SVGStartElement(void *context,const xmlChar *name, + { + if (LocaleCompare(keyword,"translate") == 0) + { +- for (p=(const char *) value; *p != '\0'; p++) ++ for (p=(const char *) token_value; *p != '\0'; p++) + if ((isspace((int) ((unsigned char) *p)) != 0) || + (*p == ',')) + break; +- affine.tx=GetUserSpaceCoordinateValue(svg_info,1,value); ++ affine.tx=GetUserSpaceCoordinateValue(svg_info,1, ++ token_value); + affine.ty=affine.tx; + if (*p != '\0') + affine.ty=GetUserSpaceCoordinateValue(svg_info,-1, +@@ -2431,7 +2789,7 @@ static void SVGStartElement(void *context,const xmlChar *name, + (void) GetNextToken(p,&p,MaxTextExtent,token); + svg_info->view_box.width=StringToDouble(token, + (char **) NULL); +- if (svg_info->bounds.width == 0) ++ if (svg_info->bounds.width < MagickEpsilon) + svg_info->bounds.width=svg_info->view_box.width; + (void) GetNextToken(p,&p,MaxTextExtent,token); + if (*token == ',') +@@ -2507,6 +2865,7 @@ static void SVGStartElement(void *context,const xmlChar *name, + default: + break; + } ++ value=DestroyString(value); + } + if (LocaleCompare((const char *) name,"svg") == 0) + { +@@ -2521,19 +2880,19 @@ static void SVGStartElement(void *context,const xmlChar *name, + tx, + ty; + +- if ((svg_info->view_box.width == 0.0) || +- (svg_info->view_box.height == 0.0)) ++ if ((svg_info->view_box.width < MagickEpsilon) || ++ (svg_info->view_box.height < MagickEpsilon)) + svg_info->view_box=svg_info->bounds; + svg_info->width=0; +- if (svg_info->bounds.width > 0.0) ++ if (svg_info->bounds.width >= MagickEpsilon) + svg_info->width=CastDoubleToUnsigned(svg_info->bounds.width+0.5); + svg_info->height=0; +- if (svg_info->bounds.height > 0.0) ++ if (svg_info->bounds.height >= MagickEpsilon) + svg_info->height=CastDoubleToUnsigned(svg_info->bounds.height+0.5); + (void) FormatLocaleFile(svg_info->file,"viewbox 0 0 %.20g %.20g\n", + (double) svg_info->width,(double) svg_info->height); +- sx=PerceptibleReciprocal(svg_info->view_box.width)*svg_info->width; +- sy=PerceptibleReciprocal(svg_info->view_box.height)*svg_info->height; ++ sx=MagickSafeReciprocal(svg_info->view_box.width)*svg_info->width; ++ sy=MagickSafeReciprocal(svg_info->view_box.height)*svg_info->height; + tx=svg_info->view_box.x != 0.0 ? (double) -sx*svg_info->view_box.x : + 0.0; + ty=svg_info->view_box.y != 0.0 ? (double) -sy*svg_info->view_box.y : +@@ -2607,20 +2966,9 @@ static void SVGEndElement(void *context,const xmlChar *name) + } + if (LocaleCompare((const char *) name,"desc") == 0) + { +- char +- *p; +- + if (*svg_info->text == '\0') + break; +- (void) fputc('#',svg_info->file); +- for (p=svg_info->text; *p != '\0'; p++) +- { +- (void) fputc(*p,svg_info->file); +- if (*p == '\n') +- (void) fputc('#',svg_info->file); +- } +- (void) fputc('\n',svg_info->file); +- *svg_info->text='\0'; ++ (void) FormatLocaleFile(svg_info->file,"# %s\n",svg_info->text); + break; + } + break; +@@ -2668,6 +3016,38 @@ static void SVGEndElement(void *context,const xmlChar *name) + { + if (LocaleCompare((const char *) name,"image") == 0) + { ++ char ++ thread_filename[MagickPathExtent]; ++ ++ Image ++ *image; ++ ++ ImageInfo ++ *image_info = AcquireImageInfo(); ++ ++ if (svg_info->url == (char*) NULL) ++ { ++ image_info=DestroyImageInfo(image_info); ++ (void) FormatLocaleFile(svg_info->file,"pop graphic-context\n"); ++ break; ++ } ++ GetMagickThreadFilename(svg_info->url,thread_filename); ++ if (GetValueFromSplayTree(svg_tree,thread_filename) != (const char *) NULL) ++ { ++ image_info=DestroyImageInfo(image_info); ++ (void) ThrowMagickException(svg_info->exception,GetMagickModule(), ++ DrawError,"VectorGraphicsNestedTooDeeply","`%s'",svg_info->url); ++ break; ++ } ++ (void) AddValueToSplayTree(svg_tree,ConstantString(thread_filename), ++ (void *) 1); ++ (void) CopyMagickString(image_info->filename,svg_info->url, ++ MagickPathExtent); ++ image=ReadImage(image_info,svg_info->exception); ++ if (image != (Image *) NULL) ++ image=DestroyImage(image); ++ image_info=DestroyImageInfo(image_info); ++ (void) DeleteNodeFromSplayTree(svg_tree,thread_filename); + (void) FormatLocaleFile(svg_info->file, + "image Over %g,%g %g,%g \"%s\"\n",svg_info->bounds.x, + svg_info->bounds.y,svg_info->bounds.width,svg_info->bounds.height, +@@ -2806,7 +3186,7 @@ static void SVGEndElement(void *context,const xmlChar *name) + &number_tokens); + if (tokens == (char **) NULL) + break; +- for (j=0; j < (ssize_t) (number_tokens-1); j+=2) ++ for (j=0; j < ((ssize_t) number_tokens-1); j+=2) + { + keyword=(char *) tokens[j]; + value=(char *) tokens[j+1]; +@@ -2908,12 +3288,6 @@ static void SVGCharacters(void *context,const xmlChar *c,int length) + char + *text; + +- char +- *p; +- +- ssize_t +- i; +- + SVGInfo + *svg_info; + +@@ -2926,10 +3300,8 @@ static void SVGCharacters(void *context,const xmlChar *c,int length) + text=(char *) AcquireQuantumMemory(length+1,sizeof(*text)); + if (text == (char *) NULL) + return; +- p=text; +- for (i=0; i < (ssize_t) length; i++) +- *p++=c[i]; +- *p='\0'; ++ memcpy(text,c,length); ++ text[length] = '\0'; + SVGStripString(MagickFalse,text); + if (svg_info->text == (char *) NULL) + svg_info->text=text; +@@ -3045,9 +3417,6 @@ static void SVGWarning(void *context,const char *format,...) + va_end(operands); + } + +-static void SVGError(void *,const char *,...) +- magick_attribute((__format__ (__printf__,2,3))); +- + static void SVGError(void *context,const char *format,...) + { + char +@@ -3078,6 +3447,7 @@ static void SVGError(void *context,const char *format,...) + reason,"`%s`",message); + message=DestroyString(message); + va_end(operands); ++ xmlStopParser(svg_info->parser); + } + + static void SVGCDataBlock(void *context,const xmlChar *value,int length) +@@ -3179,19 +3549,16 @@ static void SVGExternalSubset(void *context,const xmlChar *name, + } + #endif + +-static Image *ReadSVGImage(const ImageInfo *image_info,ExceptionInfo *exception) ++static Image *RenderMSVGImage(const ImageInfo *image_info,Image *image, ++ ExceptionInfo *exception) + { + char + filename[MaxTextExtent]; + +- const char +- *option; +- + FILE + *file; + + Image +- *image, + *next; + + int +@@ -3213,325 +3580,6 @@ static Image *ReadSVGImage(const ImageInfo *image_info,ExceptionInfo *exception) + xmlSAXHandlerPtr + sax_handler; + +- /* +- Open image file. +- */ +- assert(image_info != (const ImageInfo *) NULL); +- assert(image_info->signature == MagickCoreSignature); +- assert(exception != (ExceptionInfo *) NULL); +- if (image_info->debug != MagickFalse) +- (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", +- image_info->filename); +- assert(exception->signature == MagickCoreSignature); +- image=AcquireImage(image_info); +- status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); +- if (status == MagickFalse) +- { +- image=DestroyImageList(image); +- return((Image *) NULL); +- } +- if ((fabs(image->x_resolution) < MagickEpsilon) || +- (fabs(image->y_resolution) < MagickEpsilon)) +- { +- GeometryInfo +- geometry_info; +- +- int +- flags; +- +- flags=ParseGeometry(SVGDensityGeometry,&geometry_info); +- image->x_resolution=geometry_info.rho; +- image->y_resolution=geometry_info.sigma; +- if ((flags & SigmaValue) == 0) +- image->y_resolution=image->x_resolution; +- } +- if (LocaleCompare(image_info->magick,"MSVG") != 0) +- { +- Image +- *svg_image; +- +- svg_image=RenderSVGImage(image_info,image,exception); +- if (svg_image != (Image *) NULL) +- { +- image=DestroyImageList(image); +- return(svg_image); +- } +- { +-#if defined(MAGICKCORE_RSVG_DELEGATE) +-#if defined(MAGICKCORE_CAIRO_DELEGATE) +- cairo_surface_t +- *cairo_surface; +- +- cairo_t +- *cairo_image; +- +- MagickBooleanType +- apply_density; +- +- MemoryInfo +- *pixel_info; +- +- unsigned char +- *p; +- +- RsvgDimensionData +- dimension_info; +- +- unsigned char +- *pixels; +- +-#else +- GdkPixbuf +- *pixel_buffer; +- +- const guchar +- *p; +-#endif +- +- GError +- *error; +- +- PixelPacket +- fill_color; +- +- ssize_t +- x; +- +- PixelPacket +- *q; +- +- RsvgHandle +- *svg_handle; +- +- ssize_t +- y; +- +- unsigned char +- *buffer; +- +- buffer=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent, +- sizeof(*buffer)); +- if (buffer == (unsigned char *) NULL) +- ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); +-#if LIBRSVG_CHECK_VERSION(2,40,3) +- option=GetImageOption(image_info,"svg:xml-parse-huge"); +- if ((option != (char *) NULL) && (IsStringTrue(option) != MagickFalse)) +- svg_handle=rsvg_handle_new_with_flags(RSVG_HANDLE_FLAG_UNLIMITED); +- else +-#endif +- svg_handle=rsvg_handle_new(); +- if (svg_handle == (RsvgHandle *) NULL) +- { +- buffer=(unsigned char *) RelinquishMagickMemory(buffer); +- ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); +- } +- rsvg_handle_set_base_uri(svg_handle,image_info->filename); +- if ((fabs(image->x_resolution) > MagickEpsilon) && +- (fabs(image->y_resolution) > MagickEpsilon)) +- rsvg_handle_set_dpi_x_y(svg_handle,image->x_resolution, +- image->y_resolution); +- while ((n=ReadBlob(image,MagickMaxBufferExtent-1,buffer)) != 0) +- { +- buffer[n]='\0'; +- error=(GError *) NULL; +- (void) rsvg_handle_write(svg_handle,buffer,n,&error); +- if (error != (GError *) NULL) +- g_error_free(error); +- } +- buffer=(unsigned char *) RelinquishMagickMemory(buffer); +- error=(GError *) NULL; +- rsvg_handle_close(svg_handle,&error); +- if (error != (GError *) NULL) +- g_error_free(error); +-#if defined(MAGICKCORE_CAIRO_DELEGATE) +- apply_density=MagickTrue; +- rsvg_handle_get_dimensions(svg_handle,&dimension_info); +- if ((image->x_resolution > 0.0) && (image->y_resolution > 0.0)) +- { +- RsvgDimensionData +- dpi_dimension_info; +- +- /* +- We should not apply the density when the internal 'factor' is 'i'. +- This can be checked by using the trick below. +- */ +- rsvg_handle_set_dpi_x_y(svg_handle,image->x_resolution*256, +- image->y_resolution*256); +- rsvg_handle_get_dimensions(svg_handle,&dpi_dimension_info); +- if ((dpi_dimension_info.width != dimension_info.width) || +- (dpi_dimension_info.height != dimension_info.height)) +- apply_density=MagickFalse; +- rsvg_handle_set_dpi_x_y(svg_handle,image->x_resolution, +- image->y_resolution); +- } +- if (image_info->size != (char *) NULL) +- { +- (void) GetGeometry(image_info->size,(ssize_t *) NULL, +- (ssize_t *) NULL,&image->columns,&image->rows); +- if ((image->columns != 0) || (image->rows != 0)) +- { +- image->x_resolution=DefaultSVGDensity*image->columns/ +- dimension_info.width; +- image->y_resolution=DefaultSVGDensity*image->rows/ +- dimension_info.height; +- if (fabs(image->x_resolution) < MagickEpsilon) +- image->x_resolution=image->y_resolution; +- else +- if (fabs(image->y_resolution) < MagickEpsilon) +- image->y_resolution=image->x_resolution; +- else +- image->x_resolution=image->y_resolution=MagickMin( +- image->x_resolution,image->y_resolution); +- apply_density=MagickTrue; +- } +- } +- if (apply_density != MagickFalse) +- { +- image->columns=image->x_resolution*dimension_info.width/ +- DefaultSVGDensity; +- image->rows=image->y_resolution*dimension_info.height/ +- DefaultSVGDensity; +- } +- else +- { +- image->columns=dimension_info.width; +- image->rows=dimension_info.height; +- } +- pixel_info=(MemoryInfo *) NULL; +-#else +- pixel_buffer=rsvg_handle_get_pixbuf(svg_handle); +- rsvg_handle_free(svg_handle); +- image->columns=gdk_pixbuf_get_width(pixel_buffer); +- image->rows=gdk_pixbuf_get_height(pixel_buffer); +-#endif +- image->matte=MagickTrue; +- if (image_info->ping == MagickFalse) +- { +-#if defined(MAGICKCORE_CAIRO_DELEGATE) +- size_t +- stride; +-#endif +- +- status=SetImageExtent(image,image->columns,image->rows); +- if (status == MagickFalse) +- { +-#if !defined(MAGICKCORE_CAIRO_DELEGATE) +- g_object_unref(G_OBJECT(pixel_buffer)); +-#endif +- g_object_unref(svg_handle); +- InheritException(exception,&image->exception); +- ThrowReaderException(MissingDelegateError, +- "NoDecodeDelegateForThisImageFormat"); +- } +- +-#if defined(MAGICKCORE_CAIRO_DELEGATE) +- stride=4*image->columns; +-#if defined(MAGICKCORE_PANGOCAIRO_DELEGATE) +- stride=(size_t) cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, +- (int) image->columns); +-#endif +- pixel_info=AcquireVirtualMemory(stride,image->rows*sizeof(*pixels)); +- if (pixel_info == (MemoryInfo *) NULL) +- { +- g_object_unref(svg_handle); +- ThrowReaderException(ResourceLimitError, +- "MemoryAllocationFailed"); +- } +- pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); +-#endif +- (void) SetImageBackgroundColor(image); +-#if defined(MAGICKCORE_CAIRO_DELEGATE) +- cairo_surface=cairo_image_surface_create_for_data(pixels, +- CAIRO_FORMAT_ARGB32,(int) image->columns,(int) image->rows,(int) +- stride); +- if ((cairo_surface == (cairo_surface_t *) NULL) || +- (cairo_surface_status(cairo_surface) != CAIRO_STATUS_SUCCESS)) +- { +- if (cairo_surface != (cairo_surface_t *) NULL) +- cairo_surface_destroy(cairo_surface); +- pixel_info=RelinquishVirtualMemory(pixel_info); +- g_object_unref(svg_handle); +- ThrowReaderException(ResourceLimitError, +- "MemoryAllocationFailed"); +- } +- cairo_image=cairo_create(cairo_surface); +- cairo_set_operator(cairo_image,CAIRO_OPERATOR_CLEAR); +- cairo_paint(cairo_image); +- cairo_set_operator(cairo_image,CAIRO_OPERATOR_OVER); +- if (apply_density != MagickFalse) +- cairo_scale(cairo_image,image->x_resolution/DefaultSVGDensity, +- image->y_resolution/DefaultSVGDensity); +- rsvg_handle_render_cairo(svg_handle,cairo_image); +- cairo_destroy(cairo_image); +- cairo_surface_destroy(cairo_surface); +- g_object_unref(svg_handle); +- p=pixels; +-#else +- p=gdk_pixbuf_get_pixels(pixel_buffer); +-#endif +- for (y=0; y < (ssize_t) image->rows; y++) +- { +- q=GetAuthenticPixels(image,0,y,image->columns,1,exception); +- if (q == (PixelPacket *) NULL) +- break; +- for (x=0; x < (ssize_t) image->columns; x++) +- { +-#if defined(MAGICKCORE_CAIRO_DELEGATE) +- fill_color.blue=ScaleCharToQuantum(*p++); +- fill_color.green=ScaleCharToQuantum(*p++); +- fill_color.red=ScaleCharToQuantum(*p++); +-#else +- fill_color.red=ScaleCharToQuantum(*p++); +- fill_color.green=ScaleCharToQuantum(*p++); +- fill_color.blue=ScaleCharToQuantum(*p++); +-#endif +- fill_color.opacity=QuantumRange-ScaleCharToQuantum(*p++); +-#if defined(MAGICKCORE_CAIRO_DELEGATE) +- { +- double +- gamma; +- +- gamma=1.0-QuantumScale*fill_color.opacity; +- gamma=PerceptibleReciprocal(gamma); +- fill_color.blue*=gamma; +- fill_color.green*=gamma; +- fill_color.red*=gamma; +- } +-#endif +- MagickCompositeOver(&fill_color,fill_color.opacity,q, +- (MagickRealType) q->opacity,q); +- q++; +- } +- if (SyncAuthenticPixels(image,exception) == MagickFalse) +- break; +- if (image->previous == (Image *) NULL) +- { +- status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) +- y,image->rows); +- if (status == MagickFalse) +- break; +- } +- } +- } +-#if defined(MAGICKCORE_CAIRO_DELEGATE) +- else +- g_object_unref(svg_handle); +- if (pixel_info != (MemoryInfo *) NULL) +- pixel_info=RelinquishVirtualMemory(pixel_info); +-#else +- g_object_unref(G_OBJECT(pixel_buffer)); +-#endif +- (void) CloseBlob(image); +- for (next=GetFirstImageInList(image); next != (Image *) NULL; ) +- { +- (void) CopyMagickString(next->filename,image->filename,MaxTextExtent); +- (void) CopyMagickString(next->magick,image->magick,MaxTextExtent); +- next=GetNextImageInList(next); +- } +- return(GetFirstImageInList(image)); +-#endif +- } +- } + /* + Open draw file. + */ +@@ -3568,7 +3616,6 @@ static Image *ReadSVGImage(const ImageInfo *image_info,ExceptionInfo *exception) + if (image->debug != MagickFalse) + (void) LogMagickEvent(CoderEvent,GetMagickModule(),"begin SAX"); + xmlInitParser(); +- (void) xmlSubstituteEntitiesDefault(1); + (void) memset(&sax_modules,0,sizeof(sax_modules)); + sax_modules.internalSubset=SVGInternalSubset; + sax_modules.isStandalone=SVGIsStandalone; +@@ -3604,11 +3651,18 @@ static Image *ReadSVGImage(const ImageInfo *image_info,ExceptionInfo *exception) + { + svg_info->parser=xmlCreatePushParserCtxt(sax_handler,svg_info,(char *) + message,n,image->filename); +- option=GetImageOption(image_info,"svg:xml-parse-huge"); + if (svg_info->parser != (xmlParserCtxtPtr) NULL) + { +- if ((option != (char *) NULL) && (IsStringTrue(option) != MagickFalse)) ++ const char *option = GetImageOption(image_info,"svg:parse-huge"); ++ if (option == (char *) NULL) ++ option=GetImageOption(image_info,"svg:xml-parse-huge"); ++ if ((option != (char *) NULL) && ++ (IsStringTrue(option) != MagickFalse)) + (void) xmlCtxtUseOptions(svg_info->parser,XML_PARSE_HUGE); ++ option=GetImageOption(image_info,"svg:substitute-entities"); ++ if ((option != (char *) NULL) && ++ (IsStringTrue(option) != MagickFalse)) ++ (void) xmlCtxtUseOptions(svg_info->parser,XML_PARSE_NOENT); + while ((n=ReadBlob(image,MaxTextExtent-1,message)) != 0) + { + message[n]='\0'; +@@ -3628,7 +3682,10 @@ static Image *ReadSVGImage(const ImageInfo *image_info,ExceptionInfo *exception) + (void) xmlParseChunk(svg_info->parser,(char *) message,0,1); + SVGEndDocument(svg_info); + if (svg_info->parser->myDoc != (xmlDocPtr) NULL) +- xmlFreeDoc(svg_info->parser->myDoc); ++ { ++ xmlFreeDoc(svg_info->parser->myDoc); ++ svg_info->parser->myDoc=(xmlDocPtr) NULL; ++ } + xmlFreeParserCtxt(svg_info->parser); + if (image->debug != MagickFalse) + (void) LogMagickEvent(CoderEvent,GetMagickModule(),"end SAX"); +@@ -3675,31 +3732,44 @@ static Image *ReadSVGImage(const ImageInfo *image_info,ExceptionInfo *exception) + } + svg_info=DestroySVGInfo(svg_info); + (void) RelinquishUniqueFileResource(filename); +- for (next=GetFirstImageInList(image); next != (Image *) NULL; ) +- { +- (void) CopyMagickString(next->filename,image->filename,MaxTextExtent); +- (void) CopyMagickString(next->magick,"SVG",MaxTextExtent); +- next=GetNextImageInList(next); +- } ++ if (image != (Image *) NULL) ++ for (next=GetFirstImageInList(image); next != (Image *) NULL; ) ++ { ++ (void) CopyMagickString(next->filename,image->filename,MaxTextExtent); ++ (void) CopyMagickString(next->magick,"SVG",MaxTextExtent); ++ next=GetNextImageInList(next); ++ } + return(GetFirstImageInList(image)); + } + #else ++static Image *RenderMSVGImage(const ImageInfo *magick_unused(image_info), ++ Image *image,ExceptionInfo *magick_unused(exception)) ++{ ++ magick_unreferenced(image_info); ++ magick_unreferenced(exception); ++ image=DestroyImageList(image); ++ return((Image *) NULL); ++} ++#endif ++ + static Image *ReadSVGImage(const ImageInfo *image_info,ExceptionInfo *exception) + { + Image +- *image, +- *svg_image; ++ *image; + + MagickBooleanType + status; + ++ /* ++ Open image file. ++ */ + assert(image_info != (const ImageInfo *) NULL); + assert(image_info->signature == MagickCoreSignature); + assert(exception != (ExceptionInfo *) NULL); +- if (image_info->debug != MagickFalse) ++ assert(exception->signature == MagickCoreSignature); ++ if (IsEventLogging() != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", + image_info->filename); +- assert(exception->signature == MagickCoreSignature); + image=AcquireImage(image_info); + status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); + if (status == MagickFalse) +@@ -3717,16 +3787,42 @@ static Image *ReadSVGImage(const ImageInfo *image_info,ExceptionInfo *exception) + flags; + + flags=ParseGeometry(SVGDensityGeometry,&geometry_info); +- image->x_resolution=geometry_info.rho; +- image->y_resolution=geometry_info.sigma; +- if ((flags & SigmaValue) == 0) +- image->y_resolution=image->x_resolution; ++ if ((flags & RhoValue) != 0) ++ image->x_resolution=geometry_info.rho; ++ image->y_resolution=image->x_resolution; ++ if ((flags & SigmaValue) != 0) ++ image->y_resolution=geometry_info.sigma; + } +- svg_image=RenderSVGImage(image_info,image,exception); +- image=DestroyImage(image); +- return(svg_image); +-} ++ if (LocaleCompare(image_info->magick,"MSVG") != 0) ++ { ++ if (LocaleCompare(image_info->magick,"RSVG") != 0) ++ { ++ Image ++ *svg_image; ++ ++ svg_image=RenderSVGImage(image_info,image,exception); ++ if (svg_image != (Image *) NULL) ++ { ++ image=DestroyImageList(image); ++ return(svg_image); ++ } ++ } ++#if defined(MAGICKCORE_RSVG_DELEGATE) ++ if (rsvg_semaphore == (SemaphoreInfo *) NULL) ++ ActivateSemaphoreInfo(&rsvg_semaphore); ++ LockSemaphoreInfo(rsvg_semaphore); ++ image=RenderRSVGImage(image_info,image,exception); ++ UnlockSemaphoreInfo(rsvg_semaphore); ++ return(image); + #endif ++ } ++ status=IsRightsAuthorized(CoderPolicyDomain,ReadPolicyRights,"MSVG"); ++ if (status == MagickFalse) ++ image=DestroyImageList(image); ++ else ++ image=RenderMSVGImage(image_info,image,exception); ++ return(image); ++} + + /* + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@@ -3759,6 +3855,9 @@ ModuleExport size_t RegisterSVGImage(void) + MagickInfo + *entry; + ++ if (svg_tree == (SplayTreeInfo *) NULL) ++ svg_tree=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory, ++ (void *(*)(void *)) NULL); + *version='\0'; + #if defined(LIBXML_DOTTED_VERSION) + (void) CopyMagickString(version,"XML " LIBXML_DOTTED_VERSION,MaxTextExtent); +@@ -3777,9 +3876,7 @@ ModuleExport size_t RegisterSVGImage(void) + entry->decoder=(DecodeImageHandler *) ReadSVGImage; + entry->encoder=(EncodeImageHandler *) WriteSVGImage; + entry->seekable_stream=MagickFalse; +-#if defined(MAGICKCORE_RSVG_DELEGATE) +- entry->thread_support=MagickFalse; +-#endif ++ entry->blob_support=MagickFalse; + entry->description=ConstantString("Scalable Vector Graphics"); + entry->mime_type=ConstantString("image/svg+xml"); + if (*version != '\0') +@@ -3793,9 +3890,7 @@ ModuleExport size_t RegisterSVGImage(void) + #endif + entry->encoder=(EncodeImageHandler *) WriteSVGImage; + entry->seekable_stream=MagickFalse; +-#if defined(MAGICKCORE_RSVG_DELEGATE) +- entry->thread_support=MagickFalse; +-#endif ++ entry->blob_support=MagickFalse; + entry->description=ConstantString("Compressed Scalable Vector Graphics"); + entry->mime_type=ConstantString("image/svg+xml"); + if (*version != '\0') +@@ -3803,15 +3898,25 @@ ModuleExport size_t RegisterSVGImage(void) + entry->magick=(IsImageFormatHandler *) IsSVG; + entry->magick_module=ConstantString("SVG"); + (void) RegisterMagickInfo(entry); ++#if defined(MAGICKCORE_RSVG_DELEGATE) ++ entry=SetMagickInfo("RSVG"); ++ entry->decoder=(DecodeImageHandler *) ReadSVGImage; ++ entry->encoder=(EncodeImageHandler *) WriteSVGImage; ++ entry->seekable_stream=MagickFalse; ++ entry->blob_support=MagickFalse; ++ entry->thread_support^=DecoderThreadSupport; ++ entry->description=ConstantString("Librsvg SVG renderer"); ++ entry->magick=(IsImageFormatHandler *) IsSVG; ++ entry->magick_module=ConstantString("SVG"); ++ (void) RegisterMagickInfo(entry); ++#endif + entry=SetMagickInfo("MSVG"); + #if defined(MAGICKCORE_XML_DELEGATE) + entry->decoder=(DecodeImageHandler *) ReadSVGImage; + #endif + entry->encoder=(EncodeImageHandler *) WriteSVGImage; + entry->seekable_stream=MagickFalse; +-#if defined(MAGICKCORE_RSVG_DELEGATE) +- entry->thread_support=MagickFalse; +-#endif ++ entry->blob_support=MagickFalse; + entry->description=ConstantString("ImageMagick's own SVG internal renderer"); + entry->magick=(IsImageFormatHandler *) IsSVG; + entry->magick_module=ConstantString("SVG"); +@@ -3843,6 +3948,8 @@ ModuleExport void UnregisterSVGImage(void) + (void) UnregisterMagickInfo("SVGZ"); + (void) UnregisterMagickInfo("SVG"); + (void) UnregisterMagickInfo("MSVG"); ++ if (svg_tree != (SplayTreeInfo *) NULL) ++ svg_tree=DestroySplayTree(svg_tree); + } + + /* +@@ -3945,6 +4052,9 @@ static MagickBooleanType IsPoint(const char *point) + + static MagickBooleanType TraceSVGImage(Image *image,ExceptionInfo *exception) + { ++ MagickBooleanType ++ status = MagickTrue; ++ + #if defined(MAGICKCORE_AUTOTRACE_DELEGATE) + { + at_bitmap +@@ -4020,7 +4130,8 @@ static MagickBooleanType TraceSVGImage(Image *image,ExceptionInfo *exception) + char + *base64, + filename[MaxTextExtent], +- message[MaxTextExtent]; ++ message[MaxTextExtent], ++ *p; + + const DelegateInfo + *delegate_info; +@@ -4031,12 +4142,6 @@ static MagickBooleanType TraceSVGImage(Image *image,ExceptionInfo *exception) + ImageInfo + *image_info; + +- MagickBooleanType +- status; +- +- char +- *p; +- + size_t + blob_length, + encode_length; +@@ -4095,7 +4200,7 @@ static MagickBooleanType TraceSVGImage(Image *image,ExceptionInfo *exception) + blob=(unsigned char *) RelinquishMagickMemory(blob); + (void) FormatLocaleString(message,MaxTextExtent, + " scene,(double) image->columns,(double) image->rows, + (double) image->page.x,(double) image->page.y); + (void) WriteBlobString(image,message); +@@ -4104,7 +4209,7 @@ static MagickBooleanType TraceSVGImage(Image *image,ExceptionInfo *exception) + { + (void) FormatLocaleString(message,MaxTextExtent,"%.76s",p); + (void) WriteBlobString(image,message); +- p+=76; ++ p+=(ptrdiff_t) 76; + if (i > 76) + (void) WriteBlobString(image,"\n"); + } +@@ -4113,8 +4218,9 @@ static MagickBooleanType TraceSVGImage(Image *image,ExceptionInfo *exception) + (void) WriteBlobString(image,"\n"); + } + #endif +- (void) CloseBlob(image); +- return(MagickTrue); ++ if (CloseBlob(image) == MagickFalse) ++ status=MagickFalse; ++ return(status); + } + + static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image) +@@ -4177,7 +4283,7 @@ static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image) + assert(image_info->signature == MagickCoreSignature); + assert(image != (Image *) NULL); + assert(image->signature == MagickCoreSignature); +- if (image->debug != MagickFalse) ++ if (IsEventLogging() != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); + status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); + if (status == MagickFalse) +@@ -4195,14 +4301,11 @@ static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image) + /* + Write SVG header. + */ +- (void) WriteBlobString(image,"\n"); +- (void) WriteBlobString(image, +- "\n"); ++ "\n"); + (void) FormatLocaleString(message,MaxTextExtent, +- "\n",(double) image->columns,(double) +- image->rows); ++ "\n", ++ (double) image->columns,(double) image->rows); + (void) WriteBlobString(image,message); + /* + Allocate primitive info memory. +@@ -4615,7 +4718,7 @@ static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image) + *name='\0'; + (void) GetNextToken(q,&q,extent,token); + if (*q == '"') +- (void) GetNextToken(q,&q,extent,name); ++ (void) GetNextToken(q,&q,MaxTextExtent,name); + if (LocaleCompare("clip-path",token) == 0) + { + (void) GetNextToken(q,&q,extent,token); +@@ -4973,7 +5076,7 @@ static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image) + primitive_info[i].coordinates=0; + primitive_info[i].method=FloodfillMethod; + i++; +- if (i < (ssize_t) (number_points-6*BezierQuantum-360)) ++ if (i < ((ssize_t) number_points-6*BezierQuantum-360)) + continue; + number_points+=6*BezierQuantum+360; + primitive_info=(PrimitiveInfo *) ResizeQuantumMemory(primitive_info, +@@ -5185,7 +5288,7 @@ static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image) + image->filename); + break; + } +- if (i > (ssize_t) (number_points-quantum-1)) ++ if (i > ((ssize_t) number_points-(ssize_t) quantum-1)) + { + number_points+=quantum; + primitive_info=(PrimitiveInfo *) ResizeQuantumMemory(primitive_info, +@@ -5280,6 +5383,7 @@ static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image) + token=DestroyString(token); + if (primitive_info != (PrimitiveInfo *) NULL) + primitive_info=(PrimitiveInfo *) RelinquishMagickMemory(primitive_info); +- (void) CloseBlob(image); ++ if (CloseBlob(image) == MagickFalse) ++ status=MagickFalse; + return(status); + } diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/revert-delegate-change.patch imagemagick-6.9.11.60+dfsg/debian/patches/revert-delegate-change.patch --- imagemagick-6.9.11.60+dfsg/debian/patches/revert-delegate-change.patch 1970-01-01 00:00:00.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/revert-delegate-change.patch 2026-04-12 19:56:20.000000000 +0000 @@ -0,0 +1,39 @@ +From: =?utf-8?q?Bastien_Roucari=C3=A8s?= +Date: Sun, 12 Apr 2026 19:47:33 +0200 +Subject: Revert "No longer redirect the output with inkscape because this + causes issues on Windows." + +This reverts commit 08178d7e2dbdd4069b1b261c454afd09e37cdd4b. + +[backport] +- this fix a regression on i386 +--- + coders/svg.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/coders/svg.c b/coders/svg.c +index cf85539..7d1c40f 100644 +--- a/coders/svg.c ++++ b/coders/svg.c +@@ -315,7 +315,6 @@ static Image *RenderSVGImage(const ImageInfo *image_info,Image *image, + return((Image *) NULL); + (void) AcquireUniqueFilename(unique); + (void) FormatLocaleString(output_filename,MagickPathExtent,"%s.png",unique); +- (void) RelinquishUniqueFileResource(unique); + density=AcquireString(""); + (void) FormatLocaleString(density,MagickPathExtent,"%.20g", + sqrt(image->x_resolution*image->y_resolution)); +@@ -329,11 +328,11 @@ static Image *RenderSVGImage(const ImageInfo *image_info,Image *image, + image->background_color.opacity)); + (void) FormatLocaleString(command,MagickPathExtent, + GetDelegateCommands(delegate_info),input_filename,output_filename,density, +- background,opacity); ++ background,opacity,unique); + density=DestroyString(density); + status=ExternalDelegateCommand(MagickFalse,image_info->verbose,command, + (char *) NULL,exception); +- (void) (unique); ++ (void) RelinquishUniqueFileResource(unique); + if ((status == 0) && (stat(output_filename,&attributes) == 0) && + (attributes.st_size > 0)) + { diff -Nru imagemagick-6.9.11.60+dfsg/debian/patches/series imagemagick-6.9.11.60+dfsg/debian/patches/series --- imagemagick-6.9.11.60+dfsg/debian/patches/series 2026-03-06 16:54:58.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/patches/series 2026-04-12 19:56:20.000000000 +0000 @@ -134,3 +134,26 @@ CVE-2026-26283.patch CVE-2026-27798.patch CVE-2026-27799.patch +CVE-2026-25985.patch +CVE-2026-25985_post1.patch +CVE-2026-26284_pre1.patch +CVE-2026-26284.patch +CVE-2026-26983.patch +CVE-2026-25796_post1.patch +CVE-2026-28494.patch +CVE-2026-28686_28687_28688_28689_28690_28692.patch +CVE-2026-28693_pre1.patch +CVE-2026-28693_1.patch +CVE-2026-28693_2.patch +CVE-2026-30883.patch +CVE-2026-30936.patch +CVE-2026-30937.patch +CVE-2026-31853.patch +CVE-2026-32259.patch +GetMagickThreadFilename.patch +port-msl-svg-to-6.9.13-41.patch +revert-delegate-change.patch +i386-fix.patch +CVE-2026-32636.patch +CVE-2026-33535.patch +CVE-2026-33536.patch diff -Nru imagemagick-6.9.11.60+dfsg/debian/rules imagemagick-6.9.11.60+dfsg/debian/rules --- imagemagick-6.9.11.60+dfsg/debian/rules 2026-03-06 16:54:58.000000000 +0000 +++ imagemagick-6.9.11.60+dfsg/debian/rules 2026-04-12 09:28:14.000000000 +0000 @@ -475,7 +475,7 @@ mkdir -p $(CURDIR)/debian/tmp-$*/usr/share/icons/hicolor/$$SIZE/apps/ ;\ cd $(CURDIR)/debian/build-quantum-$*; \ echo "Make icons for size $$SIZE..."; \ - $(CONVERT) $(CURDIR)/debian/display-im$(IMVERSION).svg \ + $(CONVERT) -verbose $(CURDIR)/debian/display-im$(IMVERSION).svg \ $(CONVERT_FLAGS) -resize $$SIZE \ -gravity center -extent $$SIZE \ +set date:create +set date:modify -define png:exclude-chunk=time \