Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit eba9f61

Browse files
authored
bpo-40330: Fix utf-8 size check in ShareableList (GH-19606)
The item size must be checked after encoding to bytes, not before. Automerge-Triggered-By: @pitrou
1 parent 5dd21f5 commit eba9f61

File tree

3 files changed

+22
-6
lines changed

3 files changed

+22
-6
lines changed

Lib/multiprocessing/shared_memory.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -445,11 +445,14 @@ def __setitem__(self, position, value):
445445

446446
if not isinstance(value, (str, bytes)):
447447
new_format = self._types_mapping[type(value)]
448+
encoded_value = value
448449
else:
449450
allocated_length = self._allocated_offsets[position + 1] - item_offset
450451

451-
if len(value) > allocated_length:
452-
raise ValueError("exceeds available storage for existing str")
452+
encoded_value = (value.encode(_encoding)
453+
if isinstance(value, str) else value)
454+
if len(encoded_value) > allocated_length:
455+
raise ValueError("bytes/str item exceeds available storage")
453456
if current_format[-1] == "s":
454457
new_format = current_format
455458
else:
@@ -462,8 +465,7 @@ def __setitem__(self, position, value):
462465
new_format,
463466
value
464467
)
465-
value = value.encode(_encoding) if isinstance(value, str) else value
466-
struct.pack_into(new_format, self.shm.buf, offset, value)
468+
struct.pack_into(new_format, self.shm.buf, offset, encoded_value)
467469

468470
def __reduce__(self):
469471
return partial(self.__class__, name=self.shm.name), ()

Lib/test/_test_multiprocessing.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3995,9 +3995,21 @@ def test_shared_memory_ShareableList_basics(self):
39953995
sl[4] = 'some' # Change type at a given position.
39963996
self.assertEqual(sl[4], 'some')
39973997
self.assertEqual(sl.format, '8s8sdq8sxxxxxxx?q')
3998-
with self.assertRaises(ValueError):
3999-
sl[4] = 'far too many' # Exceeds available storage.
3998+
with self.assertRaisesRegex(ValueError,
3999+
"exceeds available storage"):
4000+
sl[4] = 'far too many'
40004001
self.assertEqual(sl[4], 'some')
4002+
sl[0] = 'encodés' # Exactly 8 bytes of UTF-8 data
4003+
self.assertEqual(sl[0], 'encodés')
4004+
self.assertEqual(sl[1], b'HoWdY') # no spillage
4005+
with self.assertRaisesRegex(ValueError,
4006+
"exceeds available storage"):
4007+
sl[0] = 'encodées' # Exactly 9 bytes of UTF-8 data
4008+
self.assertEqual(sl[1], b'HoWdY')
4009+
with self.assertRaisesRegex(ValueError,
4010+
"exceeds available storage"):
4011+
sl[1] = b'123456789'
4012+
self.assertEqual(sl[1], b'HoWdY')
40014013

40024014
# Exercise count().
40034015
with warnings.catch_warnings():
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
In :meth:`ShareableList.__setitem__`, check the size of a new string item
2+
after encoding it to utf-8, not before.

0 commit comments

Comments
 (0)