php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
dl.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Brian Schaffner <brian@tool.net> |
14 | Shane Caraveo <shane@caraveo.com> |
15 | Zeev Suraski <zeev@php.net> |
16 +----------------------------------------------------------------------+
17*/
18
19#include "php.h"
20#include "dl.h"
21#include "php_globals.h"
22#include "php_ini.h"
23#include "ext/standard/info.h"
24
25#include "SAPI.h"
26
27#ifdef HAVE_LIBDL
28#include <stdlib.h>
29#include <stdio.h>
30#include <string.h>
31#ifdef PHP_WIN32
32#include "win32/param.h"
33#include "win32/winutil.h"
34#define GET_DL_ERROR() php_win_err()
35#else
36#include <sys/param.h>
37#define GET_DL_ERROR() DL_ERROR()
38#endif
39#endif /* defined(HAVE_LIBDL) */
40
41/* {{{ Load a PHP extension at runtime */
43{
44 char *filename;
45 size_t filename_len;
46
50
51 if (!PG(enable_dl)) {
52 php_error_docref(NULL, E_WARNING, "Dynamically loaded extensions aren't enabled");
54 }
55
56 if (filename_len >= MAXPATHLEN) {
57 php_error_docref(NULL, E_WARNING, "Filename exceeds the maximum allowed length of %d characters", MAXPATHLEN);
59 }
60
61#if ZEND_RC_DEBUG
62 bool orig_rc_debug = zend_rc_debug;
63 /* FIXME: Loading extensions during the request breaks some invariants. In
64 * particular, it will create persistent interned strings, which is not
65 * allowed at this stage. */
66 zend_rc_debug = false;
67#endif
68
71 EG(full_tables_cleanup) = 1;
72 }
73
74#if ZEND_RC_DEBUG
75 zend_rc_debug = orig_rc_debug;
76#endif
77}
78/* }}} */
79
80#ifdef HAVE_LIBDL
81
82/* {{{ php_load_shlib */
83PHPAPI void *php_load_shlib(const char *path, char **errp)
84{
85 void *handle;
86 char *err;
87
88 handle = DL_LOAD(path);
89 if (!handle) {
90 err = GET_DL_ERROR();
91#ifdef PHP_WIN32
92 if (err && (*err)) {
93 size_t i = strlen(err);
94 (*errp)=estrdup(err);
96 while (i > 0 && isspace((*errp)[i-1])) { (*errp)[i-1] = '\0'; i--; }
97 } else {
98 (*errp) = estrdup("<No message>");
99 }
100#else
101 (*errp) = estrdup(err);
102 GET_DL_ERROR(); /* free the buffer storing the error */
103#endif
104 }
105 return handle;
106}
107/* }}} */
108
109/* {{{ php_load_extension */
110PHPAPI int php_load_extension(const char *filename, int type, int start_now)
111{
112 void *handle;
113 char *libpath;
114 zend_module_entry *module_entry;
115 zend_module_entry *(*get_module)(void);
116 int error_type, slash_suffix = 0;
117 char *extension_dir;
118 char *err1, *err2;
119
120 if (type == MODULE_PERSISTENT) {
121 extension_dir = INI_STR("extension_dir");
122 } else {
124 }
125
126 if (type == MODULE_TEMPORARY) {
127 error_type = E_WARNING;
128 } else {
129 error_type = E_CORE_WARNING;
130 }
131
132 /* Check if passed filename contains directory separators */
133 if (strchr(filename, '/') != NULL || strchr(filename, DEFAULT_SLASH) != NULL) {
134 /* Passing modules with full path is not supported for dynamically loaded extensions */
135 if (type == MODULE_TEMPORARY) {
136 php_error_docref(NULL, E_WARNING, "Temporary module name should contain only filename");
137 return FAILURE;
138 }
139 libpath = estrdup(filename);
140 } else if (extension_dir && extension_dir[0]) {
141 slash_suffix = IS_SLASH(extension_dir[strlen(extension_dir)-1]);
142 /* Try as filename first */
143 if (slash_suffix) {
144 spprintf(&libpath, 0, "%s%s", extension_dir, filename); /* SAFE */
145 } else {
146 spprintf(&libpath, 0, "%s%c%s", extension_dir, DEFAULT_SLASH, filename); /* SAFE */
147 }
148 } else {
149 return FAILURE; /* Not full path given or extension_dir is not set */
150 }
151
152 handle = php_load_shlib(libpath, &err1);
153 if (!handle) {
154 /* Now, consider 'filename' as extension name and build file name */
155 char *orig_libpath = libpath;
156
157 if (slash_suffix) {
158 spprintf(&libpath, 0, "%s" PHP_SHLIB_EXT_PREFIX "%s." PHP_SHLIB_SUFFIX, extension_dir, filename); /* SAFE */
159 } else {
160 spprintf(&libpath, 0, "%s%c" PHP_SHLIB_EXT_PREFIX "%s." PHP_SHLIB_SUFFIX, extension_dir, DEFAULT_SLASH, filename); /* SAFE */
161 }
162
163 handle = php_load_shlib(libpath, &err2);
164 if (!handle) {
165 php_error_docref(NULL, error_type, "Unable to load dynamic library '%s' (tried: %s (%s), %s (%s))",
166 filename, orig_libpath, err1, libpath, err2);
167 efree(orig_libpath);
168 efree(err1);
169 efree(libpath);
170 efree(err2);
171 return FAILURE;
172 }
173 efree(orig_libpath);
174 efree(err1);
175 }
176 efree(libpath);
177
178#ifdef PHP_WIN32
179 if (!php_win32_image_compatible(handle, &err1)) {
180 php_error_docref(NULL, error_type, err1);
181 efree(err1);
182 DL_UNLOAD(handle);
183 return FAILURE;
184 }
185#endif
186
187 get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "get_module");
188
189 /* Some OS prepend _ to symbol names while their dynamic linker
190 * does not do that automatically. Thus we check manually for
191 * _get_module. */
192
193 if (!get_module) {
194 get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "_get_module");
195 }
196
197 if (!get_module) {
198 if (DL_FETCH_SYMBOL(handle, "zend_extension_entry") || DL_FETCH_SYMBOL(handle, "_zend_extension_entry")) {
199 DL_UNLOAD(handle);
200 php_error_docref(NULL, error_type, "Invalid library (appears to be a Zend Extension, try loading using zend_extension=%s from php.ini)", filename);
201 return FAILURE;
202 }
203 DL_UNLOAD(handle);
204 php_error_docref(NULL, error_type, "Invalid library (maybe not a PHP library) '%s'", filename);
205 return FAILURE;
206 }
207 module_entry = get_module();
208 if (zend_hash_str_exists(&module_registry, module_entry->name, strlen(module_entry->name))) {
209 zend_error(E_CORE_WARNING, "Module \"%s\" is already loaded", module_entry->name);
210 DL_UNLOAD(handle);
211 return FAILURE;
212 }
213 if (module_entry->zend_api != ZEND_MODULE_API_NO) {
214 php_error_docref(NULL, error_type,
215 "%s: Unable to initialize module\n"
216 "Module compiled with module API=%d\n"
217 "PHP compiled with module API=%d\n"
218 "These options need to match\n",
219 module_entry->name, module_entry->zend_api, ZEND_MODULE_API_NO);
220 DL_UNLOAD(handle);
221 return FAILURE;
222 }
223 if(strcmp(module_entry->build_id, ZEND_MODULE_BUILD_ID)) {
224 php_error_docref(NULL, error_type,
225 "%s: Unable to initialize module\n"
226 "Module compiled with build ID=%s\n"
227 "PHP compiled with build ID=%s\n"
228 "These options need to match\n",
229 module_entry->name, module_entry->build_id, ZEND_MODULE_BUILD_ID);
230 DL_UNLOAD(handle);
231 return FAILURE;
232 }
233
234 if ((module_entry = zend_register_module_ex(module_entry, type)) == NULL) {
235 DL_UNLOAD(handle);
236 return FAILURE;
237 }
238
239 module_entry->handle = handle;
240
241 if ((type == MODULE_TEMPORARY || start_now) && zend_startup_module_ex(module_entry) == FAILURE) {
242 DL_UNLOAD(handle);
243 return FAILURE;
244 }
245
246 if ((type == MODULE_TEMPORARY || start_now) && module_entry->request_startup_func) {
247 if (module_entry->request_startup_func(type, module_entry->module_number) == FAILURE) {
248 php_error_docref(NULL, error_type, "Unable to initialize module '%s'", module_entry->name);
249 DL_UNLOAD(handle);
250 return FAILURE;
251 }
252 }
253 return SUCCESS;
254}
255/* }}} */
256
257#else
258
259static void php_dl_error(const char *filename)
260{
261 php_error_docref(NULL, E_WARNING, "Cannot dynamically load %s - dynamic modules are not supported", filename);
262}
263
264PHPAPI void *php_load_shlib(const char *path, char **errp)
265{
266 php_dl_error(path);
267 (*errp) = estrdup("No DL support");
268 return NULL;
269}
270
271PHPAPI int php_load_extension(const char *filename, int type, int start_now)
272{
273 php_dl_error(filename);
274
275 return FAILURE;
276}
277
278#endif
279
280/* {{{ php_dl */
281PHPAPI void php_dl(const char *file, int type, zval *return_value, int start_now)
282{
283 /* Load extension */
284 if (php_load_extension(file, type, start_now) == FAILURE) {
286 } else {
288 }
289}
290/* }}} */
291
293{
294#if defined(HAVE_LIBDL)
295#define PHP_DL_SUPPORT_STATUS "enabled"
296#else
297#define PHP_DL_SUPPORT_STATUS "unavailable"
298#endif
299 php_info_print_table_row(2, "Dynamic Library Support", PHP_DL_SUPPORT_STATUS);
300}
file(string $filename, int $flags=0, $context=null)
strchr(string $haystack, string $needle, bool $before_needle=false)
PHPAPI int php_load_extension(const char *filename, int type, int start_now)
Definition dl.c:271
PHPAPI void php_dl(const char *file, int type, zval *return_value, int start_now)
Definition dl.c:281
PHPAPI void * php_load_shlib(const char *path, char **errp)
Definition dl.c:264
#define PHP_DL_SUPPORT_STATUS
dl(string $extension_filename)
Definition dl.stub.php:3
zend_ffi_type * type
Definition ffi.c:3812
DL_HANDLE handle
Definition ffi.c:3028
char * err
Definition ffi.c:3029
size_t filename_len
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
Definition main.c:1173
const PHP_SHLIB_SUFFIX
php_info_print_table_row(2, "PDO Driver for Firebird", "enabled")
#define PHP_FUNCTION
Definition php.h:364
#define PHP_MINFO_FUNCTION
Definition php.h:404
#define PHPAPI
Definition php.h:71
#define PG(v)
Definition php_globals.h:31
char * extension_dir
Definition php_sqlite3.h:26
#define spprintf
Definition spprintf.h:29
unsigned int zend_api
const char * name
int module_number
const char * build_id
void * handle
zend_result(* request_startup_func)(INIT_FUNC_ARGS)
PHP_WINUTIL_API BOOL php_win32_image_compatible(HMODULE handle, char **err)
Definition winutil.c:479
PHP_WINUTIL_API void php_win32_error_msg_free(char *msg)
Definition winutil.c:50
ZEND_API ZEND_COLD void zend_error(int type, const char *format,...)
Definition zend.c:1666
ZEND_API zend_module_entry * zend_register_module_ex(zend_module_entry *module, int module_type)
Definition zend_API.c:2587
ZEND_API HashTable module_registry
Definition zend_API.c:41
ZEND_API zend_result zend_startup_module_ex(zend_module_entry *module)
Definition zend_API.c:2388
#define ZEND_PARSE_PARAMETERS_END()
Definition zend_API.h:1641
#define RETURN_FALSE
Definition zend_API.h:1058
#define Z_PARAM_STRING(dest, dest_len)
Definition zend_API.h:2071
#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
Definition zend_API.h:1620
#define RETVAL_TRUE
Definition zend_API.h:1033
#define RETVAL_FALSE
Definition zend_API.h:1032
#define efree(ptr)
Definition zend_alloc.h:155
#define estrdup(s)
Definition zend_alloc.h:164
struct _zval_struct zval
strlen(string $string)
strcmp(string $string1, string $string2)
#define E_WARNING
Definition zend_errors.h:24
#define E_CORE_WARNING
Definition zend_errors.h:28
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
#define EG(v)
#define INI_STR(name)
Definition zend_ini.h:195
#define ZEND_MODULE_API_NO
#define ZEND_MODULE_BUILD_ID
#define MODULE_TEMPORARY
struct _zend_module_entry zend_module_entry
#define MODULE_PERSISTENT
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define IS_TRUE
Definition zend_types.h:603
@ FAILURE
Definition zend_types.h:61
#define IS_SLASH(c)
#define DEFAULT_SLASH
#define MAXPATHLEN
zval * return_value