python / python/cpython

dis: FOR_ITER reports wrong exhausted-path jump target (END_FOR instead of POP_ITER)

Đang mở
#149,498 6 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

stdlib
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

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. 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.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. 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

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.