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

Code before:
        }
        if (cast_info.func == NULL) {
            /* We ensure memory doesn't overlap, so can use memcpy */
            memcpy(ret_data, PyArray_MultiIter_DATA(multi, mi), elsize);
        }
        else {
            char *args[2] = {PyArray_MultiIter_DATA(multi, mi), ret_data};
            if (cast_info.func(&cast_info.context, args, &one,
                                transfer_strides, cast_info.auxdata) < 0) {
                goto fail;
            }
        }
        ret_data += elsize;
        PyArray_MultiIter_NEXT(multi);
    }

    NPY_cast_info_xfree(&cast_info);
    Py_DECREF(multi);
    for (i = 0; i < n; i++) {
        Py_XDECREF(mps[i]);
    }
    Py_DECREF(ap);
    PyDataMem_FREE(mps);
    if (out != NULL && out != obj) {
        Py_INCREF(out);
        PyArray_CopyAnyInto(out, obj);
        Py_DECREF(obj);
        obj = out;
    }
    return (PyObject *)obj;

 fail:
    NPY_cast_info_xfree(&cast_info);
    Py_XDECREF(multi);
    for (i = 0; i < n; i++) {
        Py_XDECREF(mps[i]);
    }
    Py_XDECREF(ap);
    PyDataMem_FREE(mps);
    PyArray_DiscardWritebackIfCopy(obj);
    Py_XDECREF(obj);
    return NULL;
}

/*
 * These algorithms use special sorting.  They are not called unless the
 * underlying sort function for the type is available.  Note that axis is
 * already valid. The sort functions require 1-d contiguous and well-behaved
 * data.  Therefore, a copy will be made of the data if needed before handing
 * it to the sorting routine.  An iterator is constructed and adjusted to walk
 * over all but the desired sorting axis.

Review comment (bug):
This can fail so you need to check the failure case. The same bug existed in the code you're updating - `ResolveWritebackIfCopy` also returns -1 on failure.

Code after:
    npy_intp transfer_strides[2] = {elsize, elsize};
    npy_intp one = 1;
    NPY_ARRAYMETHOD_FLAGS transfer_flags = 0;
    if (PyDataType_REFCHK(dtype)) {
        int is_aligned = IsUintAligned(obj);
        PyArray_Descr *obj_dtype = PyArray_DESCR(obj);
        PyArray_GetDTypeTransferFunction(
                    is_aligned,
                    dtype->elsize,
                    obj_dtype->elsize,
                    dtype,
                    obj_dtype, 0, &cast_info,
                    &transfer_flags);
    }

    while (PyArray_MultiIter_NOTDONE(multi)) {
        mi = *((npy_intp *)PyArray_MultiIter_DATA(multi, n));
        if (mi < 0 || mi >= n) {
            switch(clipmode) {
            case NPY_RAISE:
                PyErr_SetString(PyExc_ValueError,
                        "invalid entry in choice "\
                        "array");
                goto fail;
            case NPY_WRAP:
                if (mi < 0) {
                    while (mi < 0) {
                        mi += n;
                    }
                }
                else {
                    while (mi >= n) {
                        mi -= n;
                    }
                }
                break;
            case NPY_CLIP:
                if (mi < 0) {
                    mi = 0;
                }
                else if (mi >= n) {
                    mi = n - 1;
                }
                break;
            }
        }
        if (cast_info.func == NULL) {
            /* We ensure memory doesn't overlap, so can use memcpy */
            memcpy(ret_data, PyArray_MultiIter_DATA(multi, mi), elsize);
        }
        else {