]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
select: use timediff_t instead of time_t and int for timeout_ms
authorMarc Hoersken <info@marc-hoersken.de>
Tue, 5 May 2020 19:39:39 +0000 (21:39 +0200)
committerMarc Hoersken <info@marc-hoersken.de>
Sat, 30 May 2020 08:20:40 +0000 (10:20 +0200)
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
lib/select.h

index 8e4c61bbdbea09e19d091595923f0048309fd3b7..18ccbbd861f338c7f0b9c697987c156bc593d47c 100644 (file)
@@ -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
index 9b3e0783f354b0ed25d4148dc6b7f3a7ab319b70..95181f467e024ee6b03c1cede0f12be8b673fd39 100644 (file)
@@ -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,