diff --git a/docs/changelog.md b/docs/changelog.md index 1f4307cd..38f43e96 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Remove legacy import needed only in Python 2 (#1403) * Fix typo that left the attribute `AdmonitionProcessor.content_indent` unset (#1404) +* Fix edge-case crash in `InlineProcessor` with `AtomicString` (#1406). * Improve and expand type annotations in the code base (#1401). ## [3.5.1] -- 2023-10-31 diff --git a/markdown/treeprocessors.py b/markdown/treeprocessors.py index dc857204..46d9c0cb 100644 --- a/markdown/treeprocessors.py +++ b/markdown/treeprocessors.py @@ -218,7 +218,7 @@ def linkText(text: str | None) -> None: text = data[strartIndex:index] linkText(text) - if not isString(node): # it's Element + if isinstance(node, str): # it's Element for child in [node] + list(node): if child.tail: if child.tail.strip(): @@ -304,7 +304,7 @@ def __applyPattern( if node is None: return data, True, end - if not isString(node): + if not isinstance(node, str): if not isinstance(node.text, util.AtomicString): # We need to process current node too for child in [node] + list(node): diff --git a/tests/test_apis.py b/tests/test_apis.py index d613a822..fbb46e60 100644 --- a/tests/test_apis.py +++ b/tests/test_apis.py @@ -30,6 +30,7 @@ import markdown import warnings from markdown.__main__ import parse_options +from markdown import inlinepatterns from logging import DEBUG, WARNING, CRITICAL import yaml import tempfile @@ -664,8 +665,8 @@ class testAtomicString(unittest.TestCase): """ Test that `AtomicStrings` are honored (not parsed). """ def setUp(self): - md = markdown.Markdown() - self.inlineprocessor = md.treeprocessors['inline'] + self.md = markdown.Markdown() + self.inlineprocessor = self.md.treeprocessors['inline'] def testString(self): """ Test that a regular string is parsed. """ @@ -710,6 +711,26 @@ def testNestedAtomicString(self): '*to* *test* *with*

' ) + def testInlineProcessorDoesntCrashWithAtomicString(self): + """ Test that an `AtomicString` returned from a Pattern doesn't cause a crash. """ + tree = etree.Element('div') + p = etree.SubElement(tree, 'p') + p.text = 'a marker c' + self.md.inlinePatterns.register( + _InlineProcessorThatReturnsAtomicString(r'marker', self.md), 'test', 100 + ) + new = self.inlineprocessor.run(tree) + self.assertEqual( + markdown.serializers.to_html_string(new), + '

a atomic c

' + ) + + +class _InlineProcessorThatReturnsAtomicString(inlinepatterns.InlineProcessor): + """ Return a simple text of `group(1)` of a Pattern. """ + def handleMatch(self, m, data): + return markdown.util.AtomicString('atomic'), m.start(0), m.end(0) + class TestConfigParsing(unittest.TestCase): def assertParses(self, value, result):