mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Keep a bytearray exported while it formats with % (#9147)
bytearray.__mod__ copied the format and ran the arguments' __repr__,
__str__, __bytes__ and __index__ without holding an export, so a callback
could clear or extend the format and formatting went on with the old
copy:
fmt = bytearray(b"%a end")
class S:
def __repr__(self):
fmt.clear()
return "E"
fmt % S() # bytearray(b'E end'), fmt left empty
CPython holds a buffer on the format for the whole call, so the resize
fails with BufferError and the format is left as it was. Taking an export
for the duration of __mod__ does the same here, the way bytearray.join
already does for its separator.
This lets test_mod_concurrent_mutation in test_bytes run again.
Assisted-by: Claude Code:claude-opus-5-5
This commit is contained in:
1 parent
901431963b
commit
bf404e0b7c
2 files changed
+3
-2
No files matched your search
Vendored
-1
@@ -1393,7 +1393,6 @@ class ByteArrayTest(BaseBytesTest, unittest.TestCase):
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
@unittest.skip("TODO: RUSTPYTHON; segfault")
|
||||
def test_mod_concurrent_mutation(self):
|
||||
# Prevent crash in __mod__ when formatting mutates the bytearray.
|
||||
# Regression test for https://github.com/python/cpython/issues/142557.
|
||||
|
||||
@@ -454,7 +454,9 @@ impl PyByteArray {
|
||||
|
||||
fn __mod__(&self, values: PyObjectRef, vm: &VirtualMachine) -> PyResult<Self> {
|
||||
// Formatting calls the values' conversion methods, which can reach
|
||||
// this bytearray, so the format is taken by value.
|
||||
// this bytearray, so the format is taken by value. It also stays
|
||||
// exported until formatting ends, so resizing it raises BufferError.
|
||||
let _export = self.begin_export();
|
||||
let format = self.inner().clone();
|
||||
let formatted = format.cformat(values, vm)?;
|
||||
Ok(formatted.into())
|
||||
|
||||
Reference in new issue
Block a user