dis: FOR_ITER reports wrong exhausted-path jump target (END_FOR instead of POP_ITER)
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- Python
- Star
- 77.2k
- Fork
- 35.9k
- Chỉ số merge pull request
- Chỉ số pull request đang chờ
Mô tả
Bug Report
Bug description:
In Python 3.15, dis reports the wrong jump target for FOR_ITER when the iterator is exhausted. The reported target lands on END_FOR, but the CPython runtime actually jumps one instruction past it to POP_ITER.
Root cause: In bytecodes.c, FOR_ITER uses JUMPBY(oparg + 1) to skip past END_FOR. However, dis computes the jump target as NIP + oparg * 2 bytes (without the +1), landing on END_FOR rather than POP_ITER.
import dis
def f():
for x in [1, 2, 3]:
pass
instrs = {i.offset: i for i in dis.get_instructions(f.__code__, show_caches=True)}
for i in dis.get_instructions(f.__code__):
if i.opname == "FOR_ITER":
for_iter = i
# dis reports this as the jump target:
reported_target = for_iter.jump_target
reported_name = instrs[reported_target].opname # "END_FOR"
# CPython runtime actually jumps here (oparg+1 instructions past NIP):
nip = for_iter.offset + 4 # 4 bytes = FOR_ITER word + CACHE word
actual_target = nip + (for_iter.arg + 1) * 2
actual_name = instrs[actual_target].opname # "POP_ITER"
print(f"dis reports: offset {reported_target} = {reported_name}") # END_FOR
print(f"runtime jumps: offset {actual_target} = {actual_name}") # POP_ITER
Output:
dis reports: offset 20 = END_FOR
runtime jumps: offset 22 = POP_ITER
The stack-effect model remains self-consistent (FOR_ITER +1, END_FOR -1, POP_ITER -2), but the reported jump target is misleading to any tool that builds a control-flow graph from dis output. The exhausted-iterator edge should point to POP_ITER, not END_FOR.
CPython versions tested on:
CPython main branch (3.15)
Operating systems tested on:
macOS
Linked PRs
- gh-149503
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Bắt đầu với việc triển khai FOR_ITER trong bytecodes.c và điểm vào dis tính toán các đích nhảy. So sánh đích của iterator đã cạn được mô tả trong báo cáo với hành vi khi chạy, sau đó bổ sung độ bao phủ hồi quy cho thấy đích là POP_ITER chứ không phải END_FOR.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- python
- Lĩnh vực
- devtools
- Loại issue
- Lỗi
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức phù hợp với người mới
- 35/100