Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 34k
Closed
Labels
3.12only security fixesonly security fixes3.13bugs and security fixesbugs and security fixes3.14bugs and security fixesbugs and security fixestype-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump
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 */staticintlist_ass_subscript(PyListObject*self, PyObject*item, PyObject*value){if (_PyIndex_Check(item)){/* ... */ } elseif (PySlice_Check(item)){Py_ssize_tstart, 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) returnlist_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_ti; size_tcur; /* 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
classevil: def__init__(self, lst): self.lst=lstdef__iter__(self): yieldfromself.lstself.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 - [3.10] gh-120384: gh-120298: Fix array-out-of-bounds & use after free
list(GH-121345) #140833 - [3.9] gh-120384: gh-120298: Fix array-out-of-bounds & use after free
list(GH-121345) #140834
Metadata
Metadata
Assignees
Labels
3.12only security fixesonly security fixes3.13bugs and security fixesbugs and security fixes3.14bugs and security fixesbugs and security fixestype-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump