summaryrefslogtreecommitdiff
path: root/Modules/_ctypes
diff options
context:
space:
mode:
authorSteve Dower <steve.dower@microsoft.com>2019-03-29 16:37:16 -0700
committerGitHub <noreply@github.com>2019-03-29 16:37:16 -0700
commit2438cdf0e932a341c7613bf4323d06b91ae9f1f1 (patch)
tree231cdf3f22e1d5eb9f88fe7a511ab47e3cf8d225 /Modules/_ctypes
parent32119e10b792ad7ee4e5f951a2d89ddbaf111cc5 (diff)
downloadcpython-git-2438cdf0e932a341c7613bf4323d06b91ae9f1f1.tar.gz
bpo-36085: Enable better DLL resolution on Windows (GH-12302)
Diffstat (limited to 'Modules/_ctypes')
-rw-r--r--Modules/_ctypes/callproc.c34
1 files changed, 25 insertions, 9 deletions
diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c
index 7c25e2e796..5a943d3c37 100644
--- a/Modules/_ctypes/callproc.c
+++ b/Modules/_ctypes/callproc.c
@@ -1251,19 +1251,21 @@ static PyObject *format_error(PyObject *self, PyObject *args)
}
static const char load_library_doc[] =
-"LoadLibrary(name) -> handle\n\
+"LoadLibrary(name, load_flags) -> handle\n\
\n\
Load an executable (usually a DLL), and return a handle to it.\n\
The handle may be used to locate exported functions in this\n\
-module.\n";
+module. load_flags are as defined for LoadLibraryEx in the\n\
+Windows API.\n";
static PyObject *load_library(PyObject *self, PyObject *args)
{
const WCHAR *name;
PyObject *nameobj;
- PyObject *ignored;
+ int load_flags = 0;
HMODULE hMod;
+ DWORD err;
- if (!PyArg_ParseTuple(args, "U|O:LoadLibrary", &nameobj, &ignored))
+ if (!PyArg_ParseTuple(args, "U|i:LoadLibrary", &nameobj, &load_flags))
return NULL;
name = _PyUnicode_AsUnicode(nameobj);
@@ -1271,11 +1273,22 @@ static PyObject *load_library(PyObject *self, PyObject *args)
return NULL;
Py_BEGIN_ALLOW_THREADS
- hMod = LoadLibraryW(name);
+ /* bpo-36085: Limit DLL search directories to avoid pre-loading
+ * attacks and enable use of the AddDllDirectory function.
+ */
+ hMod = LoadLibraryExW(name, NULL, (DWORD)load_flags);
+ err = hMod ? 0 : GetLastError();
Py_END_ALLOW_THREADS
- if (!hMod)
- return PyErr_SetFromWindowsErr(GetLastError());
+ if (err == ERROR_MOD_NOT_FOUND) {
+ PyErr_Format(PyExc_FileNotFoundError,
+ ("Could not find module '%.500S'. Try using "
+ "the full path with constructor syntax."),
+ nameobj);
+ return NULL;
+ } else if (err) {
+ return PyErr_SetFromWindowsErr(err);
+ }
#ifdef _WIN64
return PyLong_FromVoidPtr(hMod);
#else
@@ -1291,15 +1304,18 @@ static PyObject *free_library(PyObject *self, PyObject *args)
{
void *hMod;
BOOL result;
+ DWORD err;
if (!PyArg_ParseTuple(args, "O&:FreeLibrary", &_parse_voidp, &hMod))
return NULL;
Py_BEGIN_ALLOW_THREADS
result = FreeLibrary((HMODULE)hMod);
+ err = result ? 0 : GetLastError();
Py_END_ALLOW_THREADS
- if (!result)
- return PyErr_SetFromWindowsErr(GetLastError());
+ if (!result) {
+ return PyErr_SetFromWindowsErr(err);
+ }
Py_RETURN_NONE;
}