aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Hoersken <info@marc-hoersken.de>2020-05-27 17:24:21 +0200
committerMarc Hoersken <info@marc-hoersken.de>2020-05-30 10:21:23 +0200
commitfc55c723c4ecebabf12c32caddd0f9bc9d169ed4 (patch)
tree59ff19e138f87698427861ca41bfe02b010dd3f5
parent4a8f459837e2b7dc146825fc9a864045f7d1ae4a (diff)
select: add overflow checks for timeval conversions
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
-rwxr-xr-xconfigure.ac13
-rw-r--r--lib/select.c63
2 files changed, 72 insertions, 4 deletions
diff --git a/configure.ac b/configure.ac
index 8161eee94..949ce12c0 100755
--- a/configure.ac
+++ b/configure.ac
@@ -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(
[
diff --git a/lib/select.c b/lib/select.c
index 18ccbbd86..08468216f 100644
--- a/lib/select.c
+++ b/lib/select.c
@@ -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;