From 45a7c3677c52c9d8166184d5263f1083d32e8899 Mon Sep 17 00:00:00 2001 From: Sergei Ozeranskii <1898297+ozeranskii@users.noreply.github.com> Date: Sun, 18 Oct 2026 20:46:48 +0200 Subject: [PATCH 1/2] Avoid removed Py_FileSystemDefaultEncoding in load_library CPython 3.16 removed Py_FileSystemDefaultEncoding from the headers, so _cffi_backend.c no longer compiled. Convert the file name with PyUnicode_FSConverter instead, which uses the filesystem encoding, rejects embedded null characters and is available on all supported versions. The encoded name is kept in *p_temp, which the callers already release. --- src/c/_cffi_backend.c | 10 ++++------ src/c/test_c.py | 7 +++++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/c/_cffi_backend.c b/src/c/_cffi_backend.c index a9bc9c5a..48c872df 100644 --- a/src/c/_cffi_backend.c +++ b/src/c/_cffi_backend.c @@ -4537,14 +4537,13 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, } PyErr_Clear(); #endif - if (!PyArg_ParseTuple(args, "et|i:load_library", - Py_FileSystemDefaultEncoding, &filename_or_null, &flags)) + if (!PyArg_ParseTuple(args, "O&|i:load_library", + PyUnicode_FSConverter, p_temp, &flags)) return NULL; *p_printable_filename = PyUnicode_AsUTF8(s); - if (*p_printable_filename == NULL) { - PyMem_Free(filename_or_null); + if (*p_printable_filename == NULL) return NULL; - } + filename_or_null = PyBytes_AS_STRING(*p_temp); } if ((flags & (RTLD_NOW | RTLD_LAZY)) == 0) flags |= RTLD_NOW; @@ -4557,7 +4556,6 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename, #endif handle = dlopen(filename_or_null, flags); - PyMem_Free(filename_or_null); #ifdef MS_WIN32 got_handle: diff --git a/src/c/test_c.py b/src/c/test_c.py index 8ddea1fb..9dc9041e 100644 --- a/src/c/test_c.py +++ b/src/c/test_c.py @@ -134,6 +134,13 @@ def test_load_library(): x = find_and_load_library('c', RTLD_LAZY) assert repr(x).startswith(" Date: Sun, 18 Oct 2026 20:46:48 +0200 Subject: [PATCH 2/2] Add whatsnew entry for #287 --- doc/source/whatsnew.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/source/whatsnew.rst b/doc/source/whatsnew.rst index 8ef0a42a..0b48dc0d 100644 --- a/doc/source/whatsnew.rst +++ b/doc/source/whatsnew.rst @@ -17,8 +17,14 @@ v2.2.0.dev0 ``FILE`` type. This could happen with an already-preprocessed system header, which spells out the real struct. (`#281`_). +* Fixed building on CPython 3.16, which removed + ``Py_FileSystemDefaultEncoding``. A file name with an embedded null + character passed to ``ffi.dlopen()`` now raises ``ValueError`` instead of + ``TypeError``. (`#287`_). + .. _`#265`: https://github.com/python-cffi/cffi/pull/265 .. _`#281`: https://github.com/python-cffi/cffi/pull/281 +.. _`#287`: https://github.com/python-cffi/cffi/pull/287 v2.1.0 ======