diff options
author | Marc Hoersken <info@marc-hoersken.de> | 2020-05-27 17:24:21 +0200 |
---|---|---|
committer | Marc Hoersken <info@marc-hoersken.de> | 2020-05-30 10:21:23 +0200 |
commit | fc55c723c4ecebabf12c32caddd0f9bc9d169ed4 (patch) | |
tree | 59ff19e138f87698427861ca41bfe02b010dd3f5 /lib | |
parent | 4a8f459837e2b7dc146825fc9a864045f7d1ae4a (diff) | |
download | curl-fc55c723c4ecebabf12c32caddd0f9bc9d169ed4.tar.gz |
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
Diffstat (limited to 'lib')
-rw-r--r-- | lib/select.c | 63 |
1 files changed, 59 insertions, 4 deletions
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; |