[3.13] gh-133009: fix UAF in xml.etree.ElementTree.Element.__deepcopy__ (GH-133010) (#133806)

gh-133009: fix UAF in `xml.etree.ElementTree.Element.__deepcopy__` (GH-133010)
(cherry picked from commit 116a9f9b37)

Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
This commit is contained in:
Miss Islington (bot) 2025-05-10 09:55:47 +02:00 committed by GitHub
parent 57efb77fef
commit 9718880ba9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 81 additions and 7 deletions

View file

@ -2960,6 +2960,50 @@ class BadElementTest(ElementTestCase, unittest.TestCase):
del b
gc_collect()
def test_deepcopy_clear(self):
# Prevent crashes when __deepcopy__() clears the children list.
# See https://github.com/python/cpython/issues/133009.
class X(ET.Element):
def __deepcopy__(self, memo):
root.clear()
return self
root = ET.Element('a')
evil = X('x')
root.extend([evil, ET.Element('y')])
if is_python_implementation():
# Mutating a list over which we iterate raises an error.
self.assertRaises(RuntimeError, copy.deepcopy, root)
else:
c = copy.deepcopy(root)
# In the C implementation, we can still copy the evil element.
self.assertListEqual(list(c), [evil])
def test_deepcopy_grow(self):
# Prevent crashes when __deepcopy__() mutates the children list.
# See https://github.com/python/cpython/issues/133009.
a = ET.Element('a')
b = ET.Element('b')
c = ET.Element('c')
class X(ET.Element):
def __deepcopy__(self, memo):
root.append(a)
root.append(b)
return self
root = ET.Element('top')
evil1, evil2 = X('1'), X('2')
root.extend([evil1, c, evil2])
children = list(copy.deepcopy(root))
# mock deep copies
self.assertIs(children[0], evil1)
self.assertIs(children[2], evil2)
# true deep copies
self.assertEqual(children[1].tag, c.tag)
self.assertEqual([c.tag for c in children[3:]],
[a.tag, b.tag, a.tag, b.tag])
class MutationDeleteElementPath(str):
def __new__(cls, elem, *args):