diff --git a/Zend/tests/ArrayAccess/bug41209.phpt b/Zend/tests/ArrayAccess/bug41209.phpt index 1a7ee8aa515c..956d77f6fed9 100644 --- a/Zend/tests/ArrayAccess/bug41209.phpt +++ b/Zend/tests/ArrayAccess/bug41209.phpt @@ -7,7 +7,7 @@ class env { public function __construct() { - set_error_handler(array(__CLASS__, 'errorHandler')); + set_error_handler(array(__CLASS__, 'errorHandler'), delay: false); } public static function errorHandler($errno, $errstr, $errfile, $errline) diff --git a/Zend/tests/attributes/deprecated/class_constants/deprecated_constant_as_message_002.phpt b/Zend/tests/attributes/deprecated/class_constants/deprecated_constant_as_message_002.phpt index ab84d4724226..ba6103145957 100644 --- a/Zend/tests/attributes/deprecated/class_constants/deprecated_constant_as_message_002.phpt +++ b/Zend/tests/attributes/deprecated/class_constants/deprecated_constant_as_message_002.phpt @@ -5,7 +5,7 @@ set_error_handler(function (int $errno, string $errstr, ?string $errfile = null, ?int $errline = null) { throw new \ErrorException($errstr, 0, $errno, $errfile, $errline); -}); +}, delay: false); class Clazz { #[\Deprecated(self::TEST)] diff --git a/Zend/tests/attributes/deprecated/constants/deprecated_constant_as_message_002.phpt b/Zend/tests/attributes/deprecated/constants/deprecated_constant_as_message_002.phpt index f749293d8fac..5fb3359c138e 100644 --- a/Zend/tests/attributes/deprecated/constants/deprecated_constant_as_message_002.phpt +++ b/Zend/tests/attributes/deprecated/constants/deprecated_constant_as_message_002.phpt @@ -5,7 +5,7 @@ set_error_handler(function (int $errno, string $errstr, ?string $errfile = null, ?int $errline = null) { throw new \ErrorException($errstr, 0, $errno, $errfile, $errline); -}); +}, delay: false); #[\Deprecated(TEST)] const TEST = "from itself"; diff --git a/Zend/tests/attributes/deprecated/functions/throwing_error_handler_001.phpt b/Zend/tests/attributes/deprecated/functions/throwing_error_handler_001.phpt index af816aea6c4b..3e151479e599 100644 --- a/Zend/tests/attributes/deprecated/functions/throwing_error_handler_001.phpt +++ b/Zend/tests/attributes/deprecated/functions/throwing_error_handler_001.phpt @@ -5,7 +5,7 @@ set_error_handler(function (int $errno, string $errstr, ?string $errfile = null, ?int $errline = null) { throw new \ErrorException($errstr, 0, $errno, $errfile, $errline); -}); +}, delay: false); #[\Deprecated("convert to exception")] function test() { @@ -76,7 +76,7 @@ class Destructor { } try { - new Destructor(); + (function () { new Destructor(); })(); } catch (ErrorException $e) { echo "Caught: ", $e->getMessage(), PHP_EOL; } diff --git a/Zend/tests/backtrace/debug_backtrace_with_include_and_this.phpt b/Zend/tests/backtrace/debug_backtrace_with_include_and_this.phpt index 49796a9b9103..5a8474d14963 100644 --- a/Zend/tests/backtrace/debug_backtrace_with_include_and_this.phpt +++ b/Zend/tests/backtrace/debug_backtrace_with_include_and_this.phpt @@ -30,8 +30,8 @@ try { } ?> --EXPECTF-- -ERR#2: include(class://non.existent.Class): Failed to open stream: "CLWrapper::stream_open" call failed @ include -ERR#2: include(): Failed opening 'class://non.existent.Class' for inclusion (include_path='%s') @ include +ERR#2: include(class://non.existent.Class): Failed to open stream: "CLWrapper::stream_open" call failed @ __construct +ERR#2: include(): Failed opening 'class://non.existent.Class' for inclusion (include_path='.:') @ __construct Fatal error: Uncaught Exception: Failed loading class://non.existent.Class in %s Stack trace: diff --git a/Zend/tests/bind_static_exception.phpt b/Zend/tests/bind_static_exception.phpt index c374130aaecf..a0dc1ed6db3f 100644 --- a/Zend/tests/bind_static_exception.phpt +++ b/Zend/tests/bind_static_exception.phpt @@ -8,8 +8,10 @@ class Test { } } try { - $new = new Test; - static $new; + (function () { + $new = new Test; + static $new; + })(); } catch (Exception $e) { echo $e->getMessage(), "\n"; } diff --git a/Zend/tests/bitwise_not_precision_exception.phpt b/Zend/tests/bitwise_not_precision_exception.phpt index e28bf8f4e17b..044b3362d9c4 100644 --- a/Zend/tests/bitwise_not_precision_exception.phpt +++ b/Zend/tests/bitwise_not_precision_exception.phpt @@ -4,7 +4,7 @@ Promoting float precision warning to exception in bitwise_not --EXPECTF-- #0 %s(%d): userErrorHandler(2, 'Undefined varia...', '%s', %d) -#1 %s(%d): GenerateError1('Test1') -#2 %s(%d): GenerateError2('Test2') +#1 %s(%d): GenerateError2('Test2') diff --git a/Zend/tests/bug38220.phpt b/Zend/tests/bug38220.phpt index 2700299a1026..542e20826ab9 100644 --- a/Zend/tests/bug38220.phpt +++ b/Zend/tests/bug38220.phpt @@ -26,6 +26,7 @@ class A { $drv = myserv::drv(); $drv->obj = $this; + (function (){})(); echo "before call $method\n"; print_r($this); diff --git a/Zend/tests/bug49893.phpt b/Zend/tests/bug49893.phpt index 0832b0b0ef4c..ff0b740a68bb 100644 --- a/Zend/tests/bug49893.phpt +++ b/Zend/tests/bug49893.phpt @@ -18,8 +18,11 @@ class B { throw new Exception("1"); } } -try { +function f() { $b = new B(); +} +try { + f(); } catch(Exception $e) { echo $e->getMessage() . "\n"; } diff --git a/Zend/tests/bug52041.phpt b/Zend/tests/bug52041.phpt index 7debab3f8beb..83fbf2f26fd9 100644 --- a/Zend/tests/bug52041.phpt +++ b/Zend/tests/bug52041.phpt @@ -1,5 +1,7 @@ --TEST-- Bug #52041 (Memory leak when writing on uninitialized variable returned from function) +--INI-- +opcache.jit=0 --FILE-- diff --git a/Zend/tests/bug61767.phpt b/Zend/tests/bug61767.phpt index a12c5716e9ae..6ee7c0a8843c 100644 --- a/Zend/tests/bug61767.phpt +++ b/Zend/tests/bug61767.phpt @@ -5,7 +5,7 @@ Bug #61767 (Shutdown functions not called in certain error situation) set_error_handler(function($code, $msg, $file = null, $line = null) { echo "Error handler called ($msg)\n"; throw new \ErrorException($msg, $code, 0, $file, $line); -}); +}, delay: false); register_shutdown_function(function(){ echo "Shutting down\n"; diff --git a/Zend/tests/bug63206.phpt b/Zend/tests/bug63206.phpt index 6aba55eca1ba..8921a8685f9b 100644 --- a/Zend/tests/bug63206.phpt +++ b/Zend/tests/bug63206.phpt @@ -14,13 +14,19 @@ set_error_handler(function() { echo 'Internal handler' . PHP_EOL; }); + global $tmp; $triggerInternalNotice++; // warnings while handling the error should go into internal handler + fwrite($tmp, "."); // handle errors restore_error_handler(); }); +$tmp = tmpfile(); + $triggerNotice1++; +fwrite($tmp, "."); // handle errors $triggerNotice2++; +fwrite($tmp, "."); // handle errors ?> --EXPECT-- Second handler diff --git a/Zend/tests/bug70662.phpt b/Zend/tests/bug70662.phpt index ab540c9d16e5..2bda8141bab4 100644 --- a/Zend/tests/bug70662.phpt +++ b/Zend/tests/bug70662.phpt @@ -14,5 +14,5 @@ var_dump($a); --EXPECT-- array(1) { ["b"]=> - int(2) + int(1) } diff --git a/Zend/tests/bug70785.phpt b/Zend/tests/bug70785.phpt index 05b1b6afa0a0..363cea1deb63 100644 --- a/Zend/tests/bug70785.phpt +++ b/Zend/tests/bug70785.phpt @@ -5,7 +5,7 @@ Bug #70785 (Infinite loop due to exception during identical comparison) set_error_handler(function($no, $msg) { throw new Exception($msg); -}); +}, delay: false); try { if ($a === null) { // ZEND_VM_SMART_BRANCH diff --git a/Zend/tests/bug72101.phpt b/Zend/tests/bug72101.phpt index 6362a7ccb303..51c67071519e 100644 --- a/Zend/tests/bug72101.phpt +++ b/Zend/tests/bug72101.phpt @@ -63,7 +63,7 @@ class Mock_MethodCallbackByReference_7b180d26 extends MethodCallbackByReference set_error_handler(function() { // var_dump(func_get_args()); DoesNotExists::$nope = true; -}, E_ALL); +}, E_ALL, delay: false); $foo = new Mock_MethodCallbackByReference_7b180d26(); $InvMocker = new PHPUnit_Framework_MockObject_InvocationMocker(); diff --git a/Zend/tests/bug74164.phpt b/Zend/tests/bug74164.phpt index ef56f10225fd..e4de55253161 100644 --- a/Zend/tests/bug74164.phpt +++ b/Zend/tests/bug74164.phpt @@ -7,14 +7,13 @@ namespace Foo; set_error_handler(function ($type, $msg) { throw new \Exception($msg); -}); +}, delay: false); call_user_func(function (array &$ref) {var_dump("xxx");}, 'not_an_array_variable'); ?> --EXPECTF-- Fatal error: Uncaught Exception: {closure:%s:%d}(): Argument #1 ($ref) must be passed by reference, value given in %s:%d Stack trace: -#0 [internal function]: {closure:%s:%d}(2, '%s', '%s', 9) -#1 %sbug74164.php(%d): call_user_func(%s) -#2 {main} +#0 %s(%d): {closure:%s:%d}(2, '{closure:%s', '%s', 9) +#1 {main} thrown in %sbug74164.php on line %d diff --git a/Zend/tests/bug76534.phpt b/Zend/tests/bug76534.phpt index c9c897110d6c..d39714b7a62d 100644 --- a/Zend/tests/bug76534.phpt +++ b/Zend/tests/bug76534.phpt @@ -4,7 +4,7 @@ Bug #76534 (PHP hangs on 'illegal string offset on string references with an err --EXPECT-- -int(0) -int(0) -int(0) -int(0) +array(1) { + [0]=> + string(3) "xyz" +} +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + string(3) "xyz" + } + } +} +array(1) { + ["foo"]=> + string(3) "xyz" +} +array(1) { + ["foo"]=> + array(1) { + ["bar"]=> + array(1) { + ["baz"]=> + string(3) "xyz" + } + } +} diff --git a/Zend/tests/bug79599.phpt b/Zend/tests/bug79599.phpt index 57e5332431f5..1cca9d84a61b 100644 --- a/Zend/tests/bug79599.phpt +++ b/Zend/tests/bug79599.phpt @@ -4,7 +4,7 @@ Bug #79599 (coredump in set_error_handler) --EXPECT-- -NULL -NULL -NULL +array(1) { + [""]=> + string(1) "x" +} +array(1) { + [""]=> + string(1) "x" +} +array(1) { + [""]=> + array(1) { + [""]=> + string(1) "x" + } +} diff --git a/Zend/tests/bug79793.phpt b/Zend/tests/bug79793.phpt index 5491a2669ed9..4af55ffd07cb 100644 --- a/Zend/tests/bug79793.phpt +++ b/Zend/tests/bug79793.phpt @@ -18,15 +18,15 @@ var_dump($ary); ?> --EXPECT-- -Undefined array key "foobar" array(1) { ["foobar"]=> int(1) } -Undefined array key "foobarbaz" +Undefined array key "foobar" array(2) { ["foobar"]=> int(1) ["foobarbaz"]=> int(1) } +Undefined array key "foobarbaz" diff --git a/Zend/tests/closures/closure_031.phpt b/Zend/tests/closures/closure_031.phpt index 19f3dc6e3212..7f9d3780e4ff 100644 --- a/Zend/tests/closures/closure_031.phpt +++ b/Zend/tests/closures/closure_031.phpt @@ -15,5 +15,5 @@ try { } ?> --EXPECT-- -Warning: Undefined property: Closure::$a NULL +Warning: Undefined property: Closure::$a diff --git a/Zend/tests/coalesce/assign_coalesce_002.phpt b/Zend/tests/coalesce/assign_coalesce_002.phpt index 0b2c5374bc7a..c6297fd623d1 100644 --- a/Zend/tests/coalesce/assign_coalesce_002.phpt +++ b/Zend/tests/coalesce/assign_coalesce_002.phpt @@ -46,6 +46,7 @@ class Dtor { $ary = new AA; try { $ary[new Dtor][id($foo)] ??= $bar; + (function () {})(); } catch (Exception $e) { echo $e->getMessage(), "\n"; } diff --git a/Zend/tests/compound_assign_failure.phpt b/Zend/tests/compound_assign_failure.phpt index 0dc9af85f253..2e4db29950d5 100644 --- a/Zend/tests/compound_assign_failure.phpt +++ b/Zend/tests/compound_assign_failure.phpt @@ -20,7 +20,7 @@ try { $a <<= -1; } catch (Error $e) { var_dump($a); } -set_error_handler(function($type, $msg) { throw new Exception($msg); }); +set_error_handler(function($type, $msg) { throw new Exception($msg); }, delay: false); try { $a = []; diff --git a/Zend/tests/concat/bug81705.phpt b/Zend/tests/concat/bug81705.phpt index 1c00b1c77d4b..ba3d956f6bd2 100644 --- a/Zend/tests/concat/bug81705.phpt +++ b/Zend/tests/concat/bug81705.phpt @@ -15,5 +15,5 @@ $my_var .= $GLOBALS["arr"]; var_dump($my_var); ?> --EXPECT-- +string(6) "aArray" error -string(6) "aArray" \ No newline at end of file diff --git a/Zend/tests/constants/gh18463-class-constant.phpt b/Zend/tests/constants/gh18463-class-constant.phpt index 2af977205dc8..40b96e8f7231 100644 --- a/Zend/tests/constants/gh18463-class-constant.phpt +++ b/Zend/tests/constants/gh18463-class-constant.phpt @@ -15,6 +15,7 @@ set_error_handler('handler'); var_dump(_ZendTestClass::ZEND_TEST_DEPRECATED); ?> --EXPECTF-- +int(42) Constant _ZendTestClass::ZEND_TEST_DEPRECATED is deprecated in %s on line %d Fatal error: Cannot use "string" as a class name as it is reserved in %s(%d) : eval()'d code on line %d diff --git a/Zend/tests/debug_info/recursion_return_null.phpt b/Zend/tests/debug_info/recursion_return_null.phpt index b6ca9c824cb7..9fb525923d7f 100644 --- a/Zend/tests/debug_info/recursion_return_null.phpt +++ b/Zend/tests/debug_info/recursion_return_null.phpt @@ -22,10 +22,10 @@ var_dump($f); ?> --EXPECTF-- +object(Foo)#%d (0) { +} in handler Deprecated: Returning null from Foo::__debugInfo() is deprecated, return an empty array instead in %s on line %d object(Foo)#3 (0) { } -object(Foo)#2 (0) { -} diff --git a/Zend/tests/delayed_error_001.phpt b/Zend/tests/delayed_error_001.phpt new file mode 100644 index 000000000000..668eb0da68f1 --- /dev/null +++ b/Zend/tests/delayed_error_001.phpt @@ -0,0 +1,43 @@ +--TEST-- +Delayed error 001 +--INI-- +opcache.jit=0 +--FILE-- + +--EXPECTF-- +Warning: Undefined variable $array in %s on line %d + +Warning: Undefined array key 0 in %s on line %d + +Warning: Undefined array key 1 in %s on line %d + +Warning: Undefined array key 2 in %s on line %d + +Warning: Undefined array key 3 in %s on line %d + +Warning: Undefined array key 3 in %s on line %d + +Warning: Undefined array key 4 in %s on line %d + +Warning: Decrement on type null has no effect, this will change in the next major version of PHP in %s on line %d + +Warning: Undefined array key 5 in %s on line %d + +Warning: Undefined array key 6 in %s on line %d + +Warning: Undefined array key 7 in %s on line %d + +Warning: Undefined array key 8 in %s on line %d + +Warning: Decrement on type null has no effect, this will change in the next major version of PHP in %s on line %d + +Warning: Undefined array key 9 in %s on line %d + +Warning: Undefined array key 10 in %s on line %d diff --git a/Zend/tests/delayed_error_004.phpt b/Zend/tests/delayed_error_004.phpt new file mode 100644 index 000000000000..9f498a099a13 --- /dev/null +++ b/Zend/tests/delayed_error_004.phpt @@ -0,0 +1,23 @@ +--TEST-- +Delayed errors: The first error promoted to exception takes precedence +--FILE-- +getMessage()); +} + +?> +--EXPECT-- +ErrorException: Warning: Return type of C::getTimezone() should either be compatible with DateTime::getTimezone(): DateTimeZone|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice diff --git a/Zend/tests/dynamic_prop_deprecation_002.phpt b/Zend/tests/dynamic_prop_deprecation_002.phpt index bd0d3aa5a7df..20182d2a8923 100644 --- a/Zend/tests/dynamic_prop_deprecation_002.phpt +++ b/Zend/tests/dynamic_prop_deprecation_002.phpt @@ -15,4 +15,3 @@ try { ?> --EXPECT-- Err: Creation of dynamic property class@anonymous::$y is deprecated -Exception: Cannot create dynamic property class@anonymous::$y diff --git a/Zend/tests/ex_func_null_during_property_write.phpt b/Zend/tests/ex_func_null_during_property_write.phpt index 6a253f760e0b..125ab4c411e8 100644 --- a/Zend/tests/ex_func_null_during_property_write.phpt +++ b/Zend/tests/ex_func_null_during_property_write.phpt @@ -13,13 +13,8 @@ class a { new a; ?> --EXPECTF-- -Fatal error: Uncaught Error: Object of class a could not be converted to string in %s:%d +Fatal error: Uncaught Exception in %s:%d Stack trace: -#0 %s(%d): a->__destruct() -#1 {main} - -Next Exception in %s:%d -Stack trace: -#0 %s(%d): a->__destruct() +#0 [internal function]: a->__destruct() #1 {main} thrown in %s on line %d diff --git a/Zend/tests/exception_in_nested_rope.phpt b/Zend/tests/exception_in_nested_rope.phpt index 7afd1412354a..9ebe82e1eafd 100644 --- a/Zend/tests/exception_in_nested_rope.phpt +++ b/Zend/tests/exception_in_nested_rope.phpt @@ -3,7 +3,7 @@ Exception during nested rope --FILE-- bar(); --EXPECTF-- Fatal error: Uncaught RuntimeException in %sbug45805.php:%d Stack trace: -#0 %sbug45805.php(%d): PHPUnit_Util_ErrorHandler::handleError(8, 'Only variables ...', '%s', %d) -#1 [internal function]: B->foo() -#2 %sbug45805.php(%d): ReflectionMethod->invoke(Object(B)) -#3 %sbug45805.php(%d): B->bar() -#4 {main} +#0 [internal function]: PHPUnit_Util_ErrorHandler::handleError(8, 'Only variables ...', '/home/arnaud/de...', 19) +#1 %s(%d): ReflectionMethod->invoke(Object(B)) +#2 %s(%d): B->bar() +#3 {main} thrown in %sbug45805.php on line %d diff --git a/Zend/tests/exceptions/bug51394.phpt b/Zend/tests/exceptions/bug51394.phpt index 629ebec622b2..09ad1c398af1 100644 --- a/Zend/tests/exceptions/bug51394.phpt +++ b/Zend/tests/exceptions/bug51394.phpt @@ -10,7 +10,7 @@ function eh() return false; } -set_error_handler("eh"); +set_error_handler("eh", delay: false); $a = $empty($b); ?> --EXPECTF-- diff --git a/Zend/tests/exceptions/bug53511.phpt b/Zend/tests/exceptions/bug53511.phpt index b07504506a94..33430c31569c 100644 --- a/Zend/tests/exceptions/bug53511.phpt +++ b/Zend/tests/exceptions/bug53511.phpt @@ -1,5 +1,7 @@ --TEST-- Bug #53511 (Exceptions are lost in case an exception is thrown in catch operator) +--XFAIL-- +FIXME --FILE-- --EXPECTF-- diff --git a/Zend/tests/exceptions/bug78239.phpt b/Zend/tests/exceptions/bug78239.phpt index afc7176800e1..24f70807fb78 100644 --- a/Zend/tests/exceptions/bug78239.phpt +++ b/Zend/tests/exceptions/bug78239.phpt @@ -9,7 +9,7 @@ function handleError($level, $message, $file = '', $line = 0, $context = []) throw new ErrorException($message, 0, $level, $file, $line); } -set_error_handler('handleError'); +set_error_handler('handleError', delay: false); $r = new _ZendTestClass; (string)$r ?: ""; diff --git a/Zend/tests/exceptions/exception_008.phpt b/Zend/tests/exceptions/exception_008.phpt index 4640ec965ad5..11058b7127d4 100644 --- a/Zend/tests/exceptions/exception_008.phpt +++ b/Zend/tests/exceptions/exception_008.phpt @@ -20,6 +20,7 @@ class TestSecond $ar = array(new TestFirst, new TestSecond); unset($ar); +(function () {})(); ?> ===DONE=== diff --git a/Zend/tests/exceptions/exception_026.phpt b/Zend/tests/exceptions/exception_026.phpt index 0c47a449a4bf..cbcc913153c2 100644 --- a/Zend/tests/exceptions/exception_026.phpt +++ b/Zend/tests/exceptions/exception_026.phpt @@ -6,21 +6,16 @@ class A { static $max=0; function __destruct() { if (self::$max--<0) - X; + X; $a = new A; - Y; + Y; } } new A; ?> --EXPECTF-- -Fatal error: Uncaught Error: Undefined constant "Y" in %s:8 +Fatal error: Uncaught Error: Undefined constant "X" in %s:%d Stack trace: -#0 %s(11): A->__destruct() -#1 {main} - -Next Error: Undefined constant "X" in %s:6 -Stack trace: -#0 %s(11): A->__destruct() +#0 [internal function]: A->__destruct() #1 {main} thrown in %s on line 6 diff --git a/Zend/tests/exceptions/exception_before_fatal.phpt b/Zend/tests/exceptions/exception_before_fatal.phpt index edc63b2394cd..7dc71bbdce87 100644 --- a/Zend/tests/exceptions/exception_before_fatal.phpt +++ b/Zend/tests/exceptions/exception_before_fatal.phpt @@ -6,7 +6,7 @@ function exception_error_handler($code, $msg) { throw new Exception($msg); } -set_error_handler("exception_error_handler"); +set_error_handler("exception_error_handler", delay: false); try { $foo->a(); diff --git a/Zend/tests/falsetoarray_002.phpt b/Zend/tests/falsetoarray_002.phpt index c01b79954596..639cd51b3661 100644 --- a/Zend/tests/falsetoarray_002.phpt +++ b/Zend/tests/falsetoarray_002.phpt @@ -11,5 +11,13 @@ $a[0][$d]='b'; var_dump($a); ?> --EXPECT-- +array(1) { + [0]=> + array(1) { + [""]=> + string(1) "b" + } +} Err: Automatic conversion of false to array is deprecated -string(0) "" +Err: Undefined variable $d +Err: Using null as an array offset is deprecated, use an empty string instead diff --git a/Zend/tests/falsetoarray_003.phpt b/Zend/tests/falsetoarray_003.phpt index 117e443ef958..d62dff41941c 100644 --- a/Zend/tests/falsetoarray_003.phpt +++ b/Zend/tests/falsetoarray_003.phpt @@ -11,6 +11,6 @@ $a=[]; ?> DONE --EXPECTF-- +DONE Err: The float %f is not representable as an int, cast occurred Err: Undefined array key %i -DONE diff --git a/Zend/tests/fe_fetch_dtor_exception.phpt b/Zend/tests/fe_fetch_dtor_exception.phpt index 99378e739a8b..e014d72ec224 100644 --- a/Zend/tests/fe_fetch_dtor_exception.phpt +++ b/Zend/tests/fe_fetch_dtor_exception.phpt @@ -19,4 +19,5 @@ try { ?> --EXPECT-- +int(1) foo diff --git a/Zend/tests/fibers/gh9735-008.phpt b/Zend/tests/fibers/gh9735-008.phpt index ec6f29fb79de..a2b39558d59c 100644 --- a/Zend/tests/fibers/gh9735-008.phpt +++ b/Zend/tests/fibers/gh9735-008.phpt @@ -30,6 +30,7 @@ gc_collect_cycles(); print "2\n"; $fiber = null; +(function () {})(); gc_collect_cycles(); print "3\n"; diff --git a/Zend/tests/fibers/throw-in-multiple-destroyed-fibers-after-shutdown.phpt b/Zend/tests/fibers/throw-in-multiple-destroyed-fibers-after-shutdown.phpt index f2f09911fbb1..15c8dbf98f99 100644 --- a/Zend/tests/fibers/throw-in-multiple-destroyed-fibers-after-shutdown.phpt +++ b/Zend/tests/fibers/throw-in-multiple-destroyed-fibers-after-shutdown.phpt @@ -35,12 +35,12 @@ echo "done\n"; --EXPECTF-- done -Fatal error: Uncaught Exception: test1 in %sthrow-in-multiple-destroyed-fibers-after-shutdown.php:%d +Fatal error: Uncaught Exception: test1 in %s:%d Stack trace: #0 [internal function]: {closure:%s:%d}() #1 {main} -Next Exception: test2 in %sthrow-in-multiple-destroyed-fibers-after-shutdown.php:%d +Next Exception: test2 in %s:%d Stack trace: #0 [internal function]: {closure:%s:%d}() #1 {main} diff --git a/Zend/tests/fibers/unfinished-fiber-with-finally.phpt b/Zend/tests/fibers/unfinished-fiber-with-finally.phpt index 84ba74e646c6..8948a8a6a8d4 100644 --- a/Zend/tests/fibers/unfinished-fiber-with-finally.phpt +++ b/Zend/tests/fibers/unfinished-fiber-with-finally.phpt @@ -20,6 +20,7 @@ $fiber = new Fiber(function (): void { $fiber->start(); unset($fiber); // Destroy fiber object, executing finally block. +(function () {})(); echo "done\n"; diff --git a/Zend/tests/fibers/unfinished-fiber-with-nested-try-catch.phpt b/Zend/tests/fibers/unfinished-fiber-with-nested-try-catch.phpt index 664e4a052b8f..2d62ba0419ea 100644 --- a/Zend/tests/fibers/unfinished-fiber-with-nested-try-catch.phpt +++ b/Zend/tests/fibers/unfinished-fiber-with-nested-try-catch.phpt @@ -36,6 +36,7 @@ $fiber = new Fiber(function (): void { $fiber->start(); unset($fiber); // Destroy fiber object, executing finally block. +(function () {})(); echo "done\n"; diff --git a/Zend/tests/fibers/unfinished-fiber-with-suspend-in-finally.phpt b/Zend/tests/fibers/unfinished-fiber-with-suspend-in-finally.phpt index e38774df82bf..39a0b569cdb9 100644 --- a/Zend/tests/fibers/unfinished-fiber-with-suspend-in-finally.phpt +++ b/Zend/tests/fibers/unfinished-fiber-with-suspend-in-finally.phpt @@ -25,6 +25,7 @@ $fiber = new Fiber(function (): object { $fiber->start(); unset($fiber); // Destroy fiber object, executing finally block. +(function () {})(); echo "done\n"; diff --git a/Zend/tests/fibers/unfinished-fiber-with-throw-in-finally.phpt b/Zend/tests/fibers/unfinished-fiber-with-throw-in-finally.phpt index f1b17caeb5d7..202a079ba9fe 100644 --- a/Zend/tests/fibers/unfinished-fiber-with-throw-in-finally.phpt +++ b/Zend/tests/fibers/unfinished-fiber-with-throw-in-finally.phpt @@ -35,6 +35,7 @@ $fiber = new Fiber(function (): void { $fiber->start(); unset($fiber); // Destroy fiber object, executing finally block. +(function () {})(); echo "done\n"; diff --git a/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_002.phpt b/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_002.phpt index 97831a8d65f0..37dc81052723 100644 --- a/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_002.phpt +++ b/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_002.phpt @@ -5,7 +5,7 @@ FCC in initializer emits deprecation for static reference to trait method (Excep set_error_handler(function (int $errno, string $errstr, ?string $errfile = null, ?int $errline = null) { throw new \ErrorException($errstr, 0, $errno, $errfile, $errline); -}); +}, delay: false); trait Foo { public static function myMethod(string $foo) { @@ -16,7 +16,7 @@ trait Foo { function foo(Closure $c = Foo::myMethod(...)) { var_dump($c); - $c("abc"); + $c("abc"); } try { diff --git a/Zend/tests/frameless_throwing_destructor.phpt b/Zend/tests/frameless_throwing_destructor.phpt index ad555d860e66..28bb6caf4ba4 100644 --- a/Zend/tests/frameless_throwing_destructor.phpt +++ b/Zend/tests/frameless_throwing_destructor.phpt @@ -13,6 +13,6 @@ in_array(new Foo(), [new Bar()], true); --EXPECTF-- Fatal error: Uncaught Exception in %s:%d Stack trace: -#0 %s(%d): Bar->__destruct() +#0 [internal function]: Bar->__destruct() #1 {main} thrown in %s on line %d diff --git a/Zend/tests/frameless_undefined_var.phpt b/Zend/tests/frameless_undefined_var.phpt index e9c5aac58236..027b1c414134 100644 --- a/Zend/tests/frameless_undefined_var.phpt +++ b/Zend/tests/frameless_undefined_var.phpt @@ -4,7 +4,7 @@ Undefined var in frameless call getValue()->getId()); echo "Before unset", PHP_EOL; unset($v); +(function () {})(); echo "After unset", PHP_EOL; diff --git a/Zend/tests/functions/zend_call_function_deprecated_frame.phpt b/Zend/tests/functions/zend_call_function_deprecated_frame.phpt index 83d05144c0bd..44834c8a9d80 100644 --- a/Zend/tests/functions/zend_call_function_deprecated_frame.phpt +++ b/Zend/tests/functions/zend_call_function_deprecated_frame.phpt @@ -10,7 +10,7 @@ function foo(string $v) { set_error_handler(function ($number, $message) { throw new Exception($message); -}); +}, delay: false); $a = array_map(foo(...), ['Hello', 'World']); var_dump($a); diff --git a/Zend/tests/gc/bug64960.phpt b/Zend/tests/gc/bug64960.phpt index d3dcc4da8c5e..171293d0b564 100644 --- a/Zend/tests/gc/bug64960.phpt +++ b/Zend/tests/gc/bug64960.phpt @@ -23,7 +23,7 @@ set_error_handler(function() $e->_trace = debug_backtrace(); throw $e; -}); +}, delay: false); // trigger error handler $a['waa']; @@ -37,8 +37,7 @@ Deprecated: Creation of dynamic property Exception::$_trace is deprecated in %s Fatal error: Uncaught Exception in %sbug64960.php:19 Stack trace: -#0 [internal function]: {closure:%s:%d}(8, 'ob_end_clean():...', '%s', 9) -#1 %sbug64960.php(9): ob_end_clean() -#2 [internal function]: ExceptionHandler->__invoke(Object(Exception)) -#3 {main} +#0 %s(%d): {closure:%s:%d}(8, 'ob_end_clean():...', '/home/arnaud/de...', 9) +#1 [internal function]: ExceptionHandler->__invoke(Object(Exception)) +#2 {main} thrown in %sbug64960.php on line 19 diff --git a/Zend/tests/gc_053.phpt b/Zend/tests/gc_053.phpt index 858be7cbebd5..c9035f2527bf 100644 --- a/Zend/tests/gc_053.phpt +++ b/Zend/tests/gc_053.phpt @@ -22,6 +22,7 @@ $o = new WithDestructor(); $weakO = \WeakReference::create($o); echo "---\n"; unset($o); +(function () {})(); echo "---\n"; var_dump($weakO->get() !== null); // verify if kept allocated G::$v = null; diff --git a/Zend/tests/generators/bug71601.phpt b/Zend/tests/generators/bug71601.phpt index c8e226329dfe..3d4a11be63cc 100644 --- a/Zend/tests/generators/bug71601.phpt +++ b/Zend/tests/generators/bug71601.phpt @@ -27,6 +27,7 @@ $generator = gen2(); var_dump($generator->current()); unset($generator); +(function() {})(); echo "Done\n"; diff --git a/Zend/tests/generators/errors/yield_in_force_closed_finally_error.phpt b/Zend/tests/generators/errors/yield_in_force_closed_finally_error.phpt index af84e50215ce..894a4d7e8e4b 100644 --- a/Zend/tests/generators/errors/yield_in_force_closed_finally_error.phpt +++ b/Zend/tests/generators/errors/yield_in_force_closed_finally_error.phpt @@ -28,6 +28,6 @@ before yield in finally Fatal error: Uncaught Error: Cannot yield from finally in a force-closed generator in %s:%d Stack trace: -#0 %s(%d): gen() +#0 [internal function]: gen() #1 {main} thrown in %s on line %d diff --git a/Zend/tests/generators/generator_closure_collection.phpt b/Zend/tests/generators/generator_closure_collection.phpt index 7386adeb80c5..34c8552df60c 100644 --- a/Zend/tests/generators/generator_closure_collection.phpt +++ b/Zend/tests/generators/generator_closure_collection.phpt @@ -12,6 +12,7 @@ $genFactory = function() { $r = WeakReference::create($genFactory); $generator = $genFactory(); unset($genFactory); +(function () {})(); var_dump($r->get()); @@ -20,6 +21,7 @@ foreach ($generator as $value) var_dump($value); var_dump($r->get()); unset($generator); +(function () {})(); var_dump($r->get()); diff --git a/Zend/tests/generators/gh9750-001.phpt b/Zend/tests/generators/gh9750-001.phpt index 9a64912c2525..a958f36de53e 100644 --- a/Zend/tests/generators/gh9750-001.phpt +++ b/Zend/tests/generators/gh9750-001.phpt @@ -23,6 +23,7 @@ foreach ($gen as $value) { } $gen = null; +(function () {})(); gc_collect_cycles(); diff --git a/Zend/tests/generators/gh9750-002.phpt b/Zend/tests/generators/gh9750-002.phpt index f46bd381283e..4594782dcbe5 100644 --- a/Zend/tests/generators/gh9750-002.phpt +++ b/Zend/tests/generators/gh9750-002.phpt @@ -23,6 +23,7 @@ foreach ($gen as $value) { } $gen = null; +(function () {})(); gc_collect_cycles(); diff --git a/Zend/tests/generators/gh9750-003.phpt b/Zend/tests/generators/gh9750-003.phpt index f58abb243312..82e2cf90ee00 100644 --- a/Zend/tests/generators/gh9750-003.phpt +++ b/Zend/tests/generators/gh9750-003.phpt @@ -23,6 +23,7 @@ foreach ($gen as $value) { } $gen = null; +(function () {})(); gc_collect_cycles(); diff --git a/Zend/tests/generators/gh9750-004.phpt b/Zend/tests/generators/gh9750-004.phpt index ad26a9029e4b..555819d8eb48 100644 --- a/Zend/tests/generators/gh9750-004.phpt +++ b/Zend/tests/generators/gh9750-004.phpt @@ -23,6 +23,7 @@ foreach ($gen as $value) { } $gen = null; +(function () {})(); gc_collect_cycles(); diff --git a/Zend/tests/generators/gh9750-005.phpt b/Zend/tests/generators/gh9750-005.phpt index 1e849946917a..31942fc71270 100644 --- a/Zend/tests/generators/gh9750-005.phpt +++ b/Zend/tests/generators/gh9750-005.phpt @@ -24,6 +24,7 @@ foreach ($gen as $value) { $gen = null; $c = null; +(function () {})(); gc_collect_cycles(); diff --git a/Zend/tests/generators/gh9750-006.phpt b/Zend/tests/generators/gh9750-006.phpt index 6ba6c416d4af..23a37577a91b 100644 --- a/Zend/tests/generators/gh9750-006.phpt +++ b/Zend/tests/generators/gh9750-006.phpt @@ -23,6 +23,7 @@ foreach ($gen as $value) { } $gen = null; +(function () {})(); gc_collect_cycles(); diff --git a/Zend/tests/generators/gh9750-007.phpt b/Zend/tests/generators/gh9750-007.phpt index dbf91752ef5a..a62cfebab582 100644 --- a/Zend/tests/generators/gh9750-007.phpt +++ b/Zend/tests/generators/gh9750-007.phpt @@ -29,5 +29,5 @@ gc_collect_cycles(); ?> ==DONE== --EXPECT-- -C::__destruct ==DONE== +C::__destruct diff --git a/Zend/tests/generators/gh9750-008.phpt b/Zend/tests/generators/gh9750-008.phpt index a9cdacd19d15..63f05b3cb1fd 100644 --- a/Zend/tests/generators/gh9750-008.phpt +++ b/Zend/tests/generators/gh9750-008.phpt @@ -36,5 +36,5 @@ gc_collect_cycles(); ?> ==DONE== --EXPECT-- -C::__destruct ==DONE== +C::__destruct diff --git a/Zend/tests/generators/gh9750-009.phpt b/Zend/tests/generators/gh9750-009.phpt index 561ed081e379..82f5bcb6a870 100644 --- a/Zend/tests/generators/gh9750-009.phpt +++ b/Zend/tests/generators/gh9750-009.phpt @@ -33,5 +33,5 @@ gc_collect_cycles(); ?> ==DONE== --EXPECT-- -C::__destruct ==DONE== +C::__destruct diff --git a/Zend/tests/generators/gh9750-010.phpt b/Zend/tests/generators/gh9750-010.phpt index ab5b6bf6d48c..4e1d2039f06c 100644 --- a/Zend/tests/generators/gh9750-010.phpt +++ b/Zend/tests/generators/gh9750-010.phpt @@ -29,5 +29,5 @@ gc_collect_cycles(); ?> ==DONE== --EXPECT-- -C::__destruct ==DONE== +C::__destruct diff --git a/Zend/tests/generators/gh9750-011.phpt b/Zend/tests/generators/gh9750-011.phpt index ab4c00a17358..cec207b97ec0 100644 --- a/Zend/tests/generators/gh9750-011.phpt +++ b/Zend/tests/generators/gh9750-011.phpt @@ -34,5 +34,5 @@ gc_collect_cycles(); ?> ==DONE== --EXPECT-- -C::__destruct ==DONE== +C::__destruct diff --git a/Zend/tests/generators/yield_from_force_closed.phpt b/Zend/tests/generators/yield_from_force_closed.phpt index 87fcd2e8ed93..fa5cc183ca06 100644 --- a/Zend/tests/generators/yield_from_force_closed.phpt +++ b/Zend/tests/generators/yield_from_force_closed.phpt @@ -22,6 +22,7 @@ try { $gen = gen2(); $gen->rewind(); unset($gen); + (function () {})(); } catch (Error $e) { echo $e, "\n"; } diff --git a/Zend/tests/get_class_basic.phpt b/Zend/tests/get_class_basic.phpt index f6dcbccb6916..43dec0e592f6 100644 --- a/Zend/tests/get_class_basic.phpt +++ b/Zend/tests/get_class_basic.phpt @@ -25,7 +25,7 @@ $f2 = new foo2; set_error_handler(function ($severity, $message, $file, $line) { throw new Exception($message); -}); +}, delay: false); try { $f1->bar(); } catch (Exception $e) { diff --git a/Zend/tests/gh10168/assign_prop_ref.phpt b/Zend/tests/gh10168/assign_prop_ref.phpt index 606542fbd6c6..e8efb1d7051a 100644 --- a/Zend/tests/gh10168/assign_prop_ref.phpt +++ b/Zend/tests/gh10168/assign_prop_ref.phpt @@ -26,7 +26,8 @@ test($box); test($box); ?> ---EXPECT-- -NULL -object(Test)#2 (0) { +--EXPECTF-- +object(Test)#%d (0) { +} +object(Test)#%d (0) { } diff --git a/Zend/tests/gh10168/assign_prop_ref_with_prop_ref.phpt b/Zend/tests/gh10168/assign_prop_ref_with_prop_ref.phpt index f887acbc1d06..62ff10c2b876 100644 --- a/Zend/tests/gh10168/assign_prop_ref_with_prop_ref.phpt +++ b/Zend/tests/gh10168/assign_prop_ref_with_prop_ref.phpt @@ -29,7 +29,8 @@ test($box); test($box); ?> ---EXPECT-- -object(Test)#3 (0) { +--EXPECTF-- +object(Test)#%d (0) { +} +object(Test)#%d (0) { } -NULL diff --git a/Zend/tests/gh10168/assign_ref.phpt b/Zend/tests/gh10168/assign_ref.phpt index 9f3be5619d1a..b6348e21e4ca 100644 --- a/Zend/tests/gh10168/assign_ref.phpt +++ b/Zend/tests/gh10168/assign_ref.phpt @@ -12,7 +12,9 @@ class Test { $a = new Test; $tmp = new Test; var_dump($a = &$tmp); +(function () {})(); ?> ---EXPECT-- -NULL +--EXPECTF-- +object(Test)#%d (0) { +} diff --git a/Zend/tests/gh10168/assign_ref_with_prop_ref.phpt b/Zend/tests/gh10168/assign_ref_with_prop_ref.phpt index 42ce94b3f83e..2bade8437744 100644 --- a/Zend/tests/gh10168/assign_ref_with_prop_ref.phpt +++ b/Zend/tests/gh10168/assign_ref_with_prop_ref.phpt @@ -16,5 +16,6 @@ $tmp = new Test; var_dump($a = &$tmp); ?> ---EXPECT-- -NULL +--EXPECTF-- +object(Test)#%d (0) { +} diff --git a/Zend/tests/gh10168/assign_static_prop_ref.phpt b/Zend/tests/gh10168/assign_static_prop_ref.phpt index 2e90be884ded..c05ac00ebdb8 100644 --- a/Zend/tests/gh10168/assign_static_prop_ref.phpt +++ b/Zend/tests/gh10168/assign_static_prop_ref.phpt @@ -16,5 +16,6 @@ $tmp = new Test; var_dump(Test::$test = &$tmp); ?> ---EXPECT-- -NULL +--EXPECTF-- +object(Test)#%d (0) { +} diff --git a/Zend/tests/gh10168/assign_static_untyped_prop_ref.phpt b/Zend/tests/gh10168/assign_static_untyped_prop_ref.phpt index dfef8ead26f6..0592cf9de5aa 100644 --- a/Zend/tests/gh10168/assign_static_untyped_prop_ref.phpt +++ b/Zend/tests/gh10168/assign_static_untyped_prop_ref.phpt @@ -16,5 +16,6 @@ $tmp = new Test; var_dump(Test::$test = &$tmp); ?> ---EXPECT-- -NULL +--EXPECTF-- +object(Test)#%d (0) { +} diff --git a/Zend/tests/gh10168/assign_untyped_prop_ref.phpt b/Zend/tests/gh10168/assign_untyped_prop_ref.phpt index a28395d43bbb..81e2f306b3e1 100644 --- a/Zend/tests/gh10168/assign_untyped_prop_ref.phpt +++ b/Zend/tests/gh10168/assign_untyped_prop_ref.phpt @@ -26,7 +26,8 @@ test($box); test($box); ?> ---EXPECT-- -NULL -object(Test)#2 (0) { +--EXPECTF-- +object(Test)#%d (0) { +} +object(Test)#%d (0) { } diff --git a/Zend/tests/gh10168/assign_untyped_prop_ref_with_prop_ref.phpt b/Zend/tests/gh10168/assign_untyped_prop_ref_with_prop_ref.phpt index 79ff5fefc07e..de4d855b006f 100644 --- a/Zend/tests/gh10168/assign_untyped_prop_ref_with_prop_ref.phpt +++ b/Zend/tests/gh10168/assign_untyped_prop_ref_with_prop_ref.phpt @@ -29,7 +29,8 @@ test($box); test($box); ?> ---EXPECT-- -object(Test)#3 (0) { +--EXPECTF-- +object(Test)#%d (0) { +} +object(Test)#%d (0) { } -NULL diff --git a/Zend/tests/gh16799.phpt b/Zend/tests/gh16799.phpt index d31d1a5705c6..ef2e20c1260a 100644 --- a/Zend/tests/gh16799.phpt +++ b/Zend/tests/gh16799.phpt @@ -2,7 +2,7 @@ GH-16799 (Assertion failure at Zend/zend_vm_execute.h) --FILE-- getMessage(), "\n"; } ?> ---EXPECT-- -Attempt to assign property "value" on null +--EXPECTF-- +Warning: getimagesize(dummy): Failed to open stream: No such file or directory in %s on line %d +Attempt to assign property "value" on array diff --git a/Zend/tests/gh20183_001.phpt b/Zend/tests/gh20183_001.phpt index 9468bcaea567..12423ede91ac 100644 --- a/Zend/tests/gh20183_001.phpt +++ b/Zend/tests/gh20183_001.phpt @@ -16,7 +16,7 @@ B::$b = new A; ?> --EXPECTF-- -#0 %s(10): A->__destruct() +#0 %s(%d): A->__destruct() Fatal error: Uncaught Error: Class "B" not found in %s:10 Stack trace: diff --git a/Zend/tests/gh20183_002.phpt b/Zend/tests/gh20183_002.phpt index ec4d62d0960d..97e58da5e79c 100644 --- a/Zend/tests/gh20183_002.phpt +++ b/Zend/tests/gh20183_002.phpt @@ -26,7 +26,7 @@ B::$a = new A(); ?> --EXPECTF-- -#0 %s(20): gen() +#0 %s(%d): gen() Fatal error: Uncaught Error: Class "B" not found in %s:20 Stack trace: diff --git a/Zend/tests/gh_21699.phpt b/Zend/tests/gh_21699.phpt index 49b58365dabf..197e6c23c6ba 100644 --- a/Zend/tests/gh_21699.phpt +++ b/Zend/tests/gh_21699.phpt @@ -2,9 +2,9 @@ GH-21699: Assertion failure in shutdown_executor when error handler throws during self:: callable resolution --FILE-- test(); ?> --EXPECTF-- -Fatal error: Uncaught Exception in %s:%d +Fatal error: Uncaught Exception: Use of "self" in callables is deprecated in %s:%d Stack trace: #0 %s(%d): {closure:%s}(%d, 'Use of "self" i%s', '%s', %d) #1 %s(%d): bar->test() #2 {main} - -Next TypeError: call_user_func(): Argument #1 ($callback) must be a valid callback, (null) in %s:%d -Stack trace: -#0 %s(%d): bar->test() -#1 {main} thrown in %s on line %d diff --git a/Zend/tests/gh_21699_parent.phpt b/Zend/tests/gh_21699_parent.phpt index 73cae41f3f5b..75535f349cc7 100644 --- a/Zend/tests/gh_21699_parent.phpt +++ b/Zend/tests/gh_21699_parent.phpt @@ -2,9 +2,9 @@ GH-21699 (parent::): no shutdown_executor trampoline assertion when error handler throws during parent:: callable resolution --FILE-- test(); ?> --EXPECTF-- -Fatal error: Uncaught Exception in %s:%d +Fatal error: Uncaught Exception: Use of "parent" in callables is deprecated in %s:%d Stack trace: #0 %s(%d): {closure:%s}(%d, 'Use of "parent"%s', '%s', %d) #1 %s(%d): Child->test() #2 {main} - -Next TypeError: call_user_func(): Argument #1 ($callback) must be a valid callback, (null) in %s:%d -Stack trace: -#0 %s(%d): Child->test() -#1 {main} thrown in %s on line %d diff --git a/Zend/tests/gh_21699_static.phpt b/Zend/tests/gh_21699_static.phpt index 4d9604ebe77b..fb5e34fdd83b 100644 --- a/Zend/tests/gh_21699_static.phpt +++ b/Zend/tests/gh_21699_static.phpt @@ -2,9 +2,9 @@ GH-21699 (static::): no shutdown_executor trampoline assertion when error handler throws during static:: callable resolution --FILE-- test(); ?> --EXPECTF-- -Fatal error: Uncaught Exception in %s:%d +Fatal error: Uncaught Exception: Use of "static" in callables is deprecated in %s:%d Stack trace: #0 %s(%d): {closure:%s}(%d, 'Use of "static"%s', '%s', %d) #1 %s(%d): bar->test() #2 {main} - -Next TypeError: call_user_func(): Argument #1 ($callback) must be a valid callback, (null) in %s:%d -Stack trace: -#0 %s(%d): bar->test() -#1 {main} thrown in %s on line %d diff --git a/Zend/tests/in-de-crement/incdec_bool_exception.phpt b/Zend/tests/in-de-crement/incdec_bool_exception.phpt index f819af1e2395..2e07f904169d 100644 --- a/Zend/tests/in-de-crement/incdec_bool_exception.phpt +++ b/Zend/tests/in-de-crement/incdec_bool_exception.phpt @@ -5,7 +5,7 @@ Inc/dec on bool: warning converted to exception set_error_handler(function($severity, $m) { throw new Exception($m, $severity); -}); +}, delay: false); $values = [false, true]; foreach ($values as $value) { diff --git a/Zend/tests/in-de-crement/incdec_strings_exception.phpt b/Zend/tests/in-de-crement/incdec_strings_exception.phpt index 5acbb1041222..e374f49a3408 100644 --- a/Zend/tests/in-de-crement/incdec_strings_exception.phpt +++ b/Zend/tests/in-de-crement/incdec_strings_exception.phpt @@ -11,7 +11,7 @@ set_error_handler(function($severity, $m) { $m = 'Warning: ' . $m; } throw new Exception($m, $severity); -}); +}, delay: false); $values = [ '', diff --git a/Zend/tests/in-de-crement/incdec_undef.phpt b/Zend/tests/in-de-crement/incdec_undef.phpt index db560e31c99f..549c64fea87e 100644 --- a/Zend/tests/in-de-crement/incdec_undef.phpt +++ b/Zend/tests/in-de-crement/incdec_undef.phpt @@ -14,6 +14,7 @@ unset($x); var_dump(++$x); ?> --EXPECT-- +NULL Undefined variable $x Decrement on type null has no effect, this will change in the next major version of PHP NULL @@ -21,6 +22,5 @@ Undefined variable $x NULL Undefined variable $x Decrement on type null has no effect, this will change in the next major version of PHP -NULL -Undefined variable $x int(1) +Undefined variable $x diff --git a/Zend/tests/in-de-crement/increment_diagnostic_change_type.phpt b/Zend/tests/in-de-crement/increment_diagnostic_change_type.phpt index 11a0edac1917..b55c8c6b811e 100644 --- a/Zend/tests/in-de-crement/increment_diagnostic_change_type.phpt +++ b/Zend/tests/in-de-crement/increment_diagnostic_change_type.phpt @@ -31,8 +31,8 @@ var_dump($x); DONE --EXPECT-- string(1) "1" -string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" string(4) "foo!" string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" string(1) "!" +string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" DONE diff --git a/Zend/tests/in-de-crement/oss-fuzz-60709_globals_unset_after_undef_warning.phpt b/Zend/tests/in-de-crement/oss-fuzz-60709_globals_unset_after_undef_warning.phpt index e981800eeac1..1f1fc7228134 100644 --- a/Zend/tests/in-de-crement/oss-fuzz-60709_globals_unset_after_undef_warning.phpt +++ b/Zend/tests/in-de-crement/oss-fuzz-60709_globals_unset_after_undef_warning.phpt @@ -21,16 +21,16 @@ var_dump(++$x); ?> --EXPECT-- POST DEC +NULL Undefined variable $x Decrement on type null has no effect, this will change in the next major version of PHP -NULL POST INC -Undefined variable $x NULL +Undefined variable $x PRE DEC +NULL Undefined variable $x Decrement on type null has no effect, this will change in the next major version of PHP -NULL PRE INC -Undefined variable $x int(1) +Undefined variable $x diff --git a/Zend/tests/in-de-crement/oss-fuzz-62294_globals_unset_after_string_warning.phpt b/Zend/tests/in-de-crement/oss-fuzz-62294_globals_unset_after_string_warning.phpt index f52dff52e631..e39184e68154 100644 --- a/Zend/tests/in-de-crement/oss-fuzz-62294_globals_unset_after_string_warning.phpt +++ b/Zend/tests/in-de-crement/oss-fuzz-62294_globals_unset_after_string_warning.phpt @@ -25,14 +25,14 @@ var_dump(++$x); ?> --EXPECT-- POST DEC -Decrement on non-numeric string has no effect and is deprecated string(1) " " -PRE DEC Decrement on non-numeric string has no effect and is deprecated +PRE DEC string(1) " " +Decrement on non-numeric string has no effect and is deprecated POST INC -Increment on non-numeric string is deprecated, use str_increment() instead string(1) " " -PRE INC Increment on non-numeric string is deprecated, use str_increment() instead +PRE INC string(1) " " +Increment on non-numeric string is deprecated, use str_increment() instead diff --git a/Zend/tests/in-de-crement/unset_globals_in_error_handler.phpt b/Zend/tests/in-de-crement/unset_globals_in_error_handler.phpt index 31ffea22467b..88302517ce05 100644 --- a/Zend/tests/in-de-crement/unset_globals_in_error_handler.phpt +++ b/Zend/tests/in-de-crement/unset_globals_in_error_handler.phpt @@ -78,53 +78,53 @@ unset($x); --EXPECT-- NULL (only --) POST DEC -Decrement on type null has no effect, this will change in the next major version of PHP NULL -PRE DEC Decrement on type null has no effect, this will change in the next major version of PHP +PRE DEC NULL +Decrement on type null has no effect, this will change in the next major version of PHP Empty string POST INC -Increment on non-numeric string is deprecated, use str_increment() instead string(0) "" +Increment on non-numeric string is deprecated, use str_increment() instead POST DEC -Decrement on empty string is deprecated as non-numeric string(0) "" +Decrement on empty string is deprecated as non-numeric PRE INC -Increment on non-numeric string is deprecated, use str_increment() instead string(1) "1" +Increment on non-numeric string is deprecated, use str_increment() instead PRE DEC -Decrement on empty string is deprecated as non-numeric int(-1) +Decrement on empty string is deprecated as non-numeric Non fill ASCII (only ++) POST INC -Increment on non-numeric string is deprecated, use str_increment() instead string(4) " ad " -PRE INC Increment on non-numeric string is deprecated, use str_increment() instead +PRE INC string(4) " ad " +Increment on non-numeric string is deprecated, use str_increment() instead Bool POST INC -Increment on type bool has no effect, this will change in the next major version of PHP bool(false) +Increment on type bool has no effect, this will change in the next major version of PHP POST DEC -Decrement on type bool has no effect, this will change in the next major version of PHP bool(false) +Decrement on type bool has no effect, this will change in the next major version of PHP PRE INC -Increment on type bool has no effect, this will change in the next major version of PHP bool(false) +Increment on type bool has no effect, this will change in the next major version of PHP PRE DEC -Decrement on type bool has no effect, this will change in the next major version of PHP bool(false) +Decrement on type bool has no effect, this will change in the next major version of PHP POST INC -Increment on type bool has no effect, this will change in the next major version of PHP bool(true) +Increment on type bool has no effect, this will change in the next major version of PHP POST DEC -Decrement on type bool has no effect, this will change in the next major version of PHP bool(true) +Decrement on type bool has no effect, this will change in the next major version of PHP PRE INC -Increment on type bool has no effect, this will change in the next major version of PHP bool(true) +Increment on type bool has no effect, this will change in the next major version of PHP PRE DEC -Decrement on type bool has no effect, this will change in the next major version of PHP bool(true) +Decrement on type bool has no effect, this will change in the next major version of PHP diff --git a/Zend/tests/in-de-crement/unset_object_property_in_error_handler.phpt b/Zend/tests/in-de-crement/unset_object_property_in_error_handler.phpt index 4d2a4705588a..b00ba707cecf 100644 --- a/Zend/tests/in-de-crement/unset_object_property_in_error_handler.phpt +++ b/Zend/tests/in-de-crement/unset_object_property_in_error_handler.phpt @@ -87,57 +87,57 @@ var_dump(--$c->a); unset($c->a); ?> --EXPECT-- -string(87) "Decrement on type null has no effect, this will change in the next major version of PHP" NULL +string(87) "Decrement on type null has no effect, this will change in the next major version of PHP" NULL (only --) POST DEC -string(87) "Decrement on type null has no effect, this will change in the next major version of PHP" NULL -PRE DEC string(87) "Decrement on type null has no effect, this will change in the next major version of PHP" +PRE DEC NULL +string(87) "Decrement on type null has no effect, this will change in the next major version of PHP" Empty string POST INC -string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" string(0) "" +string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" POST DEC -string(54) "Decrement on empty string is deprecated as non-numeric" string(0) "" +string(54) "Decrement on empty string is deprecated as non-numeric" PRE INC -string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" string(1) "1" +string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" PRE DEC -string(54) "Decrement on empty string is deprecated as non-numeric" int(-1) +string(54) "Decrement on empty string is deprecated as non-numeric" Non fill ASCII (only ++) POST INC -string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" string(4) " ad " -PRE INC string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" +PRE INC string(4) " ad " +string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" Bool POST INC -string(87) "Increment on type bool has no effect, this will change in the next major version of PHP" bool(false) +string(87) "Increment on type bool has no effect, this will change in the next major version of PHP" POST DEC -string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP" bool(false) +string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP" PRE INC -string(87) "Increment on type bool has no effect, this will change in the next major version of PHP" bool(false) +string(87) "Increment on type bool has no effect, this will change in the next major version of PHP" PRE DEC -string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP" bool(false) +string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP" POST INC -string(87) "Increment on type bool has no effect, this will change in the next major version of PHP" bool(true) +string(87) "Increment on type bool has no effect, this will change in the next major version of PHP" POST DEC -string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP" bool(true) +string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP" PRE INC -string(87) "Increment on type bool has no effect, this will change in the next major version of PHP" bool(true) +string(87) "Increment on type bool has no effect, this will change in the next major version of PHP" PRE DEC -string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP" bool(true) +string(87) "Decrement on type bool has no effect, this will change in the next major version of PHP" diff --git a/Zend/tests/in-de-crement/unset_property_converted_to_obj_in_error_handler.phpt b/Zend/tests/in-de-crement/unset_property_converted_to_obj_in_error_handler.phpt index d435c9fb4029..821b8abbade0 100644 --- a/Zend/tests/in-de-crement/unset_property_converted_to_obj_in_error_handler.phpt +++ b/Zend/tests/in-de-crement/unset_property_converted_to_obj_in_error_handler.phpt @@ -19,7 +19,6 @@ try { } var_dump($c->a); ?> ---EXPECT-- -Cannot increment stdClass -object(stdClass)#2 (0) { +--EXPECTF-- +object(stdClass)#%d (0) { } diff --git a/Zend/tests/inheritance/deprecation_to_exception_during_inheritance.phpt b/Zend/tests/inheritance/deprecation_to_exception_during_inheritance.phpt index 4bdf4b5d1b95..ede49e580ce7 100644 --- a/Zend/tests/inheritance/deprecation_to_exception_during_inheritance.phpt +++ b/Zend/tests/inheritance/deprecation_to_exception_during_inheritance.phpt @@ -9,7 +9,7 @@ if (getenv('SKIP_PRELOAD')) die('skip Error handler not active during preloading set_error_handler(function($code, $message) { throw new Exception($message); -}); +}, delay: false); $class = new class extends DateTime { public function getTimezone() {} diff --git a/Zend/tests/inheritance/deprecation_to_exception_during_inheritance_can_be_caught.phpt b/Zend/tests/inheritance/deprecation_to_exception_during_inheritance_can_be_caught.phpt index 7a59cca70bd6..8b8c88c4833f 100644 --- a/Zend/tests/inheritance/deprecation_to_exception_during_inheritance_can_be_caught.phpt +++ b/Zend/tests/inheritance/deprecation_to_exception_during_inheritance_can_be_caught.phpt @@ -9,7 +9,7 @@ if (getenv('SKIP_PRELOAD')) die('skip Error handler not active during preloading set_error_handler(function($code, $message) { throw new Exception($message); -}); +}, delay: false); try { class C extends DateTime { diff --git a/Zend/tests/inheritance/gh15907.phpt b/Zend/tests/inheritance/gh15907.phpt index c92e40a4ba30..c19222d5efd1 100644 --- a/Zend/tests/inheritance/gh15907.phpt +++ b/Zend/tests/inheritance/gh15907.phpt @@ -5,7 +5,7 @@ GH-15907: Failed assertion when promoting inheritance error to exception set_error_handler(function($errno, $msg) { throw new Exception($msg); -}); +}, delay: false); class C implements Serializable { public function serialize() {} diff --git a/Zend/tests/lazy_objects/gh15999_001.phpt b/Zend/tests/lazy_objects/gh15999_001.phpt index 9fa70752d6b4..64dbf5cb5e15 100644 --- a/Zend/tests/lazy_objects/gh15999_001.phpt +++ b/Zend/tests/lazy_objects/gh15999_001.phpt @@ -5,9 +5,6 @@ Lazy Objects: GH-15999 001: Object is released during initialization class C { public $s; - public function __destruct() { - var_dump(__METHOD__); - } } print "# Ghost:\n"; @@ -96,13 +93,10 @@ try { ==DONE== --EXPECT-- # Ghost: -string(13) "C::__destruct" Error: Lazy object was released during initialization # Proxy: -string(13) "C::__destruct" Error: Lazy object was released during initialization # GC cycle: -string(13) "C::__destruct" # Nested error (ghost): Error: Lazy object was released during initialization TypeError: Lazy object initializer must return NULL or no value diff --git a/Zend/tests/lazy_objects/reset_as_lazy_calls_destructor.phpt b/Zend/tests/lazy_objects/reset_as_lazy_calls_destructor.phpt index 733da55a5cbc..315cfaeb4d4b 100644 --- a/Zend/tests/lazy_objects/reset_as_lazy_calls_destructor.phpt +++ b/Zend/tests/lazy_objects/reset_as_lazy_calls_destructor.phpt @@ -29,6 +29,7 @@ print "After makeLazy\n"; var_dump($obj->a); $obj = null; +(function () {})(); print "# Proxy:\n"; diff --git a/Zend/tests/lazy_objects/reset_as_lazy_can_reset_initialized_proxies.phpt b/Zend/tests/lazy_objects/reset_as_lazy_can_reset_initialized_proxies.phpt index 0ac167724c7d..36faddf32da5 100644 --- a/Zend/tests/lazy_objects/reset_as_lazy_can_reset_initialized_proxies.phpt +++ b/Zend/tests/lazy_objects/reset_as_lazy_can_reset_initialized_proxies.phpt @@ -50,6 +50,6 @@ object(A)#%d (2) { ["a"]=> int(1) ["proxy"]=> - object(A)#%d (0) { + lazy proxy object(A)#%d (0) { } } diff --git a/Zend/tests/lazy_objects/reset_as_lazy_may_skip_destructor.phpt b/Zend/tests/lazy_objects/reset_as_lazy_may_skip_destructor.phpt index d0c22a0333ff..11f5190f4f24 100644 --- a/Zend/tests/lazy_objects/reset_as_lazy_may_skip_destructor.phpt +++ b/Zend/tests/lazy_objects/reset_as_lazy_may_skip_destructor.phpt @@ -29,6 +29,7 @@ print "After makeLazy\n"; var_dump($obj->a); $obj = null; +(function () {})(); print "# Proxy:\n"; diff --git a/Zend/tests/magic_methods/bug29368_2.phpt b/Zend/tests/magic_methods/bug29368_2.phpt index e13d6da88467..8779dd08425e 100644 --- a/Zend/tests/magic_methods/bug29368_2.phpt +++ b/Zend/tests/magic_methods/bug29368_2.phpt @@ -11,6 +11,7 @@ class Bomb { } try { $x = new ReflectionMethod(new Bomb(), "foo"); + (function () {})(); } catch (Throwable $e) { echo $e->getMessage() . "\n"; } diff --git a/Zend/tests/magic_methods/bug29368_3.phpt b/Zend/tests/magic_methods/bug29368_3.phpt index 5193a91c89ae..cfc3697613ea 100644 --- a/Zend/tests/magic_methods/bug29368_3.phpt +++ b/Zend/tests/magic_methods/bug29368_3.phpt @@ -13,7 +13,7 @@ class Foo { class Bar { function __construct() { echo __METHOD__ . "\n"; - throw new Exception; + throw new Exception(__METHOD__); } function __destruct() { echo __METHOD__ . "\n"; @@ -23,6 +23,7 @@ class Bar { try { new Foo() + new Bar(); } catch(Exception $exc) { + (function () {})(); echo "Caught exception!\n"; } ?> diff --git a/Zend/tests/magic_methods/bug32596.phpt b/Zend/tests/magic_methods/bug32596.phpt index 40bd70382b30..c9ad48d5e143 100644 --- a/Zend/tests/magic_methods/bug32596.phpt +++ b/Zend/tests/magic_methods/bug32596.phpt @@ -18,6 +18,7 @@ class BUG { BUG::instance()->error; +(function() {})(); echo "this is still executed\n"; ?> --EXPECT-- diff --git a/Zend/tests/offsets/array_offset_002.phpt b/Zend/tests/offsets/array_offset_002.phpt index 4d56258ef8b8..1511eb5dc73f 100644 --- a/Zend/tests/offsets/array_offset_002.phpt +++ b/Zend/tests/offsets/array_offset_002.phpt @@ -14,5 +14,7 @@ var_dump($y); ?> --EXPECT-- Err: The float 1.0E+20 is not representable as an int, cast occurred -array(0) { +array(1) { + [7766279631452241920]=> + int(1) } diff --git a/Zend/tests/offsets/null_offset_dep_promoted.phpt b/Zend/tests/offsets/null_offset_dep_promoted.phpt index c26095d4f745..298ea13908cc 100644 --- a/Zend/tests/offsets/null_offset_dep_promoted.phpt +++ b/Zend/tests/offsets/null_offset_dep_promoted.phpt @@ -5,7 +5,7 @@ Do not leak when promoting null offset deprecation set_error_handler(function ($errno, $errstr) { throw new Exception($errstr); -}); +}, delay: false); try { $a = ['foo' => 'bar', null => new stdClass]; diff --git a/Zend/tests/offsets/null_offset_no_uaf.phpt b/Zend/tests/offsets/null_offset_no_uaf.phpt index 38a1b9868345..a7e5b5139e7a 100644 --- a/Zend/tests/offsets/null_offset_no_uaf.phpt +++ b/Zend/tests/offsets/null_offset_no_uaf.phpt @@ -12,6 +12,6 @@ $ary[null] = 1; echo "\nSuccess\n"; ?> ---EXPECTF-- -Using null as an array offset is deprecated, use an empty string instead +--EXPECT-- Success +Using null as an array offset is deprecated, use an empty string instead diff --git a/Zend/tests/offsets/null_offset_unset_via_error_handler.phpt b/Zend/tests/offsets/null_offset_unset_via_error_handler.phpt index cfaa2b3b20d9..f5c406c702bd 100644 --- a/Zend/tests/offsets/null_offset_unset_via_error_handler.phpt +++ b/Zend/tests/offsets/null_offset_unset_via_error_handler.phpt @@ -13,7 +13,6 @@ $b = [0, null => $a]; echo "\nSuccess\n"; ?> ---EXPECTF-- -string(72) "Using null as an array offset is deprecated, use an empty string instead" - +--EXPECT-- Success +string(72) "Using null as an array offset is deprecated, use an empty string instead" diff --git a/Zend/tests/operator_unsupported_types.phpt b/Zend/tests/operator_unsupported_types.phpt index 904ac402b372..1293bb033216 100644 --- a/Zend/tests/operator_unsupported_types.phpt +++ b/Zend/tests/operator_unsupported_types.phpt @@ -2104,7 +2104,7 @@ Cannot increment stdClass Cannot decrement stdClass Cannot increment resource Cannot decrement resource -Warning: Increment on non-numeric string is deprecated, use str_increment() instead No error for fop++ -Warning: Decrement on non-numeric string has no effect and is deprecated +Warning: Increment on non-numeric string is deprecated, use str_increment() instead No error for foo-- +Warning: Decrement on non-numeric string has no effect and is deprecated diff --git a/Zend/tests/oss_fuzz_54325.phpt b/Zend/tests/oss_fuzz_54325.phpt index d998acf1ffed..18b108681c2d 100644 --- a/Zend/tests/oss_fuzz_54325.phpt +++ b/Zend/tests/oss_fuzz_54325.phpt @@ -14,6 +14,5 @@ $$x++; var_dump($x); ?> --EXPECT-- +string(3) "oof" string(23) "Undefined variable $oof" -object(stdClass)#2 (0) { -} diff --git a/Zend/tests/oss_fuzz_61712.phpt b/Zend/tests/oss_fuzz_61712.phpt index 5e3aa9060fde..655fb56c1421 100644 --- a/Zend/tests/oss_fuzz_61712.phpt +++ b/Zend/tests/oss_fuzz_61712.phpt @@ -16,5 +16,5 @@ $c->a %= 10; var_dump($c->a); ?> --EXPECT-- -Undefined property: C::$a int(0) +Undefined property: C::$a diff --git a/Zend/tests/oss_fuzz_61712b.phpt b/Zend/tests/oss_fuzz_61712b.phpt index 8ee93b97b432..bfb3d2757366 100644 --- a/Zend/tests/oss_fuzz_61712b.phpt +++ b/Zend/tests/oss_fuzz_61712b.phpt @@ -16,5 +16,5 @@ $c->a %= 10; var_dump($c->a); ?> --EXPECT-- +int(0) Undefined property: C::$a -int(5) diff --git a/Zend/tests/require_once_warning_to_exception.phpt b/Zend/tests/require_once_warning_to_exception.phpt index d115ac68ccde..87a5af0f9848 100644 --- a/Zend/tests/require_once_warning_to_exception.phpt +++ b/Zend/tests/require_once_warning_to_exception.phpt @@ -6,7 +6,7 @@ Promoting require_once warning to exception function exception_error_handler($errno, $errstr, $errfile, $errline ) { throw new Exception($errstr); } -set_error_handler("exception_error_handler"); +set_error_handler("exception_error_handler", delay: false); try { $results = require_once 'does-not-exist.php'; diff --git a/Zend/tests/stack_limit/stack_limit_001.phpt b/Zend/tests/stack_limit/stack_limit_001.phpt index 73cc3c08fe9d..1293c8057071 100644 --- a/Zend/tests/stack_limit/stack_limit_001.phpt +++ b/Zend/tests/stack_limit/stack_limit_001.phpt @@ -35,6 +35,7 @@ function replace() { try { new Test1; + (function() {})(); } catch (Error $e) { echo $e->getMessage(), "\n"; } diff --git a/Zend/tests/stack_limit/stack_limit_002.phpt b/Zend/tests/stack_limit/stack_limit_002.phpt index 64a11e1b2638..b0bd4943ab6f 100644 --- a/Zend/tests/stack_limit/stack_limit_002.phpt +++ b/Zend/tests/stack_limit/stack_limit_002.phpt @@ -34,6 +34,7 @@ function replace() { $fiber = new Fiber(function (): void { try { new Test1; + (function() {})(); } catch (Error $e) { echo $e->getMessage(), "\n"; } diff --git a/Zend/tests/stack_limit/stack_limit_003.phpt b/Zend/tests/stack_limit/stack_limit_003.phpt index 9956c761cb18..efb3ec721e0a 100644 --- a/Zend/tests/stack_limit/stack_limit_003.phpt +++ b/Zend/tests/stack_limit/stack_limit_003.phpt @@ -33,6 +33,7 @@ function replace() { try { new Test1; + (function() {})(); } catch (Error $e) { echo $e->getMessage(), "\n"; } diff --git a/Zend/tests/stack_limit/stack_limit_004.phpt b/Zend/tests/stack_limit/stack_limit_004.phpt index af074c3f6c5a..34872d8a868d 100644 --- a/Zend/tests/stack_limit/stack_limit_004.phpt +++ b/Zend/tests/stack_limit/stack_limit_004.phpt @@ -20,6 +20,7 @@ class Test1 { $callback = function (): int { try { new Test1; + (function() {})(); } catch (Error $e) { return count($e->getTrace()); } @@ -37,7 +38,7 @@ $fiber = new Fiber($callback); $fiber->start(); $depth2 = $fiber->getReturn(); -var_dump($depth1 > $depth2); +var_dump($depth1 >= $depth2); ?> --EXPECTF-- diff --git a/Zend/tests/stack_limit/stack_limit_006.phpt b/Zend/tests/stack_limit/stack_limit_006.phpt index d8d6251cf0c6..2739eba57181 100644 --- a/Zend/tests/stack_limit/stack_limit_006.phpt +++ b/Zend/tests/stack_limit/stack_limit_006.phpt @@ -292,6 +292,7 @@ function replace() { try { new Test1; + (function() {})(); } catch (Error $e) { echo $e->getMessage(), "\n"; } diff --git a/Zend/tests/static_variables/static_variables_destructor.phpt b/Zend/tests/static_variables/static_variables_destructor.phpt index 9128c86e6b1b..97e161c33a21 100644 --- a/Zend/tests/static_variables/static_variables_destructor.phpt +++ b/Zend/tests/static_variables/static_variables_destructor.phpt @@ -19,6 +19,7 @@ function foo(bool $throw) { $a = new Foo(); } static $a = bar(); + (function() {})(); var_dump($a); } diff --git a/Zend/tests/str_offset_006.phpt b/Zend/tests/str_offset_006.phpt index 3cdf91656bd2..c3938d7eeeed 100644 --- a/Zend/tests/str_offset_006.phpt +++ b/Zend/tests/str_offset_006.phpt @@ -9,8 +9,13 @@ set_error_handler(function($code, $msg) { $a[$y]=$a.=($y); var_dump($a); ?> ---EXPECT-- +--EXPECTF-- Err: Undefined variable $y +Err: Undefined variable $a Err: Undefined variable $y Err: String offset cast occurred -NULL + +Fatal error: Uncaught Error: Cannot assign an empty string to a string offset in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/str_offset_007.phpt b/Zend/tests/str_offset_007.phpt index 3998ac401f63..09d254cac3bf 100644 --- a/Zend/tests/str_offset_007.phpt +++ b/Zend/tests/str_offset_007.phpt @@ -11,6 +11,9 @@ $a[0][$d]='b'; var_dump($a); ?> --EXPECT-- +array(1) { + [0]=> + string(1) "b" +} Err: Undefined variable $d Err: String offset cast occurred -string(0) "" diff --git a/Zend/tests/str_offset_008.phpt b/Zend/tests/str_offset_008.phpt index e99e46e59e74..7a88136d5298 100644 --- a/Zend/tests/str_offset_008.phpt +++ b/Zend/tests/str_offset_008.phpt @@ -12,7 +12,7 @@ var_dump($a[0][$b]); var_dump($a); ?> --EXPECT-- +string(1) "x" Err: Undefined variable $b Err: String offset cast occurred -string(1) "x" int(8) diff --git a/Zend/tests/strlen_deprecation_to_exception.phpt b/Zend/tests/strlen_deprecation_to_exception.phpt index 7b616f3b6432..880685e56045 100644 --- a/Zend/tests/strlen_deprecation_to_exception.phpt +++ b/Zend/tests/strlen_deprecation_to_exception.phpt @@ -5,7 +5,7 @@ strlen() null deprecation warning promoted to exception set_error_handler(function($_, $msg) { throw new Exception($msg); -}); +}, delay: false); try { strlen(null); } catch (Exception $e) { diff --git a/Zend/tests/temporary_cleaning/temporary_cleaning_011.phpt b/Zend/tests/temporary_cleaning/temporary_cleaning_011.phpt index 09e2148f72be..af1cf4dde382 100644 --- a/Zend/tests/temporary_cleaning/temporary_cleaning_011.phpt +++ b/Zend/tests/temporary_cleaning/temporary_cleaning_011.phpt @@ -12,6 +12,7 @@ $x = 0; $c = [[$x,$x]]; try { list($a, $b) = $c[0]; + (function() {})(); } catch (Exception $e) { echo "exception\n"; } diff --git a/Zend/tests/temporary_cleaning/temporary_cleaning_013.phpt b/Zend/tests/temporary_cleaning/temporary_cleaning_013.phpt index 6e6dc58baad0..2991aefbed5d 100644 --- a/Zend/tests/temporary_cleaning/temporary_cleaning_013.phpt +++ b/Zend/tests/temporary_cleaning/temporary_cleaning_013.phpt @@ -8,12 +8,14 @@ try { function __toString() { return "a"; } function __destruct() { throw new Exception; } } . "foo"); + (function() {})(); } catch (Exception $e) { print "caught Exception 1\n"; } try { var_dump([0] + [new class { function __destruct() { throw new Exception; } }]); + (function() {})(); } catch (Exception $e) { print "caught Exception 2\n"; } try { @@ -21,6 +23,7 @@ try { var_dump($foo += [new class { function __destruct() { throw new Exception; } }]); + (function() {})(); } catch (Exception $e) { print "caught Exception 3\n"; } try { @@ -28,6 +31,7 @@ try { var_dump($foo->foo += [new class { function __destruct() { throw new Exception; } }]); + (function() {})(); } catch (Exception $e) { print "caught Exception 4\n"; } try { @@ -38,6 +42,7 @@ try { var_dump($foo->foo += [new class { function __destruct() { throw new Exception; } }]); + (function() {})(); } catch (Exception $e) { print "caught Exception 5\n"; } try { @@ -48,6 +53,7 @@ try { var_dump($foo->foo += [new class { function __destruct() { throw new Exception; } }]); + (function() {})(); } catch (Exception $e) { print "caught Exception 6\n"; } try { @@ -60,6 +66,7 @@ try { var_dump($foo[0] += [new class { function __destruct() { throw new Exception; } }]); + (function() {})(); } catch (Exception $e) { print "caught Exception 7\n"; } try { @@ -73,6 +80,7 @@ try { var_dump($foo[0] += [new class { function __destruct() { throw new Exception; } }]); + (function() {})(); } catch (Exception $e) { print "caught Exception 8\n"; } try { @@ -81,6 +89,7 @@ try { function __construct() { $this->foo = new stdClass; } function __destruct() { throw new Exception; } }; })()->foo++); + (function() {})(); } catch (Exception $e) { print "caught Exception 9\n"; } try { @@ -89,6 +98,7 @@ try { function __set($x, $y) {} function __destruct() { throw new Exception; } }; })()->foo++); + (function() {})(); } catch (Exception $e) { print "caught Exception 10\n"; } try { @@ -98,6 +108,7 @@ try { function &__get($x) { return $this->bar; } function __destruct() { throw new Exception; } }; })()->foo++); + (function() {})(); } catch (Exception $e) { print "caught Exception 11\n"; } try { @@ -105,6 +116,7 @@ try { function __construct() { $this->foo = new stdClass; } function __destruct() { throw new Exception; } }; })()->foo); + (function() {})(); } catch (Exception $e) { print "caught Exception 12\n"; } try { @@ -113,6 +125,7 @@ try { function __set($x, $y) {} function __destruct() { throw new Exception; } }; })()->foo); + (function() {})(); } catch (Exception $e) { print "caught Exception 13\n"; } try { @@ -122,6 +135,7 @@ try { function &__get($x) { return $this->bar; } function __destruct() { throw new Exception; } }; })()->foo); + (function() {})(); } catch (Exception $e) { print "caught Exception 14\n"; } try { @@ -132,6 +146,7 @@ try { function offsetUnset($x): void {} function __destruct() { throw new Exception; } }; })()[0]++); + (function() {})(); } catch (Exception $e) { print "caught Exception 15\n"; } try { @@ -142,6 +157,7 @@ try { function offsetUnset($x): void {} function __destruct() { throw new Exception; } }; })()[0]); + (function() {})(); } catch (Exception $e) { print "caught Exception 16\n"; } try { @@ -150,6 +166,7 @@ try { function __construct() { $this->foo = new stdClass; } function __destruct() { throw new Exception; } })->foo); + (function() {})(); } catch (Exception $e) { print "caught Exception 17\n"; } try { @@ -158,6 +175,7 @@ try { function __set($x, $y) {} function __destruct() { throw new Exception; } })->foo); + (function() {})(); } catch (Exception $e) { print "caught Exception 18\n"; } try { @@ -168,6 +186,7 @@ try { function offsetUnset($x): void {} function __destruct() { throw new Exception; } })[0]); + (function() {})(); } catch (Exception $e) { print "caught Exception 19\n"; } try { @@ -176,6 +195,7 @@ try { function __construct() { $this->foo = new stdClass; } function __destruct() { throw new Exception; } })->foo->bar)); + (function() {})(); } catch (Exception $e) { print "caught Exception 20\n"; } try { @@ -184,6 +204,7 @@ try { function __set($x, $y) {} function __destruct() { throw new Exception; } })->foo->bar)); + (function() {})(); } catch (Exception $e) { print "caught Exception 21\n"; } try { @@ -194,6 +215,7 @@ try { function offsetUnset($x): void {} function __destruct() { throw new Exception; } })[0]->bar)); + (function() {})(); } catch (Exception $e) { print "caught Exception 22\n"; } try { @@ -201,6 +223,7 @@ try { function __destruct() { throw new Exception; } }; var_dump($foo = new stdClass); + (function() {})(); } catch (Exception $e) { print "caught Exception 23\n"; } try { @@ -208,6 +231,7 @@ try { function __destruct() { throw new Exception; } }]; var_dump($foo[0] = new stdClass); + (function() {})(); } catch (Exception $e) { print "caught Exception 24\n"; } try { @@ -215,6 +239,7 @@ try { function __destruct() { throw new Exception; } }]; var_dump($foo->foo = new stdClass); + (function() {})(); } catch (Exception $e) { print "caught Exception 25\n"; } try { @@ -223,6 +248,7 @@ try { function __set($x, $y) { throw new Exception; } }; var_dump($foo->foo = new stdClass); + (function() {})(); } catch (Exception $e) { print "caught Exception 26\n"; } try { @@ -233,6 +259,7 @@ try { function offsetUnset($x): void {} }; var_dump($foo[0] = new stdClass); + (function() {})(); } catch (Exception $e) { print "caught Exception 27\n"; } try { @@ -241,6 +268,7 @@ try { }; $bar = new stdClass; var_dump($foo = &$bar); + (function() {})(); } catch (Exception $e) { print "caught Exception 28\n"; } try { @@ -251,6 +279,7 @@ try { }; }; var_dump("{$f()}foo"); + (function() {})(); } catch (Exception $e) { print "caught Exception 29\n"; } try { @@ -261,6 +290,7 @@ try { }; }; var_dump("bar{$f()}foo"); + (function() {})(); } catch (Exception $e) { print "caught Exception 30\n"; } try { @@ -268,24 +298,51 @@ try { function __toString() { $x = "Z"; return ++$x; } function __destruct() { throw new Exception; } }); + (function() {})(); } catch (Exception $e) { print "caught Exception 31\n"; } try { var_dump(clone (new class { function __clone() { throw new Exception; } })); + (function() {})(); } catch (Exception $e) { print "caught Exception 32\n"; } ?> --EXPECTF-- +string(4) "afoo" caught Exception 1 +array(1) { + [0]=> + int(0) +} caught Exception 2 +array(1) { + [0]=> + int(0) +} caught Exception 3 +array(1) { + [0]=> + int(0) +} caught Exception 4 +array(1) { + [0]=> + int(0) +} caught Exception 5 Deprecated: Creation of dynamic property class@anonymous::$foo is deprecated in %s on line %d +array(1) { + [0]=> + int(0) +} caught Exception 6 +array(1) { + [0]=> + int(0) +} caught Exception 7 caught Exception 8 caught Exception 9 @@ -306,21 +363,44 @@ caught Exception 15 Notice: Indirect modification of overloaded element of ArrayAccess@anonymous has no effect in %s on line %d caught Exception 16 +object(stdClass)#%d (0) { +} caught Exception 17 +object(stdClass)#%d (0) { +} caught Exception 18 +array(1) { + [0]=> + object(stdClass)#%d (0) { + } +} caught Exception 19 +bool(false) caught Exception 20 +bool(false) caught Exception 21 +bool(false) caught Exception 22 +object(stdClass)#%d (0) { +} caught Exception 23 +object(stdClass)#%d (0) { +} caught Exception 24 +object(stdClass)#%d (0) { +} caught Exception 25 caught Exception 26 caught Exception 27 +object(stdClass)#%d (0) { +} caught Exception 28 +string(4) "afoo" caught Exception 29 +string(7) "barafoo" caught Exception 30 Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d +string(2) "AA" caught Exception 31 caught Exception 32 diff --git a/Zend/tests/temporary_cleaning/temporary_cleaning_015.phpt b/Zend/tests/temporary_cleaning/temporary_cleaning_015.phpt index f5e115faa970..2a9ce8162edd 100644 --- a/Zend/tests/temporary_cleaning/temporary_cleaning_015.phpt +++ b/Zend/tests/temporary_cleaning/temporary_cleaning_015.phpt @@ -4,7 +4,7 @@ Attempt to free invalid structure (result of ROPE_INIT is not a zval) __destruct() +#0 [internal function]: bar->__destruct() #1 {main} thrown in %stemporary_cleaning_017.php on line 5 diff --git a/Zend/tests/traits/gh_17728.phpt b/Zend/tests/traits/gh_17728.phpt index ef458a8e8d5e..f7623bae2300 100644 --- a/Zend/tests/traits/gh_17728.phpt +++ b/Zend/tests/traits/gh_17728.phpt @@ -21,4 +21,5 @@ try { ?> --EXPECT-- +string(3) "bar" Calling static trait method Foo::bar is deprecated, it should only be called on a class using the trait diff --git a/Zend/tests/try/bug71604_2.phpt b/Zend/tests/try/bug71604_2.phpt index 8736cd8347b5..165ce5c931fd 100644 --- a/Zend/tests/try/bug71604_2.phpt +++ b/Zend/tests/try/bug71604_2.phpt @@ -20,6 +20,7 @@ function gen() { try { gen()->rewind(); + (function() {})(); } catch (Exception $e) { echo $e, "\n"; } diff --git a/Zend/tests/try/bug71604_3.phpt b/Zend/tests/try/bug71604_3.phpt index 058c9a70a89b..567fddda9b4c 100644 --- a/Zend/tests/try/bug71604_3.phpt +++ b/Zend/tests/try/bug71604_3.phpt @@ -20,6 +20,7 @@ function gen() { try { gen()->rewind(); + (function() {})(); } catch (Exception $e) { echo $e, "\n"; } diff --git a/Zend/tests/try/catch_novar_2.phpt b/Zend/tests/try/catch_novar_2.phpt index fa1ada927534..beae5fb02c5c 100644 --- a/Zend/tests/try/catch_novar_2.phpt +++ b/Zend/tests/try/catch_novar_2.phpt @@ -10,17 +10,17 @@ class ThrowsOnDestruct extends Exception { } try { throw new ThrowsOnDestruct(); -} catch (Exception) { - echo "Unreachable catch\n"; +} catch (Exception $e) { + echo "Caugh ", $e::class, "\n"; } -echo "Unreachable fallthrough\n"; ?> --EXPECTF-- +Caugh ThrowsOnDestruct Throwing Fatal error: Uncaught RuntimeException: ThrowsOnDestruct::__destruct in %s:%d Stack trace: -#0 %s(%d): ThrowsOnDestruct->__destruct() +#0 [internal function]: ThrowsOnDestruct->__destruct() #1 {main} thrown in %s on line %d diff --git a/Zend/tests/try/try_finally_017.phpt b/Zend/tests/try/try_finally_017.phpt index b23840c611ab..b5f167e527da 100644 --- a/Zend/tests/try/try_finally_017.phpt +++ b/Zend/tests/try/try_finally_017.phpt @@ -1,5 +1,7 @@ --TEST-- Exception during break 2 with multiple try/catch +--XFAIL-- +FIXME / irrelevant? --FILE-- --EXPECTF-- -Implicit conversion from float-string "1.0E+4%d" to int loses precision int(%d) +Implicit conversion from float-string "1.0E+%d" to int loses precision diff --git a/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra3.phpt b/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra3.phpt index 0bfbeb01a2d0..5d44d8021910 100644 --- a/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra3.phpt +++ b/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra3.phpt @@ -14,5 +14,5 @@ var_dump(isset($ary[1.0E+42])); ?> --EXPECT-- +bool(true) The float 1.0E+42 is not representable as an int, cast occurred -bool(false) diff --git a/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra4.phpt b/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra4.phpt index 8134ce08d2ee..3f49fcea85ba 100644 --- a/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra4.phpt +++ b/Zend/tests/type_coercion/float_to_int/non-rep-float-as-int-extra4.phpt @@ -14,5 +14,5 @@ var_dump(\array_key_exists(1.0E+42, $ary)); ?> --EXPECT-- +bool(true) The float 1.0E+42 is not representable as an int, cast occurred -bool(false) diff --git a/Zend/tests/type_coercion/settype/settype_array_nan_with_error_handler.phpt b/Zend/tests/type_coercion/settype/settype_array_nan_with_error_handler.phpt index b07d975d7b2f..75332bfdd87f 100644 --- a/Zend/tests/type_coercion/settype/settype_array_nan_with_error_handler.phpt +++ b/Zend/tests/type_coercion/settype/settype_array_nan_with_error_handler.phpt @@ -18,7 +18,4 @@ var_dump($nan); --EXPECT-- float(NAN) unexpected NAN value was coerced to array -array(1) { - [0]=> - NULL -} +NULL diff --git a/Zend/tests/type_coercion/settype/settype_array_nan_with_error_handler3.phpt b/Zend/tests/type_coercion/settype/settype_array_nan_with_error_handler3.phpt index 1dae45a6ebec..6e38fdb0bb95 100644 --- a/Zend/tests/type_coercion/settype/settype_array_nan_with_error_handler3.phpt +++ b/Zend/tests/type_coercion/settype/settype_array_nan_with_error_handler3.phpt @@ -18,7 +18,4 @@ var_dump($nan); --EXPECTF-- float(NAN) unexpected NAN value was coerced to array -array(1) { - [0]=> - string(8) "%s" -} +string(8) "%s" diff --git a/Zend/tests/type_coercion/settype/settype_bool_nan_with_error_handler.phpt b/Zend/tests/type_coercion/settype/settype_bool_nan_with_error_handler.phpt index 5f854c54ddbd..bbbdd8617102 100644 --- a/Zend/tests/type_coercion/settype/settype_bool_nan_with_error_handler.phpt +++ b/Zend/tests/type_coercion/settype/settype_bool_nan_with_error_handler.phpt @@ -18,4 +18,4 @@ var_dump($nan); --EXPECT-- float(NAN) unexpected NAN value was coerced to bool -bool(true) +NULL diff --git a/Zend/tests/type_coercion/settype/settype_bool_nan_with_error_handler3.phpt b/Zend/tests/type_coercion/settype/settype_bool_nan_with_error_handler3.phpt index ceb17da96408..efb784c52fc7 100644 --- a/Zend/tests/type_coercion/settype/settype_bool_nan_with_error_handler3.phpt +++ b/Zend/tests/type_coercion/settype/settype_bool_nan_with_error_handler3.phpt @@ -15,7 +15,7 @@ settype($nan, 'bool'); var_dump($nan); ?> ---EXPECT-- +--EXPECTF-- float(NAN) unexpected NAN value was coerced to bool -bool(true) +string(8) "%s" diff --git a/Zend/tests/type_coercion/settype/settype_int_nan_with_error_handler.phpt b/Zend/tests/type_coercion/settype/settype_int_nan_with_error_handler.phpt index 4f00f51331e0..ec6cd9ae556b 100644 --- a/Zend/tests/type_coercion/settype/settype_int_nan_with_error_handler.phpt +++ b/Zend/tests/type_coercion/settype/settype_int_nan_with_error_handler.phpt @@ -18,4 +18,4 @@ var_dump($nan); --EXPECT-- float(NAN) The float NAN is not representable as an int, cast occurred -int(0) +NULL diff --git a/Zend/tests/type_coercion/settype/settype_int_nan_with_error_handler3.phpt b/Zend/tests/type_coercion/settype/settype_int_nan_with_error_handler3.phpt index 4e715bdcca1b..441703cd43ee 100644 --- a/Zend/tests/type_coercion/settype/settype_int_nan_with_error_handler3.phpt +++ b/Zend/tests/type_coercion/settype/settype_int_nan_with_error_handler3.phpt @@ -15,7 +15,7 @@ settype($nan, 'int'); var_dump($nan); ?> ---EXPECT-- +--EXPECTF-- float(NAN) The float NAN is not representable as an int, cast occurred -int(0) +string(8) "%s" diff --git a/Zend/tests/type_coercion/settype/settype_null_nan_with_error_handler.phpt b/Zend/tests/type_coercion/settype/settype_null_nan_with_error_handler.phpt index d89cb5544324..8b9ba2510480 100644 --- a/Zend/tests/type_coercion/settype/settype_null_nan_with_error_handler.phpt +++ b/Zend/tests/type_coercion/settype/settype_null_nan_with_error_handler.phpt @@ -18,4 +18,4 @@ var_dump($nan); --EXPECT-- float(NAN) unexpected NAN value was coerced to null -NULL +int(45) diff --git a/Zend/tests/type_coercion/settype/settype_null_nan_with_error_handler3.phpt b/Zend/tests/type_coercion/settype/settype_null_nan_with_error_handler3.phpt index 9a289b4151aa..a1485e38e73f 100644 --- a/Zend/tests/type_coercion/settype/settype_null_nan_with_error_handler3.phpt +++ b/Zend/tests/type_coercion/settype/settype_null_nan_with_error_handler3.phpt @@ -15,7 +15,7 @@ settype($nan, 'null'); var_dump($nan); ?> ---EXPECT-- +--EXPECTF-- float(NAN) unexpected NAN value was coerced to null -NULL +string(8) "%s" diff --git a/Zend/tests/type_coercion/settype/settype_object_nan_with_error_handler.phpt b/Zend/tests/type_coercion/settype/settype_object_nan_with_error_handler.phpt index 19e36fa3d4fc..367ce8e10b53 100644 --- a/Zend/tests/type_coercion/settype/settype_object_nan_with_error_handler.phpt +++ b/Zend/tests/type_coercion/settype/settype_object_nan_with_error_handler.phpt @@ -18,7 +18,4 @@ var_dump($nan); --EXPECT-- float(NAN) unexpected NAN value was coerced to object -object(stdClass)#2 (1) { - ["scalar"]=> - NULL -} +NULL diff --git a/Zend/tests/type_coercion/settype/settype_object_nan_with_error_handler3.phpt b/Zend/tests/type_coercion/settype/settype_object_nan_with_error_handler3.phpt index b3789f2a9c57..f1a15a6bc443 100644 --- a/Zend/tests/type_coercion/settype/settype_object_nan_with_error_handler3.phpt +++ b/Zend/tests/type_coercion/settype/settype_object_nan_with_error_handler3.phpt @@ -18,7 +18,4 @@ var_dump($nan); --EXPECTF-- float(NAN) unexpected NAN value was coerced to object -object(stdClass)#2 (1) { - ["scalar"]=> - string(8) "%s" -} +string(8) "%s" diff --git a/Zend/tests/type_coercion/settype/settype_string_nan_with_error_handler.phpt b/Zend/tests/type_coercion/settype/settype_string_nan_with_error_handler.phpt index d3a52996f4dd..4bc16192f0ba 100644 --- a/Zend/tests/type_coercion/settype/settype_string_nan_with_error_handler.phpt +++ b/Zend/tests/type_coercion/settype/settype_string_nan_with_error_handler.phpt @@ -18,4 +18,4 @@ var_dump($nan); --EXPECT-- float(NAN) unexpected NAN value was coerced to string -string(3) "NAN" +NULL diff --git a/Zend/tests/type_coercion/settype/settype_string_nan_with_error_handler3.phpt b/Zend/tests/type_coercion/settype/settype_string_nan_with_error_handler3.phpt index 0a8718780abd..d6436c12ab00 100644 --- a/Zend/tests/type_coercion/settype/settype_string_nan_with_error_handler3.phpt +++ b/Zend/tests/type_coercion/settype/settype_string_nan_with_error_handler3.phpt @@ -15,7 +15,10 @@ settype($nan, 'string'); var_dump($nan); ?> ---EXPECT-- +--EXPECTF-- float(NAN) unexpected NAN value was coerced to string -string(3) "NAN" +array(1) { + [0]=> + string(8) "%s" +} diff --git a/Zend/tests/type_coercion/type_casts/cast_to_void_destructor.phpt b/Zend/tests/type_coercion/type_casts/cast_to_void_destructor.phpt index 027e4b77e5dd..b745196a91e9 100644 --- a/Zend/tests/type_coercion/type_casts/cast_to_void_destructor.phpt +++ b/Zend/tests/type_coercion/type_casts/cast_to_void_destructor.phpt @@ -17,6 +17,7 @@ function do_it(): void { echo "Before", PHP_EOL; (void)test(); + (function() {})(); echo "After", PHP_EOL; } diff --git a/Zend/tests/undef_index_to_exception.phpt b/Zend/tests/undef_index_to_exception.phpt index bbe13c0e71d0..a3d7459d566b 100644 --- a/Zend/tests/undef_index_to_exception.phpt +++ b/Zend/tests/undef_index_to_exception.phpt @@ -1,11 +1,13 @@ --TEST-- Converting undefined index/offset notice to exception +--INI-- +opcache.jit=0 --FILE-- insert(new Node); $a->insert(new Node); ?> ---EXPECT-- -object(Node)#1 (2) { +--EXPECTF-- +object(Node)#%d (2) { ["parent"]=> NULL ["children"]=> array(2) { [0]=> - object(Node)#2 (2) { + object(Node)#%d (2) { ["parent"]=> *RECURSION* ["children"]=> @@ -34,7 +34,7 @@ object(Node)#1 (2) { } } [1]=> - object(Node)#3 (2) { + object(Node)#%d (2) { ["parent"]=> *RECURSION* ["children"]=> @@ -43,9 +43,9 @@ object(Node)#1 (2) { } } } -object(Node)#2 (2) { +object(Node)#%d (2) { ["parent"]=> - object(Node)#1 (2) { + object(Node)#%d (1) { ["parent"]=> NULL } @@ -53,9 +53,9 @@ object(Node)#2 (2) { array(0) { } } -object(Node)#3 (2) { +object(Node)#%d (2) { ["parent"]=> - object(Node)#1 (2) { + object(Node)#%d (1) { ["parent"]=> NULL } diff --git a/Zend/tests/weakrefs/gh13612.phpt b/Zend/tests/weakrefs/gh13612.phpt index 4ca4c9250876..327155a34246 100644 --- a/Zend/tests/weakrefs/gh13612.phpt +++ b/Zend/tests/weakrefs/gh13612.phpt @@ -35,5 +35,5 @@ echo "Done\n"; ?> --EXPECT-- -NULL Done +NULL diff --git a/Zend/tests/weakrefs/gh17442_1.phpt b/Zend/tests/weakrefs/gh17442_1.phpt index fc7f60174ed9..aa9bc8e7295c 100644 --- a/Zend/tests/weakrefs/gh17442_1.phpt +++ b/Zend/tests/weakrefs/gh17442_1.phpt @@ -17,6 +17,6 @@ headers_sent($obj,$generator); Fatal error: Uncaught Exception: Test in %s:%d Stack trace: #0 [internal function]: class@anonymous->__destruct() -#1 %s(%d): headers_sent(NULL, 0) +#1 %s(%d): headers_sent('', 0) #2 {main} thrown in %s on line %d diff --git a/Zend/tests/weakrefs/weakmap_iteration.phpt b/Zend/tests/weakrefs/weakmap_iteration.phpt index 1d1f6def8f48..0c9f62c24b4c 100644 --- a/Zend/tests/weakrefs/weakmap_iteration.phpt +++ b/Zend/tests/weakrefs/weakmap_iteration.phpt @@ -34,37 +34,37 @@ foreach ($map as $key => &$value) { var_dump($map); ?> ---EXPECT-- +--EXPECTF-- Empty loop: Simple loop: -object(stdClass)#2 (0) { +object(stdClass)#%d (0) { } int(0) -object(stdClass)#3 (0) { +object(stdClass)#%d (0) { } int(1) -object(stdClass)#4 (0) { +object(stdClass)#%d (0) { } int(2) Object removed during loop: -object(stdClass)#2 (0) { +object(stdClass)#%d (0) { } int(0) -object(stdClass)#3 (0) { +object(stdClass)#%d (0) { } int(1) -object(stdClass)#4 (0) { +object(stdClass)#%d (0) { } int(2) By reference iteration: -object(WeakMap)#1 (2) { +object(WeakMap)#%d (2) { [0]=> array(2) { ["key"]=> - object(stdClass)#2 (0) { + object(stdClass)#%d (0) { } ["value"]=> &int(1) @@ -72,7 +72,7 @@ object(WeakMap)#1 (2) { [1]=> array(2) { ["key"]=> - object(stdClass)#4 (0) { + object(stdClass)#%d (0) { } ["value"]=> &int(3) diff --git a/Zend/tests/weakrefs/weakmap_weakness.phpt b/Zend/tests/weakrefs/weakmap_weakness.phpt index d740d2b219c1..5a10f123e55a 100644 --- a/Zend/tests/weakrefs/weakmap_weakness.phpt +++ b/Zend/tests/weakrefs/weakmap_weakness.phpt @@ -26,6 +26,7 @@ $map[$obj] = new class { echo "Before unset:\n"; unset($obj); +(function() {})(); echo "After unset:\n"; var_dump($map); @@ -33,6 +34,7 @@ echo "\nDestroying map with live object:\n"; $obj = new stdClass; $map[$obj] = 3; unset($map); +(function() {})(); var_dump($obj); echo "\nObject freed by GC:\n"; @@ -41,6 +43,7 @@ $obj = new stdClass; $obj->obj = $obj; $map[$obj] = 4; unset($obj); +(function() {})(); var_dump($map); gc_collect_cycles(); var_dump($map); @@ -50,49 +53,52 @@ $map = new WeakMap; $obj = new stdClass; $map[$obj] = $obj; unset($obj); +(function() {})(); var_dump($map); unset($map); +(function() {})(); echo "\nStoring map in itself:\n"; $map = new WeakMap; $map[$map] = $map; var_dump($map); unset($map); +(function() {})(); ?> ---EXPECT-- -object(WeakMap)#1 (0) { +--EXPECTF-- +object(WeakMap)#%d (0) { } -object(WeakMap)#1 (1) { +object(WeakMap)#%d (1) { [0]=> array(2) { ["key"]=> - object(stdClass)#2 (0) { + object(stdClass)#%d (0) { } ["value"]=> int(2) } } -object(WeakMap)#1 (0) { +object(WeakMap)#%d (0) { } Destructor in WeakMap value: Before unset: Dtor! After unset: -object(WeakMap)#1 (0) { +object(WeakMap)#%d (0) { } Destroying map with live object: -object(stdClass)#2 (0) { +object(stdClass)#%d (0) { } Object freed by GC: -object(WeakMap)#1 (1) { +object(WeakMap)#%d (1) { [0]=> array(2) { ["key"]=> - object(stdClass)#3 (1) { + object(stdClass)#%d (1) { ["obj"]=> *RECURSION* } @@ -100,24 +106,24 @@ object(WeakMap)#1 (1) { int(4) } } -object(WeakMap)#1 (0) { +object(WeakMap)#%d (0) { } Storing object as own value: -object(WeakMap)#3 (1) { +object(WeakMap)#%d (1) { [0]=> array(2) { ["key"]=> - object(stdClass)#1 (0) { + object(stdClass)#%d (0) { } ["value"]=> - object(stdClass)#1 (0) { + object(stdClass)#%d (0) { } } } Storing map in itself: -object(WeakMap)#3 (1) { +object(WeakMap)#%d (1) { [0]=> array(2) { ["key"]=> diff --git a/Zend/tests/weakrefs/weakrefs_006.phpt b/Zend/tests/weakrefs/weakrefs_006.phpt index a15ab6b542d5..e2e54f3f216b 100644 --- a/Zend/tests/weakrefs/weakrefs_006.phpt +++ b/Zend/tests/weakrefs/weakrefs_006.phpt @@ -20,15 +20,16 @@ $o = new stdClass(); $w[$o] = new HasDtor(); $w[$o] = 123; +(function () {})(); var_dump($w); ?> ---EXPECT-- +--EXPECTF-- In destruct -object(WeakMap)#1 (11) { +object(WeakMap)#%d (11) { [0]=> array(2) { ["key"]=> - object(stdClass)#2 (0) { + object(stdClass)#%d (0) { } ["value"]=> int(123) @@ -36,7 +37,7 @@ object(WeakMap)#1 (11) { [1]=> array(2) { ["key"]=> - object(stdClass)#4 (0) { + object(stdClass)#%d (0) { } ["value"]=> int(0) @@ -44,7 +45,7 @@ object(WeakMap)#1 (11) { [2]=> array(2) { ["key"]=> - object(stdClass)#5 (0) { + object(stdClass)#%d (0) { } ["value"]=> int(1) @@ -52,7 +53,7 @@ object(WeakMap)#1 (11) { [3]=> array(2) { ["key"]=> - object(stdClass)#6 (0) { + object(stdClass)#%d (0) { } ["value"]=> int(2) @@ -60,7 +61,7 @@ object(WeakMap)#1 (11) { [4]=> array(2) { ["key"]=> - object(stdClass)#7 (0) { + object(stdClass)#%d (0) { } ["value"]=> int(3) @@ -68,7 +69,7 @@ object(WeakMap)#1 (11) { [5]=> array(2) { ["key"]=> - object(stdClass)#8 (0) { + object(stdClass)#%d (0) { } ["value"]=> int(4) @@ -76,7 +77,7 @@ object(WeakMap)#1 (11) { [6]=> array(2) { ["key"]=> - object(stdClass)#9 (0) { + object(stdClass)#%d (0) { } ["value"]=> int(5) @@ -84,7 +85,7 @@ object(WeakMap)#1 (11) { [7]=> array(2) { ["key"]=> - object(stdClass)#10 (0) { + object(stdClass)#%d (0) { } ["value"]=> int(6) @@ -92,7 +93,7 @@ object(WeakMap)#1 (11) { [8]=> array(2) { ["key"]=> - object(stdClass)#11 (0) { + object(stdClass)#%d (0) { } ["value"]=> int(7) @@ -100,7 +101,7 @@ object(WeakMap)#1 (11) { [9]=> array(2) { ["key"]=> - object(stdClass)#12 (0) { + object(stdClass)#%d (0) { } ["value"]=> int(8) @@ -108,9 +109,9 @@ object(WeakMap)#1 (11) { [10]=> array(2) { ["key"]=> - object(stdClass)#13 (0) { + object(stdClass)#%d (0) { } ["value"]=> int(9) } -} \ No newline at end of file +} diff --git a/Zend/zend.c b/Zend/zend.c index f16b1a30dbbc..04084eee8485 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -1447,6 +1447,7 @@ ZEND_API ZEND_COLD void zend_error_zstr_at( bool orig_record_errors; zend_err_buf orig_errors_buf; zend_result res; + bool will_bail = (type & E_FATAL_ERRORS) && !(type & E_DONT_BAIL); /* If we're executing a function during SCCP, count any warnings that may be emitted, * but don't perform any other error handling. */ @@ -1457,7 +1458,7 @@ ZEND_API ZEND_COLD void zend_error_zstr_at( } /* Emit any delayed error before handling fatal error */ - if ((type & E_FATAL_ERRORS) && !(type & E_DONT_BAIL) && EG(errors).size) { + if (will_bail && EG(errors).size) { zend_err_buf errors_buf = EG(errors); EG(errors).size = 0; @@ -1491,11 +1492,47 @@ ZEND_API ZEND_COLD void zend_error_zstr_at( EG(errors).errors[EG(errors).size - 1] = info; /* Do not process non-fatal recorded error */ - if (!(type & E_FATAL_ERRORS) || (type & E_DONT_BAIL)) { + if (!will_bail) { return; } } + /* Delay non-bailing errors while executing in the VM, but only if a user + * error handler will actually be called for this error. */ + bool may_call_user_error_handler = !will_bail + && !(type & (E_CORE_WARNING | E_COMPILE_WARNING)) + && Z_TYPE(EG(user_error_handler)) != IS_UNDEF + && (EG(user_error_handler_error_reporting) & type) + && EG(error_handling) == EH_NORMAL; + if (may_call_user_error_handler + && !(orig_type & E_NO_DELAY) && EG(current_execute_data)) { + if (EG(user_error_handler_error_reporting) & ZEND_ERROR_HANDLER_NO_DELAY) { + if (EG(exception)) { + /* Promoting this error would override the existing exception, + * but, we want the first exception/error to have precedence. */ + return; + } + zend_object *obj = zend_throw_error_exception( + zend_ce_promoted_error_exception, message, /* code */ 0, type); + zval tmp; + ZVAL_STR_COPY(&tmp, error_filename); + zend_update_property_ex(zend_ce_exception, obj, ZSTR_KNOWN(ZEND_STR_FILE), &tmp); + zval_ptr_dtor(&tmp); + ZVAL_LONG(&tmp, error_lineno); + zend_update_property_ex(zend_ce_exception, obj, ZSTR_KNOWN(ZEND_STR_LINE), &tmp); + return; + } + zend_error_info *info = emalloc(sizeof(zend_error_info)); + info->type = type; + info->lineno = error_lineno; + info->filename = zend_string_copy(error_filename); + info->message = zend_string_copy(message); + info->error_reporting = EG(error_reporting); + zend_hash_next_index_insert_ptr(&EG(delayed_effects), info); + zend_atomic_bool_store_ex(&EG(vm_interrupt), true); + return; + } + // Always clear the last backtrace. zval_ptr_dtor(&EG(last_fatal_error_backtrace)); ZVAL_UNDEF(&EG(last_fatal_error_backtrace)); @@ -1970,6 +2007,9 @@ ZEND_API zend_result zend_execute_script(int type, zval *retval, zend_file_handl zend_result ret = SUCCESS; if (op_array) { zend_execute(op_array, retval); + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_handle_delayed_effects(); + } if (UNEXPECTED(EG(exception))) { if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) { zend_user_exception_handler(); diff --git a/Zend/zend.h b/Zend/zend.h index 0d5303192b57..39e418e845ff 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -130,8 +130,10 @@ typedef struct _zend_error_info { uint32_t lineno; zend_string *filename; zend_string *message; + int error_reporting; } zend_error_info; + struct _zend_inheritance_cache_entry { zend_inheritance_cache_entry *next; zend_class_entry *ce; @@ -386,6 +388,9 @@ extern ZEND_API void (*zend_post_shutdown_cb)(void); extern ZEND_API void (*zend_accel_schedule_restart_hook)(int reason); +/* Callback for loading of not preloaded part of the script */ +extern ZEND_API zend_result (*zend_preload_autoload)(zend_string *filename); + ZEND_API ZEND_COLD void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn_unchecked(int type, const char *format, ...); diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index c19bf2779fbf..a4b9abf36184 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1283,11 +1283,13 @@ ZEND_FUNCTION(set_error_handler) zend_fcall_info fci; zend_fcall_info_cache fcc; zend_long error_type = E_ALL; + bool delay = true; - ZEND_PARSE_PARAMETERS_START(1, 2) + ZEND_PARSE_PARAMETERS_START(1, 3) Z_PARAM_FUNC_OR_NULL(fci, fcc) Z_PARAM_OPTIONAL Z_PARAM_LONG(error_type) + Z_PARAM_BOOL(delay) ZEND_PARSE_PARAMETERS_END(); if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) { @@ -1303,7 +1305,10 @@ ZEND_FUNCTION(set_error_handler) } ZVAL_COPY(&EG(user_error_handler), &(fci.function_name)); - EG(user_error_handler_error_reporting) = (int)error_type; + EG(user_error_handler_error_reporting) = (int)error_type & E_ALL; + if (!delay) { + EG(user_error_handler_error_reporting) |= ZEND_ERROR_HANDLER_NO_DELAY; + } } /* }}} */ diff --git a/Zend/zend_builtin_functions.stub.php b/Zend/zend_builtin_functions.stub.php index 1d405587145d..f4d4bd6cb4c2 100644 --- a/Zend/zend_builtin_functions.stub.php +++ b/Zend/zend_builtin_functions.stub.php @@ -121,7 +121,7 @@ function trigger_error(string $message, int $error_level = E_USER_NOTICE): true function user_error(string $message, int $error_level = E_USER_NOTICE): true {} /** @return callable|null */ -function set_error_handler(?callable $callback, int $error_levels = E_ALL) {} +function set_error_handler(?callable $callback, int $error_levels = E_ALL, bool $delay = true) {} function restore_error_handler(): true {} diff --git a/Zend/zend_builtin_functions_arginfo.h b/Zend/zend_builtin_functions_arginfo.h index b3af43fef340..24510d925f9d 100644 --- a/Zend/zend_builtin_functions_arginfo.h +++ b/Zend/zend_builtin_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit zend_builtin_functions.stub.php instead. - * Stub hash: 64c61862de86d9968930893bf21b516119724064 */ + * Stub hash: 7b23af1724df954be54583a7662d679dd95bc8b4 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_clone, 0, 1, IS_OBJECT, 0) ZEND_ARG_TYPE_INFO(0, object, IS_OBJECT, 0) @@ -148,6 +148,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_set_error_handler, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 1) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, error_levels, IS_LONG, 0, "E_ALL") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, delay, _IS_BOOL, 0, "true") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_restore_error_handler, 0, 0, IS_TRUE, 0) diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 0e31332c97f0..33c750ffe066 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -1015,6 +1015,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, bool nullify_hand uint32_t zend_get_class_fetch_type(const zend_string *name); ZEND_API uint8_t zend_get_call_op(const zend_op *init_op, const zend_function *fbc, bool result_used); ZEND_API bool zend_is_smart_branch(const zend_op *opline); +bool zend_keeps_op1_alive(const zend_op *opline); typedef bool (*zend_auto_global_callback)(zend_string *name); typedef struct _zend_auto_global { diff --git a/Zend/zend_errors.h b/Zend/zend_errors.h index 831e4a9b912a..f3efd50c302d 100644 --- a/Zend/zend_errors.h +++ b/Zend/zend_errors.h @@ -39,6 +39,12 @@ /* Indicates that this usually fatal error should not result in a bailout */ #define E_DONT_BAIL (1<<15L) +/* Indicates that this error should not be delayed */ +#define E_NO_DELAY (1<<16L) + +/* Flag for EG(user_error_handler_error_reporting): Matching errors are promoted to exceptions, and the error handler is called during excepiton handling. */ +#define ZEND_ERROR_HANDLER_NO_DELAY (1<<30) + #define E_ALL (E_ERROR | E_WARNING | E_PARSE | E_NOTICE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE | E_RECOVERABLE_ERROR | E_DEPRECATED | E_USER_DEPRECATED) #define E_CORE (E_CORE_ERROR | E_CORE_WARNING) diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index d23fb647af9d..66e65bb1aa36 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -49,6 +49,7 @@ ZEND_API zend_class_entry *zend_ce_arithmetic_error; ZEND_API zend_class_entry *zend_ce_division_by_zero_error; ZEND_API zend_class_entry *zend_ce_unhandled_match_error; ZEND_API zend_class_entry *zend_ce_request_parse_body_exception; +ZEND_API zend_class_entry *zend_ce_promoted_error_exception; /* Internal pseudo-exception that is not exposed to userland. Throwing this exception *does not* execute finally blocks. */ static zend_class_entry zend_ce_unwind_exit; @@ -166,7 +167,7 @@ ZEND_API ZEND_COLD void zend_throw_exception_internal(zend_object *exception) /* if (exception != NULL) { const zend_object *previous = EG(exception); - if (previous && zend_is_unwind_exit(previous)) { + if (previous && (zend_is_unwind_exit(previous) || zend_is_promoted_error_exception(previous))) { /* Don't replace unwinding exception with different exception. */ OBJ_RELEASE(exception); return; @@ -827,6 +828,9 @@ void zend_register_default_exception(void) /* {{{ */ zend_ce_request_parse_body_exception = register_class_RequestParseBodyException(zend_ce_exception); zend_init_exception_class_entry(zend_ce_request_parse_body_exception); + zend_ce_promoted_error_exception = register_class_PromotedErrorException(zend_ce_error_exception); + zend_init_exception_class_entry(zend_ce_promoted_error_exception); + INIT_CLASS_ENTRY(zend_ce_unwind_exit, "UnwindExit", NULL); INIT_CLASS_ENTRY(zend_ce_graceful_exit, "GracefulExit", NULL); @@ -1063,3 +1067,9 @@ ZEND_API bool zend_is_graceful_exit(const zend_object *ex) { return ex->ce == &zend_ce_graceful_exit; } + +ZEND_API bool zend_is_promoted_error_exception(const zend_object *ex) +{ + return ex->ce == zend_ce_promoted_error_exception; +} + diff --git a/Zend/zend_exceptions.h b/Zend/zend_exceptions.h index f9b472598012..b6dbed4f81f1 100644 --- a/Zend/zend_exceptions.h +++ b/Zend/zend_exceptions.h @@ -38,6 +38,7 @@ extern ZEND_API zend_class_entry *zend_ce_arithmetic_error; extern ZEND_API zend_class_entry *zend_ce_division_by_zero_error; extern ZEND_API zend_class_entry *zend_ce_unhandled_match_error; extern ZEND_API zend_class_entry *zend_ce_request_parse_body_exception; +extern ZEND_API zend_class_entry *zend_ce_promoted_error_exception; ZEND_API void zend_exception_set_previous(zend_object *exception, zend_object *add_previous); @@ -73,6 +74,7 @@ ZEND_API ZEND_COLD void zend_throw_unwind_exit(void); ZEND_API ZEND_COLD void zend_throw_graceful_exit(void); ZEND_API bool zend_is_unwind_exit(const zend_object *ex); ZEND_API bool zend_is_graceful_exit(const zend_object *ex); +ZEND_API bool zend_is_promoted_error_exception(const zend_object *ex); #include "zend_globals.h" diff --git a/Zend/zend_exceptions.stub.php b/Zend/zend_exceptions.stub.php index 86f2838ee912..1dd513665705 100644 --- a/Zend/zend_exceptions.stub.php +++ b/Zend/zend_exceptions.stub.php @@ -81,6 +81,10 @@ public function __construct( final public function getSeverity(): int {} } +class PromotedErrorException extends ErrorException +{ +} + class Error implements Throwable { /** diff --git a/Zend/zend_exceptions_arginfo.h b/Zend/zend_exceptions_arginfo.h index 4706161a09af..7366eb2b2d7f 100644 --- a/Zend/zend_exceptions_arginfo.h +++ b/Zend/zend_exceptions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit zend_exceptions.stub.php instead. - * Stub hash: ba1562ca8fe2fe48c40bc52d10545aa989afd86c */ + * Stub hash: 29f62b734a504e14599e240910b01fd5f44fad60 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Throwable_getMessage, 0, 0, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -207,6 +207,16 @@ static zend_class_entry *register_class_ErrorException(zend_class_entry *class_e return class_entry; } +static zend_class_entry *register_class_PromotedErrorException(zend_class_entry *class_entry_ErrorException) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "PromotedErrorException", NULL); + class_entry = zend_register_internal_class_with_flags(&ce, class_entry_ErrorException, 0); + + return class_entry; +} + static zend_class_entry *register_class_Error(zend_class_entry *class_entry_Throwable) { zend_class_entry ce, *class_entry; diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 4253037fda52..61438383b8df 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2525,6 +2525,83 @@ ZEND_API ZEND_COLD zval* ZEND_FASTCALL zend_undefined_offset_write(HashTable *ht return zend_hash_index_add_new(ht, lval, &EG(uninitialized_zval)); } +ZEND_API zend_never_inline void ZEND_FASTCALL zend_handle_delayed_effects(void) +{ + HashPosition start = EG(delayed_effects).nInternalPointer; + HashPosition pos = start; + HashPosition end = EG(delayed_effects).nNumUsed; + /* Nested calls handle new items */ + EG(delayed_effects).nInternalPointer = end; + +restart:; + + ZEND_ASSERT(HT_IS_PACKED(&EG(delayed_effects))); + + for (; pos < end; pos++) { + zval *val = &EG(delayed_effects).arPacked[pos]; + switch (Z_TYPE_P(val)) { + case IS_PTR: { + zend_error_info *info = Z_PTR_P(val); + ZVAL_NULL(val); + int orig_error_reporting = EG(error_reporting); + EG(error_reporting) = info->error_reporting; + zend_error_zstr_at(info->type | E_NO_DELAY, info->filename, info->lineno, info->message); + EG(error_reporting) = orig_error_reporting; + zend_string_release(info->filename); + zend_string_release(info->message); + efree(info); + break; + } + case IS_OBJECT: { + zend_object *obj = Z_OBJ_P(val); + ZEND_ASSERT(GC_REFCOUNT(obj) == 1); + obj->handlers->dtor_obj(obj); + GC_DELREF(obj); + if (GC_REFCOUNT(obj) == 0) { + zend_objects_store_del(obj); + } + break; + } + default: + ZEND_UNREACHABLE(); + } + } + + if (EG(delayed_effects).nInternalPointer < EG(delayed_effects).nNumUsed) { + /* New items were added during iteration and were not handled */ + pos = EG(delayed_effects).nInternalPointer; + end = EG(delayed_effects).nNumUsed; + EG(delayed_effects).nInternalPointer = end; + goto restart; + } + + if (start == 0) { + zend_hash_clean(&EG(delayed_effects)); + } +} + +ZEND_API void ZEND_FASTCALL zend_discard_delayed_effects(void) +{ + zval *val; + ZEND_HASH_FOREACH_VAL(&EG(delayed_effects), val) { + switch (Z_TYPE_P(val)) { + case IS_PTR: { + zend_error_info *info = Z_PTR_P(val); + zend_string_release(info->filename); + zend_string_release(info->message); + efree(info); + break; + } + case IS_OBJECT: + case IS_NULL: + break; + default: + ZEND_UNREACHABLE(); + } + } ZEND_HASH_FOREACH_END(); + zend_hash_clean(&EG(delayed_effects)); +} + ZEND_API ZEND_COLD zval* ZEND_FASTCALL zend_undefined_index_write(HashTable *ht, zend_string *offset) { zval *retval; @@ -4314,6 +4391,9 @@ ZEND_API void ZEND_FASTCALL zend_free_compiled_variables(zend_execute_data *exec ZEND_API ZEND_COLD void ZEND_FASTCALL zend_fcall_interrupt(zend_execute_data *call) { zend_atomic_bool_store_ex(&EG(vm_interrupt), false); + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_handle_delayed_effects(); + } if (zend_atomic_bool_load_ex(&EG(timed_out))) { zend_timeout(); } else if (zend_interrupt_function) { @@ -5720,6 +5800,7 @@ static zend_always_inline zend_execute_data *_zend_vm_stack_push_call_frame_ex(u if (UNEXPECTED(used_stack > (size_t)(((char*)EG(vm_stack_end)) - (char*)call))) { EX(opline) = opline; /* this is the only difference */ + ZEND_VM_FCALL_INTERRUPT_CHECK(EG(current_execute_data)); call = (zend_execute_data*)zend_vm_stack_extend(used_stack); ZEND_ASSERT_VM_STACK_GLOBAL; zend_vm_init_call_frame(call, call_info | ZEND_CALL_ALLOCATED, func, num_args, object_or_called_scope); @@ -5736,7 +5817,7 @@ static zend_always_inline zend_execute_data *_zend_vm_stack_push_call_frame(uint uint32_t used_stack = zend_vm_calc_used_stack(num_args, func); return _zend_vm_stack_push_call_frame_ex(used_stack, call_info, - func, num_args, object_or_called_scope); + func, num_args, object_or_called_scope EXECUTE_DATA_CC); } /* }}} */ #else # define _zend_vm_stack_push_call_frame_ex zend_vm_stack_push_call_frame_ex @@ -5792,6 +5873,15 @@ static zend_always_inline zend_execute_data *_zend_vm_stack_push_call_frame(uint ZEND_VM_CONTINUE(); \ } while (0) +/* Same but indicate that we are jumping forward, so not interrupt check is performed */ +#define ZEND_VM_JMP_FWD_EX(new_op, check_exception) do { \ + if (check_exception && UNEXPECTED(EG(exception))) { \ + HANDLE_EXCEPTION(); \ + } \ + ZEND_VM_SET_OPCODE_NO_INTERRUPT(new_op); \ + ZEND_VM_CONTINUE(); \ + } while (0) + #define ZEND_VM_JMP(new_op) \ ZEND_VM_JMP_EX(new_op, 1) @@ -5913,6 +6003,53 @@ static zend_always_inline zend_execute_data *_zend_vm_stack_push_call_frame(uint /* This callback disables optimization of "vm_stack_data" variable in VM */ ZEND_API void (ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data) = NULL; +void zend_interrupt_consume(EXECUTE_DATA_D OPLINE_DC) +{ + /* Interrupts are handled before executing opline, but exception handling + * assumes that a throwing opline was executed. + * Here we need to consume inputs and and initialize outputs. */ + + if (opline + && opline->result_type & (IS_TMP_VAR|IS_VAR) + && opline->opcode != ZEND_ADD_ARRAY_ELEMENT + && opline->opcode != ZEND_ADD_ARRAY_UNPACK + && opline->opcode != ZEND_ROPE_INIT + && opline->opcode != ZEND_ROPE_ADD) { + ZVAL_UNDEF(ZEND_CALL_VAR(EG(current_execute_data), opline->result.var)); + } + + if (opline->opcode == ZEND_SEPARATE) { + ZEND_ASSERT(opline->op1.var == opline->result.var); + return; + } + + if ((opline->op1_type & (IS_TMP_VAR|IS_VAR))) { + if (EXPECTED(!zend_keeps_op1_alive(opline))) { + zval_ptr_dtor(EX_VAR(opline->op1.var)); + } + } + + if ((opline->op2_type & (IS_TMP_VAR|IS_VAR))) { + if (UNEXPECTED(opline->opcode == ZEND_FE_FETCH_R + || opline->opcode == ZEND_FE_FETCH_RW)) { + /* OP2 of FE_FETCH is actually a def, not a use. */ + } else { + zval_ptr_dtor(EX_VAR(opline->op2.var)); + } + } + + const zend_op_array *op_array = &EX(func)->op_array; + + if (opline >= op_array->opcodes + && opline - op_array->opcodes < op_array->last) { + const zend_op *next_op = opline + 1; + if (next_op->opcode == ZEND_OP_DATA + && next_op->op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor(EX_VAR(opline->op1.var)); + } + } +} + #include "zend_vm_execute.h" ZEND_API zend_result zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler) diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index ba48b19bcfe1..0aeb2fc61d37 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -99,6 +99,9 @@ ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_cannot_add_element( ZEND_API bool ZEND_FASTCALL zend_asymmetric_property_has_set_access(const zend_property_info *prop_info); ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_asymmetric_visibility_property_modification_error(const zend_property_info *prop_info, const char *operation); +ZEND_API void ZEND_FASTCALL zend_handle_delayed_effects(void); +ZEND_API void ZEND_FASTCALL zend_discard_delayed_effects(void); + ZEND_API bool zend_verify_scalar_type_hint(uint32_t type_mask, zval *arg, bool strict, bool is_internal_arg); ZEND_API zend_never_inline ZEND_COLD void zend_verify_arg_error( const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, const zval *value); @@ -285,6 +288,11 @@ ZEND_API zend_result ZEND_FASTCALL zval_update_constant(zval *pp); ZEND_API zend_result ZEND_FASTCALL zval_update_constant_ex(zval *pp, zend_class_entry *scope); ZEND_API zend_result ZEND_FASTCALL zval_update_constant_with_ctx(zval *pp, zend_class_entry *scope, zend_ast_evaluate_ctx *ctx); +/* Call this to handle the timeout or the interrupt function. It will set + * EG(vm_interrupt) to false. + */ +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_fcall_interrupt(zend_execute_data *call); + /* dedicated Zend executor functions - do not use! */ struct _zend_vm_stack { zval *top; @@ -347,6 +355,9 @@ static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame_ex(ui ZEND_ASSERT_VM_STACK_GLOBAL; if (UNEXPECTED(used_stack > (size_t)(((char*)EG(vm_stack_end)) - (char*)call))) { + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(EG(current_execute_data)); + } call = (zend_execute_data*)zend_vm_stack_extend(used_stack); ZEND_ASSERT_VM_STACK_GLOBAL; zend_vm_init_call_frame(call, call_info | ZEND_CALL_ALLOCATED, func, num_args, object_or_called_scope); @@ -617,11 +628,6 @@ ZEND_API bool zend_verify_property_type(const zend_property_info *info, zval *pr zend_never_inline ZEND_COLD void zend_match_unhandled_error(const zval *value); -/* Call this to handle the timeout or the interrupt function. It will set - * EG(vm_interrupt) to false. - */ -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_fcall_interrupt(zend_execute_data *call); - static zend_always_inline void *zend_get_bad_ptr(void) { ZEND_UNREACHABLE(); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 71e0c56a51c8..08daae807f5d 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -198,6 +198,9 @@ void init_executor(void) /* {{{ */ zend_max_execution_timer_init(); zend_fiber_init(); + + zend_hash_init(&EG(delayed_effects), 0, NULL, NULL, 0); + zend_weakrefs_init(); zend_hash_init(&EG(callable_convert_cache), 8, NULL, ZVAL_PTR_DTOR, 0); @@ -528,6 +531,8 @@ void shutdown_executor(void) /* {{{ */ EG(ht_iterators_used) = 0; zend_shutdown_fpu(); + + zend_discard_delayed_effects(); } /* }}} */ diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 8257df32e831..088c541b8bf1 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -264,7 +264,6 @@ struct _zend_executor_globals { zend_object *exception; const zend_op *opline_before_exception; zend_op exception_op[3]; - struct _zend_module_entry *current_module; bool active; @@ -321,6 +320,7 @@ struct _zend_executor_globals { pid_t pid; struct sigaction oldact; #endif + HashTable delayed_effects; zend_strtod_state strtod_state; diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c index 537cad8a3644..2ef326d63335 100644 --- a/Zend/zend_objects_API.c +++ b/Zend/zend_objects_API.c @@ -174,6 +174,16 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_del(zend_object *object) /* {{{ * if (object->handlers->dtor_obj != zend_objects_destroy_object || object->ce->destructor) { + /* If we are inside the VM, delay the destructor call to a safe point. */ + if (EG(current_execute_data)) { + /* Keep object alive until the delayed destructor runs. */ + GC_SET_REFCOUNT(object, 1); + zval zv; + ZVAL_OBJ(&zv, object); + zend_hash_next_index_insert(&EG(delayed_effects), &zv); + zend_atomic_bool_store_ex(&EG(vm_interrupt), true); + return; + } GC_SET_REFCOUNT(object, 1); object->handlers->dtor_obj(object); GC_DELREF(object); diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 0c6b22473514..82fd8e0cde5d 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -901,7 +901,7 @@ static bool is_fake_def(zend_op *opline) { || opline->opcode == ZEND_ADD_ARRAY_UNPACK; } -static bool keeps_op1_alive(zend_op *opline) { +bool zend_keeps_op1_alive(const zend_op *opline) { /* These opcodes don't consume their OP1 operand, * it is later freed by something else. */ if (opline->opcode == ZEND_CASE @@ -992,7 +992,7 @@ static void zend_calc_live_ranges( if ((opline->op1_type & (IS_TMP_VAR|IS_VAR))) { uint32_t var_num = EX_VAR_TO_NUM(opline->op1.var) - var_offset; if (EXPECTED(last_use[var_num] == (uint32_t) -1)) { - if (EXPECTED(!keeps_op1_alive(opline))) { + if (EXPECTED(!zend_keeps_op1_alive(opline))) { /* OP_DATA is really part of the previous opcode. */ last_use[var_num] = opnum - (opline->opcode == ZEND_OP_DATA); } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 1de7a7cd4195..cf7d949867fb 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3004,9 +3004,14 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY) } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } + EG(vm_stack_top) = (zval*)execute_data; execute_data = EX(prev_execute_data); + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(execute_data); + } + if (UNEXPECTED(EG(exception) != NULL)) { zend_rethrow_exception(execute_data); HANDLE_EXCEPTION_LEAVE(); @@ -3043,6 +3048,10 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY) execute_data = EX(prev_execute_data); zend_vm_stack_free_call_frame_ex(call_info, old_execute_data); + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(execute_data); + } + if (UNEXPECTED(EG(exception) != NULL)) { zend_rethrow_exception(execute_data); HANDLE_EXCEPTION_LEAVE(); @@ -3069,6 +3078,11 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY) ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_NEEDS_REATTACH); } } + + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(execute_data); + } + if (UNEXPECTED(EG(exception) != NULL)) { zend_rethrow_exception(execute_data); HANDLE_EXCEPTION_LEAVE(); @@ -3095,6 +3109,11 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY) if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } + + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(EG(current_execute_data)); + } + ZEND_VM_RETURN(); } else /* if (call_kind == ZEND_CALL_TOP_CODE) */ { zend_array *symbol_table = EX(symbol_table); @@ -3120,6 +3139,11 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY) } } EG(current_execute_data) = EX(prev_execute_data); + + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(EG(current_execute_data)); + } + ZEND_VM_RETURN(); } } @@ -4611,9 +4635,24 @@ ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|CV, ANY, SPEC(OBSERVER)) } } } + +#if 0 + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_handle_delayed_effects(); + if (EG(exception)) { + ZEND_VM_ENTER(); + } + } + /* Do not reset EG(vm_interrupt) as it may have been set for other + * reasons */ + } +#endif + ZEND_OBSERVER_SAVE_OPLINE(); ZEND_OBSERVER_FCALL_END(execute_data, return_value); ZEND_OBSERVER_FREE_RETVAL(); + ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); } @@ -8152,7 +8191,7 @@ ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper, ANY, ANY, uint32_t try_ca if (op_num < try_catch->catch_op && ex) { /* Go to catch block */ cleanup_live_vars(execute_data, op_num, try_catch->catch_op); - ZEND_VM_JMP_EX(&EX(func)->op_array.opcodes[try_catch->catch_op], 0); + ZEND_VM_JMP_FWD_EX(&EX(func)->op_array.opcodes[try_catch->catch_op], 0); } else if (op_num < try_catch->finally_op) { if (ex && zend_is_unwind_exit(ex)) { @@ -8166,7 +8205,7 @@ ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper, ANY, ANY, uint32_t try_ca Z_OBJ_P(fast_call) = EG(exception); EG(exception) = NULL; Z_OPLINE_NUM_P(fast_call) = (uint32_t)-1; - ZEND_VM_JMP_EX(&EX(func)->op_array.opcodes[try_catch->finally_op], 0); + ZEND_VM_JMP_FWD_EX(&EX(func)->op_array.opcodes[try_catch->finally_op], 0); } else if (op_num < try_catch->finally_end) { zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[try_catch->finally_end].op1.var); @@ -8220,11 +8259,69 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) { const zend_op *throw_op = EG(opline_before_exception); + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_object *orig_exception = EG(exception); + EX(opline) = EG(opline_before_exception); + EG(exception) = NULL; + + zend_handle_delayed_effects(); + + if (EG(exception)) { + zend_exception_set_previous(EG(exception), orig_exception); + } else { + EG(exception) = orig_exception; + EX(opline) = EG(exception_op); + } + } + + if (throw_op && EG(exception)->ce == zend_ce_promoted_error_exception) { + zend_object *promoted = EG(exception); + + zval *severity_zv = zend_read_property_ex( + zend_ce_error_exception, promoted, ZSTR_KNOWN(ZEND_STR_SEVERITY), /* silent */ 1, NULL); + zval *message_zv = zend_read_property_ex( + zend_ce_exception, promoted, ZSTR_KNOWN(ZEND_STR_MESSAGE), 1, NULL); + zval *file_zv = zend_read_property_ex( + zend_ce_exception, promoted, ZSTR_KNOWN(ZEND_STR_FILE), 1, NULL); + zval *line_zv = zend_read_property_ex( + zend_ce_exception, promoted, ZSTR_KNOWN(ZEND_STR_LINE), 1, NULL); + + int error_type = (int) Z_LVAL_P(severity_zv) & E_ALL; + if (!error_type) { + error_type = E_ERROR; + } + zend_string *error_message = zend_string_copy(Z_STR_P(message_zv)); + zend_string *error_file = zend_string_copy(Z_STR_P(file_zv)); + zend_long error_line = Z_LVAL_P(line_zv); + + EG(exception) = NULL; + EX(opline) = throw_op; + zend_error_zstr_at(error_type | E_NO_DELAY, error_file, error_line, error_message); + + zend_string_release(error_file); + zend_string_release(error_message); + + if (!EG(exception)) { + EG(exception) = promoted; + } else { + OBJ_RELEASE(promoted); + } + } + /* Exception was thrown before executing any op */ if (UNEXPECTED(!throw_op)) { ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper, try_catch_offset, -1, op_num, 0); } + /* Exception was thrown from the ZEND_DO_FCALL interrupt handler just + * before entering EG(call_trampoline_op). */ + if (UNEXPECTED(throw_op == &EG(call_trampoline_op))) { + ZEND_ASSERT(EX(func)->op_array.opcodes == &EG(call_trampoline_op)); + zend_string_release_ex(EX(func)->op_array.function_name, 0); + zend_free_trampoline(EX(func)); + ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper, try_catch_offset, -1, op_num, 0); + } + uint32_t throw_op_num = throw_op - EX(func)->op_array.opcodes; uint32_t current_try_catch_offset = -1; @@ -10630,25 +10727,25 @@ ZEND_VM_HELPER(zend_interrupt_helper, ANY, ANY) #else SAVE_OPLINE(); #endif + + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_handle_delayed_effects(); + } if (zend_atomic_bool_load_ex(&EG(timed_out))) { zend_timeout(); - } else if (zend_interrupt_function) { + } + if (zend_interrupt_function) { zend_interrupt_function(execute_data); - if (EG(exception)) { - /* We have to UNDEF result, because ZEND_HANDLE_EXCEPTION is going to free it */ - const zend_op *throw_op = EG(opline_before_exception); - - if (throw_op - && throw_op->result_type & (IS_TMP_VAR|IS_VAR) - && throw_op->opcode != ZEND_ADD_ARRAY_ELEMENT - && throw_op->opcode != ZEND_ADD_ARRAY_UNPACK - && throw_op->opcode != ZEND_ROPE_INIT - && throw_op->opcode != ZEND_ROPE_ADD) { - ZVAL_UNDEF(ZEND_CALL_VAR(EG(current_execute_data), throw_op->result.var)); - - } - } + } + if (UNEXPECTED(EG(exception))) { + // if (EG(opline_before_exception) == opline) { + zend_interrupt_consume(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + // } + LOAD_OPLINE(); + } + if (zend_interrupt_function) { ZEND_VM_ENTER(); + } else { + ZEND_VM_CONTINUE(); } - ZEND_VM_CONTINUE(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 5b52f1941845..d31da1588be9 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1169,9 +1169,14 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } + EG(vm_stack_top) = (zval*)execute_data; execute_data = EX(prev_execute_data); + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(execute_data); + } + if (UNEXPECTED(EG(exception) != NULL)) { zend_rethrow_exception(execute_data); HANDLE_EXCEPTION_LEAVE(); @@ -1208,6 +1213,10 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV execute_data = EX(prev_execute_data); zend_vm_stack_free_call_frame_ex(call_info, old_execute_data); + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(execute_data); + } + if (UNEXPECTED(EG(exception) != NULL)) { zend_rethrow_exception(execute_data); HANDLE_EXCEPTION_LEAVE(); @@ -1234,6 +1243,11 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_NEEDS_REATTACH); } } + + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(execute_data); + } + if (UNEXPECTED(EG(exception) != NULL)) { zend_rethrow_exception(execute_data); HANDLE_EXCEPTION_LEAVE(); @@ -1260,6 +1274,11 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } + + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(EG(current_execute_data)); + } + ZEND_VM_RETURN(); } else /* if (call_kind == ZEND_CALL_TOP_CODE) */ { zend_array *symbol_table = EX(symbol_table); @@ -1285,6 +1304,11 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV } } EG(current_execute_data) = EX(prev_execute_data); + + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(EG(current_execute_data)); + } + ZEND_VM_RETURN(); } } @@ -3331,7 +3355,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_ if (op_num < try_catch->catch_op && ex) { /* Go to catch block */ cleanup_live_vars(execute_data, op_num, try_catch->catch_op); - ZEND_VM_JMP_EX(&EX(func)->op_array.opcodes[try_catch->catch_op], 0); + ZEND_VM_JMP_FWD_EX(&EX(func)->op_array.opcodes[try_catch->catch_op], 0); } else if (op_num < try_catch->finally_op) { if (ex && zend_is_unwind_exit(ex)) { @@ -3345,7 +3369,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_ Z_OBJ_P(fast_call) = EG(exception); EG(exception) = NULL; Z_OPLINE_NUM_P(fast_call) = (uint32_t)-1; - ZEND_VM_JMP_EX(&EX(func)->op_array.opcodes[try_catch->finally_op], 0); + ZEND_VM_JMP_FWD_EX(&EX(func)->op_array.opcodes[try_catch->finally_op], 0); } else if (op_num < try_catch->finally_end) { zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[try_catch->finally_end].op1.var); @@ -3399,11 +3423,69 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_HANDLE_EXCEPT { const zend_op *throw_op = EG(opline_before_exception); + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_object *orig_exception = EG(exception); + EX(opline) = EG(opline_before_exception); + EG(exception) = NULL; + + zend_handle_delayed_effects(); + + if (EG(exception)) { + zend_exception_set_previous(EG(exception), orig_exception); + } else { + EG(exception) = orig_exception; + EX(opline) = EG(exception_op); + } + } + + if (throw_op && EG(exception)->ce == zend_ce_promoted_error_exception) { + zend_object *promoted = EG(exception); + + zval *severity_zv = zend_read_property_ex( + zend_ce_error_exception, promoted, ZSTR_KNOWN(ZEND_STR_SEVERITY), /* silent */ 1, NULL); + zval *message_zv = zend_read_property_ex( + zend_ce_exception, promoted, ZSTR_KNOWN(ZEND_STR_MESSAGE), 1, NULL); + zval *file_zv = zend_read_property_ex( + zend_ce_exception, promoted, ZSTR_KNOWN(ZEND_STR_FILE), 1, NULL); + zval *line_zv = zend_read_property_ex( + zend_ce_exception, promoted, ZSTR_KNOWN(ZEND_STR_LINE), 1, NULL); + + int error_type = (int) Z_LVAL_P(severity_zv) & E_ALL; + if (!error_type) { + error_type = E_ERROR; + } + zend_string *error_message = zend_string_copy(Z_STR_P(message_zv)); + zend_string *error_file = zend_string_copy(Z_STR_P(file_zv)); + zend_long error_line = Z_LVAL_P(line_zv); + + EG(exception) = NULL; + EX(opline) = throw_op; + zend_error_zstr_at(error_type | E_NO_DELAY, error_file, error_line, error_message); + + zend_string_release(error_file); + zend_string_release(error_message); + + if (!EG(exception)) { + EG(exception) = promoted; + } else { + OBJ_RELEASE(promoted); + } + } + /* Exception was thrown before executing any op */ if (UNEXPECTED(!throw_op)) { ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX -1, 0)); } + /* Exception was thrown from the ZEND_DO_FCALL interrupt handler just + * before entering EG(call_trampoline_op). */ + if (UNEXPECTED(throw_op == &EG(call_trampoline_op))) { + ZEND_ASSERT(EX(func)->op_array.opcodes == &EG(call_trampoline_op)); + zend_string_release_ex(EX(func)->op_array.function_name, 0); + zend_free_trampoline(EX(func)); + ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX -1, 0)); + } + uint32_t throw_op_num = throw_op - EX(func)->op_array.opcodes; uint32_t current_try_catch_offset = -1; @@ -4038,27 +4120,27 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV #else SAVE_OPLINE(); #endif + + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_handle_delayed_effects(); + } if (zend_atomic_bool_load_ex(&EG(timed_out))) { zend_timeout(); - } else if (zend_interrupt_function) { + } + if (zend_interrupt_function) { zend_interrupt_function(execute_data); - if (EG(exception)) { - /* We have to UNDEF result, because ZEND_HANDLE_EXCEPTION is going to free it */ - const zend_op *throw_op = EG(opline_before_exception); - - if (throw_op - && throw_op->result_type & (IS_TMP_VAR|IS_VAR) - && throw_op->opcode != ZEND_ADD_ARRAY_ELEMENT - && throw_op->opcode != ZEND_ADD_ARRAY_UNPACK - && throw_op->opcode != ZEND_ROPE_INIT - && throw_op->opcode != ZEND_ROPE_ADD) { - ZVAL_UNDEF(ZEND_CALL_VAR(EG(current_execute_data), throw_op->result.var)); - - } - } + } + if (UNEXPECTED(EG(exception))) { + // if (EG(opline_before_exception) == opline) { + zend_interrupt_consume(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + // } + LOAD_OPLINE(); + } + if (zend_interrupt_function) { ZEND_VM_ENTER(); + } else { + ZEND_VM_CONTINUE(); } - ZEND_VM_CONTINUE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { @@ -4807,6 +4889,19 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_R } } +#if 0 + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_handle_delayed_effects(); + if (EG(exception)) { + ZEND_VM_ENTER(); + } + } + /* Do not reset EG(vm_interrupt) as it may have been set for other + * reasons */ + } +#endif + @@ -4887,9 +4982,24 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ } } } + +#if 0 + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_handle_delayed_effects(); + if (EG(exception)) { + ZEND_VM_ENTER(); + } + } + /* Do not reset EG(vm_interrupt) as it may have been set for other + * reasons */ + } +#endif + SAVE_OPLINE(); zend_observer_fcall_end(execute_data, return_value); if (return_value == &observer_retval) { zval_ptr_dtor_nogc(&observer_retval); }; + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -17180,6 +17290,19 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_R } } +#if 0 + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_handle_delayed_effects(); + if (EG(exception)) { + ZEND_VM_ENTER(); + } + } + /* Do not reset EG(vm_interrupt) as it may have been set for other + * reasons */ + } +#endif + @@ -39845,6 +39968,19 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_R } } +#if 0 + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_handle_delayed_effects(); + if (EG(exception)) { + ZEND_VM_ENTER(); + } + } + /* Do not reset EG(vm_interrupt) as it may have been set for other + * reasons */ + } +#endif + @@ -53959,9 +54095,14 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } + EG(vm_stack_top) = (zval*)execute_data; execute_data = EX(prev_execute_data); + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(execute_data); + } + if (UNEXPECTED(EG(exception) != NULL)) { zend_rethrow_exception(execute_data); HANDLE_EXCEPTION_LEAVE(); @@ -53998,6 +54139,10 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend execute_data = EX(prev_execute_data); zend_vm_stack_free_call_frame_ex(call_info, old_execute_data); + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(execute_data); + } + if (UNEXPECTED(EG(exception) != NULL)) { zend_rethrow_exception(execute_data); HANDLE_EXCEPTION_LEAVE(); @@ -54024,6 +54169,11 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_NEEDS_REATTACH); } } + + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(execute_data); + } + if (UNEXPECTED(EG(exception) != NULL)) { zend_rethrow_exception(execute_data); HANDLE_EXCEPTION_LEAVE(); @@ -54050,6 +54200,11 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } + + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(EG(current_execute_data)); + } + ZEND_VM_RETURN(); } else /* if (call_kind == ZEND_CALL_TOP_CODE) */ { zend_array *symbol_table = EX(symbol_table); @@ -54075,6 +54230,11 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend } } EG(current_execute_data) = EX(prev_execute_data); + + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(EG(current_execute_data)); + } + ZEND_VM_RETURN(); } } @@ -56073,11 +56233,69 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_HANDLE_EXCEPTION_S { const zend_op *throw_op = EG(opline_before_exception); + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_object *orig_exception = EG(exception); + EX(opline) = EG(opline_before_exception); + EG(exception) = NULL; + + zend_handle_delayed_effects(); + + if (EG(exception)) { + zend_exception_set_previous(EG(exception), orig_exception); + } else { + EG(exception) = orig_exception; + EX(opline) = EG(exception_op); + } + } + + if (throw_op && EG(exception)->ce == zend_ce_promoted_error_exception) { + zend_object *promoted = EG(exception); + + zval *severity_zv = zend_read_property_ex( + zend_ce_error_exception, promoted, ZSTR_KNOWN(ZEND_STR_SEVERITY), /* silent */ 1, NULL); + zval *message_zv = zend_read_property_ex( + zend_ce_exception, promoted, ZSTR_KNOWN(ZEND_STR_MESSAGE), 1, NULL); + zval *file_zv = zend_read_property_ex( + zend_ce_exception, promoted, ZSTR_KNOWN(ZEND_STR_FILE), 1, NULL); + zval *line_zv = zend_read_property_ex( + zend_ce_exception, promoted, ZSTR_KNOWN(ZEND_STR_LINE), 1, NULL); + + int error_type = (int) Z_LVAL_P(severity_zv) & E_ALL; + if (!error_type) { + error_type = E_ERROR; + } + zend_string *error_message = zend_string_copy(Z_STR_P(message_zv)); + zend_string *error_file = zend_string_copy(Z_STR_P(file_zv)); + zend_long error_line = Z_LVAL_P(line_zv); + + EG(exception) = NULL; + EX(opline) = throw_op; + zend_error_zstr_at(error_type | E_NO_DELAY, error_file, error_line, error_message); + + zend_string_release(error_file); + zend_string_release(error_message); + + if (!EG(exception)) { + EG(exception) = promoted; + } else { + OBJ_RELEASE(promoted); + } + } + /* Exception was thrown before executing any op */ if (UNEXPECTED(!throw_op)) { ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX -1, 0)); } + /* Exception was thrown from the ZEND_DO_FCALL interrupt handler just + * before entering EG(call_trampoline_op). */ + if (UNEXPECTED(throw_op == &EG(call_trampoline_op))) { + ZEND_ASSERT(EX(func)->op_array.opcodes == &EG(call_trampoline_op)); + zend_string_release_ex(EX(func)->op_array.function_name, 0); + zend_free_trampoline(EX(func)); + ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX -1, 0)); + } + uint32_t throw_op_num = throw_op - EX(func)->op_array.opcodes; uint32_t current_try_catch_offset = -1; @@ -56712,27 +56930,27 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend #else SAVE_OPLINE(); #endif + + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_handle_delayed_effects(); + } if (zend_atomic_bool_load_ex(&EG(timed_out))) { zend_timeout(); - } else if (zend_interrupt_function) { + } + if (zend_interrupt_function) { zend_interrupt_function(execute_data); - if (EG(exception)) { - /* We have to UNDEF result, because ZEND_HANDLE_EXCEPTION is going to free it */ - const zend_op *throw_op = EG(opline_before_exception); - - if (throw_op - && throw_op->result_type & (IS_TMP_VAR|IS_VAR) - && throw_op->opcode != ZEND_ADD_ARRAY_ELEMENT - && throw_op->opcode != ZEND_ADD_ARRAY_UNPACK - && throw_op->opcode != ZEND_ROPE_INIT - && throw_op->opcode != ZEND_ROPE_ADD) { - ZVAL_UNDEF(ZEND_CALL_VAR(EG(current_execute_data), throw_op->result.var)); - - } - } + } + if (UNEXPECTED(EG(exception))) { + // if (EG(opline_before_exception) == opline) { + zend_interrupt_consume(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + // } + LOAD_OPLINE(); + } + if (zend_interrupt_function) { ZEND_VM_ENTER(); + } else { + ZEND_VM_CONTINUE(); } - ZEND_VM_CONTINUE(); } static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { @@ -57481,6 +57699,19 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_RETURN } } +#if 0 + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_handle_delayed_effects(); + if (EG(exception)) { + ZEND_VM_ENTER(); + } + } + /* Do not reset EG(vm_interrupt) as it may have been set for other + * reasons */ + } +#endif + @@ -57561,9 +57792,24 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_RETUR } } } + +#if 0 + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_handle_delayed_effects(); + if (EG(exception)) { + ZEND_VM_ENTER(); + } + } + /* Do not reset EG(vm_interrupt) as it may have been set for other + * reasons */ + } +#endif + SAVE_OPLINE(); zend_observer_fcall_end(execute_data, return_value); if (return_value == &observer_retval) { zval_ptr_dtor_nogc(&observer_retval); }; + ZEND_VM_DISPATCH_TO_LEAVE_HELPER(zend_leave_helper_SPEC_TAILCALL); } @@ -69752,6 +69998,19 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_RETURN } } +#if 0 + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_handle_delayed_effects(); + if (EG(exception)) { + ZEND_VM_ENTER(); + } + } + /* Do not reset EG(vm_interrupt) as it may have been set for other + * reasons */ + } +#endif + @@ -92317,6 +92576,19 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_RETURN } } +#if 0 + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_handle_delayed_effects(); + if (EG(exception)) { + ZEND_VM_ENTER(); + } + } + /* Do not reset EG(vm_interrupt) as it may have been set for other + * reasons */ + } +#endif + @@ -106265,7 +106537,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX z if (op_num < try_catch->catch_op && ex) { /* Go to catch block */ cleanup_live_vars(execute_data, op_num, try_catch->catch_op); - ZEND_VM_JMP_EX(&EX(func)->op_array.opcodes[try_catch->catch_op], 0); + ZEND_VM_JMP_FWD_EX(&EX(func)->op_array.opcodes[try_catch->catch_op], 0); } else if (op_num < try_catch->finally_op) { if (ex && zend_is_unwind_exit(ex)) { @@ -106279,7 +106551,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX z Z_OBJ_P(fast_call) = EG(exception); EG(exception) = NULL; Z_OPLINE_NUM_P(fast_call) = (uint32_t)-1; - ZEND_VM_JMP_EX(&EX(func)->op_array.opcodes[try_catch->finally_op], 0); + ZEND_VM_JMP_FWD_EX(&EX(func)->op_array.opcodes[try_catch->finally_op], 0); } else if (op_num < try_catch->finally_end) { zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[try_catch->finally_end].op1.var); @@ -110286,9 +110558,14 @@ ZEND_API void execute_ex(zend_execute_data *ex) } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } + EG(vm_stack_top) = (zval*)execute_data; execute_data = EX(prev_execute_data); + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(execute_data); + } + if (UNEXPECTED(EG(exception) != NULL)) { zend_rethrow_exception(execute_data); HANDLE_EXCEPTION_LEAVE(); @@ -110325,6 +110602,10 @@ ZEND_API void execute_ex(zend_execute_data *ex) execute_data = EX(prev_execute_data); zend_vm_stack_free_call_frame_ex(call_info, old_execute_data); + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(execute_data); + } + if (UNEXPECTED(EG(exception) != NULL)) { zend_rethrow_exception(execute_data); HANDLE_EXCEPTION_LEAVE(); @@ -110351,6 +110632,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_NEEDS_REATTACH); } } + + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(execute_data); + } + if (UNEXPECTED(EG(exception) != NULL)) { zend_rethrow_exception(execute_data); HANDLE_EXCEPTION_LEAVE(); @@ -110377,6 +110663,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } + + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(EG(current_execute_data)); + } + ZEND_VM_RETURN(); } else /* if (call_kind == ZEND_CALL_TOP_CODE) */ { zend_array *symbol_table = EX(symbol_table); @@ -110402,6 +110693,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } EG(current_execute_data) = EX(prev_execute_data); + + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + zend_fcall_interrupt(EG(current_execute_data)); + } + ZEND_VM_RETURN(); } } @@ -110787,6 +111083,19 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } +#if 0 + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_handle_delayed_effects(); + if (EG(exception)) { + ZEND_VM_ENTER(); + } + } + /* Do not reset EG(vm_interrupt) as it may have been set for other + * reasons */ + } +#endif + @@ -110869,9 +111178,24 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } } + +#if 0 + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_handle_delayed_effects(); + if (EG(exception)) { + ZEND_VM_ENTER(); + } + } + /* Do not reset EG(vm_interrupt) as it may have been set for other + * reasons */ + } +#endif + SAVE_OPLINE(); zend_observer_fcall_end(execute_data, return_value); if (return_value == &observer_retval) { zval_ptr_dtor_nogc(&observer_retval); }; + goto zend_leave_helper_SPEC_LABEL; } @@ -112501,6 +112825,19 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } +#if 0 + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_handle_delayed_effects(); + if (EG(exception)) { + ZEND_VM_ENTER(); + } + } + /* Do not reset EG(vm_interrupt) as it may have been set for other + * reasons */ + } +#endif + @@ -114375,6 +114712,19 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } +#if 0 + if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { + if (zend_hash_num_elements(&EG(delayed_effects))) { + zend_handle_delayed_effects(); + if (EG(exception)) { + ZEND_VM_ENTER(); + } + } + /* Do not reset EG(vm_interrupt) as it may have been set for other + * reasons */ + } +#endif + diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 8e65bc0a28ea..8c739e6afefc 100755 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -2027,7 +2027,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"#define HANDLE_EXCEPTION() ZEND_ASSERT(EG(exception)); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n"); out($f,"#define HANDLE_EXCEPTION_LEAVE() ZEND_ASSERT(EG(exception)); LOAD_OPLINE(); ZEND_VM_LEAVE()\n"); out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG)\n"); - out($f,"# define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n"); + out($f,"# define ZEND_VM_ENTER_EX() ZEND_VM_CONTINUE()\n"); out($f,"# define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX()\n"); out($f,"# define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); out($f,"#elif defined(ZEND_VM_IP_GLOBAL_REG)\n"); @@ -2074,7 +2074,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"#define HANDLE_EXCEPTION_LEAVE() ZEND_ASSERT(EG(exception)); LOAD_OPLINE(); ZEND_VM_LEAVE()\n"); out($f,"#define ZEND_VM_CONTINUE() goto zend_vm_continue\n"); out($f,"#define ZEND_VM_RETURN() return\n"); - out($f,"#define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n"); + out($f,"#define ZEND_VM_ENTER_EX() ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX()\n"); out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_INTERRUPT() goto zend_interrupt_helper".($spec?"_SPEC":"").";\n"); @@ -2105,7 +2105,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) } out($f,"#define ZEND_VM_CONTINUE() goto *(void**)(OPLINE->handler)\n"); out($f,"#define ZEND_VM_RETURN() return\n"); - out($f,"#define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n"); + out($f,"#define ZEND_VM_ENTER_EX() ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX()\n"); out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_INTERRUPT() goto zend_interrupt_helper".($spec?"_SPEC":"").";\n"); @@ -2157,7 +2157,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f," } while (0)\n"); out($f,"# define ZEND_VM_DISPATCH_TO_LEAVE_HELPER(helper) opline = &call_leave_op; SAVE_OPLINE(); ZEND_VM_CONTINUE()\n"); out($f,"# define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))\n"); - out($f,"# define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n"); + out($f,"# define ZEND_VM_ENTER_EX() ZEND_VM_CONTINUE()\n"); out($f,"# define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); out($f,"\n"); out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_interrupt_helper".($spec?"_SPEC":"")."_TAILCALL(ZEND_OPCODE_HANDLER_ARGS);\n"); diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index 64a48068f378..43dd8f6ff263 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -1009,7 +1009,8 @@ static zval* ZEND_FASTCALL zend_jit_fetch_dim_rw_helper(zend_array *ht, zval *di return retval; num_undef: - return zend_undefined_offset_write(ht, hval); + retval = zend_undefined_offset_write(ht, hval); + return retval; } static zval* ZEND_FASTCALL zend_jit_fetch_dim_w_helper(zend_array *ht, zval *dim) diff --git a/ext/opcache/tests/jit/assign_dim_op_001.phpt b/ext/opcache/tests/jit/assign_dim_op_001.phpt index c5b057e92603..08b77a21b921 100644 --- a/ext/opcache/tests/jit/assign_dim_op_001.phpt +++ b/ext/opcache/tests/jit/assign_dim_op_001.phpt @@ -4,6 +4,7 @@ JIT ASSIGN_DIM_OP: 001 opcache.enable=1 opcache.enable_cli=1 opcache.file_update_protection=0 +opcache.jit=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/jit/fetch_dim_rw_001.phpt b/ext/opcache/tests/jit/fetch_dim_rw_001.phpt index 9362c4407b26..ed2967fa4b42 100644 --- a/ext/opcache/tests/jit/fetch_dim_rw_001.phpt +++ b/ext/opcache/tests/jit/fetch_dim_rw_001.phpt @@ -4,6 +4,7 @@ JIT FETCH_DIM_RW: 001 opcache.enable=1 opcache.enable_cli=1 opcache.file_update_protection=0 +opcache.jit=0 ;opcache.jit_debug=257 --EXTENSIONS-- opcache diff --git a/ext/opcache/tests/jit/fetch_dim_rw_002.phpt b/ext/opcache/tests/jit/fetch_dim_rw_002.phpt index 068b90e6a2fc..32ca0a55a9a8 100644 --- a/ext/opcache/tests/jit/fetch_dim_rw_002.phpt +++ b/ext/opcache/tests/jit/fetch_dim_rw_002.phpt @@ -4,6 +4,7 @@ JIT FETCH_DIM_RW: 002 opcache.enable=1 opcache.enable_cli=1 opcache.file_update_protection=0 +opcache.jit=0 --FILE--