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 19extern dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix, 20 const char *shortname, 21 PyObject *pathname, 22 FILE *fp); 23#else 24extern dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix, 25 const char *shortname, 26 const char *pathname, FILE *fp); 27#endif 28 29static const char * const ascii_only_prefix = "PyInit"; 30static 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 */ 38static PyObject * 39get_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) { 48 return NULL; 49 } 50 lastdot = PyUnicode_FindChar(name, '.', 0, name_len, -1); 51 if (lastdot < -1) { 52 return NULL; 53 } else if (lastdot >= 0) { 54 tmp = PyUnicode_Substring(name, lastdot + 1, name_len); 55 if (tmp == NULL) 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) { 66 *hook_prefix = ascii_only_prefix; 67 } else { 68 if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) { 69 PyErr_Clear(); 70 encoded = PyUnicode_AsEncodedString(name, "punycode", NULL); 71 if (encoded == NULL) { 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) 83 goto error; 84 85 Py_DECREF(name); 86 Py_DECREF(encoded); 87 return modname; 88error: 89 Py_DECREF(name); 90 Py_XDECREF(encoded); 91 return NULL; 92} 93 94PyObject * 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) { 109 return NULL; 110 } 111 if (!PyUnicode_Check(name_unicode)) { 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) { 119 goto error; 120 } 121 name_buf = PyBytes_AS_STRING(name); 122 123 path = PyObject_GetAttrString(spec, "origin"); 124 if (path == NULL) 125 goto error; 126 127 if (PySys_Audit("import", "OOOOO", name_unicode, path, 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) 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) { 146 if (!PyErr_Occurred()) { 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) 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) { 166 _Py_PackageContext = oldcontext; 167 goto error; 168 } 169 m = _PyImport_InitFunc_TrampolineCall(p0); 170 _Py_PackageContext = oldcontext; 171 172 if (m == NULL) { 173 if (!PyErr_Occurred()) { 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()) { 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) { 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) { 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) { 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) 234 goto error; 235 236 Py_DECREF(name_unicode); 237 Py_DECREF(name); 238 Py_DECREF(path); 239 240 return m; 241 242error: 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 */ 251