Closed
Description
Bug report
Bug description:
The man(3) page for dlsym()
states:
In unusual cases (see NOTES) the value of the symbol could actually be
NULL. Therefore, a NULL return from dlsym() need not indicate an error.
The correct way to distinguish an error from a symbol whose value is NULL
is to call dlerror(3) to clear any old error conditions, then call dl‐
sym(), and then call dlerror(3) again, saving its return value into a
variable, and check whether this saved value is not NULL.
As such, there can be cases where a call to dlsym
returns NULL
, while no error has been encountered and the string that dlerror()
returns has not been (re)set.
Currently, (https://github.com/python/cpython/blob/main/Modules/_ctypes/_ctypes.c#L970) we do:
<...>
address = (void *)dlsym(handle, name);
if (!address) {
#ifdef __CYGWIN__
<snip Windows stuff>
#else
PyErr_SetString(PyExc_ValueError, dlerror());
<...>
If dlsym()
returns NULL
, then by calling dlerror()
we pass either NULL
or a previous, unconsumed error string to PyErr_SetString
.
In the context of ctypes
, a NULL
return by dlsym()
might indeed always be considered an error.
To correctly express this, we should:
- Call
dlerror()
beforedlsym()
, to clear any previous error - Call
dlerror()
afterdlsym()
, to see ifdlsym()
encountered any error- If
dlerror()
returns a non-NULL value, then pass its result toPyErr_SetString
- If
dlerror()
returns NULL, then check ifaddress
is NULL, and if so, pass a custom error string toPyErr_SetString
.
- If
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Linked PRs
- gh-126554: ctypes: Correctly handle NULL dlsym values #126555
- [3.13] gh-126554: ctypes: Correctly handle NULL dlsym values (GH-126555) #126861
- [3.12] gh-126554: ctypes: Correctly handle NULL dlsym values (GH-126555) #127764
- gh-126554: correct detection of
gcc
forTestNullDlsym.test_null_dlsym
#129872 - [3.13] gh-126554: correct detection of
gcc
forTestNullDlsym.test_null_dlsym
(GH-129872) #129944 - [3.12] gh-126554: correct detection of
gcc
forTestNullDlsym.test_null_dlsym
(GH-129872) #129945