Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions crates/vm/src/builtins/bytearray.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1250,6 +1250,13 @@ impl Py<PyByteArray> {
let ResizeAccess::Exclusive(mut inner) = access else {
return Err(vm.new_buffer_error("Existing exports of data: object cannot be re-sized"));
};
// CPython 3.15's PyByteArray_SIZE_MAX subtracts _PyBytesObject_SIZE.
// The normal GIL build has four pointer-sized header fields and a
// trailing null byte. Vec accepts larger lengths on 32-bit targets.
const MAX_SIZE: usize = isize::MAX as usize - size_of::<[usize; 4]>() - 1;
if size > MAX_SIZE {
return Err(vm.no_memory_error());
}
if size == 0 {
let _old = core::mem::take(&mut inner.elements);
drop(inner);
Expand Down
14 changes: 14 additions & 0 deletions extra_tests/snippets/builtin_bytearray.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
import pickle
import struct
import sys

from testutils import assert_raises

with assert_raises(MemoryError):
bytearray(b"ab").resize(sys.maxsize)

# The backing bytes header also excludes lengths just below sys.maxsize.
for size in (sys.maxsize - 4 * struct.calcsize("n"), sys.maxsize - 1):
original = bytearray(b"unchanged")
with assert_raises(MemoryError):
original.resize(size)
assert original == b"unchanged"

# An existing export is rejected before the allocation limit is checked.
with memoryview(original):
with assert_raises(BufferError):
original.resize(size)
assert original == b"unchanged"

# new
assert bytearray([1, 2, 3])
assert bytearray((1, 2, 3))
Expand Down
Loading