From 25b23a09171e649d0c735509a43bc436c35109d9 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 7 Sep 2004 23:01:34 +0000 Subject: [PATCH] Avoid integer overflows in NTDLL_get_server_timeout (spotted by Mike McCormack). --- dlls/ntdll/time.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/dlls/ntdll/time.c b/dlls/ntdll/time.c index e9b38b820b3..3f2f3d98d20 100644 --- a/dlls/ntdll/time.c +++ b/dlls/ntdll/time.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #ifdef HAVE_SYS_TIME_H # include @@ -296,6 +297,8 @@ static const struct tagTZ_INFO TZ_INFO[] = /* 1601 to 1980 is 379 years plus 91 leap days */ #define SECS_1601_TO_1980 ((379 * 365 + 91) * (ULONGLONG)SECSPERDAY) #define TICKS_1601_TO_1980 (SECS_1601_TO_1980 * TICKSPERSEC) +/* max ticks that can be represented as Unix time */ +#define TICKS_1601_TO_UNIX_MAX ((SECS_1601_TO_1970 + INT_MAX) * TICKSPERSEC) static const int MonthLengths[2][MONSPERYEAR] = @@ -337,20 +340,35 @@ void NTDLL_get_server_timeout( abs_time_t *when, const LARGE_INTEGER *timeout ) else if (timeout->QuadPart <= 0) /* relative timeout */ { struct timeval tv; - ULONG sec = RtlEnlargedUnsignedDivide( -timeout->QuadPart, TICKSPERSEC, &remainder ); - gettimeofday( &tv, 0 ); - when->sec = tv.tv_sec + sec; - if ((when->usec = tv.tv_usec + (remainder / 10)) >= 1000000) + + if (-timeout->QuadPart > (LONGLONG)INT_MAX * TICKSPERSEC) + when->sec = when->usec = INT_MAX; + else { - when->usec -= 1000000; - when->sec++; + ULONG sec = RtlEnlargedUnsignedDivide( -timeout->QuadPart, TICKSPERSEC, &remainder ); + gettimeofday( &tv, 0 ); + when->sec = tv.tv_sec + sec; + if ((when->usec = tv.tv_usec + (remainder / 10)) >= 1000000) + { + when->usec -= 1000000; + when->sec++; + } + if (when->sec < tv.tv_sec) /* overflow */ + when->sec = when->usec = INT_MAX; } } else /* absolute time */ { - when->sec = RtlEnlargedUnsignedDivide( timeout->QuadPart - TICKS_1601_TO_1970, - TICKSPERSEC, &remainder ); - when->usec = remainder / 10; + if (timeout->QuadPart < TICKS_1601_TO_1970) + when->sec = when->usec = 0; + else if (timeout->QuadPart > TICKS_1601_TO_UNIX_MAX) + when->sec = when->usec = INT_MAX; + else + { + when->sec = RtlEnlargedUnsignedDivide( timeout->QuadPart - TICKS_1601_TO_1970, + TICKSPERSEC, &remainder ); + when->usec = remainder / 10; + } } } -- 2.11.4.GIT