https://github.com/python/cpython/commit/46c355fabff5833b77f72e26eb83f06b0e4d85ff
commit: 46c355fabff5833b77f72e26eb83f06b0e4d85ff
branch: main
author: PhysicistJohn <[email protected]>
committer: vstinner <[email protected]>
date: 2026-08-13T21:50:50+02:00
summary:

gh-154566: Fix array.byteswap() corrupting 'Zd' arrays with more than one 
element (#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.

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 d9b608fb23d0c6..c931be6df5fdaa 100755
--- a/Lib/test/test_array.py
+++ b/Lib/test/test_array.py
@@ -1583,6 +1583,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 39a399d7a49cf5..a0181c083a6036 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -1617,7 +1617,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]

Reply via email to