Commit cafc7372c for imagemagick.org
commit cafc7372c8113a9636766f0eddde7b90373c9b44
Author: Cristy <urban-warrior@imagemagick.org>
Date: Tue Sep 8 19:42:24 2026 -0400
https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-2vwg-3g4g-qprm
diff --git a/MagickCore/distribute-cache.c b/MagickCore/distribute-cache.c
index 62c6158d8..6fb387564 100644
--- a/MagickCore/distribute-cache.c
+++ b/MagickCore/distribute-cache.c
@@ -156,7 +156,7 @@ static size_t
*/
#if !defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE)
-static inline MagickOffsetType dpc_read(SOCKET_TYPE magick_unused(file),
+static inline MagickOffsetType dpc_receive(SOCKET_TYPE magick_unused(file),
const MagickSizeType magick_unused(length),
unsigned char *magick_restrict magick_unused(message))
{
@@ -165,25 +165,118 @@ static inline MagickOffsetType dpc_read(SOCKET_TYPE magick_unused(file),
magick_unreferenced(message);
return(-1);
}
+
+static inline MagickOffsetType dpc_receive_deadline(SOCKET_TYPE
+ magick_unused(file),const MagickSizeType magick_unused(length),
+ unsigned char *magick_restrict magick_unused(message),
+ double magick_unused(deadline))
+{
+ magick_unreferenced(file);
+ magick_unreferenced(length);
+ magick_unreferenced(message);
+ magick_unreferenced(deadline);
+ return(-1);
+}
#else
-static inline MagickOffsetType dpc_read(SOCKET_TYPE file,
+static void SetSocketReceiveTimeout(SOCKET_TYPE file,double seconds)
+{
+ /*
+ Set a receive timeout.
+ */
+#if defined(MAGICKCORE_HAVE_WINSOCK2)
+ {
+ DWORD timeout = (DWORD) (seconds*1000.0);
+ (void) setsockopt(file,SOL_SOCKET,SO_RCVTIMEO,
+ (const char *) &timeout,sizeof(timeout));
+ }
+#else
+ {
+ struct timeval tv;
+ tv.tv_sec=(int) seconds;
+ tv.tv_usec=(int) ((seconds-(double) tv.tv_sec)*1000000.0);
+ (void) setsockopt(file,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv));
+ }
+#endif
+}
+
+static inline MagickOffsetType dpc_receive(SOCKET_TYPE file,
const MagickSizeType length,unsigned char *magick_restrict message)
{
MagickOffsetType offset = 0;
while (offset < (MagickOffsetType) length)
{
- MagickSizeType remaining = length-(MagickSizeType) offset;
- ssize_t count = recv(file,(char *) message+offset,(LENGTH_TYPE)
- MagickMin(remaining,(MagickSizeType) MagickMaxBufferExtent),0);
+ size_t chunk = MagickMin(length-offset,(size_t) MagickMaxBufferExtent);
+ ssize_t count = recv(file,(char *) message+offset,(LENGTH_TYPE) chunk,0);
if (count > 0)
offset+=(MagickOffsetType) count;
else
if (count == 0)
- break;
+ return(0);
+ else
+ {
+#ifdef MAGICKCORE_HAVE_WINSOCK2
+ int wsa_err = WSAGetLastError();
+ if ((wsa_err == WSAEINTR) || (wsa_err == WSAEWOULDBLOCK))
+ continue;
+ if (wsa_err == WSAECONNRESET)
+ return(-2);
+#else
+ if ((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK))
+ continue;
+ if (errno == ECONNRESET)
+ return(-2);
+#endif
+ return(-1);
+ }
+ }
+ return(offset);
+}
+
+static inline MagickOffsetType dpc_receive_deadline(SOCKET_TYPE file,
+ MagickSizeType length,unsigned char *message,double deadline)
+{
+ /*
+ Enforce an absolute deadline for authentication reads.
+ */
+ MagickOffsetType offset = 0;
+ while (offset < (MagickOffsetType) length)
+ {
+ double
+ now = (double) time((time_t *) NULL),
+ remaining = deadline-now;
+
+ size_t
+ chunk;
+
+ ssize_t
+ count;
+
+ if (now >= deadline)
+ return(-1);
+ if (remaining < 0.001)
+ remaining=0.001;
+ SetSocketReceiveTimeout(file,remaining);
+ chunk=MagickMin(length-offset,(size_t) MagickMaxBufferExtent);
+ count=recv(file,(char *) message+offset,(LENGTH_TYPE) chunk,0);
+ if (count > 0)
+ offset+=(MagickOffsetType) count;
+ else
+ if (count == 0)
+ return(0);
else
{
- if (errno != EINTR)
- break;
+#ifdef _WIN32
+ int wsa_err = WSAGetLastError();
+ if ((wsa_err == WSAEINTR) || (wsa_err == WSAEWOULDBLOCK))
+ continue;
+ if (wsa_err == WSAECONNRESET)
+ return(-2);
+ return(-1);
+#else
+ if ((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK))
+ continue;
+ return(-1);
+#endif
}
}
return(offset);
@@ -314,7 +407,7 @@ static inline void DeriveSIPKeyFromSecret(const char *shared_secret,
for (i=0; i < length; i++)
{
uint8_t
- b = shared_secret[i];
+ b = (uint8_t) shared_secret[i];
k0^=b;
k0*=0x100000001b3ULL;
@@ -500,7 +593,7 @@ static char *GetHostname(int *port,ExceptionInfo *exception)
if (hostlist[2] == (char *) NULL)
*port=DPCPort;
else
- *port=StringToLong(hostlist[2]);
+ *port=(int) StringToLong(hostlist[2]);
for (i=0; i < (ssize_t) argc; i++)
hostlist[i]=DestroyString(hostlist[i]);
hostlist=(char **) RelinquishMagickMemory(hostlist);
@@ -634,7 +727,7 @@ static inline MagickOffsetType dpc_send(SOCKET_TYPE file,
count=0;
for (i=0; i < (MagickOffsetType) length; i+=count)
{
- count=(ssize_t) send(file,(char *) message+i,(LENGTH_TYPE) MagickMin(
+ count=(ssize_t) send(file,(const char *) message+i,(LENGTH_TYPE) MagickMin(
length-(MagickSizeType) i,(MagickSizeType) MagickMaxBufferExtent),
MSG_NOSIGNAL);
if (count <= 0)
@@ -701,7 +794,7 @@ static MagickBooleanType OpenDistributeCache(SplayTreeInfo *registry,
sizeof(image->alpha_trait)+sizeof(image->channels)+sizeof(image->columns)+
sizeof(image->rows)+sizeof(image->number_channels)+MaxPixelChannels*
sizeof(*image->channel_map)+sizeof(image->metacontent_extent);
- count=dpc_read(file,length,message);
+ count=dpc_receive(file,length,message);
if (count != (MagickOffsetType) length)
{
image=DestroyImage(image);
@@ -800,7 +893,7 @@ static MagickBooleanType ReadDistributeCacheMetacontent(SplayTreeInfo *registry,
return(MagickFalse);
length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
sizeof(region.y)+sizeof(length);
- count=dpc_read(file,length,message);
+ count=dpc_receive(file,length,message);
if (count != (MagickOffsetType) length)
return(MagickFalse);
q=message;
@@ -864,7 +957,7 @@ static MagickBooleanType ReadDistributeCachePixels(SplayTreeInfo *registry,
return(MagickFalse);
length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
sizeof(region.y)+sizeof(length);
- count=dpc_read(file,length,message);
+ count=dpc_receive(file,length,message);
if (count != (MagickOffsetType) length)
return(MagickFalse);
q=message;
@@ -934,7 +1027,7 @@ static MagickBooleanType WriteDistributeCacheMetacontent(
return(MagickFalse);
length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
sizeof(region.y)+sizeof(length);
- count=dpc_read(file,length,message);
+ count=dpc_receive(file,length,message);
if (count != (MagickOffsetType) length)
return(MagickFalse);
p=message;
@@ -956,7 +1049,7 @@ static MagickBooleanType WriteDistributeCacheMetacontent(
if (q == (Quantum *) NULL)
return(MagickFalse);
metacontent=(unsigned char *) GetAuthenticMetacontent(image);
- count=dpc_read(file,length,metacontent);
+ count=dpc_receive(file,length,metacontent);
if (count != (MagickOffsetType) length)
return(MagickFalse);
return(SyncAuthenticPixels(image,exception));
@@ -998,7 +1091,7 @@ static MagickBooleanType WriteDistributeCachePixels(SplayTreeInfo *registry,
return(MagickFalse);
length=sizeof(region.width)+sizeof(region.height)+sizeof(region.x)+
sizeof(region.y)+sizeof(length);
- count=dpc_read(file,length,message);
+ count=dpc_receive(file,length,message);
if (count != (MagickOffsetType) length)
return(MagickFalse);
p=message;
@@ -1019,7 +1112,7 @@ static MagickBooleanType WriteDistributeCachePixels(SplayTreeInfo *registry,
exception);
if (q == (Quantum *) NULL)
return(MagickFalse);
- count=dpc_read(file,length,(unsigned char *) q);
+ count=dpc_receive(file,length,(unsigned char *) q);
if (count != (MagickOffsetType) length)
return(MagickFalse);
return(SyncAuthenticPixels(image,exception));
@@ -1120,7 +1213,8 @@ static HANDLER_RETURN_TYPE DistributePixelCacheClient(void *socket_arg)
/*
Receive client's keyed hash.
*/
- count=dpc_read(client_socket,sizeof(key),(unsigned char *) &key);
+ count=dpc_receive_deadline(client_socket,sizeof(key),(unsigned char *) &key,
+ (double) time((time_t *) NULL)+5.0);
if ((count != (MagickOffsetType) sizeof(key)) || (key != session_key))
{
CLOSE_SOCKET(client_socket);
@@ -1140,10 +1234,10 @@ static HANDLER_RETURN_TYPE DistributePixelCacheClient(void *socket_arg)
/*
Each command must echo the authenticated session key.
*/
- count=dpc_read(client_socket,1,(unsigned char *) &command);
+ count=dpc_receive(client_socket,1,(unsigned char *) &command);
if (count <= 0)
break;
- count=dpc_read(client_socket,sizeof(key),(unsigned char *) &key);
+ count=dpc_receive(client_socket,sizeof(key),(unsigned char *) &key);
if ((count != (MagickOffsetType) sizeof(key)) || (key != session_key))
break;
switch (command)
@@ -1333,24 +1427,12 @@ MagickExport void DistributePixelCacheServer(const int port,
continue;
status=setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,(char *) &one,
(socklen_t) sizeof(one));
- if (status != -1)
- {
-#if defined(MAGICKCORE_HAVE_WINSOCK2)
- DWORD timeout = 5000; // ms
- status=setsockopt(server_socket,SOL_SOCKET,SO_RCVTIMEO,(const char *)
- &timeout,sizeof(timeout));
-#else
- struct timeval tv;
- tv.tv_sec=5;
- tv.tv_usec=0;
- status=setsockopt(server_socket,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv));
-#endif
- }
if (status == -1)
{
CLOSE_SOCKET(server_socket);
continue;
}
+ SetSocketReceiveTimeout(server_socket,5.0);
status=bind(server_socket,p->ai_addr,(socklen_t) p->ai_addrlen);
if (status == -1)
{
@@ -1395,25 +1477,7 @@ MagickExport void DistributePixelCacheServer(const int port,
client_socket_ptr);
continue;
}
-#if defined(MAGICKCORE_HAVE_WINSOCK2)
- {
- DWORD
- timeout = 5000;
-
- status=setsockopt(*client_socket_ptr,SOL_SOCKET,SO_RCVTIMEO,
- (const char *) &timeout,sizeof(timeout));
- }
-#else
- {
- struct timeval
- tv;
-
- tv.tv_sec=5;
- tv.tv_usec=0;
- status=setsockopt(*client_socket_ptr,SOL_SOCKET,SO_RCVTIMEO,&tv,
- sizeof(tv));
- }
-#endif
+ SetSocketReceiveTimeout(*client_socket_ptr,5.0);
if (status == -1)
{
CLOSE_SOCKET(*client_socket_ptr);
@@ -1648,7 +1712,7 @@ MagickPrivate MagickBooleanType OpenDistributePixelCache(
if (count != (MagickOffsetType) (p-message))
return(MagickFalse);
status=MagickFalse;
- count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status);
+ count=dpc_receive(server_info->file,sizeof(status),(unsigned char *) &status);
if (count != (MagickOffsetType) sizeof(status))
return(MagickFalse);
return(status);
@@ -1724,7 +1788,7 @@ MagickPrivate MagickOffsetType ReadDistributePixelCacheMetacontent(
count=dpc_send(server_info->file,(MagickSizeType) (p-message),message);
if (count != (MagickOffsetType) (p-message))
return(-1);
- return(dpc_read(server_info->file,length,metacontent));
+ return(dpc_receive(server_info->file,length,metacontent));
}
/*
@@ -1797,7 +1861,7 @@ MagickPrivate MagickOffsetType ReadDistributePixelCachePixels(
count=dpc_send(server_info->file,(MagickSizeType) (p-message),message);
if (count != (MagickOffsetType) (p-message))
return(-1);
- return(dpc_read(server_info->file,length,pixels));
+ return(dpc_receive(server_info->file,length,pixels));
}
/*
@@ -1850,7 +1914,7 @@ MagickPrivate MagickBooleanType RelinquishDistributePixelCache(
if (count != (MagickOffsetType) (p-message))
return(MagickFalse);
status=MagickFalse;
- count=dpc_read(server_info->file,sizeof(status),(unsigned char *) &status);
+ count=dpc_receive(server_info->file,sizeof(status),(unsigned char *) &status);
if (count != (MagickOffsetType) sizeof(status))
return(MagickFalse);
return(status);