frameobject: undefined 32-bit left shifts in `stack_swap()`

Ouverte
#161,666 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

Personne n'a encore pris cette issue.

Évaluation

Difficulté
2/5
Temps estimé
1-3 heures
Accessibilité débutants
35/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
c, python
Domaine
backend

Piste de recherche

The undefined shifts are in stack_swap() in Objects/frameobject.c, around line 1323, where MASK and top are shifted as 32-bit values. Read it alongside mark_stacks and frame_setlineno(), which call it. Run the reproducer under UBSan to see the shift warnings. Done means the shifts operate on 64-bit values and the sanitizer run is clean. The issue already links PR gh-161667, so check that before starting.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

interpreter-core type-crash
Crash report

stack_swap() in Objects/frameobject.c shifted MASK and top as
32-bit values and converted the result to int64_t, while the value-stack
model is a 63-bit int64_t and shift = BITS_PER_BLOCK*(n-1) can reach 60.
The shifts overflow / drop bits (undefined behavior) and corrupt the stack
model used by frame_setlineno() to validate line jumps.

import dis
import sys

fors = " ".join(f"for v{i} in range(1)" for i in range(11))
ns = {}
exec(f"def f():\n    return [0 {fors}]\n", ns)
f = ns["f"]

triggered = False
def tracer(frame, event, arg):
    global triggered
    if event == "line" and frame.f_code is f.__code__ and not triggered:
        triggered = True
        frame.f_lineno = frame.f_lineno  # mark_stacks -> stack_swap
    return tracer

sys.settrace(tracer)
try:
    f()
finally:
    sys.settrace(None)

UBSan output:

Objects/frameobject.c:1323:44: runtime error: shift exponent 33 is too large for 32-bit type 'int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior Objects/frameobject.c:1323:44 in 
Objects/frameobject.c:1323:62: runtime error: shift exponent 33 is too large for 32-bit type 'unsigned int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior Objects/frameobject.c:1323:62 in 

Found by Linux Verification Center (linuxtesting.org) with SVACE

CPython versions tested on:

CPython main branch

Operating systems tested on:

No response

Output from running 'python -VV' on the command line:

No response

Linked PRs
  • gh-161667
Langage dominant
Python
Étoiles
78.2k
Forks
36.6k
Merge moyen
19 h 57 min
PR mergées (30 j)
630

Préparer son environnement

Ouvrir dans Codespaces

Lance le conteneur de développement du projet dans votre navigateur, avec votre propre compte GitHub.

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de python/cpython

Toutes les issues de python/cpython

Issues similaires

Plus d'issues Python

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.