https://github.com/python/cpython/commit/30ce3d462dc97c8f351964e872c418abacaaabfd
commit: 30ce3d462dc97c8f351964e872c418abacaaabfd
branch: main
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2026-10-05T04:47:04+02:00
summary:

gh-158585: Simplify PyBytesWriter_Finish() (#158822)

PyBytesWriter_Finish() doesn't need to check the size. It's known to
be valid.

PyBytesWriter_Create() now only calls byteswriter_resize() if the
size is larger than the small buffer.

Remove byteswriter_data() function: call static inline
_PyBytesWriter_GetData() function directly.

files:
M Modules/_struct.c
M Objects/bytesobject.c
M Objects/unicodeobject.c
M Python/assemble.c

diff --git a/Modules/_struct.c b/Modules/_struct.c
index fb2f40ab9766c5..1e5d52b758f7e2 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -2498,7 +2498,8 @@ Struct_pack_impl(PyStructObject *self, PyObject * const 
*values,
         return NULL;
     }
 
-    return PyBytesWriter_FinishWithSize(writer, self->s_size);
+    assert(PyBytesWriter_GetSize(writer) == self->s_size);
+    return PyBytesWriter_Finish(writer);
 }
 
 /*[clinic input]
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index af5dce763e1f25..9bd9afc9b51ba4 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -3731,12 +3731,6 @@ _PyBytes_RepeatBuffer(char* dest, Py_ssize_t len_dest,
 // one extra NUL byte which is a common error.
 #define PyBytesWriter_CANARY_BYTE PYMEM_DEADBYTE
 
-static inline char*
-byteswriter_data(PyBytesWriter *writer)
-{
-    return _PyBytesWriter_GetData(writer);
-}
-
 
 static inline Py_ssize_t
 byteswriter_allocated(PyBytesWriter *writer)
@@ -3758,7 +3752,7 @@ byteswriter_allocated(PyBytesWriter *writer)
 static void
 byteswriter_write_canary_byte(PyBytesWriter *writer)
 {
-    unsigned char *data = (unsigned char*)byteswriter_data(writer);
+    unsigned char *data = (unsigned char*)_PyBytesWriter_GetData(writer);
     data[writer->size] = PyBytesWriter_CANARY_BYTE;
 }
 
@@ -3770,7 +3764,7 @@ byteswriter_reset_trailing_byte(PyBytesWriter *writer)
     // bytes/bytearray expects the last byte to be a null byte.
     // Reset the last byte to null for bytes/bytearray.
     Py_ssize_t allocated = byteswriter_allocated(writer);
-    char *data = byteswriter_data(writer);
+    char *data = _PyBytesWriter_GetData(writer);
     data[allocated] = '\0';
 }
 #endif
@@ -3801,7 +3795,7 @@ byteswriter_check_consistency(PyBytesWriter *writer)
     }
 
 #ifdef Py_DEBUG
-    const unsigned char *data = (const unsigned char*)byteswriter_data(writer);
+    const unsigned char *data = (const unsigned 
char*)_PyBytesWriter_GetData(writer);
     unsigned char canary = data[writer->size];
     if (canary != PyBytesWriter_CANARY_BYTE) {
         _Py_FatalErrorFormat(__func__,
@@ -3895,7 +3889,7 @@ byteswriter_resize(PyBytesWriter *writer, Py_ssize_t 
new_size, int resize)
     if (resize) {
         Py_ssize_t old_size = writer->size;
         assert(allocated > old_size);
-        memset(byteswriter_data(writer) + old_size, PyBytesWrite_NEW_BYTE,
+        memset(_PyBytesWriter_GetData(writer) + old_size, 
PyBytesWrite_NEW_BYTE,
                allocated - old_size);
     }
 #endif
@@ -3921,24 +3915,25 @@ byteswriter_create(Py_ssize_t size, int use_bytearray)
         }
     }
     writer->obj = NULL;
-    writer->size = 0;
+    writer->size = size;
     writer->use_bytearray = use_bytearray;
     writer->overallocate = !use_bytearray;
 
-    if (size >= 1) {
+    Py_ssize_t allocated = sizeof(writer->small_buffer) - 1;
+    if (size > allocated) {
         if (byteswriter_resize(writer, size, 0) < 0) {
 #ifdef Py_DEBUG
             // Write the canary byte so byteswriter_check_consistency()
             // doesn't fail in PyBytesWriter_Discard()
+            writer->size = 0;
             byteswriter_write_canary_byte(writer);
 #endif
             PyBytesWriter_Discard(writer);
             return NULL;
         }
-        writer->size = size;
     }
 #ifdef Py_DEBUG
-    memset(byteswriter_data(writer), PyBytesWrite_NEW_BYTE,
+    memset(_PyBytesWriter_GetData(writer), PyBytesWrite_NEW_BYTE,
            byteswriter_allocated(writer));
     byteswriter_write_canary_byte(writer);
 #endif
@@ -3967,34 +3962,23 @@ PyBytesWriter_Discard(PyBytesWriter *writer)
     }
 
     assert(byteswriter_check_consistency(writer));
-#ifdef Py_DEBUG
     if (writer->obj != NULL) {
+#ifdef Py_DEBUG
         byteswriter_reset_trailing_byte(writer);
-    }
 #endif
-
-    Py_XDECREF(writer->obj);
+        Py_DECREF(writer->obj);
+    }
     _Py_FREELIST_FREE(bytes_writers, writer, PyMem_Free);
 }
 
 
-PyObject*
-PyBytesWriter_FinishWithSize(PyBytesWriter *writer, Py_ssize_t size)
+static inline PyObject*
+byteswriter_finish_with_size(PyBytesWriter *writer, Py_ssize_t final_size)
 {
     assert(byteswriter_check_consistency(writer));
 
-    if (size < 0) {
-        PyErr_Format(PyExc_ValueError, "size must be positive");
-        goto error;
-    }
-
-    if (size > writer->size) {
-        PyErr_SetString(PyExc_ValueError, "size larger than allocated size");
-        goto error;
-    }
-
     PyObject *result;
-    if (size == 0 && !writer->use_bytearray) {
+    if (final_size == 0 && !writer->use_bytearray) {
         result = bytes_get_empty();
         if (writer->obj != NULL) {
 #ifdef Py_DEBUG
@@ -4011,19 +3995,19 @@ PyBytesWriter_FinishWithSize(PyBytesWriter *writer, 
Py_ssize_t size)
 #endif
 
         if (writer->use_bytearray) {
-            if (size != PyByteArray_GET_SIZE(writer->obj)) {
-                if (PyByteArray_Resize(writer->obj, size)) {
+            if (final_size != PyByteArray_GET_SIZE(writer->obj)) {
+                if (PyByteArray_Resize(writer->obj, final_size)) {
                     goto error;
                 }
             }
         }
         else {
-            if (size == 1) {
+            if (final_size == 1) {
                 unsigned char ch = PyBytes_AS_STRING(writer->obj)[0];
                 Py_SETREF(writer->obj, bytes_get_char(ch));
             }
-            else if (size != PyBytes_GET_SIZE(writer->obj)) {
-                if (bytes_resize_inplace(&writer->obj, size)) {
+            else if (final_size != PyBytes_GET_SIZE(writer->obj)) {
+                if (bytes_resize_inplace(&writer->obj, final_size)) {
                     goto error;
                 }
             }
@@ -4036,18 +4020,18 @@ PyBytesWriter_FinishWithSize(PyBytesWriter *writer, 
Py_ssize_t size)
         // Create an object from the small buffer
         const char *buffer = (const char *)writer->small_buffer;
         if (writer->use_bytearray) {
-            result = PyByteArray_FromStringAndSize(buffer, size);
+            result = PyByteArray_FromStringAndSize(buffer, final_size);
         }
         else {
-            if (size == 1) {
+            if (final_size == 1) {
                 result = bytes_get_char((uint8_t)buffer[0]);
             }
             else {
-                result = bytes_alloc(size);
+                result = bytes_alloc(final_size);
                 if (result == NULL) {
                     goto error;
                 }
-                memcpy(PyBytes_AS_STRING(result), buffer, size);
+                memcpy(PyBytes_AS_STRING(result), buffer, final_size);
             }
         }
     }
@@ -4061,17 +4045,36 @@ PyBytesWriter_FinishWithSize(PyBytesWriter *writer, 
Py_ssize_t size)
     return NULL;
 }
 
+PyObject*
+PyBytesWriter_FinishWithSize(PyBytesWriter *writer, Py_ssize_t size)
+{
+    if (size < 0) {
+        PyErr_Format(PyExc_ValueError, "size must be positive");
+        goto error;
+    }
+    if (size > writer->size) {
+        PyErr_SetString(PyExc_ValueError, "size larger than allocated size");
+        goto error;
+    }
+    return byteswriter_finish_with_size(writer, size);
+
+error:
+    PyBytesWriter_Discard(writer);
+    return NULL;
+}
+
 PyObject*
 PyBytesWriter_Finish(PyBytesWriter *writer)
 {
-    return PyBytesWriter_FinishWithSize(writer, writer->size);
+    return byteswriter_finish_with_size(writer, writer->size);
 }
 
 
 PyObject*
 PyBytesWriter_FinishWithPointer(PyBytesWriter *writer, void *buf)
 {
-    Py_ssize_t size = (char*)buf - byteswriter_data(writer);
+    Py_ssize_t size = (char*)buf - _PyBytesWriter_GetData(writer);
+    // Call PyBytesWriter_FinishWithSize() to check size
     return PyBytesWriter_FinishWithSize(writer, size);
 }
 
@@ -4081,7 +4084,7 @@ PyBytesWriter_GetData(PyBytesWriter *writer)
 {
     assert(byteswriter_check_consistency(writer));
 
-    return byteswriter_data(writer);
+    return _PyBytesWriter_GetData(writer);
 }
 
 
@@ -4125,11 +4128,11 @@ static void*
 _PyBytesWriter_ResizeAndUpdatePointer(PyBytesWriter *writer, Py_ssize_t size,
                                       void *data)
 {
-    Py_ssize_t pos = (char*)data - byteswriter_data(writer);
+    Py_ssize_t pos = (char*)data - _PyBytesWriter_GetData(writer);
     if (PyBytesWriter_Resize(writer, size) < 0) {
         return NULL;
     }
-    return byteswriter_data(writer) + pos;
+    return _PyBytesWriter_GetData(writer) + pos;
 }
 
 
@@ -4176,11 +4179,11 @@ void*
 PyBytesWriter_GrowAndUpdatePointer(PyBytesWriter *writer, Py_ssize_t size,
                                    void *buf)
 {
-    Py_ssize_t pos = (char*)buf - byteswriter_data(writer);
+    Py_ssize_t pos = (char*)buf - _PyBytesWriter_GetData(writer);
     if (PyBytesWriter_Grow(writer, size) < 0) {
         return NULL;
     }
-    return byteswriter_data(writer) + pos;
+    return _PyBytesWriter_GetData(writer) + pos;
 }
 
 
@@ -4201,7 +4204,7 @@ PyBytesWriter_WriteBytes(PyBytesWriter *writer,
     if (PyBytesWriter_Grow(writer, size) < 0) {
         return -1;
     }
-    char *buf = byteswriter_data(writer);
+    char *buf = _PyBytesWriter_GetData(writer);
     memcpy(buf + pos, bytes, size);
 
     assert(byteswriter_check_consistency(writer));
@@ -4232,7 +4235,7 @@ PyBytesWriter_Format(PyBytesWriter *writer, const char 
*format, ...)
         return -1;
     }
 
-    Py_ssize_t size = buf - byteswriter_data(writer);
+    Py_ssize_t size = buf - _PyBytesWriter_GetData(writer);
     return PyBytesWriter_Resize(writer, size);
 }
 
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 157e005c3c0b60..ded13cc37f69f1 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -4880,7 +4880,7 @@ _PyUnicode_EncodeUTF7(PyObject *str,
         else { /* not in a shift sequence */
             if (ch == '+') {
                 *out++ = '+';
-                        *out++ = '-';
+                *out++ = '-';
             }
             else if (ENCODE_DIRECT(ch)) {
                 *out++ = (char) ch;
@@ -8644,10 +8644,7 @@ _PyUnicode_EncodeIconv(const char *encoding, PyObject 
*unicode,
         iconv(cd, NULL, NULL, NULL, NULL);
     }
 
-    if (PyBytesWriter_Resize(writer, out - (char 
*)PyBytesWriter_GetData(writer)) < 0) {
-        goto done;
-    }
-    result = PyBytesWriter_Finish(writer);
+    result = PyBytesWriter_FinishWithPointer(writer, out);
     writer = NULL;
 
 done:
diff --git a/Python/assemble.c b/Python/assemble.c
index 2c8abb116b2e33..8f68e233ab7b93 100644
--- a/Python/assemble.c
+++ b/Python/assemble.c
@@ -102,7 +102,7 @@ assemble_free(struct assembler *a)
 
 static inline void
 write_except_byte(struct assembler *a, int byte) {
-    unsigned char *p = (unsigned char *) 
PyBytesWriter_GetData(a->a_except_table_writer);
+    unsigned char *p = PyBytesWriter_GetData(a->a_except_table_writer);
     p[a->a_except_table_off++] = byte;
 }
 

_______________________________________________
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