@@ -205,6 +205,20 @@ Note that the basic Get and Set functions do NOT check that the index is
205205in bounds; that's the responsibility of the caller.
206206****************************************************************************/
207207
208+ /* Check array buffer validity and bounds after calling user-defined methods
209+ (like __index__ or __float__) that might modify the array during the call.
210+ Returns false on error, true on success. */
211+ static inline bool
212+ array_check_bounds_after_user_call (arrayobject * ap , Py_ssize_t i )
213+ {
214+ if (i >= 0 && (ap -> ob_item == NULL || i >= Py_SIZE (ap ))) {
215+ PyErr_SetString (PyExc_IndexError ,
216+ "array assignment index out of range" );
217+ return false;
218+ }
219+ return true;
220+ }
221+
208222static PyObject *
209223b_getitem (arrayobject * ap , Py_ssize_t i )
210224{
@@ -222,10 +236,7 @@ b_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
222236 if (!PyArg_Parse (v , "h;array item must be integer" , & x ))
223237 return -1 ;
224238
225- // Check buffer validity and bounds after call user-defined method.
226- if (i >= 0 && (ap -> ob_item == NULL || i >= Py_SIZE (ap ))) {
227- PyErr_SetString (PyExc_IndexError ,
228- "array assignment index out of range" );
239+ if (!array_check_bounds_after_user_call (ap , i )) {
229240 return -1 ;
230241 }
231242
@@ -259,10 +270,7 @@ BB_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
259270 if (!PyArg_Parse (v , "b;array item must be integer" , & x ))
260271 return -1 ;
261272
262- // Check buffer validity and bounds after call user-defined method.
263- if (i >= 0 && (ap -> ob_item == NULL || i >= Py_SIZE (ap ))) {
264- PyErr_SetString (PyExc_IndexError ,
265- "array assignment index out of range" );
273+ if (!array_check_bounds_after_user_call (ap , i )) {
266274 return -1 ;
267275 }
268276
@@ -359,10 +367,7 @@ h_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
359367 if (!PyArg_Parse (v , "h;array item must be integer" , & x ))
360368 return -1 ;
361369
362- // Check buffer validity and bounds after call user-defined method.
363- if (i >= 0 && (ap -> ob_item == NULL || i >= Py_SIZE (ap ))) {
364- PyErr_SetString (PyExc_IndexError ,
365- "array assignment index out of range" );
370+ if (!array_check_bounds_after_user_call (ap , i )) {
366371 return -1 ;
367372 }
368373
@@ -396,10 +401,7 @@ HH_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
396401 return -1 ;
397402 }
398403
399- // Check buffer validity and bounds after call user-defined method.
400- if (i >= 0 && (ap -> ob_item == NULL || i >= Py_SIZE (ap ))) {
401- PyErr_SetString (PyExc_IndexError ,
402- "array assignment index out of range" );
404+ if (!array_check_bounds_after_user_call (ap , i )) {
403405 return -1 ;
404406 }
405407
@@ -422,10 +424,7 @@ i_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
422424 if (!PyArg_Parse (v , "i;array item must be integer" , & x ))
423425 return -1 ;
424426
425- // Check buffer validity and bounds after call user-defined method.
426- if (i >= 0 && (ap -> ob_item == NULL || i >= Py_SIZE (ap ))) {
427- PyErr_SetString (PyExc_IndexError ,
428- "array assignment index out of range" );
427+ if (!array_check_bounds_after_user_call (ap , i )) {
429428 return -1 ;
430429 }
431430
@@ -470,10 +469,7 @@ II_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
470469 return -1 ;
471470 }
472471
473- // Check buffer validity and bounds after call user-defined method.
474- if (i >= 0 && (ap -> ob_item == NULL || i >= Py_SIZE (ap ))) {
475- PyErr_SetString (PyExc_IndexError ,
476- "array assignment index out of range" );
472+ if (!array_check_bounds_after_user_call (ap , i )) {
477473 if (do_decref ) {
478474 Py_DECREF (v );
479475 }
@@ -502,10 +498,7 @@ l_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
502498 if (!PyArg_Parse (v , "l;array item must be integer" , & x ))
503499 return -1 ;
504500
505- // Check buffer validity and bounds after call user-defined method.
506- if (i >= 0 && (ap -> ob_item == NULL || i >= Py_SIZE (ap ))) {
507- PyErr_SetString (PyExc_IndexError ,
508- "array assignment index out of range" );
501+ if (!array_check_bounds_after_user_call (ap , i )) {
509502 return -1 ;
510503 }
511504
@@ -541,10 +534,7 @@ LL_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
541534 return -1 ;
542535 }
543536
544- // Check buffer validity and bounds after call user-defined method.
545- if (i >= 0 && (ap -> ob_item == NULL || i >= Py_SIZE (ap ))) {
546- PyErr_SetString (PyExc_IndexError ,
547- "array assignment index out of range" );
537+ if (!array_check_bounds_after_user_call (ap , i )) {
548538 if (do_decref ) {
549539 Py_DECREF (v );
550540 }
@@ -573,10 +563,7 @@ q_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
573563 if (!PyArg_Parse (v , "L;array item must be integer" , & x ))
574564 return -1 ;
575565
576- // Check buffer validity and bounds after call user-defined method.
577- if (i >= 0 && (ap -> ob_item == NULL || i >= Py_SIZE (ap ))) {
578- PyErr_SetString (PyExc_IndexError ,
579- "array assignment index out of range" );
566+ if (!array_check_bounds_after_user_call (ap , i )) {
580567 return -1 ;
581568 }
582569
@@ -613,10 +600,7 @@ QQ_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
613600 return -1 ;
614601 }
615602
616- // Check buffer validity and bounds after call user-defined method.
617- if (i >= 0 && (ap -> ob_item == NULL || i >= Py_SIZE (ap ))) {
618- PyErr_SetString (PyExc_IndexError ,
619- "array assignment index out of range" );
603+ if (!array_check_bounds_after_user_call (ap , i )) {
620604 if (do_decref ) {
621605 Py_DECREF (v );
622606 }
@@ -645,10 +629,7 @@ f_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
645629 if (!PyArg_Parse (v , "f;array item must be float" , & x ))
646630 return -1 ;
647631
648- // Check buffer validity and bounds after call user-defined method.
649- if (i >= 0 && (ap -> ob_item == NULL || i >= Py_SIZE (ap ))) {
650- PyErr_SetString (PyExc_IndexError ,
651- "array assignment index out of range" );
632+ if (!array_check_bounds_after_user_call (ap , i )) {
652633 return -1 ;
653634 }
654635
@@ -670,10 +651,7 @@ d_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
670651 if (!PyArg_Parse (v , "d;array item must be float" , & x ))
671652 return -1 ;
672653
673- // Check buffer validity and bounds after call user-defined method.
674- if (i >= 0 && (ap -> ob_item == NULL || i >= Py_SIZE (ap ))) {
675- PyErr_SetString (PyExc_IndexError ,
676- "array assignment index out of range" );
654+ if (!array_check_bounds_after_user_call (ap , i )) {
677655 return -1 ;
678656 }
679657
0 commit comments