| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 177bda9 commit 296d45e
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -162,5 +162,31 @@ class L(list): pass | |||
| 162 | 162 | with self.assertRaises(TypeError): | |
| 163 | 163 | (3,) + L([1,2]) | |
| 164 | 164 | ||
| 165 | + def test_count_index_remove_crashes(self): | ||
| 166 | + # bpo-38610: The count(), index(), and remove() methods were not | ||
| 167 | + # holding strong references to list elements while calling | ||
| 168 | + # PyObject_RichCompareBool(). | ||
| 169 | + class X: | ||
| 170 | + def __eq__(self, other): | ||
| 171 | + lst.clear() | ||
| 172 | + return NotImplemented | ||
| 173 | + | ||
| 174 | + lst = [X()] | ||
| 175 | + with self.assertRaises(ValueError): | ||
| 176 | + lst.index(lst) | ||
| 177 | + | ||
| 178 | + class L(list): | ||
| 179 | + def __eq__(self, other): | ||
| 180 | + str(other) | ||
| 181 | + return NotImplemented | ||
| 182 | + | ||
| 183 | + lst = L([X()]) | ||
| 184 | + lst.count(lst) | ||
| 185 | + | ||
| 186 | + lst = L([X()]) | ||
| 187 | + with self.assertRaises(ValueError): | ||
| 188 | + lst.remove(lst) | ||
| 189 | + | ||
| 190 | + | ||
| 165 | 191 | if __name__ == "__main__": | |
| 166 | 192 | unittest.main() | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,2 @@ | |||
| 1 | + Fix possible crashes in several list methods by holding strong references to | ||
| 2 | + list elements when calling :c:func:`PyObject_RichCompareBool`. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2506,7 +2506,10 @@ list_index_impl(PyListObject *self, PyObject *value, Py_ssize_t start, | |||
| 2506 | 2506 | stop = 0; | |
| 2507 | 2507 | } | |
| 2508 | 2508 | for (i = start; i < stop && i < Py_SIZE(self); i++) { | |
| 2509 | - int cmp = PyObject_RichCompareBool(self->ob_item[i], value, Py_EQ); | ||
| 2509 | + PyObject *obj = self->ob_item[i]; | ||
| 2510 | + Py_INCREF(obj); | ||
| 2511 | + int cmp = PyObject_RichCompareBool(obj, value, Py_EQ); | ||
| 2512 | + Py_DECREF(obj); | ||
| 2510 | 2513 | if (cmp > 0) | |
| 2511 | 2514 | return PyLong_FromSsize_t(i); | |
| 2512 | 2515 | else if (cmp < 0) | |
@@ -2533,7 +2536,10 @@ list_count(PyListObject *self, PyObject *value) | |||
| 2533 | 2536 | Py_ssize_t i; | |
| 2534 | 2537 | ||
| 2535 | 2538 | for (i = 0; i < Py_SIZE(self); i++) { | |
| 2536 | - int cmp = PyObject_RichCompareBool(self->ob_item[i], value, Py_EQ); | ||
| 2539 | + PyObject *obj = self->ob_item[i]; | ||
| 2540 | + Py_INCREF(obj); | ||
| 2541 | + int cmp = PyObject_RichCompareBool(obj, value, Py_EQ); | ||
| 2542 | + Py_DECREF(obj); | ||
| 2537 | 2543 | if (cmp > 0) | |
| 2538 | 2544 | count++; | |
| 2539 | 2545 | else if (cmp < 0) | |
@@ -2560,7 +2566,10 @@ list_remove(PyListObject *self, PyObject *value) | |||
| 2560 | 2566 | Py_ssize_t i; | |
| 2561 | 2567 | ||
| 2562 | 2568 | for (i = 0; i < Py_SIZE(self); i++) { | |
| 2563 | - int cmp = PyObject_RichCompareBool(self->ob_item[i], value, Py_EQ); | ||
| 2569 | + PyObject *obj = self->ob_item[i]; | ||
| 2570 | + Py_INCREF(obj); | ||
| 2571 | + int cmp = PyObject_RichCompareBool(obj, value, Py_EQ); | ||
| 2572 | + Py_DECREF(obj); | ||
| 2564 | 2573 | if (cmp > 0) { | |
| 2565 | 2574 | if (list_ass_slice(self, i, i+1, | |
| 2566 | 2575 | (PyObject *)NULL) == 0) | |
| Back | FazBrowse Home | New Git URL |
0 commit comments