Commit a2cdb89100a for php
commit a2cdb89100afdb95f25473082c785f2cdbeff9e3
Author: lazerg <lazerg2@gmail.com>
Date: Wed Sep 30 05:23:06 2026 +0100
Fix GH-23896: Assertion failure in zend_call_function() after a throwing deprecation
Since GH-21699, zend_is_callable_check_class() returns false without
setting error when the error handler throws on the self/parent/static
deprecation. zend_call_function() asserted that a failed callable check
always comes with an error message, so calling such a string callback
through call_user_function() (here unserialize_callback_func=parent::...)
aborts on debug builds.
When the check fails with no error, the exception from the handler is
already pending, so zend_call_function() now returns early without
throwing a second one, the same way it does when it is entered with an
exception.
Close GH-23903
diff --git a/NEWS b/NEWS
index 40236c24a00..2f56de0d1b2 100644
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,8 @@ PHP NEWS
. Fixed AVX being reported as supported when the OS has not enabled AVX
state. (Ilia Alshanetsky)
. Fixed GH-23980 (ZEND_ASSERT violation @ ZEND_INCLUDE_OR_EVAL). (ndossche)
+ . Fixed bug GH-23896 (Assertion failure in zend_call_function() after a
+ throwing deprecation). (lazerg)
- DOM:
. Fixed use-after-free when re-constructing a DOMXPath whose php:function
diff --git a/Zend/tests/gh23896.phpt b/Zend/tests/gh23896.phpt
new file mode 100644
index 00000000000..1524bdb5516
--- /dev/null
+++ b/Zend/tests/gh23896.phpt
@@ -0,0 +1,33 @@
+--TEST--
+GH-23896 (Assertion failure in zend_call_function() when the error handler throws during parent:: callable resolution)
+--FILE--
+<?php
+set_error_handler(function ($severity, $m) {
+ throw new Exception($m, $severity);
+});
+spl_autoload_register(function ($class) {
+ if ($class === 'Loader') {
+ throw new Exception("Cannot load $class");
+ }
+});
+class P {}
+class C extends P {
+ public function u(string $s) {
+ return unserialize($s);
+ }
+}
+foreach (['parent::my_unserialize', 'Loader::load'] as $callback) {
+ ini_set('unserialize_callback_func', $callback);
+ try {
+ (new C)->u('O:3:"FOO":0:{}');
+ } catch (Exception $e) {
+ echo $e->getMessage(), "\n";
+ var_dump($e->getPrevious());
+ }
+}
+?>
+--EXPECT--
+Use of "parent" in callables is deprecated
+NULL
+Cannot load Loader
+NULL
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 9ccb36a1e15..95ff2e4f42f 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -824,6 +824,12 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_
}
if (!zend_is_callable_ex(&fci->function_name, fci->object, 0, NULL, fci_cache, &error)) {
+ if (EG(exception)) {
+ if (error) {
+ efree(error);
+ }
+ return SUCCESS;
+ }
ZEND_ASSERT(error && "Should have error if not callable");
zend_string *callable_name
= zend_get_callable_name_ex(&fci->function_name, fci->object);
diff --git a/ext/xsl/tests/throw_in_autoload.phpt b/ext/xsl/tests/throw_in_autoload.phpt
index 2df7d3690be..90ab0098b8e 100644
--- a/ext/xsl/tests/throw_in_autoload.phpt
+++ b/ext/xsl/tests/throw_in_autoload.phpt
@@ -28,14 +28,12 @@
$xsl = $proc->importStylesheet($xsl);
try {
$newdom = $proc->transformToDoc($inputdom);
-} catch (Error $e) {
+} catch (Exception $e) {
echo $e->getMessage(), "\n";
- echo $e->getPrevious()->getMessage(), "\n";
}
?>
===DONE===
--EXPECT--
string(4) "TeSt"
-Invalid callback TeSt::dateLang, class "TeSt" not found
Autoload exception
===DONE===