mirror of
https://github.com/python/cpython.git
synced 2025-09-30 20:31:52 +00:00
[3.6] bpo-31293: Fix crashes in truediv and mul of a timedelta by a float with a bad as_integer_ratio() method. (GH-3227) (#3654)
(cherry picked from commit 865e4b4f63
)
This commit is contained in:
parent
99a51d4e5b
commit
f37dd11f0d
3 changed files with 55 additions and 4 deletions
|
@ -846,6 +846,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.
|
|
@ -1646,6 +1646,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)
|
||||||
{
|
{
|
||||||
|
@ -1656,9 +1683,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;
|
||||||
|
@ -1754,9 +1782,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…
Add table
Add a link
Reference in a new issue