Commit 1da01f076b7 for php.net

commit 1da01f076b75539e8f02b6494b29f6a3c752110e
Merge: 0dc8a54f629 fc6b78ea2a0
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date:   Fri Jul 31 11:51:25 2026 -0400

    Merge branch 'PHP-8.5'

    * PHP-8.5:
      Free previous state when re-calling Reflection*::__construct()

    Master additionally stores the reflected closure in intern->obj for the
    invoke() identity check, so the merge releases the previous object before
    overwriting it and clears the slot when re-constructing onto a named
    method.

diff --cc ext/reflection/php_reflection.c
index 6682346a5b0,fa94cb9a849..42ab6dcd8ae
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@@ -3239,14 -3402,12 +3239,18 @@@ static void instantiate_reflection_meth
  		&& memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
  		&& (mptr = zend_get_closure_invoke_method(orig_obj)) != NULL)
  	{
 -		/* do nothing, mptr already set */
 +		/* Store the original closure object so we can validate it in invoke/invokeArgs.
 +		 * Each closure has a unique __invoke signature, so we must reject different closures. */
++		zval_ptr_dtor(&intern->obj);
 +		ZVAL_OBJ_COPY(&intern->obj, orig_obj);
  	} else if ((mptr = zend_hash_str_find_ptr(&ce->function_table, lcname, method_name_len)) == NULL) {
  		efree(lcname);
  		zend_throw_exception_ex(reflection_exception_ptr, 0,
  			"Method %s::%s() does not exist", ZSTR_VAL(ce->name), method_name);
  		RETURN_THROWS();
++	} else {
++		zval_ptr_dtor(&intern->obj);
++		ZVAL_UNDEF(&intern->obj);
  	}
  	efree(lcname);