Commit 92b961a50 for imagemagick.org
commit 92b961a5040d9bddb4054dcc72a7bde67190c89e
Author: Cristy <urban-warrior@imagemagick.org>
Date: Tue Jun 30 20:22:09 2026 -0400
Improve cache I/O robustness and fix race conditions
diff --git a/MagickCore/cache.c b/MagickCore/cache.c
index 2e7854d2f..e28372ee9 100644
--- a/MagickCore/cache.c
+++ b/MagickCore/cache.c
@@ -75,6 +75,9 @@
#include "MagickCore/thread-private.h"
#include "MagickCore/utility.h"
#include "MagickCore/utility-private.h"
+#if defined(MAGICKCORE_HAVE_ERRNO_H)
+# include <errno.h>
+#endif
#if defined(MAGICKCORE_HAVE_SYS_LOADAVG_H)
# include <sys/loadavg.h>
#endif
@@ -638,10 +641,15 @@ static MagickBooleanType ClonePixelCacheOnDisk(
#if defined(MAGICKCORE_HAVE_LINUX_SENDFILE)
if (cache_info->length < 0x7ffff000)
{
- count=sendfile(clone_info->file,cache_info->file,(off_t *) NULL,
- (size_t) cache_info->length);
+ do
+ {
+ count=sendfile(clone_info->file,cache_info->file,(off_t *) NULL,
+ (size_t) cache_info->length);
+ } while ((count < 0) && (errno == EINTR));
if (count == (ssize_t) cache_info->length)
return(MagickTrue);
+ if (count < 0)
+ return(MagickFalse);
if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
(lseek(clone_info->file,0,SEEK_SET) < 0))
return(MagickFalse);
@@ -653,20 +661,46 @@ static MagickBooleanType ClonePixelCacheOnDisk(
if (buffer == (unsigned char *) NULL)
ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
extent=0;
- while ((count=read(cache_info->file,buffer,quantum)) > 0)
+ while (extent < cache_info->length)
{
- ssize_t
- number_bytes;
+ size_t
+ length;
- number_bytes=write(clone_info->file,buffer,(size_t) count);
- if (number_bytes != count)
- break;
- extent+=(size_t) number_bytes;
+ length=(size_t) MagickMin((MagickSizeType) quantum,cache_info->length-
+ extent);
+ do
+ {
+ count=read(cache_info->file,buffer,length);
+ } while ((count < 0) && (errno == EINTR));
+ if (count <= 0)
+ {
+ buffer=(unsigned char *) RelinquishMagickMemory(buffer);
+ return(MagickFalse);
+ }
+ {
+ ssize_t
+ number_bytes,
+ offset = 0;
+
+ while (offset < count)
+ {
+ do
+ {
+ number_bytes=write(clone_info->file,buffer+offset,(size_t) (count-
+ offset));
+ } while ((number_bytes < 0) && (errno == EINTR));
+ if (number_bytes <= 0)
+ {
+ buffer=(unsigned char *) RelinquishMagickMemory(buffer);
+ return(MagickFalse);
+ }
+ offset+=number_bytes;
+ }
+ extent+=(MagickSizeType) offset;
+ }
}
buffer=(unsigned char *) RelinquishMagickMemory(buffer);
- if (extent != cache_info->length)
- return(MagickFalse);
- return(MagickTrue);
+ return(extent == cache_info->length ? MagickTrue : MagickFalse);
}
#if defined(MAGICKCORE_OPENMP_SUPPORT)