@@ -1801,6 +1801,8 @@ element_subscr(PyObject *op, PyObject *item)
18011801 if (i == -1 && PyErr_Occurred ()) {
18021802 return NULL ;
18031803 }
1804+ // If PyNumber_AsSsize_t() clears 'self->extra',
1805+ // we want element_getitem() to raise IndexError.
18041806 if (i < 0 && self -> extra )
18051807 i += self -> extra -> length ;
18061808 return element_getitem (op , i );
@@ -1810,12 +1812,19 @@ element_subscr(PyObject *op, PyObject *item)
18101812 size_t cur ;
18111813 PyObject * list ;
18121814
1813- if (!self -> extra )
1814- return PyList_New (0 );
1815-
18161815 if (PySlice_Unpack (item , & start , & stop , & step ) < 0 ) {
18171816 return NULL ;
18181817 }
1818+
1819+ // Even if PySlice_Unpack() may clear 'self->extra',
1820+ // using a slice should not raise an IndexError, so
1821+ // we do not need to ensure 'extra' to exist.
1822+ //
1823+ // See https://github.com/python/cpython/issues/143200.
1824+ if (self -> extra == NULL ) {
1825+ return PyList_New (0 );
1826+ }
1827+
18191828 slicelen = PySlice_AdjustIndices (self -> extra -> length , & start , & stop ,
18201829 step );
18211830
@@ -1853,6 +1862,8 @@ element_ass_subscr(PyObject *op, PyObject *item, PyObject *value)
18531862 if (i == -1 && PyErr_Occurred ()) {
18541863 return -1 ;
18551864 }
1865+ // If PyNumber_AsSsize_t() clears 'self->extra',
1866+ // we want element_setitem() to raise IndexError.
18561867 if (i < 0 && self -> extra )
18571868 i += self -> extra -> length ;
18581869 return element_setitem (op , i , value );
@@ -1864,16 +1875,20 @@ element_ass_subscr(PyObject *op, PyObject *item, PyObject *value)
18641875 PyObject * recycle = NULL ;
18651876 PyObject * seq ;
18661877
1867- if (!self -> extra ) {
1868- if (create_extra (self , NULL ) < 0 )
1869- return -1 ;
1870- }
1871-
18721878 if (PySlice_Unpack (item , & start , & stop , & step ) < 0 ) {
18731879 return -1 ;
18741880 }
1881+ // Since PySlice_Unpack() may clear 'self->extra', we need
1882+ // to ensure that it exists now (using a slice for assignment
1883+ // should not raise IndexError).
1884+ //
1885+ // See https://github.com/python/cpython/issues/143200.
1886+ if (self -> extra == NULL && create_extra (self , NULL ) < 0 ) {
1887+ return -1 ;
1888+ }
1889+
18751890 slicelen = PySlice_AdjustIndices (self -> extra -> length , & start , & stop ,
1876- step );
1891+ step );
18771892
18781893 if (value == NULL ) {
18791894 /* Delete slice */
@@ -1908,6 +1923,8 @@ element_ass_subscr(PyObject *op, PyObject *item, PyObject *value)
19081923 * Note that in the ith iteration, shifting is done i+i places down
19091924 * because i children were already removed.
19101925 */
1926+ assert (self -> extra != NULL );
1927+ assert (self -> extra -> children != NULL );
19111928 for (cur = start , i = 0 ; cur < (size_t )stop ; cur += step , ++ i ) {
19121929 /* Compute how many children have to be moved, clipping at the
19131930 * list end.
@@ -1948,6 +1965,18 @@ element_ass_subscr(PyObject *op, PyObject *item, PyObject *value)
19481965 }
19491966 newlen = PySequence_Fast_GET_SIZE (seq );
19501967
1968+ // Re-create 'self->extra' if PySequence_Fast() cleared it.
1969+ // See https://github.com/python/cpython/issues/143200.
1970+ if (self -> extra == NULL ) {
1971+ if (create_extra (self , NULL ) < 0 ) {
1972+ Py_DECREF (seq );
1973+ return -1 ;
1974+ }
1975+ // re-compute the slice length since self->extra->length changed
1976+ slicelen = PySlice_AdjustIndices (self -> extra -> length , & start , & stop ,
1977+ step );
1978+ }
1979+
19511980 if (step != 1 && newlen != slicelen )
19521981 {
19531982 Py_DECREF (seq );
@@ -1967,6 +1996,9 @@ element_ass_subscr(PyObject *op, PyObject *item, PyObject *value)
19671996 }
19681997 }
19691998
1999+ assert (recycle == NULL );
2000+ assert (self -> extra != NULL );
2001+
19702002 PyTypeObject * tp = Py_TYPE (self );
19712003 elementtreestate * st = get_elementtree_state_by_type (tp );
19722004 for (i = 0 ; i < newlen ; i ++ ) {
0 commit comments