diff options
-rw-r--r-- | Lib/test/test_math.py | 16 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2020-03-06-06-12-37.bpo-39871.dCAj_2.rst | 3 | ||||
-rw-r--r-- | Modules/mathmodule.c | 6 |
3 files changed, 24 insertions, 1 deletions
diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index cc39402..4b848a5 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -1992,6 +1992,22 @@ class MathTests(unittest.TestCase): with self.subTest(x=x): self.assertEqual(math.ulp(-x), math.ulp(x)) + def test_issue39871(self): + # A SystemError should not be raised if the first arg to atan2(), + # copysign(), or remainder() cannot be converted to a float. + class F: + def __float__(self): + self.converted = True + 1/0 + for func in math.atan2, math.copysign, math.remainder: + y = F() + with self.assertRaises(TypeError): + func("not a number", y) + + # There should not have been any attempt to convert the second + # argument to a float. + self.assertFalse(getattr(y, "converted", False)) + # Custom assertions. def assertIsNaN(self, value): diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-03-06-06-12-37.bpo-39871.dCAj_2.rst b/Misc/NEWS.d/next/Core and Builtins/2020-03-06-06-12-37.bpo-39871.dCAj_2.rst new file mode 100644 index 0000000..0b4c2e5 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-03-06-06-12-37.bpo-39871.dCAj_2.rst @@ -0,0 +1,3 @@ +Fix a possible :exc:`SystemError` in ``math.{atan2,copysign,remainder}()`` +when the first argument cannot be converted to a :class:`float`. Patch by +Zachary Spytz. diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 77e325c..2a73a98 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -1106,9 +1106,13 @@ math_2(PyObject *const *args, Py_ssize_t nargs, if (!_PyArg_CheckPositional(funcname, nargs, 2, 2)) return NULL; x = PyFloat_AsDouble(args[0]); + if (x == -1.0 && PyErr_Occurred()) { + return NULL; + } y = PyFloat_AsDouble(args[1]); - if ((x == -1.0 || y == -1.0) && PyErr_Occurred()) + if (y == -1.0 && PyErr_Occurred()) { return NULL; + } errno = 0; r = (*func)(x, y); if (Py_IS_NAN(r)) { |