1313#endif
1414#endif
1515
16- #define _PyTime_check_mul_overflow (a , b ) \
17- (assert(b > 0), \
18- (_PyTime_t)(a) < _PyTime_MIN / (_PyTime_t)(b) \
19- || _PyTime_MAX / (_PyTime_t)(b) < (_PyTime_t)(a))
20-
2116/* To millisecond (10^-3) */
2217#define SEC_TO_MS 1000
2318
@@ -78,6 +73,49 @@ pytime_as_nanoseconds(_PyTime_t t)
7873}
7974
8075
76+ // Compute t + t2. Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow.
77+ static inline _PyTime_t
78+ pytime_add (_PyTime_t * t , _PyTime_t t2 )
79+ {
80+ if (t2 > 0 && * t > _PyTime_MAX - t2 ) {
81+ * t = _PyTime_MAX ;
82+ return -1 ;
83+ }
84+ else if (t2 < 0 && * t < _PyTime_MIN - t2 ) {
85+ * t = _PyTime_MIN ;
86+ return -1 ;
87+ }
88+ else {
89+ * t += t2 ;
90+ return 0 ;
91+ }
92+ }
93+
94+
95+ static inline int
96+ _PyTime_check_mul_overflow (_PyTime_t a , _PyTime_t b )
97+ {
98+ assert (b > 0 );
99+ return ((a < _PyTime_MIN / b ) || (_PyTime_MAX / b < a ));
100+ }
101+
102+
103+ // Compute t * k. Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow.
104+ static inline _PyTime_t
105+ pytime_mul (_PyTime_t * t , _PyTime_t k )
106+ {
107+ assert (k > 0 );
108+ if (_PyTime_check_mul_overflow (* t , k )) {
109+ * t = (* t >= 0 ) ? _PyTime_MAX : _PyTime_MIN ;
110+ return -1 ;
111+ }
112+ else {
113+ * t *= k ;
114+ return 0 ;
115+ }
116+ }
117+
118+
81119_PyTime_t
82120_PyTime_MulDiv (_PyTime_t ticks , _PyTime_t mul , _PyTime_t div )
83121{
@@ -371,41 +409,25 @@ _PyTime_FromNanosecondsObject(_PyTime_t *tp, PyObject *obj)
371409
372410#ifdef HAVE_CLOCK_GETTIME
373411static int
374- pytime_fromtimespec (_PyTime_t * tp , struct timespec * ts , int raise )
412+ pytime_fromtimespec (_PyTime_t * tp , struct timespec * ts , int raise_exc )
375413{
376414 _PyTime_t t , tv_nsec ;
377- int res = 0 ;
378415
379416 Py_BUILD_ASSERT (sizeof (ts -> tv_sec ) <= sizeof (_PyTime_t ));
380417 t = (_PyTime_t )ts -> tv_sec ;
381418
382- if (_PyTime_check_mul_overflow (t , SEC_TO_NS )) {
383- if (raise ) {
384- pytime_overflow ();
385- res = -1 ;
386- }
387- t = (t > 0 ) ? _PyTime_MAX : _PyTime_MIN ;
388- }
389- else {
390- t = t * SEC_TO_NS ;
391- }
419+ int res1 = pytime_mul (& t , SEC_TO_NS );
392420
393421 tv_nsec = ts -> tv_nsec ;
394- /* The following test is written for positive only tv_nsec */
395- assert (tv_nsec >= 0 );
396- if (t > _PyTime_MAX - tv_nsec ) {
397- if (raise ) {
398- pytime_overflow ();
399- res = -1 ;
400- }
401- t = _PyTime_MAX ;
402- }
403- else {
404- t += tv_nsec ;
405- }
422+ int res2 = pytime_add (& t , tv_nsec );
406423
407424 * tp = pytime_from_nanoseconds (t );
408- return res ;
425+
426+ if (raise_exc && (res1 < 0 || res2 < 0 )) {
427+ pytime_overflow ();
428+ return -1 ;
429+ }
430+ return 0 ;
409431}
410432
411433int
@@ -416,43 +438,25 @@ _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts)
416438#endif
417439
418440
419- #if !defined( MS_WINDOWS )
441+ #ifndef MS_WINDOWS
420442static int
421- pytime_fromtimeval (_PyTime_t * tp , struct timeval * tv , int raise )
443+ pytime_fromtimeval (_PyTime_t * tp , struct timeval * tv , int raise_exc )
422444{
423- _PyTime_t t , usec ;
424- int res = 0 ;
425-
426445 Py_BUILD_ASSERT (sizeof (tv -> tv_sec ) <= sizeof (_PyTime_t ));
427- t = (_PyTime_t )tv -> tv_sec ;
446+ _PyTime_t t = (_PyTime_t )tv -> tv_sec ;
428447
429- if (_PyTime_check_mul_overflow (t , SEC_TO_NS )) {
430- if (raise ) {
431- pytime_overflow ();
432- res = -1 ;
433- }
434- t = (t > 0 ) ? _PyTime_MAX : _PyTime_MIN ;
435- }
436- else {
437- t = t * SEC_TO_NS ;
438- }
448+ int res1 = pytime_mul (& t , SEC_TO_NS );
439449
440- usec = (_PyTime_t )tv -> tv_usec * US_TO_NS ;
441- /* The following test is written for positive only usec */
442- assert (usec >= 0 );
443- if (t > _PyTime_MAX - usec ) {
444- if (raise ) {
445- pytime_overflow ();
446- res = -1 ;
447- }
448- t = _PyTime_MAX ;
449- }
450- else {
451- t += usec ;
452- }
450+ _PyTime_t usec = (_PyTime_t )tv -> tv_usec * US_TO_NS ;
451+ int res2 = pytime_add (& t , usec );
453452
454453 * tp = pytime_from_nanoseconds (t );
455- return res ;
454+
455+ if (raise_exc && (res1 < 0 || res2 < 0 )) {
456+ pytime_overflow ();
457+ return -1 ;
458+ }
459+ return 0 ;
456460}
457461
458462
@@ -572,7 +576,7 @@ pytime_divide_round_up(const _PyTime_t t, const _PyTime_t k)
572576 assert (k > 1 );
573577 if (t >= 0 ) {
574578 // Don't use (t + k - 1) / k to avoid integer overflow
575- // if t= _PyTime_MAX
579+ // if t is equal to _PyTime_MAX
576580 _PyTime_t q = t / k ;
577581 if (t % k ) {
578582 q += 1 ;
@@ -581,7 +585,7 @@ pytime_divide_round_up(const _PyTime_t t, const _PyTime_t k)
581585 }
582586 else {
583587 // Don't use (t - (k - 1)) / k to avoid integer overflow
584- // if t= _PyTime_MIN
588+ // if t is equals to _PyTime_MIN.
585589 _PyTime_t q = t / k ;
586590 if (t % k ) {
587591 q -= 1 ;
@@ -804,14 +808,14 @@ _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts)
804808
805809
806810static int
807- py_get_system_clock (_PyTime_t * tp , _Py_clock_info_t * info , int raise )
811+ py_get_system_clock (_PyTime_t * tp , _Py_clock_info_t * info , int raise_exc )
808812{
813+ assert (info == NULL || raise_exc );
814+
809815#ifdef MS_WINDOWS
810816 FILETIME system_time ;
811817 ULARGE_INTEGER large ;
812818
813- assert (info == NULL || raise );
814-
815819 GetSystemTimeAsFileTime (& system_time );
816820 large .u .LowPart = system_time .dwLowDateTime ;
817821 large .u .HighPart = system_time .dwHighDateTime ;
@@ -846,8 +850,6 @@ py_get_system_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
846850 struct timeval tv ;
847851#endif
848852
849- assert (info == NULL || raise );
850-
851853#ifdef HAVE_CLOCK_GETTIME
852854
853855#ifdef HAVE_CLOCK_GETTIME_RUNTIME
@@ -856,12 +858,12 @@ py_get_system_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
856858
857859 err = clock_gettime (CLOCK_REALTIME , & ts );
858860 if (err ) {
859- if (raise ) {
861+ if (raise_exc ) {
860862 PyErr_SetFromErrno (PyExc_OSError );
861863 }
862864 return -1 ;
863865 }
864- if (pytime_fromtimespec (tp , & ts , raise ) < 0 ) {
866+ if (pytime_fromtimespec (tp , & ts , raise_exc ) < 0 ) {
865867 return -1 ;
866868 }
867869
@@ -890,12 +892,12 @@ py_get_system_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
890892 /* test gettimeofday() */
891893 err = gettimeofday (& tv , (struct timezone * )NULL );
892894 if (err ) {
893- if (raise ) {
895+ if (raise_exc ) {
894896 PyErr_SetFromErrno (PyExc_OSError );
895897 }
896898 return -1 ;
897899 }
898- if (pytime_fromtimeval (tp , & tv , raise ) < 0 ) {
900+ if (pytime_fromtimeval (tp , & tv , raise_exc ) < 0 ) {
899901 return -1 ;
900902 }
901903
@@ -987,28 +989,21 @@ py_mach_timebase_info(_PyTime_t *pnumer, _PyTime_t *pdenom, int raise)
987989
988990
989991static int
990- py_get_monotonic_clock (_PyTime_t * tp , _Py_clock_info_t * info , int raise )
992+ py_get_monotonic_clock (_PyTime_t * tp , _Py_clock_info_t * info , int raise_exc )
991993{
992- #if defined(MS_WINDOWS )
993- ULONGLONG ticks ;
994- _PyTime_t t ;
995-
996- assert (info == NULL || raise );
994+ assert (info == NULL || raise_exc );
997995
998- ticks = GetTickCount64 ();
996+ #if defined(MS_WINDOWS )
997+ ULONGLONG ticks = GetTickCount64 ();
999998 Py_BUILD_ASSERT (sizeof (ticks ) <= sizeof (_PyTime_t ));
1000- t = (_PyTime_t )ticks ;
999+ _PyTime_t t = (_PyTime_t )ticks ;
10011000
1002- if (_PyTime_check_mul_overflow (t , MS_TO_NS )) {
1003- if (raise ) {
1004- pytime_overflow ();
1005- return -1 ;
1006- }
1007- // Clamp to _PyTime_MAX silently.
1008- * tp = _PyTime_MAX ;
1009- }
1010- else {
1011- * tp = t * MS_TO_NS ;
1001+ int res = pytime_mul (& t , MS_TO_NS );
1002+ * tp = t ;
1003+
1004+ if (raise_exc && res < 0 ) {
1005+ pytime_overflow ();
1006+ return -1 ;
10121007 }
10131008
10141009 if (info ) {
@@ -1030,7 +1025,7 @@ py_get_monotonic_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
10301025 static _PyTime_t timebase_numer = 0 ;
10311026 static _PyTime_t timebase_denom = 0 ;
10321027 if (timebase_denom == 0 ) {
1033- if (py_mach_timebase_info (& timebase_numer , & timebase_denom , raise ) < 0 ) {
1028+ if (py_mach_timebase_info (& timebase_numer , & timebase_denom , raise_exc ) < 0 ) {
10341029 return -1 ;
10351030 }
10361031 }
@@ -1055,7 +1050,7 @@ py_get_monotonic_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
10551050
10561051 time = gethrtime ();
10571052 if (time == -1 ) {
1058- if (raise ) {
1053+ if (raise_exc ) {
10591054 PyErr_SetFromErrno (PyExc_OSError );
10601055 }
10611056 return -1 ;
@@ -1071,7 +1066,7 @@ py_get_monotonic_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
10711066 }
10721067
10731068#else
1074- struct timespec ts ;
1069+
10751070#ifdef CLOCK_HIGHRES
10761071 const clockid_t clk_id = CLOCK_HIGHRES ;
10771072 const char * implementation = "clock_gettime(CLOCK_HIGHRES)" ;
@@ -1080,30 +1075,30 @@ py_get_monotonic_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
10801075 const char * implementation = "clock_gettime(CLOCK_MONOTONIC)" ;
10811076#endif
10821077
1083- assert (info == NULL || raise );
1084-
1078+ struct timespec ts ;
10851079 if (clock_gettime (clk_id , & ts ) != 0 ) {
1086- if (raise ) {
1080+ if (raise_exc ) {
10871081 PyErr_SetFromErrno (PyExc_OSError );
10881082 return -1 ;
10891083 }
10901084 return -1 ;
10911085 }
10921086
1087+ if (pytime_fromtimespec (tp , & ts , raise_exc ) < 0 ) {
1088+ return -1 ;
1089+ }
1090+
10931091 if (info ) {
1094- struct timespec res ;
10951092 info -> monotonic = 1 ;
10961093 info -> implementation = implementation ;
10971094 info -> adjustable = 0 ;
1095+ struct timespec res ;
10981096 if (clock_getres (clk_id , & res ) != 0 ) {
10991097 PyErr_SetFromErrno (PyExc_OSError );
11001098 return -1 ;
11011099 }
11021100 info -> resolution = res .tv_sec + res .tv_nsec * 1e-9 ;
11031101 }
1104- if (pytime_fromtimespec (tp , & ts , raise ) < 0 ) {
1105- return -1 ;
1106- }
11071102#endif
11081103 return 0 ;
11091104}
@@ -1169,6 +1164,8 @@ py_win_perf_counter_frequency(LONGLONG *pfrequency, int raise)
11691164static int
11701165py_get_win_perf_counter (_PyTime_t * tp , _Py_clock_info_t * info , int raise )
11711166{
1167+ assert (info == NULL || raise_exc );
1168+
11721169 static LONGLONG frequency = 0 ;
11731170 if (frequency == 0 ) {
11741171 if (py_win_perf_counter_frequency (& frequency , raise ) < 0 ) {
0 commit comments