From a96a8f814f0bdae57904fe980ce5a16d2a1fbf9f Mon Sep 17 00:00:00 2001 From: Kienan Stewart Date: Fri, 12 Dec 2025 10:44:47 -0500 Subject: [PATCH] Fix: `clang_getClangVersion()` does not return `ctypes.c_char_p` The return value of `clang_getClangVersion()` is a CXString structure. Depending on the architecture the structure can be returned on the stack or via a register. When assuming it is a `ctypes.c_char_p`, the ctypes FFI call will segfault upon return on armhf due to not properly handling how the architecture is returning the data. Properly setting the return type for `clang_getClangVersion()` will avoid the segfault. Signed-off-by: Kienan Stewart --- ctypeslib/__init__.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/ctypeslib/__init__.py b/ctypeslib/__init__.py index 7774a27..23f9516 100644 --- a/ctypeslib/__init__.py +++ b/ctypeslib/__init__.py @@ -53,15 +53,28 @@ def __find_clang_libraries(): def clang_version(): """Pull the clang C library version from the API""" + + class CXString(ctypes.Structure): + _fields_ = [ + ("data", ctypes.c_char_p), + ("private_flags", ctypes.c_uint), + ] + # avoid loading the cindex API (cindex.conf.lib) to avoid version conflicts get_version = cindex.conf.get_cindex_library().clang_getClangVersion - get_version.restype = ctypes.c_char_p - version_string = get_version() - version = 'Unknown' + get_version.restype = CXString + + get_cstring = cindex.conf.get_cindex_library().clang_getCString + get_cstring.restype = ctypes.c_char_p + + version_cxstring = get_version() + version_string = get_cstring(version_cxstring) if version_string and len(version_string) > 0: version_groups = re.match(br'.+version ((\d+\.)?(\d+\.)?(\*|\d+))', version_string) if version_groups and len(version_groups.groups()) > 0: version = version_groups.group(1).decode() + + cindex.conf.get_cindex_library().clang_disposeString(version_cxstring) return version