From 05c31b164cf6cf1b79bd84419668c71300bb026a Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Fri, 11 Sep 2026 18:46:59 +0300 Subject: [PATCH] [3.15] gh-155526: Don't check errno in abs(complex) (GH-155527) abs(complex) no longer raises OverflowError if errno was set to ERANGE by some library call but abs() doesn't overflow. (cherry picked from commit e5d4fa281c573b764b827f3defae260787024e43) Co-authored-by: Sergey B Kirpichev Co-authored-by: Victor Stinner Co-authored-by: hpkfft.com --- Lib/test/test_complex.py | 25 +++++++++++++++++++ ...-08-11-06-04-26.gh-issue-155526.W7ZHXu.rst | 3 +++ Modules/cmathmodule.c | 2 +- Objects/complexobject.c | 5 +++- 4 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-08-11-06-04-26.gh-issue-155526.W7ZHXu.rst diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py index bb307191dffcc14..1916260465c1641 100644 --- a/Lib/test/test_complex.py +++ b/Lib/test/test_complex.py @@ -1,6 +1,8 @@ +import errno import unittest import sys from test import support +from test.support import import_helper from test.support.testcase import ComplexesAreIdenticalMixin from test.support.numbers import ( VALID_UNDERSCORE_LITERALS, @@ -9,6 +11,7 @@ from random import random from math import isnan, copysign +import cmath import operator INF = float("inf") @@ -789,8 +792,30 @@ def test_abs(self): for num in nums: self.assertAlmostEqual((num.real**2 + num.imag**2) ** 0.5, abs(num)) + for x in 0.0, -0.0, INF, -INF, NAN: + for y in 0.0, -0.0, INF, -INF, NAN: + with self.subTest(x=x, y=y): + z = complex(x, y) + r = abs(z) + if cmath.isfinite(z): + self.assertFloatsAreIdentical(r, 0.0) + elif cmath.isinf(z): + self.assertEqual(r, INF) + else: + self.assertTrue(cmath.isnan(z)) + self.assertTrue(isnan(r)) + self.assertRaises(OverflowError, abs, complex(DBL_MAX, DBL_MAX)) + def test_abs_errno_handling(self): + _testcapi = import_helper.import_module('_testcapi') + z = complex('nan') + _testcapi.set_errno(errno.ERANGE) + try: + self.assertTrue(isnan(abs(z))) + finally: + _testcapi.set_errno(0) + def test_repr_str(self): def test(v, expected, test_fn=self.assertEqual): test_fn(repr(v), expected) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-08-11-06-04-26.gh-issue-155526.W7ZHXu.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-08-11-06-04-26.gh-issue-155526.W7ZHXu.rst new file mode 100644 index 000000000000000..ae0c08973a8195b --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-08-11-06-04-26.gh-issue-155526.W7ZHXu.rst @@ -0,0 +1,3 @@ +Fix spurious :exc:`OverflowError` for ``abs(nanj)`` in case :c:data:`errno` was +previously set to :c:macro:`!ERANGE` by some library call. +Patch by Sergey B Kirpichev. diff --git a/Modules/cmathmodule.c b/Modules/cmathmodule.c index 7c736f4610bb988..7ebe0becb3439aa 100644 --- a/Modules/cmathmodule.c +++ b/Modules/cmathmodule.c @@ -1029,8 +1029,8 @@ cmath_polar_impl(PyObject *module, Py_complex z) { double r, phi; - errno = 0; phi = atan2(z.imag, z.real); /* should not cause any exception */ + errno = 0; r = _Py_c_abs(z); /* sets errno to ERANGE on overflow */ if (errno != 0) return math_error(); diff --git a/Objects/complexobject.c b/Objects/complexobject.c index 3612c2699a557db..b0a8bf90c2eb244 100644 --- a/Objects/complexobject.c +++ b/Objects/complexobject.c @@ -796,7 +796,10 @@ static PyObject * complex_abs(PyObject *op) { PyComplexObject *v = _PyComplexObject_CAST(op); - double result = _Py_c_abs(v->cval); + double result; + + errno = 0; + result = _Py_c_abs(v->cval); if (errno == ERANGE) { PyErr_SetString(PyExc_OverflowError, "absolute value too large");