From dae08cf55b83caef5e8ee39b16417692e8565278 Mon Sep 17 00:00:00 2001 From: Pravin Kamble Date: Tue, 9 Dec 2025 11:57:52 +0530 Subject: 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 --- django/core/serializers/xml_serializer.py | 28 +++++++--------------- .../fixtures/invalid_deeply_nested_elements.xml | 10 ++++++++ tests/fixtures/tests.py | 9 +++++++ 3 files changed, 28 insertions(+), 19 deletions(-) create mode 100644 tests/fixtures/fixtures/invalid_deeply_nested_elements.xml diff --git a/django/core/serializers/xml_serializer.py b/django/core/serializers/xml_serializer.py index 910c489a37..a9fe3cf01d 100644 --- a/django/core/serializers/xml_serializer.py +++ b/django/core/serializers/xml_serializer.py @@ -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 diff --git a/tests/fixtures/fixtures/invalid_deeply_nested_elements.xml b/tests/fixtures/fixtures/invalid_deeply_nested_elements.xml new file mode 100644 index 0000000000..cd164d3d26 --- /dev/null +++ b/tests/fixtures/fixtures/invalid_deeply_nested_elements.xml @@ -0,0 +1,10 @@ + + + + + + Django pony + + + + diff --git a/tests/fixtures/tests.py b/tests/fixtures/tests.py index 48e3182b59..7511569d21 100644 --- a/tests/fixtures/tests.py +++ b/tests/fixtures/tests.py @@ -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() -- cgit v1.3