curl_multi_fdset: avoid FD_SET out of bounds
If a socket is larger than FD_SETSIZE, avoid using FD_SET() on the platforms where this is possible. Bug: http://curl.haxx.se/bug/view.cgi?id=3413274 Reported by: Tim Starling
This commit is contained in:
@@ -53,6 +53,14 @@ When doing select(), you should use \fBcurl_multi_timeout\fP to figure out how
|
|||||||
long to wait for action. Call \fIcurl_multi_perform\fP even if no activity has
|
long to wait for action. Call \fIcurl_multi_perform\fP even if no activity has
|
||||||
been seen on the fd_sets after the timeout expires as otherwise internal
|
been seen on the fd_sets after the timeout expires as otherwise internal
|
||||||
retries and timeouts may not work as you'd think and want.
|
retries and timeouts may not work as you'd think and want.
|
||||||
|
|
||||||
|
If one of the sockets used by libcurl happens to be larger than what can be
|
||||||
|
set in an fd_set, which on POSIX systems means that the file descriptor is
|
||||||
|
larger than FD_SETSIZE, then libcurl will try to not set it. Setting a too
|
||||||
|
large file descriptor in an fd_set implies an out of bounds write which can
|
||||||
|
cause crashes, or worse. The effect of NOT storing it will possibly save you
|
||||||
|
from the crash, but will make your program NOT wait for sockets it should wait
|
||||||
|
for...
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
CURLMcode type, general libcurl multi interface error code. See
|
CURLMcode type, general libcurl multi interface error code. See
|
||||||
\fIlibcurl-errors(3)\fP
|
\fIlibcurl-errors(3)\fP
|
||||||
|
@@ -42,6 +42,7 @@
|
|||||||
#include "timeval.h"
|
#include "timeval.h"
|
||||||
#include "http.h"
|
#include "http.h"
|
||||||
#include "warnless.h"
|
#include "warnless.h"
|
||||||
|
#include "select.h"
|
||||||
|
|
||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
@@ -907,11 +908,11 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle,
|
|||||||
for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
|
for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
|
||||||
curl_socket_t s = CURL_SOCKET_BAD;
|
curl_socket_t s = CURL_SOCKET_BAD;
|
||||||
|
|
||||||
if(bitmap & GETSOCK_READSOCK(i)) {
|
if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
|
||||||
FD_SET(sockbunch[i], read_fd_set);
|
FD_SET(sockbunch[i], read_fd_set);
|
||||||
s = sockbunch[i];
|
s = sockbunch[i];
|
||||||
}
|
}
|
||||||
if(bitmap & GETSOCK_WRITESOCK(i)) {
|
if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
|
||||||
FD_SET(sockbunch[i], write_fd_set);
|
FD_SET(sockbunch[i], write_fd_set);
|
||||||
s = sockbunch[i];
|
s = sockbunch[i];
|
||||||
}
|
}
|
||||||
|
14
lib/select.c
14
lib/select.c
@@ -46,20 +46,6 @@
|
|||||||
#include "select.h"
|
#include "select.h"
|
||||||
#include "warnless.h"
|
#include "warnless.h"
|
||||||
|
|
||||||
/* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1] */
|
|
||||||
|
|
||||||
#if defined(USE_WINSOCK) || defined(TPF)
|
|
||||||
#define VERIFY_SOCK(x) Curl_nop_stmt
|
|
||||||
#else
|
|
||||||
#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
|
|
||||||
#define VERIFY_SOCK(x) do { \
|
|
||||||
if(!VALID_SOCK(x)) { \
|
|
||||||
SET_SOCKERRNO(EINVAL); \
|
|
||||||
return -1; \
|
|
||||||
} \
|
|
||||||
} WHILE_FALSE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Convenience local macros */
|
/* Convenience local macros */
|
||||||
|
|
||||||
#define elapsed_ms (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
|
#define elapsed_ms (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
|
||||||
|
16
lib/select.h
16
lib/select.h
@@ -96,4 +96,20 @@ int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
|
|||||||
fd_set* excepts, struct timeval* tv);
|
fd_set* excepts, struct timeval* tv);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1], which
|
||||||
|
unfortunately makes it impossible for us to easily check if they're valid
|
||||||
|
*/
|
||||||
|
#if defined(USE_WINSOCK) || defined(TPF)
|
||||||
|
#define VALID_SOCK(x) 1
|
||||||
|
#define VERIFY_SOCK(x) Curl_nop_stmt
|
||||||
|
#else
|
||||||
|
#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
|
||||||
|
#define VERIFY_SOCK(x) do { \
|
||||||
|
if(!VALID_SOCK(x)) { \
|
||||||
|
SET_SOCKERRNO(EINVAL); \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
} WHILE_FALSE
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __SELECT_H */
|
#endif /* __SELECT_H */
|
||||||
|
Reference in New Issue
Block a user