-
-
Notifications
You must be signed in to change notification settings - Fork 30.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Overflow when casting from double to time_t, and_PyTime_t. #78604
Comments
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. |
It seems like a regression introduced by: commit a853a8b
|
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. |
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:
The text was updated successfully, but these errors were encountered: