summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/Modules/arraymodule.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tools/python3/Modules/arraymodule.c')
-rw-r--r--contrib/tools/python3/Modules/arraymodule.c65
1 files changed, 64 insertions, 1 deletions
diff --git a/contrib/tools/python3/Modules/arraymodule.c b/contrib/tools/python3/Modules/arraymodule.c
index 1f800af6ad5..4c7cc4d47c0 100644
--- a/contrib/tools/python3/Modules/arraymodule.c
+++ b/contrib/tools/python3/Modules/arraymodule.c
@@ -202,6 +202,33 @@ Note that the basic Get and Set functions do NOT check that the index is
in bounds; that's the responsibility of the caller.
****************************************************************************/
+/* Macro to check array buffer validity and bounds after calling
+ user-defined methods (like __index__ or __float__) that might modify
+ the array during the call.
+*/
+#define CHECK_ARRAY_BOUNDS(OP, IDX) \
+ do { \
+ if ((IDX) >= 0 && ((OP)->ob_item == NULL || \
+ (IDX) >= Py_SIZE((OP)))) { \
+ PyErr_SetString(PyExc_IndexError, \
+ "array assignment index out of range"); \
+ return -1; \
+ } \
+ } while (0)
+
+#define CHECK_ARRAY_BOUNDS_WITH_CLEANUP(OP, IDX, VAL, CLEANUP) \
+ do { \
+ if ((IDX) >= 0 && ((OP)->ob_item == NULL || \
+ (IDX) >= Py_SIZE((OP)))) { \
+ PyErr_SetString(PyExc_IndexError, \
+ "array assignment index out of range"); \
+ if (CLEANUP) { \
+ Py_DECREF(VAL); \
+ } \
+ return -1; \
+ } \
+ } while (0)
+
static PyObject *
b_getitem(arrayobject *ap, Py_ssize_t i)
{
@@ -218,7 +245,10 @@ b_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
the overflow checking */
if (!PyArg_Parse(v, "h;array item must be integer", &x))
return -1;
- else if (x < -128) {
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
+ if (x < -128) {
PyErr_SetString(PyExc_OverflowError,
"signed char is less than minimum");
return -1;
@@ -247,6 +277,9 @@ BB_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
/* 'B' == unsigned char, maps to PyArg_Parse's 'b' formatter */
if (!PyArg_Parse(v, "b;array item must be integer", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((unsigned char *)ap->ob_item)[i] = x;
return 0;
@@ -323,6 +356,9 @@ h_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
/* 'h' == signed short, maps to PyArg_Parse's 'h' formatter */
if (!PyArg_Parse(v, "h;array item must be integer", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((short *)ap->ob_item)[i] = x;
return 0;
@@ -352,6 +388,9 @@ HH_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
"unsigned short is greater than maximum");
return -1;
}
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((short *)ap->ob_item)[i] = (short)x;
return 0;
@@ -370,6 +409,9 @@ i_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
/* 'i' == signed int, maps to PyArg_Parse's 'i' formatter */
if (!PyArg_Parse(v, "i;array item must be integer", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((int *)ap->ob_item)[i] = x;
return 0;
@@ -410,6 +452,9 @@ II_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
}
return -1;
}
+
+ CHECK_ARRAY_BOUNDS_WITH_CLEANUP(ap, i, v, do_decref);
+
if (i >= 0)
((unsigned int *)ap->ob_item)[i] = (unsigned int)x;
@@ -431,6 +476,9 @@ l_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
long x;
if (!PyArg_Parse(v, "l;array item must be integer", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((long *)ap->ob_item)[i] = x;
return 0;
@@ -462,6 +510,9 @@ LL_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
}
return -1;
}
+
+ CHECK_ARRAY_BOUNDS_WITH_CLEANUP(ap, i, v, do_decref);
+
if (i >= 0)
((unsigned long *)ap->ob_item)[i] = x;
@@ -483,6 +534,9 @@ q_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
long long x;
if (!PyArg_Parse(v, "L;array item must be integer", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((long long *)ap->ob_item)[i] = x;
return 0;
@@ -515,6 +569,9 @@ QQ_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
}
return -1;
}
+
+ CHECK_ARRAY_BOUNDS_WITH_CLEANUP(ap, i, v, do_decref);
+
if (i >= 0)
((unsigned long long *)ap->ob_item)[i] = x;
@@ -536,6 +593,9 @@ f_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
float x;
if (!PyArg_Parse(v, "f;array item must be float", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((float *)ap->ob_item)[i] = x;
return 0;
@@ -553,6 +613,9 @@ d_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
double x;
if (!PyArg_Parse(v, "d;array item must be float", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((double *)ap->ob_item)[i] = x;
return 0;