Commit c9120e952 for imagemagick.org

commit c9120e952d405b5a490726cfa870a916cb95cfda
Author: Cristy <urban-warrior@imagemagick.org>
Date:   Sat Sep 12 09:30:44 2026 -0400

    block file descriptor inheritance

diff --git a/MagickCore/blob.c b/MagickCore/blob.c
index 87fc88771..5e46cfd21 100644
--- a/MagickCore/blob.c
+++ b/MagickCore/blob.c
@@ -387,7 +387,7 @@ MagickExport MagickBooleanType BlobToFile(char *filename,const void *blob,
   if (*filename == '\0')
     file=AcquireUniqueFileResource(filename);
   else
-    file=open_utf8(filename,O_WRONLY | O_CREAT | O_EXCL | O_BINARY,P_MODE);
+    file=open_utf8(filename,O_WRONLY | O_CLOEXEC | O_CREAT | O_EXCL | O_BINARY,P_MODE);
   if (file == -1)
     {
       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
@@ -1457,7 +1457,7 @@ MagickExport void *FileToBlob(const char *filename,const size_t extent,
   if (LocaleCompare(filename,"-") != 0)
     {
       int
-        flags = O_RDONLY | O_BINARY;
+        flags = O_RDONLY | O_CLOEXEC | O_BINARY;

       status=GetPathAttributes(filename,&attributes);
       if ((status == MagickFalse) || (S_ISDIR(attributes.st_mode) != 0))
@@ -1671,7 +1671,7 @@ MagickExport MagickBooleanType FileToImage(Image *image,const char *filename,
   if (LocaleCompare(filename,"-") != 0)
     {
       int
-        flags = O_RDONLY | O_BINARY;
+        flags = O_RDONLY | O_CLOEXEC | O_BINARY;

       file=open_utf8(filename,flags,0);
     }
@@ -2380,7 +2380,7 @@ MagickExport MagickBooleanType ImageToFile(Image *image,char *filename,
     if (LocaleCompare(filename,"-") == 0)
       file=fileno(stdout);
     else
-      file=open_utf8(filename,O_RDWR | O_CREAT | O_EXCL | O_BINARY,P_MODE);
+      file=open_utf8(filename,O_RDWR | O_CLOEXEC | O_CREAT | O_EXCL | O_BINARY,P_MODE);
   if (file == -1)
     {
       ThrowFileException(exception,BlobError,"UnableToWriteBlob",filename);
@@ -2832,7 +2832,7 @@ MagickExport MagickBooleanType InjectImageBlob(const ImageInfo *image_info,
   /*
     Inject into image stream.
   */
-  file=open_utf8(filename,O_RDONLY | O_BINARY,0);
+  file=open_utf8(filename,O_RDONLY | O_CLOEXEC | O_BINARY,0);
   if (file == -1)
     {
       (void) RelinquishUniqueFileResource(filename);
@@ -3286,7 +3286,7 @@ MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
     *type;

   int
-    flags = O_RDONLY;
+    flags = O_RDONLY | O_CLOEXEC;

   MagickBooleanType
     status;
@@ -3325,43 +3325,43 @@ MagickExport MagickBooleanType OpenBlob(const ImageInfo *image_info,
   {
     case ReadBlobMode:
     {
-      flags=O_RDONLY;
+      flags=O_RDONLY | O_CLOEXEC;
       type="r";
       break;
     }
     case ReadBinaryBlobMode:
     {
-      flags=O_RDONLY | O_BINARY;
+      flags=O_RDONLY | O_CLOEXEC | O_BINARY;
       type="rb";
       break;
     }
     case WriteBlobMode:
     {
-      flags=O_WRONLY | O_CREAT | O_TRUNC;
+      flags=O_WRONLY | O_CLOEXEC | O_CREAT | O_TRUNC;
       type="w";
       break;
     }
     case WriteBinaryBlobMode:
     {
-      flags=O_RDWR | O_CREAT | O_TRUNC | O_BINARY;
+      flags=O_RDWR | O_CLOEXEC | O_CREAT | O_TRUNC | O_BINARY;
       type="w+b";
       break;
     }
     case AppendBlobMode:
     {
-      flags=O_WRONLY | O_CREAT | O_APPEND;
+      flags=O_WRONLY | O_CLOEXEC | O_CREAT | O_APPEND;
       type="a";
       break;
     }
     case AppendBinaryBlobMode:
     {
-      flags=O_RDWR | O_CREAT | O_APPEND | O_BINARY;
+      flags=O_RDWR | O_CLOEXEC | O_CREAT | O_APPEND | O_BINARY;
       type="a+b";
       break;
     }
     default:
     {
-      flags=O_RDONLY;
+      flags=O_RDONLY | O_CLOEXEC;
       type="r";
       break;
     }
diff --git a/MagickCore/cache.c b/MagickCore/cache.c
index f878ed2bf..c9a0c7d57 100644
--- a/MagickCore/cache.c
+++ b/MagickCore/cache.c
@@ -3638,24 +3638,24 @@ static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
     {
       case ReadMode:
       {
-        file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
+        file=open_utf8(cache_info->cache_filename,O_RDONLY | O_CLOEXEC | O_BINARY,0);
         break;
       }
       case WriteMode:
       {
-        file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
+        file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CLOEXEC | O_CREAT |
           O_BINARY | O_EXCL,S_MODE);
         if (file == -1)
-          file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
+          file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CLOEXEC | O_BINARY,S_MODE);
         break;
       }
       case IOMode:
       default:
       {
-        file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
+        file=open_utf8(cache_info->cache_filename,O_RDWR | O_CLOEXEC | O_CREAT | O_BINARY |
           O_EXCL,S_MODE);
         if (file == -1)
-          file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
+          file=open_utf8(cache_info->cache_filename,O_RDWR | O_CLOEXEC | O_BINARY,S_MODE);
         break;
       }
     }
diff --git a/MagickCore/delegate.c b/MagickCore/delegate.c
index 9c6e76a2f..de6ec00eb 100644
--- a/MagickCore/delegate.c
+++ b/MagickCore/delegate.c
@@ -1657,7 +1657,7 @@ static MagickBooleanType CopyDelegateFile(const char *source,
     return(MagickTrue);
   if (IsPathAuthorized(WritePolicyRights,destination) == MagickFalse)
     ThrowPolicyException(source,MagickFalse);
-  destination_file=open_utf8(destination,O_WRONLY | O_BINARY | O_CREAT |
+  destination_file=open_utf8(destination,O_WRONLY | O_CLOEXEC | O_BINARY | O_CREAT |
     O_NOFOLLOW,S_MODE);
   if (destination_file == -1)
     return(MagickFalse);
@@ -1668,7 +1668,7 @@ static MagickBooleanType CopyDelegateFile(const char *source,
       (void) close_utf8(destination_file);
       ThrowPolicyException(source,MagickFalse);
     }
-  source_file=open_utf8(source,O_RDONLY | O_BINARY,0);
+  source_file=open_utf8(source,O_RDONLY | O_CLOEXEC | O_BINARY,0);
   if (source_file == -1)
     {
       (void) close_utf8(destination_file);
diff --git a/MagickCore/random.c b/MagickCore/random.c
index ab5c9b4be..405799575 100644
--- a/MagickCore/random.c
+++ b/MagickCore/random.c
@@ -546,7 +546,7 @@ static StringInfo *GenerateEntropicChaos(RandomInfo *random_info)
     filename=AcquireString("/dev/urandom");
     device=StringToStringInfo(filename);
     device=DestroyStringInfo(device);
-    file=open_utf8(filename,O_RDONLY | O_BINARY,0);
+    file=open_utf8(filename,O_RDONLY | O_CLOEXEC | O_BINARY,0);
     filename=DestroyString(filename);
     if (file != -1)
       {
@@ -564,14 +564,14 @@ static StringInfo *GenerateEntropicChaos(RandomInfo *random_info)
         filename=AcquireString("/dev/random");
         device=StringToStringInfo(filename);
         device=DestroyStringInfo(device);
-        file=open_utf8(filename,O_RDONLY | O_BINARY,0);
+        file=open_utf8(filename,O_RDONLY | O_CLOEXEC | O_BINARY,0);
         filename=DestroyString(filename);
         if (file == -1)
           {
             filename=AcquireString("/dev/srandom");
             device=StringToStringInfo(filename);
             device=DestroyStringInfo(device);
-            file=open_utf8(filename,O_RDONLY | O_BINARY,0);
+            file=open_utf8(filename,O_RDONLY | O_CLOEXEC | O_BINARY,0);
           }
         if (file != -1)
           {
diff --git a/MagickCore/resource.c b/MagickCore/resource.c
index b8ae38a70..7bc3eacfa 100644
--- a/MagickCore/resource.c
+++ b/MagickCore/resource.c
@@ -542,7 +542,7 @@ MagickExport int AcquireUniqueFileResource(char *path)
       *p++=portable_filename[c];
     }
     key=DestroyStringInfo(key);
-    file=open_utf8(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,
+    file=open_utf8(path,O_RDWR | O_CLOEXEC | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,
       S_MODE);
     if ((file >= 0) || (errno != EEXIST))
       break;
diff --git a/MagickCore/string.c b/MagickCore/string.c
index 07ca6fe8f..969c46580 100644
--- a/MagickCore/string.c
+++ b/MagickCore/string.c
@@ -589,7 +589,7 @@ MagickExport StringInfo *ConfigureFileToStringInfo(const char *filename)
     *map;

   assert(filename != (const char *) NULL);
-  file=open_utf8(filename,O_RDONLY | O_BINARY,0);
+  file=open_utf8(filename,O_RDONLY | O_CLOEXEC | O_BINARY,0);
   if (file == -1)
     return((StringInfo *) NULL);
   offset=(MagickOffsetType) lseek(file,0,SEEK_END);
diff --git a/MagickCore/studio.h b/MagickCore/studio.h
index f8bca9257..a3debf143 100644
--- a/MagickCore/studio.h
+++ b/MagickCore/studio.h
@@ -327,6 +327,14 @@ extern int vsnprintf(char *,size_t,const char *,va_list);
 #define O_BINARY  0x00
 #endif

+#if !defined(O_CLOEXEC)
+#if defined(_WIN32) || defined(_WIN64)
+#  define O_CLOEXEC _O_NOINHERIT
+#else
+#define O_CLOEXEC 0
+#endif
+#endif
+
 #if !defined(O_NOFOLLOW)
 #define O_NOFOLLOW 0
 #endif
diff --git a/MagickCore/utility.c b/MagickCore/utility.c
index 4d0e1967f..0f21215c8 100644
--- a/MagickCore/utility.c
+++ b/MagickCore/utility.c
@@ -221,7 +221,7 @@ MagickExport MagickBooleanType AcquireUniqueSymbolicLink(const char *source,
   destination_file=AcquireUniqueFileResource(destination);
   if (destination_file == -1)
     return(MagickFalse);
-  source_file=open_utf8(source,O_RDONLY | O_BINARY,0);
+  source_file=open_utf8(source,O_RDONLY | O_CLOEXEC | O_BINARY,0);
   if (source_file == -1)
     {
       (void) close_utf8(destination_file);
@@ -2067,7 +2067,7 @@ MagickPrivate MagickBooleanType ShredFile(const char *path)
   /*
     Shred the file.
   */
-  file=open_utf8(path,O_WRONLY | O_EXCL | O_BINARY,S_MODE);
+  file=open_utf8(path,O_WRONLY | O_CLOEXEC | O_EXCL | O_BINARY,S_MODE);
   if (file == -1)
     return(MagickFalse);
   quantum=(size_t) MagickMinBufferExtent;
diff --git a/MagickCore/xml-tree.c b/MagickCore/xml-tree.c
index 166fecb93..073cb5a1a 100644
--- a/MagickCore/xml-tree.c
+++ b/MagickCore/xml-tree.c
@@ -596,7 +596,7 @@ MagickPrivate char *FileToXML(const char *filename,const size_t extent)
   length=0;
   file=fileno(stdin);
   if (LocaleCompare(filename,"-") != 0)
-    file=open_utf8(filename,O_RDONLY | O_BINARY,0);
+    file=open_utf8(filename,O_RDONLY | O_CLOEXEC | O_BINARY,0);
   if (file == -1)
     return((char *) NULL);
   offset=(MagickOffsetType) lseek(file,0,SEEK_END);
diff --git a/MagickWand/mogrify.c b/MagickWand/mogrify.c
index b397e290f..cf2ec3fa2 100644
--- a/MagickWand/mogrify.c
+++ b/MagickWand/mogrify.c
@@ -3932,7 +3932,7 @@ WandExport MagickBooleanType MogrifyImageCommand(ImageInfo *image_info,
                 "%s-%02x%02x%02x%02x~",image->filename,key_bytes[0],
                 key_bytes[1],key_bytes[2],key_bytes[3]);
               key_info=DestroyStringInfo(key_info);
-              file=open_utf8(backup_filename,O_RDWR | O_CREAT | O_EXCL |
+              file=open_utf8(backup_filename,O_RDWR | O_CLOEXEC | O_CREAT | O_EXCL |
                 O_BINARY | O_NOFOLLOW,S_MODE);
               if ((file >= 0) || (errno != EEXIST))
                 break;
diff --git a/MagickWand/studio.h b/MagickWand/studio.h
index 1ef22da21..92d245ea0 100644
--- a/MagickWand/studio.h
+++ b/MagickWand/studio.h
@@ -286,6 +286,14 @@ extern int vsnprintf(char *,size_t,const char *,va_list);
 #define O_BINARY  0x00
 #endif

+#if !defined(O_CLOEXEC)
+#if defined(_WIN32) || defined(_WIN64)
+#  define O_CLOEXEC _O_NOINHERIT
+#else
+#define O_CLOEXEC 0
+#endif
+#endif
+
 #if !defined(O_NOFOLLOW)
 #define O_NOFOLLOW 0
 #endif
diff --git a/coders/video.c b/coders/video.c
index 89ae0b192..59d366953 100644
--- a/coders/video.c
+++ b/coders/video.c
@@ -515,11 +515,11 @@ static MagickBooleanType CopyDelegateFile(const char *source,
 #endif
     }
   else
-    destination_file=open_utf8(destination,O_WRONLY | O_BINARY | O_CREAT |
+    destination_file=open_utf8(destination,O_WRONLY | O_CLOEXEC | O_BINARY | O_CREAT |
       O_TRUNC,S_MODE);
   if (destination_file == -1)
     return(MagickFalse);
-  source_file=open_utf8(source,O_RDONLY | O_BINARY,0);
+  source_file=open_utf8(source,O_RDONLY | O_CLOEXEC | O_BINARY,0);
   if (source_file == -1)
     {
       if (strcmp(destination,"-") != 0)