compile: double free of pc->fail_pop in codegen_pattern_or on allocation failure with nested or-pattern
維護者通常 1 天內回覆
還沒有人認領這個 Issue。
評估
研究方向
Start in Python/codegen.c at codegen_pattern_or and codegen_match, using the reported lines 6573 and 6775 to trace ownership of fail_pop through the allocation failure path. Reproduce with the provided _testcapi.call_with_nomemory script on an ASan build; done when injected failures raise MemoryError, the pointer is freed once, and the script prints “survived.”
由索引模型根據 Issue 內容生成。
描述
When an allocation fails while compiling a match statement whose or-pattern contains another or-pattern, codegen_pattern_or frees pc->fail_pop and codegen_match then frees it again, so compile() crashes instead of raising MemoryError.
The failure is injected with the test-only _testcapi.call_with_nomemory:
import ast, _testcapi
tree = ast.parse('def f(x):\n match x:\n case [1|2] | 3: pass\n')
for off in range(1500):
held = None
held = [[] for _ in range(128)] # refill/empty the list freelist so PyList_New in codegen really allocates
try:
_testcapi.call_with_nomemory(off, off + 1, compile, tree, 'a.py', 'exec')
except (MemoryError, SyntaxError):
pass
print('survived')
Saved as input.py and run on an ASan build that includes _testcapi:
python input.py
Output:
ERROR: AddressSanitizer: heap-use-after-free on address 0x503000002988
READ of size 1 at 0x503000002988 thread T0
#0 in _PyMem_DebugCheckAddress Objects/obmalloc.c:3351
#4 in PyMem_Free Objects/obmalloc.c:1292
#5 in codegen_match Python/codegen.c:6775
...
freed by thread T0 here:
#5 in PyMem_Free Objects/obmalloc.c:1292
#6 in codegen_pattern_or Python/codegen.c:6573
Every injected failure should surface as MemoryError from compile(), with the pointer freed once, and the script should print survived.
Found at commit 3646ea571f3d8290806a3029d555b179f8be1539. It still reproduces at 3acc941f2b72 (latest upstream checked): ASan heap-use-after-free in the checking build, and the release build segfaults (exit code 139). case (1|2) | 3, where the inner or-pattern is not inside a sequence pattern, survives.
Looks like in the inner codegen_pattern_or, old_pc = *pc copies the outer fail_pop array, and if the first PyList_New(0) in the loop fails, goto error runs before pc->fail_pop = NULL. The error block then frees old_pc.fail_pop while pc->fail_pop still points to it, and codegen_match frees it again.
Found with an LLM-based testing tool; I used Claude to reduce it and look for the cause.
Linked PRs
- gh-160875
- 主要語言
- Python
- 星號
- 77.8k
- 分支
- 37.7k
- 平均合併
- 17 小時 2 分鐘
- 30 天內合併 PR
- 699
環境準備
在瀏覽器裡用你自己的 GitHub 帳號啟動這個專案的開發容器。
- 沒有 Dockerfile 或 Docker Compose 檔案
- 有 Pull Request 範本
- 閱讀貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
python/cpython 的其他 Issue
-
build OS-unsupported OS-windows type-bug
難度 2/5 1-3 小時 新手友好度 60/100
維護者通常 1 天內回覆
-
What's New in 3.12 credits the unstable C API tier to PEP 697 instead of PEP 689可能已有人在做 @TheLouisMahdi 於 2 天前認領。 未關閉docs
難度 1/5 1 小時以內 新手友好度 82/100
python/cpython#161078 · 3 則留言 ·
維護者通常 1 天內回覆
-
OS-windows type-bug
難度 2/5 1-3 小時 新手友好度 68/100
維護者通常 1 天內回覆
-
docs
難度 2/5 1-3 小時 新手友好度 72/100
python/cpython#161007 · 4 則留言 ·
維護者通常 1 天內回覆
-
Null dereferencing of a pointer in initconfig.c可能已有人在做 @lazerg 於 4 天前認領。 未關閉interpreter-core topic-C-API type-bug
難度 2/5 1-3 小時 新手友好度 72/100
python/cpython#160962 · 4 則留言 ·
維護者通常 1 天內回覆
相似的 Issue
-
DBFS append mode silently overwrites existing files可能已有人在做 @IlyaKhalafi 今天認領。 未關閉
難度 2/5 1-3 小時 新手友好度 77/100
fsspec/filesystem_spec#2429 ·
維護者通常 1 天內回覆
-
bug
難度 2/5 1-3 小時 新手友好度 78/100
volcengine/OpenViking#7014 ·
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 68/100
fedora-copr/copr#4600 ·
維護者通常 2 天內回覆
-
bug
難度 2/5 1-3 小時 新手友好度 72/100
ansys/pydpf-core#3620 ·
維護者通常 1 天內回覆
-
bug
難度 2/5 1-3 小時 新手友好度 78/100
維護者通常 1 天內回覆