From 039612da5dd9d39f5986bc0cdb3444a43b4b4370 Mon Sep 17 00:00:00 2001
From: mattip <matti.picus@gmail.com>
Date: Tue, 1 Feb 2022 11:53:11 +0200
Subject: [PATCH 01/14] ENH: review return value from PyArray_DescrNew* calls

---
 numpy/core/src/multiarray/arrayobject.c     |    3 ++
 numpy/core/src/multiarray/buffer.c          |    6 +++++
 numpy/core/src/multiarray/ctors.c           |   25 ++++++++++++++++++++++-
 numpy/core/src/multiarray/descriptor.c      |   30 +++++++++++++++++++++-------
 numpy/core/src/multiarray/getset.c          |   13 +++++++-----
 numpy/core/src/multiarray/methods.c         |   20 ++++++++++++++++++
 numpy/core/src/multiarray/nditer_constr.c   |   11 ++++------
 numpy/core/src/multiarray/scalarapi.c       |    3 ++
 numpy/core/src/multiarray/scalartypes.c.src |   10 ++++++---
 9 files changed, 99 insertions(+), 22 deletions(-)

--- a/numpy/core/src/multiarray/arrayobject.c
+++ b/numpy/core/src/multiarray/arrayobject.c
@@ -1105,6 +1105,9 @@ _strings_richcompare(PyArrayObject *self
         if (PyArray_TYPE(self) == NPY_STRING &&
                 PyArray_DESCR(other)->type_num == NPY_UNICODE) {
             PyArray_Descr* unicode = PyArray_DescrNew(PyArray_DESCR(other));
+            if (unicode == NULL) {
+                return NULL;
+            }
             unicode->elsize = PyArray_DESCR(self)->elsize << 2;
             new = PyArray_FromAny((PyObject *)self, unicode,
                                   0, 0, 0, NULL);
--- a/numpy/core/src/multiarray/buffer.c
+++ b/numpy/core/src/multiarray/buffer.c
@@ -944,12 +944,18 @@ _descriptor_from_pep3118_format_fast(cha
     }
 
     descr = PyArray_DescrFromType(type_num);
+    if (descr == NULL) {
+        return 0;
+    }
     if (byte_order == '=') {
         *result = (PyObject*)descr;
     }
     else {
         *result = (PyObject*)PyArray_DescrNewByteorder(descr, byte_order);
         Py_DECREF(descr);
+        if (result == NULL) {
+            return 0;
+        }
     }
 
     return 1;
--- a/numpy/core/src/multiarray/ctors.c
+++ b/numpy/core/src/multiarray/ctors.c
@@ -906,6 +906,11 @@ PyArray_NewFromDescr_int(PyTypeObject *s
     int i, is_empty;
     npy_intp nbytes;
 
+    if (descr == NULL) {
+        PyErr_Format(PyExc_ValueError,
+                "NULL descr in call to PyArray_NewFromDescr*");
+        return NULL;
+    }
     if ((unsigned int)nd > (unsigned int)NPY_MAXDIMS) {
         PyErr_Format(PyExc_ValueError,
                      "number of dimensions must be within [0, %d]",
@@ -1263,6 +1268,9 @@ PyArray_New(PyTypeObject *subtype, int n
             return NULL;
         }
         PyArray_DESCR_REPLACE(descr);
+        if (descr == NULL) {
+            return NULL;
+        }
         descr->elsize = itemsize;
     }
     new = PyArray_NewFromDescr(subtype, descr, nd, dims, strides,
@@ -1312,6 +1320,9 @@ _array_from_buffer_3118(PyObject *obj, P
     }
     else {
         descr = PyArray_DescrNewFromType(NPY_STRING);
+        if (descr == NULL) {
+            return NULL;
+        }
         descr->elsize = view->itemsize;
     }
 
@@ -3405,6 +3416,10 @@ PyArray_FromFile(FILE *fp, PyArray_Descr
     PyArrayObject *ret;
     size_t nread = 0;
 
+    if (dtype == NULL) {
+        return NULL;
+    }
+
     if (PyDataType_REFCHK(dtype)) {
         PyErr_SetString(PyExc_ValueError,
                 "Cannot read into object array");
@@ -3464,6 +3479,9 @@ PyArray_FromBuffer(PyObject *buf, PyArra
     int itemsize;
     int writeable = 1;
 
+    if (type == NULL) {
+        return NULL;
+    }
 
     if (PyDataType_REFCHK(type)) {
         PyErr_SetString(PyExc_ValueError,
@@ -3681,11 +3699,16 @@ NPY_NO_EXPORT PyObject *
 PyArray_FromIter(PyObject *obj, PyArray_Descr *dtype, npy_intp count)
 {
     PyObject *value;
-    PyObject *iter = PyObject_GetIter(obj);
+    PyObject *iter = NULL;
     PyArrayObject *ret = NULL;
     npy_intp i, elsize, elcount;
     char *item, *new_data;
 
+    if (dtype == NULL) {
+        return NULL;
+    }
+
+    iter = PyObject_GetIter(obj);
     if (iter == NULL) {
         goto done;
     }
--- a/numpy/core/src/multiarray/descriptor.c
+++ b/numpy/core/src/multiarray/descriptor.c
@@ -1325,6 +1325,9 @@ PyArray_DescrNewFromType(int type_num)
     PyArray_Descr *new;
 
     old = PyArray_DescrFromType(type_num);
+    if (old == NULL) {
+        return NULL;
+    }
     new = PyArray_DescrNew(old);
     Py_DECREF(old);
     return new;
@@ -2260,7 +2263,7 @@ arraydescr_new(PyTypeObject *NPY_UNUSED(
                 PyObject *args, PyObject *kwds)
 {
     PyObject *odescr, *metadata=NULL;
-    PyArray_Descr *descr, *conv;
+    PyArray_Descr *conv;
     npy_bool align = NPY_FALSE;
     npy_bool copy = NPY_FALSE;
     npy_bool copied = NPY_FALSE;
@@ -2286,9 +2289,10 @@ arraydescr_new(PyTypeObject *NPY_UNUSED(
 
     /* Get a new copy of it unless it's already a copy */
     if (copy && conv->fields == Py_None) {
-        descr = PyArray_DescrNew(conv);
-        Py_DECREF(conv);
-        conv = descr;
+        PyArray_DESCR_REPLACE(conv);
+        if (conv == NULL) {
+            return NULL;
+        }
         copied = NPY_TRUE;
     }
 
@@ -2298,10 +2302,11 @@ arraydescr_new(PyTypeObject *NPY_UNUSED(
          * underlying dictionary
          */
         if (!copied) {
+            PyArray_DESCR_REPLACE(conv);
+            if (conv == NULL) {
+                return NULL;
+            }
             copied = NPY_TRUE;
-            descr = PyArray_DescrNew(conv);
-            Py_DECREF(conv);
-            conv = descr;
         }
         if ((conv->metadata != NULL)) {
             /*
@@ -3014,6 +3019,9 @@ PyArray_DescrNewByteorder(PyArray_Descr
     char endian;
 
     new = PyArray_DescrNew(self);
+    if (new == NULL) {
+        return NULL;
+    }
     endian = new->byteorder;
     if (endian != NPY_IGNORE) {
         if (newendian == NPY_SWAP) {
@@ -3040,6 +3048,10 @@ PyArray_DescrNewByteorder(PyArray_Descr
         int len, i;
 
         newfields = PyDict_New();
+        if (newfields == NULL) {
+            Py_DECREF(new);
+            return NULL;
+        }
         /* make new dictionary with replaced PyArray_Descr Objects */
         while (PyDict_Next(self->fields, &pos, &key, &value)) {
             if NPY_TITLE_KEY(key, value) {
@@ -3076,6 +3088,10 @@ PyArray_DescrNewByteorder(PyArray_Descr
         Py_DECREF(new->subarray->base);
         new->subarray->base = PyArray_DescrNewByteorder(
                 self->subarray->base, newendian);
+        if (new->subarray->base == NULL) {
+            Py_DECREF(new);
+            return NULL;
+        }
     }
     return new;
 }
--- a/numpy/core/src/multiarray/getset.c
+++ b/numpy/core/src/multiarray/getset.c
@@ -683,15 +683,18 @@ _get_part(PyArrayObject *self, int imag)
 
     }
     type = PyArray_DescrFromType(float_type_num);
+    if (type == NULL) {
+        return NULL;
+    }
 
     offset = (imag ? type->elsize : 0);
 
     if (!PyArray_ISNBO(PyArray_DESCR(self)->byteorder)) {
-        PyArray_Descr *new;
-        new = PyArray_DescrNew(type);
-        new->byteorder = PyArray_DESCR(self)->byteorder;
-        Py_DECREF(type);
-        type = new;
+        Py_SETREF(type, PyArray_DescrNew(type));
+        if (type == NULL) {
+            return NULL;
+        }
+        type->byteorder = PyArray_DESCR(self)->byteorder;
     }
     ret = (PyArrayObject *)
         PyArray_NewFromDescr(Py_TYPE(self),
--- a/numpy/core/src/multiarray/methods.c
+++ b/numpy/core/src/multiarray/methods.c
@@ -1199,7 +1199,15 @@ array_sort(PyArrayObject *self, PyObject
         if (new_name == NULL) {
             return NULL;
         }
+        if (newd == NULL) {
+            Py_DECREF(new_name);
+            return NULL;
+        }
         newd = PyArray_DescrNew(saved);
+        if (newd == NULL) {
+            Py_DECREF(new_name);
+            return NULL;
+        }
         Py_DECREF(newd->names);
         newd->names = new_name;
         ((PyArrayObject_fields *)self)->descr = newd;
@@ -1261,6 +1269,9 @@ array_partition(PyArrayObject *self, PyO
             return NULL;
         }
         newd = PyArray_DescrNew(saved);
+        if (newd == NULL) {
+            return NULL;
+        }
         Py_DECREF(newd->names);
         newd->names = new_name;
         ((PyArrayObject_fields *)self)->descr = newd;
@@ -1319,6 +1330,7 @@ array_argsort(PyArrayObject *self, PyObj
                                        "OO", saved, order);
         Py_DECREF(_numpy_internal);
         if (new_name == NULL) {
+            Py_DECREF(new_name);
             return NULL;
         }
         newd = PyArray_DescrNew(saved);
@@ -1376,6 +1388,10 @@ array_argpartition(PyArrayObject *self,
             return NULL;
         }
         newd = PyArray_DescrNew(saved);
+        if (newd == NULL) {
+            Py_DECREF(new_name);
+            return NULL;
+        }
         newd->names = new_name;
         ((PyArrayObject_fields *)self)->descr = newd;
     }
@@ -1833,6 +1849,10 @@ array_setstate(PyArrayObject *self, PyOb
                 }
                 else {
                     fa->descr = PyArray_DescrNew(typecode);
+                    if (fa->descr == NULL) {
+                        Py_DECREF(rawdata);
+                        return NULL;
+                    }
                     if (PyArray_DESCR(self)->byteorder == NPY_BIG) {
                         PyArray_DESCR(self)->byteorder = NPY_LITTLE;
                     }
--- a/numpy/core/src/multiarray/nditer_constr.c
+++ b/numpy/core/src/multiarray/nditer_constr.c
@@ -1101,13 +1101,12 @@ npyiter_prepare_one_operand(PyArrayObjec
         if (op_flags & NPY_ITER_NBO) {
             /* Check byte order */
             if (!PyArray_ISNBO((*op_dtype)->byteorder)) {
-                PyArray_Descr *nbo_dtype;
-
                 /* Replace with a new descr which is in native byte order */
-                nbo_dtype = PyArray_DescrNewByteorder(*op_dtype, NPY_NATIVE);
-                Py_DECREF(*op_dtype);
-                *op_dtype = nbo_dtype;
-
+                Py_SETREF(*op_dtype,
+                          PyArray_DescrNewByteorder(*op_dtype, NPY_NATIVE));
+                if (*op_dtype == NULL) {
+                    return 0;
+                }
                 NPY_IT_DBG_PRINT("Iterator: Setting NPY_OP_ITFLAG_CAST "
                                     "because of NPY_ITER_NBO\n");
                 /* Indicate that byte order or alignment needs fixing */
--- a/numpy/core/src/multiarray/scalarapi.c
+++ b/numpy/core/src/multiarray/scalarapi.c
@@ -569,6 +569,9 @@ PyArray_DescrFromScalar(PyObject *sc)
     descr = PyArray_DescrFromTypeObject((PyObject *)Py_TYPE(sc));
     if (descr->elsize == 0) {
         PyArray_DESCR_REPLACE(descr);
+        if (descr == NULL) {
+            return NULL;
+        }
         type_num = descr->type_num;
         if (type_num == NPY_STRING) {
             descr->elsize = PyString_GET_SIZE(sc);
--- a/numpy/core/src/multiarray/scalartypes.c.src
+++ b/numpy/core/src/multiarray/scalartypes.c.src
@@ -2933,12 +2933,16 @@ void_arrtype_new(PyTypeObject *type, PyO
         }
         ((PyVoidScalarObject *)ret)->obval = destptr;
         Py_SIZE((PyVoidScalarObject *)ret) = (int) memu;
-        ((PyVoidScalarObject *)ret)->descr =
-            PyArray_DescrNewFromType(NPY_VOID);
-        ((PyVoidScalarObject *)ret)->descr->elsize = (int) memu;
         ((PyVoidScalarObject *)ret)->flags = NPY_ARRAY_BEHAVED |
                                              NPY_ARRAY_OWNDATA;
         ((PyVoidScalarObject *)ret)->base = NULL;
+        ((PyVoidScalarObject *)ret)->descr =
+            PyArray_DescrNewFromType(NPY_VOID);
+        if (((PyVoidScalarObject *)ret)->descr == NULL) {
+            Py_DECREF(ret);
+            return NULL;
+        }
+        ((PyVoidScalarObject *)ret)->descr->elsize = (int) memu;
         memset(destptr, '\0', (size_t) memu);
         return ret;
     }
