@@ -3191,12 +3191,42 @@ bytes_iteritem(PyObject *obj, Py_ssize_t index)
31913191 return (_PyObjectIndexPair ) { .object = l , .index = index + 1 };
31923192}
31933193
3194+ #ifdef Py_DEBUG
3195+ void
3196+ _PyBytes_CheckOverflow (PyObject * self , void * addr , const char * type_name )
3197+ {
3198+ // Make sure that the trailing null byte was not modified
3199+ char * data = PyBytes_AS_STRING (self );
3200+ Py_ssize_t size = PyBytes_GET_SIZE (self );
3201+ if (data [size ] != '\0' ) {
3202+ _Py_FatalErrorFormat (__func__ ,
3203+ "Buffer overflow detected in %s object %p "
3204+ "at position %zd" ,
3205+ type_name , addr , size );
3206+ }
3207+ }
3208+
3209+
3210+ static void
3211+ bytes_dealloc (PyObject * op )
3212+ {
3213+ PyBytesObject * self = _PyBytes_CAST (op );
3214+ _PyBytes_CheckOverflow (op , op , "bytes" );
3215+ Py_TYPE (self )-> tp_free ((PyObject * )self );
3216+ }
3217+ #endif
3218+
3219+
31943220PyTypeObject PyBytes_Type = {
31953221 PyVarObject_HEAD_INIT (& PyType_Type , 0 )
31963222 "bytes" ,
31973223 PyBytesObject_SIZE ,
31983224 sizeof (char ),
3225+ #ifdef Py_DEBUG
3226+ bytes_dealloc , /* tp_dealloc */
3227+ #else
31993228 0 , /* tp_dealloc */
3229+ #endif
32003230 0 , /* tp_vectorcall_offset */
32013231 0 , /* tp_getattr */
32023232 0 , /* tp_setattr */
@@ -3665,6 +3695,18 @@ byteswriter_write_canary_byte(PyBytesWriter *writer)
36653695 unsigned char * data = (unsigned char * )byteswriter_data (writer );
36663696 data [writer -> size ] = PyBytesWriter_CANARY_BYTE ;
36673697}
3698+
3699+
3700+ static void
3701+ byteswriter_reset_trailing_byte (PyBytesWriter * writer )
3702+ {
3703+ // PyBytesWriter writes non-zero canary byte as the last byte.
3704+ // bytes/bytearray expects the last byte to be a null byte.
3705+ // Reset the last byte to null for bytes/bytearray.
3706+ Py_ssize_t allocated = byteswriter_allocated (writer );
3707+ char * data = byteswriter_data (writer );
3708+ data [allocated ] = '\0' ;
3709+ }
36683710#endif
36693711
36703712
@@ -3814,6 +3856,9 @@ PyBytesWriter_Discard(PyBytesWriter *writer)
38143856
38153857#ifdef Py_DEBUG
38163858 byteswriter_check_canary_byte (writer );
3859+ if (writer -> obj != NULL ) {
3860+ byteswriter_reset_trailing_byte (writer );
3861+ }
38173862#endif
38183863
38193864 Py_XDECREF (writer -> obj );
@@ -3838,23 +3883,19 @@ PyBytesWriter_FinishWithSize(PyBytesWriter *writer, Py_ssize_t size)
38383883 }
38393884
38403885#ifdef Py_DEBUG
3841- // Check for buffer overflow
38423886 byteswriter_check_canary_byte (writer );
3843-
3844- if (writer -> obj != NULL ) {
3845- // byteswriter_write_canary_byte() can override the trailing NUL byte.
3846- // So reset the trailing NUL byte to NUL.
3847- Py_ssize_t allocated = byteswriter_allocated (writer );
3848- char * data = byteswriter_data (writer );
3849- data [allocated ] = '\0' ;
3850- }
38513887#endif
38523888
38533889 PyObject * result ;
38543890 if (size == 0 ) {
38553891 result = bytes_get_empty ();
38563892 }
38573893 else if (writer -> obj != NULL ) {
3894+ // Truncate the bytes/bytearray object if needed
3895+ #ifdef Py_DEBUG
3896+ byteswriter_reset_trailing_byte (writer );
3897+ #endif
3898+
38583899 if (writer -> use_bytearray ) {
38593900 if (size != PyByteArray_GET_SIZE (writer -> obj )) {
38603901 if (PyByteArray_Resize (writer -> obj , size )) {
@@ -3868,25 +3909,28 @@ PyBytesWriter_FinishWithSize(PyBytesWriter *writer, Py_ssize_t size)
38683909 goto error ;
38693910 }
38703911 }
3912+
3913+ if (size == 1 ) {
3914+ // Get the single byte singleton
3915+ unsigned char ch = PyBytes_AS_STRING (writer -> obj )[0 ];
3916+ PyObject * op = (PyObject * )CHARACTER (ch );
3917+ assert (_Py_IsImmortal (op ));
3918+ Py_SETREF (writer -> obj , op );
3919+ }
38713920 }
38723921
38733922 result = writer -> obj ;
38743923 writer -> obj = NULL ;
3875-
3876- if (size == 1 && !writer -> use_bytearray ) {
3877- // Get the single byte singleton
3878- unsigned char ch = PyBytes_AS_STRING (result )[0 ];
3879- PyObject * op = (PyObject * )CHARACTER (ch );
3880- assert (_Py_IsImmortal (op ));
3881- Py_SETREF (result , op );
3882- }
3883- }
3884- else if (writer -> use_bytearray ) {
3885- result = PyByteArray_FromStringAndSize (writer -> small_buffer , size );
38863924 }
38873925 else {
3888- // The function returns single byte singleton if size equals 1
3889- result = PyBytes_FromStringAndSize (writer -> small_buffer , size );
3926+ // Create an object from the small buffer
3927+ if (writer -> use_bytearray ) {
3928+ result = PyByteArray_FromStringAndSize (writer -> small_buffer , size );
3929+ }
3930+ else {
3931+ // The function returns single byte singleton if size equals 1
3932+ result = PyBytes_FromStringAndSize (writer -> small_buffer , size );
3933+ }
38903934 }
38913935
38923936#ifdef Py_DEBUG
0 commit comments