Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
1f7838bc
Commit
1f7838bc
authored
Oct 05, 2000
by
Mark Hammond
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Detect conflicting Python DLL on module import under Windows - as per [ Patch #101676 ]
parent
85788edc
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
152 additions
and
1 deletion
+152
-1
Python/dynload_win.c
Python/dynload_win.c
+152
-1
No files found.
Python/dynload_win.c
View file @
1f7838bc
...
@@ -3,6 +3,7 @@
...
@@ -3,6 +3,7 @@
#include <windows.h>
#include <windows.h>
#include <direct.h>
#include <direct.h>
#include <ctype.h>
#include "Python.h"
#include "Python.h"
#include "importdl.h"
#include "importdl.h"
...
@@ -19,11 +20,144 @@ const struct filedescr _PyImport_DynLoadFiletab[] = {
...
@@ -19,11 +20,144 @@ const struct filedescr _PyImport_DynLoadFiletab[] = {
};
};
#ifdef MS_WIN32
/* Case insensitive string compare, to avoid any dependencies on particular
C RTL implementations */
static
int
strcasecmp
(
char
*
string1
,
char
*
string2
)
{
int
first
,
second
;
do
{
first
=
tolower
(
*
string1
);
second
=
tolower
(
*
string2
);
string1
++
;
string2
++
;
}
while
(
first
&&
first
==
second
);
return
(
first
-
second
);
}
/* Function to return the name of the "python" DLL that the supplied module
directly imports. Looks through the list of imported modules and
returns the first entry that starts with "python" (case sensitive) and
is followed by nothing but numbers until the separator (period).
Returns a pointer to the import name, or NULL if no matching name was
located.
This function parses through the PE header for the module as loaded in
memory by the system loader. The PE header is accessed as documented by
Microsoft in the MSDN PE and COFF specification (2/99), and handles
both PE32 and PE32+. It only worries about the direct import table and
not the delay load import table since it's unlikely an extension is
going to be delay loading Python (after all, it's already loaded).
If any magic values are not found (e.g., the PE header or optional
header magic), then this function simply returns NULL. */
#define DWORD_AT(mem) (*(DWORD *)(mem))
#define WORD_AT(mem) (*(WORD *)(mem))
static
char
*
GetPythonImport
(
HINSTANCE
hModule
)
{
unsigned
char
*
dllbase
,
*
import_data
,
*
import_name
;
DWORD
pe_offset
,
opt_offset
;
WORD
opt_magic
;
int
num_dict_off
,
import_off
;
/* Safety check input */
if
(
hModule
==
NULL
)
{
return
NULL
;
}
/* Module instance is also the base load address. First portion of
memory is the MS-DOS loader, which holds the offset to the PE
header (from the load base) at 0x3C */
dllbase
=
(
unsigned
char
*
)
hModule
;
pe_offset
=
DWORD_AT
(
dllbase
+
0x3C
);
/* The PE signature must be "PE\0\0" */
if
(
memcmp
(
dllbase
+
pe_offset
,
"PE
\0\0
"
,
4
))
{
return
NULL
;
}
/* Following the PE signature is the standard COFF header (20
bytes) and then the optional header. The optional header starts
with a magic value of 0x10B for PE32 or 0x20B for PE32+ (PE32+
uses 64-bits for some fields). It might also be 0x107 for a ROM
image, but we don't process that here.
The optional header ends with a data dictionary that directly
points to certain types of data, among them the import entries
(in the second table entry). Based on the header type, we
determine offsets for the data dictionary count and the entry
within the dictionary pointing to the imports. */
opt_offset
=
pe_offset
+
4
+
20
;
opt_magic
=
WORD_AT
(
dllbase
+
opt_offset
);
if
(
opt_magic
==
0x10B
)
{
/* PE32 */
num_dict_off
=
92
;
import_off
=
104
;
}
else
if
(
opt_magic
==
0x20B
)
{
/* PE32+ */
num_dict_off
=
108
;
import_off
=
120
;
}
else
{
/* Unsupported */
return
NULL
;
}
/* Now if an import table exists, offset to it and walk the list of
imports. The import table is an array (ending when an entry has
empty values) of structures (20 bytes each), which contains (at
offset 12) a relative address (to the module base) at which a
string constant holding the import name is located. */
if
(
DWORD_AT
(
dllbase
+
opt_offset
+
num_dict_off
)
>=
2
)
{
import_data
=
dllbase
+
DWORD_AT
(
dllbase
+
opt_offset
+
import_off
);
while
(
DWORD_AT
(
import_data
))
{
import_name
=
dllbase
+
DWORD_AT
(
import_data
+
12
);
if
(
strlen
(
import_name
)
>=
6
&&
!
strncmp
(
import_name
,
"python"
,
6
))
{
char
*
pch
;
/* Ensure python prefix is followed only
by numbers to the end of the basename */
pch
=
import_name
+
6
;
while
(
*
pch
&&
*
pch
!=
'.'
)
{
if
(
*
pch
>=
'0'
&&
*
pch
<=
'9'
)
{
pch
++
;
}
else
{
pch
=
NULL
;
break
;
}
}
if
(
pch
)
{
/* Found it - return the name */
return
import_name
;
}
}
import_data
+=
20
;
}
}
return
NULL
;
}
#endif
/* MS_WIN32 */
dl_funcptr
_PyImport_GetDynLoadFunc
(
const
char
*
fqname
,
const
char
*
shortname
,
dl_funcptr
_PyImport_GetDynLoadFunc
(
const
char
*
fqname
,
const
char
*
shortname
,
const
char
*
pathname
,
FILE
*
fp
)
const
char
*
pathname
,
FILE
*
fp
)
{
{
dl_funcptr
p
;
dl_funcptr
p
;
char
funcname
[
258
];
char
funcname
[
258
]
,
*
import_python
;
sprintf
(
funcname
,
"init%.200s"
,
shortname
);
sprintf
(
funcname
,
"init%.200s"
,
shortname
);
...
@@ -91,6 +225,23 @@ dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
...
@@ -91,6 +225,23 @@ dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
}
}
PyErr_SetString
(
PyExc_ImportError
,
errBuf
);
PyErr_SetString
(
PyExc_ImportError
,
errBuf
);
return
NULL
;
return
NULL
;
}
else
{
char
buffer
[
256
];
sprintf
(
buffer
,
"python%d%d.dll"
,
PY_MAJOR_VERSION
,
PY_MINOR_VERSION
);
import_python
=
GetPythonImport
(
hDLL
);
if
(
import_python
&&
strcasecmp
(
buffer
,
import_python
))
{
sprintf
(
buffer
,
"Module use of %s conflicts "
"with this version of Python."
,
import_python
);
PyErr_SetString
(
PyExc_ImportError
,
buffer
);
FreeLibrary
(
hDLL
);
return
NULL
;
}
}
}
p
=
GetProcAddress
(
hDLL
,
funcname
);
p
=
GetProcAddress
(
hDLL
,
funcname
);
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment