bpo-31293: Fix crashes in truediv and mul of a timedelta by a float with a bad as_integer_ratio() method. (#3227)
This commit is contained in:
parent
9974e1bcf3
commit
865e4b4f63
|
@ -866,6 +866,26 @@ class TestTimeDelta(HarmlessMixedComparison, unittest.TestCase):
|
|||
|
||||
self.assertRaises(TypeError, divmod, t, 10)
|
||||
|
||||
def test_issue31293(self):
|
||||
# The interpreter shouldn't crash in case a timedelta is divided or
|
||||
# multiplied by a float with a bad as_integer_ratio() method.
|
||||
def get_bad_float(bad_ratio):
|
||||
class BadFloat(float):
|
||||
def as_integer_ratio(self):
|
||||
return bad_ratio
|
||||
return BadFloat()
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
timedelta() / get_bad_float(1 << 1000)
|
||||
with self.assertRaises(TypeError):
|
||||
timedelta() * get_bad_float(1 << 1000)
|
||||
|
||||
for bad_ratio in [(), (42, ), (1, 2, 3)]:
|
||||
with self.assertRaises(ValueError):
|
||||
timedelta() / get_bad_float(bad_ratio)
|
||||
with self.assertRaises(ValueError):
|
||||
timedelta() * get_bad_float(bad_ratio)
|
||||
|
||||
|
||||
#############################################################################
|
||||
# date tests
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Fix crashes in true division and multiplication of a timedelta object by a
|
||||
float with a bad as_integer_ratio() method. Patch by Oren Milman.
|
|
@ -1650,6 +1650,33 @@ multiply_int_timedelta(PyObject *intobj, PyDateTime_Delta *delta)
|
|||
return result;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
get_float_as_integer_ratio(PyObject *floatobj)
|
||||
{
|
||||
PyObject *ratio;
|
||||
|
||||
assert(floatobj && PyFloat_Check(floatobj));
|
||||
ratio = _PyObject_CallMethodId(floatobj, &PyId_as_integer_ratio, NULL);
|
||||
if (ratio == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (!PyTuple_Check(ratio)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"unexpected return type from as_integer_ratio(): "
|
||||
"expected tuple, got '%.200s'",
|
||||
Py_TYPE(ratio)->tp_name);
|
||||
Py_DECREF(ratio);
|
||||
return NULL;
|
||||
}
|
||||
if (PyTuple_Size(ratio) != 2) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"as_integer_ratio() must return a 2-tuple");
|
||||
Py_DECREF(ratio);
|
||||
return NULL;
|
||||
}
|
||||
return ratio;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
multiply_float_timedelta(PyObject *floatobj, PyDateTime_Delta *delta)
|
||||
{
|
||||
|
@ -1660,9 +1687,10 @@ multiply_float_timedelta(PyObject *floatobj, PyDateTime_Delta *delta)
|
|||
pyus_in = delta_to_microseconds(delta);
|
||||
if (pyus_in == NULL)
|
||||
return NULL;
|
||||
ratio = _PyObject_CallMethodId(floatobj, &PyId_as_integer_ratio, NULL);
|
||||
if (ratio == NULL)
|
||||
ratio = get_float_as_integer_ratio(floatobj);
|
||||
if (ratio == NULL) {
|
||||
goto error;
|
||||
}
|
||||
temp = PyNumber_Multiply(pyus_in, PyTuple_GET_ITEM(ratio, 0));
|
||||
Py_DECREF(pyus_in);
|
||||
pyus_in = NULL;
|
||||
|
@ -1758,9 +1786,10 @@ truedivide_timedelta_float(PyDateTime_Delta *delta, PyObject *f)
|
|||
pyus_in = delta_to_microseconds(delta);
|
||||
if (pyus_in == NULL)
|
||||
return NULL;
|
||||
ratio = _PyObject_CallMethodId(f, &PyId_as_integer_ratio, NULL);
|
||||
if (ratio == NULL)
|
||||
ratio = get_float_as_integer_ratio(f);
|
||||
if (ratio == NULL) {
|
||||
goto error;
|
||||
}
|
||||
temp = PyNumber_Multiply(pyus_in, PyTuple_GET_ITEM(ratio, 1));
|
||||
Py_DECREF(pyus_in);
|
||||
pyus_in = NULL;
|
||||
|
|
Loading…
Reference in New Issue