python / python/cpython

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

Aberta
#149,498 6 comentários 0 reações 0 responsáveis Ver no GitHub

Ninguém assumiu esta issue ainda.

stdlib
Linguagem predominante
Python
Estrelas
77.2k
Forks
35.9k
Métricas de merge de PRs
Métricas de PR pendentes

Descrição

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

Guia de contribuição

Abrir o guia de contribuição

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Direção de pesquisa

Comece pela implementação de FOR_ITER em bytecodes.c e pelo ponto de entrada de dis que calcula os destinos de salto. Compare o destino do iterador esgotado descrito no relatório com o comportamento em tempo de execução e, em seguida, adicione cobertura de regressão mostrando que o destino é POP_ITER, e não END_FOR.

Escrita pelo modelo de indexação a partir do texto da issue.

Avaliação

Stack de tecnologia
python
Domínio
devtools
Tipo de issue
Bug
Dificuldade
3/5
Tempo estimado
1-2 dias
Status de atividade
Estagnada
Clareza
Claramente especificada
Facilidade para iniciantes
35/100

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.