mirror of
https://github.com/python/cpython.git
synced 2025-10-02 21:25:24 +00:00
[3.12] gh-120384: Fix array-out-of-bounds crash in list_ass_subscript
(GH-120442) (#120825)
gh-120384: Fix array-out-of-bounds crash in `list_ass_subscript` (GH-120442)
(cherry picked from commit 8334a1b55c
)
Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
This commit is contained in:
parent
e58bece8ce
commit
d75eddcf36
4 changed files with 58 additions and 12 deletions
|
@ -191,6 +191,14 @@ class CommonTest(seq_tests.CommonTest):
|
||||||
|
|
||||||
self.assertRaises(TypeError, a.__setitem__)
|
self.assertRaises(TypeError, a.__setitem__)
|
||||||
|
|
||||||
|
def test_slice_assign_iterator(self):
|
||||||
|
x = self.type2test(range(5))
|
||||||
|
x[0:3] = reversed(range(3))
|
||||||
|
self.assertEqual(x, self.type2test([2, 1, 0, 3, 4]))
|
||||||
|
|
||||||
|
x[:] = reversed(range(3))
|
||||||
|
self.assertEqual(x, self.type2test([2, 1, 0]))
|
||||||
|
|
||||||
def test_delslice(self):
|
def test_delslice(self):
|
||||||
a = self.type2test([0, 1])
|
a = self.type2test([0, 1])
|
||||||
del a[1:2]
|
del a[1:2]
|
||||||
|
|
|
@ -240,6 +240,20 @@ class ListTest(list_tests.CommonTest):
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
a[0] < a
|
a[0] < a
|
||||||
|
|
||||||
|
def test_list_index_modifing_operand(self):
|
||||||
|
# See gh-120384
|
||||||
|
class evil:
|
||||||
|
def __init__(self, lst):
|
||||||
|
self.lst = lst
|
||||||
|
def __iter__(self):
|
||||||
|
yield from self.lst
|
||||||
|
self.lst.clear()
|
||||||
|
|
||||||
|
lst = list(range(5))
|
||||||
|
operand = evil(lst)
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
lst[::-1] = operand
|
||||||
|
|
||||||
@cpython_only
|
@cpython_only
|
||||||
def test_preallocation(self):
|
def test_preallocation(self):
|
||||||
iterable = [0] * 10
|
iterable = [0] * 10
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Fix an array out of bounds crash in ``list_ass_subscript``, which could be
|
||||||
|
invoked via some specificly tailored input: including concurrent modification
|
||||||
|
of a list object, where one thread assigns a slice and another clears it.
|
|
@ -2935,6 +2935,23 @@ list_subscript(PyListObject* self, PyObject* item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Py_ssize_t
|
||||||
|
adjust_slice_indexes(PyListObject *lst,
|
||||||
|
Py_ssize_t *start, Py_ssize_t *stop,
|
||||||
|
Py_ssize_t step)
|
||||||
|
{
|
||||||
|
Py_ssize_t slicelength = PySlice_AdjustIndices(Py_SIZE(lst), start, stop,
|
||||||
|
step);
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
return slicelength;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
|
list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
|
||||||
{
|
{
|
||||||
|
@ -2947,22 +2964,11 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
|
||||||
return list_ass_item(self, i, value);
|
return list_ass_item(self, i, value);
|
||||||
}
|
}
|
||||||
else if (PySlice_Check(item)) {
|
else if (PySlice_Check(item)) {
|
||||||
Py_ssize_t start, stop, step, slicelength;
|
Py_ssize_t start, stop, step;
|
||||||
|
|
||||||
if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
|
if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
|
||||||
return -1;
|
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) {
|
if (value == NULL) {
|
||||||
/* delete slice */
|
/* delete slice */
|
||||||
|
@ -2971,6 +2977,12 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
|
||||||
Py_ssize_t i;
|
Py_ssize_t i;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
Py_ssize_t slicelength = adjust_slice_indexes(self, &start, &stop,
|
||||||
|
step);
|
||||||
|
|
||||||
|
if (step == 1)
|
||||||
|
return list_ass_slice(self, start, stop, value);
|
||||||
|
|
||||||
if (slicelength <= 0)
|
if (slicelength <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -3046,6 +3058,15 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
|
||||||
if (!seq)
|
if (!seq)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
Py_ssize_t slicelength = adjust_slice_indexes(self, &start, &stop,
|
||||||
|
step);
|
||||||
|
|
||||||
|
if (step == 1) {
|
||||||
|
int res = list_ass_slice(self, start, stop, seq);
|
||||||
|
Py_DECREF(seq);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
if (PySequence_Fast_GET_SIZE(seq) != slicelength) {
|
if (PySequence_Fast_GET_SIZE(seq) != slicelength) {
|
||||||
PyErr_Format(PyExc_ValueError,
|
PyErr_Format(PyExc_ValueError,
|
||||||
"attempt to assign sequence of "
|
"attempt to assign sequence of "
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue