File CVE-2021-41495-retval-PyArray_DescrNew.patch of Package python-numpy.24870
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/arrayobject.h | 25 +++++++++++++++++++++++
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 | 21 +++++++++++++++++++
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, 119 insertions(+), 22 deletions(-)
--- a/numpy/core/src/multiarray/arrayobject.c
+++ b/numpy/core/src/multiarray/arrayobject.c
@@ -1073,6 +1073,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/arrayobject.h
+++ b/numpy/core/src/multiarray/arrayobject.h
@@ -5,6 +5,31 @@
#error You should not include this
#endif
+/* For Python earlier than 2.7.12. */
+#ifndef Py_SETREF
+/* Safely decref `op` and set `op` to `op2`.
+ *
+ * As in case of Py_CLEAR "the obvious" code can be deadly:
+ *
+ * Py_XDECREF(op);
+ * op = op2;
+ *
+ * The safe way is:
+ *
+ * Py_SETREF(op, op2);
+ *
+ * That arranges to set `op` to `op2` _before_ decref'ing, so that any code
+ * triggered as a side-effect of `op` getting torn down no longer believes
+ * `op` points to a valid object.
+ */
+#define Py_SETREF(op, op2) \
+ do { \
+ PyObject *_py_tmp = (PyObject *)(op); \
+ (op) = (op2); \
+ Py_XDECREF(_py_tmp); \
+ } while (0)
+#endif
+
NPY_NO_EXPORT PyObject *
_strings_richcompare(PyArrayObject *self, PyArrayObject *other, int cmp_op,
int rstrip);
--- a/numpy/core/src/multiarray/ctors.c
+++ b/numpy/core/src/multiarray/ctors.c
@@ -854,6 +854,11 @@ PyArray_NewFromDescr_int(PyTypeObject *s
npy_intp largest;
npy_intp size;
+ 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]",
@@ -1208,6 +1213,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,
@@ -1257,6 +1265,9 @@ _array_from_buffer_3118(PyObject *obj, P
}
else {
descr = PyArray_DescrNewFromType(NPY_STRING);
+ if (descr == NULL) {
+ return NULL;
+ }
descr->elsize = view->itemsize;
}
@@ -3234,6 +3245,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");
@@ -3291,6 +3306,9 @@ PyArray_FromBuffer(PyObject *buf, PyArra
int itemsize;
int writeable = 1;
+ if (type == NULL) {
+ return NULL;
+ }
if (PyDataType_REFCHK(type)) {
PyErr_SetString(PyExc_ValueError,
@@ -3508,11 +3526,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
@@ -1144,6 +1144,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;
@@ -2004,7 +2007,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;
@@ -2030,9 +2033,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;
}
@@ -2042,10 +2046,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)) {
/*
@@ -2673,6 +2678,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) {
@@ -2699,6 +2707,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) {
@@ -2735,6 +2747,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
@@ -656,15 +656,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
@@ -1162,6 +1162,10 @@ array_sort(PyArrayObject *self, PyObject
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;
@@ -1223,7 +1227,15 @@ array_partition(PyArrayObject *self, PyO
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;
@@ -1337,9 +1349,14 @@ array_argpartition(PyArrayObject *self,
"OO", saved, order);
Py_DECREF(_numpy_internal);
if (new_name == NULL) {
+ Py_DECREF(new_name);
return NULL;
}
newd = PyArray_DescrNew(saved);
+ if (newd == NULL) {
+ Py_DECREF(new_name);
+ return NULL;
+ }
newd->names = new_name;
((PyArrayObject_fields *)self)->descr = newd;
}
@@ -1754,6 +1771,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
@@ -1088,13 +1088,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
@@ -554,6 +554,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
@@ -2849,12 +2849,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;
}