@@ -202,6 +202,33 @@ Note that the basic Get and Set functions do NOT check that the index is
202202in bounds; that's the responsibility of the caller.
203203****************************************************************************/
204204
205+ /* Macro to check array buffer validity and bounds after calling
206+ user-defined methods (like __index__ or __float__) that might modify
207+ the array during the call.
208+ */
209+ #define CHECK_ARRAY_BOUNDS (OP , IDX ) \
210+ do { \
211+ if ((IDX) >= 0 && ((OP)->ob_item == NULL || \
212+ (IDX) >= Py_SIZE((OP)))) { \
213+ PyErr_SetString(PyExc_IndexError, \
214+ "array assignment index out of range"); \
215+ return -1; \
216+ } \
217+ } while (0)
218+
219+ #define CHECK_ARRAY_BOUNDS_WITH_CLEANUP (OP , IDX , VAL , CLEANUP ) \
220+ do { \
221+ if ((IDX) >= 0 && ((OP)->ob_item == NULL || \
222+ (IDX) >= Py_SIZE((OP)))) { \
223+ PyErr_SetString(PyExc_IndexError, \
224+ "array assignment index out of range"); \
225+ if (CLEANUP) { \
226+ Py_DECREF(VAL); \
227+ } \
228+ return -1; \
229+ } \
230+ } while (0)
231+
205232static PyObject *
206233b_getitem (arrayobject * ap , Py_ssize_t i )
207234{
@@ -218,7 +245,10 @@ b_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
218245 the overflow checking */
219246 if (!PyArg_Parse (v , "h;array item must be integer" , & x ))
220247 return -1 ;
221- else if (x < -128 ) {
248+
249+ CHECK_ARRAY_BOUNDS (ap , i );
250+
251+ if (x < -128 ) {
222252 PyErr_SetString (PyExc_OverflowError ,
223253 "signed char is less than minimum" );
224254 return -1 ;
@@ -247,6 +277,9 @@ BB_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
247277 /* 'B' == unsigned char, maps to PyArg_Parse's 'b' formatter */
248278 if (!PyArg_Parse (v , "b;array item must be integer" , & x ))
249279 return -1 ;
280+
281+ CHECK_ARRAY_BOUNDS (ap , i );
282+
250283 if (i >= 0 )
251284 ((unsigned char * )ap -> ob_item )[i ] = x ;
252285 return 0 ;
@@ -323,6 +356,9 @@ h_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
323356 /* 'h' == signed short, maps to PyArg_Parse's 'h' formatter */
324357 if (!PyArg_Parse (v , "h;array item must be integer" , & x ))
325358 return -1 ;
359+
360+ CHECK_ARRAY_BOUNDS (ap , i );
361+
326362 if (i >= 0 )
327363 ((short * )ap -> ob_item )[i ] = x ;
328364 return 0 ;
@@ -352,6 +388,9 @@ HH_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
352388 "unsigned short is greater than maximum" );
353389 return -1 ;
354390 }
391+
392+ CHECK_ARRAY_BOUNDS (ap , i );
393+
355394 if (i >= 0 )
356395 ((short * )ap -> ob_item )[i ] = (short )x ;
357396 return 0 ;
@@ -370,6 +409,9 @@ i_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
370409 /* 'i' == signed int, maps to PyArg_Parse's 'i' formatter */
371410 if (!PyArg_Parse (v , "i;array item must be integer" , & x ))
372411 return -1 ;
412+
413+ CHECK_ARRAY_BOUNDS (ap , i );
414+
373415 if (i >= 0 )
374416 ((int * )ap -> ob_item )[i ] = x ;
375417 return 0 ;
@@ -410,6 +452,9 @@ II_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
410452 }
411453 return -1 ;
412454 }
455+
456+ CHECK_ARRAY_BOUNDS_WITH_CLEANUP (ap , i , v , do_decref );
457+
413458 if (i >= 0 )
414459 ((unsigned int * )ap -> ob_item )[i ] = (unsigned int )x ;
415460
@@ -431,6 +476,9 @@ l_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
431476 long x ;
432477 if (!PyArg_Parse (v , "l;array item must be integer" , & x ))
433478 return -1 ;
479+
480+ CHECK_ARRAY_BOUNDS (ap , i );
481+
434482 if (i >= 0 )
435483 ((long * )ap -> ob_item )[i ] = x ;
436484 return 0 ;
@@ -462,6 +510,9 @@ LL_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
462510 }
463511 return -1 ;
464512 }
513+
514+ CHECK_ARRAY_BOUNDS_WITH_CLEANUP (ap , i , v , do_decref );
515+
465516 if (i >= 0 )
466517 ((unsigned long * )ap -> ob_item )[i ] = x ;
467518
@@ -483,6 +534,9 @@ q_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
483534 long long x ;
484535 if (!PyArg_Parse (v , "L;array item must be integer" , & x ))
485536 return -1 ;
537+
538+ CHECK_ARRAY_BOUNDS (ap , i );
539+
486540 if (i >= 0 )
487541 ((long long * )ap -> ob_item )[i ] = x ;
488542 return 0 ;
@@ -515,6 +569,9 @@ QQ_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
515569 }
516570 return -1 ;
517571 }
572+
573+ CHECK_ARRAY_BOUNDS_WITH_CLEANUP (ap , i , v , do_decref );
574+
518575 if (i >= 0 )
519576 ((unsigned long long * )ap -> ob_item )[i ] = x ;
520577
@@ -536,6 +593,9 @@ f_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
536593 float x ;
537594 if (!PyArg_Parse (v , "f;array item must be float" , & x ))
538595 return -1 ;
596+
597+ CHECK_ARRAY_BOUNDS (ap , i );
598+
539599 if (i >= 0 )
540600 ((float * )ap -> ob_item )[i ] = x ;
541601 return 0 ;
@@ -553,6 +613,9 @@ d_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
553613 double x ;
554614 if (!PyArg_Parse (v , "d;array item must be float" , & x ))
555615 return -1 ;
616+
617+ CHECK_ARRAY_BOUNDS (ap , i );
618+
556619 if (i >= 0 )
557620 ((double * )ap -> ob_item )[i ] = x ;
558621 return 0 ;
0 commit comments