diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py index c931be6df5fdaa..ba9c25c835bc39 100755 --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -1607,10 +1607,19 @@ class HalfFloatTest(FPTest, unittest.TestCase): typecode = 'e' minitemsize = 2 + def test_overflows(self): + # Overflows half-float type: + self.assertRaises(OverflowError, array.array, self.typecode, [123456]) + # Overflows also float type: + self.assertRaises(OverflowError, array.array, self.typecode, [1e300]) + class FloatTest(FPTest, unittest.TestCase): typecode = 'f' minitemsize = 4 + def test_overflows(self): + self.assertRaises(OverflowError, array.array, self.typecode, [1e300]) + class DoubleTest(FPTest, unittest.TestCase): typecode = 'd' minitemsize = 8 @@ -1637,6 +1646,10 @@ class ComplexFloatTest(CFPTest, unittest.TestCase): typecode = 'Zf' minitemsize = 8 + def test_overflows(self): + self.assertRaises(OverflowError, array.array, self.typecode, [1e300]) + self.assertRaises(OverflowError, array.array, self.typecode, [1e300j]) + class ComplexDoubleTest(CFPTest, unittest.TestCase): typecode = 'Zd' minitemsize = 16 diff --git a/Misc/NEWS.d/next/Library/2026-09-03-04-51-46.gh-issue-156864.Pbe7Tl.rst b/Misc/NEWS.d/next/Library/2026-09-03-04-51-46.gh-issue-156864.Pbe7Tl.rst new file mode 100644 index 00000000000000..ee89b830d3d486 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-09-03-04-51-46.gh-issue-156864.Pbe7Tl.rst @@ -0,0 +1,2 @@ +:func:`array.array` setter now correctly detects overflows for the ``'e'``, +``'f'`` and ``'Zf'`` type codes. Patch by Sergey B Kirpichev. diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index a0181c083a6036..ef492d143d5644 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -584,8 +584,8 @@ e_getitem(arrayobject *ap, Py_ssize_t i) static int e_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) { - float x; - if (!PyArg_Parse(v, "f;array item must be float", &x)) { + double x; + if (!PyArg_Parse(v, "d;array item must be float", &x)) { return -1; } @@ -607,14 +607,16 @@ f_getitem(arrayobject *ap, Py_ssize_t i) static int f_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) { - float x; - if (!PyArg_Parse(v, "f;array item must be float", &x)) + double x; + if (!PyArg_Parse(v, "d;array item must be float", &x)) return -1; CHECK_ARRAY_BOUNDS(ap, i); - if (i >= 0) - ((float *)ap->ob_item)[i] = x; + if (i >= 0) { + return PyFloat_Pack4(x, ap->ob_item + sizeof(float)*i, + PY_LITTLE_ENDIAN); + } return 0; } @@ -651,7 +653,6 @@ static int cf_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) { Py_complex x; - float f[2]; if (!PyArg_Parse(v, "D;array item must be complex", &x)) { return -1; @@ -659,10 +660,18 @@ cf_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) CHECK_ARRAY_BOUNDS(ap, i); - f[0] = (float)x.real; - f[1] = (float)x.imag; if (i >= 0) { - memcpy(ap->ob_item + i*sizeof(f), &f, sizeof(f)); + char f[8]; + int ret = PyFloat_Pack4(x.real, f, PY_LITTLE_ENDIAN); + + if (ret) { + return ret; + } + ret = PyFloat_Pack4(x.imag, f + sizeof(float), PY_LITTLE_ENDIAN); + if (!ret) { + memcpy(ap->ob_item + i*sizeof(f), &f, sizeof(f)); + } + return ret; } return 0; }