Data race: ctypes `PyCData_NewGetBuffer` reads `b_ptr` without the critical section `_ctypes_resize` holds
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
Bug description:
#131336 / #128182 made ctypes.resize and addressof/byref thread-safe by taking a critical section in _ctypes_resize, which reallocates obj->b_ptr:
But the buffer-protocol getbuffer, PyCData_NewGetBuffer (reached via memoryview(cdata)), reads self->b_ptr without that critical section:
So memoryview(obj) racing ctypes.resize(obj) reads a b_ptr that resize concurrently reallocates.
Reproducer:
import ctypes
from threading import Thread
buf = (ctypes.c_char * 64)()
def viewer():
for _ in range(20000):
try:
memoryview(buf)
except Exception:
pass
def resizer():
for i in range(20000):
try:
ctypes.resize(buf, 128 if (i & 1) else 256)
except Exception:
pass
threads = [Thread(target=viewer) for _ in range(6)]
threads += [Thread(target=resizer) for _ in range(2)]
for t in threads: t.start()
for t in threads: t.join()
TSAN Report:
==================
WARNING: ThreadSanitizer: data race (pid=1524546)
Read of size 8 at 0x7fffb6b50208 by thread T1:
#0 PyCData_NewGetBuffer /cpython/./Modules/_ctypes/_ctypes.c:3129:23
#1 PyObject_GetBuffer /cpython/Objects/abstract.c:455:15
#2 _PyManagedBuffer_FromObject /cpython/Objects/memoryobject.c:97:9
#3 PyMemoryView_FromObjectAndFlags /cpython/Objects/memoryobject.c:813:42
#4 PyMemoryView_FromObject /cpython/Objects/memoryobject.c:856:12
#5 memoryview_impl /cpython/Objects/memoryobject.c:1017:12
#6 memoryview /cpython/Objects/clinic/memoryobject.c.h:63:20
#7 type_call /cpython/Objects/typeobject.c:2472:11
#8 _PyObject_MakeTpCall /cpython/Objects/call.c:242:18
#9 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:142:16)
#10 PyObject_Vectorcall /cpython/Objects/call.c:327:12
#11 _Py_VectorCall_StackRefSteal /cpython/Python/ceval.c:726:11
#12 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:4559:35
Previous write of size 8 at 0x7fffb6b50208 by thread T7:
#0 _ctypes_resize_impl /cpython/./Modules/_ctypes/callproc.c
#1 _ctypes_resize /cpython/./Modules/_ctypes/clinic/callproc.c.h:139:20
#2 _Py_BuiltinCallFast_StackRef /cpython/Python/ceval.c:817:11
#3 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:2510:35
#4 _PyEval_EvalFrame /cpython/./Include/internal/pycore_ceval.h:122:16
SUMMARY: ThreadSanitizer: data race /cpython/./Modules/_ctypes/_ctypes.c:3129:23 in PyCData_NewGetBuffer
==================
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Linked PRs
- gh-157759
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 Modules/_ctypes/_ctypes.c au niveau de PyCData_NewGetBuffer et comparez son accès à b_ptr avec la section critique de Modules/_ctypes/callproc.c au niveau de _ctypes_resize_impl. Exécutez le reproducer multithread fourni avec ThreadSanitizer. Le travail est terminé lorsque la course entre memoryview et ctypes.resize n’est plus signalée, tandis que le comportement existant reste intact.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- c, python
- Domaine
- backend
- Type d'issue
- Bug
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Activité
- À l'abandon
- Clarté
- Clairement spécifiée
- Accessibilité débutants
- 30/100