From e81a294cdbfff457f74cbc01d0dba65695dff4ad Mon Sep 17 00:00:00 2001 From: Stian Halseth Date: Fri, 6 Nov 2026 11:51:19 +0100 Subject: [PATCH] gh-161475: Fix ctypes structures with float arrays returned on Linux SPARC On Linux, GCC and clang pass arrays of floating-point type in a structure in integer registers; only Solaris follows the vendor ABI there (GCC PR target/114416). Since gh-110190, ctypes described such array elements to libffi as floats on all SPARC, so libffi read structures returned by value from the FP registers on Linux. --- .../2026-11-06-11-59-26.gh-issue-161475.82LWf4.rst | 2 ++ Modules/_ctypes/stgdict.c | 14 +++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2026-11-06-11-59-26.gh-issue-161475.82LWf4.rst diff --git a/Misc/NEWS.d/next/Library/2026-11-06-11-59-26.gh-issue-161475.82LWf4.rst b/Misc/NEWS.d/next/Library/2026-11-06-11-59-26.gh-issue-161475.82LWf4.rst new file mode 100644 index 000000000000000..3033bc7543b9016 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-11-06-11-59-26.gh-issue-161475.82LWf4.rst @@ -0,0 +1,2 @@ +Fix :mod:`ctypes` structures containing arrays of floating-point type +returned by value on 64-bit Linux SPARC. diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index fc47844104876ea..7920c87ebe3cef3 100644 --- a/Modules/_ctypes/stgdict.c +++ b/Modules/_ctypes/stgdict.c @@ -683,10 +683,22 @@ _replace_array_elements(ctypes_state *st, PyObject *layout_fields, structs[struct_index].type = FFI_TYPE_STRUCT; structs[struct_index].elements = &dummy_types[dummy_index]; ++struct_index; + ffi_type *etype = &einfo->ffi_type_pointer; +#if defined(__sparc__) && defined(__arch64__) && !defined(__sun) + /* On Linux, GCC and clang pass arrays of floating-point type + in a structure in integer registers; only Solaris follows + the vendor ABI here (GCC PR target/114416). */ + if (etype->type == FFI_TYPE_FLOAT) { + etype = &ffi_type_uint32; + } + else if (etype->type == FFI_TYPE_DOUBLE) { + etype = &ffi_type_uint64; + } +#endif /* Copy over the element's type, length times. */ while (length > 0) { assert(dummy_index < (num_ffi_type_pointers)); - dummy_types[dummy_index++] = &einfo->ffi_type_pointer; + dummy_types[dummy_index++] = etype; length--; } assert(dummy_index < (num_ffi_type_pointers));