summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPravin Kamble <iampbkamble@gmail.com>2025-12-09 11:57:52 +0530
committerJacob Walls <jacobtylerwalls@gmail.com>2025-12-11 12:38:04 -0500
commitdae08cf55b83caef5e8ee39b16417692e8565278 (patch)
tree92a4b3b3b82c59e19195cb1ee9767adac0267be7
parent37eb8909699d261b9b879e6f04dbfeec75b5e080 (diff)
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>
-rw-r--r--django/core/serializers/xml_serializer.py28
-rw-r--r--tests/fixtures/fixtures/invalid_deeply_nested_elements.xml10
-rw-r--r--tests/fixtures/tests.py9
3 files changed, 28 insertions, 19 deletions
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 @@
+<?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>
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()