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]

Reply via email to