Skip to content

Free previous state when re-calling Reflection*::__construct() - #22968

Closed
iliaal wants to merge 1 commit into
php:PHP-8.4from
iliaal:fix/reflection-method-reconstruct-leak
Closed

Free previous state when re-calling Reflection*::__construct()#22968
iliaal wants to merge 1 commit into
php:PHP-8.4from
iliaal:fix/reflection-method-reconstruct-leak

Conversation

@iliaal

@iliaal iliaal commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

ReflectionMethod::__construct() overwrites intern->ptr without releasing the previous value. When the reflected method is Closure::__invoke() that value is a trampoline allocated by zend_get_closure_invoke_method(), so every re-construct leaks one. ReflectionClassConstant::__construct() has the same shape for the $name and $class property slots and leaks a string reference whenever the constant name is not interned. ReflectionFunction, ReflectionParameter and ReflectionProperty already release prior state on re-entry.

$r = new ReflectionMethod(function () {}, '__invoke');
for ($i = 0; $i < 10000; $i++) {
    $r->__construct(function () {}, '__invoke');
}
// 2.5 MB of growth on PHP-8.4, zero with the patch

@iliaal
iliaal requested a review from DanielEScherzer as a code owner July 31, 2026 13:26
iliaal added a commit to iliaal/php-src that referenced this pull request Jul 31, 2026
ReflectionMethod::__construct() overwrote intern->ptr without releasing
the previous Closure::__invoke() trampoline, and
ReflectionClassConstant::__construct() overwrote the $name and $class
slots without dropping their previous references. ReflectionFunction,
ReflectionParameter and ReflectionProperty already release prior state
on re-entry.

Closes phpGH-22968
@iliaal
iliaal force-pushed the fix/reflection-method-reconstruct-leak branch from cd9d932 to e3a79ed Compare July 31, 2026 13:27

@DanielEScherzer DanielEScherzer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense to me, one suggestion for clarity

Comment thread ext/reflection/php_reflection.c
ReflectionMethod::__construct() overwrote intern->ptr without releasing
the previous Closure::__invoke() trampoline, and
ReflectionClassConstant::__construct() overwrote the $name and $class
slots without dropping their previous references. ReflectionFunction,
ReflectionParameter and ReflectionProperty already release prior state
on re-entry.

Closes phpGH-22968
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants