diff -r c61d2c43d22e Lib/test/test_decimal.py --- a/Lib/test/test_decimal.py Sun May 08 14:02:35 2016 +0000 +++ b/Lib/test/test_decimal.py Sun May 08 18:24:23 2016 +0300 @@ -2548,6 +2548,19 @@ class PythonAPItests(unittest.TestCase): x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0) self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip + # Issue #26974: Crash when as_integer_ratio() returns insane value. + class BadFloat(float): + def as_integer_ratio(self): + return ratio + def __abs__(self): + return self + ratio = 1 + self.assertRaises(TypeError, Decimal.from_float, BadFloat(1.2)) + ratio = 1, + self.assertRaises(ValueError, Decimal.from_float, BadFloat(1.2)) + ratio = 1, 2, 3 + self.assertRaises(ValueError, Decimal.from_float, BadFloat(1.2)) + def test_create_decimal_from_float(self): Decimal = self.decimal.Decimal Context = self.decimal.Context diff -r c61d2c43d22e Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c Sun May 08 14:02:35 2016 +0000 +++ b/Modules/_decimal/_decimal.c Sun May 08 18:24:23 2016 +0300 @@ -2268,6 +2268,18 @@ PyDecType_FromFloatExact(PyTypeObject *t if (n_d == NULL) { return NULL; } + if (!PyTuple_Check(n_d)) { + Py_DECREF(n_d); + PyErr_SetString(PyExc_TypeError, + "as_integer_ratio() returned wrong type"); + return NULL; + } + if (PyTuple_GET_SIZE(n_d) != 2) { + Py_DECREF(n_d); + PyErr_SetString(PyExc_ValueError, + "as_integer_ratio() returned a tuple with wrong size"); + return NULL; + } n = PyTuple_GET_ITEM(n_d, 0); d = PyTuple_GET_ITEM(n_d, 1);