Skip to content

Commit 28003b0

Browse files
committed
Perform filesystem encoding manually on filename
In python 3.12 the Py_FileSystemDefaultEncoding global variable has been deprecated. This was used in combination with a "et" PyArgs format specifier to get a raw C string with the encoded bytes for the input filename. This commit replaces the usage of Py_FileSystemDefaultEncoding with a manual call to PyUnicode_EncodeFSDefault instead (only within b_do_dlopen_posix). This function requires a unicode object as an input, and therefore we now need to accept the argument with the "U" format specifier. While this is a departure from the "et" specifier, which accepts not only strings, but also bytes and bytearrays, this is inconsequential, since the higher-level cffi API already ensures we get a string object here. Moreover, we were already calling PyUnicode_AsUTF8 on it, which would have failed if we received bytes. Thus this new constrain is fine. With this change there's no need anymore to keep around the raw C pointer in the b_do_dlopen() function, and it can be moved down to b_do_dlopen_posix(), where it doensn't need to be freed (as it's now taken from a PyBytes object via PyBytes_AsString). We can also now remove the unnecessary "s" variable since the filename_unicode variable (previously used only in the win32 case, now always) holds the same value.
1 parent cd3cac6 commit 28003b0

File tree

1 file changed

+15
-12
lines changed

1 file changed

+15
-12
lines changed

src/c/_cffi_backend.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4375,12 +4375,21 @@ static void *b_handle_or_error(void *handle, const char *printable_filename)
43754375
return handle;
43764376
}
43774377

4378-
static void *b_do_dlopen_posix(const char *filename_or_null, int flags, const char *printable_filename)
4378+
static void *b_do_dlopen_posix(PyObject *filename_unicode, int flags, const char *printable_filename)
43794379
{
4380+
char *filename_or_null = NULL;
4381+
PyObject *filename_bytes = NULL;
4382+
if (filename_unicode) {
4383+
filename_bytes = PyUnicode_EncodeFSDefault(filename_unicode);
4384+
if (filename_bytes == NULL)
4385+
return NULL;
4386+
filename_or_null = PyBytes_AsString(filename_bytes);
4387+
}
43804388
if ((flags & (RTLD_NOW | RTLD_LAZY)) == 0)
43814389
flags |= RTLD_NOW;
43824390

43834391
void *handle = dlopen(filename_or_null, flags);
4392+
Py_XDECREF(filename_bytes);
43844393
return b_handle_or_error(handle, printable_filename);
43854394
}
43864395

@@ -4412,7 +4421,6 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename,
44124421
to a temporary object that must be freed after looking at printable_filename.
44134422
*/
44144423
void *handle;
4415-
char *filename_or_null;
44164424
int flags = 0;
44174425
*p_temp = NULL;
44184426
*auto_close = 1;
@@ -4454,30 +4462,25 @@ static void *b_do_dlopen(PyObject *args, const char **p_printable_filename,
44544462
}
44554463
else
44564464
{
4457-
PyObject *s = PyTuple_GET_ITEM(args, 0);
4458-
#ifdef MS_WIN32
44594465
PyObject *filename_unicode;
4466+
#ifdef MS_WIN32
44604467
if (PyArg_ParseTuple(args, "U|i:load_library", &filename_unicode, &flags))
44614468
{
4462-
*p_printable_filename = PyUnicode_AsUTF8(s);
4469+
*p_printable_filename = PyUnicode_AsUTF8(filename_unicode);
44634470
if (*p_printable_filename == NULL)
44644471
return NULL;
44654472
return b_do_dlopen_win32(filename_unicode, flags, *p_printable_filename);
44664473
}
44674474
PyErr_Clear();
44684475
#endif
4469-
if (!PyArg_ParseTuple(args, "et|i:load_library",
4470-
Py_FileSystemDefaultEncoding, &filename_or_null, &flags))
4476+
if (!PyArg_ParseTuple(args, "U|i:load_library", &filename_unicode, &flags))
44714477
return NULL;
4472-
*p_printable_filename = PyUnicode_AsUTF8(s);
4478+
*p_printable_filename = PyUnicode_AsUTF8(filename_unicode);
44734479
if (*p_printable_filename == NULL) {
4474-
PyMem_Free(filename_or_null);
44754480
return NULL;
44764481
}
4482+
return b_do_dlopen_posix(filename_unicode, flags, *p_printable_filename);
44774483
}
4478-
handle = b_do_dlopen_posix(filename_or_null, flags, *p_printable_filename);
4479-
PyMem_Free(filename_or_null);
4480-
return handle;
44814484
}
44824485

44834486
static PyObject *b_load_library(PyObject *self, PyObject *args)

0 commit comments

Comments
 (0)