python / python/cpython

Data race reading `UnicodeDecodeError.start`/`end` in `__str__` under free-threading

Đang mở
#154,930 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

interpreter-core type-bug
Ngôn ngữ chính
Python
Star
77.2k
Fork
35.9k
Chỉ số merge pull request
Chỉ số pull request đang chờ

Mô tả

Bug report

Bug description:

On a free-threaded build, UnicodeDecodeError.__str__ reads the start and end members with plain (non-atomic) loads, while assigning to exc.start / exc.end goes through PyMember_SetOne, which does an atomic store. So calling str(exc) on a shared UnicodeDecodeError concurrently with setting its start/end is a data race on those Py_ssize_t members.

start and end are exposed as Py_T_PYSSIZET members:
https://github.com/python/cpython/blob/22a6c51c94a4fde986b8964f1d36d5ec3ac20dcc/Objects/exceptions.c#L3758-L3761

Plain read in UnicodeDecodeError_str:
https://github.com/python/cpython/blob/22a6c51c94a4fde986b8964f1d36d5ec3ac20dcc/Objects/exceptions.c#L3947-L3966

Reproducer:

from threading import Thread

shared_exc = UnicodeDecodeError('utf-8', b'\xff\xfe\xfa', 1, 2, 'invalid start byte')

def chain1_thread():
    for i in range(20000):
        try:
            shared_exc.start = i % 3
        except Exception:
            pass

def chain2_thread():
    for _ in range(20000):
        try:
            str(shared_exc)
        except Exception:
            pass

N_C1 = 4
N_C2 = 8
threads  = [Thread(target=chain1_thread) for _ in range(N_C1)]
threads += [Thread(target=chain2_thread) for _ in range(N_C2)]
for t in threads: t.start()
for t in threads: t.join()

TSAN Report:

WARNING: ThreadSanitizer: data race (pid=656224)
  Read of size 8 at 0x7fffb63734e8 by thread T5:
    #0 UnicodeDecodeError_str /cpython/Objects/exceptions.c:3948:29 
    #1 PyObject_Str /cpython/Objects/object.c:826:11 
    #2 unicode_vectorcall /cpython/Objects/unicodeobject.c:14279:16 
    #3 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 
    #4 PyObject_Vectorcall /cpython/Objects/call.c:327:12 
    #5 _Py_VectorCallInstrumentation_StackRefSteal /cpython/Python/ceval.c:768:11 
    #6 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:1906:35

  Previous atomic write of size 8 at 0x7fffb63734e8 by thread T3:
    #0 PyMember_SetOne /cpython/Python/structmember.c 
    #1 member_set /cpython/Objects/descrobject.c:239:12 
    #2 _PyObject_GenericSetAttrWithDict /cpython/Objects/object.c:2049:19 
    #3 PyObject_GenericSetAttr /cpython/Objects/object.c:2120:12 
    #4 PyObject_SetAttr /cpython/Objects/object.c:1533:15 
    #5 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:12057:27

SUMMARY: ThreadSanitizer: data race/cpython/Objects/exceptions.c:3948:29 in UnicodeDecodeError_str
CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs
  • gh-155255

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Bắt đầu trong Objects/exceptions.c tại các khai báo member Py_T_PYSSIZET và UnicodeDecodeError_str, sau đó chạy threading reproducer được cung cấp trên một bản build free-threaded và kiểm tra báo cáo TSAN. Hoàn thành khi race được báo cáo đã được xử lý và các bài kiểm thử CPython liên quan đều đạt.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
c, python
Lĩnh vực
operating-systems
Loại issue
Lỗi
Độ khó
3/5
Thời gian dự kiến
1-2 ngày
Mức độ hoạt động
Đình trệ
Độ rõ ràng
Đặc tả rõ ràng
Mức phù hợp với người mới
25/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.