GeezerVison is showing github.com — Data race in `sys_set_flag` when `sys.set_int_max_str_digits()` is called concurrently with free-threaded build · Issue #151218 · python/cpython
Data race in sys_set_flag when sys.set_int_max_str_digits() is called concurrently with free-threaded build #151218Labels interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)topic-free-threadingtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error DescriptionBug report
Bug description:
sys.set_int_max_str_digits() updates sys.flags via sys_set_flag(), which modifies a shared struct-sequence slot without synchronization:
|
static void |
|
sys_set_flag(PyObject *flags, Py_ssize_t pos, PyObject *value) |
|
{ |
|
assert(pos >= 0 && pos < (Py_ssize_t)(Py_ARRAY_LENGTH(flags_fields) - 1)); |
|
|
|
PyObject *old_value = PyStructSequence_GET_ITEM(flags, pos); |
|
PyStructSequence_SET_ITEM(flags, pos, Py_NewRef(value)); |
|
Py_XDECREF(old_value); |
|
} |
Concurrent callers race on the slot and can Py_XDECREF the same old_value, leading to a use-after-free of the old flag object.
Reproducer:
import sys
from threading import Thread
def thread1():
for i in range (20000):
sys.set_int_max_str_digits(4300 + (i & 7))
threads = [Thread(target=thread1) for _ in range(4)]
for t in threads: t.start()
for t in threads: t.join()
TSAN Report:
==================
WARNING: ThreadSanitizer: data race (pid=1518581)
Read of size 8 at 0x7fffb63e01b8 by thread T1:
#0 PyStructSequence_GetItem /cpython/Objects/structseq.c:112:12
#1 sys_set_flag /cpython/./Python/sysmodule.c:3484:27
#2 _PySys_SetFlagObj /cpython/./Python/sysmodule.c:3498:5
#3 _PySys_SetFlagInt /cpython/./Python/sysmodule.c:3512:15
#4 _PySys_SetIntMaxStrDigits /cpython/./Python/sysmodule.c:4671:9
#5 sys_set_int_max_str_digits_impl /cpython/./Python/sysmodule.c:1894:9
#6 sys_set_int_max_str_digits /cpython/./Python/clinic/sysmodule.c.h:932:20
#7 _Py_BuiltinCallFastWithKeywords_StackRef /cpython/Python/ceval.c:839:11
#8 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:2508:35
Previous write of size 8 at 0x7fffb63e01b8 by thread T2:
#0 PyStructSequence_SetItem /cpython/Objects/structseq.c:100:27
#1 sys_set_flag /cpython/./Python/sysmodule.c:3485:5
#2 _PySys_SetFlagObj /cpython/./Python/sysmodule.c:3498:5
#3 _PySys_SetFlagInt /cpython/./Python/sysmodule.c:3512:15
#4 _PySys_SetIntMaxStrDigits /cpython/./Python/sysmodule.c:4671:9
#5 sys_set_int_max_str_digits_impl /cpython/./Python/sysmodule.c:1894:9
#6 sys_set_int_max_str_digits /cpython/./Python/clinic/sysmodule.c.h:932:20
#7 cfunction_vectorcall_FASTCALL_KEYWORDS /cpython/Objects/methodobject.c:465:24
#8 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11
#9 PyObject_Vectorcall /cpython/Objects/call.c:327:12
...
SUMMARY: ThreadSanitizer: data race /cpython/Objects/structseq.c:112:12 in PyStructSequence_GetItem
==================
==================
WARNING: ThreadSanitizer: data race (pid=1518581)
Read of size 4 at 0x7fffc004057c by thread T2:
#0 _Py_ExplicitMergeRefcount /cpython/Objects/object.c:477:40
#1 _Py_brc_queue_object /cpython/Python/brc.c:73:31
#2 _Py_DecRefSharedIsDead /cpython/Objects/object.c:413:9
#3 _Py_DecRefSharedDebug /cpython/Objects/object.c:425:9
#4 _Py_DecRefShared /cpython/Objects/object.c:433:5
#5 Py_DECREF /cpython/./Include/refcount.h:385:9
#6 Py_XDECREF /cpython/./Include/refcount.h:520:9
#7 sys_set_flag /cpython/./Python/sysmodule.c:3486:5
#8 _PySys_SetFlagObj /cpython/./Python/sysmodule.c:3498:5
#9 _PySys_SetFlagInt /cpython/./Python/sysmodule.c:3512:15
#10 _PySys_SetIntMaxStrDigits /cpython/./Python/sysmodule.c:4671:9
#11 sys_set_int_max_str_digits_impl /cpython/./Python/sysmodule.c:1894:9
#12 sys_set_int_max_str_digits /cpython/./Python/clinic/sysmodule.c.h:932:20
Previous atomic write of size 4 at 0x7fffc004057c by thread T3:
#0 _Py_atomic_store_uint32_relaxed /cpython/./Include/cpython/pyatomic_gcc.h:493:3
#1 Py_DECREF /cpython/./Include/refcount.h:379:9
#2 Py_XDECREF /cpython/./Include/refcount.h:520:9
#3 sys_set_flag /cpython/./Python/sysmodule.c:3486:5
#4 _PySys_SetFlagObj /cpython/./Python/sysmodule.c:3498:5
#5 _PySys_SetFlagInt /cpython/./Python/sysmodule.c:3512:15
#6 _PySys_SetIntMaxStrDigits /cpython/./Python/sysmodule.c:4671:9
#7 sys_set_int_max_str_digits_impl /cpython/./Python/sysmodule.c:1894:9
#8 sys_set_int_max_str_digits /cpython/./Python/clinic/sysmodule.c.h:932:20
...
SUMMARY: ThreadSanitizer: data race /cpython/Objects/object.c:477:40 in _Py_ExplicitMergeRefcount
==================
==================
WARNING: ThreadSanitizer: data race (pid=1518581)
Read of size 8 at 0x7fffc4042720 by thread T3:
#0 long_dealloc /cpython/Objects/longobject.c:3653:9
#1 _Py_Dealloc /cpython/Objects/object.c:3312:5
#2 _Py_brc_queue_object /cpython/Python/brc.c
#3 _Py_DecRefSharedIsDead /cpython/Objects/object.c:413:9
#4 _Py_DecRefSharedDebug /cpython/Objects/object.c:425:9
#5 _Py_DecRefShared /cpython/Objects/object.c:433:5
#6 Py_DECREF /cpython/./Include/refcount.h:385:9
#7 Py_XDECREF /cpython/./Include/refcount.h:520:9
#8 sys_set_flag /cpython/./Python/sysmodule.c:3486:5
#9 _PySys_SetFlagObj /cpython/./Python/sysmodule.c:3498:5
#10 _PySys_SetFlagInt /cpython/./Python/sysmodule.c:3512:15
#11 _PySys_SetIntMaxStrDigits /cpython/./Python/sysmodule.c:4671:9
#12 sys_set_int_max_str_digits_impl /cpython/./Python/sysmodule.c:1894:9
#13 sys_set_int_max_str_digits /cpython/./Python/clinic/sysmodule.c.h:932:20
Previous write of size 8 at 0x7fffc4042720 by thread T4:
#0 _PyLong_SetSignAndDigitCount /cpython/./Include/internal/pycore_long.h:307:27
#1 _PyLong_FromMedium /cpython/Objects/longobject.c:267:5
#2 PyLong_FromLong /cpython/Objects/longobject.c:409:5
#3 _PySys_SetFlagInt /cpython/./Python/sysmodule.c:3507:21
#4 _PySys_SetIntMaxStrDigits /cpython/./Python/sysmodule.c:4671:9
#5 sys_set_int_max_str_digits_impl /cpython/./Python/sysmodule.c:1894:9
#6 sys_set_int_max_str_digits /cpython/./Python/clinic/sysmodule.c.h:932:20
...
SUMMARY: ThreadSanitizer: data race /cpython/Objects/longobject.c:3653:9 in long_dealloc
==================
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Linked PRs
Activitybhuvi27 commented on Jun 10, 2026 I'd like to work on this. vstinner commented on Jun 16, 2026 Thanks for your bug report. It's now fixed in the main branch. 3.14 and 3.15 backports will follow.
MetadataMetadatainterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)topic-free-threadingtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error DevelopmentNo branches or pull requestsIssue actions
|