From 5208b4b37953a406db0ed6a9db545c2948dde989 Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Sat, 14 Mar 2020 04:45:32 -0600 Subject: [PATCH] bpo-39871: Fix possible SystemError in atan2, copysign and remainder (GH-18806) In math_2(), the first PyFloat_AsDouble() call should be checked for failure before the second call. Co-authored-by: Mark Dickinson --- Lib/test/test_math.py | 16 ++++++++++++++++ .../2020-03-06-06-12-37.bpo-39871.dCAj_2.rst | 3 +++ Modules/mathmodule.c | 8 ++++++-- 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2020-03-06-06-12-37.bpo-39871.dCAj_2.rst diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index cc39402b3c6..4b848a5e7e5 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 00000000000..0b4c2e5f4cc --- /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 77e325cf0c6..2a73a983f56 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]); - y = PyFloat_AsDouble(args[1]); - if ((x == -1.0 || y == -1.0) && PyErr_Occurred()) + if (x == -1.0 && PyErr_Occurred()) { return NULL; + } + y = PyFloat_AsDouble(args[1]); + if (y == -1.0 && PyErr_Occurred()) { + return NULL; + } errno = 0; r = (*func)(x, y); if (Py_IS_NAN(r)) {