Skip to content

Commit c8a9982

Browse files
committed
gh-155850: Fix array unpickling of odd-length 'w' arrays across endianness
mformat_descriptors stored a wrong item size for the UTF-16 (4, should be 2) and UTF-32 (8, should be 4) machine formats. The field gates the cross-endian unpickling length check, so an odd-length 'w' array pickled on an opposite- endian machine was rejected with ValueError.
1 parent 948fd7e commit c8a9982

3 files changed

Lines changed: 21 additions & 12 deletions

File tree

Lib/test/test_array.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -254,20 +254,26 @@ def test_float16_endianness(self):
254254
self.assertEqual(b_be.tolist(), [1.5])
255255

256256
def test_unicode(self):
257-
teststr = "Bonne Journ\xe9e \U0002030a\U00020347"
258257
testcases = (
259258
(UTF16_LE, "UTF-16-LE"),
260259
(UTF16_BE, "UTF-16-BE"),
261260
(UTF32_LE, "UTF-32-LE"),
262261
(UTF32_BE, "UTF-32-BE")
263262
)
264-
for testcase in testcases:
265-
mformat_code, encoding = testcase
266-
a = array.array('w', teststr)
267-
b = array_reconstructor(
268-
array.array, 'w', mformat_code, teststr.encode(encoding))
269-
self.assertEqual(a, b,
270-
msg="{0!r} != {1!r}; testcase={2!r}".format(a, b, testcase))
263+
# An even and an odd number of code points: the reconstructor's
264+
# slow-path length check used a wrong item size for UTF-16/UTF-32,
265+
# which rejected odd-length input.
266+
for teststr in ("Bonne Journ\xe9e \U0002030a\U00020347",
267+
"Bonne Journ\xe9e \U0002030a\U00020347!"):
268+
for testcase in testcases:
269+
mformat_code, encoding = testcase
270+
a = array.array('w', teststr)
271+
b = array_reconstructor(
272+
array.array, 'w', mformat_code, teststr.encode(encoding))
273+
self.assertEqual(
274+
a, b,
275+
msg="{0!r} != {1!r}; testcase={2!r}".format(
276+
a, b, testcase))
271277

272278

273279
class BaseTest:
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix :mod:`array` unpickling of an odd-length ``'w'`` array pickled on a
2+
machine of the opposite endianness; a wrong item size for the UTF-16 and
3+
UTF-32 machine formats made it raise :exc:`ValueError`.

Modules/arraymodule.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2050,10 +2050,10 @@ static const struct mformatdescr {
20502050
{4, 0, 1}, /* 15: IEEE_754_FLOAT_BE */
20512051
{8, 0, 0}, /* 16: IEEE_754_DOUBLE_LE */
20522052
{8, 0, 1}, /* 17: IEEE_754_DOUBLE_BE */
2053-
{4, 0, 0}, /* 18: UTF16_LE */
2054-
{4, 0, 1}, /* 19: UTF16_BE */
2055-
{8, 0, 0}, /* 20: UTF32_LE */
2056-
{8, 0, 1}, /* 21: UTF32_BE */
2053+
{2, 0, 0}, /* 18: UTF16_LE */
2054+
{2, 0, 1}, /* 19: UTF16_BE */
2055+
{4, 0, 0}, /* 20: UTF32_LE */
2056+
{4, 0, 1}, /* 21: UTF32_BE */
20572057
{8, 0, 0}, /* 22: IEEE_754_FLOAT_COMPLEX_LE */
20582058
{8, 0, 1}, /* 23: IEEE_754_FLOAT_COMPLEX_BE */
20592059
{16, 0, 0}, /* 24: IEEE_754_DOUBLE_COMPLEX_LE */

0 commit comments

Comments
 (0)