@@ -847,8 +847,11 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo)
847847
848848 assert (!element -> extra || !element -> extra -> length );
849849 if (self -> extra ) {
850- if (element_resize (element , self -> extra -> length ) < 0 )
850+ Py_ssize_t expected_count = self -> extra -> length ;
851+ if (element_resize (element , expected_count ) < 0 ) {
852+ assert (!element -> extra -> length );
851853 goto error ;
854+ }
852855
853856 for (i = 0 ; self -> extra && i < self -> extra -> length ; i ++ ) {
854857 PyObject * child = deepcopy (st , self -> extra -> children [i ], memo );
@@ -860,15 +863,23 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo)
860863 element -> extra -> length = i ;
861864 goto error ;
862865 }
866+ if (self -> extra && expected_count != self -> extra -> length ) {
867+ // 'self->extra' got mutated and 'element' may not have
868+ // sufficient space to hold the next iteration's item.
869+ expected_count = self -> extra -> length ;
870+ if (element_resize (element , expected_count ) < 0 ) {
871+ Py_DECREF (child );
872+ element -> extra -> length = i ;
873+ goto error ;
874+ }
875+ }
863876 element -> extra -> children [i ] = child ;
864877 }
865878
866879 assert (!element -> extra -> length );
867- /*
868- * The original 'self->extra' may be gone at this point if deepcopy()
869- * has side-effects. However, 'i' is the number of copied items that
870- * we were able to successfully copy.
871- */
880+ // The original 'self->extra' may be gone at this point if deepcopy()
881+ // has side-effects. However, 'i' is the number of copied items that
882+ // we were able to successfully copy.
872883 element -> extra -> length = i ;
873884 }
874885
@@ -903,8 +914,6 @@ deepcopy(elementtreestate *st, PyObject *object, PyObject *memo)
903914
904915 if (Py_REFCNT (object ) == 1 ) {
905916 if (PyDict_CheckExact (object )) {
906- // Exact dictionaries do not execute arbitrary code as it's
907- // impossible to override their __iter__() method.
908917 PyObject * key , * value ;
909918 Py_ssize_t pos = 0 ;
910919 int simple = 1 ;
@@ -915,18 +924,18 @@ deepcopy(elementtreestate *st, PyObject *object, PyObject *memo)
915924 }
916925 }
917926 if (simple ) {
918- // This does not call object.__copy__(), so it's still safe.
919927 return PyDict_Copy (object );
920928 }
921929 /* Fall through to general case */
922930 }
923931 else if (Element_CheckExact (st , object )) {
924932 // The __deepcopy__() call may call arbitrary code even if the
925933 // object to copy is a built-in XML element (one of its children
926- // may mutate 'object' in its own __deepcopy__() implementation).
927- ElementObject * tmp = (ElementObject * )Py_NewRef (object );
928- PyObject * res = _elementtree_Element___deepcopy___impl (tmp , memo );
929- Py_DECREF (tmp );
934+ // any of its parents in its own __deepcopy__() implementation).
935+ Py_INCREF (object );
936+ PyObject * res = _elementtree_Element___deepcopy___impl (
937+ (ElementObject * )object , memo );
938+ Py_DECREF (object );
930939 return res ;
931940 }
932941 }
@@ -938,9 +947,10 @@ deepcopy(elementtreestate *st, PyObject *object, PyObject *memo)
938947 return NULL ;
939948 }
940949
941- PyObject * args [2 ] = {Py_NewRef (object ), memo };
950+ Py_INCREF (object );
951+ PyObject * args [2 ] = {object , memo };
942952 PyObject * res = PyObject_Vectorcall (st -> deepcopy_obj , args , 2 , NULL );
943- Py_DECREF (args [ 0 ] );
953+ Py_DECREF (object );
944954 return res ;
945955}
946956
0 commit comments