Commit 11313ac54 for imagemagick.org
commit 11313ac549e3466edaa47012616b0db4def5c22b
Author: Dirk Lemstra <dirk@lemstra.org>
Date: Sat Oct 24 18:19:38 2026 +0200
Added new security option that can be used to limit the number of profiles an image can have (GHSA-2h6m-67xh-cm4p)
diff --git a/MagickCore/profile-private.h b/MagickCore/profile-private.h
index 96c7e56b4..03d99c378 100644
--- a/MagickCore/profile-private.h
+++ b/MagickCore/profile-private.h
@@ -27,6 +27,9 @@ extern "C" {
extern MagickExport MagickBooleanType
SetImageProfilePrivate(Image *,StringInfo *,ExceptionInfo *);
+extern MagickExport size_t
+ GetMaxProfileCount(void);
+
extern MagickExport StringInfo
*AcquireProfileStringInfo(const char *,const size_t length,ExceptionInfo *),
*BlobToProfileStringInfo(const char *,const void *blob,const size_t length,
diff --git a/MagickCore/profile.c b/MagickCore/profile.c
index bf384281b..a7b11d5a3 100644
--- a/MagickCore/profile.c
+++ b/MagickCore/profile.c
@@ -56,6 +56,7 @@
#include "MagickCore/option.h"
#include "MagickCore/option-private.h"
#include "MagickCore/pixel-accessor.h"
+#include "MagickCore/policy.h"
#include "MagickCore/profile.h"
#include "MagickCore/profile-private.h"
#include "MagickCore/property.h"
@@ -91,6 +92,12 @@ static MagickBooleanType
static void
WriteTo8BimProfile(Image *,const char*,const StringInfo *);
+/*
+ Global declarations.
+*/
+static size_t
+ max_profile_count = 0;
+
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
@@ -350,6 +357,51 @@ MagickExport const StringInfo *GetImageProfile(const Image *image,
% %
% %
% %
++ G e t M a x P r o f i l e C o u n t %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% GetMaxProfileCount() returns the max profile count value.
+%
+% The format of the GetMaxProfileCount method is:
+%
+% size_t GetMaxProfileCount(void)
+%
+*/
+static size_t GetMaxProfileCountFromPolicy(void)
+{
+ char
+ *value;
+
+ size_t
+ max=(size_t) MAGICK_SSIZE_MAX;
+
+ value=GetPolicyValue("system:max-profile-count");
+ if (value != (char *) NULL)
+ {
+ /*
+ The security policy sets a max profile count limit.
+ */
+ max=StringToSizeType(value,100.0);
+ value=DestroyString(value);
+ }
+ return(MagickMin(max,(size_t) MAGICK_SSIZE_MAX));
+}
+
+MagickExport size_t GetMaxProfileCount(void)
+{
+ if (max_profile_count == 0)
+ max_profile_count=GetMaxProfileCountFromPolicy();
+ return(max_profile_count);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
% G e t N e x t I m a g e P r o f i l e %
% %
% %
@@ -2042,6 +2094,14 @@ static MagickBooleanType SetImageProfileInternal(Image *image,const char *name,
assert(name != (const char *) NULL);
if (IsEventLogging() != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ if ((image->profiles != (SplayTreeInfo*) NULL) &&
+ (GetNumberOfNodesInSplayTree((SplayTreeInfo*) image->profiles) >= GetMaxProfileCount()))
+ {
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ ResourceLimitWarning,"MaximumProfilesExceeded","`%s'",name);
+ profile=DestroyStringInfo(profile);
+ return(MagickFalse);
+ }
length=GetStringInfoLength(profile);
if ((length == 0) || (length > GetMaxProfileSize()))
{