Commit bbbf79e33 for imagemagick.org
commit bbbf79e33935be36890707a49103b0e66698b82e
Author: Cristy <urban-warrior@imagemagick.org>
Date: Wed Jul 8 20:22:02 2026 -0400
ensure file resource identify is valid
diff --git a/MagickCore/policy-private.h b/MagickCore/policy-private.h
index 839e6acdc..ba551d558 100644
--- a/MagickCore/policy-private.h
+++ b/MagickCore/policy-private.h
@@ -22,6 +22,7 @@
extern "C" {
#endif
+#include "MagickCore/resource-private.h"
#include "MagickCore/utility-private.h"
#if MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
@@ -126,20 +127,22 @@ static inline MagickBooleanType IsPathContainsSymlink(const char *path)
}
static inline MagickBooleanType IsPathAuthorized(const PolicyRights rights,
- const char *filename)
+ const char *path)
{
MagickBooleanType symlink_follow_allowed = IsRightsAuthorizedByName(
SystemPolicyDomain,"symlink",rights,"follow");
MagickBooleanType status =
- ((IsRightsAuthorized(PathPolicyDomain,rights,filename) != MagickFalse) &&
+ ((IsRightsAuthorized(PathPolicyDomain,rights,path) != MagickFalse) &&
((symlink_follow_allowed != MagickFalse) ||
- (is_symlink_utf8(filename) == MagickFalse))) ? MagickTrue : MagickFalse;
+ (is_symlink_utf8(path) == MagickFalse))) ? MagickTrue : MagickFalse;
if ((status != MagickFalse) && (symlink_follow_allowed == MagickFalse))
{
- if ((is_symlink_utf8(filename) != MagickFalse) ||
- (IsPathContainsSymlink(filename) != MagickFalse))
+ if ((is_symlink_utf8(path) != MagickFalse) ||
+ (IsPathContainsSymlink(path) != MagickFalse))
status=MagickFalse;
}
+ if (status != MagickFalse)
+ status=IsFileResourceIdentityValid(path);
return(status);
}
diff --git a/MagickCore/resource-private.h b/MagickCore/resource-private.h
index abcd143a6..0965d6396 100644
--- a/MagickCore/resource-private.h
+++ b/MagickCore/resource-private.h
@@ -26,6 +26,9 @@ extern "C" {
# define MagickFormatExtent 64
#endif
+extern MagickExport MagickBooleanType
+ IsFileResourceIdentityValid(const char *);
+
extern MagickPrivate MagickBooleanType
ResourceComponentGenesis(void);
diff --git a/MagickCore/resource.c b/MagickCore/resource.c
index 5bdc3704d..05c77d8ec 100644
--- a/MagickCore/resource.c
+++ b/MagickCore/resource.c
@@ -70,7 +70,6 @@
/*
Define declarations.
*/
-#define MagickPathTemplate "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" /* min 6 X's */
#define NumberOfResourceTypes \
(sizeof(resource_semaphore)/sizeof(*resource_semaphore))
@@ -462,89 +461,6 @@ static void *DestroyTemporaryResources(void *temporary_resource)
return((void *) NULL);
}
-MagickExport MagickBooleanType GetPathTemplate(char *path)
-{
- char
- *directory,
- *value;
-
- ExceptionInfo
- *exception;
-
- MagickBooleanType
- status;
-
- struct stat
- attributes;
-
- (void) FormatLocaleString(path,MagickPathExtent,"magick-" MagickPathTemplate);
- exception=AcquireExceptionInfo();
- directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path",
- exception);
- exception=DestroyExceptionInfo(exception);
- if (directory == (char *) NULL)
- directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH");
- if (directory == (char *) NULL)
- directory=GetEnvironmentValue("MAGICK_TMPDIR");
- if (directory == (char *) NULL)
- directory=GetEnvironmentValue("TMPDIR");
-#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__) || defined(__CYGWIN__)
- if (directory == (char *) NULL)
- directory=GetEnvironmentValue("TMP");
- if (directory == (char *) NULL)
- directory=GetEnvironmentValue("TEMP");
-#endif
-#if defined(__VMS)
- if (directory == (char *) NULL)
- directory=GetEnvironmentValue("MTMPDIR");
-#endif
-#if defined(P_tmpdir)
- if (directory == (char *) NULL)
- directory=ConstantString(P_tmpdir);
-#endif
- if (directory == (char *) NULL)
- return(MagickFalse);
- value=GetPolicyValue("resource:temporary-path");
- if (value != (char *) NULL)
- {
- (void) CloneString(&directory,value);
- value=DestroyString(value);
- }
- if (strlen(directory) > (MagickPathExtent-25))
- {
- directory=DestroyString(directory);
- return(MagickFalse);
- }
- status=GetPathAttributes(directory,&attributes);
- if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode))
- {
- directory=DestroyString(directory);
- return(MagickFalse);
- }
- if (directory[strlen(directory)-1] == *DirectorySeparator)
- (void) FormatLocaleString(path,MagickPathExtent,"%smagick-"
- MagickPathTemplate,directory);
- else
- (void) FormatLocaleString(path,MagickPathExtent,
- "%s%smagick-" MagickPathTemplate,directory,DirectorySeparator);
- directory=DestroyString(directory);
-#if defined(MAGICKCORE_WINDOWS_SUPPORT)
- {
- char
- *p;
-
- /*
- Ghostscript does not like backslashes so we need to replace them. The
- forward slash also works under Windows.
- */
- for (p=(path[1] == *DirectorySeparator ? path+2 : path); *p != '\0'; p++)
- if (*p == *DirectorySeparator)
- *p='/';
- }
-#endif
- return(MagickTrue);
-}
-
MagickExport int AcquireUniqueFileResource(char *path)
{
#if !defined(O_NOFOLLOW)
@@ -785,6 +701,57 @@ MagickExport MagickSizeType GetMagickResource(const ResourceType type)
% %
% %
% %
+% I s F i l e R e s o u r c e I d e n t i t y V a l i d %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% IsFileResourceIdentityValid() returns MagickTrue if the file resource
+% identity is valid.
+%
+% The format of the IsFileResourceIdentityValid() method is:
+%
+% MagickBooleanType IsFileResourceIdentityValid(const char *path)
+%
+% A description of each parameter follows:
+%
+% o path: the file resource path.
+%
+*/
+MagickExport MagickBooleanType IsFileResourceIdentityValid(const char *path)
+{
+ const struct stat
+ *temporary_attributes;
+
+ MagickBooleanType
+ status = MagickTrue;
+
+ struct stat
+ attributes;
+
+ if (temporary_resources == (SplayTreeInfo *) NULL)
+ return(MagickTrue);
+ LockSemaphoreInfo(resource_semaphore[FileResource]);
+ temporary_attributes=(const struct stat *) GetValueFromSplayTree(
+ temporary_resources,(const void *) path);
+ if (temporary_attributes != (const struct stat *) NULL)
+ {
+ status=GetPathAttributes(path,&attributes);
+ if (status != MagickFalse)
+ if ((attributes.st_dev != temporary_attributes->st_dev) ||
+ (attributes.st_ino != temporary_attributes->st_ino))
+ status=MagickFalse;
+ }
+ UnlockSemaphoreInfo(resource_semaphore[FileResource]);
+ return(status);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
% G e t M a g i c k R e s o u r c e L i m i t %
% %
% %
@@ -1181,26 +1148,7 @@ MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
ActivateSemaphoreInfo(&resource_semaphore[FileResource]);
LockSemaphoreInfo(resource_semaphore[FileResource]);
if (temporary_resources != (SplayTreeInfo *) NULL)
- {
- const struct stat
- *temporary_attributes;
-
- struct stat
- attributes;
-
- temporary_attributes=(const struct stat *) GetValueFromSplayTree(
- temporary_resources,(const void *) path);
- status=GetPathAttributes(path,&attributes);
- if ((temporary_attributes != (const struct stat *) NULL) &&
- (status != MagickFalse))
- {
- if ((attributes.st_dev != temporary_attributes->st_dev) ||
- (attributes.st_ino != temporary_attributes->st_ino))
- ThrowFatalException(PolicyFatalError,
- "time-of-check to time-of-use violation");
- }
- status=DeleteNodeFromSplayTree(temporary_resources,(const void *) path);
- }
+ status=DeleteNodeFromSplayTree(temporary_resources,(const void *) path);
UnlockSemaphoreInfo(resource_semaphore[FileResource]);
(void) CopyMagickString(cache_path,path,MagickPathExtent);
AppendImageFormat("cache",cache_path);
diff --git a/MagickCore/resource_.h b/MagickCore/resource_.h
index 500b64998..a65a1251c 100644
--- a/MagickCore/resource_.h
+++ b/MagickCore/resource_.h
@@ -45,7 +45,6 @@ extern MagickExport int
extern MagickExport MagickBooleanType
AcquireMagickResource(const ResourceType,const MagickSizeType),
- GetPathTemplate(char *),
ListMagickResourceInfo(FILE *,ExceptionInfo *),
RelinquishUniqueFileResource(const char *),
SetMagickResourceLimit(const ResourceType,const MagickSizeType);
diff --git a/MagickCore/utility-private.h b/MagickCore/utility-private.h
index d644c2c14..8242e5f1e 100644
--- a/MagickCore/utility-private.h
+++ b/MagickCore/utility-private.h
@@ -32,6 +32,8 @@
extern "C" {
#endif
+#define MagickPathTemplate "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" /* min 6 X's */
+
extern MagickPrivate char
**GetPathComponents(const char *,size_t *),
**ListFiles(const char *,const char *,size_t *);
diff --git a/MagickCore/utility.c b/MagickCore/utility.c
index 58a46beee..f06cfeaad 100644
--- a/MagickCore/utility.c
+++ b/MagickCore/utility.c
@@ -1522,6 +1522,114 @@ MagickPrivate char **GetPathComponents(const char *path,
% %
% %
% %
+% G e t P a t h T e m p l a t e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% GetPathTemplate() constructs a template for a temporary filename.
+%
+% The format of the GetPathComponent function is:
+%
+% MagickBooleanType GetPathComponent(const char *path)
+%
+% A description of each parameter follows:
+%
+% o path: Specifies a pointer to a character array populated with the
+% file path template.
+%
+%
+*/
+MagickExport MagickBooleanType GetPathTemplate(char *path)
+{
+ char
+ *directory,
+ *value;
+
+ ExceptionInfo
+ *exception;
+
+ MagickBooleanType
+ status;
+
+ struct stat
+ attributes;
+
+ (void) FormatLocaleString(path,MagickPathExtent,"magick-"
+ MagickPathTemplate);
+ exception=AcquireExceptionInfo();
+ directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path",
+ exception);
+ exception=DestroyExceptionInfo(exception);
+ if (directory == (char *) NULL)
+ directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH");
+ if (directory == (char *) NULL)
+ directory=GetEnvironmentValue("MAGICK_TMPDIR");
+ if (directory == (char *) NULL)
+ directory=GetEnvironmentValue("TMPDIR");
+#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__) || defined(__CYGWIN__)
+ if (directory == (char *) NULL)
+ directory=GetEnvironmentValue("TMP");
+ if (directory == (char *) NULL)
+ directory=GetEnvironmentValue("TEMP");
+#endif
+#if defined(__VMS)
+ if (directory == (char *) NULL)
+ directory=GetEnvironmentValue("MTMPDIR");
+#endif
+#if defined(P_tmpdir)
+ if (directory == (char *) NULL)
+ directory=ConstantString(P_tmpdir);
+#endif
+ if (directory == (char *) NULL)
+ return(MagickFalse);
+ value=GetPolicyValue("resource:temporary-path");
+ if (value != (char *) NULL)
+ {
+ (void) CloneString(&directory,value);
+ value=DestroyString(value);
+ }
+ if (strlen(directory) > (MagickPathExtent-25))
+ {
+ directory=DestroyString(directory);
+ return(MagickFalse);
+ }
+ status=GetPathAttributes(directory,&attributes);
+ if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode))
+ {
+ directory=DestroyString(directory);
+ return(MagickFalse);
+ }
+ if (directory[strlen(directory)-1] == *DirectorySeparator)
+ (void) FormatLocaleString(path,MagickPathExtent,"%smagick-"
+ MagickPathTemplate,directory);
+ else
+ (void) FormatLocaleString(path,MagickPathExtent,
+ "%s%smagick-" MagickPathTemplate,directory,DirectorySeparator);
+ directory=DestroyString(directory);
+#if defined(MAGICKCORE_WINDOWS_SUPPORT)
+ {
+ char
+ *p;
+
+ /*
+ Ghostscript does not like backslashes so we need to replace them. The
+ forward slash also works under Windows.
+ */
+ for (p=(path[1] == *DirectorySeparator ? path+2 : path); *p != '\0'; p++)
+ if (*p == *DirectorySeparator)
+ *p='/';
+ }
+#endif
+ return(MagickTrue);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
% I s P a t h A c c e s s i b l e %
% %
% %
diff --git a/MagickCore/utility.h b/MagickCore/utility.h
index ebdc44bb0..5190f967d 100644
--- a/MagickCore/utility.h
+++ b/MagickCore/utility.h
@@ -45,6 +45,7 @@ extern MagickExport MagickBooleanType
AcquireUniqueSymbolicLink(const char *,char *),
ExpandFilenames(int *,char ***),
GetPathAttributes(const char *,void *),
+ GetPathTemplate(char *),
IsPathAccessible(const char *);
extern MagickExport size_t
diff --git a/configure b/configure
index d0cb6bfc3..3e4277837 100755
--- a/configure
+++ b/configure
@@ -4104,8 +4104,8 @@ ac_cxx_conftest_cxx11_main='
}
{
// Unicode literals
- char const *utf8 = u8"UTF-8 string \u2500";
- char16_t const *utf16 = u"UTF-8 string \u2500";
+ auto const *utf8 = u8"UTF-8 string \u2500";
+ char16_t const *utf16 = u"UTF-16 string \u2500";
char32_t const *utf32 = U"UTF-32 string \u2500";
}
'
@@ -5389,7 +5389,7 @@ MAGICK_PATCHLEVEL_VERSION=28
MAGICK_VERSION=7.1.2-28
-MAGICK_GIT_REVISION=b661ac969:20260705
+MAGICK_GIT_REVISION=9f1810998:20260707
# Substitute library versioning
@@ -5423,7 +5423,7 @@ PACKAGE_LIB_VERSION=0x712
PACKAGE_LIB_VERSION_NUMBER=7,1,2,28
-PACKAGE_RELEASE_DATE=2026-07-05
+PACKAGE_RELEASE_DATE=2026-07-07
# Ensure that make can run correctly
@@ -12128,18 +12128,18 @@ then :
fi
if test "$enable_largefile,$enable_year2038" != no,no
then :
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CPPFLAGS option for large files" >&5
-printf %s "checking for $CPPFLAGS option for large files... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable large file support" >&5
+printf %s "checking for $CC option to enable large file support... " >&6; }
if test ${ac_cv_sys_largefile_opts+y}
then :
printf %s "(cached) " >&6
else case e in #(
- e) ac_save_CPPFLAGS=$CPPFLAGS
+ e) ac_save_CC="$CC"
ac_opt_found=no
- for ac_opt in "none needed" "-D_FILE_OFFSET_BITS=64" "-D_LARGE_FILES=1"; do
+ for ac_opt in "none needed" "-D_FILE_OFFSET_BITS=64" "-D_LARGE_FILES=1" "-n32"; do
if test x"$ac_opt" != x"none needed"
then :
- CPPFLAGS="$ac_save_CPPFLAGS $ac_opt"
+ CC="$ac_save_CC $ac_opt"
fi
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -12168,12 +12168,12 @@ then :
if test x"$ac_opt" = x"none needed"
then :
# GNU/Linux s390x and alpha need _FILE_OFFSET_BITS=64 for wide ino_t.
- CPPFLAGS="$CPPFLAGS -DFTYPE=ino_t"
+ CC="$CC -DFTYPE=ino_t"
if ac_fn_c_try_compile "$LINENO"
then :
else case e in #(
- e) CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64"
+ e) CC="$CC -D_FILE_OFFSET_BITS=64"
if ac_fn_c_try_compile "$LINENO"
then :
ac_opt='-D_FILE_OFFSET_BITS=64'
@@ -12189,7 +12189,7 @@ fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
test $ac_opt_found = no || break
done
- CPPFLAGS=$ac_save_CPPFLAGS
+ CC="$ac_save_CC"
test $ac_opt_found = yes || ac_cv_sys_largefile_opts="support not detected" ;;
esac
@@ -12213,14 +12213,16 @@ printf "%s\n" "#define _FILE_OFFSET_BITS 64" >>confdefs.h
printf "%s\n" "#define _LARGE_FILES 1" >>confdefs.h
;; #(
+ "-n32") :
+ CC="$CC -n32" ;; #(
*) :
as_fn_error $? "internal error: bad value for \$ac_cv_sys_largefile_opts" "$LINENO" 5 ;;
esac
if test "$enable_year2038" != no
then :
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CPPFLAGS option for timestamps after 2038" >&5
-printf %s "checking for $CPPFLAGS option for timestamps after 2038... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option for timestamps after 2038" >&5
+printf %s "checking for $CC option for timestamps after 2038... " >&6; }
if test ${ac_cv_sys_year2038_opts+y}
then :
printf %s "(cached) " >&6