Commit b8ff8d64ac5 for php.net

commit b8ff8d64ac5af53af0ceca5e991c2fc9dc73f04b
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date:   Sun May 24 20:14:51 2026 -0400

    Fix GH-22112: assertion when error handler throws during NaN coercion

    zend_parse_arg_bool_weak and zend_parse_arg_str_weak could return
    success with EG(exception) already set, because zend_is_true and
    convert_to_string emit the NaN coercion warning without checking
    whether the user error handler threw. Recv-arg verification for a
    userland function then took the no-check ZEND_VM_NEXT_OPCODE branch,
    aborting on ZEND_ASSERT(!EG(exception)). Mirror the existing check in
    zend_parse_arg_long_weak and propagate failure when the warning leaves
    an exception pending.

    Fixes GH-22112
    Closes GH-22114

diff --git a/NEWS b/NEWS
index f127593dbe0..5e480287f24 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,8 @@ PHP                                                                        NEWS
 - Core:
   . Fixed bug GH-22280 (Incorrect compile error for goto to label preceding
     try/finally block). (Pratik Bhujel)
+  . Fixed bug GH-22112 (Assertion when error handler throws during NaN to
+    bool/string coercion). (iliaal)

 - BCMath:
   . Fixed issues with oversized allocations and signed overflow in bcround()
diff --git a/Zend/tests/type_coercion/gh22112.phpt b/Zend/tests/type_coercion/gh22112.phpt
new file mode 100644
index 00000000000..84fdc393a82
--- /dev/null
+++ b/Zend/tests/type_coercion/gh22112.phpt
@@ -0,0 +1,35 @@
+--TEST--
+GH-22112 (Assertion failure when error handler throws during NaN to bool/string coercion at function entry)
+--FILE--
+<?php
+
+set_error_handler(function ($errno, $errstr) {
+    throw new Exception($errstr);
+});
+
+function take_bool(bool $v) {
+    echo "take_bool entered\n";
+}
+
+function take_string(string $v) {
+    echo "take_string entered\n";
+}
+
+$nan = fdiv(0, 0);
+
+try {
+    take_bool($nan);
+} catch (Exception $e) {
+    echo "bool: ", $e->getMessage(), "\n";
+}
+
+try {
+    take_string($nan);
+} catch (Exception $e) {
+    echo "string: ", $e->getMessage(), "\n";
+}
+
+?>
+--EXPECT--
+bool: unexpected NAN value was coerced to bool
+string: unexpected NAN value was coerced to string
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 538c02f0395..e874c4a5bbd 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -537,6 +537,9 @@ ZEND_API bool ZEND_FASTCALL zend_parse_arg_bool_weak(const zval *arg, bool *dest
 			return 0;
 		}
 		*dest = zend_is_true(arg);
+		if (UNEXPECTED(EG(exception))) {
+			return 0;
+		}
 	} else {
 		return 0;
 	}
@@ -762,6 +765,9 @@ ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **des
 			return 0;
 		}
 		convert_to_string(arg);
+		if (UNEXPECTED(EG(exception))) {
+			return 0;
+		}
 		*dest = Z_STR_P(arg);
 	} else if (UNEXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
 		zend_object *zobj = Z_OBJ_P(arg);