https://github.com/python/cpython/commit/3b1057d4b5b2dfa57f6dbd868ffe7f787e0a82c9
commit: 3b1057d4b5b2dfa57f6dbd868ffe7f787e0a82c9
branch: main
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2026-09-15T15:10:07Z
summary:
gh-156939: Clear newly allocated bytes in PyBytesWriter_Resize() (#157455)
Adjust the logic to set newly allocated bytes to a known byte pattern
(PyBytesWrite_NEW_BYTE). Only copy 'size' bytes from the small buffer
to the new bytes/bytearray object.
files:
M Lib/test/test_capi/test_bytes.py
M Objects/bytesobject.c
diff --git a/Lib/test/test_capi/test_bytes.py b/Lib/test/test_capi/test_bytes.py
index 12a1e88eac82d9..b68412a02b3228 100644
--- a/Lib/test/test_capi/test_bytes.py
+++ b/Lib/test/test_capi/test_bytes.py
@@ -386,7 +386,7 @@ def test_get_data(self):
writer.write(0, b's' * small)
self.assertEqual(writer.get_data(), b's' * small)
writer.resize(large)
- self.assertEqual(writer.get_data(), b's' * small + CANARY_BYTE +
NEW_BYTE * (large - small - 1))
+ self.assertEqual(writer.get_data(), b's' * small + NEW_BYTE * (large -
small))
writer.write(small, b'L' * (large - small))
self.assertEqual(writer.get_data(), b's' * small + b'L' * (large -
small))
@@ -475,6 +475,7 @@ def test_resize(self):
@unittest.skipUnless(support.Py_DEBUG, 'need debug build')
def test_resize_canary(self):
CANARY_BYTE = self.CANARY_BYTE
+
for size in (self.SMALL_BUFFER, self.LARGE_BUFFER):
with self.subTest(size=size):
# Truncate the last byte
@@ -490,7 +491,7 @@ def test_resize_canary(self):
writer = self.create_writer(size)
writer.write(0, data)
writer.resize(0)
- self.assertEqual(writer.get_data(), b'')
+ self.assertEqual(get_data_canary(writer), CANARY_BYTE)
self.assertEqual(writer.finish(), b'')
@support.nomemtest
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index 4f33b14a197eab..38ec7a4aefcf56 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -3719,25 +3719,26 @@ byteswriter_reset_trailing_byte(PyBytesWriter *writer)
#endif
static inline int
-byteswriter_resize(PyBytesWriter *writer, Py_ssize_t size, int resize)
+byteswriter_resize(PyBytesWriter *writer, Py_ssize_t new_size, int resize)
{
- assert(size >= 0);
+ assert(new_size >= 0);
Py_ssize_t old_allocated = byteswriter_allocated(writer);
- if (size <= old_allocated) {
+ if (new_size <= old_allocated) {
// Do not shrink the buffer before PyBytesWriter_FinishWithSize()
return 0;
}
+ Py_ssize_t alloc = new_size;
if (resize && writer->overallocate) {
- if (size <= (PY_SSIZE_T_MAX - size / OVERALLOCATE_FACTOR)) {
- size += size / OVERALLOCATE_FACTOR;
+ if (alloc <= (PY_SSIZE_T_MAX - alloc / OVERALLOCATE_FACTOR)) {
+ alloc += alloc / OVERALLOCATE_FACTOR;
}
}
if (writer->obj != NULL) {
if (writer->use_bytearray) {
- if (PyByteArray_Resize(writer->obj, size)) {
+ if (PyByteArray_Resize(writer->obj, alloc)) {
#ifdef Py_DEBUG
// bytearray can override the canary byte on error
byteswriter_write_canary_byte(writer);
@@ -3747,7 +3748,7 @@ byteswriter_resize(PyBytesWriter *writer, Py_ssize_t
size, int resize)
}
else {
// Can raise MemoryError or OverflowError
- if (_PyBytes_ResizeKeepOnError(&writer->obj, size)) {
+ if (_PyBytes_ResizeKeepOnError(&writer->obj, alloc)) {
assert(writer->obj != NULL);
return -1;
}
@@ -3755,37 +3756,40 @@ byteswriter_resize(PyBytesWriter *writer, Py_ssize_t
size, int resize)
}
assert(writer->obj != NULL);
}
- else if (writer->use_bytearray) {
- writer->obj = PyByteArray_FromStringAndSize(NULL, size);
- if (writer->obj == NULL) {
- return -1;
- }
- if (resize) {
- assert((size_t)size > sizeof(writer->small_buffer));
- memcpy(PyByteArray_AS_STRING(writer->obj),
- writer->small_buffer,
- sizeof(writer->small_buffer));
- }
- }
else {
- writer->obj = PyBytes_FromStringAndSize(NULL, size);
- if (writer->obj == NULL) {
- return -1;
+ char *data;
+ if (writer->use_bytearray) {
+ writer->obj = PyByteArray_FromStringAndSize(NULL, alloc);
+ if (writer->obj == NULL) {
+ return -1;
+ }
+ data = PyByteArray_AS_STRING(writer->obj);
+ }
+ else {
+ writer->obj = PyBytes_FromStringAndSize(NULL, alloc);
+ if (writer->obj == NULL) {
+ return -1;
+ }
+ assert(_PyBytes_IsMutable(writer->obj));
+ data = PyBytes_AS_STRING(writer->obj);
}
+
if (resize) {
- assert((size_t)size > sizeof(writer->small_buffer));
- memcpy(PyBytes_AS_STRING(writer->obj),
- writer->small_buffer,
- sizeof(writer->small_buffer));
+ // Copy data from the small buffer
+ Py_ssize_t old_size = writer->size;
+ assert((size_t)old_size <= sizeof(writer->small_buffer));
+ assert(old_size <= alloc);
+ memcpy(data, writer->small_buffer, old_size);
}
- assert(_PyBytes_IsMutable(writer->obj));
}
#ifdef Py_DEBUG
Py_ssize_t allocated = byteswriter_allocated(writer);
- if (resize && allocated > old_allocated) {
- memset(byteswriter_data(writer) + old_allocated, PyBytesWrite_NEW_BYTE,
- allocated - old_allocated);
+ if (resize) {
+ Py_ssize_t old_size = writer->size;
+ assert(allocated > old_size);
+ memset(byteswriter_data(writer) + old_size, PyBytesWrite_NEW_BYTE,
+ allocated - old_size);
}
#endif
_______________________________________________
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]