Skip to content

Commit 721481d

Browse files
committed
always protect against possible mutations in __deepcopy__
1 parent 2b5be5f commit 721481d

File tree

1 file changed

+15
-15
lines changed

1 file changed

+15
-15
lines changed

Modules/_elementtree.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,7 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo)
805805
{
806806
Py_ssize_t i;
807807
ElementObject* element;
808+
PyObject* tmp;
808809
PyObject* tag;
809810
PyObject* attrib;
810811
PyObject* text;
@@ -813,17 +814,17 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo)
813814

814815
PyTypeObject *tp = Py_TYPE(self);
815816
elementtreestate *st = get_elementtree_state_by_type(tp);
816-
// Since the 'tag' attribute is undeletable, deepcopy() should be safe.
817-
tag = deepcopy(st, self->tag, memo);
817+
tmp = Py_NewRef(self->tag);
818+
tag = deepcopy(st, tmp, memo);
819+
Py_DECREF(tmp);
818820
assert(self->tag != NULL);
819821
if (!tag)
820822
return NULL;
821823

822824
if (self->extra && self->extra->attrib) {
823-
// While deepcopy(self->extra->attrib) may cause 'self->extra' to be
824-
// NULL, we do not use it afterawrds without checking this, so no need
825-
// to temporarily incref 'self->extra->attrib'.
825+
tmp = Py_NewRef(self->extra->attrib);
826826
attrib = deepcopy(st, self->extra->attrib, memo);
827+
Py_DECREF(tmp);
827828
if (!attrib) {
828829
Py_DECREF(tag);
829830
return NULL;
@@ -840,16 +841,16 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo)
840841
if (!element)
841842
return NULL;
842843

843-
// Since the 'text' attribute is undeletable, deepcopy() should be safe.
844-
text = deepcopy(st, JOIN_OBJ(self->text), memo);
845-
assert(JOIN_OBJ(self->text) != NULL);
844+
tmp = Py_NewRef(JOIN_OBJ(self->text));
845+
text = deepcopy(st, tmp, memo);
846+
Py_DECREF(tmp);
846847
if (!text)
847848
goto error;
848849
_set_joined_ptr(&element->text, JOIN_SET(text, JOIN_GET(self->text)));
849850

850-
// Since the 'tail' attribute is undeletable, deepcopy() should be safe.
851-
tail = deepcopy(st, JOIN_OBJ(self->tail), memo);
852-
assert(JOIN_OBJ(self->tail) != NULL);
851+
tmp = Py_NewRef(JOIN_OBJ(self->tail));
852+
tail = deepcopy(st, tmp, memo);
853+
Py_DECREF(tmp);
853854
if (!tail)
854855
goto error;
855856
_set_joined_ptr(&element->tail, JOIN_SET(tail, JOIN_GET(self->tail)));
@@ -859,11 +860,10 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo)
859860
if (element_resize(element, self->extra->length) < 0)
860861
goto error;
861862

862-
// TODO(picnixz): should we protect against mutations from 'memo'?
863863
for (i = 0; self->extra && i < self->extra->length; i++) {
864-
PyObject* itemi = Py_NewRef(self->extra->children[i]);
865-
PyObject* child = deepcopy(st, itemi, memo);
866-
Py_DECREF(itemi);
864+
tmp = Py_NewRef(self->extra->children[i]);
865+
PyObject* child = deepcopy(st, tmp, memo);
866+
Py_DECREF(tmp);
867867
if (!child || !Element_Check(st, child)) {
868868
if (child) {
869869
raise_type_error(child);

0 commit comments

Comments
 (0)