Skip to content

cdll.LoadLibrary allows None as an argument #78773

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
superbobry mannequin opened this issue Sep 5, 2018 · 6 comments
Open

cdll.LoadLibrary allows None as an argument #78773

superbobry mannequin opened this issue Sep 5, 2018 · 6 comments
Labels
3.11 only security fixes docs Documentation in the Doc dir topic-ctypes

Comments

@superbobry
Copy link
Mannequin

superbobry mannequin commented Sep 5, 2018

BPO 34592
Nosy @gpshead, @vstinner, @superbobry, @mhsmith

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = None
created_at = <Date 2018-09-05.21:35:41.405>
labels = ['3.11', 'invalid', 'docs']
title = 'cdll.LoadLibrary allows None as an argument'
updated_at = <Date 2021-11-19.04:06:58.621>
user = 'https://github.com/superbobry'

bugs.python.org fields:

activity = <Date 2021-11-19.04:06:58.621>
actor = 'gregory.p.smith'
assignee = 'docs@python'
closed = False
closed_date = None
closer = None
components = ['Documentation']
creation = <Date 2018-09-05.21:35:41.405>
creator = 'superbobry'
dependencies = []
files = []
hgrepos = []
issue_num = 34592
keywords = []
message_count = 5.0
messages = ['324654', '361734', '361735', '361807', '406570']
nosy_count = 5.0
nosy_names = ['gregory.p.smith', 'vstinner', 'docs@python', 'superbobry', 'Malcolm Smith']
pr_nums = []
priority = 'normal'
resolution = 'not a bug'
stage = 'needs patch'
status = 'open'
superseder = None
type = None
url = 'https://bugs.python.org/issue34592'
versions = ['Python 3.11']

@superbobry
Copy link
Mannequin Author

superbobry mannequin commented Sep 5, 2018

LoadLibrary in Python 2.7 through 3.7 accepts None as an argument. I wonder if this has been allowed for a reason? If not, it should probably be changed to raise a TypeError instead.

>>> ctypes.cdll.LoadLibrary(None)
<CDLL 'None', handle fffffffffffffffe at 10eedbe90>

Interestingly, on Python 2.7 LoadLibrary explicitly mentions None as allowed in the error message:

>>> ctypes.cdll.LoadLibrary(42)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "[...]/ctypes/__init__.py", line 444, in LoadLibrary
    return self._dlltype(name)
  File "[...]/ctypes/__init__.py", line 366, in __init__
    self._handle = _dlopen(self._name, mode)
TypeError: dlopen() argument 1 must be string or None, not int

A side-effect of None being allowed is that chaining find_library and LoadLibrary is error-prone:

>>> ctypes.cdll.LoadLibrary(find_library("foobar"))
<CDLL 'None', handle fffffffffffffffe at 10ef35fd0>

@superbobry superbobry mannequin added the 3.7 (EOL) end of life label Sep 5, 2018
@mhsmith
Copy link
Mannequin

mhsmith mannequin commented Feb 10, 2020

This isn't documented, but CDLL(None) is translated to dlopen(NULL), which "causes a search for a symbol in the main program, followed by all shared libraries loaded at program startup, and then all shared libraries loaded by dlopen() with the flag RTLD_GLOBAL" (https://linux.die.net/man/3/dlopen).

This is sometimes useful because it lets you look up a symbol in an already-loaded library without needing to give the library's name. For example:

>>> import ctypes
>>> dll = ctypes.CDLL(None)
>>> dll.printf
<_FuncPtr object at 0x7f3427d547c0>
>>> dll.PyObject_Str
<_FuncPtr object at 0x7f3427d54880>

@vstinner
Copy link
Member

I'm using LoadLibrary(None) commonly to load symbols in Python itself ;-)

@vstinner
Copy link
Member

In clear, it's a feature, not a bug.

@gpshead
Copy link
Member

gpshead commented Nov 19, 2021

We do need to document this in ctypes.rst. Quite a bit of code depends on ctypes.CDLL(None) and similar to get at symbols linked into the interpreter or already dlopened into the process these days. It works on Linux; I'm assuming it likely does on everything POSIXy.

@gpshead gpshead added docs Documentation in the Doc dir 3.11 only security fixes and removed 3.7 (EOL) end of life labels Nov 19, 2021
@gpshead gpshead reopened this Nov 19, 2021
@ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
@encukou
Copy link
Member

encukou commented Feb 4, 2025

I'm assuming it likely does on everything POSIXy.

Indeed. POSIX says:

If file is a null pointer, dlopen() shall return a global symbol table handle for the currently running process image. This symbol table handle shall provide access to the symbols from an ordered set of executable object files consisting of the original program image file, any executable object files loaded at program start-up as specified by that process file (for example, shared libraries), and the set of executable object files loaded using dlopen() operations with the RTLD_GLOBAL flag. As the latter set of executable object files can change during execution, the set of symbols made available by this symbol table handle can also change dynamically.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.11 only security fixes docs Documentation in the Doc dir topic-ctypes
Projects
None yet
Development

No branches or pull requests

5 participants