/home/mdboom/Work/builds/cpython/Python/importdl.c
Line | Count | Source (jump to first uncovered line) |
1 | |
2 | /* Support for dynamic loading of extension modules */ |
3 | |
4 | #include "Python.h" |
5 | #include "pycore_call.h" |
6 | #include "pycore_pystate.h" |
7 | #include "pycore_runtime.h" |
8 | |
9 | /* ./configure sets HAVE_DYNAMIC_LOADING if dynamic loading of modules is |
10 | supported on this platform. configure will then compile and link in one |
11 | of the dynload_*.c files, as appropriate. We will call a function in |
12 | those modules to get a function pointer to the module's init function. |
13 | */ |
14 | #ifdef HAVE_DYNAMIC_LOADING |
15 | |
16 | #include "importdl.h" |
17 | |
18 | #ifdef MS_WINDOWS |
19 | extern dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix, |
20 | const char *shortname, |
21 | PyObject *pathname, |
22 | FILE *fp); |
23 | #else |
24 | extern dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix, |
25 | const char *shortname, |
26 | const char *pathname, FILE *fp); |
27 | #endif |
28 | |
29 | static const char * const ascii_only_prefix = "PyInit"; |
30 | static const char * const nonascii_prefix = "PyInitU"; |
31 | |
32 | /* Get the variable part of a module's export symbol name. |
33 | * Returns a bytes instance. For non-ASCII-named modules, the name is |
34 | * encoded as per PEP 489. |
35 | * The hook_prefix pointer is set to either ascii_only_prefix or |
36 | * nonascii_prefix, as appropriate. |
37 | */ |
38 | static PyObject * |
39 | get_encoded_name(PyObject *name, const char **hook_prefix) { |
40 | PyObject *tmp; |
41 | PyObject *encoded = NULL; |
42 | PyObject *modname = NULL; |
43 | Py_ssize_t name_len, lastdot; |
44 | |
45 | /* Get the short name (substring after last dot) */ |
46 | name_len = PyUnicode_GetLength(name); |
47 | if (name_len < 0) { Branch (47:9): [True: 0, False: 299]
|
48 | return NULL; |
49 | } |
50 | lastdot = PyUnicode_FindChar(name, '.', 0, name_len, -1); |
51 | if (lastdot < -1) { Branch (51:9): [True: 0, False: 299]
|
52 | return NULL; |
53 | } else if (lastdot >= 0) { Branch (53:16): [True: 3, False: 296]
|
54 | tmp = PyUnicode_Substring(name, lastdot + 1, name_len); |
55 | if (tmp == NULL) Branch (55:13): [True: 0, False: 3]
|
56 | return NULL; |
57 | name = tmp; |
58 | /* "name" now holds a new reference to the substring */ |
59 | } else { |
60 | Py_INCREF(name); |
61 | } |
62 | |
63 | /* Encode to ASCII or Punycode, as needed */ |
64 | encoded = PyUnicode_AsEncodedString(name, "ascii", NULL); |
65 | if (encoded != NULL) { Branch (65:9): [True: 293, False: 6]
|
66 | *hook_prefix = ascii_only_prefix; |
67 | } else { |
68 | if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) { Branch (68:13): [True: 6, False: 0]
|
69 | PyErr_Clear(); |
70 | encoded = PyUnicode_AsEncodedString(name, "punycode", NULL); |
71 | if (encoded == NULL) { Branch (71:17): [True: 0, False: 6]
|
72 | goto error; |
73 | } |
74 | *hook_prefix = nonascii_prefix; |
75 | } else { |
76 | goto error; |
77 | } |
78 | } |
79 | |
80 | /* Replace '-' by '_' */ |
81 | modname = _PyObject_CallMethod(encoded, &_Py_ID(replace), "cc", '-', '_'); |
82 | if (modname == NULL) Branch (82:9): [True: 0, False: 299]
|
83 | goto error; |
84 | |
85 | Py_DECREF(name); |
86 | Py_DECREF(encoded); |
87 | return modname; |
88 | error: |
89 | Py_DECREF(name); |
90 | Py_XDECREF(encoded); |
91 | return NULL; |
92 | } |
93 | |
94 | PyObject * |
95 | _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp) |
96 | { |
97 | #ifndef MS_WINDOWS |
98 | PyObject *pathbytes = NULL; |
99 | #endif |
100 | PyObject *name_unicode = NULL, *name = NULL, *path = NULL, *m = NULL; |
101 | const char *name_buf, *hook_prefix; |
102 | const char *oldcontext; |
103 | dl_funcptr exportfunc; |
104 | PyModuleDef *def; |
105 | PyModInitFunction p0; |
106 | |
107 | name_unicode = PyObject_GetAttrString(spec, "name"); |
108 | if (name_unicode == NULL) { Branch (108:9): [True: 0, False: 300]
|
109 | return NULL; |
110 | } |
111 | if (!PyUnicode_Check(name_unicode)) { Branch (111:9): [True: 1, False: 299]
|
112 | PyErr_SetString(PyExc_TypeError, |
113 | "spec.name must be a string"); |
114 | goto error; |
115 | } |
116 | |
117 | name = get_encoded_name(name_unicode, &hook_prefix); |
118 | if (name == NULL) { Branch (118:9): [True: 0, False: 299]
|
119 | goto error; |
120 | } |
121 | name_buf = PyBytes_AS_STRING(name); |
122 | |
123 | path = PyObject_GetAttrString(spec, "origin"); |
124 | if (path == NULL) Branch (124:9): [True: 0, False: 299]
|
125 | goto error; |
126 | |
127 | if (PySys_Audit("import", "OOOOO", name_unicode, path, Branch (127:9): [True: 0, False: 299]
|
128 | Py_None, Py_None, Py_None) < 0) { |
129 | goto error; |
130 | } |
131 | |
132 | #ifdef MS_WINDOWS |
133 | exportfunc = _PyImport_FindSharedFuncptrWindows(hook_prefix, name_buf, |
134 | path, fp); |
135 | #else |
136 | pathbytes = PyUnicode_EncodeFSDefault(path); |
137 | if (pathbytes == NULL) Branch (137:9): [True: 0, False: 299]
|
138 | goto error; |
139 | exportfunc = _PyImport_FindSharedFuncptr(hook_prefix, name_buf, |
140 | PyBytes_AS_STRING(pathbytes), |
141 | fp); |
142 | Py_DECREF(pathbytes); |
143 | #endif |
144 | |
145 | if (exportfunc == NULL) { Branch (145:9): [True: 6, False: 293]
|
146 | if (!PyErr_Occurred()) { Branch (146:13): [True: 5, False: 1]
|
147 | PyObject *msg; |
148 | msg = PyUnicode_FromFormat( |
149 | "dynamic module does not define " |
150 | "module export function (%s_%s)", |
151 | hook_prefix, name_buf); |
152 | if (msg == NULL) Branch (152:17): [True: 0, False: 5]
|
153 | goto error; |
154 | PyErr_SetImportError(msg, name_unicode, path); |
155 | Py_DECREF(msg); |
156 | } |
157 | goto error; |
158 | } |
159 | |
160 | p0 = (PyModInitFunction)exportfunc; |
161 | |
162 | /* Package context is needed for single-phase init */ |
163 | oldcontext = _Py_PackageContext; |
164 | _Py_PackageContext = PyUnicode_AsUTF8(name_unicode); |
165 | if (_Py_PackageContext == NULL) { Branch (165:9): [True: 0, False: 293]
|
166 | _Py_PackageContext = oldcontext; |
167 | goto error; |
168 | } |
169 | m = _PyImport_InitFunc_TrampolineCall(p0); |
170 | _Py_PackageContext = oldcontext; |
171 | |
172 | if (m == NULL) { Branch (172:9): [True: 4, False: 289]
|
173 | if (!PyErr_Occurred()) { Branch (173:13): [True: 2, False: 2]
|
174 | PyErr_Format( |
175 | PyExc_SystemError, |
176 | "initialization of %s failed without raising an exception", |
177 | name_buf); |
178 | } |
179 | goto error; |
180 | } else if (PyErr_Occurred()) { Branch (180:16): [True: 2, False: 287]
|
181 | PyErr_Clear(); |
182 | PyErr_Format( |
183 | PyExc_SystemError, |
184 | "initialization of %s raised unreported exception", |
185 | name_buf); |
186 | m = NULL; |
187 | goto error; |
188 | } |
189 | if (Py_IS_TYPE(m, NULL)) { |
190 | /* This can happen when a PyModuleDef is returned without calling |
191 | * PyModuleDef_Init on it |
192 | */ |
193 | PyErr_Format(PyExc_SystemError, |
194 | "init function of %s returned uninitialized object", |
195 | name_buf); |
196 | m = NULL; /* prevent segfault in DECREF */ |
197 | goto error; |
198 | } |
199 | if (PyObject_TypeCheck(m, &PyModuleDef_Type)) { |
200 | Py_DECREF(name_unicode); |
201 | Py_DECREF(name); |
202 | Py_DECREF(path); |
203 | return PyModule_FromDefAndSpec((PyModuleDef*)m, spec); |
204 | } |
205 | |
206 | /* Fall back to single-phase init mechanism */ |
207 | |
208 | if (hook_prefix == nonascii_prefix) { Branch (208:9): [True: 0, False: 60]
|
209 | /* don't allow legacy init for non-ASCII module names */ |
210 | PyErr_Format( |
211 | PyExc_SystemError, |
212 | "initialization of %s did not return PyModuleDef", |
213 | name_buf); |
214 | goto error; |
215 | } |
216 | |
217 | /* Remember pointer to module init function. */ |
218 | def = PyModule_GetDef(m); |
219 | if (def == NULL) { Branch (219:9): [True: 0, False: 60]
|
220 | PyErr_Format(PyExc_SystemError, |
221 | "initialization of %s did not return an extension " |
222 | "module", name_buf); |
223 | goto error; |
224 | } |
225 | def->m_base.m_init = p0; |
226 | |
227 | /* Remember the filename as the __file__ attribute */ |
228 | if (PyModule_AddObjectRef(m, "__file__", path) < 0) { Branch (228:9): [True: 0, False: 60]
|
229 | PyErr_Clear(); /* Not important enough to report */ |
230 | } |
231 | |
232 | PyObject *modules = PyImport_GetModuleDict(); |
233 | if (_PyImport_FixupExtensionObject(m, name_unicode, path, modules) < 0) Branch (233:9): [True: 0, False: 60]
|
234 | goto error; |
235 | |
236 | Py_DECREF(name_unicode); |
237 | Py_DECREF(name); |
238 | Py_DECREF(path); |
239 | |
240 | return m; |
241 | |
242 | error: |
243 | Py_DECREF(name_unicode); |
244 | Py_XDECREF(name); |
245 | Py_XDECREF(path); |
246 | Py_XDECREF(m); |
247 | return NULL; |
248 | } |
249 | |
250 | #endif /* HAVE_DYNAMIC_LOADING */ |