Skip to content

Commit b884536

Browse files
miss-islingtonsobolevnserhiy-storchaka
authored
[3.12] gh-120298: Fix use-after-free in list_richcompare_impl (GH-120303) (#120339)
gh-120298: Fix use-after-free in `list_richcompare_impl` (GH-120303) (cherry picked from commit 141baba) Co-authored-by: Nikita Sobolev <[email protected]> Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent f648192 commit b884536

File tree

3 files changed

+21
-1
lines changed

3 files changed

+21
-1
lines changed

Lib/test/test_list.py

+11
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,17 @@ def __eq__(self, other):
229229
list4 = [1]
230230
self.assertFalse(list3 == list4)
231231

232+
def test_lt_operator_modifying_operand(self):
233+
# See gh-120298
234+
class evil:
235+
def __lt__(self, other):
236+
other.clear()
237+
return NotImplemented
238+
239+
a = [[evil()]]
240+
with self.assertRaises(TypeError):
241+
a[0] < a
242+
232243
@cpython_only
233244
def test_preallocation(self):
234245
iterable = [0] * 10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix use-after free in ``list_richcompare_impl`` which can be invoked via
2+
some specificly tailored evil input.

Objects/listobject.c

+8-1
Original file line numberDiff line numberDiff line change
@@ -2759,7 +2759,14 @@ list_richcompare(PyObject *v, PyObject *w, int op)
27592759
}
27602760

27612761
/* Compare the final item again using the proper operator */
2762-
return PyObject_RichCompare(vl->ob_item[i], wl->ob_item[i], op);
2762+
PyObject *vitem = vl->ob_item[i];
2763+
PyObject *witem = wl->ob_item[i];
2764+
Py_INCREF(vitem);
2765+
Py_INCREF(witem);
2766+
PyObject *result = PyObject_RichCompare(vl->ob_item[i], wl->ob_item[i], op);
2767+
Py_DECREF(vitem);
2768+
Py_DECREF(witem);
2769+
return result;
27632770
}
27642771

27652772
/*[clinic input]

0 commit comments

Comments
 (0)