Fixed #36769 -- Avoided visiting deeply nested nodes in XML deserializer.

Only children at one level of depth need to be visited.

Co-authored-by: Jacob Walls <jacobtylerwalls@gmail.com>
This commit is contained in:
Pravin Kamble 2025-12-09 11:57:52 +05:30 committed by Jacob Walls
parent 37eb890969
commit dae08cf55b
3 changed files with 28 additions and 19 deletions

View file

@ -416,27 +416,17 @@ class Deserializer(base.Deserializer):
def getInnerText(node):
"""Get all the inner text of a DOM node (recursively)."""
inner_text_list = getInnerTextList(node)
return "".join(inner_text_list)
def getInnerTextList(node):
"""Return a list of the inner texts of a DOM node (recursively)."""
"""Get the inner text of a DOM node and any children one level deep."""
# inspired by
# https://mail.python.org/pipermail/xml-sig/2005-March/011022.html
result = []
for child in node.childNodes:
if (
child.nodeType == child.TEXT_NODE
or child.nodeType == child.CDATA_SECTION_NODE
):
result.append(child.data)
elif child.nodeType == child.ELEMENT_NODE:
result.extend(getInnerTextList(child))
else:
pass
return result
return "".join(
[
element.data
for child in node.childNodes
for element in (child, *child.childNodes)
if element.nodeType in (element.TEXT_NODE, element.CDATA_SECTION_NODE)
]
)
# Below code based on Christian Heimes' defusedxml

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<django-objects version="1.0">
<object pk="1" model="fixtures.person">
<field type="CharField" name="name">
<natural>Django <em>pony</em></natural>
</field>
</object>
</django-objects>

View file

@ -23,6 +23,7 @@ from .models import (
CircularA,
CircularB,
NaturalKeyThing,
Person,
PrimaryKeyUUIDModel,
ProxySpy,
Spy,
@ -520,6 +521,14 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase):
natural_foreign_keys=True,
)
def test_deeply_nested_elements(self):
"""Text inside deeply-nested tags is skipped."""
management.call_command(
"loaddata", "invalid_deeply_nested_elements.xml", verbosity=0
)
person = Person.objects.get(pk=1)
self.assertEqual(person.name, "Django") # not "Django pony"
def test_dumpdata_with_excludes(self):
# Load fixture1 which has a site, two articles, and a category
Site.objects.all().delete()