From f5fea3b8b85462bf2a42a6e2d2aa609b643ce7bc Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Wed, 18 Sep 2024 11:39:11 +0300 Subject: [PATCH] gh-119771: Set errno on overflows in _Py_c_pow() (#120256) Before we did this in complex_pow() and behavior of the public C API function _Py_c_pow() was different from the pure-python pow(). --- Doc/c-api/complex.rst | 2 ++ Lib/test/test_capi/test_complex.py | 6 +++++- .../C API/2024-06-08-08-33-40.gh-issue-119771.Oip2dL.rst | 2 ++ Objects/complexobject.c | 4 +++- 4 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2024-06-08-08-33-40.gh-issue-119771.Oip2dL.rst diff --git a/Doc/c-api/complex.rst b/Doc/c-api/complex.rst index 67d0c5f144e0753..16bd79475dc1e66 100644 --- a/Doc/c-api/complex.rst +++ b/Doc/c-api/complex.rst @@ -79,6 +79,8 @@ pointers. This is consistent throughout the API. If *num* is null and *exp* is not a positive real number, this method returns zero and sets :c:data:`errno` to :c:macro:`!EDOM`. + Set :c:data:`errno` to :c:macro:`!ERANGE` on overflows. + Complex Numbers as Python Objects ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Lib/test/test_capi/test_complex.py b/Lib/test/test_capi/test_complex.py index 328ea12f97462c1..368edfbf2ce97ee 100644 --- a/Lib/test/test_capi/test_complex.py +++ b/Lib/test/test_capi/test_complex.py @@ -226,7 +226,11 @@ def test_py_c_pow(self): self.assertEqual(_py_c_pow(0j, -1)[1], errno.EDOM) self.assertEqual(_py_c_pow(0j, 1j)[1], errno.EDOM) - self.assertEqual(_py_c_pow(*[DBL_MAX+1j]*2)[0], complex(*[INF]*2)) + max_num = DBL_MAX+1j + self.assertEqual(_py_c_pow(max_num, max_num), + (complex(INF, INF), errno.ERANGE)) + self.assertEqual(_py_c_pow(max_num, 2), + (complex(INF, INF), errno.ERANGE)) def test_py_c_abs(self): diff --git a/Misc/NEWS.d/next/C API/2024-06-08-08-33-40.gh-issue-119771.Oip2dL.rst b/Misc/NEWS.d/next/C API/2024-06-08-08-33-40.gh-issue-119771.Oip2dL.rst new file mode 100644 index 000000000000000..61619082487c3b6 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2024-06-08-08-33-40.gh-issue-119771.Oip2dL.rst @@ -0,0 +1,2 @@ +Set :data:`errno` in :c:func:`_Py_c_pow` on overflows. Patch by Sergey B +Kirpichev. diff --git a/Objects/complexobject.c b/Objects/complexobject.c index 4a8dac6c53f5295..787235c63a6be12 100644 --- a/Objects/complexobject.c +++ b/Objects/complexobject.c @@ -173,6 +173,8 @@ _Py_c_pow(Py_complex a, Py_complex b) } r.real = len*cos(phase); r.imag = len*sin(phase); + + _Py_ADJUST_ERANGE2(r.real, r.imag); } return r; } @@ -567,12 +569,12 @@ complex_pow(PyObject *v, PyObject *w, PyObject *z) // a faster and more accurate algorithm. if (b.imag == 0.0 && b.real == floor(b.real) && fabs(b.real) <= 100.0) { p = c_powi(a, (long)b.real); + _Py_ADJUST_ERANGE2(p.real, p.imag); } else { p = _Py_c_pow(a, b); } - _Py_ADJUST_ERANGE2(p.real, p.imag); if (errno == EDOM) { PyErr_SetString(PyExc_ZeroDivisionError, "zero to a negative or complex power");