@@ -42,14 +42,25 @@ static Py_ssize_t _PyBytesWriter_ResizeToAllocated(PyBytesWriter *writer);
4242
4343
4444// Return a reference to the immortal empty bytes string singleton.
45- static inline PyObject * bytes_get_empty (void )
45+ static inline PyObject *
46+ bytes_get_empty (void )
4647{
4748 PyObject * empty = & EMPTY -> ob_base .ob_base ;
4849 assert (_Py_IsImmortal (empty ));
4950 return empty ;
5051}
5152
5253
54+ // The function cannot fail
55+ static inline PyObject *
56+ bytes_get_char (uint8_t ch )
57+ {
58+ PyObject * obj = (PyObject * )CHARACTER (ch );
59+ assert (_Py_IsImmortal (obj ));
60+ return obj ;
61+ }
62+
63+
5364static inline void
5465set_ob_shash (PyBytesObject * a , Py_hash_t hash )
5566{
@@ -130,9 +141,7 @@ PyBytes_FromStringAndSize(const char *str, Py_ssize_t size)
130141 return NULL ;
131142 }
132143 if (size == 1 && str != NULL ) {
133- op = CHARACTER (* str & 255 );
134- assert (_Py_IsImmortal (op ));
135- return (PyObject * )op ;
144+ return bytes_get_char ((uint8_t )* str );
136145 }
137146 if (size == 0 ) {
138147 return bytes_get_empty ();
@@ -166,9 +175,7 @@ PyBytes_FromString(const char *str)
166175 return bytes_get_empty ();
167176 }
168177 else if (size == 1 ) {
169- op = CHARACTER (* str & 255 );
170- assert (_Py_IsImmortal (op ));
171- return (PyObject * )op ;
178+ return bytes_get_char ((uint8_t )* str );
172179 }
173180
174181 /* Inline PyObject_NewVar */
@@ -3347,6 +3354,51 @@ _PyBytes_IsMutable(PyObject *self)
33473354#endif
33483355
33493356
3357+ static inline int
3358+ bytes_resize_inplace (PyObject * * pv , Py_ssize_t newsize )
3359+ {
3360+ PyObject * v = * pv ;
3361+ assert (_PyObject_IsUniquelyReferenced (v ));
3362+ assert (PyBytes_GET_SIZE (v ) >= 1 );
3363+ assert (newsize >= 1 );
3364+
3365+ // Only mutable bytes can be resized in-place
3366+ assert (_PyBytes_IsMutable (v ));
3367+
3368+ if ((size_t )newsize > (size_t )PY_SSIZE_T_MAX - PyBytesObject_SIZE ) {
3369+ PyErr_SetString (PyExc_OverflowError ,
3370+ "byte string is too large" );
3371+ return -1 ;
3372+ }
3373+
3374+ #ifdef Py_TRACE_REFS
3375+ _Py_ForgetReference (v );
3376+ #endif
3377+ _PyReftracerTrack (v , PyRefTracer_DESTROY );
3378+
3379+ PyObject * result = PyObject_Realloc (v , PyBytesObject_SIZE + newsize );
3380+ if (result == NULL ) {
3381+ #ifdef Py_TRACE_REFS
3382+ _Py_AddToAllObjects (v );
3383+ #endif
3384+ _PyReftracerTrack (v , PyRefTracer_CREATE );
3385+
3386+ PyErr_NoMemory ();
3387+ return -1 ;
3388+ }
3389+
3390+ * pv = result ;
3391+ v = result ;
3392+ _Py_NewReferenceNoTotal (v );
3393+ PyBytesObject * sv = (PyBytesObject * )v ;
3394+ Py_SET_SIZE (sv , newsize );
3395+ sv -> ob_sval [newsize ] = '\0' ;
3396+ set_ob_shash (sv , -1 ); /* invalidate cached hash value */
3397+ assert (_PyBytes_IsMutable (* pv ));
3398+ return 0 ;
3399+ }
3400+
3401+
33503402/* The following function breaks the notion that bytes are immutable:
33513403 it changes the size of a bytes object. You can think of it
33523404 as creating a new bytes object and destroying the old one, only
@@ -3410,40 +3462,7 @@ _PyBytes_ResizeKeepOnError(PyObject **pv, Py_ssize_t newsize)
34103462 return 0 ;
34113463 }
34123464
3413- // Only mutable bytes can be resized in-place
3414- assert (_PyBytes_IsMutable (v ));
3415-
3416- if ((size_t )newsize > (size_t )PY_SSIZE_T_MAX - PyBytesObject_SIZE ) {
3417- PyErr_SetString (PyExc_OverflowError ,
3418- "byte string is too large" );
3419- return -1 ;
3420- }
3421-
3422- #ifdef Py_TRACE_REFS
3423- _Py_ForgetReference (v );
3424- #endif
3425- _PyReftracerTrack (v , PyRefTracer_DESTROY );
3426-
3427- result = (PyObject * )PyObject_Realloc (v , PyBytesObject_SIZE + newsize );
3428- if (result == NULL ) {
3429- #ifdef Py_TRACE_REFS
3430- _Py_AddToAllObjects (v );
3431- #endif
3432- _PyReftracerTrack (v , PyRefTracer_CREATE );
3433-
3434- PyErr_NoMemory ();
3435- return -1 ;
3436- }
3437-
3438- * pv = result ;
3439- v = result ;
3440- _Py_NewReferenceNoTotal (v );
3441- PyBytesObject * sv = (PyBytesObject * )v ;
3442- Py_SET_SIZE (sv , newsize );
3443- sv -> ob_sval [newsize ] = '\0' ;
3444- set_ob_shash (sv , -1 ); /* invalidate cached hash value */
3445- assert (_PyBytes_IsMutable (* pv ));
3446- return 0 ;
3465+ return bytes_resize_inplace (pv , newsize );
34473466}
34483467
34493468
@@ -3903,9 +3922,6 @@ PyBytesWriter_FinishWithSize(PyBytesWriter *writer, Py_ssize_t size)
39033922{
39043923 assert (byteswriter_check_consistency (writer ));
39053924
3906- // Check for negative size here to raise ValueError in all cases, rather
3907- // than having a different exception depending on the code path. For
3908- // example, _PyBytes_Resize() raises SystemError on negative size.
39093925 if (size < 0 ) {
39103926 PyErr_Format (PyExc_ValueError , "size must be positive" );
39113927 goto error ;
@@ -3919,6 +3935,13 @@ PyBytesWriter_FinishWithSize(PyBytesWriter *writer, Py_ssize_t size)
39193935 PyObject * result ;
39203936 if (size == 0 && !writer -> use_bytearray ) {
39213937 result = bytes_get_empty ();
3938+ if (writer -> obj != NULL ) {
3939+ #ifdef Py_DEBUG
3940+ byteswriter_reset_trailing_byte (writer );
3941+ #endif
3942+ Py_DECREF (writer -> obj );
3943+ writer -> obj = NULL ;
3944+ }
39223945 }
39233946 else if (writer -> obj != NULL ) {
39243947 // Truncate the bytes/bytearray object if needed
@@ -3935,14 +3958,11 @@ PyBytesWriter_FinishWithSize(PyBytesWriter *writer, Py_ssize_t size)
39353958 }
39363959 else {
39373960 if (size == 1 ) {
3938- // Get the single byte singleton
39393961 unsigned char ch = PyBytes_AS_STRING (writer -> obj )[0 ];
3940- PyObject * op = (PyObject * )CHARACTER (ch );
3941- assert (_Py_IsImmortal (op ));
3942- Py_SETREF (writer -> obj , op );
3962+ Py_SETREF (writer -> obj , bytes_get_char (ch ));
39433963 }
39443964 else if (size != PyBytes_GET_SIZE (writer -> obj )) {
3945- if (_PyBytes_Resize (& writer -> obj , size )) {
3965+ if (bytes_resize_inplace (& writer -> obj , size )) {
39463966 goto error ;
39473967 }
39483968 }
@@ -3953,23 +3973,26 @@ PyBytesWriter_FinishWithSize(PyBytesWriter *writer, Py_ssize_t size)
39533973 }
39543974 else {
39553975 // Create an object from the small buffer
3976+ const char * buffer = (const char * )writer -> small_buffer ;
39563977 if (writer -> use_bytearray ) {
3957- result = PyByteArray_FromStringAndSize (writer -> small_buffer , size );
3978+ result = PyByteArray_FromStringAndSize (buffer , size );
39583979 }
39593980 else {
3960- // The function returns single byte singleton if size equals 1
3961- result = PyBytes_FromStringAndSize (writer -> small_buffer , size );
3981+ if (size == 1 ) {
3982+ result = bytes_get_char ((uint8_t )buffer [0 ]);
3983+ }
3984+ else {
3985+ result = _PyBytes_FromSize (size , 0 );
3986+ if (result == NULL ) {
3987+ goto error ;
3988+ }
3989+ memcpy (PyBytes_AS_STRING (result ), buffer , size );
3990+ }
39623991 }
39633992 }
39643993
3965- #ifdef Py_DEBUG
3966- // Reset the writer, so byteswriter_check_consistency() doesn't fail
3967- // in PyBytesWriter_Discard().
3968- writer -> size = 0 ;
3969- byteswriter_write_canary_byte (writer );
3970- #endif
3971-
3972- PyBytesWriter_Discard (writer );
3994+ assert (writer -> obj == NULL );
3995+ _Py_FREELIST_FREE (bytes_writers , writer , PyMem_Free );
39733996 return result ;
39743997
39753998error :
0 commit comments