From 1c94ff0595bbe6f3df8058aff7252bda09dc4a15 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 9 Mar 2015 13:57:15 +0100 Subject: [PATCH] Implement engine exceptions RFC: https://wiki.php.net/rfc/engine_exceptions_for_php7 Pending changes regarding naming of BaseException and whether it should be an interface. --- Zend/tests/030.phpt | 6 +- Zend/tests/arg_unpack/string_keys.phpt | 16 +- Zend/tests/bug37251.phpt | 14 +- Zend/tests/bug48693.phpt | 43 +- Zend/tests/bug64135.phpt | 2 +- Zend/tests/bug64966.phpt | 21 +- Zend/tests/closure_031.phpt | 7 +- Zend/tests/exception_010.phpt | 14 +- Zend/tests/exception_before_fatal.phpt | 14 +- Zend/tests/generators/bug67497.phpt | 5 +- .../methods-on-non-objects-args-catch.phpt | 18 - .../methods-on-non-objects-array-access.phpt | 18 - ...methods-on-non-objects-array-creation.phpt | 35 - Zend/tests/methods-on-non-objects-as-arg.phpt | 47 - Zend/tests/methods-on-non-objects-catch.phpt | 7 +- Zend/tests/methods-on-non-objects-chain.phpt | 22 - Zend/tests/methods-on-non-objects-concat.phpt | 18 - .../tests/methods-on-non-objects-dynamic.phpt | 23 - Zend/tests/methods-on-non-objects-eval.phpt | 18 - .../tests/methods-on-non-objects-in-echo.phpt | 18 - ...thods-on-non-objects-nested-calls-dyn.phpt | 37 - ...thods-on-non-objects-nested-calls-new.phpt | 37 - ...ods-on-non-objects-nested-calls-nonct.phpt | 43 - ...ethods-on-non-objects-nested-calls-ns.phpt | 26 - ...ds-on-non-objects-nested-calls-static.phpt | 33 - .../methods-on-non-objects-nested-calls.phpt | 47 - .../methods-on-non-objects-return-unused.phpt | 17 - Zend/tests/methods-on-non-objects-throw.phpt | 29 - Zend/tests/methods-on-non-objects-usort.phpt | 7 +- .../variadic/typehint_suppressed_error.phpt | 25 +- Zend/zend.c | 17 +- Zend/zend_closures.c | 8 +- Zend/zend_errors.h | 2 + Zend/zend_exceptions.c | 171 +- Zend/zend_exceptions.h | 3 + Zend/zend_execute.c | 41 +- Zend/zend_generators.c | 2 +- Zend/zend_vm_def.h | 421 ++- Zend/zend_vm_execute.h | 2966 +++++++++++------ Zend/zend_vm_gen.php | 26 +- ext/date/tests/timezone_offset_get_error.phpt | 75 +- .../tests/timezone_offset_get_variation1.phpt | 34 +- .../tests/timezone_offset_get_variation2.phpt | 34 +- ext/dom/tests/dom003.phpt | 6 +- ext/dom/tests/dom_set_attr_node.phpt | 6 +- ext/intl/tests/badargs.phpt | 6 +- .../tests/calendar_before_after_error.phpt | 56 +- ext/intl/tests/calendar_equals_error.phpt | 46 +- ..._Least_Greatest_Minimum_Maximum_error.phpt | 40 +- ...r_get_getActualMaximum_Minumum_error2.phpt | 84 +- .../tests/calendar_isEquivalentTo_error.phpt | 51 +- .../tests/calendar_setTimeZone_error.phpt | 27 +- .../tests/timezone_hasSameRules_error.phpt | 26 +- ext/mysqli/tests/mysqli_fetch_object.phpt | 5 +- ext/mysqli/tests/mysqli_fetch_object_oo.phpt | 38 +- .../ReflectionMethod_invokeArgs_error2.phpt | 6 +- ext/session/tests/bug60634_error_1.phpt | 1 - ext/simplexml/tests/bug37565.phpt | 14 +- ext/soap/soap.c | 71 +- ext/soap/tests/server014.phpt | 1 + .../tests/CallbackFilterIteratorTest-002.phpt | 3 +- ext/spl/tests/iterator_042.phpt | 8 +- ext/spl/tests/spl_004.phpt | 8 +- ext/standard/tests/file/bug38450_3.phpt | 2 + .../tests/general_functions/bug47857.phpt | 2 +- main/main.c | 7 + sapi/cli/tests/005.phpt | 4 +- tests/classes/type_hinting_004.phpt | 136 +- tests/lang/catchable_error_002.phpt | 20 +- 69 files changed, 2953 insertions(+), 2188 deletions(-) delete mode 100644 Zend/tests/methods-on-non-objects-args-catch.phpt delete mode 100755 Zend/tests/methods-on-non-objects-array-access.phpt delete mode 100755 Zend/tests/methods-on-non-objects-array-creation.phpt delete mode 100755 Zend/tests/methods-on-non-objects-as-arg.phpt delete mode 100644 Zend/tests/methods-on-non-objects-chain.phpt delete mode 100755 Zend/tests/methods-on-non-objects-concat.phpt delete mode 100755 Zend/tests/methods-on-non-objects-dynamic.phpt delete mode 100644 Zend/tests/methods-on-non-objects-eval.phpt delete mode 100755 Zend/tests/methods-on-non-objects-in-echo.phpt delete mode 100755 Zend/tests/methods-on-non-objects-nested-calls-dyn.phpt delete mode 100755 Zend/tests/methods-on-non-objects-nested-calls-new.phpt delete mode 100755 Zend/tests/methods-on-non-objects-nested-calls-nonct.phpt delete mode 100755 Zend/tests/methods-on-non-objects-nested-calls-ns.phpt delete mode 100755 Zend/tests/methods-on-non-objects-nested-calls-static.phpt delete mode 100644 Zend/tests/methods-on-non-objects-nested-calls.phpt delete mode 100755 Zend/tests/methods-on-non-objects-return-unused.phpt delete mode 100644 Zend/tests/methods-on-non-objects-throw.phpt diff --git a/Zend/tests/030.phpt b/Zend/tests/030.phpt index 8afcb66bd8..cff21d4935 100644 --- a/Zend/tests/030.phpt +++ b/Zend/tests/030.phpt @@ -34,7 +34,7 @@ $test->bar(); object(Exception)#%d (7) { ["message":protected]=> string(3) "foo" - ["string":"Exception":private]=> + ["string":"BaseException":private]=> string(0) "" ["code":protected]=> int(0) @@ -42,7 +42,7 @@ object(Exception)#%d (7) { string(%d) "%s030.php" ["line":protected]=> int(%d) - ["trace":"Exception":private]=> + ["trace":"BaseException":private]=> array(1) { [0]=> array(6) { @@ -61,7 +61,7 @@ object(Exception)#%d (7) { } } } - ["previous":"Exception":private]=> + ["previous":"BaseException":private]=> NULL } 'test' => '0' diff --git a/Zend/tests/arg_unpack/string_keys.phpt b/Zend/tests/arg_unpack/string_keys.phpt index 443a882941..51db52e146 100644 --- a/Zend/tests/arg_unpack/string_keys.phpt +++ b/Zend/tests/arg_unpack/string_keys.phpt @@ -7,14 +7,18 @@ set_error_handler(function($errno, $errstr) { var_dump($errstr); }); -var_dump(...[1, 2, "foo" => 3, 4]); -var_dump(...new ArrayIterator([1, 2, "foo" => 3, 4])); +try { + var_dump(...[1, 2, "foo" => 3, 4]); +} catch (EngineException $ex) { + var_dump($ex->getMessage()); +} +try { + var_dump(...new ArrayIterator([1, 2, "foo" => 3, 4])); +} catch (EngineException $ex) { + var_dump($ex->getMessage()); +} ?> --EXPECTF-- string(36) "Cannot unpack array with string keys" -int(1) -int(2) string(42) "Cannot unpack Traversable with string keys" -int(1) -int(2) diff --git a/Zend/tests/bug37251.phpt b/Zend/tests/bug37251.phpt index 320d544ce5..2b545a530f 100644 --- a/Zend/tests/bug37251.phpt +++ b/Zend/tests/bug37251.phpt @@ -2,18 +2,16 @@ Bug #37251 (deadlock when custom error handler is to catch array type hint error) --FILE-- bar(); +try { + $foo = new Foo(); + $foo->bar(); +} catch (EngineException $e) { + echo 'OK'; +} --EXPECT-- OK diff --git a/Zend/tests/bug48693.phpt b/Zend/tests/bug48693.phpt index e5f7ce8f45..d2baf2a695 100644 --- a/Zend/tests/bug48693.phpt +++ b/Zend/tests/bug48693.phpt @@ -3,26 +3,43 @@ Bug #48693 (Double declaration of __lambda_func when lambda wrongly formatted) --FILE-- --EXPECTF-- -Parse error: %s in %s(%d) : runtime-created function on line 1 +exception 'ParseException' with message 'syntax error, unexpected '}', expecting end of file' in %sbug48693.php(4) : runtime-created function:1 +Stack trace: +#0 %sbug48693.php(4): create_function('', 'return 1; }') +#1 {main} + +exception 'ParseException' with message 'syntax error, unexpected end of file' in %sbug48693.php(14) : runtime-created function:1 +Stack trace: +#0 %sbug48693.php(14): create_function('', '{') +#1 {main} -Parse error: %s %s(%d) : runtime-created function on line 1 -bool(false) int(2) -bool(false) int(3) -bool(true) diff --git a/Zend/tests/bug64135.phpt b/Zend/tests/bug64135.phpt index 1c7b1500a2..53bcba1d0d 100644 --- a/Zend/tests/bug64135.phpt +++ b/Zend/tests/bug64135.phpt @@ -10,7 +10,7 @@ function exception_error_handler() { set_error_handler("exception_error_handler"); try { $undefined->undefined(); -} catch(Exception $e) { +} catch(BaseException $e) { echo "Exception is thrown"; } --EXPECT-- diff --git a/Zend/tests/bug64966.phpt b/Zend/tests/bug64966.phpt index c1cdbbf812..931460ba60 100644 --- a/Zend/tests/bug64966.phpt +++ b/Zend/tests/bug64966.phpt @@ -2,11 +2,12 @@ Bug #64966 (segfault in zend_do_fcall_common_helper_SPEC) --FILE-- b(); ?> --EXPECTF-- -Fatal error: Uncaught exception 'Exception' in %sbug64966.php:3 +Fatal error: Uncaught exception 'Exception' in %sbug64966.php:6 Stack trace: -#0 [internal function]: {closure}(4096, 'Argument 1 pass...', '%s', 6, Array) -#1 %sbug64966.php(6): iterator_apply('') -#2 %sbug64966.php(12): test('iterator_apply') -#3 %sbug64966.php(17): A->b() -#4 {main} - thrown in %sbug64966.php on line 3 +#0 %sbug64966.php(13): test('iterator_apply') +#1 %sbug64966.php(18): A->b() +#2 {main} + thrown in %sbug64966.php on line 6 diff --git a/Zend/tests/closure_031.phpt b/Zend/tests/closure_031.phpt index dace4a4e73..6b4586e8b0 100644 --- a/Zend/tests/closure_031.phpt +++ b/Zend/tests/closure_031.phpt @@ -8,9 +8,12 @@ function foo($errno, $errstr, $errfile, $errline) { set_error_handler('foo'); $foo = function() { }; -var_dump($foo->a); +try { + var_dump($foo->a); +} catch (EngineException $ex) { + echo "Error: {$ex->getMessage()}\n"; +} ?> --EXPECT-- Error: Closure object cannot have properties -NULL diff --git a/Zend/tests/exception_010.phpt b/Zend/tests/exception_010.phpt index 6bff8c6e5e..d67cddab58 100644 --- a/Zend/tests/exception_010.phpt +++ b/Zend/tests/exception_010.phpt @@ -15,16 +15,16 @@ $x->getcode(1); ?> --EXPECTF-- -Warning: Exception::getTraceAsString() expects exactly 0 parameters, 1 given in %s on line %d +Warning: BaseException::getTraceAsString() expects exactly 0 parameters, 1 given in %s on line %d -Warning: Exception::__toString() expects exactly 0 parameters, 1 given in %s on line %d +Warning: BaseException::__toString() expects exactly 0 parameters, 1 given in %s on line %d -Warning: Exception::getTrace() expects exactly 0 parameters, 1 given in %s on line %d +Warning: BaseException::getTrace() expects exactly 0 parameters, 1 given in %s on line %d -Warning: Exception::getLine() expects exactly 0 parameters, 1 given in %s on line %d +Warning: BaseException::getLine() expects exactly 0 parameters, 1 given in %s on line %d -Warning: Exception::getFile() expects exactly 0 parameters, 1 given in %s on line %d +Warning: BaseException::getFile() expects exactly 0 parameters, 1 given in %s on line %d -Warning: Exception::getMessage() expects exactly 0 parameters, 1 given in %s on line %d +Warning: BaseException::getMessage() expects exactly 0 parameters, 1 given in %s on line %d -Warning: Exception::getCode() expects exactly 0 parameters, 1 given in %s on line %d +Warning: BaseException::getCode() expects exactly 0 parameters, 1 given in %s on line %d diff --git a/Zend/tests/exception_before_fatal.phpt b/Zend/tests/exception_before_fatal.phpt index 608d65094b..1109097e1f 100644 --- a/Zend/tests/exception_before_fatal.phpt +++ b/Zend/tests/exception_before_fatal.phpt @@ -10,38 +10,38 @@ set_error_handler("exception_error_handler"); try { $foo->a(); -} catch(Exception $e) { +} catch(BaseException $e) { var_dump($e->getMessage()); } try { new $foo(); -} catch(Exception $e) { +} catch(BaseException $e) { var_dump($e->getMessage()); } try { throw $foo; -} catch(Exception $e) { +} catch(BaseException $e) { var_dump($e->getMessage()); } try { $foo(); -} catch(Exception $e) { +} catch(BaseException $e) { var_dump($e->getMessage()); } try { $foo::b(); -} catch(Exception $e) { +} catch(BaseException $e) { var_dump($e->getMessage()); } try { $b = clone $foo; -} catch(Exception $e) { +} catch(BaseException $e) { var_dump($e->getMessage()); } @@ -50,7 +50,7 @@ class b { try { b::$foo(); -} catch(Exception $e) { +} catch(BaseException $e) { var_dump($e->getMessage()); } ?> diff --git a/Zend/tests/generators/bug67497.phpt b/Zend/tests/generators/bug67497.phpt index 483857b96c..63e535d331 100644 --- a/Zend/tests/generators/bug67497.phpt +++ b/Zend/tests/generators/bug67497.phpt @@ -8,7 +8,10 @@ function gen() { yield $a; } -@eval('abc'); +try { + eval('abc'); +} catch (ParseException $ex) { +} $values = gen(); $values->next(); diff --git a/Zend/tests/methods-on-non-objects-args-catch.phpt b/Zend/tests/methods-on-non-objects-args-catch.phpt deleted file mode 100644 index 853d2d5602..0000000000 --- a/Zend/tests/methods-on-non-objects-args-catch.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -Catch method calls on non-objects raise recoverable errors ---FILE-- -method(1, 2, 3)); -echo "Alive\n"; -?> ---EXPECTF-- - -int(4096) -string(%d) "Call to a member function method() on null" -NULL -Alive diff --git a/Zend/tests/methods-on-non-objects-array-access.phpt b/Zend/tests/methods-on-non-objects-array-access.phpt deleted file mode 100755 index be87457c6c..0000000000 --- a/Zend/tests/methods-on-non-objects-array-access.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -Catch method calls on non-objects inside array access ---FILE-- - 'OK']; -var_dump($a[$x->method()]); -echo "Alive\n"; -?> ---EXPECTF-- -int(4096) -string(%d) "Call to a member function method() on null" -string(2) "OK" -Alive \ No newline at end of file diff --git a/Zend/tests/methods-on-non-objects-array-creation.phpt b/Zend/tests/methods-on-non-objects-array-creation.phpt deleted file mode 100755 index 74cbb9c179..0000000000 --- a/Zend/tests/methods-on-non-objects-array-creation.phpt +++ /dev/null @@ -1,35 +0,0 @@ ---TEST-- -Catch method calls on non-objects inside array creation ---FILE-- -method() => 'OK']); -var_dump([$x->method(), $x->method(), $x->method()]); -echo "Alive\n"; -?> ---EXPECTF-- -int(4096) -string(%d) "Call to a member function method() on null" -array(1) { - [""]=> - string(2) "OK" -} -int(4096) -string(%d) "Call to a member function method() on null" -int(4096) -string(%d) "Call to a member function method() on null" -int(4096) -string(%d) "Call to a member function method() on null" -array(3) { - [0]=> - NULL - [1]=> - NULL - [2]=> - NULL -} -Alive \ No newline at end of file diff --git a/Zend/tests/methods-on-non-objects-as-arg.phpt b/Zend/tests/methods-on-non-objects-as-arg.phpt deleted file mode 100755 index 13b83cb06e..0000000000 --- a/Zend/tests/methods-on-non-objects-as-arg.phpt +++ /dev/null @@ -1,47 +0,0 @@ ---TEST-- -Catch method calls on non-objects as argument ---FILE-- -method())); -var_dump(nesting(nesting($x->method()))); -var_dump(nesting($x->method(nesting($x->method())))); -var_dump(nesting($x->method(), $x->method())); -echo "Alive\n"; -?> ---EXPECTF-- -Called #1 -array(1) { - [0]=> - NULL -} -Called #2 -array(1) { - [0]=> - array(1) { - [0]=> - NULL - } -} -Called #3 -array(1) { - [0]=> - NULL -} -Called #4 -Called #5 -array(2) { - [0]=> - NULL - [1]=> - NULL -} -Alive diff --git a/Zend/tests/methods-on-non-objects-catch.phpt b/Zend/tests/methods-on-non-objects-catch.phpt index bbfadac107..b38da3657b 100644 --- a/Zend/tests/methods-on-non-objects-catch.phpt +++ b/Zend/tests/methods-on-non-objects-catch.phpt @@ -7,12 +7,15 @@ set_error_handler(function($code, $message) { }); $x= null; -var_dump($x->method()); +try { + var_dump($x->method()); +} catch (EngineException $e) { + var_dump($e->getCode(), $e->getMessage()); +} echo "Alive\n"; ?> --EXPECTF-- int(4096) string(%d) "Call to a member function method() on null" -NULL Alive diff --git a/Zend/tests/methods-on-non-objects-chain.phpt b/Zend/tests/methods-on-non-objects-chain.phpt deleted file mode 100644 index 30da254cd5..0000000000 --- a/Zend/tests/methods-on-non-objects-chain.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -Catch chained method calls on non-objects raise recoverable errors ---FILE-- -method()->chained()->invocations()); -echo "Alive\n"; -?> ---EXPECTF-- - -int(4096) -string(%d) "Call to a member function method() on null" -int(4096) -string(%d) "Call to a member function chained() on null" -int(4096) -string(%d) "Call to a member function invocations() on null" -NULL -Alive diff --git a/Zend/tests/methods-on-non-objects-concat.phpt b/Zend/tests/methods-on-non-objects-concat.phpt deleted file mode 100755 index 4ff47aa454..0000000000 --- a/Zend/tests/methods-on-non-objects-concat.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -Catch method calls on non-objects inside concatenation ---FILE-- -method()."After\n"; -echo "Alive\n"; -?> ---EXPECTF-- -int(4096) -string(%d) "Call to a member function method() on null" -Before -After -Alive \ No newline at end of file diff --git a/Zend/tests/methods-on-non-objects-dynamic.phpt b/Zend/tests/methods-on-non-objects-dynamic.phpt deleted file mode 100755 index 11c5c9f44b..0000000000 --- a/Zend/tests/methods-on-non-objects-dynamic.phpt +++ /dev/null @@ -1,23 +0,0 @@ ---TEST-- -Catch method calls on non-objects with dynamic lookups ---FILE-- -{$arr[1]}()); - -$fun= function() { return null; }; -var_dump($fun()->{'method'}()); - -echo "Alive\n"; -?> ---EXPECTF-- -Called #1 -NULL -Called #2 -NULL -Alive diff --git a/Zend/tests/methods-on-non-objects-eval.phpt b/Zend/tests/methods-on-non-objects-eval.phpt deleted file mode 100644 index 8ee494c434..0000000000 --- a/Zend/tests/methods-on-non-objects-eval.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -Indirect call inside eval to member function on non-object ---FILE-- -method(1, 2, 3);')); -echo "Alive\n"; -?> ---EXPECTF-- - -int(4096) -string(%d) "Call to a member function method() on null" -NULL -Alive diff --git a/Zend/tests/methods-on-non-objects-in-echo.phpt b/Zend/tests/methods-on-non-objects-in-echo.phpt deleted file mode 100755 index a0267c0ea5..0000000000 --- a/Zend/tests/methods-on-non-objects-in-echo.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -Catch method calls on non-objects inside echo ---FILE-- -method(), "After\n"; -echo "Alive\n"; -?> ---EXPECTF-- -Before -int(4096) -string(%d) "Call to a member function method() on null" -After -Alive \ No newline at end of file diff --git a/Zend/tests/methods-on-non-objects-nested-calls-dyn.phpt b/Zend/tests/methods-on-non-objects-nested-calls-dyn.phpt deleted file mode 100755 index 267104f1b3..0000000000 --- a/Zend/tests/methods-on-non-objects-nested-calls-dyn.phpt +++ /dev/null @@ -1,37 +0,0 @@ ---TEST-- -Catch method calls on non-objects with nested dynamic calls ---FILE-- -method($closure())); - -$lambda= create_function('', 'return nested();'); -var_dump($x->method($lambda())); - -$func= 'nested'; -var_dump($x->method($func())); - -var_dump($x->method(call_user_func('nested'))); - -echo "Alive\n"; -?> ---EXPECTF-- -Called #1 -NULL -Called #2 -NULL -Called #3 -NULL -Called #4 -NULL -Alive diff --git a/Zend/tests/methods-on-non-objects-nested-calls-new.phpt b/Zend/tests/methods-on-non-objects-nested-calls-new.phpt deleted file mode 100755 index d8e3dd21bf..0000000000 --- a/Zend/tests/methods-on-non-objects-nested-calls-new.phpt +++ /dev/null @@ -1,37 +0,0 @@ ---TEST-- -Catch method calls on non-objects with nested calls to new ---FILE-- -method(new Nesting())); -var_dump($x->method(new Nesting(), new Nesting())); -var_dump($x->method(new Nesting(new Nesting()))); -var_dump($x->method(new Nesting($x->nested()))); -var_dump($x->method(new Nesting($x->nested(new Nesting())))); -var_dump($x->method($x->nested(new Nesting($x->deep())))); -var_dump($x->method([new Nesting()])); -echo "Alive\n"; -?> ---EXPECTF-- -Called #1 -NULL -Called #2 -NULL -Called #3 -NULL -Called #4 -NULL -Called #5 -NULL -Called #6 -NULL -Called #7 -NULL -Alive diff --git a/Zend/tests/methods-on-non-objects-nested-calls-nonct.phpt b/Zend/tests/methods-on-non-objects-nested-calls-nonct.phpt deleted file mode 100755 index a4529eecdc..0000000000 --- a/Zend/tests/methods-on-non-objects-nested-calls-nonct.phpt +++ /dev/null @@ -1,43 +0,0 @@ ---TEST-- -Catch method calls on non-objects with nested non-compile-time-resolveable calls ---FILE-- -method(nested())); - -$closure= function() { return nested(); }; -var_dump($x->method($closure())); - -$lambda= create_function('', 'return nested();'); -var_dump($x->method($lambda())); - -$func= 'nested'; -var_dump($x->method($func())); - -var_dump($x->method(call_user_func('nested'))); -var_dump($x->method(call_user_func_array('nested', []))); - -echo "Alive\n"; -?> ---EXPECTF-- -Called #1 -NULL -Called #2 -NULL -Called #3 -NULL -Called #4 -NULL -Called #5 -NULL -Called #6 -NULL -Alive diff --git a/Zend/tests/methods-on-non-objects-nested-calls-ns.phpt b/Zend/tests/methods-on-non-objects-nested-calls-ns.phpt deleted file mode 100755 index b16f579fa9..0000000000 --- a/Zend/tests/methods-on-non-objects-nested-calls-ns.phpt +++ /dev/null @@ -1,26 +0,0 @@ ---TEST-- -Catch method calls on non-objects with nested calls to namespaced functions with core counterparts ---FILE-- -method(strlen('Test'))); -var_dump($x->method(strlen('Test'), strlen('Test'))); -var_dump($x->method([strlen('Test')])); -echo "Alive\n"; -?> ---EXPECTF-- -Called #1 -NULL -Called #2 -NULL -Called #3 -NULL -Alive diff --git a/Zend/tests/methods-on-non-objects-nested-calls-static.phpt b/Zend/tests/methods-on-non-objects-nested-calls-static.phpt deleted file mode 100755 index 64972ee871..0000000000 --- a/Zend/tests/methods-on-non-objects-nested-calls-static.phpt +++ /dev/null @@ -1,33 +0,0 @@ ---TEST-- -Catch method calls on non-objects with nested calls to static methods ---FILE-- -method(Nesting::nested())); -var_dump($x->method($class::nested())); -var_dump($x->method($class::{$method}())); -var_dump($x->method([Nesting::nested()])); -echo "Alive\n"; -?> ---EXPECTF-- -Called #1 -NULL -Called #2 -NULL -Called #3 -NULL -Called #4 -NULL -Alive diff --git a/Zend/tests/methods-on-non-objects-nested-calls.phpt b/Zend/tests/methods-on-non-objects-nested-calls.phpt deleted file mode 100644 index b25aeafd9c..0000000000 --- a/Zend/tests/methods-on-non-objects-nested-calls.phpt +++ /dev/null @@ -1,47 +0,0 @@ ---TEST-- -Catch method calls on non-objects with nested function and method calls ---FILE-- -method(nested())); -var_dump($x->method(nested(), nested())); -var_dump($x->method(nested(nested()))); -var_dump($x->method($x->nested())); -var_dump($x->method($x->nested(), $x->nested())); -var_dump($x->method($x->nested(nested()))); -var_dump($x->method($x->nested($x->deep()))); -var_dump($x->method($x->nested(nested($x->deep())))); -var_dump($x->method(nested(nested($x->nested())))); -var_dump($x->method([nested()])); -echo "Alive\n"; -?> ---EXPECTF-- -Called #1 -NULL -Called #2 -NULL -Called #3 -NULL -Called #4 -NULL -Called #5 -NULL -Called #6 -NULL -Called #7 -NULL -Called #8 -NULL -Called #9 -NULL -Called #10 -NULL -Alive diff --git a/Zend/tests/methods-on-non-objects-return-unused.phpt b/Zend/tests/methods-on-non-objects-return-unused.phpt deleted file mode 100755 index ab2951f94f..0000000000 --- a/Zend/tests/methods-on-non-objects-return-unused.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -Catch method calls on non-objects without using return value ---INI-- -report_memleaks=1 ---FILE-- -method(); -echo "Alive\n"; -?> ---EXPECTF-- -Caught -Alive diff --git a/Zend/tests/methods-on-non-objects-throw.phpt b/Zend/tests/methods-on-non-objects-throw.phpt deleted file mode 100644 index 874f57cb24..0000000000 --- a/Zend/tests/methods-on-non-objects-throw.phpt +++ /dev/null @@ -1,29 +0,0 @@ ---TEST-- -Convert errors to exceptions from method calls on non-objects raise recoverable errors ---FILE-- -method(); -} catch (BadMethodCallException $e) { - echo "Caught expected ", $e->getMessage(), "!\n"; -} -echo "Alive\n"; -?> ---EXPECTF-- -Calling... -Raising... -Caught expected Call to a member function method() on null! -Alive diff --git a/Zend/tests/methods-on-non-objects-usort.phpt b/Zend/tests/methods-on-non-objects-usort.phpt index fb1869c1c8..54779cd1ea 100644 --- a/Zend/tests/methods-on-non-objects-usort.phpt +++ b/Zend/tests/methods-on-non-objects-usort.phpt @@ -9,7 +9,12 @@ set_error_handler(function($code, $message) { $comparator= null; $list= [1, 4, 2, 3, -1]; usort($list, function($a, $b) use ($comparator) { - return $comparator->compare($a, $b); + try { + return $comparator->compare($a, $b); + } catch (EngineException $e) { + var_dump($e->getCode(), $e->getMessage()); + return 0; + } }); var_dump($list); echo "Alive\n"; diff --git a/Zend/tests/variadic/typehint_suppressed_error.phpt b/Zend/tests/variadic/typehint_suppressed_error.phpt index 5048e1c1bb..f03ec43d0a 100644 --- a/Zend/tests/variadic/typehint_suppressed_error.phpt +++ b/Zend/tests/variadic/typehint_suppressed_error.phpt @@ -7,27 +7,12 @@ function test(array... $args) { var_dump($args); } -set_error_handler(function($errno, $errstr) { - var_dump($errstr); - return true; -}); - -test([0], [1], 2); +try { + test([0], [1], 2); +} catch(EngineException $e) { + var_dump($e->getMessage()); +} ?> --EXPECTF-- string(%d) "Argument 3 passed to test() must be of the type array, integer given, called in %s on line %d and defined" -array(3) { - [0]=> - array(1) { - [0]=> - int(0) - } - [1]=> - array(1) { - [0]=> - int(1) - } - [2]=> - int(2) -} diff --git a/Zend/zend.c b/Zend/zend.c index 8d6cd7148f..fe507d7154 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -842,7 +842,7 @@ void zend_set_utility_values(zend_utility_values *utility_values) /* {{{ */ /* this should be compatible with the standard zenderror */ void zenderror(const char *error) /* {{{ */ { - zend_error(E_PARSE, "%s", error); + zend_throw_exception(zend_get_parse_exception(), error, E_PARSE); } /* }}} */ @@ -1016,6 +1016,21 @@ static void zend_error_va_list(int type, const char *format, va_list args) zend_stack context_stack; zend_array *symbol_table; + if (type & E_EXCEPTION) { + char *message = NULL; + +#if !defined(HAVE_NORETURN) || defined(HAVE_NORETURN_ALIAS) + va_start(args, format); +#endif + zend_vspprintf(&message, 0, format, args); + zend_throw_exception(zend_get_engine_exception(), message, type & ~E_EXCEPTION); + efree(message); +#if !defined(HAVE_NORETURN) || defined(HAVE_NORETURN_ALIAS) + va_end(args); +#endif + return; + } + /* Report about uncaught exception in case of fatal errors */ if (EG(exception)) { zend_execute_data *ex; diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 37f8d55bd3..382bb1849a 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -32,7 +32,7 @@ #define ZEND_CLOSURE_PRINT_NAME "Closure object" #define ZEND_CLOSURE_PROPERTY_ERROR() \ - zend_error(E_RECOVERABLE_ERROR, "Closure object cannot have properties") + zend_error(E_EXCEPTION | E_RECOVERABLE_ERROR, "Closure object cannot have properties") typedef struct _zend_closure { zend_object std; @@ -53,7 +53,7 @@ ZEND_METHOD(Closure, __invoke) /* {{{ */ arguments = emalloc(sizeof(zval) * ZEND_NUM_ARGS()); if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), arguments) == FAILURE) { efree(arguments); - zend_error(E_RECOVERABLE_ERROR, "Cannot get arguments for calling closure"); + zend_error(E_EXCEPTION | E_RECOVERABLE_ERROR, "Cannot get arguments for calling closure"); RETVAL_FALSE; } else if (call_user_function_ex(CG(function_table), NULL, getThis(), return_value, ZEND_NUM_ARGS(), arguments, 1, NULL) == FAILURE) { RETVAL_FALSE; @@ -168,7 +168,7 @@ ZEND_METHOD(Closure, bind) static zend_function *zend_closure_get_constructor(zend_object *object) /* {{{ */ { - zend_error(E_RECOVERABLE_ERROR, "Instantiation of 'Closure' is not allowed"); + zend_error(E_EXCEPTION | E_RECOVERABLE_ERROR, "Instantiation of 'Closure' is not allowed"); return NULL; } /* }}} */ @@ -418,7 +418,7 @@ static HashTable *zend_closure_get_gc(zval *obj, zval **table, int *n) /* {{{ */ Private constructor preventing instantiation */ ZEND_METHOD(Closure, __construct) { - zend_error(E_RECOVERABLE_ERROR, "Instantiation of 'Closure' is not allowed"); + zend_error(E_EXCEPTION | E_RECOVERABLE_ERROR, "Instantiation of 'Closure' is not allowed"); } /* }}} */ diff --git a/Zend/zend_errors.h b/Zend/zend_errors.h index 25bb68de7a..95be1aa2fb 100644 --- a/Zend/zend_errors.h +++ b/Zend/zend_errors.h @@ -38,6 +38,8 @@ #define E_DEPRECATED (1<<13L) #define E_USER_DEPRECATED (1<<14L) +#define E_EXCEPTION (1<<15L) + #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 | E_STRICT) #define E_CORE (E_CORE_ERROR | E_CORE_WARNING) diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 655542fc30..7070934426 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -30,8 +30,11 @@ #include "zend_dtrace.h" #include "zend_smart_str.h" +static zend_class_entry *base_exception_ce; static zend_class_entry *default_exception_ce; static zend_class_entry *error_exception_ce; +static zend_class_entry *engine_exception_ce; +static zend_class_entry *parse_exception_ce; static zend_object_handlers default_exception_handlers; ZEND_API void (*zend_throw_exception_hook)(zval *ex); @@ -43,16 +46,16 @@ void zend_exception_set_previous(zend_object *exception, zend_object *add_previo return; } ZVAL_OBJ(&tmp, add_previous); - if (!instanceof_function(Z_OBJCE(tmp), default_exception_ce)) { + if (!instanceof_function(Z_OBJCE(tmp), base_exception_ce)) { zend_error(E_ERROR, "Cannot set non exception as previous exception"); return; } ZVAL_OBJ(&zv, exception); pzv = &zv; do { - previous = zend_read_property(default_exception_ce, pzv, "previous", sizeof("previous")-1, 1, &rv); + previous = zend_read_property(base_exception_ce, pzv, "previous", sizeof("previous")-1, 1, &rv); if (Z_TYPE_P(previous) == IS_NULL) { - zend_update_property(default_exception_ce, pzv, "previous", sizeof("previous")-1, &tmp); + zend_update_property(base_exception_ce, pzv, "previous", sizeof("previous")-1, &tmp); GC_REFCOUNT(add_previous)--; return; } @@ -106,6 +109,9 @@ ZEND_API void zend_throw_exception_internal(zval *exception) /* {{{ */ } } if (!EG(current_execute_data)) { + if (exception && Z_OBJCE_P(exception) == parse_exception_ce) { + return; + } if(EG(exception)) { zend_exception_error(EG(exception), E_ERROR); } @@ -157,12 +163,21 @@ static zend_object *zend_default_exception_new_ex(zend_class_entry *class_type, object_properties_init(object, class_type); - zend_fetch_debug_backtrace(&trace, skip_top_traces, 0, 0); + if (EG(current_execute_data)) { + zend_fetch_debug_backtrace(&trace, skip_top_traces, 0, 0); + } else { + array_init(&trace); + } Z_SET_REFCOUNT(trace, 0); - zend_update_property_string(default_exception_ce, &obj, "file", sizeof("file")-1, zend_get_executed_filename()); - zend_update_property_long(default_exception_ce, &obj, "line", sizeof("line")-1, zend_get_executed_lineno()); - zend_update_property(default_exception_ce, &obj, "trace", sizeof("trace")-1, &trace); + if (EXPECTED(class_type != parse_exception_ce)) { + zend_update_property_string(base_exception_ce, &obj, "file", sizeof("file")-1, zend_get_executed_filename()); + zend_update_property_long(base_exception_ce, &obj, "line", sizeof("line")-1, zend_get_executed_lineno()); + } else { + zend_update_property_string(base_exception_ce, &obj, "file", sizeof("file")-1, zend_get_compiled_filename()->val); + zend_update_property_long(base_exception_ce, &obj, "line", sizeof("line")-1, zend_get_compiled_lineno()); + } + zend_update_property(base_exception_ce, &obj, "trace", sizeof("trace")-1, &trace); return object; } @@ -198,22 +213,22 @@ ZEND_METHOD(exception, __construct) zval *object, *previous = NULL; int argc = ZEND_NUM_ARGS(); - if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|SlO!", &message, &code, &previous, default_exception_ce) == FAILURE) { + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|SlO!", &message, &code, &previous, base_exception_ce) == FAILURE) { zend_error(E_ERROR, "Wrong parameters for Exception([string $exception [, long $code [, Exception $previous = NULL]]])"); } object = getThis(); if (message) { - zend_update_property_str(default_exception_ce, object, "message", sizeof("message")-1, message); + zend_update_property_str(base_exception_ce, object, "message", sizeof("message")-1, message); } if (code) { - zend_update_property_long(default_exception_ce, object, "code", sizeof("code")-1, code); + zend_update_property_long(base_exception_ce, object, "code", sizeof("code")-1, code); } if (previous) { - zend_update_property(default_exception_ce, object, "previous", sizeof("previous")-1, previous); + zend_update_property(base_exception_ce, object, "previous", sizeof("previous")-1, previous); } } /* }}} */ @@ -228,32 +243,32 @@ ZEND_METHOD(error_exception, __construct) int argc = ZEND_NUM_ARGS(); size_t message_len, filename_len; - if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|sllslO!", &message, &message_len, &code, &severity, &filename, &filename_len, &lineno, &previous, default_exception_ce) == FAILURE) { + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|sllslO!", &message, &message_len, &code, &severity, &filename, &filename_len, &lineno, &previous, base_exception_ce) == FAILURE) { zend_error(E_ERROR, "Wrong parameters for ErrorException([string $exception [, long $code, [ long $severity, [ string $filename, [ long $lineno [, Exception $previous = NULL]]]]]])"); } object = getThis(); if (message) { - zend_update_property_string(default_exception_ce, object, "message", sizeof("message")-1, message); + zend_update_property_string(base_exception_ce, object, "message", sizeof("message")-1, message); } if (code) { - zend_update_property_long(default_exception_ce, object, "code", sizeof("code")-1, code); + zend_update_property_long(base_exception_ce, object, "code", sizeof("code")-1, code); } if (previous) { - zend_update_property(default_exception_ce, object, "previous", sizeof("previous")-1, previous); + zend_update_property(base_exception_ce, object, "previous", sizeof("previous")-1, previous); } - zend_update_property_long(default_exception_ce, object, "severity", sizeof("severity")-1, severity); + zend_update_property_long(base_exception_ce, object, "severity", sizeof("severity")-1, severity); if (argc >= 4) { - zend_update_property_string(default_exception_ce, object, "file", sizeof("file")-1, filename); + zend_update_property_string(base_exception_ce, object, "file", sizeof("file")-1, filename); if (argc < 5) { lineno = 0; /* invalidate lineno */ } - zend_update_property_long(default_exception_ce, object, "line", sizeof("line")-1, lineno); + zend_update_property_long(base_exception_ce, object, "line", sizeof("line")-1, lineno); } } /* }}} */ @@ -264,9 +279,9 @@ ZEND_METHOD(error_exception, __construct) } #define GET_PROPERTY(object, name) \ - zend_read_property(default_exception_ce, (object), name, sizeof(name) - 1, 0, &rv) + zend_read_property(base_exception_ce, (object), name, sizeof(name) - 1, 0, &rv) #define GET_PROPERTY_SILENT(object, name) \ - zend_read_property(default_exception_ce, (object), name, sizeof(name) - 1, 1, &rv) + zend_read_property(base_exception_ce, (object), name, sizeof(name) - 1, 1, &rv) /* {{{ proto string Exception::getFile() Get the file in which the exception occurred */ @@ -538,7 +553,7 @@ ZEND_METHOD(exception, getTraceAsString) DEFAULT_0_PARAMS; - trace = zend_read_property(default_exception_ce, getThis(), "trace", sizeof("trace")-1, 1, &rv); + trace = zend_read_property(base_exception_ce, getThis(), "trace", sizeof("trace")-1, 1, &rv); ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(trace), index, frame) { if (Z_TYPE_P(frame) != IS_ARRAY) { zend_error(E_WARNING, "Expected array for frame %pu", index); @@ -656,7 +671,7 @@ ZEND_METHOD(exception, __toString) /* We store the result in the private property string so we can access * the result in uncaught exception handlers without memleaks. */ - zend_update_property_str(default_exception_ce, getThis(), "string", sizeof("string")-1, str); + zend_update_property_str(base_exception_ce, getThis(), "string", sizeof("string")-1, str); RETURN_STR(str); } @@ -711,25 +726,64 @@ static const zend_function_entry error_exception_functions[] = { void zend_register_default_exception(void) /* {{{ */ { zend_class_entry ce; + zend_property_info *prop; - INIT_CLASS_ENTRY(ce, "Exception", default_exception_functions); - default_exception_ce = zend_register_internal_class(&ce); - default_exception_ce->create_object = zend_default_exception_new; + INIT_CLASS_ENTRY(ce, "BaseException", default_exception_functions); + base_exception_ce = zend_register_internal_class(&ce); + base_exception_ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; + base_exception_ce->create_object = NULL; memcpy(&default_exception_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); default_exception_handlers.clone_obj = NULL; - zend_declare_property_string(default_exception_ce, "message", sizeof("message")-1, "", ZEND_ACC_PROTECTED); - zend_declare_property_string(default_exception_ce, "string", sizeof("string")-1, "", ZEND_ACC_PRIVATE); - zend_declare_property_long(default_exception_ce, "code", sizeof("code")-1, 0, ZEND_ACC_PROTECTED); - zend_declare_property_null(default_exception_ce, "file", sizeof("file")-1, ZEND_ACC_PROTECTED); - zend_declare_property_null(default_exception_ce, "line", sizeof("line")-1, ZEND_ACC_PROTECTED); - zend_declare_property_null(default_exception_ce, "trace", sizeof("trace")-1, ZEND_ACC_PRIVATE); - zend_declare_property_null(default_exception_ce, "previous", sizeof("previous")-1, ZEND_ACC_PRIVATE); + zend_declare_property_string(base_exception_ce, "message", sizeof("message")-1, "", ZEND_ACC_PROTECTED); + zend_declare_property_string(base_exception_ce, "string", sizeof("string")-1, "", ZEND_ACC_PRIVATE); + zend_declare_property_long(base_exception_ce, "code", sizeof("code")-1, 0, ZEND_ACC_PROTECTED); + zend_declare_property_null(base_exception_ce, "file", sizeof("file")-1, ZEND_ACC_PROTECTED); + zend_declare_property_null(base_exception_ce, "line", sizeof("line")-1, ZEND_ACC_PROTECTED); + zend_declare_property_null(base_exception_ce, "trace", sizeof("trace")-1, ZEND_ACC_PRIVATE); + zend_declare_property_null(base_exception_ce, "previous", sizeof("previous")-1, ZEND_ACC_PRIVATE); + + INIT_CLASS_ENTRY(ce, "Exception", NULL); + default_exception_ce = zend_register_internal_class_ex(&ce, base_exception_ce); + default_exception_ce->create_object = zend_default_exception_new; + + /* A trick, to make visible prvate properties of BaseException */ + ZEND_HASH_FOREACH_PTR(&default_exception_ce->properties_info, prop) { + if (prop->flags & ZEND_ACC_SHADOW) { + if (prop->name->len == sizeof("\0BaseException\0string")-1) { + prop->flags &= ~ZEND_ACC_SHADOW; + prop->flags |= ZEND_ACC_PRIVATE; + prop->ce = default_exception_ce; + } else if (prop->name->len == sizeof("\0BaseException\0trace")-1) { + prop->flags &= ~ZEND_ACC_SHADOW; + prop->flags |= ZEND_ACC_PRIVATE; + prop->ce = default_exception_ce; + } else if (prop->name->len == sizeof("\0BaseException\0previous")-1) { + prop->flags &= ~ZEND_ACC_SHADOW; + prop->flags |= ZEND_ACC_PRIVATE; + prop->ce = default_exception_ce; + } + } + } ZEND_HASH_FOREACH_END(); INIT_CLASS_ENTRY(ce, "ErrorException", error_exception_functions); error_exception_ce = zend_register_internal_class_ex(&ce, default_exception_ce); error_exception_ce->create_object = zend_error_exception_new; zend_declare_property_long(error_exception_ce, "severity", sizeof("severity")-1, E_ERROR, ZEND_ACC_PROTECTED); + + INIT_CLASS_ENTRY(ce, "EngineException", NULL); + engine_exception_ce = zend_register_internal_class_ex(&ce, base_exception_ce); + engine_exception_ce->create_object = zend_default_exception_new; + + INIT_CLASS_ENTRY(ce, "ParseException", NULL); + parse_exception_ce = zend_register_internal_class_ex(&ce, base_exception_ce); + parse_exception_ce->create_object = zend_default_exception_new; +} +/* }}} */ + +ZEND_API zend_class_entry *zend_exception_get_base(void) /* {{{ */ +{ + return base_exception_ce; } /* }}} */ @@ -745,12 +799,25 @@ ZEND_API zend_class_entry *zend_get_error_exception(void) /* {{{ */ } /* }}} */ +ZEND_API zend_class_entry *zend_get_engine_exception(void) /* {{{ */ +{ + return engine_exception_ce; +} +/* }}} */ + +ZEND_API zend_class_entry *zend_get_parse_exception(void) /* {{{ */ +{ + return parse_exception_ce; +} +/* }}} */ + + ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const char *message, zend_long code) /* {{{ */ { zval ex; if (exception_ce) { - if (!instanceof_function(exception_ce, default_exception_ce)) { + if (!instanceof_function(exception_ce, base_exception_ce)) { zend_error(E_NOTICE, "Exceptions must be derived from the Exception base class"); exception_ce = default_exception_ce; } @@ -761,10 +828,10 @@ ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const if (message) { - zend_update_property_string(default_exception_ce, &ex, "message", sizeof("message")-1, message); + zend_update_property_string(base_exception_ce, &ex, "message", sizeof("message")-1, message); } if (code) { - zend_update_property_long(default_exception_ce, &ex, "code", sizeof("code")-1, code); + zend_update_property_long(base_exception_ce, &ex, "code", sizeof("code")-1, code); } zend_throw_exception_internal(&ex); @@ -792,7 +859,7 @@ ZEND_API zend_object *zend_throw_error_exception(zend_class_entry *exception_ce, zval ex; zend_object *obj = zend_throw_exception(exception_ce, message, code); ZVAL_OBJ(&ex, obj); - zend_update_property_long(default_exception_ce, &ex, "severity", sizeof("severity")-1, severity); + zend_update_property_long(base_exception_ce, &ex, "severity", sizeof("severity")-1, severity); return obj; } /* }}} */ @@ -807,27 +874,45 @@ static void zend_error_va(int type, const char *file, uint lineno, const char *f } /* }}} */ +static void zend_error_helper(int type, const char *filename, const uint lineno, const char *format, ...) +{ + va_list va; + + va_start(va, format); + zend_error_cb(type, filename, lineno, format, va); + va_end(va); +} + /* This function doesn't return if it uses E_ERROR */ ZEND_API void zend_exception_error(zend_object *ex, int severity) /* {{{ */ { - zval exception; + zval exception, rv; zend_class_entry *ce_exception; ZVAL_OBJ(&exception, ex); ce_exception = Z_OBJCE(exception); - if (instanceof_function(ce_exception, default_exception_ce)) { + EG(exception) = NULL; + if (ce_exception == parse_exception_ce || ce_exception == engine_exception_ce) { + zend_string *message = zval_get_string(GET_PROPERTY(&exception, "message")); + zend_string *file = zval_get_string(GET_PROPERTY_SILENT(&exception, "file")); + zend_long line = zval_get_long(GET_PROPERTY_SILENT(&exception, "line")); + zend_long code = zval_get_long(GET_PROPERTY_SILENT(&exception, "code")); + + zend_error_helper(code, file->val, line, "%s", message->val); + zend_string_release(file); + zend_string_release(message); + OBJ_RELEASE(ex); + } else if (instanceof_function(ce_exception, base_exception_ce)) { zval tmp, rv; zend_string *str, *file = NULL; zend_long line = 0; - EG(exception) = NULL; - zend_call_method_with_0_params(&exception, ce_exception, NULL, "__tostring", &tmp); if (!EG(exception)) { if (Z_TYPE(tmp) != IS_STRING) { zend_error(E_WARNING, "%s::__toString() must return a string", ce_exception->name->val); } else { - zend_update_property_string(default_exception_ce, &exception, "string", sizeof("string")-1, EG(exception) ? ce_exception->name->val : Z_STRVAL(tmp)); + zend_update_property_string(base_exception_ce, &exception, "string", sizeof("string")-1, EG(exception) ? ce_exception->name->val : Z_STRVAL(tmp)); } } zval_ptr_dtor(&tmp); @@ -837,7 +922,7 @@ ZEND_API void zend_exception_error(zend_object *ex, int severity) /* {{{ */ ZVAL_OBJ(&zv, EG(exception)); /* do the best we can to inform about the inner exception */ - if (instanceof_function(ce_exception, default_exception_ce)) { + if (instanceof_function(ce_exception, base_exception_ce)) { file = zval_get_string(GET_PROPERTY_SILENT(&zv, "file")); line = zval_get_long(GET_PROPERTY_SILENT(&zv, "line")); } @@ -876,7 +961,7 @@ ZEND_API void zend_throw_exception_object(zval *exception) /* {{{ */ exception_ce = Z_OBJCE_P(exception); - if (!exception_ce || !instanceof_function(exception_ce, default_exception_ce)) { + if (!exception_ce || !instanceof_function(exception_ce, base_exception_ce)) { zend_error(E_ERROR, "Exceptions must be valid objects derived from the Exception base class"); } zend_throw_exception_internal(exception); diff --git a/Zend/zend_exceptions.h b/Zend/zend_exceptions.h index e223108efd..10609fecb6 100644 --- a/Zend/zend_exceptions.h +++ b/Zend/zend_exceptions.h @@ -34,8 +34,11 @@ ZEND_API void zend_throw_exception_internal(zval *exception); void zend_register_default_exception(void); +ZEND_API zend_class_entry *zend_exception_get_base(void); ZEND_API zend_class_entry *zend_exception_get_default(void); ZEND_API zend_class_entry *zend_get_error_exception(void); +ZEND_API zend_class_entry *zend_get_engine_exception(void); +ZEND_API zend_class_entry *zend_get_parse_exception(void); ZEND_API void zend_register_default_classes(void); /* exception_ce NULL or zend_exception_get_default() or a derived class diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 1609e7367c..9df49f1bb6 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -103,6 +103,11 @@ static const zend_internal_function zend_pass_function = { zval_ptr_dtor_nogc(should_free); \ } +#define FREE_UNFETCHED_OP(type, var) \ + if ((type) & (IS_TMP_VAR|IS_VAR)) { \ + zval_ptr_dtor_nogc(EX_VAR(var)); \ + } + #define FREE_OP_VAR_PTR(should_free) \ if (should_free) { \ zval_ptr_dtor_nogc(should_free); \ @@ -631,21 +636,21 @@ static void zend_verify_internal_arg_type(zend_function *zf, uint32_t arg_num, z if (Z_TYPE_P(arg) == IS_OBJECT) { need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce); if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce)) { - zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg); + zend_verify_arg_error(E_EXCEPTION | E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg); } } else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) { need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce); - zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg); + zend_verify_arg_error(E_EXCEPTION | E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg); } } else if (cur_arg_info->type_hint) { if (cur_arg_info->type_hint == IS_ARRAY) { ZVAL_DEREF(arg); if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) { - zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg); + zend_verify_arg_error(E_EXCEPTION | E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg); } } else if (cur_arg_info->type_hint == IS_CALLABLE) { if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) { - zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg); + zend_verify_arg_error(E_EXCEPTION | E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg); } #if ZEND_DEBUG } else { @@ -676,21 +681,21 @@ static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, if (Z_TYPE_P(arg) == IS_OBJECT) { need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce); if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce)) { - zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg); + zend_verify_arg_error(E_EXCEPTION | E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg); } } else if (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value)))) { need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce); - zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg); + zend_verify_arg_error(E_EXCEPTION | E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg); } } else if (cur_arg_info->type_hint) { if (cur_arg_info->type_hint == IS_ARRAY) { ZVAL_DEREF(arg); if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value))))) { - zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg); + zend_verify_arg_error(E_EXCEPTION | E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg); } } else if (cur_arg_info->type_hint == IS_CALLABLE) { if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value))))) { - zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg); + zend_verify_arg_error(E_EXCEPTION | E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg); } #if ZEND_DEBUG } else { @@ -718,13 +723,13 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_n char *class_name; need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce); - zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "none", "", NULL); + zend_verify_arg_error(E_EXCEPTION | E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "none", "", NULL); return 0; } else if (cur_arg_info->type_hint) { if (cur_arg_info->type_hint == IS_ARRAY) { - zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", "none", "", NULL); + zend_verify_arg_error(E_EXCEPTION | E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", "none", "", NULL); } else if (cur_arg_info->type_hint == IS_CALLABLE) { - zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", "none", "", NULL); + zend_verify_arg_error(E_EXCEPTION | E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", "none", "", NULL); #if ZEND_DEBUG } else { zend_error(E_ERROR, "Unknown typehint"); @@ -826,20 +831,20 @@ static void zend_verify_return_type(zend_function *zf, zval *ret) if (Z_TYPE_P(ret) == IS_OBJECT) { need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce); if (!ce || !instanceof_function(Z_OBJCE_P(ret), ce)) { - zend_verify_return_error(E_RECOVERABLE_ERROR, zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val); + zend_verify_return_error(E_EXCEPTION | E_RECOVERABLE_ERROR, zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val); } } else if (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null) { need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce); - zend_verify_return_error(E_RECOVERABLE_ERROR, zf, need_msg, class_name, zend_zval_type_name(ret), ""); + zend_verify_return_error(E_EXCEPTION | E_RECOVERABLE_ERROR, zf, need_msg, class_name, zend_zval_type_name(ret), ""); } } else if (ret_info->type_hint) { if (ret_info->type_hint == IS_ARRAY) { if (Z_TYPE_P(ret) != IS_ARRAY && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) { - zend_verify_return_error(E_RECOVERABLE_ERROR, zf, "be of the type array", "", zend_zval_type_name(ret), ""); + zend_verify_return_error(E_EXCEPTION | E_RECOVERABLE_ERROR, zf, "be of the type array", "", zend_zval_type_name(ret), ""); } } else if (ret_info->type_hint == IS_CALLABLE) { if (!zend_is_callable(ret, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) { - zend_verify_return_error(E_RECOVERABLE_ERROR, zf, "be callable", "", zend_zval_type_name(ret), ""); + zend_verify_return_error(E_EXCEPTION | E_RECOVERABLE_ERROR, zf, "be callable", "", zend_zval_type_name(ret), ""); } #if ZEND_DEBUG } else { @@ -859,13 +864,13 @@ static inline int zend_verify_missing_return_type(zend_function *zf) char *class_name; need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce); - zend_verify_return_error(E_RECOVERABLE_ERROR, zf, need_msg, class_name, "none", ""); + zend_verify_return_error(E_EXCEPTION | E_RECOVERABLE_ERROR, zf, need_msg, class_name, "none", ""); return 0; } else if (ret_info->type_hint) { if (ret_info->type_hint == IS_ARRAY) { - zend_verify_return_error(E_RECOVERABLE_ERROR, zf, "be of the type array", "", "none", ""); + zend_verify_return_error(E_EXCEPTION | E_RECOVERABLE_ERROR, zf, "be of the type array", "", "none", ""); } else if (ret_info->type_hint == IS_CALLABLE) { - zend_verify_return_error(E_RECOVERABLE_ERROR, zf, "be callable", "", "none", ""); + zend_verify_return_error(E_EXCEPTION | E_RECOVERABLE_ERROR, zf, "be callable", "", "none", ""); #if ZEND_DEBUG } else { zend_error(E_ERROR, "Unknown typehint"); diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index a8c589964b..50548c58e7 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -286,7 +286,7 @@ ZEND_API void zend_generator_create_zval(zend_execute_data *call, zend_op_array static zend_function *zend_generator_get_constructor(zend_object *object) /* {{{ */ { - zend_error(E_RECOVERABLE_ERROR, "The \"Generator\" class is reserved for internal use and cannot be manually instantiated"); + zend_error(E_EXCEPTION | E_RECOVERABLE_ERROR, "The \"Generator\" class is reserved for internal use and cannot be manually instantiated"); return NULL; } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 551e98bd52..c08280aaa2 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -359,7 +359,11 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR| zval *zptr; if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + FREE_OP2(); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } do { @@ -439,7 +443,11 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMPVAR| SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + FREE_UNFETCHED_OP2(); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } dim = GET_OP2_ZVAL_PTR(BP_VAR_R); @@ -464,7 +472,11 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMPVAR| var_ptr = Z_INDIRECT(rv); if (UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + FREE_OP2(); + FREE_OP(free_op_data1); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } if (UNEXPECTED(var_ptr == &EG(error_zval))) { @@ -503,7 +515,10 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|CV, CONST|TMPVAR|CV, int (*b var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW); if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + FREE_OP2(); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { @@ -762,7 +777,10 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|C retval = EX_VAR(opline->result.var); if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + FREE_OP2(); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } do { @@ -852,7 +870,10 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR| retval = EX_VAR(opline->result.var); if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + FREE_OP2(); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } do { @@ -930,7 +951,9 @@ ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY) var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW); if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { @@ -973,7 +996,9 @@ ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY) var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW); if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { @@ -1016,7 +1041,9 @@ ZEND_VM_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY) var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW); if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { @@ -1052,7 +1079,9 @@ ZEND_VM_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY) var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW); if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { @@ -1306,7 +1335,9 @@ ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMPVAR|UNUSED|CV) container = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE); FREE_OP2(); @@ -1328,7 +1359,9 @@ ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMPVAR|UNUSED|CV) container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW); if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE); FREE_OP2(); @@ -1365,11 +1398,17 @@ ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUS if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + FREE_UNFETCHED_OP2(); + FREE_UNFETCHED_OP1(); + HANDLE_EXCEPTION(); } container = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP2(); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE); if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) { @@ -1379,7 +1418,10 @@ ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUS FREE_OP1_VAR_PTR(); } else { if (OP2_TYPE == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use [] for reading"); + FREE_UNFETCHED_OP2(); + FREE_UNFETCHED_OP1(); + HANDLE_EXCEPTION(); } container = GET_OP1_ZVAL_PTR(BP_VAR_R); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE); @@ -1400,7 +1442,10 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMPVAR|CV) container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_UNSET); if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP2(); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE); FREE_OP2(); @@ -1490,7 +1535,10 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMPVAR|CV) container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + FREE_OP2(); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); @@ -1515,7 +1563,10 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMPVAR|CV) container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + FREE_OP2(); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW); FREE_OP2(); @@ -1607,11 +1658,17 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|CV, CONST|TMPV property = GET_OP2_ZVAL_PTR(BP_VAR_R); container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); - if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } + if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + FREE_OP2(); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); + } if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + FREE_OP2(); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); FREE_OP2(); @@ -1637,7 +1694,10 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|CV, CONST|TMPVAR|CV) property = GET_OP2_ZVAL_PTR(BP_VAR_R); if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + FREE_OP2(); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET); FREE_OP2(); @@ -1697,7 +1757,10 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV) property_name = GET_OP2_ZVAL_PTR(BP_VAR_R); if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_OP2(); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, OP1_TYPE, property_name, OP2_TYPE, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL)); FREE_OP2(); @@ -1722,7 +1785,11 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMPVAR|UNUSED|CV) object_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); if (OP1_TYPE == IS_VAR && UNEXPECTED(object_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + FREE_UNFETCHED_OP2(); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } ZEND_VM_C_LABEL(try_assign_dim): @@ -1849,7 +1916,10 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV) value_ptr = GET_OP2_ZVAL_PTR_PTR(BP_VAR_W); if (OP2_TYPE == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + FREE_OP2_VAR_PTR(); + FREE_UNFETCHED_OP1(); + HANDLE_EXCEPTION(); } if (OP2_TYPE == IS_VAR && (value_ptr == &EG(uninitialized_zval) || @@ -1868,12 +1938,18 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV) variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); if (OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + FREE_OP2_VAR_PTR(); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && UNEXPECTED(!Z_ISREF_P(variable_ptr))) { - zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot assign by reference to overloaded object"); + FREE_OP2_VAR_PTR(); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } if ((OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || (OP2_TYPE == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { @@ -2312,7 +2388,7 @@ ZEND_VM_C_LABEL(try_class_name): if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string"); + zend_error(E_EXCEPTION | E_ERROR, "Class name must be a valid object or a string"); } FREE_OP2(); @@ -2335,7 +2411,8 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMPVAR|UNUSED|CV, CONST|TMPVAR|CV) function_name = GET_OP2_ZVAL_PTR(BP_VAR_R); - if (OP2_TYPE != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (OP2_TYPE != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { do { if ((OP2_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { function_name = Z_REFVAL_P(function_name); @@ -2346,69 +2423,27 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMPVAR|UNUSED|CV, CONST|TMPVAR|CV) if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Method name must be a string"); + zend_error(E_EXCEPTION | E_ERROR, "Method name must be a string"); + FREE_OP2(); + FREE_UNFETCHED_OP1(); + HANDLE_EXCEPTION(); } while (0); } object = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R); - do { - if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - uint32_t nesting = 1; - - if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(object)) { - object = Z_REFVAL_P(object); - if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { - break; - } - } - + if (OP1_TYPE != IS_UNUSED) { + ZVAL_DEREF(object); + if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (UNEXPECTED(EG(exception) != NULL)) { - FREE_OP2(); HANDLE_EXCEPTION(); } - - zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + zend_error(E_EXCEPTION | E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); FREE_OP2(); FREE_OP1(); - - if (EG(exception) != NULL) { - HANDLE_EXCEPTION(); - } - - /* No exception raised: Skip over arguments until fcall opcode with correct - * nesting level. Return NULL (except when return value unused) */ - do { - opline++; - if (opline->opcode == ZEND_INIT_FCALL || - opline->opcode == ZEND_INIT_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_DYNAMIC_CALL || - opline->opcode == ZEND_INIT_METHOD_CALL || - opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || - opline->opcode == ZEND_INIT_USER_CALL || - opline->opcode == ZEND_NEW - ) { - nesting++; - } else if (opline->opcode == ZEND_DO_FCALL || - opline->opcode == ZEND_DO_ICALL || - opline->opcode == ZEND_DO_UCALL || - opline->opcode == ZEND_DO_FCALL_BY_NAME) { - nesting--; - } - } while (nesting); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - - /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ - if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { - opline++; - } - ZEND_VM_JMP(++opline); + HANDLE_EXCEPTION(); } - } while (0); + } obj = Z_OBJ_P(object); called_scope = obj->ce; @@ -2418,13 +2453,19 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMPVAR|UNUSED|CV, CONST|TMPVAR|CV) zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { - zend_error_noreturn(E_ERROR, "Object does not support method calls"); + zend_error(E_EXCEPTION | E_ERROR, "Object does not support method calls"); + FREE_OP2(); + FREE_OP1(); + HANDLE_EXCEPTION(); } /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((OP2_TYPE == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL)); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + FREE_OP2(); + FREE_OP1(); + HANDLE_EXCEPTION(); } if (OP2_TYPE == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -2470,7 +2511,8 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); } @@ -2495,7 +2537,9 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Function name must be a string"); + zend_error(E_EXCEPTION | E_ERROR, "Function name must be a string"); + FREE_OP2(); + HANDLE_EXCEPTION(); } } @@ -2505,7 +2549,9 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((OP2_TYPE == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL)); } if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); + FREE_OP2(); + HANDLE_EXCEPTION(); } if (OP2_TYPE == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -2521,10 +2567,12 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE } } else { if (UNEXPECTED(ce->constructor == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot call constructor"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call constructor"); + HANDLE_EXCEPTION(); } if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { - zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call private %s::__construct()", ce->name->val); + HANDLE_EXCEPTION(); } fbc = ce->constructor; } @@ -2547,11 +2595,12 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE object ? ", assuming $this from incompatible context" : ""); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, + zend_error( + E_EXCEPTION | E_ERROR, "Non-static method %s::%s() cannot be called statically%s", fbc->common.scope->name->val, fbc->common.function_name->val, object ? ", assuming $this from incompatible context" : ""); + HANDLE_EXCEPTION(); } } } @@ -2586,7 +2635,8 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST) function_name = (zval*)(EX_CONSTANT(opline->op2)+1); if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) { SAVE_OPLINE(); - zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + HANDLE_EXCEPTION(); } else { fbc = Z_FUNC_P(func); CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc); @@ -2621,7 +2671,9 @@ ZEND_VM_C_LABEL(try_function_name): lcname = zend_string_tolower(Z_STR_P(function_name)); } if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name)); + FREE_OP2(); + HANDLE_EXCEPTION(); } zend_string_release(lcname); FREE_OP2(); @@ -2650,17 +2702,23 @@ ZEND_VM_C_LABEL(try_function_name): method = zend_hash_index_find(Z_ARRVAL_P(function_name), 1); if (!obj || !method) { - zend_error_noreturn(E_ERROR, "Array callback has to contain indices 0 and 1"); + zend_error(E_EXCEPTION | E_ERROR, "Array callback has to contain indices 0 and 1"); + FREE_OP2(); + HANDLE_EXCEPTION(); } ZVAL_DEREF(obj); if (Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_OBJECT) { - zend_error_noreturn(E_ERROR, "First array member is not a valid class name or object"); + zend_error(E_EXCEPTION | E_ERROR, "First array member is not a valid class name or object"); + FREE_OP2(); + HANDLE_EXCEPTION(); } ZVAL_DEREF(method); if (Z_TYPE_P(method) != IS_STRING) { - zend_error_noreturn(E_ERROR, "Second array member is not a valid method"); + zend_error(E_EXCEPTION | E_ERROR, "Second array member is not a valid method"); + FREE_OP2(); + HANDLE_EXCEPTION(); } if (Z_TYPE_P(obj) == IS_STRING) { @@ -2677,7 +2735,9 @@ ZEND_VM_C_LABEL(try_function_name): fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL); } if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method)); + FREE_OP2(); + HANDLE_EXCEPTION(); } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -2685,10 +2745,12 @@ ZEND_VM_C_LABEL(try_function_name): "Non-static method %s::%s() should not be called statically", fbc->common.scope->name->val, fbc->common.function_name->val); } else { - zend_error_noreturn( - E_ERROR, + zend_error( + E_EXCEPTION | E_ERROR, "Non-static method %s::%s() cannot be called statically", fbc->common.scope->name->val, fbc->common.function_name->val); + FREE_OP2(); + HANDLE_EXCEPTION(); } } } else { @@ -2697,7 +2759,9 @@ ZEND_VM_C_LABEL(try_function_name): fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method)); + FREE_OP2(); + HANDLE_EXCEPTION(); } if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { @@ -2714,8 +2778,9 @@ ZEND_VM_C_LABEL(try_function_name): if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Function name must be a string"); - ZEND_VM_CONTINUE(); /* Never reached */ + zend_error(E_EXCEPTION | E_ERROR, "Function name must be a string"); + FREE_OP2(); + HANDLE_EXCEPTION(); } EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, called_scope, object, EX(call)); @@ -2756,10 +2821,12 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV) "Non-static method %s::%s() should not be called statically", func->common.scope->name->val, func->common.function_name->val); } else { - zend_error_noreturn( - E_ERROR, + zend_error( + E_EXCEPTION | E_ERROR, "Non-static method %s::%s() cannot be called statically", func->common.scope->name->val, func->common.function_name->val); + FREE_OP2(); + HANDLE_EXCEPTION(); } } } else { @@ -2792,7 +2859,8 @@ ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST) func_name++; if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(func_name))) == NULL)) { SAVE_OPLINE(); - zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + HANDLE_EXCEPTION(); } else { fbc = Z_FUNC_P(func); CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc); @@ -2820,7 +2888,8 @@ ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, ANY, CONST) fbc = CACHED_PTR(Z_CACHE_SLOT_P(fname)); } else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(fname))) == NULL)) { SAVE_OPLINE(); - zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(fname)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(fname)); + HANDLE_EXCEPTION(); } else { fbc = Z_FUNC_P(func); CACHE_PTR(Z_CACHE_SLOT_P(fname), fbc); @@ -3026,7 +3095,8 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) EX(call) = call->prev_execute_data; if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) { if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) { - zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name->val, fbc->common.function_name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name->val, fbc->common.function_name->val); + HANDLE_EXCEPTION(); } if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated", @@ -3097,20 +3167,20 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) for (i = 0; i < num_args; ++i) { zend_verify_internal_arg_type(fbc, i + 1, p); - p++; - } - if (UNEXPECTED(EG(exception) != NULL)) { - EG(current_execute_data) = call->prev_execute_data; - zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); - if (RETURN_VALUE_USED(opline)) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - } - if (UNEXPECTED(should_change_scope)) { - ZEND_VM_C_GOTO(fcall_end_change_scope); - } else { - ZEND_VM_C_GOTO(fcall_end); + if (UNEXPECTED(EG(exception) != NULL)) { + EG(current_execute_data) = call->prev_execute_data; + zend_vm_stack_free_args(call); + zend_vm_stack_free_call_frame(call); + if (RETURN_VALUE_USED(opline)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + if (UNEXPECTED(should_change_scope)) { + ZEND_VM_C_GOTO(fcall_end_change_scope); + } else { + ZEND_VM_C_GOTO(fcall_end); + } } + p++; } } @@ -3155,7 +3225,8 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) object->handlers->call_method(fbc->common.function_name, object, call, EX_VAR(opline->result.var)); EG(current_execute_data) = call->prev_execute_data; } else { - zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call overloaded function for non-object"); + HANDLE_EXCEPTION(); } zend_vm_stack_free_args(call); @@ -3285,7 +3356,9 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY) retval_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); if (OP1_TYPE == IS_VAR && UNEXPECTED(retval_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot return string offsets by reference"); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } if (OP1_TYPE == IS_VAR) { @@ -3346,7 +3419,9 @@ ZEND_VM_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY) if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Can only throw objects"); + zend_error(E_EXCEPTION | E_ERROR, "Can only throw objects"); + FREE_OP1(); + HANDLE_EXCEPTION(); } } while (0); @@ -3438,7 +3513,9 @@ ZEND_VM_HANDLER(116, ZEND_SEND_VAL_EX, CONST|TMP, ANY) SAVE_OPLINE(); if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { - zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.num); + zend_error(E_EXCEPTION | E_ERROR, "Cannot pass parameter %d by reference", opline->op2.num); + FREE_UNFETCHED_OP1(); + HANDLE_EXCEPTION(); } value = GET_OP1_ZVAL_PTR(BP_VAR_R); arg = ZEND_CALL_VAR(EX(call), opline->result.var); @@ -3519,7 +3596,9 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY) varptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); if (OP1_TYPE == IS_VAR && UNEXPECTED(varptr == NULL)) { - zend_error_noreturn(E_ERROR, "Only variables can be passed by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Only variables can be passed by reference"); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } arg = ZEND_CALL_VAR(EX(call), opline->result.var); @@ -3606,10 +3685,9 @@ ZEND_VM_C_LABEL(send_again): ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) { if (name) { - zend_error(E_RECOVERABLE_ERROR, "Cannot unpack array with string keys"); + zend_error(E_EXCEPTION | E_RECOVERABLE_ERROR, "Cannot unpack array with string keys"); FREE_OP1(); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + HANDLE_EXCEPTION(); } top = ZEND_CALL_ARG(EX(call), arg_num); @@ -3680,7 +3758,7 @@ ZEND_VM_C_LABEL(send_again): } if (Z_TYPE(key) == IS_STRING) { - zend_error(E_RECOVERABLE_ERROR, + zend_error(E_EXCEPTION | E_RECOVERABLE_ERROR, "Cannot unpack Traversable with string keys"); zend_string_release(Z_STR(key)); ZEND_VM_C_GOTO(unpack_iter_dtor); @@ -4133,12 +4211,13 @@ ZEND_VM_HANDLER(68, ZEND_NEW, CONST|VAR, ANY) } if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) { if (ce->ce_flags & ZEND_ACC_INTERFACE) { - zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate interface %s", ce->name->val); } else if (ce->ce_flags & ZEND_ACC_TRAIT) { - zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate trait %s", ce->name->val); } else { - zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate abstract class %s", ce->name->val); } + HANDLE_EXCEPTION(); } object_init_ex(&object_zval, ce); constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval)); @@ -4197,7 +4276,9 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|CV, ANY) if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "__clone method called on non-object"); + zend_error(E_EXCEPTION | E_ERROR, "__clone method called on non-object"); + FREE_OP1(); + HANDLE_EXCEPTION(); } } while (0); @@ -4206,10 +4287,12 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|CV, ANY) clone_call = Z_OBJ_HT_P(obj)->clone_obj; if (UNEXPECTED(clone_call == NULL)) { if (ce) { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val); } else { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); + zend_error(E_EXCEPTION | E_ERROR, "Trying to clone an uncloneable object"); } + FREE_OP1(); + HANDLE_EXCEPTION(); } if (ce && clone) { @@ -4217,13 +4300,17 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|CV, ANY) /* Ensure that if we're calling a private function, we're allowed to do so. */ if (UNEXPECTED(ce != EG(scope))) { - zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + zend_error(E_EXCEPTION | E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + FREE_OP1(); + HANDLE_EXCEPTION(); } } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { - zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + zend_error(E_EXCEPTION | E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + FREE_OP1(); + HANDLE_EXCEPTION(); } } } @@ -4266,7 +4353,8 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST) CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + HANDLE_EXCEPTION(); } } else { CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c); @@ -4299,7 +4387,8 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST) HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); } @@ -4329,7 +4418,8 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST) /* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */ ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); } else { - zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + HANDLE_EXCEPTION(); } } ZEND_VM_C_LABEL(constant_fetch_end): @@ -4348,7 +4438,9 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSE (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); if (OP1_TYPE == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } ZVAL_MAKE_REF(expr_ptr); Z_ADDREF_P(expr_ptr); @@ -4739,7 +4831,11 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR) HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + if (OP1_TYPE != IS_CONST) { + zend_string_release(Z_STR(tmp)); + } + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce); } @@ -4771,7 +4867,10 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMPVAR|CV) SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET); if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + FREE_UNFETCHED_OP2(); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } offset = GET_OP2_ZVAL_PTR(BP_VAR_R); @@ -4824,25 +4923,22 @@ ZEND_VM_C_LABEL(num_index_dim): zend_error(E_WARNING, "Illegal offset type in unset"); break; } - FREE_OP2(); } else if (OP1_TYPE == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + } else { //??? if (OP2_TYPE == IS_CONST) { //??? zval_copy_ctor(offset); //??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); - FREE_OP2(); + Z_OBJ_HT_P(container)->unset_dimension(container, offset); + } } else if (OP1_TYPE != IS_UNUSED && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); ZEND_VM_C_GOTO(unset_dim_again); } else if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - } else { - FREE_OP2(); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); } + FREE_OP2(); FREE_OP1_VAR_PTR(); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -4858,7 +4954,10 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV) SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET); if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + FREE_UNFETCHED_OP2(); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); } offset = GET_OP2_ZVAL_PTR(BP_VAR_R); @@ -6417,10 +6516,8 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED) SAVE_OPLINE(); - if (UNEXPECTED((zfunc = zend_hash_find(EG(function_table), Z_STR_P(EX_CONSTANT(opline->op1)))) == NULL) || - UNEXPECTED(Z_FUNC_P(zfunc)->type != ZEND_USER_FUNCTION)) { - zend_error_noreturn(E_ERROR, "Base lambda function for closure not found"); - } + zfunc = zend_hash_find(EG(function_table), Z_STR_P(EX_CONSTANT(opline->op1))); + ZEND_ASSERT(zfunc != NULL && Z_FUNC_P(zfunc)->type == ZEND_USER_FUNCTION); closure_is_static = Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC; closure_is_being_defined_inside_static_context = EX(func)->common.fn_flags & ZEND_ACC_STATIC; @@ -6460,7 +6557,10 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + FREE_UNFETCHED_OP2(); + FREE_UNFETCHED_OP1(); + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -6493,7 +6593,10 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE zval *value_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); if (OP1_TYPE == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + FREE_UNFETCHED_OP2(); + FREE_OP1(); + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index daf6ad9957..320779c2e8 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -676,7 +676,8 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) EX(call) = call->prev_execute_data; if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) { if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) { - zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name->val, fbc->common.function_name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name->val, fbc->common.function_name->val); + HANDLE_EXCEPTION(); } if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated", @@ -747,20 +748,20 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) for (i = 0; i < num_args; ++i) { zend_verify_internal_arg_type(fbc, i + 1, p); - p++; - } - if (UNEXPECTED(EG(exception) != NULL)) { - EG(current_execute_data) = call->prev_execute_data; - zend_vm_stack_free_args(call); - zend_vm_stack_free_call_frame(call); - if (RETURN_VALUE_USED(opline)) { - ZVAL_UNDEF(EX_VAR(opline->result.var)); - } - if (UNEXPECTED(should_change_scope)) { - goto fcall_end_change_scope; - } else { - goto fcall_end; + if (UNEXPECTED(EG(exception) != NULL)) { + EG(current_execute_data) = call->prev_execute_data; + zend_vm_stack_free_args(call); + zend_vm_stack_free_call_frame(call); + if (RETURN_VALUE_USED(opline)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + if (UNEXPECTED(should_change_scope)) { + goto fcall_end_change_scope; + } else { + goto fcall_end; + } } + p++; } } @@ -805,7 +806,8 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) object->handlers->call_method(fbc->common.function_name, object, call, EX_VAR(opline->result.var)); EG(current_execute_data) = call->prev_execute_data; } else { - zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call overloaded function for non-object"); + HANDLE_EXCEPTION(); } zend_vm_stack_free_args(call); @@ -903,10 +905,9 @@ send_again: ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) { if (name) { - zend_error(E_RECOVERABLE_ERROR, "Cannot unpack array with string keys"); + zend_error(E_EXCEPTION | E_RECOVERABLE_ERROR, "Cannot unpack array with string keys"); FREE_OP(free_op1); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); + HANDLE_EXCEPTION(); } top = ZEND_CALL_ARG(EX(call), arg_num); @@ -977,7 +978,7 @@ send_again: } if (Z_TYPE(key) == IS_STRING) { - zend_error(E_RECOVERABLE_ERROR, + zend_error(E_EXCEPTION | E_RECOVERABLE_ERROR, "Cannot unpack Traversable with string keys"); zend_string_release(Z_STR(key)); goto unpack_iter_dtor; @@ -1746,7 +1747,7 @@ try_class_name: if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string"); + zend_error(E_EXCEPTION | E_ERROR, "Class name must be a valid object or a string"); } CHECK_EXCEPTION(); @@ -1766,7 +1767,8 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE function_name = (zval*)(EX_CONSTANT(opline->op2)+1); if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) { SAVE_OPLINE(); - zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + HANDLE_EXCEPTION(); } else { fbc = Z_FUNC_P(func); CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc); @@ -1801,7 +1803,9 @@ try_function_name: lcname = zend_string_tolower(Z_STR_P(function_name)); } if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name)); + + HANDLE_EXCEPTION(); } zend_string_release(lcname); @@ -1829,17 +1833,23 @@ try_function_name: method = zend_hash_index_find(Z_ARRVAL_P(function_name), 1); if (!obj || !method) { - zend_error_noreturn(E_ERROR, "Array callback has to contain indices 0 and 1"); + zend_error(E_EXCEPTION | E_ERROR, "Array callback has to contain indices 0 and 1"); + + HANDLE_EXCEPTION(); } ZVAL_DEREF(obj); if (Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_OBJECT) { - zend_error_noreturn(E_ERROR, "First array member is not a valid class name or object"); + zend_error(E_EXCEPTION | E_ERROR, "First array member is not a valid class name or object"); + + HANDLE_EXCEPTION(); } ZVAL_DEREF(method); if (Z_TYPE_P(method) != IS_STRING) { - zend_error_noreturn(E_ERROR, "Second array member is not a valid method"); + zend_error(E_EXCEPTION | E_ERROR, "Second array member is not a valid method"); + + HANDLE_EXCEPTION(); } if (Z_TYPE_P(obj) == IS_STRING) { @@ -1856,7 +1866,9 @@ try_function_name: fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL); } if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method)); + + HANDLE_EXCEPTION(); } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -1864,10 +1876,12 @@ try_function_name: "Non-static method %s::%s() should not be called statically", fbc->common.scope->name->val, fbc->common.function_name->val); } else { - zend_error_noreturn( - E_ERROR, + zend_error( + E_EXCEPTION | E_ERROR, "Non-static method %s::%s() cannot be called statically", fbc->common.scope->name->val, fbc->common.function_name->val); + + HANDLE_EXCEPTION(); } } } else { @@ -1876,7 +1890,9 @@ try_function_name: fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method)); + + HANDLE_EXCEPTION(); } if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { @@ -1893,8 +1909,9 @@ try_function_name: if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Function name must be a string"); - ZEND_VM_CONTINUE(); /* Never reached */ + zend_error(E_EXCEPTION | E_ERROR, "Function name must be a string"); + + HANDLE_EXCEPTION(); } EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, called_scope, object, EX(call)); @@ -1917,7 +1934,8 @@ static int ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPC func_name++; if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(func_name))) == NULL)) { SAVE_OPLINE(); - zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + HANDLE_EXCEPTION(); } else { fbc = Z_FUNC_P(func); CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc); @@ -1945,7 +1963,8 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER fbc = CACHED_PTR(Z_CACHE_SLOT_P(fname)); } else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(fname))) == NULL)) { SAVE_OPLINE(); - zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(fname)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(fname)); + HANDLE_EXCEPTION(); } else { fbc = Z_FUNC_P(func); CACHE_PTR(Z_CACHE_SLOT_P(fname), fbc); @@ -2098,7 +2117,7 @@ try_class_name: if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string"); + zend_error(E_EXCEPTION | E_ERROR, "Class name must be a valid object or a string"); } CHECK_EXCEPTION(); @@ -2141,7 +2160,7 @@ try_class_name: if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string"); + zend_error(E_EXCEPTION | E_ERROR, "Class name must be a valid object or a string"); } CHECK_EXCEPTION(); @@ -2171,7 +2190,9 @@ try_function_name: lcname = zend_string_tolower(Z_STR_P(function_name)); } if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name)); + + HANDLE_EXCEPTION(); } zend_string_release(lcname); @@ -2199,17 +2220,23 @@ try_function_name: method = zend_hash_index_find(Z_ARRVAL_P(function_name), 1); if (!obj || !method) { - zend_error_noreturn(E_ERROR, "Array callback has to contain indices 0 and 1"); + zend_error(E_EXCEPTION | E_ERROR, "Array callback has to contain indices 0 and 1"); + + HANDLE_EXCEPTION(); } ZVAL_DEREF(obj); if (Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_OBJECT) { - zend_error_noreturn(E_ERROR, "First array member is not a valid class name or object"); + zend_error(E_EXCEPTION | E_ERROR, "First array member is not a valid class name or object"); + + HANDLE_EXCEPTION(); } ZVAL_DEREF(method); if (Z_TYPE_P(method) != IS_STRING) { - zend_error_noreturn(E_ERROR, "Second array member is not a valid method"); + zend_error(E_EXCEPTION | E_ERROR, "Second array member is not a valid method"); + + HANDLE_EXCEPTION(); } if (Z_TYPE_P(obj) == IS_STRING) { @@ -2226,7 +2253,9 @@ try_function_name: fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL); } if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method)); + + HANDLE_EXCEPTION(); } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -2234,10 +2263,12 @@ try_function_name: "Non-static method %s::%s() should not be called statically", fbc->common.scope->name->val, fbc->common.function_name->val); } else { - zend_error_noreturn( - E_ERROR, + zend_error( + E_EXCEPTION | E_ERROR, "Non-static method %s::%s() cannot be called statically", fbc->common.scope->name->val, fbc->common.function_name->val); + + HANDLE_EXCEPTION(); } } } else { @@ -2246,7 +2277,9 @@ try_function_name: fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method)); + + HANDLE_EXCEPTION(); } if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { @@ -2263,8 +2296,9 @@ try_function_name: if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Function name must be a string"); - ZEND_VM_CONTINUE(); /* Never reached */ + zend_error(E_EXCEPTION | E_ERROR, "Function name must be a string"); + + HANDLE_EXCEPTION(); } EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, called_scope, object, EX(call)); @@ -2308,7 +2342,7 @@ try_class_name: if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string"); + zend_error(E_EXCEPTION | E_ERROR, "Class name must be a valid object or a string"); } zval_ptr_dtor_nogc(free_op2); @@ -2339,7 +2373,9 @@ try_function_name: lcname = zend_string_tolower(Z_STR_P(function_name)); } if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name)); + zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); } zend_string_release(lcname); zval_ptr_dtor_nogc(free_op2); @@ -2368,17 +2404,23 @@ try_function_name: method = zend_hash_index_find(Z_ARRVAL_P(function_name), 1); if (!obj || !method) { - zend_error_noreturn(E_ERROR, "Array callback has to contain indices 0 and 1"); + zend_error(E_EXCEPTION | E_ERROR, "Array callback has to contain indices 0 and 1"); + zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); } ZVAL_DEREF(obj); if (Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_OBJECT) { - zend_error_noreturn(E_ERROR, "First array member is not a valid class name or object"); + zend_error(E_EXCEPTION | E_ERROR, "First array member is not a valid class name or object"); + zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); } ZVAL_DEREF(method); if (Z_TYPE_P(method) != IS_STRING) { - zend_error_noreturn(E_ERROR, "Second array member is not a valid method"); + zend_error(E_EXCEPTION | E_ERROR, "Second array member is not a valid method"); + zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); } if (Z_TYPE_P(obj) == IS_STRING) { @@ -2395,7 +2437,9 @@ try_function_name: fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL); } if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method)); + zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { @@ -2403,10 +2447,12 @@ try_function_name: "Non-static method %s::%s() should not be called statically", fbc->common.scope->name->val, fbc->common.function_name->val); } else { - zend_error_noreturn( - E_ERROR, + zend_error( + E_EXCEPTION | E_ERROR, "Non-static method %s::%s() cannot be called statically", fbc->common.scope->name->val, fbc->common.function_name->val); + zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); } } } else { @@ -2415,7 +2461,9 @@ try_function_name: fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method)); + zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); } if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { @@ -2432,8 +2480,9 @@ try_function_name: if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Function name must be a string"); - ZEND_VM_CONTINUE(); /* Never reached */ + zend_error(E_EXCEPTION | E_ERROR, "Function name must be a string"); + zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); } EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, fbc, opline->extended_value, called_scope, object, EX(call)); @@ -2743,7 +2792,9 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND retval_ptr = NULL; if (IS_CONST == IS_VAR && UNEXPECTED(retval_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot return string offsets by reference"); + + HANDLE_EXCEPTION(); } if (IS_CONST == IS_VAR) { @@ -2791,7 +2842,9 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Can only throw objects"); + zend_error(E_EXCEPTION | E_ERROR, "Can only throw objects"); + + HANDLE_EXCEPTION(); } } while (0); @@ -2832,7 +2885,9 @@ static int ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { - zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.num); + zend_error(E_EXCEPTION | E_ERROR, "Cannot pass parameter %d by reference", opline->op2.num); + + HANDLE_EXCEPTION(); } value = EX_CONSTANT(opline->op1); arg = ZEND_CALL_VAR(EX(call), opline->result.var); @@ -2889,12 +2944,13 @@ static int ZEND_FASTCALL ZEND_NEW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) { if (ce->ce_flags & ZEND_ACC_INTERFACE) { - zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate interface %s", ce->name->val); } else if (ce->ce_flags & ZEND_ACC_TRAIT) { - zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate trait %s", ce->name->val); } else { - zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate abstract class %s", ce->name->val); } + HANDLE_EXCEPTION(); } object_init_ex(&object_zval, ce); constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval)); @@ -2953,7 +3009,9 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "__clone method called on non-object"); + zend_error(E_EXCEPTION | E_ERROR, "__clone method called on non-object"); + + HANDLE_EXCEPTION(); } } while (0); @@ -2962,10 +3020,12 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS clone_call = Z_OBJ_HT_P(obj)->clone_obj; if (UNEXPECTED(clone_call == NULL)) { if (ce) { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val); } else { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); + zend_error(E_EXCEPTION | E_ERROR, "Trying to clone an uncloneable object"); } + + HANDLE_EXCEPTION(); } if (ce && clone) { @@ -2973,13 +3033,17 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS /* Ensure that if we're calling a private function, we're allowed to do so. */ if (UNEXPECTED(ce != EG(scope))) { - zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + zend_error(E_EXCEPTION | E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + + HANDLE_EXCEPTION(); } } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { - zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + zend_error(E_EXCEPTION | E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + + HANDLE_EXCEPTION(); } } } @@ -4225,11 +4289,17 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_ if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + + HANDLE_EXCEPTION(); } container = NULL; if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1)) { @@ -4239,7 +4309,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_ } else { if (IS_CONST == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use [] for reading"); + + + HANDLE_EXCEPTION(); } container = EX_CONSTANT(opline->op1); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST); @@ -4394,11 +4467,17 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_ property = EX_CONSTANT(opline->op2); container = NULL; - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + + HANDLE_EXCEPTION(); + } if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); @@ -4469,7 +4548,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); } @@ -4494,7 +4574,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Function name must be a string"); + zend_error(E_EXCEPTION | E_ERROR, "Function name must be a string"); + + HANDLE_EXCEPTION(); } } @@ -4504,7 +4586,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL)); } if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); + + HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -4520,10 +4604,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( } } else { if (UNEXPECTED(ce->constructor == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot call constructor"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call constructor"); + HANDLE_EXCEPTION(); } if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { - zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call private %s::__construct()", ce->name->val); + HANDLE_EXCEPTION(); } fbc = ce->constructor; } @@ -4546,11 +4632,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( object ? ", assuming $this from incompatible context" : ""); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, + zend_error( + E_EXCEPTION | E_ERROR, "Non-static method %s::%s() cannot be called statically%s", fbc->common.scope->name->val, fbc->common.function_name->val, object ? ", assuming $this from incompatible context" : ""); + HANDLE_EXCEPTION(); } } } @@ -4605,10 +4692,12 @@ static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCO "Non-static method %s::%s() should not be called statically", func->common.scope->name->val, func->common.function_name->val); } else { - zend_error_noreturn( - E_ERROR, + zend_error( + E_EXCEPTION | E_ERROR, "Non-static method %s::%s() cannot be called statically", func->common.scope->name->val, func->common.function_name->val); + + HANDLE_EXCEPTION(); } } } else { @@ -4668,7 +4757,8 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + HANDLE_EXCEPTION(); } } else { CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c); @@ -4701,7 +4791,8 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); } @@ -4731,7 +4822,8 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO /* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */ ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); } else { - zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + HANDLE_EXCEPTION(); } } constant_fetch_end: @@ -4750,7 +4842,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_O (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); + + HANDLE_EXCEPTION(); } ZVAL_MAKE_REF(expr_ptr); Z_ADDREF_P(expr_ptr); @@ -4912,7 +5006,11 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HA HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + if (IS_CONST != IS_CONST) { + zend_string_release(Z_STR(tmp)); + } + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce); } @@ -5228,7 +5326,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLE zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + + + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -5261,7 +5362,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLE zval *value_ptr = NULL; if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + + + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -5405,7 +5509,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -5438,7 +5545,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ zval *value_ptr = NULL; if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -5786,7 +5896,11 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAND HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + if (IS_CONST != IS_CONST) { + zend_string_release(Z_STR(tmp)); + } + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce); } @@ -5913,7 +6027,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -5946,7 +6063,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ zval *value_ptr = NULL; if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -6219,11 +6339,17 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + + HANDLE_EXCEPTION(); } container = NULL; if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1)) { @@ -6233,7 +6359,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND } else { if (IS_UNUSED == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use [] for reading"); + + + HANDLE_EXCEPTION(); } container = EX_CONSTANT(opline->op1); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, NULL, IS_UNUSED); @@ -6264,7 +6393,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); } @@ -6289,7 +6419,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Function name must be a string"); + zend_error(E_EXCEPTION | E_ERROR, "Function name must be a string"); + + HANDLE_EXCEPTION(); } } @@ -6299,7 +6431,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_UNUSED == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL)); } if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); + + HANDLE_EXCEPTION(); } if (IS_UNUSED == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -6315,10 +6449,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER } } else { if (UNEXPECTED(ce->constructor == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot call constructor"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call constructor"); + HANDLE_EXCEPTION(); } if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { - zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call private %s::__construct()", ce->name->val); + HANDLE_EXCEPTION(); } fbc = ce->constructor; } @@ -6341,11 +6477,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER object ? ", assuming $this from incompatible context" : ""); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, + zend_error( + E_EXCEPTION | E_ERROR, "Non-static method %s::%s() cannot be called statically%s", fbc->common.scope->name->val, fbc->common.function_name->val, object ? ", assuming $this from incompatible context" : ""); + HANDLE_EXCEPTION(); } } } @@ -6398,7 +6535,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_ (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); + + HANDLE_EXCEPTION(); } ZVAL_MAKE_REF(expr_ptr); Z_ADDREF_P(expr_ptr); @@ -6560,7 +6699,11 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_H HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + if (IS_CONST != IS_CONST) { + zend_string_release(Z_STR(tmp)); + } + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce); } @@ -6687,10 +6830,8 @@ static int ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER SAVE_OPLINE(); - if (UNEXPECTED((zfunc = zend_hash_find(EG(function_table), Z_STR_P(EX_CONSTANT(opline->op1)))) == NULL) || - UNEXPECTED(Z_FUNC_P(zfunc)->type != ZEND_USER_FUNCTION)) { - zend_error_noreturn(E_ERROR, "Base lambda function for closure not found"); - } + zfunc = zend_hash_find(EG(function_table), Z_STR_P(EX_CONSTANT(opline->op1))); + ZEND_ASSERT(zfunc != NULL && Z_FUNC_P(zfunc)->type == ZEND_USER_FUNCTION); closure_is_static = Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC; closure_is_being_defined_inside_static_context = EX(func)->common.fn_flags & ZEND_ACC_STATIC; @@ -6712,7 +6853,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDL zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + + + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -6745,7 +6889,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDL zval *value_ptr = NULL; if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + + + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -7166,11 +7313,17 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPC if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + + HANDLE_EXCEPTION(); } container = NULL; if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1)) { @@ -7180,7 +7333,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPC } else { if (IS_CV == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use [] for reading"); + + + HANDLE_EXCEPTION(); } container = EX_CONSTANT(opline->op1); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV); @@ -7335,11 +7491,17 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPC property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); container = NULL; - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + + HANDLE_EXCEPTION(); + } if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); @@ -7374,7 +7536,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); } @@ -7399,7 +7562,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Function name must be a string"); + zend_error(E_EXCEPTION | E_ERROR, "Function name must be a string"); + + HANDLE_EXCEPTION(); } } @@ -7409,7 +7574,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL)); } if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); + + HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -7425,10 +7592,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN } } else { if (UNEXPECTED(ce->constructor == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot call constructor"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call constructor"); + HANDLE_EXCEPTION(); } if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { - zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call private %s::__construct()", ce->name->val); + HANDLE_EXCEPTION(); } fbc = ce->constructor; } @@ -7451,11 +7620,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN object ? ", assuming $this from incompatible context" : ""); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, + zend_error( + E_EXCEPTION | E_ERROR, "Non-static method %s::%s() cannot be called statically%s", fbc->common.scope->name->val, fbc->common.function_name->val, object ? ", assuming $this from incompatible context" : ""); + HANDLE_EXCEPTION(); } } } @@ -7510,10 +7680,12 @@ static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_ "Non-static method %s::%s() should not be called statically", func->common.scope->name->val, func->common.function_name->val); } else { - zend_error_noreturn( - E_ERROR, + zend_error( + E_EXCEPTION | E_ERROR, "Non-static method %s::%s() cannot be called statically", func->common.scope->name->val, func->common.function_name->val); + + HANDLE_EXCEPTION(); } } } else { @@ -7608,7 +7780,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCO (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); + + HANDLE_EXCEPTION(); } ZVAL_MAKE_REF(expr_ptr); Z_ADDREF_P(expr_ptr); @@ -7880,7 +8054,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + + + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -7913,7 +8090,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A zval *value_ptr = NULL; if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + + + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -8318,11 +8498,17 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER(ZEND if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } container = NULL; if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR)); if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1)) { @@ -8332,7 +8518,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER(ZEND } else { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use [] for reading"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } container = EX_CONSTANT(opline->op1); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR)); @@ -8489,11 +8678,17 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER(ZEND property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); container = NULL; - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); + } if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); zval_ptr_dtor_nogc(free_op2); @@ -8528,7 +8723,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); } @@ -8553,7 +8749,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Function name must be a string"); + zend_error(E_EXCEPTION | E_ERROR, "Function name must be a string"); + zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); } } @@ -8563,7 +8761,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL)); } if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); + zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -8579,10 +8779,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER } } else { if (UNEXPECTED(ce->constructor == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot call constructor"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call constructor"); + HANDLE_EXCEPTION(); } if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { - zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call private %s::__construct()", ce->name->val); + HANDLE_EXCEPTION(); } fbc = ce->constructor; } @@ -8605,11 +8807,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER object ? ", assuming $this from incompatible context" : ""); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, + zend_error( + E_EXCEPTION | E_ERROR, "Non-static method %s::%s() cannot be called statically%s", fbc->common.scope->name->val, fbc->common.function_name->val, object ? ", assuming $this from incompatible context" : ""); + HANDLE_EXCEPTION(); } } } @@ -8664,10 +8867,12 @@ static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPC "Non-static method %s::%s() should not be called statically", func->common.scope->name->val, func->common.function_name->val); } else { - zend_error_noreturn( - E_ERROR, + zend_error( + E_EXCEPTION | E_ERROR, "Non-static method %s::%s() cannot be called statically", func->common.scope->name->val, func->common.function_name->val); + zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); } } } else { @@ -8713,7 +8918,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_HANDLER(ZEND_ (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); + + HANDLE_EXCEPTION(); } ZVAL_MAKE_REF(expr_ptr); Z_ADDREF_P(expr_ptr); @@ -9058,7 +9265,9 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE retval_ptr = NULL; if (IS_TMP_VAR == IS_VAR && UNEXPECTED(retval_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot return string offsets by reference"); + + HANDLE_EXCEPTION(); } if (IS_TMP_VAR == IS_VAR) { @@ -9106,7 +9315,9 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Can only throw objects"); + zend_error(E_EXCEPTION | E_ERROR, "Can only throw objects"); + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } } while (0); @@ -9147,7 +9358,9 @@ static int ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { - zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.num); + zend_error(E_EXCEPTION | E_ERROR, "Cannot pass parameter %d by reference", opline->op2.num); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); arg = ZEND_CALL_VAR(EX(call), opline->result.var); @@ -9725,11 +9938,17 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OP if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } container = NULL; if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { @@ -9739,7 +9958,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OP } else { if (IS_CONST == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use [] for reading"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST); @@ -9829,11 +10051,17 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OP property = EX_CONSTANT(opline->op2); container = NULL; - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + + HANDLE_EXCEPTION(); + } if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); @@ -9897,7 +10125,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPC (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); + + HANDLE_EXCEPTION(); } ZVAL_MAKE_REF(expr_ptr); Z_ADDREF_P(expr_ptr); @@ -10013,7 +10243,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -10046,7 +10279,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ zval *value_ptr = NULL; if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -10175,7 +10411,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -10208,7 +10447,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR zval *value_ptr = NULL; if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -10337,7 +10579,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -10370,7 +10615,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR zval *value_ptr = NULL; if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -10470,11 +10718,17 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_O if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } container = NULL; if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { @@ -10484,7 +10738,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_O } else { if (IS_UNUSED == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use [] for reading"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, NULL, IS_UNUSED); @@ -10525,7 +10782,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OP (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); + + HANDLE_EXCEPTION(); } ZVAL_MAKE_REF(expr_ptr); Z_ADDREF_P(expr_ptr); @@ -10641,7 +10900,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -10674,7 +10936,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER zval *value_ptr = NULL; if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -10805,11 +11070,17 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCOD if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } container = NULL; if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { @@ -10819,7 +11090,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCOD } else { if (IS_CV == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use [] for reading"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV); @@ -10909,11 +11183,17 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCOD property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); container = NULL; - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + + HANDLE_EXCEPTION(); + } if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); @@ -10979,7 +11259,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); + + HANDLE_EXCEPTION(); } ZVAL_MAKE_REF(expr_ptr); Z_ADDREF_P(expr_ptr); @@ -11095,7 +11377,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -11128,7 +11413,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG zval *value_ptr = NULL; if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -11228,11 +11516,17 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_O if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } container = NULL; if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR)); if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { @@ -11242,7 +11536,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_O } else { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use [] for reading"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR)); @@ -11333,11 +11630,17 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_O property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); container = NULL; - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); + } if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); zval_ptr_dtor_nogc(free_op2); @@ -11404,7 +11707,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OP (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); + + HANDLE_EXCEPTION(); } ZVAL_MAKE_REF(expr_ptr); Z_ADDREF_P(expr_ptr); @@ -11522,7 +11827,9 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { @@ -11565,7 +11872,9 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { @@ -11608,7 +11917,9 @@ static int ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { @@ -11644,7 +11955,9 @@ static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { @@ -11734,7 +12047,9 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE retval_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(retval_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot return string offsets by reference"); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } if (IS_VAR == IS_VAR) { @@ -11783,7 +12098,9 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Can only throw objects"); + zend_error(E_EXCEPTION | E_ERROR, "Can only throw objects"); + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } } while (0); @@ -11866,7 +12183,9 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG varptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(varptr == NULL)) { - zend_error_noreturn(E_ERROR, "Only variables can be passed by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Only variables can be passed by reference"); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } arg = ZEND_CALL_VAR(EX(call), opline->result.var); @@ -12016,12 +12335,13 @@ static int ZEND_FASTCALL ZEND_NEW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) { if (ce->ce_flags & ZEND_ACC_INTERFACE) { - zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate interface %s", ce->name->val); } else if (ce->ce_flags & ZEND_ACC_TRAIT) { - zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate trait %s", ce->name->val); } else { - zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate abstract class %s", ce->name->val); } + HANDLE_EXCEPTION(); } object_init_ex(&object_zval, ce); constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval)); @@ -12956,7 +13276,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b zval *zptr; if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } do { @@ -13036,7 +13360,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(int (*b SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } dim = EX_CONSTANT(opline->op2); @@ -13061,7 +13389,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(int (*b var_ptr = Z_INDIRECT(rv); if (UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + + FREE_OP(free_op_data1); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } if (UNEXPECTED(var_ptr == &EG(error_zval))) { @@ -13099,7 +13431,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binar var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { @@ -13357,7 +13692,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t retval = EX_VAR(opline->result.var); if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } do { @@ -13446,7 +13784,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_ retval = EX_VAR(opline->result.var); if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } do { @@ -13523,7 +13864,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST); @@ -13545,7 +13888,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST); @@ -13567,11 +13912,17 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { @@ -13581,7 +13932,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; } else { if (IS_CONST == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use [] for reading"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST); @@ -13602,7 +13956,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST); @@ -13691,7 +14048,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); @@ -13716,7 +14076,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW); @@ -13742,11 +14105,17 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP property = EX_CONSTANT(opline->op2); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); + } if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); @@ -13772,7 +14141,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD property = EX_CONSTANT(opline->op2); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET); @@ -13796,7 +14168,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN property_name = EX_CONSTANT(opline->op2); if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_VAR, property_name, IS_CONST, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL)); @@ -13821,7 +14196,11 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } try_assign_dim: @@ -13956,7 +14335,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); } @@ -13981,7 +14361,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Function name must be a string"); + zend_error(E_EXCEPTION | E_ERROR, "Function name must be a string"); + + HANDLE_EXCEPTION(); } } @@ -13991,7 +14373,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL)); } if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); + + HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -14007,10 +14391,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE } } else { if (UNEXPECTED(ce->constructor == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot call constructor"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call constructor"); + HANDLE_EXCEPTION(); } if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { - zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call private %s::__construct()", ce->name->val); + HANDLE_EXCEPTION(); } fbc = ce->constructor; } @@ -14033,11 +14419,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE object ? ", assuming $this from incompatible context" : ""); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, + zend_error( + E_EXCEPTION | E_ERROR, "Non-static method %s::%s() cannot be called statically%s", fbc->common.scope->name->val, fbc->common.function_name->val, object ? ", assuming $this from incompatible context" : ""); + HANDLE_EXCEPTION(); } } } @@ -14087,7 +14474,8 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + HANDLE_EXCEPTION(); } } else { CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c); @@ -14120,7 +14508,8 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); } @@ -14150,7 +14539,8 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE /* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */ ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); } else { - zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + HANDLE_EXCEPTION(); } } constant_fetch_end: @@ -14169,7 +14559,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPC (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } ZVAL_MAKE_REF(expr_ptr); Z_ADDREF_P(expr_ptr); @@ -14288,7 +14680,10 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } offset = EX_CONSTANT(opline->op2); @@ -14341,25 +14736,22 @@ num_index_dim: zend_error(E_WARNING, "Illegal offset type in unset"); break; } - } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + } else { //??? if (IS_CONST == IS_CONST) { //??? zval_copy_ctor(offset); //??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); - + Z_OBJ_HT_P(container)->unset_dimension(container, offset); + } } else if (IS_VAR != IS_UNUSED && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); goto unset_dim_again; } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - } else { - + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); } + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -14375,7 +14767,10 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } offset = EX_CONSTANT(opline->op2); @@ -14410,7 +14805,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -14443,7 +14841,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -14610,7 +15011,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -14643,7 +15047,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -14809,7 +15216,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL value_ptr = _get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2); if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + if (free_op2) {zval_ptr_dtor_nogc(free_op2);}; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } if (IS_VAR == IS_VAR && (value_ptr == &EG(uninitialized_zval) || @@ -14828,12 +15238,18 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + if (free_op2) {zval_ptr_dtor_nogc(free_op2);}; + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && UNEXPECTED(!Z_ISREF_P(variable_ptr))) { - zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot assign by reference to overloaded object"); + if (free_op2) {zval_ptr_dtor_nogc(free_op2);}; + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } if ((IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { @@ -14861,7 +15277,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -14894,7 +15313,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -14995,7 +15417,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(int (* SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } dim = NULL; @@ -15020,7 +15446,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(int (* var_ptr = Z_INDIRECT(rv); if (UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + + FREE_OP(free_op_data1); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } if (UNEXPECTED(var_ptr == &EG(error_zval))) { @@ -15276,7 +15706,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_H container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED); @@ -15298,7 +15730,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_ container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, NULL, IS_UNUSED); @@ -15320,11 +15754,17 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_O if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { @@ -15334,7 +15774,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_O if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; } else { if (IS_UNUSED == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use [] for reading"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, NULL, IS_UNUSED); @@ -15359,7 +15802,11 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } try_assign_dim: @@ -15462,7 +15909,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); } @@ -15487,7 +15935,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Function name must be a string"); + zend_error(E_EXCEPTION | E_ERROR, "Function name must be a string"); + + HANDLE_EXCEPTION(); } } @@ -15497,7 +15947,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_UNUSED == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL)); } if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); + + HANDLE_EXCEPTION(); } if (IS_UNUSED == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -15513,10 +15965,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z } } else { if (UNEXPECTED(ce->constructor == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot call constructor"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call constructor"); + HANDLE_EXCEPTION(); } if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { - zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call private %s::__construct()", ce->name->val); + HANDLE_EXCEPTION(); } fbc = ce->constructor; } @@ -15539,11 +15993,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z object ? ", assuming $this from incompatible context" : ""); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, + zend_error( + E_EXCEPTION | E_ERROR, "Non-static method %s::%s() cannot be called statically%s", fbc->common.scope->name->val, fbc->common.function_name->val, object ? ", assuming $this from incompatible context" : ""); + HANDLE_EXCEPTION(); } } } @@ -15596,7 +16051,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OP (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } ZVAL_MAKE_REF(expr_ptr); Z_ADDREF_P(expr_ptr); @@ -15730,7 +16187,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -15763,7 +16223,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -15895,7 +16358,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina zval *zptr; if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } do { @@ -15975,7 +16442,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CV(int (*bina SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); @@ -16000,7 +16471,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CV(int (*bina var_ptr = Z_INDIRECT(rv); if (UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + + FREE_OP(free_op_data1); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } if (UNEXPECTED(var_ptr == &EG(error_zval))) { @@ -16038,7 +16513,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CV(int (*binary_o var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { @@ -16296,7 +16774,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t in retval = EX_VAR(opline->result.var); if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } do { @@ -16385,7 +16866,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t i retval = EX_VAR(opline->result.var); if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } do { @@ -16462,7 +16946,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV); @@ -16484,7 +16970,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV); @@ -16506,11 +16994,17 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { @@ -16520,7 +17014,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; } else { if (IS_CV == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use [] for reading"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV); @@ -16541,7 +17038,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV); @@ -16630,7 +17130,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); @@ -16655,7 +17158,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW); @@ -16681,11 +17187,17 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); + } if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); @@ -16711,7 +17223,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET); @@ -16735,7 +17250,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_VAR, property_name, IS_CV, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL)); @@ -16760,7 +17278,11 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } try_assign_dim: @@ -16886,7 +17408,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op2.var); if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } if (IS_CV == IS_VAR && (value_ptr == &EG(uninitialized_zval) || @@ -16905,12 +17430,18 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && UNEXPECTED(!Z_ISREF_P(variable_ptr))) { - zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot assign by reference to overloaded object"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } if ((IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || (IS_CV == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { @@ -16949,7 +17480,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); } @@ -16974,7 +17506,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Function name must be a string"); + zend_error(E_EXCEPTION | E_ERROR, "Function name must be a string"); + + HANDLE_EXCEPTION(); } } @@ -16984,7 +17518,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL)); } if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); + + HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -17000,10 +17536,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ } } else { if (UNEXPECTED(ce->constructor == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot call constructor"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call constructor"); + HANDLE_EXCEPTION(); } if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { - zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call private %s::__construct()", ce->name->val); + HANDLE_EXCEPTION(); } fbc = ce->constructor; } @@ -17026,11 +17564,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ object ? ", assuming $this from incompatible context" : ""); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, + zend_error( + E_EXCEPTION | E_ERROR, "Non-static method %s::%s() cannot be called statically%s", fbc->common.scope->name->val, fbc->common.function_name->val, object ? ", assuming $this from incompatible context" : ""); + HANDLE_EXCEPTION(); } } } @@ -17064,7 +17603,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } ZVAL_MAKE_REF(expr_ptr); Z_ADDREF_P(expr_ptr); @@ -17183,7 +17724,10 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); @@ -17236,25 +17780,22 @@ num_index_dim: zend_error(E_WARNING, "Illegal offset type in unset"); break; } - } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + } else { //??? if (IS_CV == IS_CONST) { //??? zval_copy_ctor(offset); //??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); - + Z_OBJ_HT_P(container)->unset_dimension(container, offset); + } } else if (IS_VAR != IS_UNUSED && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); goto unset_dim_again; } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - } else { - + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); } + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -17270,7 +17811,10 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); @@ -17305,7 +17849,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -17338,7 +17885,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -17444,7 +17994,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMPVAR(int (* zval *zptr; if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(free_op2); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } do { @@ -17524,7 +18078,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(int (* SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); @@ -17549,7 +18107,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(int (* var_ptr = Z_INDIRECT(rv); if (UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zval_ptr_dtor_nogc(free_op2); + FREE_OP(free_op_data1); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } if (UNEXPECTED(var_ptr == &EG(error_zval))) { @@ -17588,7 +18150,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_TMPVAR(int (*bina var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zval_ptr_dtor_nogc(free_op2); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { @@ -17847,7 +18412,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMPVAR(incdec_ retval = EX_VAR(opline->result.var); if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zval_ptr_dtor_nogc(free_op2); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } do { @@ -17937,7 +18505,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMPVAR(incdec retval = EX_VAR(opline->result.var); if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zval_ptr_dtor_nogc(free_op2); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } do { @@ -18015,7 +18586,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_H container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR)); zval_ptr_dtor_nogc(free_op2); @@ -18037,7 +18610,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_ container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR)); zval_ptr_dtor_nogc(free_op2); @@ -18059,11 +18634,17 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER(ZEND_O if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR)); if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) { @@ -18073,7 +18654,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER(ZEND_O if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; } else { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use [] for reading"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR)); @@ -18094,7 +18678,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCO container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR)); zval_ptr_dtor_nogc(free_op2); @@ -18184,7 +18771,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_H container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + zval_ptr_dtor_nogc(free_op2); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); @@ -18209,7 +18799,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_ container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + zval_ptr_dtor_nogc(free_op2); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW); zval_ptr_dtor_nogc(free_op2); @@ -18235,11 +18828,17 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER(ZEND_O property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + zval_ptr_dtor_nogc(free_op2); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); + } if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + zval_ptr_dtor_nogc(free_op2); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); zval_ptr_dtor_nogc(free_op2); @@ -18265,7 +18864,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCO property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + zval_ptr_dtor_nogc(free_op2); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET); zval_ptr_dtor_nogc(free_op2); @@ -18289,7 +18891,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HA property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + zval_ptr_dtor_nogc(free_op2); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_VAR, property_name, (IS_TMP_VAR|IS_VAR), (opline+1)->op1_type, (opline+1)->op1, execute_data, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL)); zval_ptr_dtor_nogc(free_op2); @@ -18314,7 +18919,11 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HA object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } try_assign_dim: @@ -18417,7 +19026,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER(Z HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); } @@ -18442,7 +19052,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER(Z if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Function name must be a string"); + zend_error(E_EXCEPTION | E_ERROR, "Function name must be a string"); + zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); } } @@ -18452,7 +19064,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER(Z fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL)); } if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name)); + zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -18468,10 +19082,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER(Z } } else { if (UNEXPECTED(ce->constructor == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot call constructor"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call constructor"); + HANDLE_EXCEPTION(); } if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { - zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot call private %s::__construct()", ce->name->val); + HANDLE_EXCEPTION(); } fbc = ce->constructor; } @@ -18494,11 +19110,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER(Z object ? ", assuming $this from incompatible context" : ""); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, + zend_error( + E_EXCEPTION | E_ERROR, "Non-static method %s::%s() cannot be called statically%s", fbc->common.scope->name->val, fbc->common.function_name->val, object ? ", assuming $this from incompatible context" : ""); + HANDLE_EXCEPTION(); } } } @@ -18532,7 +19149,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER(ZEND_OP (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } ZVAL_MAKE_REF(expr_ptr); Z_ADDREF_P(expr_ptr); @@ -18651,7 +19270,10 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); @@ -18704,25 +19326,22 @@ num_index_dim: zend_error(E_WARNING, "Illegal offset type in unset"); break; } - zval_ptr_dtor_nogc(free_op2); } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + } else { //??? if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { //??? zval_copy_ctor(offset); //??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); - zval_ptr_dtor_nogc(free_op2); + Z_OBJ_HT_P(container)->unset_dimension(container, offset); + } } else if (IS_VAR != IS_UNUSED && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); goto unset_dim_again; } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - } else { - zval_ptr_dtor_nogc(free_op2); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); } + zval_ptr_dtor_nogc(free_op2); if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -18738,7 +19357,10 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); } offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); @@ -18795,7 +19417,9 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARG if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "__clone method called on non-object"); + zend_error(E_EXCEPTION | E_ERROR, "__clone method called on non-object"); + + HANDLE_EXCEPTION(); } } while (0); @@ -18804,10 +19428,12 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARG clone_call = Z_OBJ_HT_P(obj)->clone_obj; if (UNEXPECTED(clone_call == NULL)) { if (ce) { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val); } else { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); + zend_error(E_EXCEPTION | E_ERROR, "Trying to clone an uncloneable object"); } + + HANDLE_EXCEPTION(); } if (ce && clone) { @@ -18815,13 +19441,17 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARG /* Ensure that if we're calling a private function, we're allowed to do so. */ if (UNEXPECTED(ce != EG(scope))) { - zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + zend_error(E_EXCEPTION | E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + + HANDLE_EXCEPTION(); } } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { - zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + zend_error(E_EXCEPTION | E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + + HANDLE_EXCEPTION(); } } } @@ -18878,7 +19508,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int zval *zptr; if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + + HANDLE_EXCEPTION(); } do { @@ -18958,7 +19592,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(int SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + + HANDLE_EXCEPTION(); } dim = EX_CONSTANT(opline->op2); @@ -18983,7 +19621,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(int var_ptr = Z_INDIRECT(rv); if (UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + + FREE_OP(free_op_data1); + + HANDLE_EXCEPTION(); } if (UNEXPECTED(var_ptr == &EG(error_zval))) { @@ -19244,7 +19886,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incde retval = EX_VAR(opline->result.var); if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + + + HANDLE_EXCEPTION(); } do { @@ -19333,7 +19978,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incd retval = EX_VAR(opline->result.var); if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + + + HANDLE_EXCEPTION(); } do { @@ -19477,7 +20125,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE container = _get_obj_zval_ptr_unused(execute_data); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); @@ -19502,7 +20153,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCOD container = _get_obj_zval_ptr_unused(execute_data); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW); @@ -19593,11 +20247,17 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND property = EX_CONSTANT(opline->op2); container = _get_obj_zval_ptr_unused(execute_data); - if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + + HANDLE_EXCEPTION(); + } if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); @@ -19623,7 +20283,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_HANDLER(ZEND_OP property = EX_CONSTANT(opline->op2); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET); @@ -19647,7 +20310,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_ property_name = EX_CONSTANT(opline->op2); if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + + HANDLE_EXCEPTION(); } zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_UNUSED, property_name, IS_CONST, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL)); @@ -19710,7 +20376,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O function_name = EX_CONSTANT(opline->op2); - if (IS_CONST != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (IS_CONST != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { do { if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { function_name = Z_REFVAL_P(function_name); @@ -19721,68 +20388,27 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Method name must be a string"); + zend_error(E_EXCEPTION | E_ERROR, "Method name must be a string"); + + + HANDLE_EXCEPTION(); } while (0); } object = _get_obj_zval_ptr_unused(execute_data); - do { - if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - uint32_t nesting = 1; - - if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(object)) { - object = Z_REFVAL_P(object); - if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { - break; - } - } - + if (IS_UNUSED != IS_UNUSED) { + ZVAL_DEREF(object); + if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); } - - zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + zend_error(E_EXCEPTION | E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); - if (EG(exception) != NULL) { - HANDLE_EXCEPTION(); - } - - /* No exception raised: Skip over arguments until fcall opcode with correct - * nesting level. Return NULL (except when return value unused) */ - do { - opline++; - if (opline->opcode == ZEND_INIT_FCALL || - opline->opcode == ZEND_INIT_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_DYNAMIC_CALL || - opline->opcode == ZEND_INIT_METHOD_CALL || - opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || - opline->opcode == ZEND_INIT_USER_CALL || - opline->opcode == ZEND_NEW - ) { - nesting++; - } else if (opline->opcode == ZEND_DO_FCALL || - opline->opcode == ZEND_DO_ICALL || - opline->opcode == ZEND_DO_UCALL || - opline->opcode == ZEND_DO_FCALL_BY_NAME) { - nesting--; - } - } while (nesting); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - - /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ - if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { - opline++; - } - ZEND_VM_JMP(++opline); + HANDLE_EXCEPTION(); } - } while (0); + } obj = Z_OBJ_P(object); called_scope = obj->ce; @@ -19792,13 +20418,19 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { - zend_error_noreturn(E_ERROR, "Object does not support method calls"); + zend_error(E_EXCEPTION | E_ERROR, "Object does not support method calls"); + + + HANDLE_EXCEPTION(); } /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL)); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + + + HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -19849,7 +20481,8 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + HANDLE_EXCEPTION(); } } else { CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c); @@ -19882,7 +20515,8 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); } @@ -19912,7 +20546,8 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC /* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */ ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); } else { - zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + HANDLE_EXCEPTION(); } } constant_fetch_end: @@ -19962,7 +20597,10 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + + + HANDLE_EXCEPTION(); } offset = EX_CONSTANT(opline->op2); @@ -20015,26 +20653,23 @@ num_index_dim: zend_error(E_WARNING, "Illegal offset type in unset"); break; } - } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + } else { //??? if (IS_CONST == IS_CONST) { //??? zval_copy_ctor(offset); //??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); - + Z_OBJ_HT_P(container)->unset_dimension(container, offset); + } } else if (IS_UNUSED != IS_UNUSED && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); goto unset_dim_again; } else if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - } else { - + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -20049,7 +20684,10 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + + + HANDLE_EXCEPTION(); } offset = EX_CONSTANT(opline->op2); @@ -20240,7 +20878,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDL zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + + + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -20273,7 +20914,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDL zval *value_ptr = NULL; if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + + + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -20371,7 +21015,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -20404,7 +21051,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER zval *value_ptr = NULL; if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -20502,7 +21152,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -20535,7 +21188,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER zval *value_ptr = NULL; if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -20635,7 +21291,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(int SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + + HANDLE_EXCEPTION(); } dim = NULL; @@ -20660,7 +21320,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(int var_ptr = Z_INDIRECT(rv); if (UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + + FREE_OP(free_op_data1); + + HANDLE_EXCEPTION(); } if (UNEXPECTED(var_ptr == &EG(error_zval))) { @@ -20964,7 +21628,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HAND zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + + + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -20997,7 +21664,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HAND zval *value_ptr = NULL; if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + + + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -21097,7 +21767,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b zval *zptr; if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + + HANDLE_EXCEPTION(); } do { @@ -21177,7 +21851,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(int (*b SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + + HANDLE_EXCEPTION(); } dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); @@ -21202,7 +21880,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(int (*b var_ptr = Z_INDIRECT(rv); if (UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + + FREE_OP(free_op_data1); + + HANDLE_EXCEPTION(); } if (UNEXPECTED(var_ptr == &EG(error_zval))) { @@ -21463,7 +22145,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t retval = EX_VAR(opline->result.var); if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + + + HANDLE_EXCEPTION(); } do { @@ -21552,7 +22237,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_ retval = EX_VAR(opline->result.var); if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + + + HANDLE_EXCEPTION(); } do { @@ -21696,7 +22384,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HA container = _get_obj_zval_ptr_unused(execute_data); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); @@ -21721,7 +22412,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_H container = _get_obj_zval_ptr_unused(execute_data); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW); @@ -21812,11 +22506,17 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER(ZEND_OP property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); container = _get_obj_zval_ptr_unused(execute_data); - if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + + HANDLE_EXCEPTION(); + } if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); @@ -21842,7 +22542,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_HANDLER(ZEND_OPCOD property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET); @@ -21866,7 +22569,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAN property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + + HANDLE_EXCEPTION(); } zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_UNUSED, property_name, IS_CV, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL)); @@ -21931,7 +22637,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); - if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (IS_CV != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { do { if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { function_name = Z_REFVAL_P(function_name); @@ -21942,68 +22649,27 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Method name must be a string"); + zend_error(E_EXCEPTION | E_ERROR, "Method name must be a string"); + + + HANDLE_EXCEPTION(); } while (0); } object = _get_obj_zval_ptr_unused(execute_data); - do { - if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - uint32_t nesting = 1; - - if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(object)) { - object = Z_REFVAL_P(object); - if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { - break; - } - } - + if (IS_UNUSED != IS_UNUSED) { + ZVAL_DEREF(object); + if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); } + zend_error(E_EXCEPTION | E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); - zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); - - if (EG(exception) != NULL) { - HANDLE_EXCEPTION(); - } - - /* No exception raised: Skip over arguments until fcall opcode with correct - * nesting level. Return NULL (except when return value unused) */ - do { - opline++; - if (opline->opcode == ZEND_INIT_FCALL || - opline->opcode == ZEND_INIT_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_DYNAMIC_CALL || - opline->opcode == ZEND_INIT_METHOD_CALL || - opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || - opline->opcode == ZEND_INIT_USER_CALL || - opline->opcode == ZEND_NEW - ) { - nesting++; - } else if (opline->opcode == ZEND_DO_FCALL || - opline->opcode == ZEND_DO_ICALL || - opline->opcode == ZEND_DO_UCALL || - opline->opcode == ZEND_DO_FCALL_BY_NAME) { - nesting--; - } - } while (nesting); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - - /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ - if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { - opline++; - } - ZEND_VM_JMP(++opline); + HANDLE_EXCEPTION(); } - } while (0); + } obj = Z_OBJ_P(object); called_scope = obj->ce; @@ -22013,13 +22679,19 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { - zend_error_noreturn(E_ERROR, "Object does not support method calls"); + zend_error(E_EXCEPTION | E_ERROR, "Object does not support method calls"); + + + HANDLE_EXCEPTION(); } /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL)); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + + + HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -22085,7 +22757,10 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + + + HANDLE_EXCEPTION(); } offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); @@ -22138,26 +22813,23 @@ num_index_dim: zend_error(E_WARNING, "Illegal offset type in unset"); break; } - } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + } else { //??? if (IS_CV == IS_CONST) { //??? zval_copy_ctor(offset); //??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); - + Z_OBJ_HT_P(container)->unset_dimension(container, offset); + } } else if (IS_UNUSED != IS_UNUSED && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); goto unset_dim_again; } else if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - } else { - + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -22172,7 +22844,10 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + + + HANDLE_EXCEPTION(); } offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); @@ -22363,7 +23038,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + + + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -22396,7 +23074,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ zval *value_ptr = NULL; if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + + + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -22496,7 +23177,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMPVAR(int zval *zptr; if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } do { @@ -22576,7 +23261,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(int SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); @@ -22601,7 +23290,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(int var_ptr = Z_INDIRECT(rv); if (UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zval_ptr_dtor_nogc(free_op2); + FREE_OP(free_op_data1); + + HANDLE_EXCEPTION(); } if (UNEXPECTED(var_ptr == &EG(error_zval))) { @@ -22863,7 +23556,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMPVAR(incd retval = EX_VAR(opline->result.var); if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } do { @@ -22953,7 +23649,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMPVAR(inc retval = EX_VAR(opline->result.var); if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } do { @@ -23099,7 +23798,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCOD container = _get_obj_zval_ptr_unused(execute_data); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); @@ -23124,7 +23826,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCO container = _get_obj_zval_ptr_unused(execute_data); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW); zval_ptr_dtor_nogc(free_op2); @@ -23216,11 +23921,17 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR_HANDLER(ZEN property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); container = _get_obj_zval_ptr_unused(execute_data); - if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); + } if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); zval_ptr_dtor_nogc(free_op2); @@ -23246,7 +23957,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_O property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET); zval_ptr_dtor_nogc(free_op2); @@ -23270,7 +23984,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_UNUSED, property_name, (IS_TMP_VAR|IS_VAR), (opline+1)->op1_type, (opline+1)->op1, execute_data, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL)); zval_ptr_dtor_nogc(free_op2); @@ -23336,7 +24053,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_ function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { do { if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { function_name = Z_REFVAL_P(function_name); @@ -23347,68 +24065,27 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_ if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Method name must be a string"); + zend_error(E_EXCEPTION | E_ERROR, "Method name must be a string"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } while (0); } object = _get_obj_zval_ptr_unused(execute_data); - do { - if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - uint32_t nesting = 1; - - if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(object)) { - object = Z_REFVAL_P(object); - if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { - break; - } - } - + if (IS_UNUSED != IS_UNUSED) { + ZVAL_DEREF(object); + if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op2); HANDLE_EXCEPTION(); } - - zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + zend_error(E_EXCEPTION | E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); zval_ptr_dtor_nogc(free_op2); - if (EG(exception) != NULL) { - HANDLE_EXCEPTION(); - } - - /* No exception raised: Skip over arguments until fcall opcode with correct - * nesting level. Return NULL (except when return value unused) */ - do { - opline++; - if (opline->opcode == ZEND_INIT_FCALL || - opline->opcode == ZEND_INIT_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_DYNAMIC_CALL || - opline->opcode == ZEND_INIT_METHOD_CALL || - opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || - opline->opcode == ZEND_INIT_USER_CALL || - opline->opcode == ZEND_NEW - ) { - nesting++; - } else if (opline->opcode == ZEND_DO_FCALL || - opline->opcode == ZEND_DO_ICALL || - opline->opcode == ZEND_DO_UCALL || - opline->opcode == ZEND_DO_FCALL_BY_NAME) { - nesting--; - } - } while (nesting); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - - /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ - if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { - opline++; - } - ZEND_VM_JMP(++opline); + HANDLE_EXCEPTION(); } - } while (0); + } obj = Z_OBJ_P(object); called_scope = obj->ce; @@ -23418,13 +24095,19 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_ zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { - zend_error_noreturn(E_ERROR, "Object does not support method calls"); + zend_error(E_EXCEPTION | E_ERROR, "Object does not support method calls"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL)); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -23491,7 +24174,10 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); @@ -23544,25 +24230,22 @@ num_index_dim: zend_error(E_WARNING, "Illegal offset type in unset"); break; } - zval_ptr_dtor_nogc(free_op2); } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + } else { //??? if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { //??? zval_copy_ctor(offset); //??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); - zval_ptr_dtor_nogc(free_op2); + Z_OBJ_HT_P(container)->unset_dimension(container, offset); + } } else if (IS_UNUSED != IS_UNUSED && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); goto unset_dim_again; } else if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - } else { - zval_ptr_dtor_nogc(free_op2); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); } + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -23578,7 +24261,10 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(execute_data); if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); @@ -23807,7 +24493,9 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + + HANDLE_EXCEPTION(); } if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { @@ -23849,7 +24537,9 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + + HANDLE_EXCEPTION(); } if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { @@ -23891,7 +24581,9 @@ static int ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + + HANDLE_EXCEPTION(); } if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { @@ -23926,7 +24618,9 @@ static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + + HANDLE_EXCEPTION(); } if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { @@ -24219,7 +24913,9 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER retval_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(retval_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot return string offsets by reference"); + + HANDLE_EXCEPTION(); } if (IS_CV == IS_VAR) { @@ -24267,7 +24963,9 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Can only throw objects"); + zend_error(E_EXCEPTION | E_ERROR, "Can only throw objects"); + + HANDLE_EXCEPTION(); } } while (0); @@ -24350,7 +25048,9 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS varptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(varptr == NULL)) { - zend_error_noreturn(E_ERROR, "Only variables can be passed by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Only variables can be passed by reference"); + + HANDLE_EXCEPTION(); } arg = ZEND_CALL_VAR(EX(call), opline->result.var); @@ -24517,7 +25217,9 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "__clone method called on non-object"); + zend_error(E_EXCEPTION | E_ERROR, "__clone method called on non-object"); + + HANDLE_EXCEPTION(); } } while (0); @@ -24526,10 +25228,12 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) clone_call = Z_OBJ_HT_P(obj)->clone_obj; if (UNEXPECTED(clone_call == NULL)) { if (ce) { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val); } else { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); + zend_error(E_EXCEPTION | E_ERROR, "Trying to clone an uncloneable object"); } + + HANDLE_EXCEPTION(); } if (ce && clone) { @@ -24537,13 +25241,17 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) /* Ensure that if we're calling a private function, we're allowed to do so. */ if (UNEXPECTED(ce != EG(scope))) { - zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + zend_error(E_EXCEPTION | E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + + HANDLE_EXCEPTION(); } } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { - zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + zend_error(E_EXCEPTION | E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + + HANDLE_EXCEPTION(); } } } @@ -25568,7 +26276,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi zval *zptr; if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + + HANDLE_EXCEPTION(); } do { @@ -25648,7 +26360,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CONST(int (*bi SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + + HANDLE_EXCEPTION(); } dim = EX_CONSTANT(opline->op2); @@ -25673,7 +26389,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CONST(int (*bi var_ptr = Z_INDIRECT(rv); if (UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + + FREE_OP(free_op_data1); + + HANDLE_EXCEPTION(); } if (UNEXPECTED(var_ptr == &EG(error_zval))) { @@ -25711,7 +26431,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + + + HANDLE_EXCEPTION(); } if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { @@ -25969,7 +26692,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t retval = EX_VAR(opline->result.var); if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + + + HANDLE_EXCEPTION(); } do { @@ -26058,7 +26784,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t retval = EX_VAR(opline->result.var); if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + + + HANDLE_EXCEPTION(); } do { @@ -26323,7 +27052,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST); @@ -26345,7 +27076,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST); @@ -26382,11 +27115,17 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + + HANDLE_EXCEPTION(); } container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { @@ -26396,7 +27135,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC } else { if (IS_CONST == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use [] for reading"); + + + HANDLE_EXCEPTION(); } container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST); @@ -26417,7 +27159,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST); @@ -26506,7 +27251,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); @@ -26531,7 +27279,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW); @@ -26622,11 +27373,17 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC property = EX_CONSTANT(opline->op2); container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + + HANDLE_EXCEPTION(); + } if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); @@ -26652,7 +27409,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE property = EX_CONSTANT(opline->op2); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET); @@ -26712,7 +27472,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND property_name = EX_CONSTANT(opline->op2); if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + + HANDLE_EXCEPTION(); } zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_CV, property_name, IS_CONST, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL)); @@ -26737,7 +27500,11 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND object_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + + HANDLE_EXCEPTION(); } try_assign_dim: @@ -26866,7 +27633,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD function_name = EX_CONSTANT(opline->op2); - if (IS_CONST != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (IS_CONST != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { do { if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { function_name = Z_REFVAL_P(function_name); @@ -26877,68 +27645,27 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Method name must be a string"); + zend_error(E_EXCEPTION | E_ERROR, "Method name must be a string"); + + + HANDLE_EXCEPTION(); } while (0); } object = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); - do { - if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - uint32_t nesting = 1; - - if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(object)) { - object = Z_REFVAL_P(object); - if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { - break; - } - } - + if (IS_CV != IS_UNUSED) { + ZVAL_DEREF(object); + if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); } + zend_error(E_EXCEPTION | E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); - zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); - - if (EG(exception) != NULL) { - HANDLE_EXCEPTION(); - } - - /* No exception raised: Skip over arguments until fcall opcode with correct - * nesting level. Return NULL (except when return value unused) */ - do { - opline++; - if (opline->opcode == ZEND_INIT_FCALL || - opline->opcode == ZEND_INIT_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_DYNAMIC_CALL || - opline->opcode == ZEND_INIT_METHOD_CALL || - opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || - opline->opcode == ZEND_INIT_USER_CALL || - opline->opcode == ZEND_NEW - ) { - nesting++; - } else if (opline->opcode == ZEND_DO_FCALL || - opline->opcode == ZEND_DO_ICALL || - opline->opcode == ZEND_DO_UCALL || - opline->opcode == ZEND_DO_FCALL_BY_NAME) { - nesting--; - } - } while (nesting); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - - /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ - if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { - opline++; - } - ZEND_VM_JMP(++opline); + HANDLE_EXCEPTION(); } - } while (0); + } obj = Z_OBJ_P(object); called_scope = obj->ce; @@ -26948,13 +27675,19 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { - zend_error_noreturn(E_ERROR, "Object does not support method calls"); + zend_error(E_EXCEPTION | E_ERROR, "Object does not support method calls"); + + + HANDLE_EXCEPTION(); } /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL)); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + + + HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -27004,7 +27737,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCO (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); + + HANDLE_EXCEPTION(); } ZVAL_MAKE_REF(expr_ptr); Z_ADDREF_P(expr_ptr); @@ -27166,7 +27901,11 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + if (IS_CV != IS_CONST) { + zend_string_release(Z_STR(tmp)); + } + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce); } @@ -27198,7 +27937,10 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + + + HANDLE_EXCEPTION(); } offset = EX_CONSTANT(opline->op2); @@ -27251,26 +27993,23 @@ num_index_dim: zend_error(E_WARNING, "Illegal offset type in unset"); break; } - } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + } else { //??? if (IS_CONST == IS_CONST) { //??? zval_copy_ctor(offset); //??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); - + Z_OBJ_HT_P(container)->unset_dimension(container, offset); + } } else if (IS_CV != IS_UNUSED && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); goto unset_dim_again; } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - } else { - + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -27285,7 +28024,10 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + + + HANDLE_EXCEPTION(); } offset = EX_CONSTANT(opline->op2); @@ -27617,7 +28359,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_A zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + + + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -27650,7 +28395,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_A zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + + + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -27887,7 +28635,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -27920,7 +28671,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -28258,7 +29012,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE value_ptr = _get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2); if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + if (free_op2) {zval_ptr_dtor_nogc(free_op2);}; + + HANDLE_EXCEPTION(); } if (IS_VAR == IS_VAR && (value_ptr == &EG(uninitialized_zval) || @@ -28277,12 +29034,18 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + if (free_op2) {zval_ptr_dtor_nogc(free_op2);}; + + HANDLE_EXCEPTION(); } if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && UNEXPECTED(!Z_ISREF_P(variable_ptr))) { - zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot assign by reference to overloaded object"); + if (free_op2) {zval_ptr_dtor_nogc(free_op2);}; + + HANDLE_EXCEPTION(); } if ((IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { @@ -28355,7 +29118,11 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + if (IS_CV != IS_CONST) { + zend_string_release(Z_STR(tmp)); + } + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce); } @@ -28525,7 +29292,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -28558,7 +29328,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -28658,7 +29431,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*b SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + + HANDLE_EXCEPTION(); } dim = NULL; @@ -28683,7 +29460,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*b var_ptr = Z_INDIRECT(rv); if (UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + + FREE_OP(free_op_data1); + + HANDLE_EXCEPTION(); } if (UNEXPECTED(var_ptr == &EG(error_zval))) { @@ -29112,7 +29893,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HA container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED); @@ -29134,7 +29917,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_H container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, NULL, IS_UNUSED); @@ -29156,11 +29941,17 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OP if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + + HANDLE_EXCEPTION(); } container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { @@ -29170,7 +29961,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OP } else { if (IS_UNUSED == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use [] for reading"); + + + HANDLE_EXCEPTION(); } container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, NULL, IS_UNUSED); @@ -29195,7 +29989,11 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN object_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + + HANDLE_EXCEPTION(); } try_assign_dim: @@ -29308,7 +30106,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPC (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); + + HANDLE_EXCEPTION(); } ZVAL_MAKE_REF(expr_ptr); Z_ADDREF_P(expr_ptr); @@ -29470,7 +30270,11 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAND HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + if (IS_CV != IS_CONST) { + zend_string_release(Z_STR(tmp)); + } + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce); } @@ -29597,7 +30401,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + + + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -29630,7 +30437,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + + + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -30021,7 +30831,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar zval *zptr; if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + + HANDLE_EXCEPTION(); } do { @@ -30101,7 +30915,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CV(int (*binar SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + + HANDLE_EXCEPTION(); } dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); @@ -30126,7 +30944,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CV(int (*binar var_ptr = Z_INDIRECT(rv); if (UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + + FREE_OP(free_op_data1); + + HANDLE_EXCEPTION(); } if (UNEXPECTED(var_ptr == &EG(error_zval))) { @@ -30164,7 +30986,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + + + HANDLE_EXCEPTION(); } if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { @@ -30422,7 +31247,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc retval = EX_VAR(opline->result.var); if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + + + HANDLE_EXCEPTION(); } do { @@ -30511,7 +31339,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in retval = EX_VAR(opline->result.var); if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + + + HANDLE_EXCEPTION(); } do { @@ -30603,7 +31434,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV); @@ -30625,7 +31458,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV); @@ -30662,11 +31497,17 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + + HANDLE_EXCEPTION(); } container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { @@ -30676,7 +31517,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE } else { if (IS_CV == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use [] for reading"); + + + HANDLE_EXCEPTION(); } container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV); @@ -30697,7 +31541,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV); @@ -30786,7 +31633,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); @@ -30811,7 +31661,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW); @@ -30902,11 +31755,17 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + + + HANDLE_EXCEPTION(); + } if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); @@ -30932,7 +31791,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET); @@ -30956,7 +31818,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + + HANDLE_EXCEPTION(); } zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_CV, property_name, IS_CV, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL)); @@ -30981,7 +31846,11 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER object_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + + + HANDLE_EXCEPTION(); } try_assign_dim: @@ -31107,7 +31976,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op2.var); if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + + + HANDLE_EXCEPTION(); } if (IS_CV == IS_VAR && (value_ptr == &EG(uninitialized_zval) || @@ -31126,12 +31998,18 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); + + + HANDLE_EXCEPTION(); } if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && UNEXPECTED(!Z_ISREF_P(variable_ptr))) { - zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot assign by reference to overloaded object"); + + + HANDLE_EXCEPTION(); } if ((IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || (IS_CV == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { @@ -31163,7 +32041,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); - if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (IS_CV != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { do { if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { function_name = Z_REFVAL_P(function_name); @@ -31174,68 +32053,27 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Method name must be a string"); + zend_error(E_EXCEPTION | E_ERROR, "Method name must be a string"); + + + HANDLE_EXCEPTION(); } while (0); } object = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); - do { - if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - uint32_t nesting = 1; - - if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(object)) { - object = Z_REFVAL_P(object); - if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { - break; - } - } - + if (IS_CV != IS_UNUSED) { + ZVAL_DEREF(object); + if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (UNEXPECTED(EG(exception) != NULL)) { - - HANDLE_EXCEPTION(); - } - - zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); - - - if (EG(exception) != NULL) { HANDLE_EXCEPTION(); } + zend_error(E_EXCEPTION | E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); - /* No exception raised: Skip over arguments until fcall opcode with correct - * nesting level. Return NULL (except when return value unused) */ - do { - opline++; - if (opline->opcode == ZEND_INIT_FCALL || - opline->opcode == ZEND_INIT_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_DYNAMIC_CALL || - opline->opcode == ZEND_INIT_METHOD_CALL || - opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || - opline->opcode == ZEND_INIT_USER_CALL || - opline->opcode == ZEND_NEW - ) { - nesting++; - } else if (opline->opcode == ZEND_DO_FCALL || - opline->opcode == ZEND_DO_ICALL || - opline->opcode == ZEND_DO_UCALL || - opline->opcode == ZEND_DO_FCALL_BY_NAME) { - nesting--; - } - } while (nesting); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ - if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { - opline++; - } - ZEND_VM_JMP(++opline); + HANDLE_EXCEPTION(); } - } while (0); + } obj = Z_OBJ_P(object); called_scope = obj->ce; @@ -31245,13 +32083,19 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { - zend_error_noreturn(E_ERROR, "Object does not support method calls"); + zend_error(E_EXCEPTION | E_ERROR, "Object does not support method calls"); + + + HANDLE_EXCEPTION(); } /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL)); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + + + HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -31301,7 +32145,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_ (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); + + HANDLE_EXCEPTION(); } ZVAL_MAKE_REF(expr_ptr); Z_ADDREF_P(expr_ptr); @@ -31420,7 +32266,10 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + + + HANDLE_EXCEPTION(); } offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); @@ -31473,26 +32322,23 @@ num_index_dim: zend_error(E_WARNING, "Illegal offset type in unset"); break; } - } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + } else { //??? if (IS_CV == IS_CONST) { //??? zval_copy_ctor(offset); //??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); - + Z_OBJ_HT_P(container)->unset_dimension(container, offset); + } } else if (IS_CV != IS_UNUSED && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); goto unset_dim_again; } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - } else { - + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -31507,7 +32353,10 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + + + HANDLE_EXCEPTION(); } offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); @@ -31698,7 +32547,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS zend_generator *generator = (zend_generator *) EX(return_value); if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { - zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator"); + + + HANDLE_EXCEPTION(); } /* Destroy the previously yielded value */ @@ -31731,7 +32583,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference"); + + + HANDLE_EXCEPTION(); } /* If a function call result is yielded and the function did @@ -32111,7 +32966,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMPVAR(int (*b zval *zptr; if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } do { @@ -32191,7 +33050,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(int (*b SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); @@ -32216,7 +33079,11 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(int (*b var_ptr = Z_INDIRECT(rv); if (UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zval_ptr_dtor_nogc(free_op2); + FREE_OP(free_op_data1); + + HANDLE_EXCEPTION(); } if (UNEXPECTED(var_ptr == &EG(error_zval))) { @@ -32255,7 +33122,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_TMPVAR(int (*binar var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { @@ -32514,7 +33384,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMPVAR(incdec_t retval = EX_VAR(opline->result.var); if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } do { @@ -32604,7 +33477,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMPVAR(incdec_ retval = EX_VAR(opline->result.var); if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } do { @@ -32697,7 +33573,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HA container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR)); zval_ptr_dtor_nogc(free_op2); @@ -32719,7 +33597,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_H container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR)); zval_ptr_dtor_nogc(free_op2); @@ -32756,11 +33636,17 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER(ZEND_OP if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR)); if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) { @@ -32770,7 +33656,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER(ZEND_OP } else { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use [] for reading"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR)); @@ -32791,7 +33680,10 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCOD container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR)); zval_ptr_dtor_nogc(free_op2); @@ -32881,7 +33773,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HA container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); @@ -32906,7 +33801,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_H container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW); zval_ptr_dtor_nogc(free_op2); @@ -32998,11 +33896,17 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER(ZEND_OP property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { - zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); - } + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use temporary expression in write context"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); + } if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W); zval_ptr_dtor_nogc(free_op2); @@ -33028,7 +33932,10 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCOD property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET); zval_ptr_dtor_nogc(free_op2); @@ -33052,7 +33959,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HAN property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_CV, property_name, (IS_TMP_VAR|IS_VAR), (opline+1)->op1_type, (opline+1)->op1, execute_data, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL)); zval_ptr_dtor_nogc(free_op2); @@ -33077,7 +33987,11 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HAN object_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } try_assign_dim: @@ -33174,7 +34088,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCO function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { do { if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { function_name = Z_REFVAL_P(function_name); @@ -33185,68 +34100,27 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCO if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Method name must be a string"); + zend_error(E_EXCEPTION | E_ERROR, "Method name must be a string"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } while (0); } object = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); - do { - if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - uint32_t nesting = 1; - - if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(object)) { - object = Z_REFVAL_P(object); - if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { - break; - } - } - + if (IS_CV != IS_UNUSED) { + ZVAL_DEREF(object); + if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op2); HANDLE_EXCEPTION(); } - - zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + zend_error(E_EXCEPTION | E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); zval_ptr_dtor_nogc(free_op2); - if (EG(exception) != NULL) { - HANDLE_EXCEPTION(); - } - - /* No exception raised: Skip over arguments until fcall opcode with correct - * nesting level. Return NULL (except when return value unused) */ - do { - opline++; - if (opline->opcode == ZEND_INIT_FCALL || - opline->opcode == ZEND_INIT_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_DYNAMIC_CALL || - opline->opcode == ZEND_INIT_METHOD_CALL || - opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || - opline->opcode == ZEND_INIT_USER_CALL || - opline->opcode == ZEND_NEW - ) { - nesting++; - } else if (opline->opcode == ZEND_DO_FCALL || - opline->opcode == ZEND_DO_ICALL || - opline->opcode == ZEND_DO_UCALL || - opline->opcode == ZEND_DO_FCALL_BY_NAME) { - nesting--; - } - } while (nesting); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - - /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ - if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { - opline++; - } - ZEND_VM_JMP(++opline); + HANDLE_EXCEPTION(); } - } while (0); + } obj = Z_OBJ_P(object); called_scope = obj->ce; @@ -33256,13 +34130,19 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCO zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { - zend_error_noreturn(E_ERROR, "Object does not support method calls"); + zend_error(E_EXCEPTION | E_ERROR, "Object does not support method calls"); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL)); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + zval_ptr_dtor_nogc(free_op2); + + HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -33314,7 +34194,9 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPC (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets"); + + HANDLE_EXCEPTION(); } ZVAL_MAKE_REF(expr_ptr); Z_ADDREF_P(expr_ptr); @@ -33433,7 +34315,10 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); @@ -33486,25 +34371,22 @@ num_index_dim: zend_error(E_WARNING, "Illegal offset type in unset"); break; } - zval_ptr_dtor_nogc(free_op2); } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); - } + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + } else { //??? if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { //??? zval_copy_ctor(offset); //??? } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); - zval_ptr_dtor_nogc(free_op2); + Z_OBJ_HT_P(container)->unset_dimension(container, offset); + } } else if (IS_CV != IS_UNUSED && Z_ISREF_P(container)) { container = Z_REFVAL_P(container); goto unset_dim_again; } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); - ZEND_VM_CONTINUE(); /* bailed out before */ - } else { - zval_ptr_dtor_nogc(free_op2); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); } + zval_ptr_dtor_nogc(free_op2); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -33520,7 +34402,10 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { - zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + HANDLE_EXCEPTION(); } offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); @@ -34033,7 +34918,9 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARG if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "__clone method called on non-object"); + zend_error(E_EXCEPTION | E_ERROR, "__clone method called on non-object"); + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } } while (0); @@ -34042,10 +34929,12 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARG clone_call = Z_OBJ_HT_P(obj)->clone_obj; if (UNEXPECTED(clone_call == NULL)) { if (ce) { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val); } else { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); + zend_error(E_EXCEPTION | E_ERROR, "Trying to clone an uncloneable object"); } + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } if (ce && clone) { @@ -34053,13 +34942,17 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARG /* Ensure that if we're calling a private function, we're allowed to do so. */ if (UNEXPECTED(ce != EG(scope))) { - zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + zend_error(E_EXCEPTION | E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { - zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + zend_error(E_EXCEPTION | E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : ""); + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } } } @@ -34853,7 +35746,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CONST_HANDLER(ZEND_O function_name = EX_CONSTANT(opline->op2); - if (IS_CONST != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (IS_CONST != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { do { if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { function_name = Z_REFVAL_P(function_name); @@ -34864,69 +35758,27 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CONST_HANDLER(ZEND_O if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Method name must be a string"); + zend_error(E_EXCEPTION | E_ERROR, "Method name must be a string"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } while (0); } object = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - do { - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - uint32_t nesting = 1; - - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(object)) { - object = Z_REFVAL_P(object); - if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { - break; - } - } - + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + ZVAL_DEREF(object); + if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); } - - zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + zend_error(E_EXCEPTION | E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); zval_ptr_dtor_nogc(free_op1); - - if (EG(exception) != NULL) { - HANDLE_EXCEPTION(); - } - - /* No exception raised: Skip over arguments until fcall opcode with correct - * nesting level. Return NULL (except when return value unused) */ - do { - opline++; - if (opline->opcode == ZEND_INIT_FCALL || - opline->opcode == ZEND_INIT_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_DYNAMIC_CALL || - opline->opcode == ZEND_INIT_METHOD_CALL || - opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || - opline->opcode == ZEND_INIT_USER_CALL || - opline->opcode == ZEND_NEW - ) { - nesting++; - } else if (opline->opcode == ZEND_DO_FCALL || - opline->opcode == ZEND_DO_ICALL || - opline->opcode == ZEND_DO_UCALL || - opline->opcode == ZEND_DO_FCALL_BY_NAME) { - nesting--; - } - } while (nesting); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - - /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ - if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { - opline++; - } - ZEND_VM_JMP(++opline); + HANDLE_EXCEPTION(); } - } while (0); + } obj = Z_OBJ_P(object); called_scope = obj->ce; @@ -34936,13 +35788,19 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CONST_HANDLER(ZEND_O zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { - zend_error_noreturn(E_ERROR, "Object does not support method calls"); + zend_error(E_EXCEPTION | E_ERROR, "Object does not support method calls"); + + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL)); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -35036,7 +35894,11 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_H HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release(Z_STR(tmp)); + } + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce); } @@ -35598,7 +36460,11 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HAN HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release(Z_STR(tmp)); + } + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce); } @@ -35989,7 +36855,11 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_ HANDLE_EXCEPTION(); } if (UNEXPECTED(ce == NULL)) { - zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release(Z_STR(tmp)); + } + HANDLE_EXCEPTION(); } CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce); } @@ -36478,7 +37348,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCO function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); - if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if (IS_CV != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { do { if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { function_name = Z_REFVAL_P(function_name); @@ -36489,69 +37360,27 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCO if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Method name must be a string"); + zend_error(E_EXCEPTION | E_ERROR, "Method name must be a string"); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } while (0); } object = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - do { - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - uint32_t nesting = 1; - - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(object)) { - object = Z_REFVAL_P(object); - if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { - break; - } - } - + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + ZVAL_DEREF(object); + if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); } - - zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + zend_error(E_EXCEPTION | E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); zval_ptr_dtor_nogc(free_op1); - - if (EG(exception) != NULL) { - HANDLE_EXCEPTION(); - } - - /* No exception raised: Skip over arguments until fcall opcode with correct - * nesting level. Return NULL (except when return value unused) */ - do { - opline++; - if (opline->opcode == ZEND_INIT_FCALL || - opline->opcode == ZEND_INIT_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_DYNAMIC_CALL || - opline->opcode == ZEND_INIT_METHOD_CALL || - opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || - opline->opcode == ZEND_INIT_USER_CALL || - opline->opcode == ZEND_NEW - ) { - nesting++; - } else if (opline->opcode == ZEND_DO_FCALL || - opline->opcode == ZEND_DO_ICALL || - opline->opcode == ZEND_DO_UCALL || - opline->opcode == ZEND_DO_FCALL_BY_NAME) { - nesting--; - } - } while (nesting); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - - /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ - if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { - opline++; - } - ZEND_VM_JMP(++opline); + HANDLE_EXCEPTION(); } - } while (0); + } obj = Z_OBJ_P(object); called_scope = obj->ce; @@ -36561,13 +37390,19 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCO zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { - zend_error_noreturn(E_ERROR, "Object does not support method calls"); + zend_error(E_EXCEPTION | E_ERROR, "Object does not support method calls"); + + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL)); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && @@ -37148,7 +37983,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_ function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { do { if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { function_name = Z_REFVAL_P(function_name); @@ -37159,69 +37995,27 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_ if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - zend_error_noreturn(E_ERROR, "Method name must be a string"); + zend_error(E_EXCEPTION | E_ERROR, "Method name must be a string"); + zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); } while (0); } object = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); - do { - if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - uint32_t nesting = 1; - - if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(object)) { - object = Z_REFVAL_P(object); - if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { - break; - } - } - + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + ZVAL_DEREF(object); + if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op2); HANDLE_EXCEPTION(); } - - zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); + zend_error(E_EXCEPTION | E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object))); zval_ptr_dtor_nogc(free_op2); zval_ptr_dtor_nogc(free_op1); - - if (EG(exception) != NULL) { - HANDLE_EXCEPTION(); - } - - /* No exception raised: Skip over arguments until fcall opcode with correct - * nesting level. Return NULL (except when return value unused) */ - do { - opline++; - if (opline->opcode == ZEND_INIT_FCALL || - opline->opcode == ZEND_INIT_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME || - opline->opcode == ZEND_INIT_DYNAMIC_CALL || - opline->opcode == ZEND_INIT_METHOD_CALL || - opline->opcode == ZEND_INIT_STATIC_METHOD_CALL || - opline->opcode == ZEND_INIT_USER_CALL || - opline->opcode == ZEND_NEW - ) { - nesting++; - } else if (opline->opcode == ZEND_DO_FCALL || - opline->opcode == ZEND_DO_ICALL || - opline->opcode == ZEND_DO_UCALL || - opline->opcode == ZEND_DO_FCALL_BY_NAME) { - nesting--; - } - } while (nesting); - - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - - /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */ - if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) { - opline++; - } - ZEND_VM_JMP(++opline); + HANDLE_EXCEPTION(); } - } while (0); + } obj = Z_OBJ_P(object); called_scope = obj->ce; @@ -37231,13 +38025,19 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_ zend_object *orig_obj = obj; if (UNEXPECTED(obj->handlers->get_method == NULL)) { - zend_error_noreturn(E_ERROR, "Object does not support method calls"); + zend_error(E_EXCEPTION | E_ERROR, "Object does not support method calls"); + zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } /* First, locate the function. */ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL)); if (UNEXPECTED(fbc == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + zend_error(E_EXCEPTION | E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name)); + zval_ptr_dtor_nogc(free_op2); + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index c3b16b3478..65b1c72c06 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -353,6 +353,26 @@ $op2_free_op_var_ptr = array( "TMPVAR" => "???", ); +$op1_free_unfetched = array( + "ANY" => "FREE_UNFETCHED_OP(opline->op1_type, opline->op1.var)", + "TMP" => "zval_ptr_dtor_nogc(EX_VAR(opline->op1.var))", + "VAR" => "zval_ptr_dtor_nogc(EX_VAR(opline->op1.var))", + "CONST" => "", + "UNUSED" => "", + "CV" => "", + "TMPVAR" => "zval_ptr_dtor_nogc(EX_VAR(opline->op1.var))", +); + +$op2_free_unfetched = array( + "ANY" => "FREE_UNFETCHED_OP(opline->op2_type, opline->op2.var)", + "TMP" => "zval_ptr_dtor_nogc(EX_VAR(opline->op2.var))", + "VAR" => "zval_ptr_dtor_nogc(EX_VAR(opline->op2.var))", + "CONST" => "", + "UNUSED" => "", + "CV" => "", + "TMPVAR" => "zval_ptr_dtor_nogc(EX_VAR(opline->op2.var))", +); + $list = array(); // list of opcode handlers and helpers in original order $opcodes = array(); // opcode handlers by code $helpers = array(); // opcode helpers by name @@ -405,7 +425,7 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) { $op1_get_obj_zval_ptr_deref, $op2_get_obj_zval_ptr_deref, $op1_get_obj_zval_ptr_ptr, $op2_get_obj_zval_ptr_ptr, $op1_get_obj_zval_ptr_ptr_undef, $op2_get_obj_zval_ptr_ptr_undef, - $op1_free, $op2_free, + $op1_free, $op2_free, $op1_free_unfetched, $op2_free_unfetched, $op1_free_op, $op2_free_op, $op1_free_op_if_var, $op2_free_op_if_var, $op1_free_op_var_ptr, $op2_free_op_var_ptr, $prefix; @@ -438,6 +458,8 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) { "/FREE_OP2_IF_VAR\(\)/", "/FREE_OP1_VAR_PTR\(\)/", "/FREE_OP2_VAR_PTR\(\)/", + "/FREE_UNFETCHED_OP1\(\)/", + "/FREE_UNFETCHED_OP2\(\)/", "/^#(\s*)ifdef\s+ZEND_VM_SPEC\s*\n/m", "/^#(\s*)ifndef\s+ZEND_VM_SPEC\s*\n/m", "/\!defined\(ZEND_VM_SPEC\)/m", @@ -476,6 +498,8 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) { $op2_free_op_if_var[$op2], $op1_free_op_var_ptr[$op1], $op2_free_op_var_ptr[$op2], + $op1_free_unfetched[$op1], + $op2_free_unfetched[$op2], ($op1!="ANY"||$op2!="ANY")?"#\\1if 1\n":"#\\1if 0\n", ($op1!="ANY"||$op2!="ANY")?"#\\1if 0\n":"#\\1if 1\n", ($op1!="ANY"||$op2!="ANY")?"0":"1", diff --git a/ext/date/tests/timezone_offset_get_error.phpt b/ext/date/tests/timezone_offset_get_error.phpt index 9e9daacf84..653625dd34 100644 --- a/ext/date/tests/timezone_offset_get_error.phpt +++ b/ext/date/tests/timezone_offset_get_error.phpt @@ -24,30 +24,75 @@ function err($errno, $errstr) { echo "*** Testing timezone_offset_get() : error conditions ***\n"; echo "\n-- Testing timezone_offset_get() function with zero arguments --\n"; -var_dump( timezone_offset_get() ); +try { + var_dump( timezone_offset_get() ); +} catch (EngineException $ex) { + var_dump($ex->getMessage()); + echo "\n"; +} echo "\n-- Testing timezone_offset_get() function with less than expected no. of arguments --\n"; -var_dump( timezone_offset_get($tz) ); +try { + var_dump( timezone_offset_get($tz) ); +} catch (EngineException $ex) { + var_dump($ex->getMessage()); + echo "\n"; +} echo "\n-- Testing timezone_offset_get() function with more than expected no. of arguments --\n"; $extra_arg = 99; -var_dump( timezone_offset_get($tz, $date, $extra_arg) ); +try { + var_dump( timezone_offset_get($tz, $date, $extra_arg) ); +} catch (EngineException $ex) { + var_dump($ex->getMessage()); + echo "\n"; +} echo "\n-- Testing timezone_offset_get() function with an invalid values for \$object argument --\n"; $invalid_obj = new stdClass(); -var_dump( timezone_offset_get($invalid_obj, $date) ); +try { + var_dump( timezone_offset_get($invalid_obj, $date) ); +} catch (EngineException $ex) { + var_dump($ex->getMessage()); + echo "\n"; +} $invalid_obj = 10; -var_dump( timezone_offset_get($invalid_obj, $date) ); +try { + var_dump( timezone_offset_get($invalid_obj, $date) ); +} catch (EngineException $ex) { + var_dump($ex->getMessage()); + echo "\n"; +} $invalid_obj = null; -var_dump( timezone_offset_get($invalid_obj, $date) ); +try { + var_dump( timezone_offset_get($invalid_obj, $date) ); +} catch (EngineException $ex) { + var_dump($ex->getMessage()); + echo "\n"; +} echo "\n-- Testing timezone_offset_get() function with an invalid values for \$datetime argument --\n"; $invalid_obj = new stdClass(); -var_dump( timezone_offset_get($tz, $invalid_obj) ); +try { + var_dump( timezone_offset_get($tz, $invalid_obj) ); +} catch (EngineException $ex) { + var_dump($ex->getMessage()); + echo "\n"; +} $invalid_obj = 10; -var_dump( timezone_offset_get($tz, $invalid_obj) ); +try { + var_dump( timezone_offset_get($tz, $invalid_obj) ); +} catch (EngineException $ex) { + var_dump($ex->getMessage()); + echo "\n"; +} $invalid_obj = null; -var_dump( timezone_offset_get($tz, $invalid_obj) ); +try { + var_dump( timezone_offset_get($tz, $invalid_obj) ); +} catch (EngineException $ex) { + var_dump($ex->getMessage()); + echo "\n"; +} ?> ===DONE=== --EXPECTF-- @@ -64,17 +109,17 @@ bool(false) -- Testing timezone_offset_get() function with an invalid values for $object argument -- string(%d) "Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, instance of stdClass given" -bool(false) + string(%d) "Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, integer given" -bool(false) + string(%d) "Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, null given" -bool(false) + -- Testing timezone_offset_get() function with an invalid values for $datetime argument -- string(%d) "Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, instance of stdClass given" -bool(false) + string(%d) "Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, integer given" -bool(false) + string(%d) "Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, null given" -bool(false) + ===DONE=== diff --git a/ext/date/tests/timezone_offset_get_variation1.phpt b/ext/date/tests/timezone_offset_get_variation1.phpt index b8de45a5d7..d2cfeedaaf 100644 --- a/ext/date/tests/timezone_offset_get_variation1.phpt +++ b/ext/date/tests/timezone_offset_get_variation1.phpt @@ -107,7 +107,11 @@ $datetime = new DateTime("2009-01-31 15:14:10"); foreach($inputs as $variation =>$object) { echo "\n-- $variation --\n"; - var_dump( timezone_offset_get($object, $datetime) ); + try { + var_dump( timezone_offset_get($object, $datetime) ); + } catch (EngineException $ex) { + echo $ex->getMessage()."\n"; + } }; // closing the resource @@ -120,113 +124,85 @@ fclose( $file_handle ); -- int 0 -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, integer given -bool(false) -- int 1 -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, integer given -bool(false) -- int 12345 -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, integer given -bool(false) -- int -12345 -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, integer given -bool(false) -- float 10.5 -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, float given -bool(false) -- float -10.5 -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, float given -bool(false) -- float .5 -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, float given -bool(false) -- empty array -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, array given -bool(false) -- int indexed array -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, array given -bool(false) -- associative array -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, array given -bool(false) -- nested arrays -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, array given -bool(false) -- uppercase NULL -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, null given -bool(false) -- lowercase null -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, null given -bool(false) -- lowercase true -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, boolean given -bool(false) -- lowercase false -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, boolean given -bool(false) -- uppercase TRUE -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, boolean given -bool(false) -- uppercase FALSE -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, boolean given -bool(false) -- empty string DQ -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, string given -bool(false) -- empty string SQ -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, string given -bool(false) -- string DQ -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, string given -bool(false) -- string SQ -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, string given -bool(false) -- mixed case string -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, string given -bool(false) -- heredoc -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, string given -bool(false) -- instance of classWithToString -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, instance of classWithToString given -bool(false) -- instance of classWithoutToString -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, instance of classWithoutToString given -bool(false) -- undefined var -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, null given -bool(false) -- unset var -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, null given -bool(false) -- resource -- Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, resource given -bool(false) ===DONE=== diff --git a/ext/date/tests/timezone_offset_get_variation2.phpt b/ext/date/tests/timezone_offset_get_variation2.phpt index dc218ea7d2..8191e18ee7 100644 --- a/ext/date/tests/timezone_offset_get_variation2.phpt +++ b/ext/date/tests/timezone_offset_get_variation2.phpt @@ -107,7 +107,11 @@ $object = new DateTimezone("Europe/London"); foreach($inputs as $variation =>$datetime) { echo "\n-- $variation --\n"; - var_dump( timezone_offset_get($object, $datetime) ); + try { + var_dump( timezone_offset_get($object, $datetime) ); + } catch (EngineException $ex) { + echo $ex->getMessage()."\n"; + } }; // closing the resource @@ -120,113 +124,85 @@ fclose( $file_handle ); -- int 0 -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, integer given -bool(false) -- int 1 -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, integer given -bool(false) -- int 12345 -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, integer given -bool(false) -- int -12345 -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, integer given -bool(false) -- float 10.5 -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, float given -bool(false) -- float -10.5 -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, float given -bool(false) -- float .5 -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, float given -bool(false) -- empty array -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, array given -bool(false) -- int indexed array -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, array given -bool(false) -- associative array -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, array given -bool(false) -- nested arrays -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, array given -bool(false) -- uppercase NULL -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, null given -bool(false) -- lowercase null -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, null given -bool(false) -- lowercase true -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, boolean given -bool(false) -- lowercase false -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, boolean given -bool(false) -- uppercase TRUE -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, boolean given -bool(false) -- uppercase FALSE -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, boolean given -bool(false) -- empty string DQ -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, string given -bool(false) -- empty string SQ -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, string given -bool(false) -- string DQ -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, string given -bool(false) -- string SQ -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, string given -bool(false) -- mixed case string -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, string given -bool(false) -- heredoc -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, string given -bool(false) -- instance of classWithToString -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, instance of classWithToString given -bool(false) -- instance of classWithoutToString -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, instance of classWithoutToString given -bool(false) -- undefined var -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, null given -bool(false) -- unset var -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, null given -bool(false) -- resource -- Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, resource given -bool(false) ===DONE=== diff --git a/ext/dom/tests/dom003.phpt b/ext/dom/tests/dom003.phpt index 060a2c184e..37db1f7677 100644 --- a/ext/dom/tests/dom003.phpt +++ b/ext/dom/tests/dom003.phpt @@ -28,13 +28,13 @@ $rootNode->appendChild($rootNode); object(DOMException)#%d (%d) { ["message":protected]=> string(23) "Hierarchy Request Error" - ["string":"Exception":private]=> + ["string":"BaseException":private]=> string(0) "" ["file":protected]=> string(%d) "%sdom003.php" ["line":protected]=> int(8) - ["trace":"Exception":private]=> + ["trace":"BaseException":private]=> array(1) { [0]=> array(6) { @@ -55,7 +55,7 @@ object(DOMException)#%d (%d) { } } } - ["previous":"Exception":private]=> + ["previous":"BaseException":private]=> NULL ["code"]=> int(3) diff --git a/ext/dom/tests/dom_set_attr_node.phpt b/ext/dom/tests/dom_set_attr_node.phpt index 1916cd524a..1c4960615c 100644 --- a/ext/dom/tests/dom_set_attr_node.phpt +++ b/ext/dom/tests/dom_set_attr_node.phpt @@ -40,13 +40,13 @@ ob_start(); object(DOMException)#%d (7) { ["message":protected]=> string(20) "Wrong Document Error" - ["string":"Exception":private]=> + ["string":"BaseException":private]=> string(0) "" ["file":protected]=> string(%d) "%sdom_set_attr_node.php" ["line":protected]=> int(%d) - ["trace":"Exception":private]=> + ["trace":"BaseException":private]=> array(1) { [0]=> array(6) { @@ -67,7 +67,7 @@ object(DOMException)#%d (7) { } } } - ["previous":"Exception":private]=> + ["previous":"BaseException":private]=> NULL ["code"]=> int(4) diff --git a/ext/intl/tests/badargs.phpt b/ext/intl/tests/badargs.phpt index b2120977f3..300ac2653e 100644 --- a/ext/intl/tests/badargs.phpt +++ b/ext/intl/tests/badargs.phpt @@ -16,7 +16,11 @@ foreach($funcs as $func) { try { $res = $func($arg); - } catch (Exception $e) { continue; } + } catch (Exception $e) { + continue; + } catch (EngineException $e) { + continue; + } if($res != false) { echo "$func: "; var_dump($res); diff --git a/ext/intl/tests/calendar_before_after_error.phpt b/ext/intl/tests/calendar_before_after_error.phpt index 10011ef852..2fcd81d93a 100644 --- a/ext/intl/tests/calendar_before_after_error.phpt +++ b/ext/intl/tests/calendar_before_after_error.phpt @@ -17,17 +17,49 @@ echo "error: $errno, $errstr\n"; } set_error_handler('eh'); -var_dump($c->after()); -var_dump($c->before()); +try { + var_dump($c->after()); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump($c->before()); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} -var_dump($c->after(1)); -var_dump($c->before(1)); +try { + var_dump($c->after(1)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump($c->before(1)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} -var_dump($c->after($c, 1)); -var_dump($c->before($c, 1)); +try{ + var_dump($c->after($c, 1)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump($c->before($c, 1)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} -var_dump(intlcal_after($c)); -var_dump(intlcal_before($c)); +try { + var_dump(intlcal_after($c)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump(intlcal_before($c)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} --EXPECT-- error: 2, IntlCalendar::after() expects exactly 1 parameter, 0 given error: 2, IntlCalendar::after(): intlcal_before/after: bad arguments @@ -36,13 +68,9 @@ error: 2, IntlCalendar::before() expects exactly 1 parameter, 0 given error: 2, IntlCalendar::before(): intlcal_before/after: bad arguments bool(false) error: 4096, Argument 1 passed to IntlCalendar::after() must be an instance of IntlCalendar, integer given -error: 2, IntlCalendar::after() expects parameter 1 to be IntlCalendar, integer given -error: 2, IntlCalendar::after(): intlcal_before/after: bad arguments -bool(false) + error: 4096, Argument 1 passed to IntlCalendar::before() must be an instance of IntlCalendar, integer given -error: 2, IntlCalendar::before() expects parameter 1 to be IntlCalendar, integer given -error: 2, IntlCalendar::before(): intlcal_before/after: bad arguments -bool(false) + error: 2, IntlCalendar::after() expects exactly 1 parameter, 2 given error: 2, IntlCalendar::after(): intlcal_before/after: bad arguments bool(false) diff --git a/ext/intl/tests/calendar_equals_error.phpt b/ext/intl/tests/calendar_equals_error.phpt index a947b42bfe..e6b2397c09 100644 --- a/ext/intl/tests/calendar_equals_error.phpt +++ b/ext/intl/tests/calendar_equals_error.phpt @@ -17,30 +17,42 @@ echo "error: $errno, $errstr\n"; } set_error_handler('eh'); -var_dump($c->equals()); -var_dump($c->equals(new stdclass)); -var_dump($c->equals(1, 2)); +try { + var_dump($c->equals()); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump($c->equals(new stdclass)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump($c->equals(1, 2)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} + -var_dump(intlcal_equals($c, array())); -var_dump(intlcal_equals(1, $c)); +try { + var_dump(intlcal_equals($c, array())); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump(intlcal_equals(1, $c)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} --EXPECT-- error: 2, IntlCalendar::equals() expects exactly 1 parameter, 0 given error: 2, IntlCalendar::equals(): intlcal_equals: bad arguments bool(false) error: 4096, Argument 1 passed to IntlCalendar::equals() must be an instance of IntlCalendar, instance of stdClass given -error: 2, IntlCalendar::equals() expects parameter 1 to be IntlCalendar, object given -error: 2, IntlCalendar::equals(): intlcal_equals: bad arguments -bool(false) + error: 4096, Argument 1 passed to IntlCalendar::equals() must be an instance of IntlCalendar, integer given -error: 2, IntlCalendar::equals() expects exactly 1 parameter, 2 given -error: 2, IntlCalendar::equals(): intlcal_equals: bad arguments -bool(false) + error: 4096, Argument 2 passed to intlcal_equals() must be an instance of IntlCalendar, array given -error: 2, intlcal_equals() expects parameter 2 to be IntlCalendar, array given -error: 2, intlcal_equals(): intlcal_equals: bad arguments -bool(false) + error: 4096, Argument 1 passed to intlcal_equals() must be an instance of IntlCalendar, integer given -error: 2, intlcal_equals() expects parameter 1 to be IntlCalendar, integer given -error: 2, intlcal_equals(): intlcal_equals: bad arguments -bool(false) diff --git a/ext/intl/tests/calendar_get_Least_Greatest_Minimum_Maximum_error.phpt b/ext/intl/tests/calendar_get_Least_Greatest_Minimum_Maximum_error.phpt index acd9b58c1d..653df1a043 100644 --- a/ext/intl/tests/calendar_get_Least_Greatest_Minimum_Maximum_error.phpt +++ b/ext/intl/tests/calendar_get_Least_Greatest_Minimum_Maximum_error.phpt @@ -32,10 +32,26 @@ echo "error: $errno, $errstr\n"; } set_error_handler('eh'); -var_dump(intlcal_get_least_maximum(1, 1)); -var_dump(intlcal_get_maximum(1, 1)); -var_dump(intlcal_get_greatest_minimum(1, -1)); -var_dump(intlcal_get_minimum(1, -1)); +try { + var_dump(intlcal_get_least_maximum(1, 1)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump(intlcal_get_maximum(1, 1)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump(intlcal_get_greatest_minimum(1, -1)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump(intlcal_get_minimum(1, -1)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} --EXPECTF-- @@ -83,18 +99,10 @@ bool(false) Warning: intlcal_get_minimum(): intlcal_get_minimum: invalid field in %s on line %d bool(false) error: 4096, Argument 1 passed to intlcal_get_least_maximum() must be an instance of IntlCalendar, integer given -error: 2, intlcal_get_least_maximum() expects parameter 1 to be IntlCalendar, integer given -error: 2, intlcal_get_least_maximum(): intlcal_get_least_maximum: bad arguments -bool(false) + error: 4096, Argument 1 passed to intlcal_get_maximum() must be an instance of IntlCalendar, integer given -error: 2, intlcal_get_maximum() expects parameter 1 to be IntlCalendar, integer given -error: 2, intlcal_get_maximum(): intlcal_get_maximum: bad arguments -bool(false) + error: 4096, Argument 1 passed to intlcal_get_greatest_minimum() must be an instance of IntlCalendar, integer given -error: 2, intlcal_get_greatest_minimum() expects parameter 1 to be IntlCalendar, integer given -error: 2, intlcal_get_greatest_minimum(): intlcal_get_greatest_minimum: bad arguments -bool(false) + error: 4096, Argument 1 passed to intlcal_get_minimum() must be an instance of IntlCalendar, integer given -error: 2, intlcal_get_minimum() expects parameter 1 to be IntlCalendar, integer given -error: 2, intlcal_get_minimum(): intlcal_get_minimum: bad arguments -bool(false) + diff --git a/ext/intl/tests/calendar_get_getActualMaximum_Minumum_error2.phpt b/ext/intl/tests/calendar_get_getActualMaximum_Minumum_error2.phpt index 6b9845a913..4940b19b40 100644 --- a/ext/intl/tests/calendar_get_getActualMaximum_Minumum_error2.phpt +++ b/ext/intl/tests/calendar_get_getActualMaximum_Minumum_error2.phpt @@ -17,21 +17,69 @@ echo "error: $errno, $errstr\n"; } set_error_handler('eh'); -var_dump(intlcal_get($c)); -var_dump(intlcal_get_actual_maximum($c)); -var_dump(intlcal_get_actual_minimum($c)); +try { + var_dump(intlcal_get($c)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump(intlcal_get_actual_maximum($c)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump(intlcal_get_actual_minimum($c)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} -var_dump(intlcal_get($c, -1)); -var_dump(intlcal_get_actual_maximum($c, -1)); -var_dump(intlcal_get_actual_minimum($c, -1)); +try { + var_dump(intlcal_get($c, -1)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump(intlcal_get_actual_maximum($c, -1)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump(intlcal_get_actual_minimum($c, -1)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} -var_dump(intlcal_get($c, "s")); -var_dump(intlcal_get_actual_maximum($c, "s")); -var_dump(intlcal_get_actual_minimum($c, "s")); +try { + var_dump(intlcal_get($c, "s")); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump(intlcal_get_actual_maximum($c, "s")); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump(intlcal_get_actual_minimum($c, "s")); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} -var_dump(intlcal_get(1)); -var_dump(intlcal_get_actual_maximum(1)); -var_dump(intlcal_get_actual_minimum(1)); +try { + var_dump(intlcal_get(1)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump(intlcal_get_actual_maximum(1)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump(intlcal_get_actual_minimum(1)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} --EXPECT-- error: 2, intlcal_get() expects exactly 2 parameters, 1 given error: 2, intlcal_get(): intlcal_get: bad arguments @@ -58,14 +106,8 @@ error: 2, intlcal_get_actual_minimum() expects parameter 2 to be integer, string error: 2, intlcal_get_actual_minimum(): intlcal_get_actual_minimum: bad arguments bool(false) error: 4096, Argument 1 passed to intlcal_get() must be an instance of IntlCalendar, integer given -error: 2, intlcal_get() expects exactly 2 parameters, 1 given -error: 2, intlcal_get(): intlcal_get: bad arguments -bool(false) + error: 4096, Argument 1 passed to intlcal_get_actual_maximum() must be an instance of IntlCalendar, integer given -error: 2, intlcal_get_actual_maximum() expects exactly 2 parameters, 1 given -error: 2, intlcal_get_actual_maximum(): intlcal_get_actual_maximum: bad arguments -bool(false) + error: 4096, Argument 1 passed to intlcal_get_actual_minimum() must be an instance of IntlCalendar, integer given -error: 2, intlcal_get_actual_minimum() expects exactly 2 parameters, 1 given -error: 2, intlcal_get_actual_minimum(): intlcal_get_actual_minimum: bad arguments -bool(false) + diff --git a/ext/intl/tests/calendar_isEquivalentTo_error.phpt b/ext/intl/tests/calendar_isEquivalentTo_error.phpt index 4fa7da5eb6..055b0f18e1 100644 --- a/ext/intl/tests/calendar_isEquivalentTo_error.phpt +++ b/ext/intl/tests/calendar_isEquivalentTo_error.phpt @@ -17,34 +17,49 @@ echo "error: $errno, $errstr\n"; } set_error_handler('eh'); -var_dump($c->isEquivalentTo(0)); -var_dump($c->isEquivalentTo($c, 1)); -var_dump($c->isEquivalentTo(1)); +try { + var_dump($c->isEquivalentTo(0)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump($c->isEquivalentTo($c, 1)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump($c->isEquivalentTo(1)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} -var_dump(intlcal_is_equivalent_to($c)); -var_dump(intlcal_is_equivalent_to($c, 1)); -var_dump(intlcal_is_equivalent_to(1, $c)); +try { + var_dump(intlcal_is_equivalent_to($c)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump(intlcal_is_equivalent_to($c, 1)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump(intlcal_is_equivalent_to(1, $c)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} --EXPECT-- error: 4096, Argument 1 passed to IntlCalendar::isEquivalentTo() must be an instance of IntlCalendar, integer given -error: 2, IntlCalendar::isEquivalentTo() expects parameter 1 to be IntlCalendar, integer given -error: 2, IntlCalendar::isEquivalentTo(): intlcal_is_equivalent_to: bad arguments -bool(false) + error: 2, IntlCalendar::isEquivalentTo() expects exactly 1 parameter, 2 given error: 2, IntlCalendar::isEquivalentTo(): intlcal_is_equivalent_to: bad arguments bool(false) error: 4096, Argument 1 passed to IntlCalendar::isEquivalentTo() must be an instance of IntlCalendar, integer given -error: 2, IntlCalendar::isEquivalentTo() expects parameter 1 to be IntlCalendar, integer given -error: 2, IntlCalendar::isEquivalentTo(): intlcal_is_equivalent_to: bad arguments -bool(false) + error: 2, intlcal_is_equivalent_to() expects exactly 2 parameters, 1 given error: 2, intlcal_is_equivalent_to(): intlcal_is_equivalent_to: bad arguments bool(false) error: 4096, Argument 2 passed to intlcal_is_equivalent_to() must be an instance of IntlCalendar, integer given -error: 2, intlcal_is_equivalent_to() expects parameter 2 to be IntlCalendar, integer given -error: 2, intlcal_is_equivalent_to(): intlcal_is_equivalent_to: bad arguments -bool(false) + error: 4096, Argument 1 passed to intlcal_is_equivalent_to() must be an instance of IntlCalendar, integer given -error: 2, intlcal_is_equivalent_to() expects parameter 1 to be IntlCalendar, integer given -error: 2, intlcal_is_equivalent_to(): intlcal_is_equivalent_to: bad arguments -bool(false) diff --git a/ext/intl/tests/calendar_setTimeZone_error.phpt b/ext/intl/tests/calendar_setTimeZone_error.phpt index ebe4d119ea..70e5380ef8 100644 --- a/ext/intl/tests/calendar_setTimeZone_error.phpt +++ b/ext/intl/tests/calendar_setTimeZone_error.phpt @@ -19,11 +19,27 @@ echo "error: $errno, $errstr\n"; } set_error_handler('eh'); -var_dump($c->setTimeZone($gmt, 2)); -var_dump($c->setTimeZone()); +try { + var_dump($c->setTimeZone($gmt, 2)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try { + var_dump($c->setTimeZone()); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} -var_dump(intlcal_set_time_zone($c, 1, 2)); -var_dump(intlcal_set_time_zone(1, $gmt)); +try{ + var_dump(intlcal_set_time_zone($c, 1, 2)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} +try{ + var_dump(intlcal_set_time_zone(1, $gmt)); +} catch (EngineException $ex) { + echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; +} --EXPECT-- error: 2, IntlCalendar::setTimeZone() expects exactly 1 parameter, 2 given @@ -36,6 +52,3 @@ error: 2, intlcal_set_time_zone() expects exactly 2 parameters, 3 given error: 2, intlcal_set_time_zone(): intlcal_set_time_zone: bad arguments bool(false) error: 4096, Argument 1 passed to intlcal_set_time_zone() must be an instance of IntlCalendar, integer given -error: 2, intlcal_set_time_zone() expects parameter 1 to be IntlCalendar, integer given -error: 2, intlcal_set_time_zone(): intlcal_set_time_zone: bad arguments -bool(false) diff --git a/ext/intl/tests/timezone_hasSameRules_error.phpt b/ext/intl/tests/timezone_hasSameRules_error.phpt index 35a29be5db..102dfc9f8d 100644 --- a/ext/intl/tests/timezone_hasSameRules_error.phpt +++ b/ext/intl/tests/timezone_hasSameRules_error.phpt @@ -16,22 +16,24 @@ function error_handler($errno, $errstr, $errfile, $errline) set_error_handler("error_handler"); $tz = IntlTimeZone::createTimeZone('Europe/Lisbon'); -var_dump($tz->hasSameRules('foo')); +try { + var_dump($tz->hasSameRules('foo')); +} catch (EngineException $ex) { + var_dump($ex->getCode(), $ex->getMessage()); + echo "\n"; +} -var_dump(intltz_has_same_rules(null, $tz)); +try { + var_dump(intltz_has_same_rules(null, $tz)); +} catch (EngineException $ex) { + var_dump($ex->getCode(), $ex->getMessage()); + echo "\n"; +} --EXPECT-- int(4096) string(99) "Argument 1 passed to IntlTimeZone::hasSameRules() must be an instance of IntlTimeZone, string given" -int(2) -string(81) "IntlTimeZone::hasSameRules() expects parameter 1 to be IntlTimeZone, string given" -int(2) -string(66) "IntlTimeZone::hasSameRules(): intltz_has_same_rules: bad arguments" -bool(false) + int(4096) string(92) "Argument 1 passed to intltz_has_same_rules() must be an instance of IntlTimeZone, null given" -int(2) -string(74) "intltz_has_same_rules() expects parameter 1 to be IntlTimeZone, null given" -int(2) -string(61) "intltz_has_same_rules(): intltz_has_same_rules: bad arguments" -bool(false) + diff --git a/ext/mysqli/tests/mysqli_fetch_object.phpt b/ext/mysqli/tests/mysqli_fetch_object.phpt index c70871e6ea..0a970a82b8 100644 --- a/ext/mysqli/tests/mysqli_fetch_object.phpt +++ b/ext/mysqli/tests/mysqli_fetch_object.phpt @@ -101,8 +101,8 @@ require_once('skipifconnectfailure.inc'); try { if (false !== ($obj = @mysqli_fetch_object($res, 'mysqli_fetch_object_construct', 'a'))) printf("[011] Should have failed\n"); - } catch (Exception $e) { - printf("%s\n", $e->getMessage()); + } catch (EngineException $e) { + handle_catchable_fatal($e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine()); } mysqli_free_result($res); @@ -151,6 +151,5 @@ NULL [E_WARNING] mysqli_fetch_object(): Couldn't fetch mysqli_result in %s on line %d NULL [E_RECOVERABLE_ERROR] Argument 3 passed to mysqli_fetch_object() must be of the type array, string given in %s on line %d -Parameter ctor_params must be an array Fatal error: Class 'this_class_does_not_exist' not found in %s on line %d \ No newline at end of file diff --git a/ext/mysqli/tests/mysqli_fetch_object_oo.phpt b/ext/mysqli/tests/mysqli_fetch_object_oo.phpt index 1d62c6dd4f..ff53fbefcd 100644 --- a/ext/mysqli/tests/mysqli_fetch_object_oo.phpt +++ b/ext/mysqli/tests/mysqli_fetch_object_oo.phpt @@ -31,11 +31,20 @@ require_once('skipifconnectfailure.inc'); if (!is_null($tmp = @$res->fetch_object($link))) printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp); - if (!is_null($tmp = @$res->fetch_object($link, $link))) - printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp); + try { + if (!is_null($tmp = @$res->fetch_object($link, $link))) + printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp); + } catch (EngineException $e) { + handle_catchable_fatal($e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine()); + } + - if (!is_null($tmp = @$res->fetch_object($link, $link, $link))) - printf("[006] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp); + try { + if (!is_null($tmp = @$res->fetch_object($link, $link, $link))) + printf("[006] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp); + } catch (EngineException $e) { + handle_catchable_fatal($e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine()); + } $obj = mysqli_fetch_object($res); if (($obj->ID !== "1") || ($obj->label !== "a") || (get_class($obj) != 'stdClass')) { @@ -68,11 +77,16 @@ require_once('skipifconnectfailure.inc'); } - $obj = $res->fetch_object('mysqli_fetch_object_construct', null); + try { + $obj = $res->fetch_object('mysqli_fetch_object_construct', null); - if (($obj->ID !== "3") || ($obj->label !== "c") || ($obj->a !== NULL) || ($obj->b !== NULL) || (get_class($obj) != 'mysqli_fetch_object_construct')) { - printf("[009] Object seems wrong. [%d] %s\n", $mysqli->errno, $mysqli->error); - var_dump($obj); + if (($obj->ID !== "3") || ($obj->label !== "c") || ($obj->a !== NULL) || ($obj->b !== NULL) || (get_class($obj) != 'mysqli_fetch_object_construct')) { + printf("[009] Object seems wrong. [%d] %s\n", $mysqli->errno, $mysqli->error); + var_dump($obj); + } + } catch (EngineException $e) { + handle_catchable_fatal($e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine()); + mysqli_fetch_object($res); } $obj = $res->fetch_object('mysqli_fetch_object_construct', array('a')); @@ -116,14 +130,8 @@ require_once('skipifconnectfailure.inc'); [E_WARNING] mysqli_result::fetch_object(): Couldn't fetch mysqli_result in %s on line %d [E_WARNING] mysqli_result::fetch_object() expects parameter 1 to be string, object given in %s on line %d [E_RECOVERABLE_ERROR] Argument 2 passed to mysqli_result::fetch_object() must be of the type array, object given in %s on line %d -[E_WARNING] mysqli_result::fetch_object() expects parameter 1 to be string, object given in %s on line %d [E_RECOVERABLE_ERROR] Argument 2 passed to mysqli_result::fetch_object() must be of the type array, object given in %s on line %d -[E_WARNING] mysqli_result::fetch_object() expects at most 2 parameters, 3 given in %s on line %d [E_RECOVERABLE_ERROR] Argument 2 passed to mysqli_result::fetch_object() must be of the type array, null given in %s on line %d -[E_WARNING] Missing argument 1 for mysqli_fetch_object_construct::__construct() in %s on line %d -[E_WARNING] Missing argument 2 for mysqli_fetch_object_construct::__construct() in %s on line %d -[E_NOTICE] Undefined variable: a in %s on line %d -[E_NOTICE] Undefined variable: b in %s on line %d [E_WARNING] Missing argument 2 for mysqli_fetch_object_construct::__construct() in %s on line %d [E_NOTICE] Undefined variable: b in %s on line %d NULL @@ -131,4 +139,4 @@ NULL [E_WARNING] mysqli_fetch_object(): Couldn't fetch mysqli_result in %s on line %d NULL -Fatal error: Class 'this_class_does_not_exist' not found in %s on line %d \ No newline at end of file +Fatal error: Class 'this_class_does_not_exist' not found in %s on line %d diff --git a/ext/reflection/tests/ReflectionMethod_invokeArgs_error2.phpt b/ext/reflection/tests/ReflectionMethod_invokeArgs_error2.phpt index 5fc7564245..0405df67e1 100644 --- a/ext/reflection/tests/ReflectionMethod_invokeArgs_error2.phpt +++ b/ext/reflection/tests/ReflectionMethod_invokeArgs_error2.phpt @@ -18,10 +18,10 @@ $testClassInstance = new TestClass(); try { var_dump($foo->invokeArgs($testClassInstance, true)); -} catch (Exception $e) { +} catch (EngineException $e) { var_dump($e->getMessage()); } ?> ---EXPECTF-- -Catchable fatal error: Argument 2 passed to ReflectionMethod::invokeArgs() must be of the type array, boolean given in %s on line %d +--EXPECT-- +string(92) "Argument 2 passed to ReflectionMethod::invokeArgs() must be of the type array, boolean given" diff --git a/ext/session/tests/bug60634_error_1.phpt b/ext/session/tests/bug60634_error_1.phpt index cc50e81209..276153e322 100644 --- a/ext/session/tests/bug60634_error_1.phpt +++ b/ext/session/tests/bug60634_error_1.phpt @@ -46,4 +46,3 @@ echo "um, hi\n"; write: goodbye cruel world Fatal error: Call to undefined function undefined_function() in %s on line %d -close: goodbye cruel world diff --git a/ext/simplexml/tests/bug37565.phpt b/ext/simplexml/tests/bug37565.phpt index c1e51040b6..cf5a3d8849 100644 --- a/ext/simplexml/tests/bug37565.phpt +++ b/ext/simplexml/tests/bug37565.phpt @@ -15,17 +15,23 @@ class Setting extends ReflectionObject { } -Reflection::export(simplexml_load_string('', 'Setting')); +try { + Reflection::export(simplexml_load_string('', 'Setting')); +} catch (EngineException $e) { + my_error_handler($e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine()); +} -Reflection::export(simplexml_load_file('data:,', 'Setting')); +try { + Reflection::export(simplexml_load_file('data:,', 'Setting')); +} catch (EngineException $e) { + my_error_handler($e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine()); +} ?> ===DONE=== --EXPECTF-- Error: simplexml_load_string() expects parameter 2 to be a class name derived from SimpleXMLElement, 'Setting' given Error: Argument 1 passed to Reflection::export() must implement interface Reflector, null given -Error: Reflection::export() expects parameter 1 to be Reflector, null given Error: simplexml_load_file() expects parameter 2 to be a class name derived from SimpleXMLElement, 'Setting' given Error: Argument 1 passed to Reflection::export() must implement interface Reflector, null given -Error: Reflection::export() expects parameter 1 to be Reflector, null given ===DONE=== diff --git a/ext/soap/soap.c b/ext/soap/soap.c index 400f89700d..3e3f0d9ee0 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -1482,6 +1482,26 @@ PHP_METHOD(SoapServer, addFunction) } /* }}} */ +static void _soap_server_exception(soapServicePtr service, sdlFunctionPtr function, zval *this_ptr) /* {{{ */ +{ + zval exception_object; + + ZVAL_OBJ(&exception_object, EG(exception)); + if (instanceof_function(Z_OBJCE(exception_object), soap_fault_class_entry)) { + soap_server_fault_ex(function, &exception_object, NULL); + } else if (instanceof_function(Z_OBJCE(exception_object), zend_get_engine_exception())) { + if (service->send_errors) { + zval rv; + zend_string *msg = zval_get_string(zend_read_property(zend_exception_get_base(), &exception_object, "message", sizeof("message")-1, 0, &rv)); + add_soap_fault_ex(&exception_object, this_ptr, "Server", msg->val, NULL, NULL); + zend_string_release(msg); + } else { + add_soap_fault_ex(&exception_object, this_ptr, "Server", "Internal Error", NULL, NULL); + } + soap_server_fault_ex(function, &exception_object, NULL); + } +} +/* }}} */ /* {{{ proto void SoapServer::handle ( [string soap_request]) Handles a SOAP request */ @@ -1646,13 +1666,8 @@ PHP_METHOD(SoapServer, handle) xmlFreeDoc(doc_request); if (EG(exception)) { - zval exception_object; - - ZVAL_OBJ(&exception_object, EG(exception)); php_output_discard(); - if (instanceof_function(Z_OBJCE(exception_object), soap_fault_class_entry)) { - soap_server_fault_ex(function, &exception_object, NULL); - } + _soap_server_exception(service, function, getThis()); goto fail; } @@ -1700,13 +1715,8 @@ PHP_METHOD(SoapServer, handle) php_error_docref(NULL, E_ERROR, "Error calling constructor"); } if (EG(exception)) { - zval exception_object; - - ZVAL_OBJ(&exception_object, EG(exception)); php_output_discard(); - if (instanceof_function(Z_OBJCE(exception_object), soap_fault_class_entry)) { - soap_server_fault_ex(function, &exception_object, NULL); - } + _soap_server_exception(service, function, getThis()); zval_dtor(&constructor); zval_dtor(&c_ret); zval_ptr_dtor(&tmp_soap); @@ -1728,13 +1738,8 @@ PHP_METHOD(SoapServer, handle) } if (EG(exception)) { - zval exception_object; - - ZVAL_OBJ(&exception_object, EG(exception)); php_output_discard(); - if (instanceof_function(Z_OBJCE(exception_object), soap_fault_class_entry)) { - soap_server_fault_ex(function, &exception_object, NULL); - } + _soap_server_exception(service, function, getThis()); zval_dtor(&constructor); zval_dtor(&c_ret); efree(class_name); @@ -1823,20 +1828,8 @@ PHP_METHOD(SoapServer, handle) if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(soap_obj);} goto fail; } else if (EG(exception)) { - zval exception_object; - - ZVAL_OBJ(&exception_object, EG(exception)); php_output_discard(); - if (instanceof_function(Z_OBJCE(exception_object), soap_fault_class_entry)) { -//??? zval *headerfault = NULL; - zval *tmp; - - if ((tmp = zend_hash_str_find(Z_OBJPROP(exception_object), "headerfault", sizeof("headerfault")-1)) != NULL && - Z_TYPE_P(tmp) != IS_NULL) { -//??? headerfault = tmp; - } - soap_server_fault_ex(function, &exception_object, h); - } + _soap_server_exception(service, function, getThis()); efree(fn_name); if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(soap_obj);} goto fail; @@ -1874,13 +1867,8 @@ PHP_METHOD(SoapServer, handle) efree(fn_name); if (EG(exception)) { - zval exception_object; - - ZVAL_OBJ(&exception_object, EG(exception)); php_output_discard(); - if (instanceof_function(Z_OBJCE(exception_object), soap_fault_class_entry)) { - soap_server_fault_ex(function, &exception_object, NULL); - } + _soap_server_exception(service, function, getThis()); if (service->type == SOAP_CLASS) { #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION) if (soap_obj && service->soap_class.persistence != SOAP_PERSISTENCE_SESSION) { @@ -1918,13 +1906,8 @@ PHP_METHOD(SoapServer, handle) } if (EG(exception)) { - zval exception_object; - - ZVAL_OBJ(&exception_object, EG(exception)); php_output_discard(); - if (instanceof_function(Z_OBJCE(exception_object), soap_fault_class_entry)) { - soap_server_fault_ex(function, &exception_object, NULL); - } + _soap_server_exception(service, function, getThis()); if (service->type == SOAP_CLASS) { #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION) if (soap_obj && service->soap_class.persistence != SOAP_PERSISTENCE_SESSION) { @@ -2143,7 +2126,7 @@ static void soap_error_handler(int error_num, const char *error_filename, const _old_http_response_code = SG(sapi_headers).http_response_code; _old_http_status_line = SG(sapi_headers).http_status_line; - if (!SOAP_GLOBAL(use_soap_error_handler) || !EG(objects_store).object_buckets) { + if (!SOAP_GLOBAL(use_soap_error_handler) || !EG(objects_store).object_buckets || (error_num & E_EXCEPTION)) { call_old_error_handler(error_num, error_filename, error_lineno, format, args); return; } diff --git a/ext/soap/tests/server014.phpt b/ext/soap/tests/server014.phpt index fcb62a542c..d248c355bd 100644 --- a/ext/soap/tests/server014.phpt +++ b/ext/soap/tests/server014.phpt @@ -35,3 +35,4 @@ echo "ok\n"; --EXPECT-- SOAP-ENV:ServerCall to undefined function undefined_function_x() +ok diff --git a/ext/spl/tests/CallbackFilterIteratorTest-002.phpt b/ext/spl/tests/CallbackFilterIteratorTest-002.phpt index cbad2e3b9c..bc4fd14647 100644 --- a/ext/spl/tests/CallbackFilterIteratorTest-002.phpt +++ b/ext/spl/tests/CallbackFilterIteratorTest-002.phpt @@ -18,6 +18,8 @@ try { new CallbackFilterIterator(null); } catch(InvalidArgumentException $e) { echo $e->getMessage() . "\n"; +} catch(EngineException $e) { + echo $e->getMessage() . "\n"; } try { @@ -44,7 +46,6 @@ try { --EXPECT-- CallbackFilterIterator::__construct() expects exactly 2 parameters, 0 given Argument 1 passed to CallbackFilterIterator::__construct() must implement interface Iterator, null given -CallbackFilterIterator::__construct() expects exactly 2 parameters, 1 given CallbackFilterIterator::__construct() expects parameter 2 to be a valid callback, no array or string given CallbackFilterIterator::__construct() expects parameter 2 to be a valid callback, array must have exactly two members some message diff --git a/ext/spl/tests/iterator_042.phpt b/ext/spl/tests/iterator_042.phpt index e2fb167583..d654ede97a 100644 --- a/ext/spl/tests/iterator_042.phpt +++ b/ext/spl/tests/iterator_042.phpt @@ -3,7 +3,7 @@ SPL: AppendIterator and its ArrayIterator --FILE-- append(array()); +try { + $it->append(array()); +} catch (EngineException $e) { + test_error_handler($e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine()); +} $it->append(new ArrayIterator(array(1))); $it->append(new ArrayIterator(array(21, 22))); diff --git a/ext/spl/tests/spl_004.phpt b/ext/spl/tests/spl_004.phpt index d56f48f896..c321bab296 100644 --- a/ext/spl/tests/spl_004.phpt +++ b/ext/spl/tests/spl_004.phpt @@ -42,7 +42,11 @@ $it = new RecursiveIteratorIterator($it); var_dump(iterator_apply($it, 'test')); echo "===ERRORS===\n"; -var_dump(iterator_apply($it, 'test', 1)); +try { + var_dump(iterator_apply($it, 'test', 1)); +} catch (EngineException $e) { + my_error_handler($e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine()); +} var_dump(iterator_apply($it, 'non_existing_function')); var_dump(iterator_apply($it, 'non_existing_function', NULL, 2)); @@ -75,8 +79,6 @@ int(6) int(4) ===ERRORS=== Error: Argument 3 passed to iterator_apply() must be of the type array, integer given -Error: iterator_apply() expects parameter 3 to be array, integer given -NULL Error: iterator_apply() expects parameter 2 to be a valid callback, function 'non_existing_function' not found or invalid function name NULL Error: iterator_apply() expects at most 3 parameters, 4 given diff --git a/ext/standard/tests/file/bug38450_3.phpt b/ext/standard/tests/file/bug38450_3.phpt index 389de87b4c..1e4c8c50c6 100644 --- a/ext/standard/tests/file/bug38450_3.phpt +++ b/ext/standard/tests/file/bug38450_3.phpt @@ -102,4 +102,6 @@ var_dump($myvar); echo "Done\n"; ?> --EXPECTF-- +Warning: fopen(var://myvar): failed to open stream: "VariableStream::stream_open" call failed in %sbug38450_3.php on line %d + Catchable fatal error: Argument 1 passed to VariableStream::__construct() must be of the type array, none given in %s on line %d diff --git a/ext/standard/tests/general_functions/bug47857.phpt b/ext/standard/tests/general_functions/bug47857.phpt index 3bdf1c23d6..b3714a210d 100644 --- a/ext/standard/tests/general_functions/bug47857.phpt +++ b/ext/standard/tests/general_functions/bug47857.phpt @@ -19,5 +19,5 @@ Strict Standards: Non-static method foo::bar() should not be called statically i ok bool(false) -Fatal error: Non-static method Exception::getMessage() cannot be called statically in %sbug47857.php on line %d +Fatal error: Non-static method BaseException::getMessage() cannot be called statically in %sbug47857.php on line %d diff --git a/main/main.c b/main/main.c index f5c04099ea..ffbead83c8 100644 --- a/main/main.c +++ b/main/main.c @@ -2540,6 +2540,10 @@ PHPAPI int php_execute_script(zend_file_handle *primary_file) } } zend_end_try(); + if (EG(exception)) { + zend_exception_error(EG(exception), E_ERROR); + } + #if HAVE_BROKEN_GETCWD if (old_cwd_fd != -1) { fchdir(old_cwd_fd); @@ -2665,6 +2669,9 @@ PHPAPI int php_lint_script(zend_file_handle *file) retval = SUCCESS; } } zend_end_try(); + if (EG(exception)) { + zend_exception_error(EG(exception), E_ERROR); + } return retval; } diff --git a/sapi/cli/tests/005.phpt b/sapi/cli/tests/005.phpt index 84b0f98440..2ec0a40df3 100644 --- a/sapi/cli/tests/005.phpt +++ b/sapi/cli/tests/005.phpt @@ -14,7 +14,7 @@ $php = getenv('TEST_PHP_EXECUTABLE'); var_dump(`"$php" -n --rc unknown`); var_dump(`"$php" -n --rc stdclass`); -var_dump(`"$php" -n --rc exception`); +var_dump(`"$php" -n --rc baseexception`); echo "Done\n"; ?> @@ -40,7 +40,7 @@ string(183) "Class [ class stdClass ] { } " -string(1355) "Class [ class Exception ] { +string(1368) "Class [ abstract class BaseException ] { - Constants [0] { } diff --git a/tests/classes/type_hinting_004.phpt b/tests/classes/type_hinting_004.phpt index 9068909a82..70637173bd 100644 --- a/tests/classes/type_hinting_004.phpt +++ b/tests/classes/type_hinting_004.phpt @@ -16,13 +16,36 @@ Ensure type hints are enforced for functions invoked as callbacks. function f2(A $a = null) { echo "in f2;\n"; } - call_user_func('f1', 1); - call_user_func('f1', new A); - call_user_func('f2', 1); - call_user_func('f2'); - call_user_func('f2', new A); - call_user_func('f2', null); - + try { + call_user_func('f1', 1); + } catch (EngineException $ex) { + echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; + } + try { + call_user_func('f1', new A); + } catch (EngineException $ex) { + echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; + } + try { + call_user_func('f2', 1); + } catch (EngineException $ex) { + echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; + } + try { + call_user_func('f2'); + } catch (EngineException $ex) { + echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; + } + try { + call_user_func('f2', new A); + } catch (EngineException $ex) { + echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; + } + try { + call_user_func('f2', null); + } catch (EngineException $ex) { + echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; + } echo "\n\n---> Type hints with callback static method:\n"; class C { @@ -41,13 +64,37 @@ Ensure type hints are enforced for functions invoked as callbacks. } } } - call_user_func(array('C', 'f1'), 1); - call_user_func(array('C', 'f1'), new A); - call_user_func(array('C', 'f2'), 1); - call_user_func(array('C', 'f2')); - call_user_func(array('C', 'f2'), new A); - call_user_func(array('C', 'f2'), null); - + + try { + call_user_func(array('C', 'f1'), 1); + } catch (EngineException $ex) { + echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; + } + try { + call_user_func(array('C', 'f1'), new A); + } catch (EngineException $ex) { + echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; + } + try { + call_user_func(array('C', 'f2'), 1); + } catch (EngineException $ex) { + echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; + } + try { + call_user_func(array('C', 'f2')); + } catch (EngineException $ex) { + echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; + } + try { + call_user_func(array('C', 'f2'), new A); + } catch (EngineException $ex) { + echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; + } + try { + call_user_func(array('C', 'f2'), null); + } catch (EngineException $ex) { + echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; + } echo "\n\n---> Type hints with callback instance method:\n"; class D { @@ -67,43 +114,68 @@ Ensure type hints are enforced for functions invoked as callbacks. } } $d = new D; - call_user_func(array($d, 'f1'), 1); - call_user_func(array($d, 'f1'), new A); - call_user_func(array($d, 'f2'), 1); - call_user_func(array($d, 'f2')); - call_user_func(array($d, 'f2'), new A); - call_user_func(array($d, 'f2'), null); + + try { + call_user_func(array($d, 'f1'), 1); + } catch (EngineException $ex) { + echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; + } + try { + call_user_func(array($d, 'f1'), new A); + } catch (EngineException $ex) { + echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; + } + try { + call_user_func(array($d, 'f2'), 1); + } catch (EngineException $ex) { + echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; + } + try { + call_user_func(array($d, 'f2')); + } catch (EngineException $ex) { + echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; + } + try { + call_user_func(array($d, 'f2'), new A); + } catch (EngineException $ex) { + echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; + } + try { + call_user_func(array($d, 'f2'), null); + } catch (EngineException $ex) { + echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n"; + } ?> --EXPECTF-- ---> Type hints with callback function: -4096: Argument 1 passed to f1() must be an instance of A, integer given%s(10) -in f1; +4096: Argument 1 passed to f1() must be an instance of A, integer given%s(%d) + in f1; -4096: Argument 1 passed to f2() must be an instance of A, integer given%s(13) -in f2; +4096: Argument 1 passed to f2() must be an instance of A, integer given%s(%d) + in f2; in f2; in f2; ---> Type hints with callback static method: -4096: Argument 1 passed to C::f1() must be an instance of A, integer given%s(26) -in C::f1 (static); +4096: Argument 1 passed to C::f1() must be an instance of A, integer given%s(%d) + in C::f1 (static); -4096: Argument 1 passed to C::f2() must be an instance of A, integer given%s(33) -in C::f2 (static); +4096: Argument 1 passed to C::f2() must be an instance of A, integer given%s(%d) + in C::f2 (static); in C::f2 (static); in C::f2 (static); ---> Type hints with callback instance method: -4096: Argument 1 passed to D::f1() must be an instance of A, integer given%s(51) -in C::f1 (instance); +4096: Argument 1 passed to D::f1() must be an instance of A, integer given%s(%d) + in C::f1 (instance); -4096: Argument 1 passed to D::f2() must be an instance of A, integer given%s(58) -in C::f2 (instance); +4096: Argument 1 passed to D::f2() must be an instance of A, integer given%s(%d) + in C::f2 (instance); in C::f2 (instance); in C::f2 (instance); diff --git a/tests/lang/catchable_error_002.phpt b/tests/lang/catchable_error_002.phpt index c1762b2db7..a80928523b 100644 --- a/tests/lang/catchable_error_002.phpt +++ b/tests/lang/catchable_error_002.phpt @@ -17,21 +17,13 @@ Catchable fatal error [2] set_error_handler('error'); - blah (new StdClass); + try { + blah (new StdClass); + } catch (engineException $ex) { + echo $ex->getMessage(), "\n"; + } echo "ALIVE!\n"; ?> --EXPECTF-- -array(5) { - [0]=> - int(4096) - [1]=> - string(%d) "Argument 1 passed to blah() must be an instance of Foo, instance of stdClass given, called in %scatchable_error_002.php on line %d and defined" - [2]=> - string(%d) "%scatchable_error_002.php" - [3]=> - int(5) - [4]=> - array(0) { - } -} +Argument 1 passed to blah() must be an instance of Foo, instance of stdClass given, called in %scatchable_error_002.php on line 18 and defined ALIVE! -- 2.40.0