From 23e2b789ae2d6ca625843132fa580740daa8b84d Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Sun, 24 Apr 2022 12:39:40 +0200 Subject: [PATCH] Fix unregistering ini entries of dynamically loaded extension --- .cirrus.yml | 2 +- .github/actions/configure-macos/action.yml | 1 + .github/actions/configure-x64/action.yml | 1 + Zend/zend.c | 4 +- Zend/zend_API.c | 2 +- Zend/zend_ini.c | 47 +++++- Zend/zend_ini.h | 2 + azure/configure.yml | 1 + azure/i386/job.yml | 1 + azure/msan_job.yml | 1 + build/Makefile.global | 5 +- ext/dl_test/config.m4 | 8 + ext/dl_test/config.w32 | 8 + ext/dl_test/dl_test.c | 146 ++++++++++++++++++ ext/dl_test/dl_test.stub.php | 7 + ext/dl_test/dl_test_arginfo.h | 20 +++ ext/dl_test/php_dl_test.h | 36 +++++ ext/dl_test/tests/skip.inc | 14 ++ .../tests/general_functions/dl-001.phpt | 34 ++++ .../tests/general_functions/dl-002.phpt | 35 +++++ .../tests/general_functions/dl-003.phpt | 36 +++++ main/main.c | 10 +- travis/compile.sh | 1 + 23 files changed, 408 insertions(+), 14 deletions(-) create mode 100644 ext/dl_test/config.m4 create mode 100644 ext/dl_test/config.w32 create mode 100644 ext/dl_test/dl_test.c create mode 100644 ext/dl_test/dl_test.stub.php create mode 100644 ext/dl_test/dl_test_arginfo.h create mode 100644 ext/dl_test/php_dl_test.h create mode 100644 ext/dl_test/tests/skip.inc create mode 100644 ext/standard/tests/general_functions/dl-001.phpt create mode 100644 ext/standard/tests/general_functions/dl-002.phpt create mode 100644 ext/standard/tests/general_functions/dl-003.phpt diff --git a/.cirrus.yml b/.cirrus.yml index 917859dad2b81..f2db9f81aa50d 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -14,7 +14,7 @@ task: - pkg install -y autoconf bison gmake re2c icu libiconv png freetype2 enchant2 bzip2 krb5 t1lib gmp tidyp libsodium libzip libxml2 libxslt openssl oniguruma pkgconf webp libavif script: - ./buildconf -f - - ./configure --prefix=/usr/local --enable-debug --enable-option-checking=fatal --enable-fpm --with-pdo-sqlite --without-pear --with-bz2 --with-avif --with-jpeg --with-webp --with-freetype --enable-gd --enable-exif --with-zip --with-zlib --enable-soap --enable-xmlreader --with-xsl --with-libxml --enable-shmop --enable-pcntl --enable-mbstring --with-curl --enable-sockets --with-openssl --with-iconv=/usr/local --enable-bcmath --enable-calendar --enable-ftp --with-kerberos --with-ffi --enable-zend-test --enable-intl --with-mhash --with-sodium --enable-werror --with-config-file-path=/etc --with-config-file-scan-dir=/etc/php.d + - ./configure --prefix=/usr/local --enable-debug --enable-option-checking=fatal --enable-fpm --with-pdo-sqlite --without-pear --with-bz2 --with-avif --with-jpeg --with-webp --with-freetype --enable-gd --enable-exif --with-zip --with-zlib --enable-soap --enable-xmlreader --with-xsl --with-libxml --enable-shmop --enable-pcntl --enable-mbstring --with-curl --enable-sockets --with-openssl --with-iconv=/usr/local --enable-bcmath --enable-calendar --enable-ftp --with-kerberos --with-ffi --enable-zend-test --enable-dl-test=shared --enable-intl --with-mhash --with-sodium --enable-werror --with-config-file-path=/etc --with-config-file-scan-dir=/etc/php.d - gmake -j2 - mkdir /etc/php.d - gmake install diff --git a/.github/actions/configure-macos/action.yml b/.github/actions/configure-macos/action.yml index 852d8f62b68e1..319a00595ffc4 100644 --- a/.github/actions/configure-macos/action.yml +++ b/.github/actions/configure-macos/action.yml @@ -61,6 +61,7 @@ runs: --enable-sysvmsg \ --with-ffi \ --enable-zend-test \ + --enable-dl-test=shared \ --enable-intl \ --with-mhash \ --with-sodium \ diff --git a/.github/actions/configure-x64/action.yml b/.github/actions/configure-x64/action.yml index f9b774218f4ef..5b5583918bcfe 100644 --- a/.github/actions/configure-x64/action.yml +++ b/.github/actions/configure-x64/action.yml @@ -56,6 +56,7 @@ runs: --enable-sysvmsg \ --with-ffi \ --enable-zend-test \ + --enable-dl-test=shared \ --with-ldap \ --with-ldap-sasl \ --with-password-argon2 \ diff --git a/Zend/zend.c b/Zend/zend.c index 5f9325cb31c35..808d7648fe805 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -1033,9 +1033,7 @@ void zend_startup(zend_utility_functions *utility_functions) /* {{{ */ void zend_register_standard_ini_entries(void) /* {{{ */ { - int module_number = 0; - - REGISTER_INI_ENTRIES(); + zend_register_ini_entries_ex(ini_entries, 0, MODULE_PERSISTENT); } /* }}} */ diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 0fdf1a02ce991..e21e42c585313 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2965,7 +2965,7 @@ void module_destructor(zend_module_entry *module) /* {{{ */ if (module->module_started && !module->module_shutdown_func && module->type == MODULE_TEMPORARY) { - zend_unregister_ini_entries(module->module_number); + zend_unregister_ini_entries_ex(module->module_number, module->type); } /* Deinitialize module globals */ diff --git a/Zend/zend_ini.c b/Zend/zend_ini.c index 59c8184381862..baef011023c84 100644 --- a/Zend/zend_ini.c +++ b/Zend/zend_ini.c @@ -23,6 +23,7 @@ #include "zend_alloc.h" #include "zend_operators.h" #include "zend_strtod.h" +#include "zend_modules.h" static HashTable *registered_zend_ini_directives; @@ -194,7 +195,7 @@ ZEND_API void zend_ini_sort_entries(void) /* {{{ */ /* * Registration / unregistration */ -ZEND_API zend_result zend_register_ini_entries(const zend_ini_entry_def *ini_entry, int module_number) /* {{{ */ +ZEND_API zend_result zend_register_ini_entries_ex(const zend_ini_entry_def *ini_entry, int module_number, int module_type) /* {{{ */ { zend_ini_entry *p; zval *default_value; @@ -210,7 +211,10 @@ ZEND_API zend_result zend_register_ini_entries(const zend_ini_entry_def *ini_ent * lead to death. */ if (directives != EG(ini_directives)) { + ZEND_ASSERT(module_type == MODULE_TEMPORARY); directives = EG(ini_directives); + } else { + ZEND_ASSERT(module_type == MODULE_PERSISTENT); } #endif @@ -234,7 +238,7 @@ ZEND_API zend_result zend_register_ini_entries(const zend_ini_entry_def *ini_ent if (p->name) { zend_string_release_ex(p->name, 1); } - zend_unregister_ini_entries(module_number); + zend_unregister_ini_entries_ex(module_number, module_type); return FAILURE; } if (((default_value = zend_get_configuration_directive(p->name)) != NULL) && @@ -255,9 +259,46 @@ ZEND_API zend_result zend_register_ini_entries(const zend_ini_entry_def *ini_ent } /* }}} */ +ZEND_API zend_result zend_register_ini_entries(const zend_ini_entry_def *ini_entry, int module_number) /* {{{ */ +{ + zend_module_entry *module; + + /* Module is likely to be the last one in the list */ + ZEND_HASH_REVERSE_FOREACH_PTR(&module_registry, module) { + if (module->module_number == module_number) { + return zend_register_ini_entries_ex(ini_entry, module_number, module->type); + } + } ZEND_HASH_FOREACH_END(); + + return FAILURE; +} +/* }}} */ + +ZEND_API void zend_unregister_ini_entries_ex(int module_number, int module_type) /* {{{ */ +{ + static HashTable *ini_directives; + + if (module_type == MODULE_TEMPORARY) { + ini_directives = EG(ini_directives); + } else { + ini_directives = registered_zend_ini_directives; + } + + zend_hash_apply_with_argument(ini_directives, zend_remove_ini_entries, (void *) &module_number); +} +/* }}} */ + ZEND_API void zend_unregister_ini_entries(int module_number) /* {{{ */ { - zend_hash_apply_with_argument(registered_zend_ini_directives, zend_remove_ini_entries, (void *) &module_number); + zend_module_entry *module; + + /* Module is likely to be the last one in the list */ + ZEND_HASH_REVERSE_FOREACH_PTR(&module_registry, module) { + if (module->module_number == module_number) { + zend_unregister_ini_entries_ex(module_number, module->type); + return; + } + } ZEND_HASH_FOREACH_END(); } /* }}} */ diff --git a/Zend/zend_ini.h b/Zend/zend_ini.h index 590ff09cef0c5..08a4a9cca065f 100644 --- a/Zend/zend_ini.h +++ b/Zend/zend_ini.h @@ -72,7 +72,9 @@ ZEND_API void zend_copy_ini_directives(void); ZEND_API void zend_ini_sort_entries(void); ZEND_API zend_result zend_register_ini_entries(const zend_ini_entry_def *ini_entry, int module_number); +ZEND_API zend_result zend_register_ini_entries_ex(const zend_ini_entry_def *ini_entry, int module_number, int module_type); ZEND_API void zend_unregister_ini_entries(int module_number); +ZEND_API void zend_unregister_ini_entries_ex(int module_number, int module_type); ZEND_API void zend_ini_refresh_caches(int stage); ZEND_API zend_result zend_alter_ini_entry(zend_string *name, zend_string *new_value, int modify_type, int stage); ZEND_API zend_result zend_alter_ini_entry_ex(zend_string *name, zend_string *new_value, int modify_type, int stage, bool force_change); diff --git a/azure/configure.yml b/azure/configure.yml index 9869de514e82c..cf2e3bb2a2d8b 100644 --- a/azure/configure.yml +++ b/azure/configure.yml @@ -50,6 +50,7 @@ steps: --enable-sysvmsg \ --with-ffi \ --enable-zend-test \ + --enable-dl-test=shared \ --with-ldap \ --with-ldap-sasl \ --with-password-argon2 \ diff --git a/azure/i386/job.yml b/azure/i386/job.yml index 6fdfc539fc0c2..6f945aef36c94 100644 --- a/azure/i386/job.yml +++ b/azure/i386/job.yml @@ -62,6 +62,7 @@ jobs: --enable-sysvmsg \ --with-ffi \ --enable-zend-test \ + --enable-dl-test=shared \ --with-mhash \ --with-sodium \ --enable-dba \ diff --git a/azure/msan_job.yml b/azure/msan_job.yml index 919547b11858c..28f9dbe2015a0 100644 --- a/azure/msan_job.yml +++ b/azure/msan_job.yml @@ -49,6 +49,7 @@ jobs: --enable-calendar \ --enable-ftp \ --enable-zend-test \ + --enable-dl-test=shared \ --enable-werror \ --enable-memory-sanitizer \ --with-config-file-path=/etc \ diff --git a/build/Makefile.global b/build/Makefile.global index f93a874ce1b57..0b454a06cfd88 100644 --- a/build/Makefile.global +++ b/build/Makefile.global @@ -75,7 +75,10 @@ PHP_TEST_SETTINGS = -d 'open_basedir=' -d 'output_buffering=0' -d 'memory_limit= PHP_TEST_SHARED_EXTENSIONS = ` \ if test "x$(PHP_MODULES)" != "x"; then \ for i in $(PHP_MODULES)""; do \ - . $$i; $(top_srcdir)/build/shtool echo -n -- " -d extension=$$dlname"; \ + . $$i; \ + if test "x$$dlname" != "xdl_test.so"; then \ + $(top_srcdir)/build/shtool echo -n -- " -d extension=$$dlname"; \ + fi; \ done; \ fi; \ if test "x$(PHP_ZEND_EX)" != "x"; then \ diff --git a/ext/dl_test/config.m4 b/ext/dl_test/config.m4 new file mode 100644 index 0000000000000..10f1adae71b08 --- /dev/null +++ b/ext/dl_test/config.m4 @@ -0,0 +1,8 @@ +PHP_ARG_ENABLE([dl-test], + [whether to enable dl-test extension], + [AS_HELP_STRING([--enable-dl-test], + [Enable dl_test extension])]) + +if test "$PHP_DL_TEST" != "no"; then + PHP_NEW_EXTENSION(dl_test, dl_test.c, [shared],, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) +fi diff --git a/ext/dl_test/config.w32 b/ext/dl_test/config.w32 new file mode 100644 index 0000000000000..8f50eb58c3448 --- /dev/null +++ b/ext/dl_test/config.w32 @@ -0,0 +1,8 @@ +// vim:ft=javascript + +ARG_ENABLE("dl-test", "enable dl_test extension", "no"); + +if (PHP_DL_TEST != "no") { + EXTENSION("dl_test", "dl_test.c", true, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); + ADD_FLAG("CFLAGS_DL_TEST", "/D PHP_DL_TEST_EXPORTS "); +} diff --git a/ext/dl_test/dl_test.c b/ext/dl_test/dl_test.c new file mode 100644 index 0000000000000..88a298b0ec88a --- /dev/null +++ b/ext/dl_test/dl_test.c @@ -0,0 +1,146 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | https://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Arnaud Le Blanc | + +----------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "php.h" +#include "ext/standard/info.h" +#include "php_dl_test.h" +#include "dl_test_arginfo.h" + +ZEND_DECLARE_MODULE_GLOBALS(dl_test) + +/* {{{ void dl_test_test1() */ +PHP_FUNCTION(dl_test_test1) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + php_printf("The extension %s is loaded and working!\r\n", "dl_test"); +} +/* }}} */ + +/* {{{ string dl_test_test2( [ string $var ] ) */ +PHP_FUNCTION(dl_test_test2) +{ + char *var = "World"; + size_t var_len = sizeof("World") - 1; + zend_string *retval; + + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_STRING(var, var_len) + ZEND_PARSE_PARAMETERS_END(); + + retval = strpprintf(0, "Hello %s", var); + + RETURN_STR(retval); +} +/* }}}*/ + +/* {{{ INI */ +PHP_INI_BEGIN() + STD_PHP_INI_BOOLEAN("dl_test.long", "0", PHP_INI_ALL, OnUpdateLong, long_value, zend_dl_test_globals, dl_test_globals) + STD_PHP_INI_ENTRY("dl_test.string", "hello", PHP_INI_ALL, OnUpdateString, string_value, zend_dl_test_globals, dl_test_globals) +PHP_INI_END() +/* }}} */ + +/* {{{ PHP_MINIT_FUNCTION */ +PHP_MINIT_FUNCTION(dl_test) +{ + /* Test backwards compatibility */ + if (getenv("PHP_DL_TEST_USE_OLD_REGISTER_INI_ENTRIES")) { + zend_register_ini_entries(ini_entries, module_number); + } else { + REGISTER_INI_ENTRIES(); + } + + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MSHUTDOWN_FUNCTION */ +static PHP_MSHUTDOWN_FUNCTION(dl_test) +{ + /* Test backwards compatibility */ + if (getenv("PHP_DL_TEST_USE_OLD_REGISTER_INI_ENTRIES")) { + zend_unregister_ini_entries(module_number); + } else { + UNREGISTER_INI_ENTRIES(); + } + + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_RINIT_FUNCTION */ +PHP_RINIT_FUNCTION(dl_test) +{ +#if defined(ZTS) && defined(COMPILE_DL_DL_TEST) + ZEND_TSRMLS_CACHE_UPDATE(); +#endif + + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MINFO_FUNCTION */ +PHP_MINFO_FUNCTION(dl_test) +{ + php_info_print_table_start(); + php_info_print_table_header(2, "dl_test support", "enabled"); + php_info_print_table_end(); + + DISPLAY_INI_ENTRIES(); +} +/* }}} */ + +/* {{{ PHP_GINIT_FUNCTION */ +static PHP_GINIT_FUNCTION(dl_test) +{ +#if defined(COMPILE_DL_DL_TEST) && defined(ZTS) + ZEND_TSRMLS_CACHE_UPDATE(); +#endif + memset(dl_test_globals, 0, sizeof(*dl_test_globals)); +} +/* }}} */ + +/* {{{ dl_test_module_entry */ +zend_module_entry dl_test_module_entry = { + STANDARD_MODULE_HEADER, + "dl_test", + ext_functions, + PHP_MINIT(dl_test), + PHP_MSHUTDOWN(dl_test), + PHP_RINIT(dl_test), + NULL, + PHP_MINFO(dl_test), + PHP_DL_TEST_VERSION, + PHP_MODULE_GLOBALS(dl_test), + PHP_GINIT(dl_test), + NULL, + NULL, + STANDARD_MODULE_PROPERTIES_EX +}; +/* }}} */ + +#ifdef COMPILE_DL_DL_TEST +# ifdef ZTS +ZEND_TSRMLS_CACHE_DEFINE() +# endif +ZEND_GET_MODULE(dl_test) +#endif diff --git a/ext/dl_test/dl_test.stub.php b/ext/dl_test/dl_test.stub.php new file mode 100644 index 0000000000000..36d59480a8d25 --- /dev/null +++ b/ext/dl_test/dl_test.stub.php @@ -0,0 +1,7 @@ + +--FILE-- + +--FILE-- + +--FILE-- +version = PHP_VERSION; module->info_func = PHP_MINFO(php_core); } - + /* freeze the list of observer fcall_init handlers */ zend_observer_post_startup(); @@ -2389,7 +2389,7 @@ int php_module_shutdown_wrapper(sapi_module_struct *sapi_globals) /* {{{ php_module_shutdown */ void php_module_shutdown(void) { - int module_number=0; /* for UNREGISTER_INI_ENTRIES() */ + int module_number=0; module_shutdown = 1; @@ -2420,7 +2420,7 @@ void php_module_shutdown(void) /* Destroys filter & transport registries too */ php_shutdown_stream_wrappers(module_number); - UNREGISTER_INI_ENTRIES(); + zend_unregister_ini_entries_ex(module_number, MODULE_PERSISTENT); /* close down the ini config */ php_shutdown_config(); diff --git a/travis/compile.sh b/travis/compile.sh index dc278c2e15868..8cccc7b883347 100755 --- a/travis/compile.sh +++ b/travis/compile.sh @@ -68,6 +68,7 @@ $S390X_CONFIG \ --with-ffi \ --with-sodium \ --enable-zend-test=shared \ +--enable-dl-test=shared \ --enable-werror \ --with-pear