@@ -127,15 +127,14 @@ PyObject *
127127PyByteArray_FromStringAndSize (const char * bytes , Py_ssize_t size )
128128{
129129 PyByteArrayObject * new ;
130- Py_ssize_t alloc ;
131130
132131 if (size < 0 ) {
133132 PyErr_SetString (PyExc_SystemError ,
134133 "Negative size passed to PyByteArray_FromStringAndSize" );
135134 return NULL ;
136135 }
137136
138- /* Prevent buffer overflow when setting alloc to size+1 . */
137+ /* Prevent buffer overflow when setting alloc to size. */
139138 if (size == PY_SSIZE_T_MAX ) {
140139 return PyErr_NoMemory ();
141140 }
@@ -145,27 +144,18 @@ PyByteArray_FromStringAndSize(const char *bytes, Py_ssize_t size)
145144 return NULL ;
146145 }
147146
148- if ( size == 0 ) {
149- new -> ob_bytes_object = NULL ;
150- new -> ob_bytes = NULL ;
151- alloc = 0 ;
147+ new -> ob_bytes_object = PyBytes_FromStringAndSize ( NULL , size );
148+ if ( new -> ob_bytes_object == NULL ) {
149+ Py_DECREF ( new ) ;
150+ return NULL ;
152151 }
153- else {
154- alloc = size + 1 ;
155- new -> ob_bytes_object = PyBytes_FromStringAndSize (NULL , alloc );
156- if (new -> ob_bytes_object == NULL ) {
157- Py_DECREF (new );
158- return NULL ;
159- }
160- new -> ob_bytes = PyBytes_AS_STRING (new -> ob_bytes_object );
161- assert (new -> ob_bytes );
162- if (bytes != NULL && size > 0 ) {
163- memcpy (new -> ob_bytes , bytes , size );
164- }
165- new -> ob_bytes [size ] = '\0' ; /* Trailing null byte */
152+ new -> ob_bytes = PyBytes_AS_STRING (new -> ob_bytes_object );
153+ assert (new -> ob_bytes );
154+ if (bytes != NULL && size > 0 ) {
155+ memcpy (new -> ob_bytes , bytes , size );
166156 }
167157 Py_SET_SIZE (new , size );
168- new -> ob_alloc = alloc ;
158+ new -> ob_alloc = size ;
169159 new -> ob_start = new -> ob_bytes ;
170160 new -> ob_exports = 0 ;
171161
@@ -218,21 +208,17 @@ bytearray_resize_lock_held(PyObject *self, Py_ssize_t requested_size)
218208 return -1 ;
219209 }
220210
221- if (size + logical_offset + 1 <= alloc ) {
211+ if (size + logical_offset <= alloc ) {
222212 /* Current buffer is large enough to host the requested size,
223213 decide on a strategy. */
224214 if (size < alloc / 2 ) {
225215 /* Major downsize; resize down to exact size */
226- alloc = size + 1 ;
227-
228- /* If new size is 0; don't need to allocate one byte for null. */
229- if (size == 0 ) {
230- alloc = 0 ;
231- }
216+ alloc = size ;
232217 }
233218 else {
234219 /* Minor downsize; quick exit */
235220 Py_SET_SIZE (self , size );
221+ /* Add mid-buffer null; end provided by bytes. */
236222 PyByteArray_AS_STRING (self )[size ] = '\0' ; /* Trailing null */
237223 return 0 ;
238224 }
@@ -245,10 +231,11 @@ bytearray_resize_lock_held(PyObject *self, Py_ssize_t requested_size)
245231 }
246232 else {
247233 /* Major upsize; resize up to exact size. Upsize always means size > 0 */
248- alloc = size + 1 ;
234+ alloc = size ;
249235 }
250236 }
251- if (alloc > PY_SSIZE_T_MAX ) {
237+ // NOTE: offsetof() logic copied from PyBytesObject_SIZE in bytesobject.c
238+ if (alloc > PY_SSIZE_T_MAX - (offsetof(PyBytesObject , ob_sval ) + 1 )) {
252239 PyErr_NoMemory ();
253240 return -1 ;
254241 }
@@ -277,7 +264,10 @@ bytearray_resize_lock_held(PyObject *self, Py_ssize_t requested_size)
277264 obj -> ob_bytes = obj -> ob_start = PyBytes_AS_STRING (obj -> ob_bytes_object );
278265 Py_SET_SIZE (self , size );
279266 FT_ATOMIC_STORE_SSIZE_RELAXED (obj -> ob_alloc , alloc );
280- obj -> ob_bytes [size ] = '\0' ; /* Trailing null byte */
267+ if (alloc != size ) {
268+ /* Add mid-buffer null; end provided by bytes. */
269+ obj -> ob_bytes [size ] = '\0' ;
270+ }
281271
282272 return 0 ;
283273}
@@ -1550,15 +1540,11 @@ bytearray_take_bytes_impl(PyByteArrayObject *self, PyObject *n)
15501540 }
15511541
15521542 // Copy remaining bytes to a new bytes.
1553- PyObject * remaining = NULL ;
15541543 Py_ssize_t remaining_length = size - to_take ;
1555- if (remaining_length > 0 ) {
1556- // +1 to copy across the null which always ends a bytearray.
1557- remaining = PyBytes_FromStringAndSize (self -> ob_start + to_take ,
1558- remaining_length + 1 );
1559- if (remaining == NULL ) {
1560- return NULL ;
1561- }
1544+ PyObject * remaining = PyBytes_FromStringAndSize (self -> ob_start + to_take ,
1545+ remaining_length );
1546+ if (remaining == NULL ) {
1547+ return NULL ;
15621548 }
15631549
15641550 // If the bytes are offset inside the buffer must first align.
@@ -1575,17 +1561,9 @@ bytearray_take_bytes_impl(PyByteArrayObject *self, PyObject *n)
15751561 // Point the bytearray towards the buffer with the remaining data.
15761562 PyObject * result = self -> ob_bytes_object ;
15771563 self -> ob_bytes_object = remaining ;
1578- if (remaining ) {
1579- self -> ob_bytes = self -> ob_start = PyBytes_AS_STRING (self -> ob_bytes_object );
1580- Py_SET_SIZE (self , size - to_take );
1581- FT_ATOMIC_STORE_SSIZE_RELAXED (self -> ob_alloc , size - to_take + 1 );
1582- }
1583- else {
1584- self -> ob_bytes = self -> ob_start = NULL ;
1585- Py_SET_SIZE (self , 0 );
1586- FT_ATOMIC_STORE_SSIZE_RELAXED (self -> ob_alloc , 0 );
1587- }
1588-
1564+ self -> ob_bytes = self -> ob_start = PyBytes_AS_STRING (self -> ob_bytes_object );
1565+ Py_SET_SIZE (self , remaining_length );
1566+ FT_ATOMIC_STORE_SSIZE_RELAXED (self -> ob_alloc , remaining_length );
15891567 return result ;
15901568}
15911569
@@ -1967,11 +1945,6 @@ bytearray_insert_impl(PyByteArrayObject *self, Py_ssize_t index, int item)
19671945 Py_ssize_t n = Py_SIZE (self );
19681946 char * buf ;
19691947
1970- if (n == PY_SSIZE_T_MAX ) {
1971- PyErr_SetString (PyExc_OverflowError ,
1972- "cannot add more objects to bytearray" );
1973- return NULL ;
1974- }
19751948 if (bytearray_resize_lock_held ((PyObject * )self , n + 1 ) < 0 )
19761949 return NULL ;
19771950 buf = PyByteArray_AS_STRING (self );
@@ -2086,11 +2059,6 @@ bytearray_append_impl(PyByteArrayObject *self, int item)
20862059{
20872060 Py_ssize_t n = Py_SIZE (self );
20882061
2089- if (n == PY_SSIZE_T_MAX ) {
2090- PyErr_SetString (PyExc_OverflowError ,
2091- "cannot add more objects to bytearray" );
2092- return NULL ;
2093- }
20942062 if (bytearray_resize_lock_held ((PyObject * )self , n + 1 ) < 0 )
20952063 return NULL ;
20962064
0 commit comments