Repository navigation
Overflow when casting from double to time_t, and_PyTime_t. #78604
Description
Activity
Code triggering bug:
import time time.sleep(2**63 / 10**9)
Result:
ValueError: sleep length must be non-negative
The problem is with the macro that checks the range of provided double:
Line 228 of Include/pymath.h: #define _Py_InIntegralTypeRange(type, v) (_Py_IntegralTypeMin(type) <= v && v <= _Py_IntegralTypeMax(type))
The type here is _PyTime_t, which is a typedef to int64_t.
Proposed solution is to change <= into <, since float(2**63-1) == float(2**63), and that means that none double can ever be equal to 2**63-1.
- added3.7 (EOL)end of lifeend of life3.8 (EOL)end of lifeend of lifeinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
on Aug 17, 2018 It seems like a regression introduced by:
commit a853a8b
Author: Benjamin Peterson <benjamin@python.org>
Date: Thu Sep 7 11:13:59 2017 -0700bpo-31373: fix undefined floating-point demotions (bpo-3396)I'm not sure that the pytime.c change in commit a853a8b is correct:
diff --git a/Python/pytime.c b/Python/pytime.c index 8979adc219..f3c913226c 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -276,7 +278,6 @@ static int _PyTime_FromFloatObject(_PyTime_t *t, double value, _PyTime_round_t round, long unit_to_ns) { - double err; /* volatile avoids optimization changing how numbers are rounded */ volatile double d; @@ -285,12 +286,11 @@ _PyTime_FromFloatObject(_PyTime_t *t, double value, _PyTime_round_t round, d *= (double)unit_to_ns; d = _PyTime_Round(d, round); - *t = (_PyTime_t)d; - err = d - (double)*t; - if (fabs(err) >= 1.0) { + if (!_Py_InIntegralTypeRange(_PyTime_t, d)) { _PyTime_overflow(); return -1; } + *t = (_PyTime_t)d; return 0; }
I don't think that modifying _Py_InIntegralTypeRange() macro to replace "<=" with "<" is correct, since this bug is very specific to pytime.c, when _Py_InIntegralTypeRange() is used with a double. The PR proposes:
#define _Py_InIntegralTypeRange(type, v) (_Py_IntegralTypeMin(type) <= v && v < _Py_IntegralTypeMax(type))
Although you're right - this issue is specific to pytime.c, when _Py_InIntegralTypeRange() is used with a double, it is actually true that _Py_InIntegralTypeRange() is used with double, in pytime.c only (as a quick recursive grep discovers).
Perhaps the macro should be renamed not to cause confusion (include note about floating point, or define it as a function).
I don't have good idea on how this issue could be resolved otherwise.
See also bpo-36048: "Deprecate implicit truncating when convert Python numbers to C integers: use __index__, not __int__".
Closed along with the PR.
- added3.11only security fixesonly security fixes3.10 (EOL)end of lifeend of life3.12only security fixesonly security fixesand removed3.8 (EOL)end of lifeend of life3.7 (EOL)end of lifeend of life
on Mar 4, 2023 Fixed for Python 3.10 and later by #101826 and its backports.
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields: