Last active
August 29, 2015 14:07
-
-
Save thekid/4f68e84e44773a88cd99 to your computer and use it in GitHub Desktop.
Patch for PHP PR #847 - Catchable "Call to a member function bar() on a non-object"
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/NEWS b/NEWS | |
| index c348efe..2f8883b 100644 | |
| --- a/NEWS | |
| +++ b/NEWS | |
| @@ -8,6 +8,8 @@ PHP NEWS | |
| . Update the MIME type list from the one shipped by Apache HTTPD. (Adam) | |
| - Core: | |
| + . Implemented the RFC `Catchable "Call to a member function bar() on a | |
| + non-object"` (Timm) | |
| . Added PHP_INT_MIN constant. (Andrea) | |
| . Added Closure::apply() method. (Andrea) | |
| . Implemented FR #38409 (parse_ini_file() looses the type of booleans). (Tjerk) | |
| diff --git a/Zend/tests/dereference_002.phpt b/Zend/tests/dereference_002.phpt | |
| index da13dec..cc0f27d 100644 | |
| --- a/Zend/tests/dereference_002.phpt | |
| +++ b/Zend/tests/dereference_002.phpt | |
| @@ -76,4 +76,4 @@ NULL | |
| Notice: Undefined offset: 3 in %s on line %d | |
| -Fatal error: Call to a member function bar() on null in %s on line %d | |
| +Catchable fatal error: Call to a member function bar() on null in %s on line %d | |
| diff --git a/Zend/tests/methods-on-non-objects-args-catch.phpt b/Zend/tests/methods-on-non-objects-args-catch.phpt | |
| new file mode 100644 | |
| index 0000000..853d2d5 | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-args-catch.phpt | |
| @@ -0,0 +1,18 @@ | |
| +--TEST-- | |
| +Catch method calls on non-objects raise recoverable errors | |
| +--FILE-- | |
| +<?php | |
| +set_error_handler(function($code, $message) { | |
| + var_dump($code, $message); | |
| +}); | |
| + | |
| +$x= null; | |
| +var_dump($x->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 | |
| new file mode 100755 | |
| index 0000000..be87457 | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-array-access.phpt | |
| @@ -0,0 +1,18 @@ | |
| +--TEST-- | |
| +Catch method calls on non-objects inside array access | |
| +--FILE-- | |
| +<?php | |
| +set_error_handler(function($code, $message) { | |
| + var_dump($code, $message); | |
| +}); | |
| + | |
| +$x= null; | |
| +$a= [null => '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 | |
| new file mode 100755 | |
| index 0000000..74cbb9c | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-array-creation.phpt | |
| @@ -0,0 +1,35 @@ | |
| +--TEST-- | |
| +Catch method calls on non-objects inside array creation | |
| +--FILE-- | |
| +<?php | |
| +set_error_handler(function($code, $message) { | |
| + var_dump($code, $message); | |
| +}); | |
| + | |
| +$x= null; | |
| +var_dump([$x->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 | |
| new file mode 100644 | |
| index 0000000..13b83cb | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-as-arg.phpt | |
| @@ -0,0 +1,47 @@ | |
| +--TEST-- | |
| +Catch method calls on non-objects as argument | |
| +--FILE-- | |
| +<?php | |
| +function nesting() { | |
| + return func_get_args(); | |
| +} | |
| +set_error_handler(function($code, $message) { | |
| + static $i= 0; | |
| + echo 'Called #'.(++$i)."\n"; | |
| +}); | |
| + | |
| +$x= null; | |
| +var_dump(nesting($x->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-call-user-func.phpt b/Zend/tests/methods-on-non-objects-call-user-func.phpt | |
| new file mode 100644 | |
| index 0000000..f76b7d4 | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-call-user-func.phpt | |
| @@ -0,0 +1,13 @@ | |
| +--TEST-- | |
| +call_user_func() in combination with "Call to a member function method() on a non-object" | |
| +--FILE-- | |
| +<?php | |
| +$comparator= null; | |
| +var_dump(call_user_func([$comparator, 'compare'], 1, 2)); | |
| +echo "Alive\n"; | |
| +?> | |
| +--EXPECTF-- | |
| +Warning: call_user_func() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in %s on line %d | |
| +NULL | |
| +Alive | |
| + | |
| diff --git a/Zend/tests/methods-on-non-objects-catch.phpt b/Zend/tests/methods-on-non-objects-catch.phpt | |
| new file mode 100644 | |
| index 0000000..bbfadac | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-catch.phpt | |
| @@ -0,0 +1,18 @@ | |
| +--TEST-- | |
| +Catch method calls on non-objects raise recoverable errors | |
| +--FILE-- | |
| +<?php | |
| +set_error_handler(function($code, $message) { | |
| + var_dump($code, $message); | |
| +}); | |
| + | |
| +$x= null; | |
| +var_dump($x->method()); | |
| +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 | |
| new file mode 100644 | |
| index 0000000..30da254 | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-chain.phpt | |
| @@ -0,0 +1,22 @@ | |
| +--TEST-- | |
| +Catch chained method calls on non-objects raise recoverable errors | |
| +--FILE-- | |
| +<?php | |
| +set_error_handler(function($code, $message) { | |
| + var_dump($code, $message); | |
| +}); | |
| + | |
| +$x= null; | |
| +var_dump($x->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 | |
| new file mode 100755 | |
| index 0000000..4ff47aa | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-concat.phpt | |
| @@ -0,0 +1,18 @@ | |
| +--TEST-- | |
| +Catch method calls on non-objects inside concatenation | |
| +--FILE-- | |
| +<?php | |
| +set_error_handler(function($code, $message) { | |
| + var_dump($code, $message); | |
| +}); | |
| + | |
| +$x= null; | |
| +echo "Before\n".$x->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 | |
| new file mode 100644 | |
| index 0000000..11c5c9f | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-dynamic.phpt | |
| @@ -0,0 +1,23 @@ | |
| +--TEST-- | |
| +Catch method calls on non-objects with dynamic lookups | |
| +--FILE-- | |
| +<?php | |
| +set_error_handler(function($code, $message) { | |
| + static $i= 0; | |
| + echo 'Called #'.(++$i)."\n"; | |
| +}); | |
| + | |
| +$arr= [null, 'method']; | |
| +var_dump($arr[0]->{$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 | |
| new file mode 100644 | |
| index 0000000..8ee494c | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-eval.phpt | |
| @@ -0,0 +1,18 @@ | |
| +--TEST-- | |
| +Indirect call inside eval to member function on non-object | |
| +--FILE-- | |
| +<?php | |
| +set_error_handler(function($code, $message) { | |
| + var_dump($code, $message); | |
| +}); | |
| + | |
| +$x= null; | |
| +var_dump(eval('$x->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 | |
| new file mode 100755 | |
| index 0000000..a0267c0 | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-in-echo.phpt | |
| @@ -0,0 +1,18 @@ | |
| +--TEST-- | |
| +Catch method calls on non-objects inside echo | |
| +--FILE-- | |
| +<?php | |
| +set_error_handler(function($code, $message) { | |
| + var_dump($code, $message); | |
| +}); | |
| + | |
| +$x= null; | |
| +echo "Before\n", $x->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 | |
| new file mode 100644 | |
| index 0000000..267104f | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-nested-calls-dyn.phpt | |
| @@ -0,0 +1,37 @@ | |
| +--TEST-- | |
| +Catch method calls on non-objects with nested dynamic calls | |
| +--FILE-- | |
| +<?php | |
| +function nested() { | |
| + throw new LogicException('Should not be called'); | |
| +} | |
| +set_error_handler(function($code, $message) { | |
| + static $i= 0; | |
| + echo 'Called #'.(++$i)."\n"; | |
| +}); | |
| + | |
| +$x= null; | |
| + | |
| +$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'))); | |
| + | |
| +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 | |
| new file mode 100644 | |
| index 0000000..d8e3dd2 | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-nested-calls-new.phpt | |
| @@ -0,0 +1,37 @@ | |
| +--TEST-- | |
| +Catch method calls on non-objects with nested calls to new | |
| +--FILE-- | |
| +<?php | |
| +class Nesting { | |
| +} | |
| +set_error_handler(function($code, $message) { | |
| + static $i= 0; | |
| + echo 'Called #'.(++$i)."\n"; | |
| +}); | |
| + | |
| +$x= null; | |
| +var_dump($x->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 | |
| new file mode 100644 | |
| index 0000000..a4529ee | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-nested-calls-nonct.phpt | |
| @@ -0,0 +1,43 @@ | |
| +--TEST-- | |
| +Catch method calls on non-objects with nested non-compile-time-resolveable calls | |
| +--FILE-- | |
| +<?php | |
| +require('methods-on-non-objects-nested.inc'); | |
| + | |
| +set_error_handler(function($code, $message) { | |
| + static $i= 0; | |
| + echo 'Called #'.(++$i)."\n"; | |
| +}); | |
| + | |
| +$x= null; | |
| + | |
| +var_dump($x->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 | |
| new file mode 100644 | |
| index 0000000..b16f579 | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-nested-calls-ns.phpt | |
| @@ -0,0 +1,26 @@ | |
| +--TEST-- | |
| +Catch method calls on non-objects with nested calls to namespaced functions with core counterparts | |
| +--FILE-- | |
| +<?php namespace test; | |
| +function strlen($str) { | |
| + throw new LogicException('Should not be called'); | |
| +} | |
| +set_error_handler(function($code, $message) { | |
| + static $i= 0; | |
| + echo 'Called #'.(++$i)."\n"; | |
| +}); | |
| + | |
| +$x= null; | |
| +var_dump($x->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 | |
| new file mode 100644 | |
| index 0000000..64972ee | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-nested-calls-static.phpt | |
| @@ -0,0 +1,33 @@ | |
| +--TEST-- | |
| +Catch method calls on non-objects with nested calls to static methods | |
| +--FILE-- | |
| +<?php | |
| +class Nesting { | |
| + static function nested() { | |
| + throw new LogicException('Should not be called'); | |
| + } | |
| +} | |
| +set_error_handler(function($code, $message) { | |
| + static $i= 0; | |
| + echo 'Called #'.(++$i)."\n"; | |
| +}); | |
| + | |
| +$x= null; | |
| +$class= 'Nesting'; | |
| +$method= 'nested'; | |
| +var_dump($x->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 | |
| new file mode 100644 | |
| index 0000000..b25aeaf | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-nested-calls.phpt | |
| @@ -0,0 +1,47 @@ | |
| +--TEST-- | |
| +Catch method calls on non-objects with nested function and method calls | |
| +--FILE-- | |
| +<?php | |
| +function nested() { | |
| + throw new LogicException('Should not be called'); | |
| +} | |
| +set_error_handler(function($code, $message) { | |
| + static $i= 0; | |
| + echo 'Called #'.(++$i)."\n"; | |
| +}); | |
| + | |
| +$x= null; | |
| +var_dump($x->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-nested.inc b/Zend/tests/methods-on-non-objects-nested.inc | |
| new file mode 100644 | |
| index 0000000..8511414 | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-nested.inc | |
| @@ -0,0 +1,4 @@ | |
| +<?php | |
| +function nested() { | |
| + throw new LogicException('Should not be called'); | |
| +} | |
| \ No newline at end of file | |
| diff --git a/Zend/tests/methods-on-non-objects-return-unused.phpt b/Zend/tests/methods-on-non-objects-return-unused.phpt | |
| new file mode 100644 | |
| index 0000000..ab2951f | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-return-unused.phpt | |
| @@ -0,0 +1,17 @@ | |
| +--TEST-- | |
| +Catch method calls on non-objects without using return value | |
| +--INI-- | |
| +report_memleaks=1 | |
| +--FILE-- | |
| +<?php | |
| +set_error_handler(function($code, $message) { | |
| + echo "Caught\n"; | |
| +}); | |
| + | |
| +$x= null; | |
| +$x->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 | |
| new file mode 100644 | |
| index 0000000..874f57c | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-throw.phpt | |
| @@ -0,0 +1,29 @@ | |
| +--TEST-- | |
| +Convert errors to exceptions from method calls on non-objects raise recoverable errors | |
| +--FILE-- | |
| +<?php | |
| +set_error_handler(function($code, $message) { | |
| + echo "Raising...\n"; | |
| + if (0 === strncmp('Call', $message, 4)) { | |
| + throw new BadMethodCallException($message); | |
| + } else if (0 === strncmp('Argument', $message, 8)) { | |
| + throw new InvalidArgumentException($message); | |
| + } else { | |
| + trigger_error($message, E_USER_ERROR); | |
| + } | |
| +}, E_RECOVERABLE_ERROR); | |
| + | |
| +$x= null; | |
| +echo "Calling...\n"; | |
| +try { | |
| + $x->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 | |
| new file mode 100644 | |
| index 0000000..760d481 | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects-usort.phpt | |
| @@ -0,0 +1,43 @@ | |
| +--TEST-- | |
| +usort() in combination with "Call to a member function method() on null" | |
| +--FILE-- | |
| +<?php | |
| +set_error_handler(function($code, $message) { | |
| + var_dump($code, $message); | |
| +}); | |
| + | |
| +$comparator= null; | |
| +$list= [1, 4, 2, 3, -1]; | |
| +usort($list, function($a, $b) use ($comparator) { | |
| + return $comparator->compare($a, $b); | |
| +}); | |
| +var_dump($list); | |
| +echo "Alive\n"; | |
| +?> | |
| +--EXPECTF-- | |
| +int(4096) | |
| +string(43) "Call to a member function compare() on null" | |
| +int(4096) | |
| +string(43) "Call to a member function compare() on null" | |
| +int(4096) | |
| +string(43) "Call to a member function compare() on null" | |
| +int(4096) | |
| +string(43) "Call to a member function compare() on null" | |
| +int(4096) | |
| +string(43) "Call to a member function compare() on null" | |
| +int(4096) | |
| +string(43) "Call to a member function compare() on null" | |
| +array(5) { | |
| + [0]=> | |
| + int(-1) | |
| + [1]=> | |
| + int(3) | |
| + [2]=> | |
| + int(2) | |
| + [3]=> | |
| + int(4) | |
| + [4]=> | |
| + int(1) | |
| +} | |
| +Alive | |
| + | |
| diff --git a/Zend/tests/methods-on-non-objects.phpt b/Zend/tests/methods-on-non-objects.phpt | |
| new file mode 100644 | |
| index 0000000..01031b8 | |
| --- /dev/null | |
| +++ b/Zend/tests/methods-on-non-objects.phpt | |
| @@ -0,0 +1,12 @@ | |
| +--TEST-- | |
| +Method calls on non-objects raise recoverable errors | |
| +--FILE-- | |
| +<?php | |
| + | |
| +$x= null; | |
| +$x->method(); | |
| +echo "Should not get here!\n"; | |
| +?> | |
| +--EXPECTF-- | |
| + | |
| +Catchable fatal error: Call to a member function method() on null in %s on line %d | |
| diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h | |
| index 6122429..fd0e11d 100644 | |
| --- a/Zend/zend_vm_def.h | |
| +++ b/Zend/zend_vm_def.h | |
| @@ -2139,11 +2139,48 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) | |
| object = GET_OP1_OBJ_ZVAL_PTR_DEREF(BP_VAR_R); | |
| if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
| + uint32_t nesting = 1; | |
| + | |
| if (UNEXPECTED(EG(exception) != NULL)) { | |
| FREE_OP2(); | |
| HANDLE_EXCEPTION(); | |
| } | |
| - zend_error_noreturn(E_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))); | |
| + FREE_OP2(); | |
| + FREE_OP1_IF_VAR(); | |
| + | |
| + 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_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) { | |
| + 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); | |
| } | |
| obj = Z_OBJ_P(object); | |
| diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h | |
| index 54d2bb2..d932701 100644 | |
| --- a/Zend/zend_vm_execute.h | |
| +++ b/Zend/zend_vm_execute.h | |
| @@ -11003,11 +11003,47 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO | |
| object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); | |
| if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
| + uint32_t nesting = 1; | |
| + | |
| if (UNEXPECTED(EG(exception) != NULL)) { | |
| HANDLE_EXCEPTION(); | |
| } | |
| - zend_error_noreturn(E_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_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) { | |
| + 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); | |
| } | |
| obj = Z_OBJ_P(object); | |
| @@ -12135,11 +12171,47 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE | |
| object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); | |
| if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
| + uint32_t nesting = 1; | |
| + | |
| if (UNEXPECTED(EG(exception) != NULL)) { | |
| zval_ptr_dtor_nogc(free_op2.var); | |
| HANDLE_EXCEPTION(); | |
| } | |
| - zend_error_noreturn(E_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))); | |
| + zval_ptr_dtor_nogc(free_op2.var); | |
| + | |
| + 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_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) { | |
| + 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); | |
| } | |
| obj = Z_OBJ_P(object); | |
| @@ -13266,11 +13338,47 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE | |
| object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); | |
| if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
| + uint32_t nesting = 1; | |
| + | |
| if (UNEXPECTED(EG(exception) != NULL)) { | |
| zval_ptr_dtor_nogc(free_op2.var); | |
| HANDLE_EXCEPTION(); | |
| } | |
| - zend_error_noreturn(E_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))); | |
| + zval_ptr_dtor_nogc(free_op2.var); | |
| + | |
| + 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_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) { | |
| + 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); | |
| } | |
| obj = Z_OBJ_P(object); | |
| @@ -14990,11 +15098,47 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_ | |
| object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); | |
| if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
| + uint32_t nesting = 1; | |
| + | |
| if (UNEXPECTED(EG(exception) != NULL)) { | |
| HANDLE_EXCEPTION(); | |
| } | |
| - zend_error_noreturn(E_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_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) { | |
| + 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); | |
| } | |
| obj = Z_OBJ_P(object); | |
| @@ -18568,11 +18712,48 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO | |
| object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); | |
| if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
| + uint32_t nesting = 1; | |
| + | |
| if (UNEXPECTED(EG(exception) != NULL)) { | |
| HANDLE_EXCEPTION(); | |
| } | |
| - zend_error_noreturn(E_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))); | |
| + | |
| + zval_ptr_dtor_nogc(free_op1.var); | |
| + | |
| + 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_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) { | |
| + 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); | |
| } | |
| obj = Z_OBJ_P(object); | |
| @@ -20790,11 +20971,48 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE | |
| object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); | |
| if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
| + uint32_t nesting = 1; | |
| + | |
| if (UNEXPECTED(EG(exception) != NULL)) { | |
| zval_ptr_dtor_nogc(free_op2.var); | |
| HANDLE_EXCEPTION(); | |
| } | |
| - zend_error_noreturn(E_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))); | |
| + zval_ptr_dtor_nogc(free_op2.var); | |
| + zval_ptr_dtor_nogc(free_op1.var); | |
| + | |
| + 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_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) { | |
| + 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); | |
| } | |
| obj = Z_OBJ_P(object); | |
| @@ -22979,11 +23197,48 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE | |
| object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); | |
| if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
| + uint32_t nesting = 1; | |
| + | |
| if (UNEXPECTED(EG(exception) != NULL)) { | |
| zval_ptr_dtor_nogc(free_op2.var); | |
| HANDLE_EXCEPTION(); | |
| } | |
| - zend_error_noreturn(E_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))); | |
| + zval_ptr_dtor_nogc(free_op2.var); | |
| + zval_ptr_dtor_nogc(free_op1.var); | |
| + | |
| + 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_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) { | |
| + 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); | |
| } | |
| obj = Z_OBJ_P(object); | |
| @@ -26364,11 +26619,48 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_ | |
| object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); | |
| if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
| + uint32_t nesting = 1; | |
| + | |
| if (UNEXPECTED(EG(exception) != NULL)) { | |
| HANDLE_EXCEPTION(); | |
| } | |
| - zend_error_noreturn(E_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))); | |
| + | |
| + zval_ptr_dtor_nogc(free_op1.var); | |
| + | |
| + 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_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) { | |
| + 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); | |
| } | |
| obj = Z_OBJ_P(object); | |
| @@ -27945,11 +28237,47 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O | |
| object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); | |
| if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
| + uint32_t nesting = 1; | |
| + | |
| if (UNEXPECTED(EG(exception) != NULL)) { | |
| HANDLE_EXCEPTION(); | |
| } | |
| - zend_error_noreturn(E_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_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) { | |
| + 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); | |
| } | |
| obj = Z_OBJ_P(object); | |
| @@ -29308,11 +29636,47 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC | |
| object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); | |
| if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
| + uint32_t nesting = 1; | |
| + | |
| if (UNEXPECTED(EG(exception) != NULL)) { | |
| zval_ptr_dtor_nogc(free_op2.var); | |
| HANDLE_EXCEPTION(); | |
| } | |
| - zend_error_noreturn(E_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))); | |
| + zval_ptr_dtor_nogc(free_op2.var); | |
| + | |
| + 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_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) { | |
| + 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); | |
| } | |
| obj = Z_OBJ_P(object); | |
| @@ -30578,11 +30942,47 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC | |
| object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); | |
| if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
| + uint32_t nesting = 1; | |
| + | |
| if (UNEXPECTED(EG(exception) != NULL)) { | |
| zval_ptr_dtor_nogc(free_op2.var); | |
| HANDLE_EXCEPTION(); | |
| } | |
| - zend_error_noreturn(E_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))); | |
| + zval_ptr_dtor_nogc(free_op2.var); | |
| + | |
| + 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_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) { | |
| + 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); | |
| } | |
| obj = Z_OBJ_P(object); | |
| @@ -32358,11 +32758,47 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO | |
| object = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC); | |
| if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
| + uint32_t nesting = 1; | |
| + | |
| if (UNEXPECTED(EG(exception) != NULL)) { | |
| HANDLE_EXCEPTION(); | |
| } | |
| - zend_error_noreturn(E_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_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) { | |
| + 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); | |
| } | |
| obj = Z_OBJ_P(object); | |
| @@ -35674,11 +36110,47 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD | |
| object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); | |
| if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
| + uint32_t nesting = 1; | |
| + | |
| if (UNEXPECTED(EG(exception) != NULL)) { | |
| HANDLE_EXCEPTION(); | |
| } | |
| - zend_error_noreturn(E_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_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) { | |
| + 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); | |
| } | |
| obj = Z_OBJ_P(object); | |
| @@ -37729,11 +38201,47 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_ | |
| object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); | |
| if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
| + uint32_t nesting = 1; | |
| + | |
| if (UNEXPECTED(EG(exception) != NULL)) { | |
| zval_ptr_dtor_nogc(free_op2.var); | |
| HANDLE_EXCEPTION(); | |
| } | |
| - zend_error_noreturn(E_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))); | |
| + zval_ptr_dtor_nogc(free_op2.var); | |
| + | |
| + 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_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) { | |
| + 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); | |
| } | |
| obj = Z_OBJ_P(object); | |
| @@ -39789,11 +40297,47 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_ | |
| object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); | |
| if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
| + uint32_t nesting = 1; | |
| + | |
| if (UNEXPECTED(EG(exception) != NULL)) { | |
| zval_ptr_dtor_nogc(free_op2.var); | |
| HANDLE_EXCEPTION(); | |
| } | |
| - zend_error_noreturn(E_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))); | |
| + zval_ptr_dtor_nogc(free_op2.var); | |
| + | |
| + 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_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) { | |
| + 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); | |
| } | |
| obj = Z_OBJ_P(object); | |
| @@ -42900,11 +43444,47 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H | |
| object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); | |
| if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
| + uint32_t nesting = 1; | |
| + | |
| if (UNEXPECTED(EG(exception) != NULL)) { | |
| HANDLE_EXCEPTION(); | |
| } | |
| - zend_error_noreturn(E_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_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) { | |
| + 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); | |
| } | |
| obj = Z_OBJ_P(object); | |
| diff --git a/ext/mysqli/tests/bug33491.phpt b/ext/mysqli/tests/bug33491.phpt | |
| index 7e994bc..c83e126 100644 | |
| --- a/ext/mysqli/tests/bug33491.phpt | |
| +++ b/ext/mysqli/tests/bug33491.phpt | |
| @@ -1,7 +1,7 @@ | |
| --TEST-- | |
| Bug #33491 (extended mysqli class crashes when result is not object) | |
| --INI-- | |
| -error_reporting=4095 | |
| +error_reporting=4096 | |
| --SKIPIF-- | |
| <?php | |
| require_once('skipif.inc'); | |
| @@ -26,4 +26,4 @@ $DB->query_single('SELECT DATE()'); | |
| ?> | |
| --EXPECTF-- | |
| -Fatal error: Call to a member function fetch_row() on boolean in %sbug33491.php on line %d | |
| +Catchable fatal error: Call to a member function fetch_row() on boolean in %sbug33491.php on line %d | |
| diff --git a/ext/mysqli/tests/mysqli_change_user_new.phpt b/ext/mysqli/tests/mysqli_change_user_new.phpt | |
| index e168957..06c721ac 100644 | |
| --- a/ext/mysqli/tests/mysqli_change_user_new.phpt | |
| +++ b/ext/mysqli/tests/mysqli_change_user_new.phpt | |
| @@ -41,4 +41,4 @@ Warning: mysqli_query(): MySQL server has gone away in %s on line %d | |
| Warning: mysqli_query(): Error reading result set's header in %s on line %d | |
| [003] [2006] MySQL server has gone away | |
| -Fatal error: Call to a member function fetch_assoc() on %s in %s on line %d | |
| \ No newline at end of file | |
| +Catchable fatal error: Call to a member function fetch_assoc() on %s in %s on line %d | |
| diff --git a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_clear_error.phpt b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_clear_error.phpt | |
| index 224684b..0beca90 100644 | |
| --- a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_clear_error.phpt | |
| +++ b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_clear_error.phpt | |
| @@ -93,4 +93,4 @@ array(1) { | |
| Warning: PDO::prepare(): SQLSTATE[42S22]: Column not found: 1054 Unknown column 'unknown_column' in 'field list' in %s on line %d | |
| -Fatal error: Call to a member function execute() on boolean in %s on line %d | |
| +Catchable fatal error: Call to a member function execute() on boolean in %s on line %d | |
| diff --git a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_mixed_style.phpt b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_mixed_style.phpt | |
| index b7b0ab6..fc55547 100644 | |
| --- a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_mixed_style.phpt | |
| +++ b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_mixed_style.phpt | |
| @@ -36,4 +36,4 @@ Warning: PDO::prepare(): SQLSTATE[HY093]: Invalid parameter number: mixed named | |
| Warning: PDO::prepare(): SQLSTATE[HY093]: Invalid parameter number in %s on line %d | |
| -Fatal error: Call to a member function execute() on boolean in %s on line %d | |
| +Catchable fatal error: Call to a member function execute() on boolean in %s on line %d | |
| diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_errorcode.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_errorcode.phpt | |
| index c16ce5d..36295e9 100644 | |
| --- a/ext/pdo_mysql/tests/pdo_mysql_stmt_errorcode.phpt | |
| +++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_errorcode.phpt | |
| @@ -56,4 +56,4 @@ Testing native PS... | |
| Warning: PDO::prepare(): SQLSTATE[42S02]: Base table or view not found: 1146 Table '%s.ihopeitdoesnotexist' doesn't exist in %s on line %d | |
| -Fatal error: Call to a member function execute() on boolean in %s on line %d | |
| +Catchable fatal error: Call to a member function execute() on boolean in %s on line %d | |
| diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_multiquery.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_multiquery.phpt | |
| index 52ecc91..278cd4e 100644 | |
| --- a/ext/pdo_mysql/tests/pdo_mysql_stmt_multiquery.phpt | |
| +++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_multiquery.phpt | |
| @@ -99,4 +99,4 @@ Native Prepared Statements... | |
| Warning: PDO::query(): SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your %s server version for the right syntax to use near '%SSELECT label FROM test ORDER BY id ASC LIMIT 1' at line %d in %s on line %d | |
| -Fatal error: Call to a member function errorInfo() on boolean in %s on line %d | |
| +Catchable fatal error: Call to a member function errorInfo() on boolean in %s on line %d | |
| \ No newline at end of file |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Commit message