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

Code before:
                                 &from_buffer_func) == -1) {
        Py_DECREF(rev_perm);
        Py_XDECREF(transposed_array);
        Py_DECREF(buffer);
        return NULL;
    }

    PyObject *shape = NULL;
    if (order == 'K') {
        shape = PyArray_IntTupleFromIntp(
                PyArray_NDIM((PyArrayObject *)transposed_array),
                PyArray_SHAPE((PyArrayObject *)transposed_array));
    }
    else {
        shape = PyArray_IntTupleFromIntp(PyArray_NDIM(self),
                                         PyArray_SHAPE(self));
    }
    Py_XDECREF(transposed_array);
    if(shape == NULL) {
        Py_DECREF(rev_perm);
        Py_DECREF(buffer);
        return NULL;
    }
    return Py_BuildValue("N(NONNN)", from_buffer_func, buffer,
                         (PyObject *)descr, shape,
                         PyUnicode_FromStringAndSize(&order, 1), rev_perm);
}

static PyObject *
array_reduce_ex(PyArrayObject *self, PyObject *args)
{
    int protocol;
    PyArray_Descr *descr = NULL;

    if (!PyArg_ParseTuple(args, "i", &protocol)) {
        return NULL;
    }

    descr = PyArray_DESCR(self);
    if ((protocol < 5) ||
        PyDataType_FLAGCHK(descr, NPY_ITEM_HASOBJECT) ||
        (PyType_IsSubtype(((PyObject*)self)->ob_type, &PyArray_Type) &&
         ((PyObject*)self)->ob_type != &PyArray_Type) ||
        descr->elsize == 0) {
        /* The PickleBuffer class from version 5 of the pickle protocol
         * can only be used for arrays backed by a contiguous data buffer.
         * For all other cases we fallback to the generic array_reduce
         * method that involves using a temporary bytes allocation. */
        return array_reduce_ex_regular(self, protocol);
    }
    else {

Review comment (suggestion):
I.e. we'll need to branches here, one for C/F when `rev_perm` is NULL` and one for the others.

You may also need an `XDECREF` for `rev_perm` in a few places.

Code after:
                             PyUnicode_FromStringAndSize(&order, 1), rev_perm);
    }
    else {
        return Py_BuildValue("N(NONN)", from_buffer_func, buffer,
                             (PyObject *)descr, shape,
                             PyUnicode_FromStringAndSize(&order, 1));
    }
}

static PyObject *
array_reduce_ex(PyArrayObject *self, PyObject *args)
{
    int protocol;
    PyArray_Descr *descr = NULL;

    if (!PyArg_ParseTuple(args, "i", &protocol)) {
        return NULL;
    }

    descr = PyArray_DESCR(self);
    if ((protocol < 5) ||
        PyDataType_FLAGCHK(descr, NPY_ITEM_HASOBJECT) ||
        (PyType_IsSubtype(((PyObject*)self)->ob_type, &PyArray_Type) &&
         ((PyObject*)self)->ob_type != &PyArray_Type) ||
        descr->elsize == 0) {
        /* The PickleBuffer class from version 5 of the pickle protocol
         * can only be used for arrays backed by a contiguous data buffer.
         * For all other cases we fallback to the generic array_reduce
         * method that involves using a temporary bytes allocation. */
        return array_reduce_ex_regular(self, protocol);
    }
    else {
        /* The func will check internally
         * if the array isn't backed by a contiguous data buffer or
         * if the array refuses to export a buffer
         * In either case, fall back to `array_reduce_ex_regular`
         */
        return array_reduce_ex_picklebuffer(self, protocol);
    }
}

static PyObject *
array_setstate(PyArrayObject *self, PyObject *args)
{
    PyObject *shape;
    PyArray_Descr *typecode;
    int version = 1;
    int is_f_order;
    PyObject *rawdata = NULL;
    char *datastr;
    Py_ssize_t len;