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)
|
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
|
# 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;
|
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 *
|
static PyObject *
|
||||||
multiply_float_timedelta(PyObject *floatobj, PyDateTime_Delta *delta)
|
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);
|
pyus_in = delta_to_microseconds(delta);
|
||||||
if (pyus_in == NULL)
|
if (pyus_in == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
ratio = _PyObject_CallMethodId(floatobj, &PyId_as_integer_ratio, NULL);
|
ratio = get_float_as_integer_ratio(floatobj);
|
||||||
if (ratio == NULL)
|
if (ratio == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
temp = PyNumber_Multiply(pyus_in, PyTuple_GET_ITEM(ratio, 0));
|
temp = PyNumber_Multiply(pyus_in, PyTuple_GET_ITEM(ratio, 0));
|
||||||
Py_DECREF(pyus_in);
|
Py_DECREF(pyus_in);
|
||||||
pyus_in = NULL;
|
pyus_in = NULL;
|
||||||
|
@ -1758,9 +1786,10 @@ truedivide_timedelta_float(PyDateTime_Delta *delta, PyObject *f)
|
||||||
pyus_in = delta_to_microseconds(delta);
|
pyus_in = delta_to_microseconds(delta);
|
||||||
if (pyus_in == NULL)
|
if (pyus_in == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
ratio = _PyObject_CallMethodId(f, &PyId_as_integer_ratio, NULL);
|
ratio = get_float_as_integer_ratio(f);
|
||||||
if (ratio == NULL)
|
if (ratio == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
temp = PyNumber_Multiply(pyus_in, PyTuple_GET_ITEM(ratio, 1));
|
temp = PyNumber_Multiply(pyus_in, PyTuple_GET_ITEM(ratio, 1));
|
||||||
Py_DECREF(pyus_in);
|
Py_DECREF(pyus_in);
|
||||||
pyus_in = NULL;
|
pyus_in = NULL;
|
||||||
|
|
Loading…
Reference in New Issue