https://github.com/python/cpython/commit/5056ac552a413b394fd189ac2c8b8a519a1c9580
commit: 5056ac552a413b394fd189ac2c8b8a519a1c9580
branch: main
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-09-03T00:10:23+03:00
summary:
gh-156797: Escape the namespace URI in xml.sax.saxutils.XMLGenerator (GH-156799)
The namespace declarations were the only attribute values written without
quoteattr(), so a URI containing "&", "<" or a quote character produced a
document which cannot be parsed.
files:
A Misc/NEWS.d/next/Library/2026-09-01-16-58-30.gh-issue-156797.Qm4tRs.rst
M Lib/test/test_sax.py
M Lib/xml/sax/saxutils.py
diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py
index 29babd7bf6996a..46b29650d9383b 100644
--- a/Lib/test/test_sax.py
+++ b/Lib/test/test_sax.py
@@ -614,6 +614,22 @@ def test_xmlgen_ns(self):
'<ns1:doc xmlns:ns1="%s"><udoc></udoc></ns1:doc>' %
ns_uri))
+ def test_xmlgen_ns_escaped_uri(self):
+ uri = 'http://example.org/?a="1"&b=<2>'
+ result = self.ioclass()
+ gen = XMLGenerator(result)
+
+ gen.startDocument()
+ gen.startPrefixMapping("ns1", uri)
+ gen.startElementNS((uri, "doc"), "ns1:doc", {})
+ gen.endElementNS((uri, "doc"), "ns1:doc")
+ gen.endPrefixMapping("ns1")
+ gen.endDocument()
+
+ self.assertEqual(result.getvalue(), self.xml(
+ """<ns1:doc
xmlns:ns1='http://example.org/?a="1"&b=<2>'>"""
+ "</ns1:doc>"))
+
def test_xmlgen_ns_empty(self):
result = self.ioclass()
gen = XMLGenerator(result, short_empty_elements=True)
diff --git a/Lib/xml/sax/saxutils.py b/Lib/xml/sax/saxutils.py
index 77ab9ee2faf038..920283c3f3496f 100644
--- a/Lib/xml/sax/saxutils.py
+++ b/Lib/xml/sax/saxutils.py
@@ -187,9 +187,9 @@ def startElementNS(self, name, qname, attrs):
for prefix, uri in self._undeclared_ns_maps:
if prefix:
- self._write(' xmlns:%s="%s"' % (prefix, uri))
+ self._write(' xmlns:%s=%s' % (prefix, quoteattr(uri)))
else:
- self._write(' xmlns="%s"' % uri)
+ self._write(' xmlns=%s' % quoteattr(uri))
self._undeclared_ns_maps = []
for (name, value) in attrs.items():
diff --git
a/Misc/NEWS.d/next/Library/2026-09-01-16-58-30.gh-issue-156797.Qm4tRs.rst
b/Misc/NEWS.d/next/Library/2026-09-01-16-58-30.gh-issue-156797.Qm4tRs.rst
new file mode 100644
index 00000000000000..7879ac7e71c71d
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-09-01-16-58-30.gh-issue-156797.Qm4tRs.rst
@@ -0,0 +1,3 @@
+Fix :class:`xml.sax.saxutils.XMLGenerator`: the namespace URI is now escaped
+in the namespace declaration. Previously a URI containing ``&``, ``<`` or a
+quote character produced a document which cannot be parsed.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]