GeezerVison is showing github.com — gh-146174: Prevent re-entrant Parse() calls in pyexpat · python/cpython@c924f57
File tree
Expand file treeCollapse file tree
Open diff view settings
Expand file treeCollapse file tree
Open diff view settings
Collapse file
Copy file name to clipboardExpand all lines: Lib/test/test_pyexpat.py +26Lines changed: 26 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -276,6 +276,32 @@ def test_parse_again(self): |
276 | 276 | self.assertEqual(expat.ErrorString(cm.exception.code), |
277 | 277 | expat.errors.XML_ERROR_FINISHED) |
278 | 278 |
|
| 279 | + def test_reentrant_parse_crash(self): |
| 280 | + from xml.parsers import expat |
| 281 | + p = expat.ParserCreate(encoding="utf-16") |
| 282 | + |
| 283 | + def start(name, attrs): |
| 284 | + def handler(data): |
| 285 | + p.Parse(data, 0) |
| 286 | + p.CharacterDataHandler = handler |
| 287 | + |
| 288 | + p.StartElementHandler = start |
| 289 | + data = b"\xff\xfe<\x00a\x00>\x00x\x00" |
| 290 | + with self.assertRaises(RuntimeError) as cm: |
| 291 | + for i in range(len(data)): |
| 292 | + p.Parse(data[i:i+1], i == len(data) - 1) |
| 293 | + self.assertEqual(str(cm.exception), |
| 294 | + "cannot call Parse() from within a handler") |
| 295 | + |
| 296 | + def test_parse_normal(self): |
| 297 | + from xml.parsers import expat |
| 298 | + p = expat.ParserCreate() |
| 299 | + data = "<root><child/></root>".encode('utf-8') |
| 300 | + try: |
| 301 | + p.Parse(data, 1) |
| 302 | + except RuntimeError: |
| 303 | + self.fail("Parse() raised RuntimeError during normal operation") |
| 304 | + |
279 | 305 | class NamespaceSeparatorTest(unittest.TestCase): |
280 | 306 | def test_legal(self): |
281 | 307 | # Tests that make sure we get errors when the namespace_separator value |
|
Collapse file
Copy file name to clipboard +9Lines changed: 9 additions & 0 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
|
| 1 | +.. gh-issue: 146169 |
| 2 | +
|
| 3 | +.. section: Library |
| 4 | +
|
| 5 | +Prevent re-entrant calls to ``Parse()`` from within expat handlers, |
| 6 | +which |
| 7 | +could cause a crash. Now raises :exc:`RuntimeError` when such a |
| 8 | +call is |
| 9 | +attempted. |
Collapse file
Copy file name to clipboardExpand all lines: Modules/pyexpat.c +7Lines changed: 7 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -857,6 +857,13 @@ pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyTypeObject *cls, |
857 | 857 | PyObject *data, int isfinal) |
858 | 858 | /*[clinic end generated code: output=8faffe07fe1f862a input=053e0f047e55c05a]*/ |
859 | 859 | { |
| 860 | + |
| 861 | + if (self->in_callback) { |
| 862 | + PyErr_SetString(PyExc_RuntimeError, |
| 863 | + "cannot call Parse() from within a handler"); |
| 864 | + return NULL; |
| 865 | + } |
| 866 | + |
860 | 867 | const char *s; |
861 | 868 | Py_ssize_t slen; |
862 | 869 | Py_buffer view; |
|