| 
									
										
										
										
											1999-12-20 21:18:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Support for dynamic loading of extension modules */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "Python.h"
 | 
					
						
							| 
									
										
										
										
											2020-04-14 14:26:24 +02:00
										 |  |  | #include "pycore_interp.h"    // _PyInterpreterState.dlopenflags
 | 
					
						
							| 
									
										
										
										
											2020-04-14 15:14:01 +02:00
										 |  |  | #include "pycore_pystate.h"   // _PyInterpreterState_GET()
 | 
					
						
							| 
									
										
										
										
											1999-12-20 21:18:49 +00:00
										 |  |  | #include "importdl.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <sys/types.h>
 | 
					
						
							|  |  |  | #include <sys/stat.h>
 | 
					
						
							| 
									
										
										
										
											2001-10-18 21:24:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-18 11:45:19 +00:00
										 |  |  | #if defined(__NetBSD__)
 | 
					
						
							|  |  |  | #include <sys/param.h>
 | 
					
						
							|  |  |  | #if (NetBSD < 199712)
 | 
					
						
							| 
									
										
										
										
											1999-12-20 21:18:49 +00:00
										 |  |  | #include <nlist.h>
 | 
					
						
							|  |  |  | #include <link.h>
 | 
					
						
							|  |  |  | #define dlerror() "error in dynamic linking"
 | 
					
						
							| 
									
										
										
										
											2001-10-18 21:24:04 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #endif /* NetBSD */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-12-20 21:18:49 +00:00
										 |  |  | #ifdef HAVE_DLFCN_H
 | 
					
						
							|  |  |  | #include <dlfcn.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-18 11:45:19 +00:00
										 |  |  | #if (defined(__OpenBSD__) || defined(__NetBSD__)) && !defined(__ELF__)
 | 
					
						
							| 
									
										
										
										
											2000-10-25 22:07:45 +00:00
										 |  |  | #define LEAD_UNDERSCORE "_"
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define LEAD_UNDERSCORE ""
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-03 18:30:30 +00:00
										 |  |  | /* The .so extension module ABI tag, supplied by the Makefile via
 | 
					
						
							|  |  |  |    Makefile.pre.in and configure.  This is used to discriminate between | 
					
						
							|  |  |  |    incompatible .so files so that extensions for different Python builds can | 
					
						
							|  |  |  |    live in the same directory.  E.g. foomodule.cpython-32.so | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											1999-12-20 21:18:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-04 15:20:40 -04:00
										 |  |  | const char *_PyImport_DynLoadFiletab[] = { | 
					
						
							| 
									
										
										
										
											2000-10-05 19:24:26 +00:00
										 |  |  | #ifdef __CYGWIN__
 | 
					
						
							| 
									
										
										
										
											2012-05-04 15:20:40 -04:00
										 |  |  |     ".dll", | 
					
						
							| 
									
										
										
										
											2010-09-03 18:30:30 +00:00
										 |  |  | #else  /* !__CYGWIN__ */
 | 
					
						
							| 
									
										
										
										
											2012-05-04 15:20:40 -04:00
										 |  |  |     "." SOABI ".so", | 
					
						
							| 
									
										
										
										
											2019-04-26 01:40:00 +02:00
										 |  |  | #ifdef ALT_SOABI
 | 
					
						
							|  |  |  |     "." ALT_SOABI ".so", | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-05-04 15:20:40 -04:00
										 |  |  |     ".abi" PYTHON_ABI_STRING ".so", | 
					
						
							|  |  |  |     ".so", | 
					
						
							| 
									
										
										
										
											2010-09-03 18:30:30 +00:00
										 |  |  | #endif  /* __CYGWIN__ */
 | 
					
						
							| 
									
										
										
										
											2012-05-04 15:20:40 -04:00
										 |  |  |     NULL, | 
					
						
							| 
									
										
										
										
											1999-12-20 21:18:49 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     dev_t dev; | 
					
						
							|  |  |  |     ino_t ino; | 
					
						
							|  |  |  |     void *handle; | 
					
						
							| 
									
										
										
										
											1999-12-20 21:18:49 +00:00
										 |  |  | } handles[128]; | 
					
						
							|  |  |  | static int nhandles = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-23 22:24:10 +10:00
										 |  |  | dl_funcptr | 
					
						
							|  |  |  | _PyImport_FindSharedFuncptr(const char *prefix, | 
					
						
							|  |  |  |                             const char *shortname, | 
					
						
							|  |  |  |                             const char *pathname, FILE *fp) | 
					
						
							| 
									
										
										
										
											1999-12-20 21:18:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     dl_funcptr p; | 
					
						
							|  |  |  |     void *handle; | 
					
						
							|  |  |  |     char funcname[258]; | 
					
						
							|  |  |  |     char pathbuf[260]; | 
					
						
							|  |  |  |     int dlopenflags=0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (strchr(pathname, '/') == NULL) { | 
					
						
							|  |  |  |         /* Prefix bare filename with "./" */ | 
					
						
							|  |  |  |         PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname); | 
					
						
							|  |  |  |         pathname = pathbuf; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyOS_snprintf(funcname, sizeof(funcname), | 
					
						
							| 
									
										
										
										
											2015-05-23 22:24:10 +10:00
										 |  |  |                   LEAD_UNDERSCORE "%.20s_%.200s", prefix, shortname); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (fp != NULL) { | 
					
						
							|  |  |  |         int i; | 
					
						
							| 
									
										
										
										
											2015-03-30 10:09:31 +02:00
										 |  |  |         struct _Py_stat_struct status; | 
					
						
							|  |  |  |         if (_Py_fstat(fileno(fp), &status) == -1) | 
					
						
							| 
									
										
										
										
											2013-07-22 22:08:09 -07:00
										 |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         for (i = 0; i < nhandles; i++) { | 
					
						
							| 
									
										
										
										
											2015-03-30 10:09:31 +02:00
										 |  |  |             if (status.st_dev == handles[i].dev && | 
					
						
							|  |  |  |                 status.st_ino == handles[i].ino) { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |                 p = (dl_funcptr) dlsym(handles[i].handle, | 
					
						
							|  |  |  |                                        funcname); | 
					
						
							|  |  |  |                 return p; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (nhandles < 128) { | 
					
						
							| 
									
										
										
										
											2015-03-30 10:09:31 +02:00
										 |  |  |             handles[nhandles].dev = status.st_dev; | 
					
						
							|  |  |  |             handles[nhandles].ino = status.st_ino; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1999-12-20 21:18:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-14 15:14:01 +02:00
										 |  |  |     dlopenflags = _PyInterpreterState_GET()->dlopenflags; | 
					
						
							| 
									
										
										
										
											2001-07-18 16:17:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     handle = dlopen(pathname, dlopenflags); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (handle == NULL) { | 
					
						
							| 
									
										
										
										
											2012-10-02 00:55:07 +02:00
										 |  |  |         PyObject *mod_name; | 
					
						
							|  |  |  |         PyObject *path; | 
					
						
							|  |  |  |         PyObject *error_ob; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         const char *error = dlerror(); | 
					
						
							|  |  |  |         if (error == NULL) | 
					
						
							|  |  |  |             error = "unknown dlopen() error"; | 
					
						
							| 
									
										
											  
											
												bpo-41894: Fix UnicodeDecodeError while loading native module (GH-22466)
When running in a non-UTF-8 locale, if an error occurs while importing a
native Python module (say because a dependent share library is missing),
the error message string returned may contain non-ASCII code points
causing a UnicodeDecodeError.
PyUnicode_DecodeFSDefault is used for buffers which may contain
filesystem  paths. For consistency with os.strerror(),
PyUnicode_DecodeLocale is used for buffers which contain system error
messages. While the shortname parameter is always encoded in ASCII
according to PEP 489, it is left decoded using PyUnicode_FromString to
minimize the changes and since it should not affect the decoding (albeit
_potentially_ slower).
In dynload_hpux, since the error buffer contains a message generated
from a static ASCII string and the module filesystem path,
PyUnicode_DecodeFSDefault is used instead of PyUnicode_DecodeLocale as
is used elsewhere.
* bpo-41894: Fix bugs in dynload error msg handling
For both dynload_aix and dynload_hpux, properly handle the possibility
that decoding strings may return NULL and when such an error happens,
properly decrement any previously decoded strings and return early.
In addition, in dynload_aix, ensure that we pass the decoded string
*object* pathname_ob to PyErr_SetImportError instead of the original
pathname buffer.
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
											
										 
											2020-10-14 20:53:27 -05:00
										 |  |  |         error_ob = PyUnicode_DecodeLocale(error, "surrogateescape"); | 
					
						
							| 
									
										
										
										
											2012-10-02 00:55:07 +02:00
										 |  |  |         if (error_ob == NULL) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2012-04-20 15:22:50 -04:00
										 |  |  |         mod_name = PyUnicode_FromString(shortname); | 
					
						
							| 
									
										
										
										
											2012-10-02 00:55:07 +02:00
										 |  |  |         if (mod_name == NULL) { | 
					
						
							|  |  |  |             Py_DECREF(error_ob); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
											  
											
												bpo-41894: Fix UnicodeDecodeError while loading native module (GH-22466)
When running in a non-UTF-8 locale, if an error occurs while importing a
native Python module (say because a dependent share library is missing),
the error message string returned may contain non-ASCII code points
causing a UnicodeDecodeError.
PyUnicode_DecodeFSDefault is used for buffers which may contain
filesystem  paths. For consistency with os.strerror(),
PyUnicode_DecodeLocale is used for buffers which contain system error
messages. While the shortname parameter is always encoded in ASCII
according to PEP 489, it is left decoded using PyUnicode_FromString to
minimize the changes and since it should not affect the decoding (albeit
_potentially_ slower).
In dynload_hpux, since the error buffer contains a message generated
from a static ASCII string and the module filesystem path,
PyUnicode_DecodeFSDefault is used instead of PyUnicode_DecodeLocale as
is used elsewhere.
* bpo-41894: Fix bugs in dynload error msg handling
For both dynload_aix and dynload_hpux, properly handle the possibility
that decoding strings may return NULL and when such an error happens,
properly decrement any previously decoded strings and return early.
In addition, in dynload_aix, ensure that we pass the decoded string
*object* pathname_ob to PyErr_SetImportError instead of the original
pathname buffer.
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
											
										 
											2020-10-14 20:53:27 -05:00
										 |  |  |         path = PyUnicode_DecodeFSDefault(pathname); | 
					
						
							| 
									
										
										
										
											2012-10-02 00:55:07 +02:00
										 |  |  |         if (path == NULL) { | 
					
						
							|  |  |  |             Py_DECREF(error_ob); | 
					
						
							|  |  |  |             Py_DECREF(mod_name); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2012-04-20 15:22:50 -04:00
										 |  |  |         PyErr_SetImportError(error_ob, mod_name, path); | 
					
						
							| 
									
										
										
										
											2012-10-02 00:55:07 +02:00
										 |  |  |         Py_DECREF(error_ob); | 
					
						
							|  |  |  |         Py_DECREF(mod_name); | 
					
						
							|  |  |  |         Py_DECREF(path); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (fp != NULL && nhandles < 128) | 
					
						
							|  |  |  |         handles[nhandles++].handle = handle; | 
					
						
							|  |  |  |     p = (dl_funcptr) dlsym(handle, funcname); | 
					
						
							|  |  |  |     return p; | 
					
						
							| 
									
										
										
										
											1999-12-20 21:18:49 +00:00
										 |  |  | } |