diff options
Diffstat (limited to 'libs/libcurl/src/select.c')
-rw-r--r-- | libs/libcurl/src/select.c | 136 |
1 files changed, 85 insertions, 51 deletions
diff --git a/libs/libcurl/src/select.c b/libs/libcurl/src/select.c index d91b20a4bc..abb124ae8f 100644 --- a/libs/libcurl/src/select.c +++ b/libs/libcurl/src/select.c @@ -22,6 +22,8 @@ #include "curl_setup.h" +#include <limits.h> + #ifdef HAVE_SYS_SELECT_H #include <sys/select.h> #elif defined(HAVE_UNISTD_H) @@ -50,11 +52,9 @@ #include "urldata.h" #include "connect.h" #include "select.h" +#include "timeval.h" #include "warnless.h" -/* Convenience local macros */ -#define ELAPSED_MS() (int)Curl_timediff(Curl_now(), initial_tv) - /* * Internal function used for waiting a specific amount of ms * in Curl_socket_check() and Curl_poll() when no file descriptor @@ -71,7 +71,7 @@ * -1 = system call error, invalid timeout value, or interrupted * 0 = specified timeout has elapsed */ -int Curl_wait_ms(int timeout_ms) +int Curl_wait_ms(timediff_t timeout_ms) { int r = 0; @@ -83,16 +83,44 @@ int Curl_wait_ms(int timeout_ms) } #if defined(MSDOS) delay(timeout_ms); -#elif defined(USE_WINSOCK) - Sleep(timeout_ms); +#elif defined(WIN32) + /* prevent overflow, timeout_ms is typecast to ULONG/DWORD. */ +#if TIMEDIFF_T_MAX >= ULONG_MAX + if(timeout_ms >= ULONG_MAX) + timeout_ms = ULONG_MAX-1; + /* don't use ULONG_MAX, because that is equal to INFINITE */ +#endif + Sleep((ULONG)timeout_ms); #else #if defined(HAVE_POLL_FINE) - r = poll(NULL, 0, timeout_ms); + /* prevent overflow, timeout_ms is typecast to int. */ +#if TIMEDIFF_T_MAX > INT_MAX + if(timeout_ms > INT_MAX) + timeout_ms = INT_MAX; +#endif + r = poll(NULL, 0, (int)timeout_ms); #else { struct timeval pending_tv; - pending_tv.tv_sec = timeout_ms / 1000; - pending_tv.tv_usec = (timeout_ms % 1000) * 1000; + timediff_t tv_sec = timeout_ms / 1000; + timediff_t tv_usec = (timeout_ms % 1000) * 1000; /* max=999999 */ +#ifdef HAVE_SUSECONDS_T +#if TIMEDIFF_T_MAX > TIME_T_MAX + /* tv_sec overflow check in case time_t is signed */ + if(tv_sec > TIME_T_MAX) + tv_sec = TIME_T_MAX; +#endif + pending_tv.tv_sec = (time_t)tv_sec; + pending_tv.tv_usec = (suseconds_t)tv_usec; +#else +#if TIMEDIFF_T_MAX > INT_MAX + /* tv_sec overflow check in case time_t is signed */ + if(tv_sec > INT_MAX) + tv_sec = INT_MAX; +#endif + pending_tv.tv_sec = (int)tv_sec; + pending_tv.tv_usec = (int)tv_usec; +#endif r = select(0, NULL, NULL, NULL, &pending_tv); } #endif /* HAVE_POLL_FINE */ @@ -113,44 +141,60 @@ int Curl_wait_ms(int timeout_ms) * 0 = timeout * N = number of signalled file descriptors */ -int Curl_select(curl_socket_t maxfd, - fd_set *fds_read, - fd_set *fds_write, - fd_set *fds_err, - time_t timeout_ms) /* milliseconds to wait */ +int Curl_select(curl_socket_t maxfd, /* highest socket number */ + fd_set *fds_read, /* sockets ready for reading */ + fd_set *fds_write, /* sockets ready for writing */ + fd_set *fds_err, /* sockets with errors */ + timediff_t timeout_ms) /* milliseconds to wait */ { struct timeval pending_tv; struct timeval *ptimeout; - int pending_ms; int r; -#if SIZEOF_TIME_T != SIZEOF_INT - /* wrap-around precaution */ - if(timeout_ms >= INT_MAX) - timeout_ms = INT_MAX; -#endif - #ifdef USE_WINSOCK /* WinSock select() can't handle zero events. See the comment below. */ if((!fds_read || fds_read->fd_count == 0) && (!fds_write || fds_write->fd_count == 0) && (!fds_err || fds_err->fd_count == 0)) { - r = Curl_wait_ms((int)timeout_ms); + r = Curl_wait_ms(timeout_ms); return r; } #endif ptimeout = &pending_tv; - if(timeout_ms < 0) { ptimeout = NULL; } else if(timeout_ms > 0) { - pending_ms = (int)timeout_ms; - pending_tv.tv_sec = pending_ms / 1000; - pending_tv.tv_usec = (pending_ms % 1000) * 1000; + timediff_t tv_sec = timeout_ms / 1000; + timediff_t tv_usec = (timeout_ms % 1000) * 1000; /* max=999999 */ +#ifdef HAVE_SUSECONDS_T +#if TIMEDIFF_T_MAX > TIME_T_MAX + /* tv_sec overflow check in case time_t is signed */ + if(tv_sec > TIME_T_MAX) + tv_sec = TIME_T_MAX; +#endif + pending_tv.tv_sec = (time_t)tv_sec; + pending_tv.tv_usec = (suseconds_t)tv_usec; +#elif defined(WIN32) /* maybe also others in the future */ +#if TIMEDIFF_T_MAX > LONG_MAX + /* tv_sec overflow check on Windows there we know it is long */ + if(tv_sec > LONG_MAX) + tv_sec = LONG_MAX; +#endif + pending_tv.tv_sec = (long)tv_sec; + pending_tv.tv_usec = (long)tv_usec; +#else +#if TIMEDIFF_T_MAX > INT_MAX + /* tv_sec overflow check in case time_t is signed */ + if(tv_sec > INT_MAX) + tv_sec = INT_MAX; +#endif + pending_tv.tv_sec = (int)tv_sec; + pending_tv.tv_usec = (int)tv_usec; +#endif } - else if(!timeout_ms) { + else { pending_tv.tv_sec = 0; pending_tv.tv_usec = 0; } @@ -201,11 +245,10 @@ int Curl_select(curl_socket_t maxfd, int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ curl_socket_t readfd1, curl_socket_t writefd, /* socket to write to */ - timediff_t timeout_ms) /* milliseconds to wait */ + timediff_t timeout_ms) /* milliseconds to wait */ { #ifdef HAVE_POLL_FINE struct pollfd pfd[3]; - int pending_ms; int num; #else fd_set fds_read; @@ -216,16 +259,10 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ int r; int ret; -#if SIZEOF_TIME_T != SIZEOF_INT - /* wrap-around precaution */ - if(timeout_ms >= INT_MAX) - timeout_ms = INT_MAX; -#endif - if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) && (writefd == CURL_SOCKET_BAD)) { /* no sockets, just wait */ - r = Curl_wait_ms((int)timeout_ms); + r = Curl_wait_ms(timeout_ms); return r; } @@ -256,18 +293,9 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ num++; } - if(timeout_ms > 0) - pending_ms = (int)timeout_ms; - else if(timeout_ms < 0) - pending_ms = -1; - else - pending_ms = 0; - r = poll(pfd, num, pending_ms); - - if(r < 0) - return -1; - if(r == 0) - return 0; + r = Curl_poll(pfd, num, timeout_ms); + if(r <= 0) + return r; ret = 0; num = 0; @@ -333,7 +361,7 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ curl_socket_t is unsigned in such cases and thus -1 is the largest value). */ - r = Curl_select(maxfd, &fds_read, &fds_write, &fds_err, (time_t)timeout_ms); + r = Curl_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms); if(r < 0) return -1; @@ -379,7 +407,7 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ * 0 = timeout * N = number of structures with non zero revent fields */ -int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) +int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms) { #ifdef HAVE_POLL_FINE int pending_ms; @@ -402,6 +430,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) } } if(fds_none) { + /* no sockets, just wait */ r = Curl_wait_ms(timeout_ms); return r; } @@ -413,8 +442,13 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) #ifdef HAVE_POLL_FINE + /* prevent overflow, timeout_ms is typecast to int. */ +#if TIMEDIFF_T_MAX > INT_MAX + if(timeout_ms > INT_MAX) + timeout_ms = INT_MAX; +#endif if(timeout_ms > 0) - pending_ms = timeout_ms; + pending_ms = (int)timeout_ms; else if(timeout_ms < 0) pending_ms = -1; else |