Skip to content

Commit 0b3db3c

Browse files
committed
Change the bound check from function to macro
1 parent c8cbd28 commit 0b3db3c

File tree

1 file changed

+34
-58
lines changed

1 file changed

+34
-58
lines changed

Modules/arraymodule.c

Lines changed: 34 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -205,19 +205,28 @@ Note that the basic Get and Set functions do NOT check that the index is
205205
in 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-
}
208+
/* Macro to check array buffer validity and bounds after calling
209+
user-defined methods (like __index__ or __float__) that might modify
210+
the array during the call.
211+
*/
212+
#define CHECK_ARRAY_BOUNDS(ap, i) \
213+
do { \
214+
if ((i) >= 0 && ((ap)->ob_item == NULL || (i) >= Py_SIZE((ap)))) { \
215+
PyErr_SetString(PyExc_IndexError, "array assignment index out of range"); \
216+
return -1; \
217+
} \
218+
} while (0)
219+
220+
#define CHECK_ARRAY_BOUNDS_WITH_CLEANUP(ap, i, v, cleanup) \
221+
do { \
222+
if ((i) >= 0 && ((ap)->ob_item == NULL || (i) >= Py_SIZE((ap)))) { \
223+
PyErr_SetString(PyExc_IndexError, "array assignment index out of range"); \
224+
if (cleanup) { \
225+
Py_DECREF(v); \
226+
} \
227+
return -1; \
228+
} \
229+
} while (0)
221230

222231
static PyObject *
223232
b_getitem(arrayobject *ap, Py_ssize_t i)
@@ -236,9 +245,7 @@ b_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
236245
if (!PyArg_Parse(v, "h;array item must be integer", &x))
237246
return -1;
238247

239-
if (!array_check_bounds_after_user_call(ap, i)) {
240-
return -1;
241-
}
248+
CHECK_ARRAY_BOUNDS(ap, i);
242249

243250
if (x < -128) {
244251
PyErr_SetString(PyExc_OverflowError,
@@ -270,9 +277,7 @@ BB_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
270277
if (!PyArg_Parse(v, "b;array item must be integer", &x))
271278
return -1;
272279

273-
if (!array_check_bounds_after_user_call(ap, i)) {
274-
return -1;
275-
}
280+
CHECK_ARRAY_BOUNDS(ap, i);
276281

277282
if (i >= 0)
278283
((unsigned char *)ap->ob_item)[i] = x;
@@ -367,9 +372,7 @@ h_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
367372
if (!PyArg_Parse(v, "h;array item must be integer", &x))
368373
return -1;
369374

370-
if (!array_check_bounds_after_user_call(ap, i)) {
371-
return -1;
372-
}
375+
CHECK_ARRAY_BOUNDS(ap, i);
373376

374377
if (i >= 0)
375378
((short *)ap->ob_item)[i] = x;
@@ -401,9 +404,7 @@ HH_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
401404
return -1;
402405
}
403406

404-
if (!array_check_bounds_after_user_call(ap, i)) {
405-
return -1;
406-
}
407+
CHECK_ARRAY_BOUNDS(ap, i);
407408

408409
if (i >= 0)
409410
((short *)ap->ob_item)[i] = (short)x;
@@ -424,9 +425,7 @@ i_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
424425
if (!PyArg_Parse(v, "i;array item must be integer", &x))
425426
return -1;
426427

427-
if (!array_check_bounds_after_user_call(ap, i)) {
428-
return -1;
429-
}
428+
CHECK_ARRAY_BOUNDS(ap, i);
430429

431430
if (i >= 0)
432431
((int *)ap->ob_item)[i] = x;
@@ -469,12 +468,7 @@ II_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
469468
return -1;
470469
}
471470

472-
if (!array_check_bounds_after_user_call(ap, i)) {
473-
if (do_decref) {
474-
Py_DECREF(v);
475-
}
476-
return -1;
477-
}
471+
CHECK_ARRAY_BOUNDS_WITH_CLEANUP(ap, i, v, do_decref);
478472

479473
if (i >= 0)
480474
((unsigned int *)ap->ob_item)[i] = (unsigned int)x;
@@ -498,9 +492,7 @@ l_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
498492
if (!PyArg_Parse(v, "l;array item must be integer", &x))
499493
return -1;
500494

501-
if (!array_check_bounds_after_user_call(ap, i)) {
502-
return -1;
503-
}
495+
CHECK_ARRAY_BOUNDS(ap, i);
504496

505497
if (i >= 0)
506498
((long *)ap->ob_item)[i] = x;
@@ -534,12 +526,7 @@ LL_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
534526
return -1;
535527
}
536528

537-
if (!array_check_bounds_after_user_call(ap, i)) {
538-
if (do_decref) {
539-
Py_DECREF(v);
540-
}
541-
return -1;
542-
}
529+
CHECK_ARRAY_BOUNDS_WITH_CLEANUP(ap, i, v, do_decref);
543530

544531
if (i >= 0)
545532
((unsigned long *)ap->ob_item)[i] = x;
@@ -563,9 +550,7 @@ q_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
563550
if (!PyArg_Parse(v, "L;array item must be integer", &x))
564551
return -1;
565552

566-
if (!array_check_bounds_after_user_call(ap, i)) {
567-
return -1;
568-
}
553+
CHECK_ARRAY_BOUNDS(ap, i);
569554

570555
if (i >= 0)
571556
((long long *)ap->ob_item)[i] = x;
@@ -600,12 +585,7 @@ QQ_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
600585
return -1;
601586
}
602587

603-
if (!array_check_bounds_after_user_call(ap, i)) {
604-
if (do_decref) {
605-
Py_DECREF(v);
606-
}
607-
return -1;
608-
}
588+
CHECK_ARRAY_BOUNDS_WITH_CLEANUP(ap, i, v, do_decref);
609589

610590
if (i >= 0)
611591
((unsigned long long *)ap->ob_item)[i] = x;
@@ -629,9 +609,7 @@ f_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
629609
if (!PyArg_Parse(v, "f;array item must be float", &x))
630610
return -1;
631611

632-
if (!array_check_bounds_after_user_call(ap, i)) {
633-
return -1;
634-
}
612+
CHECK_ARRAY_BOUNDS(ap, i);
635613

636614
if (i >= 0)
637615
((float *)ap->ob_item)[i] = x;
@@ -651,9 +629,7 @@ d_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
651629
if (!PyArg_Parse(v, "d;array item must be float", &x))
652630
return -1;
653631

654-
if (!array_check_bounds_after_user_call(ap, i)) {
655-
return -1;
656-
}
632+
CHECK_ARRAY_BOUNDS(ap, i);
657633

658634
if (i >= 0)
659635
((double *)ap->ob_item)[i] = x;

0 commit comments

Comments
 (0)