diff --git a/Include/cpython/bytearrayobject.h b/Include/cpython/bytearrayobject.h index f116271ad655b5..904e6ac658cc37 100644 --- a/Include/cpython/bytearrayobject.h +++ b/Include/cpython/bytearrayobject.h @@ -12,19 +12,13 @@ typedef struct { PyObject *ob_bytes_object; /* PyBytes for zero-copy bytes conversion */ } PyByteArrayObject; -PyAPI_DATA(char) _PyByteArray_empty_string[]; - /* Macros and static inline functions, trading safety for speed */ #define _PyByteArray_CAST(op) \ (assert(PyByteArray_Check(op)), _Py_CAST(PyByteArrayObject*, op)) static inline char* PyByteArray_AS_STRING(PyObject *op) { - PyByteArrayObject *self = _PyByteArray_CAST(op); - if (Py_SIZE(self)) { - return self->ob_start; - } - return _PyByteArray_empty_string; + return _PyByteArray_CAST(op)->ob_start; } #define PyByteArray_AS_STRING(self) PyByteArray_AS_STRING(_PyObject_CAST(self)) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 11cae2cb1c8b97..bd4a9548723eb8 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -17,9 +17,6 @@ class bytearray "PyByteArrayObject *" "&PyByteArray_Type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=5535b77c37a119e0]*/ -/* For PyByteArray_AS_STRING(). */ -char _PyByteArray_empty_string[] = ""; - /* Max number of bytes a bytearray can contain */ #define PyByteArray_SIZE_MAX ((Py_ssize_t)(PY_SSIZE_T_MAX - _PyBytesObject_SIZE)) @@ -46,6 +43,14 @@ _getbytevalue(PyObject* arg, int *value) return 1; } +static void +bytearray_reinit_from_bytes(PyByteArrayObject *self, Py_ssize_t size, + Py_ssize_t alloc) { + self->ob_bytes = self->ob_start = PyBytes_AS_STRING(self->ob_bytes_object); + Py_SET_SIZE(self, size); + FT_ATOMIC_STORE_SSIZE_RELAXED(self->ob_alloc, alloc); +} + static int bytearray_getbuffer_lock_held(PyObject *self, Py_buffer *view, int flags) { @@ -151,14 +156,10 @@ PyByteArray_FromStringAndSize(const char *bytes, Py_ssize_t size) Py_DECREF(new); return NULL; } - new->ob_bytes = PyBytes_AS_STRING(new->ob_bytes_object); - assert(new->ob_bytes); + bytearray_reinit_from_bytes(new, size, size); if (bytes != NULL && size > 0) { memcpy(new->ob_bytes, bytes, size); } - Py_SET_SIZE(new, size); - new->ob_alloc = size; - new->ob_start = new->ob_bytes; new->ob_exports = 0; return (PyObject *)new; @@ -247,26 +248,12 @@ bytearray_resize_lock_held(PyObject *self, Py_ssize_t requested_size) Py_MIN(requested_size, Py_SIZE(self))); } - if (obj->ob_bytes_object == NULL) { - obj->ob_bytes_object = PyBytes_FromStringAndSize(NULL, alloc); - } - else { - _PyBytes_Resize(&obj->ob_bytes_object, alloc); - } - - int ret; - if (obj->ob_bytes_object == NULL) { + int ret = _PyBytes_Resize(&obj->ob_bytes_object, alloc); + if (ret == -1) { obj->ob_bytes_object = Py_GetConstant(Py_CONSTANT_EMPTY_BYTES); size = alloc = 0; - ret = -1; } - else { - ret = 0; - } - - obj->ob_bytes = obj->ob_start = PyBytes_AS_STRING(obj->ob_bytes_object); - Py_SET_SIZE(self, size); - FT_ATOMIC_STORE_SSIZE_RELAXED(obj->ob_alloc, alloc); + bytearray_reinit_from_bytes(obj, size, alloc); if (alloc != size) { /* Add mid-buffer null; end provided by bytes. */ obj->ob_bytes[size] = '\0'; @@ -904,6 +891,13 @@ bytearray___init___impl(PyByteArrayObject *self, PyObject *arg, PyObject *it; PyObject *(*iternext)(PyObject *); + /* First __init__; set ob_bytes_object so ob_bytes is always non-null. */ + if (self->ob_bytes_object == NULL) { + self->ob_bytes_object = Py_GetConstant(Py_CONSTANT_EMPTY_BYTES); + bytearray_reinit_from_bytes(self, 0, 0); + self->ob_exports = 0; + } + if (Py_SIZE(self) != 0) { /* Empty previous contents (yes, do this first of all!) */ if (PyByteArray_Resize((PyObject *)self, 0) < 0) @@ -1564,9 +1558,7 @@ bytearray_take_bytes_impl(PyByteArrayObject *self, PyObject *n) // Point the bytearray towards the buffer with the remaining data. PyObject *result = self->ob_bytes_object; self->ob_bytes_object = remaining; - self->ob_bytes = self->ob_start = PyBytes_AS_STRING(self->ob_bytes_object); - Py_SET_SIZE(self, remaining_length); - FT_ATOMIC_STORE_SSIZE_RELAXED(self->ob_alloc, remaining_length); + bytearray_reinit_from_bytes(self, remaining_length, remaining_length); return result; } diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index c3b13d69f0de8e..1e4d87d93d9273 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -324,7 +324,6 @@ Modules/pyexpat.c - error_info_of - Modules/pyexpat.c - handler_info - Modules/termios.c - termios_constants - Modules/timemodule.c init_timezone YEAR - -Objects/bytearrayobject.c - _PyByteArray_empty_string - Objects/complexobject.c - c_1 - Objects/exceptions.c - static_exceptions - Objects/genobject.c - ASYNC_GEN_IGNORED_EXIT_MSG -