From 7b47fe369eda90483402fcd3d78fa4167d3bb129 Mon Sep 17 00:00:00 2001 From: Cristy Date: Sat, 18 Oct 2025 10:54:39 -0400 Subject: [PATCH] https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-wpp4-vqfq-v4hp --- MagickCore/composite.c | 2 +- MagickCore/enhance.c | 48 +++++++++-------- MagickCore/image-private.h | 103 +++++++++++++++++++++++-------------- configure | 2 +- 4 files changed, 91 insertions(+), 64 deletions(-) diff --git a/MagickCore/composite.c b/MagickCore/composite.c index e4394ea4fc..75d41c077f 100644 --- a/MagickCore/composite.c +++ b/MagickCore/composite.c @@ -986,7 +986,7 @@ static MagickBooleanType CompositeOverImage(Image *image, } pixels=p; if (x_offset < 0) - p-=(ptrdiff_t)CastDoubleToSsizeT((double) x_offset* + p-=(ptrdiff_t) CastDoubleToSsizeT((double) x_offset* GetPixelChannels(source_image)); } q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); diff --git a/MagickCore/enhance.c b/MagickCore/enhance.c index 0e77dce90c..425b26c5f8 100644 --- a/MagickCore/enhance.c +++ b/MagickCore/enhance.c @@ -69,6 +69,7 @@ #include "MagickCore/option.h" #include "MagickCore/pixel.h" #include "MagickCore/pixel-accessor.h" +#include "MagickCore/pixel-private.h" #include "MagickCore/property.h" #include "MagickCore/quantum.h" #include "MagickCore/quantum-private.h" @@ -318,11 +319,8 @@ static void ClipCLAHEHistogram(const double clip_limit,const size_t number_bins, return; cumulative_excess=0; for (i=0; i < (ssize_t) number_bins; i++) - { - excess=(ssize_t) histogram[i]-(ssize_t) clip_limit; - if (excess > 0) - cumulative_excess+=excess; - } + if (histogram[i] > clip_limit) + cumulative_excess+=(ssize_t) (histogram[i]-clip_limit); /* Clip histogram and redistribute excess pixels across all bins. */ @@ -481,9 +479,6 @@ static MagickBooleanType CLAHE(const RectangleInfo *clahe_info, MemoryInfo *tile_cache; - unsigned short - *p; - size_t limit, *tiles; @@ -492,15 +487,16 @@ static MagickBooleanType CLAHE(const RectangleInfo *clahe_info, y; unsigned short - *lut; + *lut, + *p; /* Contrast limited adapted histogram equalization. */ if (clip_limit == 1.0) return(MagickTrue); - tile_cache=AcquireVirtualMemory((size_t) clahe_info->x*number_bins, - (size_t) clahe_info->y*sizeof(*tiles)); + tile_cache=AcquireVirtualMemory((size_t) clahe_info->x*number_bins,(size_t) + clahe_info->y*sizeof(*tiles)); if (tile_cache == (MemoryInfo *) NULL) return(MagickFalse); lut=(unsigned short *) AcquireQuantumMemory(NumberCLAHEGrays,sizeof(*lut)); @@ -510,7 +506,8 @@ static MagickBooleanType CLAHE(const RectangleInfo *clahe_info, return(MagickFalse); } tiles=(size_t *) GetVirtualMemoryBlob(tile_cache); - limit=(size_t) (clip_limit*(tile_info->width*tile_info->height)/number_bins); + limit=(size_t) (clip_limit*((double) tile_info->width*tile_info->height)/ + number_bins); if (limit < 1UL) limit=1UL; /* @@ -535,7 +532,7 @@ static MagickBooleanType CLAHE(const RectangleInfo *clahe_info, tile_info->height,histogram); p+=(ptrdiff_t) tile_info->width; } - p+=(ptrdiff_t) clahe_info->width*(tile_info->height-1); + p+=CastDoubleToPtrdiffT((double) clahe_info->width*(tile_info->height-1)); } /* Interpolate greylevel mappings to get CLAHE image. @@ -576,6 +573,12 @@ static MagickBooleanType CLAHE(const RectangleInfo *clahe_info, } for (x=0; x <= (ssize_t) clahe_info->x; x++) { + double + Q11, + Q12, + Q21, + Q22; + tile.width=tile_info->width; tile.x=x-1; offset.x=tile.x+1; @@ -598,15 +601,16 @@ static MagickBooleanType CLAHE(const RectangleInfo *clahe_info, tile.x=clahe_info->x-1; offset.x=tile.x; } - InterpolateCLAHE(clahe_info, - tiles+((ssize_t) number_bins*(tile.y*clahe_info->x+tile.x)), /* Q12 */ - tiles+((ssize_t) number_bins*(tile.y*clahe_info->x+offset.x)), /* Q22 */ - tiles+((ssize_t) number_bins*(offset.y*clahe_info->x+tile.x)), /* Q11 */ - tiles+((ssize_t) number_bins*(offset.y*clahe_info->x+offset.x)), /* Q21 */ - &tile,lut,p); + Q12=(double) number_bins*(tile.y*clahe_info->x+tile.x); + Q22=(double) number_bins*(tile.y*clahe_info->x+offset.x); + Q11=(double) number_bins*(offset.y*clahe_info->x+tile.x); + Q21=(double) number_bins*(offset.y*clahe_info->x+offset.x); + InterpolateCLAHE(clahe_info,tiles+CastDoubleToPtrdiffT(Q12), + tiles+CastDoubleToPtrdiffT(Q22),tiles+CastDoubleToPtrdiffT(Q11), + tiles+CastDoubleToPtrdiffT(Q21),&tile,lut,p); p+=(ptrdiff_t) tile.width; } - p+=(ptrdiff_t) clahe_info->width*(tile.height-1); + p+=CastDoubleToPtrdiffT((double) clahe_info->width*(tile.height-1)); } lut=(unsigned short *) RelinquishMagickMemory(lut); tile_cache=RelinquishVirtualMemory(tile_cache); @@ -659,10 +663,10 @@ MagickExport MagickBooleanType CLAHEImage(Image *image,const size_t width, (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); range_info.min=0; range_info.max=NumberCLAHEGrays-1; - tile_info.width=width; + tile_info.width=MagickMax(width,2); if (tile_info.width == 0) tile_info.width=image->columns >> 3; - tile_info.height=height; + tile_info.height=MagickMax(height,2); if (tile_info.height == 0) tile_info.height=image->rows >> 3; tile_info.x=0; diff --git a/MagickCore/image-private.h b/MagickCore/image-private.h index 81269ef890..13203b8537 100644 --- a/MagickCore/image-private.h +++ b/MagickCore/image-private.h @@ -46,6 +46,8 @@ extern "C" { #define MagickPHI 1.61803398874989484820458683436563811772030917980576 #define MagickPI2 1.57079632679489661923132169163975144209858469968755 #define MagickPI 3.1415926535897932384626433832795028841971693993751058209749445923078164062 +#define MAGICK_PTRDIFF_MAX (PTRDIFF_MAX) +#define MAGICK_PTRDIFF_MIN (-PTRDIFF_MAX-1) #define MagickSQ1_2 0.70710678118654752440084436210484903928483593768847 #define MagickSQ2 1.41421356237309504880168872420969807856967187537695 #define MagickSQ2PI 2.50662827463100024161235523934010416269302368164062 @@ -67,24 +69,52 @@ extern "C" { #define UndefinedCompressionQuality 0UL #define UndefinedTicksPerSecond 100L -static inline QuantumAny CastDoubleToQuantumAny(const double x) +static inline ptrdiff_t CastDoubleToPtrdiffT(const double x) { + double + value; + if (IsNaN(x) != 0) { errno=ERANGE; return(0); } - if (x > ((double) ((QuantumAny) ~0))) + value=(x < 0.0) ? ceil(x) : floor(x); + if (value < ((double) MAGICK_PTRDIFF_MIN)) + { + errno=ERANGE; + return(MAGICK_PTRDIFF_MIN); + } + if (value > ((double) MAGICK_PTRDIFF_MAX)) + { + errno=ERANGE; + return(MAGICK_PTRDIFF_MAX); + } + return((ptrdiff_t) value); +} + +static inline QuantumAny CastDoubleToQuantumAny(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) ((QuantumAny) ~0))) { errno=ERANGE; return((QuantumAny) ~0); } - if (x < 0.0) - { - errno=ERANGE; - return((QuantumAny) 0); - } - return((QuantumAny) (x+0.5)); + return((QuantumAny) value); } static inline size_t CastDoubleToSizeT(const double x) @@ -97,17 +127,17 @@ static inline size_t CastDoubleToSizeT(const double x) errno=ERANGE; return(0); } - value=floor(x); - if (value >= ((double) MAGICK_SIZE_MAX)) - { - errno=ERANGE; - return((size_t) MAGICK_SIZE_MAX); - } + 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); } @@ -121,23 +151,16 @@ static inline ssize_t CastDoubleToSsizeT(const double x) errno=ERANGE; return(0); } - if (x < 0.0) + value=(x < 0.0) ? ceil(x) : floor(x); + if (value < ((double) MAGICK_SSIZE_MIN)) { - value=ceil(x); - if (value < ((double) MAGICK_SSIZE_MIN)) - { - errno=ERANGE; - return((ssize_t) MAGICK_SSIZE_MIN); - } + errno=ERANGE; + return(MAGICK_SSIZE_MIN); } - else + if (value > ((double) MAGICK_SSIZE_MAX)) { - value=floor(x); - if (value > ((double) MAGICK_SSIZE_MAX)) - { - errno=ERANGE; - return((ssize_t) MAGICK_SSIZE_MAX); - } + errno=ERANGE; + return(MAGICK_SSIZE_MAX); } return((ssize_t) value); } @@ -152,17 +175,17 @@ static inline unsigned int CastDoubleToUInt(const double x) errno=ERANGE; return(0); } - value=floor(x); - if (value >= ((double) MAGICK_UINT_MAX)) - { - errno=ERANGE; - return((unsigned int) MAGICK_UINT_MAX); - } + value=(x < 0.0) ? ceil(x) : floor(x); if (value < 0.0) { errno=ERANGE; return(0); } + if (value > ((double) MAGICK_UINT_MAX)) + { + errno=ERANGE; + return(MAGICK_UINT_MAX); + } return((unsigned int) value); } @@ -176,17 +199,17 @@ static inline unsigned short CastDoubleToUShort(const double x) errno=ERANGE; return(0); } - value=floor(x); - if (value >= ((double) MAGICK_USHORT_MAX)) - { - errno=ERANGE; - return((unsigned short) MAGICK_USHORT_MAX); - } + 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); } diff --git a/configure b/configure index f67e7fe2ca..b4f43e7c8a 100755 --- a/configure +++ b/configure @@ -5371,7 +5371,7 @@ MAGICK_PATCHLEVEL_VERSION=8 MAGICK_VERSION=7.1.2-8 -MAGICK_GIT_REVISION=47ef75820:20251014 +MAGICK_GIT_REVISION=d56b6afca:20251014 # Substitute library versioning