diff options
author | Steve Dower <steve.dower@microsoft.com> | 2019-03-29 23:37:16 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-29 23:37:16 (GMT) |
commit | 2438cdf0e932a341c7613bf4323d06b91ae9f1f1 (patch) | |
tree | 231cdf3f22e1d5eb9f88fe7a511ab47e3cf8d225 /Doc | |
parent | 32119e10b792ad7ee4e5f951a2d89ddbaf111cc5 (diff) | |
download | cpython-2438cdf0e932a341c7613bf4323d06b91ae9f1f1.zip cpython-2438cdf0e932a341c7613bf4323d06b91ae9f1f1.tar.gz cpython-2438cdf0e932a341c7613bf4323d06b91ae9f1f1.tar.bz2 |
bpo-36085: Enable better DLL resolution on Windows (GH-12302)
Diffstat (limited to 'Doc')
-rw-r--r-- | Doc/library/ctypes.rst | 17 | ||||
-rw-r--r-- | Doc/library/os.rst | 30 | ||||
-rw-r--r-- | Doc/whatsnew/3.8.rst | 30 |
3 files changed, 74 insertions, 3 deletions
diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index 500aad8..baab0de 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -1322,14 +1322,14 @@ There are several ways to load shared libraries into the Python process. One way is to instantiate one of the following classes: -.. class:: CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False) +.. class:: CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=0) Instances of this class represent loaded shared libraries. Functions in these libraries use the standard C calling convention, and are assumed to return :c:type:`int`. -.. class:: OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False) +.. class:: OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=0) Windows only: Instances of this class represent loaded shared libraries, functions in these libraries use the ``stdcall`` calling convention, and are @@ -1342,7 +1342,7 @@ way is to instantiate one of the following classes: :exc:`WindowsError` used to be raised. -.. class:: WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False) +.. class:: WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=0) Windows only: Instances of this class represent loaded shared libraries, functions in these libraries use the ``stdcall`` calling convention, and are @@ -1394,6 +1394,17 @@ the Windows error code which is managed by the :func:`GetLastError` and :func:`ctypes.set_last_error` are used to request and change the ctypes private copy of the windows error code. +The *winmode* parameter is used on Windows to specify how the library is loaded +(since *mode* is ignored). It takes any value that is valid for the Win32 API +``LoadLibraryEx`` flags parameter. When omitted, the default is to use the flags +that result in the most secure DLL load to avoiding issues such as DLL +hijacking. Passing the full path to the DLL is the safest way to ensure the +correct library and dependencies are loaded. + +.. versionchanged:: 3.8 + Added *winmode* parameter. + + .. data:: RTLD_GLOBAL :noindex: diff --git a/Doc/library/os.rst b/Doc/library/os.rst index f8803af..85e240a 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -3079,6 +3079,36 @@ to be ignored. :func:`signal.signal`. +.. function:: add_dll_directory(path) + + Add a path to the DLL search path. + + This search path is used when resolving dependencies for imported + extension modules (the module itself is resolved through sys.path), + and also by :mod:`ctypes`. + + Remove the directory by calling **close()** on the returned object + or using it in a :keyword:`with` statement. + + See the `Microsoft documentation + <https://msdn.microsoft.com/44228cf2-6306-466c-8f16-f513cd3ba8b5>`_ + for more information about how DLLs are loaded. + + .. availability:: Windows. + + .. versionadded:: 3.8 + Previous versions of CPython would resolve DLLs using the default + behavior for the current process. This led to inconsistencies, + such as only sometimes searching :envvar:`PATH` or the current + working directory, and OS functions such as ``AddDllDirectory`` + having no effect. + + In 3.8, the two primary ways DLLs are loaded now explicitly + override the process-wide behavior to ensure consistency. See the + :ref:`porting notes <bpo-36085-whatsnew>` for information on + updating libraries. + + .. function:: execl(path, arg0, arg1, ...) execle(path, arg0, arg1, ..., env) execlp(file, arg0, arg1, ...) diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 0ffbcab..f0423c3 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -168,6 +168,16 @@ asyncio On Windows, the default event loop is now :class:`~asyncio.ProactorEventLoop`. +ctypes +------ + +On Windows, :class:`~ctypes.CDLL` and subclasses now accept a *winmode* parameter +to specify flags for the underlying ``LoadLibraryEx`` call. The default flags are +set to only load DLL dependencies from trusted locations, including the path +where the DLL is stored (if a full or partial path is used to load the initial +DLL) and paths added by :func:`~os.add_dll_directory`. + + gettext ------- @@ -238,6 +248,13 @@ Added new function, :func:`math.prod`, as analogous function to :func:`sum` that returns the product of a 'start' value (default: 1) times an iterable of numbers. (Contributed by Pablo Galindo in :issue:`35606`) +os +-- + +Added new function :func:`~os.add_dll_directory` on Windows for providing +additional search paths for native dependencies when importing extension +modules or loading DLLs using :mod:`ctypes`. + os.path ------- @@ -727,6 +744,19 @@ Changes in the Python API environment variable and does not use :envvar:`HOME`, which is not normally set for regular user accounts. +.. _bpo-36085-whatsnew: + +* DLL dependencies for extension modules and DLLs loaded with :mod:`ctypes` on + Windows are now resolved more securely. Only the system paths, the directory + containing the DLL or PYD file, and directories added with + :func:`~os.add_dll_directory` are searched for load-time dependencies. + Specifically, :envvar:`PATH` and the current working directory are no longer + used, and modifications to these will no longer have any effect on normal DLL + resolution. If your application relies on these mechanisms, you should check + for :func:`~os.add_dll_directory` and if it exists, use it to add your DLLs + directory while loading your library. + (See :issue:`36085`.) + Changes in the C API -------------------- |