From 4a8f459837e2b7dc146825fc9a864045f7d1ae4a Mon Sep 17 00:00:00 2001 From: Marc Hoersken Date: Tue, 5 May 2020 21:39:39 +0200 Subject: select: use timediff_t instead of time_t and int for timeout_ms Make all functions in select.[ch] take timeout_ms as timediff_t which should always be large enough and signed on all platforms to take all possible timeout values and avoid type conversions. Reviewed-by: Jay Satiro Reviewed-by: Daniel Stenberg Replaces #5107 and partially #5262 Related to #5240 and #5286 Closes #5343 --- lib/select.c | 85 +++++++++++++++++++++++++----------------------------------- lib/select.h | 6 ++--- 2 files changed, 39 insertions(+), 52 deletions(-) (limited to 'lib') diff --git a/lib/select.c b/lib/select.c index 8e4c61bbd..18ccbbd86 100644 --- a/lib/select.c +++ b/lib/select.c @@ -74,7 +74,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; @@ -87,10 +87,20 @@ int Curl_wait_ms(int timeout_ms) #if defined(MSDOS) delay(timeout_ms); #elif defined(USE_WINSOCK) - Sleep(timeout_ms); + /* prevent overflow, timeout_ms is typecast to ULONG/DWORD. */ +#if TIMEDIFF_T_MAX > ULONG_MAX + if(timeout_ms > ULONG_MAX) + timeout_ms = ULONG_MAX; +#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; @@ -116,44 +126,35 @@ 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; + pending_tv.tv_sec = timeout_ms / 1000; + pending_tv.tv_usec = (timeout_ms % 1000) * 1000; } - else if(!timeout_ms) { + else { pending_tv.tv_sec = 0; pending_tv.tv_usec = 0; } @@ -204,11 +205,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; @@ -219,20 +219,10 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ int r; int ret; - /* prevent overflow. timeout_ms is typecast to time_t and int. */ -#if TIMEDIFF_T_MAX > INT_MAX - if(timeout_ms > INT_MAX) - timeout_ms = INT_MAX; -#endif -#if INT_MAX > TIME_T_MAX - if(timeout_ms > (int)TIME_T_MAX) - timeout_ms = (int)TIME_T_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; } @@ -263,18 +253,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; @@ -340,7 +321,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; @@ -386,7 +367,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; @@ -409,6 +390,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; } @@ -420,8 +402,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 diff --git a/lib/select.h b/lib/select.h index 9b3e0783f..95181f467 100644 --- a/lib/select.h +++ b/lib/select.h @@ -76,7 +76,7 @@ int Curl_select(curl_socket_t maxfd, fd_set *fds_read, fd_set *fds_write, fd_set *fds_err, - time_t timeout_ms); + timediff_t timeout_ms); int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2, curl_socket_t writefd, @@ -86,8 +86,8 @@ int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2, #define SOCKET_WRITABLE(x,z) \ Curl_socket_check(CURL_SOCKET_BAD, CURL_SOCKET_BAD, x, z) -int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms); -int Curl_wait_ms(int timeout_ms); +int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms); +int Curl_wait_ms(timediff_t timeout_ms); #ifdef TPF int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes, -- cgit v1.2.3