Recursion Error: Process_element / process_tag mutual recursion (infinite loop)
评估
调研方向
先在 markdownify/init.py 中阅读 process_element 和 process_tag,然后使用包含循环引用的 HTML 树重现 RecursionError。跟踪子元素处理如何经过这两个方法,并验证转换能够在不耗尽堆栈的情况下终止,同时正常的 HTML 转换保持不变。
由索引模型根据 Issue 内容生成。
描述
When converting HTML that contains circular parent-child references in the parsed BeautifulSoup tree (produced by certain PDF-to-HTML pipelines), process_element and process_tag recurse infinitely, crashing with a RecursionError.
Encountered when using markdownify via marker-pdf to convert PDF documents. The HTML produced by the PDF parser contained structures that caused BeautifulSoup's html.parser to create a non-tree graph where a descendant node held a reference back to an ancestor creating an unbounded call stack.
The mutual recursion introduced in 1.2.2 between process_element and process_tag has no cycle guard:
- process_tag iterates node.children and calls process_element for each child
- process_element calls process_tag for any Tag node
RecursionError: maximum recursion depth exceeded
File "markdownify/__init__.py", line 232, in process_element
return self.process_tag(node, parent_tags=parent_tags)
File "markdownify/__init__.py", line 287, in process_tag
child_strings = [
File "markdownify/__init__.py", line 288, in <listcomp>
self.process_element(el, parent_tags=parent_tags_for_children)
File "markdownify/__init__.py", line 232, in process_element
return self.process_tag(node, parent_tags=parent_tags)
... (repeating until stack exhausted)
Suggested fix:
Pass a visited set of node ids through the call chain to detect and break cycles:
def process_element(self, node, parent_tags=None, _visited=None):
if isinstance(node, NavigableString):
return self.process_text(node, parent_tags=parent_tags)
else:
return self.process_tag(node, parent_tags=parent_tags, _visited=_visited)
def process_tag(self, node, parent_tags=None, _visited=None):
if parent_tags is None:
parent_tags = set()
# Cycle detection
if _visited is None:
_visited = set()
node_id = id(node)
if node_id in _visited:
return ''
_visited.add(node_id)
# ... rest of method unchanged, but pass _visited= to process_element calls
child_strings = [
self.process_element(el, parent_tags=parent_tags_for_children, _visited=_visited)
for el in children_to_convert
]
- 主要语言
- Python
- 星标
- 2.3k
- 派生
- 210
- PR 合并指标
- 30 天内没有已合并 PR
环境准备
这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
matthewwithanm/python-markdownify 的其他 Issue
-
Trailing whitespace strip in <pre> is quadratic on a long whitespace run可能已有人在做 @ac1982 于 4 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 78/100
-
RecursionError on deeply nested HTML (about 330 levels), separate from the cyclic-tree case in #256可能已有人在做 @HardMax71 于 42 天前认领。 未关闭
难度 3/5 1-2 天 新手友好度 68/100
-
Image/link attributes containing `]`, `)`, or spaces produce broken Markdown output可能已有人在做 @assinscreedFC 于 132 天前认领。 未关闭
难度 4/5 3-5 天 新手友好度 52/100
matthewwithanm/python-markdownify#261 · 1 条评论 · 1 个 reaction ·
-
难度 3/5 1-2 天 新手友好度 65/100
matthewwithanm/python-markdownify#259 · 2 个 reaction ·
-
Behavior with strip_pre=mdfy.STRIP_ONE seems incorrect with trailing newlines within the pre可能已有人在做 @oiahoon 于 95 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 50/100
查看 matthewwithanm/python-markdownify 的全部 Issue
相似的 Issue
-
`burr` fails to start when the Python path has a space in it可能已有人在做 @enekoreto 今天认领。 未关闭status/needs-triage
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 5 天内回复
-
难度 1/5 1 小时以内 新手友好度 72/100
-
难度 2/5 半天 新手友好度 72/100
debpalash/VoiceStudio#2903 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 72/100
dagster-io/community-integrations#367 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 74/100
aws-samples/sample-per-model-bedrock#243 ·
维护者通常 1 天内回复