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