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
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)
{
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;
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;