diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py index ba9c25c835bc39..943420f4c3f4e8 100755 --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -1612,6 +1612,13 @@ def test_overflows(self): self.assertRaises(OverflowError, array.array, self.typecode, [123456]) # Overflows also float type: self.assertRaises(OverflowError, array.array, self.typecode, [1e300]) + # A failed append, insert or extend leaves the array unchanged: + for x in 123456, 1e300: + a = array.array(self.typecode, [1]) + self.assertRaises(OverflowError, a.append, x) + self.assertRaises(OverflowError, a.insert, 0, x) + self.assertRaises(OverflowError, a.extend, [x]) + self.assertEqual(a, array.array(self.typecode, [1])) class FloatTest(FPTest, unittest.TestCase): typecode = 'f' @@ -1619,6 +1626,12 @@ class FloatTest(FPTest, unittest.TestCase): def test_overflows(self): self.assertRaises(OverflowError, array.array, self.typecode, [1e300]) + # A failed append, insert or extend leaves the array unchanged: + a = array.array(self.typecode, [1]) + self.assertRaises(OverflowError, a.append, 1e300) + self.assertRaises(OverflowError, a.insert, 0, 1e300) + self.assertRaises(OverflowError, a.extend, [1e300]) + self.assertEqual(a, array.array(self.typecode, [1])) class DoubleTest(FPTest, unittest.TestCase): typecode = 'd' @@ -1649,6 +1662,13 @@ class ComplexFloatTest(CFPTest, unittest.TestCase): def test_overflows(self): self.assertRaises(OverflowError, array.array, self.typecode, [1e300]) self.assertRaises(OverflowError, array.array, self.typecode, [1e300j]) + # A failed append, insert or extend leaves the array unchanged: + for x in 1e300, 1e300j: + a = array.array(self.typecode, [1]) + self.assertRaises(OverflowError, a.append, x) + self.assertRaises(OverflowError, a.insert, 0, x) + self.assertRaises(OverflowError, a.extend, [x]) + self.assertEqual(a, array.array(self.typecode, [1])) class ComplexDoubleTest(CFPTest, unittest.TestCase): typecode = 'Zd' diff --git a/Misc/NEWS.d/next/Library/2026-09-28-13-52-36.gh-issue-158345.GNlDCF.rst b/Misc/NEWS.d/next/Library/2026-09-28-13-52-36.gh-issue-158345.GNlDCF.rst new file mode 100644 index 00000000000000..208b3e8055e54a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-09-28-13-52-36.gh-issue-158345.GNlDCF.rst @@ -0,0 +1,3 @@ +Fix :meth:`array.array.append`, :meth:`~array.array.insert` and +:meth:`~array.array.extend` leaving an extra item in the array when they +raise :exc:`OverflowError` for the ``'e'``, ``'f'`` or ``'Zf'`` type code. diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index ef492d143d5644..9b5afe09a5e751 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -585,15 +585,18 @@ static int e_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) { double x; + char buf[sizeof(short)]; if (!PyArg_Parse(v, "d;array item must be float", &x)) { return -1; } + if (PyFloat_Pack2(x, buf, PY_LITTLE_ENDIAN) < 0) { + return -1; + } CHECK_ARRAY_BOUNDS(ap, i); if (i >= 0) { - return PyFloat_Pack2(x, ap->ob_item + sizeof(short)*i, - PY_LITTLE_ENDIAN); + memcpy(ap->ob_item + sizeof(short)*i, buf, sizeof(buf)); } return 0; } @@ -608,14 +611,17 @@ static int f_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) { double x; + char buf[sizeof(float)]; if (!PyArg_Parse(v, "d;array item must be float", &x)) return -1; + if (PyFloat_Pack4(x, buf, PY_LITTLE_ENDIAN) < 0) { + return -1; + } CHECK_ARRAY_BOUNDS(ap, i); if (i >= 0) { - return PyFloat_Pack4(x, ap->ob_item + sizeof(float)*i, - PY_LITTLE_ENDIAN); + memcpy(ap->ob_item + sizeof(float)*i, buf, sizeof(buf)); } return 0; } @@ -653,25 +659,21 @@ static int cf_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) { Py_complex x; + char f[8]; if (!PyArg_Parse(v, "D;array item must be complex", &x)) { return -1; } + if (PyFloat_Pack4(x.real, f, PY_LITTLE_ENDIAN) < 0 + || PyFloat_Pack4(x.imag, f + sizeof(float), PY_LITTLE_ENDIAN) < 0) + { + return -1; + } CHECK_ARRAY_BOUNDS(ap, i); if (i >= 0) { - 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; + memcpy(ap->ob_item + i*sizeof(f), &f, sizeof(f)); } return 0; }