Skip to content

Commit fc6b78e

Browse files
committed
Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4: Free previous state when re-calling Reflection*::__construct()
2 parents 4ff84aa + 87f8d17 commit fc6b78e

3 files changed

Lines changed: 73 additions & 0 deletions

File tree

ext/reflection/php_reflection.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3411,6 +3411,13 @@ static void instantiate_reflection_method(INTERNAL_FUNCTION_PARAMETERS, bool is_
34113411
}
34123412
efree(lcname);
34133413

3414+
if (intern->ptr) {
3415+
ZEND_ASSERT(is_constructor);
3416+
_free_function(intern->ptr);
3417+
zval_ptr_dtor(reflection_prop_name(object));
3418+
zval_ptr_dtor(reflection_prop_class(object));
3419+
}
3420+
34143421
ZVAL_STR_COPY(reflection_prop_name(object), mptr->common.function_name);
34153422
ZVAL_STR_COPY(reflection_prop_class(object), mptr->common.scope->name);
34163423
intern->ptr = mptr;
@@ -3895,6 +3902,11 @@ ZEND_METHOD(ReflectionClassConstant, __construct)
38953902
RETURN_THROWS();
38963903
}
38973904

3905+
if (intern->ptr) {
3906+
zval_ptr_dtor(reflection_prop_name(object));
3907+
zval_ptr_dtor(reflection_prop_class(object));
3908+
}
3909+
38983910
intern->ptr = constant;
38993911
intern->ref_type = REF_TYPE_CLASS_CONSTANT;
39003912
intern->ce = constant->ce;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
ReflectionClassConstant double construct call does not leak $name and $class
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
const FOO = 1;
8+
}
9+
10+
function test(ReflectionClassConstant $r) {
11+
/* implode() so that the name is not an interned string. */
12+
$r->__construct(C::class, implode('', ['F', 'O', 'O']));
13+
}
14+
15+
$r = new ReflectionClassConstant(C::class, 'FOO');
16+
for ($i = 0; $i < 10; $i++) {
17+
test($r);
18+
}
19+
20+
$before = memory_get_usage();
21+
for ($i = 0; $i < 1000; $i++) {
22+
test($r);
23+
}
24+
$after = memory_get_usage();
25+
26+
var_dump($before === $after);
27+
var_dump($r->name, $r->class);
28+
29+
?>
30+
--EXPECT--
31+
bool(true)
32+
string(3) "FOO"
33+
string(1) "C"
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
ReflectionMethod double construct call on Closure::__invoke() does not leak
3+
--FILE--
4+
<?php
5+
6+
function test(ReflectionMethod $r) {
7+
$r->__construct(function () {}, '__invoke');
8+
}
9+
10+
$r = new ReflectionMethod(function () {}, '__invoke');
11+
for ($i = 0; $i < 10; $i++) {
12+
test($r);
13+
}
14+
15+
$before = memory_get_usage();
16+
for ($i = 0; $i < 1000; $i++) {
17+
test($r);
18+
}
19+
$after = memory_get_usage();
20+
21+
var_dump($before === $after);
22+
var_dump($r->name, $r->class);
23+
24+
?>
25+
--EXPECT--
26+
bool(true)
27+
string(8) "__invoke"
28+
string(7) "Closure"

0 commit comments

Comments
 (0)