https://github.com/python/cpython/commit/71cb1655b944337f83f68b188c10fd13a3919163 commit: 71cb1655b944337f83f68b188c10fd13a3919163 branch: 3.15 author: Miss Islington (bot) <[email protected]> committer: hugovk <[email protected]> date: 2026-08-14T17:54:37+09:00 summary:
[3.15] gh-154566: Fix array.byteswap() corrupting 'Zd' arrays with more than one element (GH-154567) (#155756) gh-154566: Fix array.byteswap() corrupting 'Zd' arrays with more than one element (GH-154567) Fix array.array.byteswap() corrupting data for 'Zd' (complex double) arrays with more than one element: the 16-byte item loop advanced the buffer pointer by only 8 bytes per iteration, causing items after the first to be scrambled. (cherry picked from commit 46c355fabff5833b77f72e26eb83f06b0e4d85ff) Co-authored-by: PhysicistJohn <[email protected]> Co-authored-by: Victor Stinner <[email protected]> files: A Misc/NEWS.d/next/Library/2026-07-23-20-00-00.gh-issue-154566.byteswap-zd.rst M Lib/test/test_array.py M Modules/arraymodule.c diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py index 430f55f2129884..85cecc083f752e 100755 --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -1638,6 +1638,22 @@ def test_byteswap(self): b.byteswap() self.assertEqual(a, b) + def test_byteswap_single_call_result(self): + # A single byteswap() must swap each item's two halves (real, + # imag) independently. test_byteswap above only checks that + # byteswap() twice round-trips to the original, which passes + # even if a single call scrambles multi-item arrays. + a = array.array(self.typecode, self.example) + original = a.tobytes() + a.byteswap() + itemsize = a.itemsize + half = itemsize // 2 + expected = bytearray() + for i in range(0, len(original), itemsize): + item = original[i:i + itemsize] + expected += item[half - 1::-1] + item[itemsize - 1:half - 1:-1] + self.assertEqual(a.tobytes(), bytes(expected)) + class HalfFloatTest(FPTest, unittest.TestCase): example = [-42.0, 0, 42, 1e2, -1e4] diff --git a/Misc/NEWS.d/next/Library/2026-07-23-20-00-00.gh-issue-154566.byteswap-zd.rst b/Misc/NEWS.d/next/Library/2026-07-23-20-00-00.gh-issue-154566.byteswap-zd.rst new file mode 100644 index 00000000000000..e86b9a979946cd --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-07-23-20-00-00.gh-issue-154566.byteswap-zd.rst @@ -0,0 +1,4 @@ +Fix :meth:`array.array.byteswap` corrupting data for ``'Zd'`` (complex +double) arrays with more than one element: the 16-byte item loop advanced +the buffer pointer by only 8 bytes per iteration, causing items after the +first to be scrambled. diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 45cdf351cbb6ce..505c44d23735b4 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -1661,7 +1661,7 @@ array_array_byteswap_impl(arrayobject *self) break; case 16: assert(strcmp(self->ob_descr->typecode, "Zd") == 0); - for (p = self->ob_item, i = Py_SIZE(self); --i >= 0; p += 8) { + for (p = self->ob_item, i = Py_SIZE(self); --i >= 0; p += 16) { char t0 = p[0]; char t1 = p[1]; char t2 = p[2]; _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
