marshal.dumps() crashes when an item's __buffer__ concurrently mutates the container
Personne n'a encore pris cette issue.
- Langage dominant
- Python
- Étoiles
- 77.2k
- Forks
- 35.9k
- Métriques de merge des PR
- Métriques de PR en attente
Description
Bug report
marshal.dumps() can crash the interpreter when serializing a list, dict
or set containing an item that supports the buffer protocol, if the item's
__buffer__() (PEP 688) concurrently mutates the container being serialized.
w_complex_object() hands each item to w_object(), which for a buffer item
reaches PyObject_GetBuffer() and runs the item's __buffer__() — arbitrary
Python that can clear, shrink, grow, or drop the last reference to the
container (or to a borrowed key/value) while it is still being iterated.
Reproducer
import marshal
class Evil:
def __buffer__(self, flags):
container.clear() # mutate the container mid-serialization
return memoryview(bytearray(4))
container = {Evil(), 1, 2, 3} # also reproduces with list and dict
marshal.dumps(container)
On a debug build the set case aborts at assert(i == n); the dict and
list cases segfault through a use-after-free or an out-of-bounds read, and a
set whose element instead grows the set writes past the pairs buffer that
was pre-sized to the original length.
Notes
This is a robustness issue, not a security vulnerability: triggering it
requires a custom __buffer__() — i.e. the ability to run arbitrary in-process
Python — and marshal is
documented as not intended
for serializing untrusted data.
Same family as the recently fixed bytes.join crash in gh-151295.
Linked PRs
- gh-151371
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Piste de recherche
Commencez par w_complex_object() et w_object(), puis examinez comment PyObject_GetBuffer() peut exécuter buffer() pendant la sérialisation de list, dict et set. Reproduisez les cas fournis dans une build de débogage et vérifiez que la mutation du conteneur ne provoque plus d’abort, de Use-after-free, de lecture hors limites ni de dépassement de tampon.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- python
- Domaine
- backend
- Type d'issue
- Bug
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Activité
- À l'abandon
- Clarté
- Plutôt claire
- Accessibilité débutants
- 25/100