]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
select: add overflow checks for timeval conversions
authorMarc Hoersken <info@marc-hoersken.de>
Wed, 27 May 2020 15:24:21 +0000 (17:24 +0200)
committerMarc Hoersken <info@marc-hoersken.de>
Sat, 30 May 2020 08:21:23 +0000 (10:21 +0200)
Using time_t and suseconds_t if suseconds_t is available,
long on Windows (maybe others in the future) and int elsewhere.

Also handle case of ULONG_MAX being greater or equal to INFINITE.

Assisted-by: Jay Satiro
Reviewed-by: Daniel Stenberg
Part of #5343

configure.ac
lib/select.c

index 8161eee947c4ca8ae33ef4b8aad472d3bcc800c6..949ce12c0ec0a1c7fbe0f3fcd6e93d0dd87d84b8 100755 (executable)
@@ -4064,6 +4064,19 @@ AC_CHECK_TYPE(sa_family_t,
 #endif
 ])
 
+# check for suseconds_t
+AC_CHECK_TYPE([suseconds_t],[
+  AC_DEFINE(HAVE_SUSECONDS_T, 1,
+    [Define to 1 if suseconds_t is an available type.])
+], ,[
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+])
+
 AC_MSG_CHECKING([if time_t is unsigned])
 CURL_RUN_IFELSE(
   [
index 18ccbbd861f338c7f0b9c697987c156bc593d47c..08468216f8593637f05c115581c9cdfe037aa1e8 100644 (file)
@@ -90,7 +90,12 @@ int Curl_wait_ms(timediff_t timeout_ms)
   /* prevent overflow, timeout_ms is typecast to ULONG/DWORD. */
 #if TIMEDIFF_T_MAX > ULONG_MAX
   if(timeout_ms > ULONG_MAX)
+#if ULONG_MAX < INFINITE
     timeout_ms = ULONG_MAX;
+#else
+    timeout_ms = ULONG_MAX-1;
+    /* avoid waiting forever */
+#endif
 #endif
   Sleep((ULONG)timeout_ms);
 #else
@@ -104,8 +109,33 @@ int Curl_wait_ms(timediff_t 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;
+#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
     r = select(0, NULL, NULL, NULL, &pending_tv);
   }
 #endif /* HAVE_POLL_FINE */
@@ -151,8 +181,33 @@ int Curl_select(curl_socket_t maxfd,   /* highest socket number */
     ptimeout = NULL;
   }
   else if(timeout_ms > 0) {
-    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;
+#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 {
     pending_tv.tv_sec = 0;