From 11956d7d720051268ff8f91ebdd01f81ba3ee69d Mon Sep 17 00:00:00 2001 From: dynapx <2310384514@qq.com> Date: Tue, 14 Jul 2026 15:24:51 +0800 Subject: [PATCH] Fix C-API exception handling issues - Add PyErr_SetString for PyThread_allocate_lock failure (ffi_init_once: lock allocation failure does not set exception) - Add PyErr_NoMemory for ctypedescr_new OOM (new_struct_or_union_type: ctypedescr_new does not set exception on OOM) - Fix signed char -1 false negative detection (convert_from_object: -1 is valid signed char value, check PyErr_Occurred) - Preserve exceptions in _convert_to_char16_t/_convert_to_char32_t (avoid overwriting existing exception from _my_PyUnicode_AsSingleChar*) --- src/c/_cffi_backend.c | 3 ++- src/c/ffi_obj.c | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/c/_cffi_backend.c b/src/c/_cffi_backend.c index b8b3d8ff..c6bf45cd 100644 --- a/src/c/_cffi_backend.c +++ b/src/c/_cffi_backend.c @@ -1762,7 +1762,7 @@ convert_from_object(char *data, CTypeDescrObject *ct, PyObject *init) switch (ct->ct_size) { case sizeof(char): { int res = _convert_to_char(init); - if (res < 0) + if (res < 0 && PyErr_Occurred()) return -1; data[0] = res; return 0; @@ -5009,6 +5009,7 @@ static PyObject *new_struct_or_union_type(const char *name, int flag) int namelen = strlen(name); CTypeDescrObject *td = ctypedescr_new(namelen + 1); if (td == NULL) + PyErr_NoMemory(); /* ctypedescr_new does not set an exception on OOM */ return NULL; td->ct_size = -1; diff --git a/src/c/ffi_obj.c b/src/c/ffi_obj.c index fbba2894..e1a1d1b8 100644 --- a/src/c/ffi_obj.c +++ b/src/c/ffi_obj.c @@ -1014,7 +1014,12 @@ static PyObject *ffi_init_once(FFIObject *self, PyObject *args, PyObject *kwds) if (tup == NULL) { lock = PyThread_allocate_lock(); if (lock == NULL) + { + PyErr_SetString(PyExc_RuntimeError, + "failed to allocate thread lock for init_once"); return NULL; + } + x = PyCapsule_New(lock, "cffi_init_once_lock", _free_init_once_lock); if (x == NULL) { PyThread_free_lock(lock);