@@ -805,7 +805,6 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo)
805805{
806806 Py_ssize_t i ;
807807 ElementObject * element ;
808- PyObject * tmp ;
809808 PyObject * tag ;
810809 PyObject * attrib ;
811810 PyObject * text ;
@@ -814,16 +813,14 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo)
814813
815814 PyTypeObject * tp = Py_TYPE (self );
816815 elementtreestate * st = get_elementtree_state_by_type (tp );
817- tmp = Py_NewRef ( self -> tag );
818- tag = deepcopy ( st , tmp , memo );
819- Py_CLEAR ( tmp );
816+ // The deepcopy() helper takes care of incrementing the refcount
817+ // of the object to copy so to avoid use-after-frees.
818+ tag = deepcopy ( st , self -> tag , memo );
820819 if (!tag )
821820 return NULL ;
822821
823822 if (self -> extra && self -> extra -> attrib ) {
824- tmp = Py_NewRef (self -> extra -> attrib );
825- attrib = deepcopy (st , tmp , memo );
826- Py_CLEAR (tmp );
823+ attrib = deepcopy (st , self -> extra -> attrib , memo );
827824 if (!attrib ) {
828825 Py_DECREF (tag );
829826 return NULL ;
@@ -840,16 +837,12 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo)
840837 if (!element )
841838 return NULL ;
842839
843- tmp = Py_NewRef (JOIN_OBJ (self -> text ));
844- text = deepcopy (st , tmp , memo );
845- Py_CLEAR (tmp );
840+ text = deepcopy (st , JOIN_OBJ (self -> text ), memo );
846841 if (!text )
847842 goto error ;
848843 _set_joined_ptr (& element -> text , JOIN_SET (text , JOIN_GET (self -> text )));
849844
850- tmp = Py_NewRef (JOIN_OBJ (self -> tail ));
851- tail = deepcopy (st , tmp , memo );
852- Py_CLEAR (tmp );
845+ tail = deepcopy (st , JOIN_OBJ (self -> tail ), memo );
853846 if (!tail )
854847 goto error ;
855848 _set_joined_ptr (& element -> tail , JOIN_SET (tail , JOIN_GET (self -> tail )));
@@ -860,9 +853,7 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo)
860853 goto error ;
861854
862855 for (i = 0 ; self -> extra && i < self -> extra -> length ; i ++ ) {
863- tmp = Py_NewRef (self -> extra -> children [i ]);
864- PyObject * child = deepcopy (st , tmp , memo );
865- Py_CLEAR (tmp );
856+ PyObject * child = deepcopy (st , self -> extra -> children [i ], memo );
866857 if (!child || !Element_Check (st , child )) {
867858 if (child ) {
868859 raise_type_error (child );
@@ -877,7 +868,7 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo)
877868 assert (!element -> extra -> length );
878869 /*
879870 * The original 'self->extra' may be gone at this point if deepcopy()
880- * had side-effects. However, 'i' is the number of copied items that
871+ * has side-effects. However, 'i' is the number of copied items that
881872 * we were able to successfully copy.
882873 */
883874 element -> extra -> length = i ;
@@ -914,6 +905,8 @@ deepcopy(elementtreestate *st, PyObject *object, PyObject *memo)
914905
915906 if (Py_REFCNT (object ) == 1 ) {
916907 if (PyDict_CheckExact (object )) {
908+ // Exact dictionaries do not execute arbitrary code as it's
909+ // impossible to override their __iter__() method.
917910 PyObject * key , * value ;
918911 Py_ssize_t pos = 0 ;
919912 int simple = 1 ;
@@ -923,13 +916,20 @@ deepcopy(elementtreestate *st, PyObject *object, PyObject *memo)
923916 break ;
924917 }
925918 }
926- if (simple )
919+ if (simple ) {
920+ // This does not call object.__copy__(), so it's still safe.
927921 return PyDict_Copy (object );
922+ }
928923 /* Fall through to general case */
929924 }
930925 else if (Element_CheckExact (st , object )) {
931- return _elementtree_Element___deepcopy___impl (
932- (ElementObject * )object , memo );
926+ // The __deepcopy__() call may call arbitrary code even if the
927+ // object to copy is a built-in XML element (one of its children
928+ // may mutate 'object' in its own __deepcopy__() implementation).
929+ ElementObject * tmp = (ElementObject * )Py_NewRef (object );
930+ PyObject * res = _elementtree_Element___deepcopy___impl (tmp , memo );
931+ Py_DECREF (tmp );
932+ return res ;
933933 }
934934 }
935935
@@ -940,8 +940,10 @@ deepcopy(elementtreestate *st, PyObject *object, PyObject *memo)
940940 return NULL ;
941941 }
942942
943- PyObject * args [2 ] = {object , memo };
944- return PyObject_Vectorcall (st -> deepcopy_obj , args , 2 , NULL );
943+ PyObject * args [2 ] = {Py_NewRef (object ), memo };
944+ PyObject * res = PyObject_Vectorcall (st -> deepcopy_obj , args , 2 , NULL );
945+ Py_DECREF (args [0 ]);
946+ return res ;
945947}
946948
947949
0 commit comments