gh-112087: Make list_{count, index, contains} to be thread-safe. (gh-114916)

This commit is contained in:
Donghee Na 2024-02-07 01:41:18 +09:00 committed by GitHub
parent de61d4bd4d
commit f7a22a7055
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 33 additions and 19 deletions

View File

@ -272,6 +272,15 @@ PyList_GetItemRef(PyObject *op, Py_ssize_t i)
return Py_NewRef(PyList_GET_ITEM(op, i)); return Py_NewRef(PyList_GET_ITEM(op, i));
} }
static inline PyObject*
list_get_item_ref(PyListObject *op, Py_ssize_t i)
{
if (!valid_index(i, Py_SIZE(op))) {
return NULL;
}
return Py_NewRef(PyList_GET_ITEM(op, i));
}
int int
PyList_SetItem(PyObject *op, Py_ssize_t i, PyList_SetItem(PyObject *op, Py_ssize_t i,
PyObject *newitem) PyObject *newitem)
@ -478,18 +487,20 @@ list_length(PyObject *a)
static int static int
list_contains(PyObject *aa, PyObject *el) list_contains(PyObject *aa, PyObject *el)
{ {
PyListObject *a = (PyListObject *)aa;
PyObject *item;
Py_ssize_t i;
int cmp;
for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(a); ++i) { for (Py_ssize_t i = 0; ; i++) {
item = PyList_GET_ITEM(a, i); PyObject *item = list_get_item_ref((PyListObject *)aa, i);
Py_INCREF(item); if (item == NULL) {
cmp = PyObject_RichCompareBool(item, el, Py_EQ); // out-of-bounds
return 0;
}
int cmp = PyObject_RichCompareBool(item, el, Py_EQ);
Py_DECREF(item); Py_DECREF(item);
if (cmp != 0) {
return cmp;
}
} }
return cmp; return 0;
} }
static PyObject * static PyObject *
@ -2724,8 +2735,6 @@ list_index_impl(PyListObject *self, PyObject *value, Py_ssize_t start,
Py_ssize_t stop) Py_ssize_t stop)
/*[clinic end generated code: output=ec51b88787e4e481 input=40ec5826303a0eb1]*/ /*[clinic end generated code: output=ec51b88787e4e481 input=40ec5826303a0eb1]*/
{ {
Py_ssize_t i;
if (start < 0) { if (start < 0) {
start += Py_SIZE(self); start += Py_SIZE(self);
if (start < 0) if (start < 0)
@ -2736,9 +2745,12 @@ list_index_impl(PyListObject *self, PyObject *value, Py_ssize_t start,
if (stop < 0) if (stop < 0)
stop = 0; stop = 0;
} }
for (i = start; i < stop && i < Py_SIZE(self); i++) { for (Py_ssize_t i = start; i < stop; i++) {
PyObject *obj = self->ob_item[i]; PyObject *obj = list_get_item_ref(self, i);
Py_INCREF(obj); if (obj == NULL) {
// out-of-bounds
break;
}
int cmp = PyObject_RichCompareBool(obj, value, Py_EQ); int cmp = PyObject_RichCompareBool(obj, value, Py_EQ);
Py_DECREF(obj); Py_DECREF(obj);
if (cmp > 0) if (cmp > 0)
@ -2764,15 +2776,17 @@ list_count(PyListObject *self, PyObject *value)
/*[clinic end generated code: output=b1f5d284205ae714 input=3bdc3a5e6f749565]*/ /*[clinic end generated code: output=b1f5d284205ae714 input=3bdc3a5e6f749565]*/
{ {
Py_ssize_t count = 0; Py_ssize_t count = 0;
Py_ssize_t i; for (Py_ssize_t i = 0; ; i++) {
PyObject *obj = list_get_item_ref(self, i);
for (i = 0; i < Py_SIZE(self); i++) { if (obj == NULL) {
PyObject *obj = self->ob_item[i]; // out-of-bounds
break;
}
if (obj == value) { if (obj == value) {
count++; count++;
Py_DECREF(obj);
continue; continue;
} }
Py_INCREF(obj);
int cmp = PyObject_RichCompareBool(obj, value, Py_EQ); int cmp = PyObject_RichCompareBool(obj, value, Py_EQ);
Py_DECREF(obj); Py_DECREF(obj);
if (cmp > 0) if (cmp > 0)