2121#include "php_globals.h"
2222#include "php_ini.h"
2323#include "ext/standard/info.h"
24+ #include "Zend/zend_extensions.h"
2425
2526#include "SAPI.h"
2627
@@ -106,16 +107,75 @@ PHPAPI void *php_load_shlib(const char *path, char **errp)
106107}
107108/* }}} */
108109
110+ static zend_result php_register_module_entry (
111+ zend_module_entry * (* get_module )(void ), void * handle , int type , int start_now , int error_type , zend_module_entry * * registered_module )
112+ {
113+ zend_module_entry * module_entry = get_module ();
114+
115+ if (registered_module ) {
116+ * registered_module = NULL ;
117+ }
118+
119+ if (zend_hash_str_exists (& module_registry , module_entry -> name , strlen (module_entry -> name ))) {
120+ zend_error (E_CORE_WARNING , "Module \"%s\" is already loaded" , module_entry -> name );
121+ return FAILURE ;
122+ }
123+ if (module_entry -> zend_api != ZEND_MODULE_API_NO ) {
124+ php_error_docref (NULL , error_type ,
125+ "%s: Unable to initialize module\n"
126+ "Module compiled with module API=%d\n"
127+ "PHP compiled with module API=%d\n"
128+ "These options need to match\n" ,
129+ module_entry -> name , module_entry -> zend_api , ZEND_MODULE_API_NO );
130+ return FAILURE ;
131+ }
132+ if (strcmp (module_entry -> build_id , ZEND_MODULE_BUILD_ID )) {
133+ php_error_docref (NULL , error_type ,
134+ "%s: Unable to initialize module\n"
135+ "Module compiled with build ID=%s\n"
136+ "PHP compiled with build ID=%s\n"
137+ "These options need to match\n" ,
138+ module_entry -> name , module_entry -> build_id , ZEND_MODULE_BUILD_ID );
139+ return FAILURE ;
140+ }
141+
142+ if ((module_entry = zend_register_module_ex (module_entry , type )) == NULL ) {
143+ return FAILURE ;
144+ }
145+
146+ module_entry -> handle = handle ;
147+
148+ if ((type == MODULE_TEMPORARY || start_now ) && zend_startup_module_ex (module_entry ) == FAILURE ) {
149+ return FAILURE ;
150+ }
151+
152+ if ((type == MODULE_TEMPORARY || start_now ) && module_entry -> request_startup_func ) {
153+ if (module_entry -> request_startup_func (type , module_entry -> module_number ) == FAILURE ) {
154+ php_error_docref (NULL , error_type , "Unable to initialize module '%s'" , module_entry -> name );
155+ return FAILURE ;
156+ }
157+ }
158+
159+ if (registered_module ) {
160+ * registered_module = module_entry ;
161+ }
162+ return SUCCESS ;
163+ }
164+
109165/* {{{ php_load_extension */
110166PHPAPI int php_load_extension (const char * filename , int type , int start_now )
111167{
112168 void * handle ;
113169 char * libpath ;
114- zend_module_entry * module_entry ;
170+ zend_module_entry * module_entry = NULL ;
115171 zend_module_entry * (* get_module )(void );
172+ zend_extension * zend_extension_entry ;
116173 int error_type , slash_suffix = 0 ;
117174 char * extension_dir ;
118175 char * err1 , * err2 ;
176+ bool module_loaded = false;
177+ bool zend_extension_loaded = false;
178+ bool allow_zend_extension_load = (type == MODULE_PERSISTENT );
119179
120180 if (type == MODULE_PERSISTENT ) {
121181 extension_dir = INI_STR ("extension_dir" );
@@ -173,13 +233,13 @@ PHPAPI int php_load_extension(const char *filename, int type, int start_now)
173233 efree (orig_libpath );
174234 efree (err1 );
175235 }
176- efree (libpath );
177236
178237#ifdef PHP_WIN32
179238 if (!php_win32_image_compatible (handle , & err1 )) {
180239 php_error_docref (NULL , error_type , "%s" , err1 );
181240 efree (err1 );
182241 DL_UNLOAD (handle );
242+ efree (libpath );
183243 return FAILURE ;
184244 }
185245#endif
@@ -189,68 +249,50 @@ PHPAPI int php_load_extension(const char *filename, int type, int start_now)
189249 /* Some OS prepend _ to symbol names while their dynamic linker
190250 * does not do that automatically. Thus we check manually for
191251 * _get_module. */
192-
193252 if (!get_module ) {
194253 get_module = (zend_module_entry * (* )(void )) DL_FETCH_SYMBOL (handle , "_get_module" );
195254 }
196255
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 ;
256+ zend_extension_entry = (zend_extension * ) DL_FETCH_SYMBOL (handle , "zend_extension_entry" );
257+ if (!zend_extension_entry ) {
258+ zend_extension_entry = (zend_extension * ) DL_FETCH_SYMBOL (handle , "_zend_extension_entry" );
212259 }
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 );
260+
261+ if (!get_module && zend_extension_entry && !allow_zend_extension_load ) {
230262 DL_UNLOAD (handle );
263+ php_error_docref (NULL , error_type , "Invalid library (appears to be a Zend Extension and cannot be loaded via dl()) '%s'" , filename );
264+ efree (libpath );
231265 return FAILURE ;
232266 }
233267
234- if (( module_entry = zend_register_module_ex ( module_entry , type )) == NULL ) {
268+ if (! get_module && ! zend_extension_entry ) {
235269 DL_UNLOAD (handle );
270+ php_error_docref (NULL , error_type , "Invalid library (maybe not a PHP library) '%s'" , filename );
271+ efree (libpath );
236272 return FAILURE ;
237273 }
238274
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 ;
275+ if (get_module && php_register_module_entry (get_module , handle , type , start_now , error_type , & module_entry ) == SUCCESS ) {
276+ module_loaded = true;
244277 }
245278
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 ;
279+ if (zend_extension_entry && allow_zend_extension_load
280+ && zend_load_extension_handle_ex (handle , libpath , false) == SUCCESS ) {
281+ zend_extension_loaded = true;
282+ if (module_loaded && module_entry ) {
283+ /* In dual mode, let Zend extension own this handle. */
284+ module_entry -> handle = NULL ;
251285 }
252286 }
253- return SUCCESS ;
287+
288+ efree (libpath );
289+
290+ if (module_loaded || zend_extension_loaded ) {
291+ return SUCCESS ;
292+ }
293+
294+ DL_UNLOAD (handle );
295+ return FAILURE ;
254296}
255297/* }}} */
256298
0 commit comments