Skip to content

Commit 1c18267

Browse files
committed
Destroy temporary module classes in reverse order
We destroy classes of dl()'ed modules in clean_module_classes(), during shutdown. Child classes of a module use structures of the parent class (such as inherited properties), which are destroyed earlier, so we have a use-after-free when destroying a child class. Here I destroy classes in reverse order, as it is done in zend_shutdown() for persistent classes. Fixes GH-17961 Fixes GH-15367
1 parent a7d2703 commit 1c18267

File tree

5 files changed

+97
-14
lines changed

5 files changed

+97
-14
lines changed

NEWS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 8.3.20
44

5+
- Core:
6+
. Fixed bug GH-17961 (use-after-free during dl()'ed module class destruction).
7+
(Arnaud)
8+
. Fixed bug GH-15367 (dl() of module with aliased class crashes in shutdown).
9+
(Arnaud)
10+
511
- DOM:
612
. Fix weird unpack behaviour in DOM. (nielsdos)
713

Zend/zend_API.c

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "zend.h"
2323
#include "zend_execute.h"
2424
#include "zend_API.h"
25+
#include "zend_hash.h"
2526
#include "zend_modules.h"
2627
#include "zend_extensions.h"
2728
#include "zend_constants.h"
@@ -3111,21 +3112,17 @@ ZEND_API zend_result zend_get_module_started(const char *module_name) /* {{{ */
31113112
}
31123113
/* }}} */
31133114

3114-
static int clean_module_class(zval *el, void *arg) /* {{{ */
3115-
{
3116-
zend_class_entry *ce = (zend_class_entry *)Z_PTR_P(el);
3117-
int module_number = *(int *)arg;
3118-
if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module->module_number == module_number) {
3119-
return ZEND_HASH_APPLY_REMOVE;
3120-
} else {
3121-
return ZEND_HASH_APPLY_KEEP;
3122-
}
3123-
}
3124-
/* }}} */
3125-
31263115
static void clean_module_classes(int module_number) /* {{{ */
31273116
{
3128-
zend_hash_apply_with_argument(EG(class_table), clean_module_class, (void *) &module_number);
3117+
/* Child classes may reuse structures from parent classes, so destroy in reverse order. */
3118+
Bucket *bucket;
3119+
ZEND_HASH_REVERSE_FOREACH_BUCKET(EG(class_table), bucket) {
3120+
zend_class_entry *ce = Z_CE(bucket->val);
3121+
if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module->module_number == module_number) {
3122+
zend_hash_del_bucket(EG(class_table), bucket);
3123+
}
3124+
} ZEND_HASH_FOREACH_END();
3125+
31293126
}
31303127
/* }}} */
31313128

ext/dl_test/dl_test.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,22 @@ PHP_METHOD(DlTest, test)
9292
RETURN_STR(retval);
9393
}
9494

95+
PHP_METHOD(DlTestSuperClass, test)
96+
{
97+
ZEND_PARSE_PARAMETERS_NONE();
98+
99+
RETURN_NULL();
100+
}
101+
95102
/* {{{ PHP_MINIT_FUNCTION */
96103
PHP_MINIT_FUNCTION(dl_test)
97104
{
105+
zend_class_entry *ce;
106+
98107
register_class_DlTest();
108+
ce = register_class_DlTestSuperClass();
109+
register_class_DlTestSubClass(ce);
110+
register_class_DlTestAliasedClass();
99111

100112
/* Test backwards compatibility */
101113
if (getenv("PHP_DL_TEST_USE_OLD_REGISTER_INI_ENTRIES")) {

ext/dl_test/dl_test.stub.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,15 @@ function dl_test_test2(string $str = ""): string {}
1212
class DlTest {
1313
public function test(string $str = ""): string {}
1414
}
15+
16+
class DlTestSuperClass {
17+
public int $a;
18+
public function test(string $str = ""): string {}
19+
}
20+
21+
class DlTestSubClass extends DlTestSuperClass {
22+
}
23+
24+
/** @alias DlTestClassAlias */
25+
class DlTestAliasedClass {
26+
}

ext/dl_test/dl_test_arginfo.h

Lines changed: 57 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)