Closed
Description
Crash report
What happened?
Root Cause
When step is not 1 in slice assignment, list_ass_subscript
first calculates the length of the slice and then converts the input iterable into a list. During the conversion, arbitrary code in Python can be executed to modify the length of the current list or even clear it:
/* Python 3.10 source code */
static int
list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
{
if (_PyIndex_Check(item)) { /* ... */ }
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return -1;
}
slicelength = PySlice_AdjustIndices(Py_SIZE(self), &start, &stop,
step);
if (step == 1)
return list_ass_slice(self, start, stop, value);
/* Make sure s[5:2] = [..] inserts at the right place:
before 5, not before 2. */
if ((step < 0 && start < stop) ||
(step > 0 && start > stop))
stop = start;
if (value == NULL) { /* ... */ }
else {
/* assign slice */
PyObject *ins, *seq;
PyObject **garbage, **seqitems, **selfitems;
Py_ssize_t i;
size_t cur;
/* protect against a[::-1] = a */
if (self == (PyListObject*)value) {
seq = list_slice((PyListObject*)value, 0,
PyList_GET_SIZE(value));
}
else {
seq = PySequence_Fast(value, // <-- call arbitrary code in python
"must assign iterable "
"to extended slice");
}
if (!seq)
return -1;
/* ... */
selfitems = self->ob_item;
seqitems = PySequence_Fast_ITEMS(seq);
for (cur = start, i = 0; i < slicelength;
cur += (size_t)step, i++) {
garbage[i] = selfitems[cur];
ins = seqitems[i];
Py_INCREF(ins);
selfitems[cur] = ins; // <-- maybe out of bounds
}
/* ... */
}
/* ... */
}
POC
class evil:
def __init__(self, lst):
self.lst = lst
def __iter__(self):
yield from self.lst
self.lst.clear()
lst = list(range(10))
lst[::-1] = evil(lst)
CPython versions tested on:
3.10, 3.11, 3.12
Operating systems tested on:
Windows
Output from running 'python -VV' on the command line:
Python 3.10.11 (tags/v3.10.11:7d4cc5a, Apr 5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)]
Python 3.11.8 (tags/v3.11.8:db85d51, Feb 6 2024, 22:03:32) [MSC v.1937 64 bit (AMD64)]
Python 3.12.3 (tags/v3.12.3:f6650f9, Apr 9 2024, 14:05:25) [MSC v.1938 64 bit (AMD64)]
Linked PRs
- gh-120384: Fix array-out-of-bounds crash in
list_ass_subscript
#120442 - [3.12] gh-120384: Fix array-out-of-bounds crash in
list_ass_subscript
(GH-120442) #120825 - [3.13] gh-120384: Fix array-out-of-bounds crash in
list_ass_subscript
(GH-120442) #120826 - [3.11] gh-120384: gh-120298: Fix array-out-of-bounds & use after free
list
#121345