From 75998d7b7bd627cf46ad762ceb59e6865a6aee3a Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Mon, 3 Mar 2025 13:12:21 +0100 Subject: [PATCH 1/2] Destroy classes in reverse order when destroying temporary module --- Zend/zend_API.c | 23 +++++++++---------- ext/dl_test/dl_test.c | 11 +++++++++ ext/dl_test/dl_test.stub.php | 8 +++++++ ext/dl_test/dl_test_arginfo.h | 42 ++++++++++++++++++++++++++++++++++- 4 files changed, 70 insertions(+), 14 deletions(-) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 13c640a64dd51..47de6e7897546 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -22,6 +22,7 @@ #include "zend.h" #include "zend_execute.h" #include "zend_API.h" +#include "zend_hash.h" #include "zend_modules.h" #include "zend_extensions.h" #include "zend_constants.h" @@ -3111,21 +3112,17 @@ ZEND_API zend_result zend_get_module_started(const char *module_name) /* {{{ */ } /* }}} */ -static int clean_module_class(zval *el, void *arg) /* {{{ */ -{ - zend_class_entry *ce = (zend_class_entry *)Z_PTR_P(el); - int module_number = *(int *)arg; - if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module->module_number == module_number) { - return ZEND_HASH_APPLY_REMOVE; - } else { - return ZEND_HASH_APPLY_KEEP; - } -} -/* }}} */ - static void clean_module_classes(int module_number) /* {{{ */ { - zend_hash_apply_with_argument(EG(class_table), clean_module_class, (void *) &module_number); + /* Child classes may reuse structures from parent classes, so destroy in reverse order. */ + Bucket *bucket; + ZEND_HASH_REVERSE_FOREACH_BUCKET(EG(class_table), bucket) { + zend_class_entry *ce = Z_CE(bucket->val); + if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module->module_number == module_number) { + zend_hash_del_bucket(EG(class_table), bucket); + } + } ZEND_HASH_FOREACH_END(); + } /* }}} */ diff --git a/ext/dl_test/dl_test.c b/ext/dl_test/dl_test.c index 1121a96b9df8d..5db139d564c9a 100644 --- a/ext/dl_test/dl_test.c +++ b/ext/dl_test/dl_test.c @@ -92,10 +92,21 @@ PHP_METHOD(DlTest, test) RETURN_STR(retval); } +PHP_METHOD(DlTestSuperClass, test) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + RETURN_NULL(); +} + /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(dl_test) { + zend_class_entry *ce; + register_class_DlTest(); + ce = register_class_DlTestSuperClass(); + register_class_DlTestSubClass(ce); /* Test backwards compatibility */ if (getenv("PHP_DL_TEST_USE_OLD_REGISTER_INI_ENTRIES")) { diff --git a/ext/dl_test/dl_test.stub.php b/ext/dl_test/dl_test.stub.php index cd8b3916bae2e..86cda8dbf4458 100644 --- a/ext/dl_test/dl_test.stub.php +++ b/ext/dl_test/dl_test.stub.php @@ -12,3 +12,11 @@ function dl_test_test2(string $str = ""): string {} class DlTest { public function test(string $str = ""): string {} } + +class DlTestSuperClass { + public int $a; + public function test(string $str = ""): string {} +} + +class DlTestSubClass extends DlTestSuperClass { +} diff --git a/ext/dl_test/dl_test_arginfo.h b/ext/dl_test/dl_test_arginfo.h index 0618bbdb222ca..862aab57cdcac 100644 --- a/ext/dl_test/dl_test_arginfo.h +++ b/ext/dl_test/dl_test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 2dbacf5282b0f8e53923ac70495c2da43c7237e3 */ + * Stub hash: 70c8eee05cd6efeedac013d60bd436eec91d43c1 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_dl_test_test1, 0, 0, IS_VOID, 0) ZEND_END_ARG_INFO() @@ -10,10 +10,13 @@ ZEND_END_ARG_INFO() #define arginfo_class_DlTest_test arginfo_dl_test_test2 +#define arginfo_class_DlTestSuperClass_test arginfo_dl_test_test2 + ZEND_FUNCTION(dl_test_test1); ZEND_FUNCTION(dl_test_test2); ZEND_METHOD(DlTest, test); +ZEND_METHOD(DlTestSuperClass, test); static const zend_function_entry ext_functions[] = { @@ -28,6 +31,17 @@ static const zend_function_entry class_DlTest_methods[] = { ZEND_FE_END }; + +static const zend_function_entry class_DlTestSuperClass_methods[] = { + ZEND_ME(DlTestSuperClass, test, arginfo_class_DlTestSuperClass_test, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + + +static const zend_function_entry class_DlTestSubClass_methods[] = { + ZEND_FE_END +}; + static zend_class_entry *register_class_DlTest(void) { zend_class_entry ce, *class_entry; @@ -37,3 +51,29 @@ static zend_class_entry *register_class_DlTest(void) return class_entry; } + +static zend_class_entry *register_class_DlTestSuperClass(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "DlTestSuperClass", class_DlTestSuperClass_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); + + zval property_a_default_value; + ZVAL_UNDEF(&property_a_default_value); + zend_string *property_a_name = zend_string_init("a", sizeof("a") - 1, 1); + zend_declare_typed_property(class_entry, property_a_name, &property_a_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(property_a_name); + + return class_entry; +} + +static zend_class_entry *register_class_DlTestSubClass(zend_class_entry *class_entry_DlTestSuperClass) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "DlTestSubClass", class_DlTestSubClass_methods); + class_entry = zend_register_internal_class_ex(&ce, class_entry_DlTestSuperClass); + + return class_entry; +} From 80f95091ac4e543c15148802357b7b3293521a87 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Mon, 10 Mar 2025 12:23:50 +0100 Subject: [PATCH 2/2] Add class alias in dl_test --- ext/dl_test/dl_test.c | 1 + ext/dl_test/dl_test.stub.php | 4 ++++ ext/dl_test/dl_test_arginfo.h | 18 +++++++++++++++++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/ext/dl_test/dl_test.c b/ext/dl_test/dl_test.c index 5db139d564c9a..1176a874d6027 100644 --- a/ext/dl_test/dl_test.c +++ b/ext/dl_test/dl_test.c @@ -107,6 +107,7 @@ PHP_MINIT_FUNCTION(dl_test) register_class_DlTest(); ce = register_class_DlTestSuperClass(); register_class_DlTestSubClass(ce); + register_class_DlTestAliasedClass(); /* Test backwards compatibility */ if (getenv("PHP_DL_TEST_USE_OLD_REGISTER_INI_ENTRIES")) { diff --git a/ext/dl_test/dl_test.stub.php b/ext/dl_test/dl_test.stub.php index 86cda8dbf4458..c2d8ff577780f 100644 --- a/ext/dl_test/dl_test.stub.php +++ b/ext/dl_test/dl_test.stub.php @@ -20,3 +20,7 @@ public function test(string $str = ""): string {} class DlTestSubClass extends DlTestSuperClass { } + +/** @alias DlTestClassAlias */ +class DlTestAliasedClass { +} diff --git a/ext/dl_test/dl_test_arginfo.h b/ext/dl_test/dl_test_arginfo.h index 862aab57cdcac..549ac220b58bc 100644 --- a/ext/dl_test/dl_test_arginfo.h +++ b/ext/dl_test/dl_test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 70c8eee05cd6efeedac013d60bd436eec91d43c1 */ + * Stub hash: 0641a8eeff00e6c8083fe4a8639f970e3ba80db9 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_dl_test_test1, 0, 0, IS_VOID, 0) ZEND_END_ARG_INFO() @@ -42,6 +42,11 @@ static const zend_function_entry class_DlTestSubClass_methods[] = { ZEND_FE_END }; + +static const zend_function_entry class_DlTestAliasedClass_methods[] = { + ZEND_FE_END +}; + static zend_class_entry *register_class_DlTest(void) { zend_class_entry ce, *class_entry; @@ -77,3 +82,14 @@ static zend_class_entry *register_class_DlTestSubClass(zend_class_entry *class_e return class_entry; } + +static zend_class_entry *register_class_DlTestAliasedClass(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "DlTestAliasedClass", class_DlTestAliasedClass_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); + zend_register_class_alias("DlTestClassAlias", class_entry); + + return class_entry; +}