Repository: numpy/numpy
File: numpy/_core/src/multiarray/methods.c (C)

Code before:

        if (!PyBytes_Check(rawdata)) {
            PyErr_SetString(PyExc_TypeError,
                            "pickle not returning string");
            Py_DECREF(rawdata);
            return NULL;
        }

        if (PyBytes_AsStringAndSize(rawdata, &datastr, &len) < 0) {
            Py_DECREF(rawdata);
            return NULL;
        }

        if (len != nbytes) {
            PyErr_SetString(PyExc_ValueError,
                    "buffer size does not match array size");
            Py_DECREF(rawdata);
            return NULL;
        }
    }
    /*
     * Get rid of everything on self, and then populate with pickle data.
     */
    if (dealloc_all_but_self(self) < 0) {
        return NULL;
    }
    fa->descr = typecode;
    fa->flags = NPY_ARRAY_DEFAULT;

    fa->nd = nd;

    if (nd > 0) {
        fa->dimensions = npy_alloc_cache_dim(2 * nd);
        if (fa->dimensions == NULL) {
            return PyErr_NoMemory();
        }
        fa->strides = PyArray_DIMS(self) + nd;
        if (nd) {
            memcpy(PyArray_DIMS(self), dimensions, sizeof(npy_intp)*nd);
        }
        _array_fill_strides(PyArray_STRIDES(self), dimensions, nd,
                               PyArray_ITEMSIZE(self),
                               (is_f_order ? NPY_ARRAY_F_CONTIGUOUS :
                                             NPY_ARRAY_C_CONTIGUOUS),
                               &(fa->flags));
    }

    if (!PyDataType_FLAGCHK(typecode, NPY_LIST_PICKLE)) {
        int swap = PyArray_ISBYTESWAPPED(self);
        /* Bytes should always be considered immutable, but we just grab the
         * pointer if they are large, to save memory. */

Review comment (bug):
OK, we assume that the only place where `__setitem__` is called is unpickling, which means that the _only_ thing that can happen to `self` on error return is that it is deleted (at this point, the array is completely broken!).

Of course, this can't actually fail in that context, because all of the paths that _might_ fail are actually unreachable.

Code after:
        }

        if (!PyBytes_Check(rawdata)) {
            PyErr_SetString(PyExc_TypeError,
                            "pickle not returning string");
            Py_DECREF(rawdata);
            return NULL;
        }

        if (PyBytes_AsStringAndSize(rawdata, &datastr, &len) < 0) {
            Py_DECREF(rawdata);
            return NULL;
        }

        if (len != nbytes) {
            PyErr_SetString(PyExc_ValueError,
                    "buffer size does not match array size");
            Py_DECREF(rawdata);
            return NULL;
        }
    }
    /*
     * Get rid of everything on self, and then populate with pickle data.
     */
    if (clear_array_attributes(self) < 0) {
        return NULL;
    }
    fa->descr = typecode;
    fa->flags = NPY_ARRAY_DEFAULT;

    fa->nd = nd;

    if (nd > 0) {
        fa->dimensions = npy_alloc_cache_dim(2 * nd);
        if (fa->dimensions == NULL) {
            return PyErr_NoMemory();
        }
        fa->strides = PyArray_DIMS(self) + nd;
        if (nd) {
            memcpy(PyArray_DIMS(self), dimensions, sizeof(npy_intp)*nd);
        }
        _array_fill_strides(PyArray_STRIDES(self), dimensions, nd,
                               PyArray_ITEMSIZE(self),
                               (is_f_order ? NPY_ARRAY_F_CONTIGUOUS :
                                             NPY_ARRAY_C_CONTIGUOUS),
                               &(fa->flags));
    }

    if (!PyDataType_FLAGCHK(typecode, NPY_LIST_PICKLE)) {
        int swap = PyArray_ISBYTESWAPPED(self);
        /* Bytes should always be considered immutable, but we just grab the