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.
This commit is contained in:
Dmitry Stogov 2015-03-09 13:57:15 +01:00 committed by Nikita Popov
parent 2f156c61f1
commit 1c94ff0595
69 changed files with 2953 additions and 2188 deletions

View file

@ -34,7 +34,7 @@ $test->bar();
object(Exception)#%d (7) { object(Exception)#%d (7) {
["message":protected]=> ["message":protected]=>
string(3) "foo" string(3) "foo"
["string":"Exception":private]=> ["string":"BaseException":private]=>
string(0) "" string(0) ""
["code":protected]=> ["code":protected]=>
int(0) int(0)
@ -42,7 +42,7 @@ object(Exception)#%d (7) {
string(%d) "%s030.php" string(%d) "%s030.php"
["line":protected]=> ["line":protected]=>
int(%d) int(%d)
["trace":"Exception":private]=> ["trace":"BaseException":private]=>
array(1) { array(1) {
[0]=> [0]=>
array(6) { array(6) {
@ -61,7 +61,7 @@ object(Exception)#%d (7) {
} }
} }
} }
["previous":"Exception":private]=> ["previous":"BaseException":private]=>
NULL NULL
} }
'test' => '0' 'test' => '0'

View file

@ -7,14 +7,18 @@ set_error_handler(function($errno, $errstr) {
var_dump($errstr); var_dump($errstr);
}); });
var_dump(...[1, 2, "foo" => 3, 4]); try {
var_dump(...new ArrayIterator([1, 2, "foo" => 3, 4])); 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-- --EXPECTF--
string(36) "Cannot unpack array with string keys" string(36) "Cannot unpack array with string keys"
int(1)
int(2)
string(42) "Cannot unpack Traversable with string keys" string(42) "Cannot unpack Traversable with string keys"
int(1)
int(2)

View file

@ -2,18 +2,16 @@
Bug #37251 (deadlock when custom error handler is to catch array type hint error) Bug #37251 (deadlock when custom error handler is to catch array type hint error)
--FILE-- --FILE--
<?php <?php
function error_handler($errno, $errstr, $errfile, $errline, $context) {
echo 'OK';
}
set_error_handler('error_handler');
class Foo { class Foo {
function bar(array $foo) { function bar(array $foo) {
} }
} }
$foo = new Foo(); try {
$foo->bar(); $foo = new Foo();
$foo->bar();
} catch (EngineException $e) {
echo 'OK';
}
--EXPECT-- --EXPECT--
OK OK

View file

@ -3,26 +3,43 @@ Bug #48693 (Double declaration of __lambda_func when lambda wrongly formatted)
--FILE-- --FILE--
<?php <?php
$x = create_function('', 'return 1; }'); try {
$y = create_function('', 'function a() { }; return 2;'); $x = create_function('', 'return 1; }');
$z = create_function('', '{'); } catch (ParseException $e) {
$w = create_function('', 'return 3;'); echo "$e\n\n";
}
try {
$y = create_function('', 'function a() { }; return 2;');
} catch (ParseException $e) {
echo "$e\n\n";
}
try {
$z = create_function('', '{');
} catch (ParseException $e) {
echo "$e\n\n";
}
try {
$w = create_function('', 'return 3;');
} catch (ParseException $e) {
echo "$e\n\n";
}
var_dump( var_dump(
$x,
$y(), $y(),
$z, $w()
$w(),
$y != $z
); );
?> ?>
--EXPECTF-- --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) int(2)
bool(false)
int(3) int(3)
bool(true)

View file

@ -10,7 +10,7 @@ function exception_error_handler() {
set_error_handler("exception_error_handler"); set_error_handler("exception_error_handler");
try { try {
$undefined->undefined(); $undefined->undefined();
} catch(Exception $e) { } catch(BaseException $e) {
echo "Exception is thrown"; echo "Exception is thrown";
} }
--EXPECT-- --EXPECT--

View file

@ -2,11 +2,12 @@
Bug #64966 (segfault in zend_do_fcall_common_helper_SPEC) Bug #64966 (segfault in zend_do_fcall_common_helper_SPEC)
--FILE-- --FILE--
<?php <?php
error_reporting(E_ALL);
set_error_handler(function($error) { throw new Exception(); }, E_RECOVERABLE_ERROR);
function test($func) { function test($func) {
$a = $func(""); try {
$a = $func("");
} catch (EngineException $e) {
throw new Exception();
}
return true; return true;
} }
class A { class A {
@ -20,11 +21,9 @@ $a = new A();
$a->b(); $a->b();
?> ?>
--EXPECTF-- --EXPECTF--
Fatal error: Uncaught exception 'Exception' in %sbug64966.php:3 Fatal error: Uncaught exception 'Exception' in %sbug64966.php:6
Stack trace: Stack trace:
#0 [internal function]: {closure}(4096, 'Argument 1 pass...', '%s', 6, Array) #0 %sbug64966.php(13): test('iterator_apply')
#1 %sbug64966.php(6): iterator_apply('') #1 %sbug64966.php(18): A->b()
#2 %sbug64966.php(12): test('iterator_apply') #2 {main}
#3 %sbug64966.php(17): A->b() thrown in %sbug64966.php on line 6
#4 {main}
thrown in %sbug64966.php on line 3

View file

@ -8,9 +8,12 @@ function foo($errno, $errstr, $errfile, $errline) {
set_error_handler('foo'); set_error_handler('foo');
$foo = function() { $foo = function() {
}; };
var_dump($foo->a); try {
var_dump($foo->a);
} catch (EngineException $ex) {
echo "Error: {$ex->getMessage()}\n";
}
?> ?>
--EXPECT-- --EXPECT--
Error: Closure object cannot have properties Error: Closure object cannot have properties
NULL

View file

@ -15,16 +15,16 @@ $x->getcode(1);
?> ?>
--EXPECTF-- --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

View file

@ -10,38 +10,38 @@ set_error_handler("exception_error_handler");
try { try {
$foo->a(); $foo->a();
} catch(Exception $e) { } catch(BaseException $e) {
var_dump($e->getMessage()); var_dump($e->getMessage());
} }
try { try {
new $foo(); new $foo();
} catch(Exception $e) { } catch(BaseException $e) {
var_dump($e->getMessage()); var_dump($e->getMessage());
} }
try { try {
throw $foo; throw $foo;
} catch(Exception $e) { } catch(BaseException $e) {
var_dump($e->getMessage()); var_dump($e->getMessage());
} }
try { try {
$foo(); $foo();
} catch(Exception $e) { } catch(BaseException $e) {
var_dump($e->getMessage()); var_dump($e->getMessage());
} }
try { try {
$foo::b(); $foo::b();
} catch(Exception $e) { } catch(BaseException $e) {
var_dump($e->getMessage()); var_dump($e->getMessage());
} }
try { try {
$b = clone $foo; $b = clone $foo;
} catch(Exception $e) { } catch(BaseException $e) {
var_dump($e->getMessage()); var_dump($e->getMessage());
} }
@ -50,7 +50,7 @@ class b {
try { try {
b::$foo(); b::$foo();
} catch(Exception $e) { } catch(BaseException $e) {
var_dump($e->getMessage()); var_dump($e->getMessage());
} }
?> ?>

View file

@ -8,7 +8,10 @@ function gen() {
yield $a; yield $a;
} }
@eval('abc'); try {
eval('abc');
} catch (ParseException $ex) {
}
$values = gen(); $values = gen();
$values->next(); $values->next();

View file

@ -1,18 +0,0 @@
--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

View file

@ -1,18 +0,0 @@
--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

View file

@ -1,35 +0,0 @@
--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

View file

@ -1,47 +0,0 @@
--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

View file

@ -7,12 +7,15 @@ set_error_handler(function($code, $message) {
}); });
$x= null; $x= null;
var_dump($x->method()); try {
var_dump($x->method());
} catch (EngineException $e) {
var_dump($e->getCode(), $e->getMessage());
}
echo "Alive\n"; echo "Alive\n";
?> ?>
--EXPECTF-- --EXPECTF--
int(4096) int(4096)
string(%d) "Call to a member function method() on null" string(%d) "Call to a member function method() on null"
NULL
Alive Alive

View file

@ -1,22 +0,0 @@
--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

View file

@ -1,18 +0,0 @@
--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

View file

@ -1,23 +0,0 @@
--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

View file

@ -1,18 +0,0 @@
--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

View file

@ -1,18 +0,0 @@
--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

View file

@ -1,37 +0,0 @@
--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

View file

@ -1,37 +0,0 @@
--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

View file

@ -1,43 +0,0 @@
--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

View file

@ -1,26 +0,0 @@
--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

View file

@ -1,33 +0,0 @@
--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

View file

@ -1,47 +0,0 @@
--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

View file

@ -1,17 +0,0 @@
--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

View file

@ -1,29 +0,0 @@
--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

View file

@ -9,7 +9,12 @@ set_error_handler(function($code, $message) {
$comparator= null; $comparator= null;
$list= [1, 4, 2, 3, -1]; $list= [1, 4, 2, 3, -1];
usort($list, function($a, $b) use ($comparator) { 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); var_dump($list);
echo "Alive\n"; echo "Alive\n";

View file

@ -7,27 +7,12 @@ function test(array... $args) {
var_dump($args); var_dump($args);
} }
set_error_handler(function($errno, $errstr) { try {
var_dump($errstr); test([0], [1], 2);
return true; } catch(EngineException $e) {
}); var_dump($e->getMessage());
}
test([0], [1], 2);
?> ?>
--EXPECTF-- --EXPECTF--
string(%d) "Argument 3 passed to test() must be of the type array, integer given, called in %s on line %d and defined" 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)
}

View file

@ -842,7 +842,7 @@ void zend_set_utility_values(zend_utility_values *utility_values) /* {{{ */
/* this should be compatible with the standard zenderror */ /* this should be compatible with the standard zenderror */
void zenderror(const char *error) /* {{{ */ 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_stack context_stack;
zend_array *symbol_table; 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 */ /* Report about uncaught exception in case of fatal errors */
if (EG(exception)) { if (EG(exception)) {
zend_execute_data *ex; zend_execute_data *ex;

View file

@ -32,7 +32,7 @@
#define ZEND_CLOSURE_PRINT_NAME "Closure object" #define ZEND_CLOSURE_PRINT_NAME "Closure object"
#define ZEND_CLOSURE_PROPERTY_ERROR() \ #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 { typedef struct _zend_closure {
zend_object std; zend_object std;
@ -53,7 +53,7 @@ ZEND_METHOD(Closure, __invoke) /* {{{ */
arguments = emalloc(sizeof(zval) * ZEND_NUM_ARGS()); arguments = emalloc(sizeof(zval) * ZEND_NUM_ARGS());
if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), arguments) == FAILURE) { if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), arguments) == FAILURE) {
efree(arguments); 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; RETVAL_FALSE;
} else if (call_user_function_ex(CG(function_table), NULL, getThis(), return_value, ZEND_NUM_ARGS(), arguments, 1, NULL) == FAILURE) { } else if (call_user_function_ex(CG(function_table), NULL, getThis(), return_value, ZEND_NUM_ARGS(), arguments, 1, NULL) == FAILURE) {
RETVAL_FALSE; RETVAL_FALSE;
@ -168,7 +168,7 @@ ZEND_METHOD(Closure, bind)
static zend_function *zend_closure_get_constructor(zend_object *object) /* {{{ */ 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; return NULL;
} }
/* }}} */ /* }}} */
@ -418,7 +418,7 @@ static HashTable *zend_closure_get_gc(zval *obj, zval **table, int *n) /* {{{ */
Private constructor preventing instantiation */ Private constructor preventing instantiation */
ZEND_METHOD(Closure, __construct) 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");
} }
/* }}} */ /* }}} */

View file

@ -38,6 +38,8 @@
#define E_DEPRECATED (1<<13L) #define E_DEPRECATED (1<<13L)
#define E_USER_DEPRECATED (1<<14L) #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_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) #define E_CORE (E_CORE_ERROR | E_CORE_WARNING)

View file

@ -30,8 +30,11 @@
#include "zend_dtrace.h" #include "zend_dtrace.h"
#include "zend_smart_str.h" #include "zend_smart_str.h"
static zend_class_entry *base_exception_ce;
static zend_class_entry *default_exception_ce; static zend_class_entry *default_exception_ce;
static zend_class_entry *error_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; static zend_object_handlers default_exception_handlers;
ZEND_API void (*zend_throw_exception_hook)(zval *ex); 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; return;
} }
ZVAL_OBJ(&tmp, add_previous); 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"); zend_error(E_ERROR, "Cannot set non exception as previous exception");
return; return;
} }
ZVAL_OBJ(&zv, exception); ZVAL_OBJ(&zv, exception);
pzv = &zv; pzv = &zv;
do { 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) { 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)--; GC_REFCOUNT(add_previous)--;
return; return;
} }
@ -106,6 +109,9 @@ ZEND_API void zend_throw_exception_internal(zval *exception) /* {{{ */
} }
} }
if (!EG(current_execute_data)) { if (!EG(current_execute_data)) {
if (exception && Z_OBJCE_P(exception) == parse_exception_ce) {
return;
}
if(EG(exception)) { if(EG(exception)) {
zend_exception_error(EG(exception), E_ERROR); 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); 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); Z_SET_REFCOUNT(trace, 0);
zend_update_property_string(default_exception_ce, &obj, "file", sizeof("file")-1, zend_get_executed_filename()); if (EXPECTED(class_type != parse_exception_ce)) {
zend_update_property_long(default_exception_ce, &obj, "line", sizeof("line")-1, zend_get_executed_lineno()); zend_update_property_string(base_exception_ce, &obj, "file", sizeof("file")-1, zend_get_executed_filename());
zend_update_property(default_exception_ce, &obj, "trace", sizeof("trace")-1, &trace); 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; return object;
} }
@ -198,22 +213,22 @@ ZEND_METHOD(exception, __construct)
zval *object, *previous = NULL; zval *object, *previous = NULL;
int argc = ZEND_NUM_ARGS(); 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]]])"); zend_error(E_ERROR, "Wrong parameters for Exception([string $exception [, long $code [, Exception $previous = NULL]]])");
} }
object = getThis(); object = getThis();
if (message) { 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) { 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) { 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(); int argc = ZEND_NUM_ARGS();
size_t message_len, filename_len; 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]]]]]])"); zend_error(E_ERROR, "Wrong parameters for ErrorException([string $exception [, long $code, [ long $severity, [ string $filename, [ long $lineno [, Exception $previous = NULL]]]]]])");
} }
object = getThis(); object = getThis();
if (message) { 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) { 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) { 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) { 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) { if (argc < 5) {
lineno = 0; /* invalidate lineno */ 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) \ #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) \ #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() /* {{{ proto string Exception::getFile()
Get the file in which the exception occurred */ Get the file in which the exception occurred */
@ -538,7 +553,7 @@ ZEND_METHOD(exception, getTraceAsString)
DEFAULT_0_PARAMS; 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) { ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(trace), index, frame) {
if (Z_TYPE_P(frame) != IS_ARRAY) { if (Z_TYPE_P(frame) != IS_ARRAY) {
zend_error(E_WARNING, "Expected array for frame %pu", index); 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 /* We store the result in the private property string so we can access
* the result in uncaught exception handlers without memleaks. */ * 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); RETURN_STR(str);
} }
@ -711,25 +726,64 @@ static const zend_function_entry error_exception_functions[] = {
void zend_register_default_exception(void) /* {{{ */ void zend_register_default_exception(void) /* {{{ */
{ {
zend_class_entry ce; zend_class_entry ce;
zend_property_info *prop;
INIT_CLASS_ENTRY(ce, "Exception", default_exception_functions); INIT_CLASS_ENTRY(ce, "BaseException", default_exception_functions);
default_exception_ce = zend_register_internal_class(&ce); base_exception_ce = zend_register_internal_class(&ce);
default_exception_ce->create_object = zend_default_exception_new; 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)); memcpy(&default_exception_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
default_exception_handlers.clone_obj = NULL; default_exception_handlers.clone_obj = NULL;
zend_declare_property_string(default_exception_ce, "message", sizeof("message")-1, "", ZEND_ACC_PROTECTED); zend_declare_property_string(base_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_string(base_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_long(base_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(base_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(base_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(base_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_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); INIT_CLASS_ENTRY(ce, "ErrorException", error_exception_functions);
error_exception_ce = zend_register_internal_class_ex(&ce, default_exception_ce); error_exception_ce = zend_register_internal_class_ex(&ce, default_exception_ce);
error_exception_ce->create_object = zend_error_exception_new; 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); 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) /* {{{ */ ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const char *message, zend_long code) /* {{{ */
{ {
zval ex; zval ex;
if (exception_ce) { 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"); zend_error(E_NOTICE, "Exceptions must be derived from the Exception base class");
exception_ce = default_exception_ce; exception_ce = default_exception_ce;
} }
@ -761,10 +828,10 @@ ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const
if (message) { 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) { 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); zend_throw_exception_internal(&ex);
@ -792,7 +859,7 @@ ZEND_API zend_object *zend_throw_error_exception(zend_class_entry *exception_ce,
zval ex; zval ex;
zend_object *obj = zend_throw_exception(exception_ce, message, code); zend_object *obj = zend_throw_exception(exception_ce, message, code);
ZVAL_OBJ(&ex, obj); 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; 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 */ /* This function doesn't return if it uses E_ERROR */
ZEND_API void zend_exception_error(zend_object *ex, int severity) /* {{{ */ ZEND_API void zend_exception_error(zend_object *ex, int severity) /* {{{ */
{ {
zval exception; zval exception, rv;
zend_class_entry *ce_exception; zend_class_entry *ce_exception;
ZVAL_OBJ(&exception, ex); ZVAL_OBJ(&exception, ex);
ce_exception = Z_OBJCE(exception); 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; zval tmp, rv;
zend_string *str, *file = NULL; zend_string *str, *file = NULL;
zend_long line = 0; zend_long line = 0;
EG(exception) = NULL;
zend_call_method_with_0_params(&exception, ce_exception, NULL, "__tostring", &tmp); zend_call_method_with_0_params(&exception, ce_exception, NULL, "__tostring", &tmp);
if (!EG(exception)) { if (!EG(exception)) {
if (Z_TYPE(tmp) != IS_STRING) { if (Z_TYPE(tmp) != IS_STRING) {
zend_error(E_WARNING, "%s::__toString() must return a string", ce_exception->name->val); zend_error(E_WARNING, "%s::__toString() must return a string", ce_exception->name->val);
} else { } 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); zval_ptr_dtor(&tmp);
@ -837,7 +922,7 @@ ZEND_API void zend_exception_error(zend_object *ex, int severity) /* {{{ */
ZVAL_OBJ(&zv, EG(exception)); ZVAL_OBJ(&zv, EG(exception));
/* do the best we can to inform about the inner 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")); file = zval_get_string(GET_PROPERTY_SILENT(&zv, "file"));
line = zval_get_long(GET_PROPERTY_SILENT(&zv, "line")); 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); 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_error(E_ERROR, "Exceptions must be valid objects derived from the Exception base class");
} }
zend_throw_exception_internal(exception); zend_throw_exception_internal(exception);

View file

@ -34,8 +34,11 @@ ZEND_API void zend_throw_exception_internal(zval *exception);
void zend_register_default_exception(void); 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_exception_get_default(void);
ZEND_API zend_class_entry *zend_get_error_exception(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); ZEND_API void zend_register_default_classes(void);
/* exception_ce NULL or zend_exception_get_default() or a derived class /* exception_ce NULL or zend_exception_get_default() or a derived class

View file

@ -103,6 +103,11 @@ static const zend_internal_function zend_pass_function = {
zval_ptr_dtor_nogc(should_free); \ 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) \ #define FREE_OP_VAR_PTR(should_free) \
if (should_free) { \ if (should_free) { \
zval_ptr_dtor_nogc(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) { 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); 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)) { 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) { } 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); 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) { } else if (cur_arg_info->type_hint) {
if (cur_arg_info->type_hint == IS_ARRAY) { if (cur_arg_info->type_hint == IS_ARRAY) {
ZVAL_DEREF(arg); ZVAL_DEREF(arg);
if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) { 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) { } 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)) { 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 #if ZEND_DEBUG
} else { } 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) { if (Z_TYPE_P(arg) == IS_OBJECT) {
need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce); need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce);
if (!ce || !instanceof_function(Z_OBJCE_P(arg), 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)))) { } 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); 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) { } else if (cur_arg_info->type_hint) {
if (cur_arg_info->type_hint == IS_ARRAY) { if (cur_arg_info->type_hint == IS_ARRAY) {
ZVAL_DEREF(arg); 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))))) { 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) { } 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))))) { 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 #if ZEND_DEBUG
} else { } else {
@ -718,13 +723,13 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_n
char *class_name; char *class_name;
need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce); 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; return 0;
} else if (cur_arg_info->type_hint) { } else if (cur_arg_info->type_hint) {
if (cur_arg_info->type_hint == IS_ARRAY) { 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) { } 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 #if ZEND_DEBUG
} else { } else {
zend_error(E_ERROR, "Unknown typehint"); 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) { if (Z_TYPE_P(ret) == IS_OBJECT) {
need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce); need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce);
if (!ce || !instanceof_function(Z_OBJCE_P(ret), 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) { } else if (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null) {
need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce); 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) { } else if (ret_info->type_hint) {
if (ret_info->type_hint == IS_ARRAY) { if (ret_info->type_hint == IS_ARRAY) {
if (Z_TYPE_P(ret) != IS_ARRAY && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) { 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) { } 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)) { 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 #if ZEND_DEBUG
} else { } else {
@ -859,13 +864,13 @@ static inline int zend_verify_missing_return_type(zend_function *zf)
char *class_name; char *class_name;
need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce); 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; return 0;
} else if (ret_info->type_hint) { } else if (ret_info->type_hint) {
if (ret_info->type_hint == IS_ARRAY) { 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) { } 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 #if ZEND_DEBUG
} else { } else {
zend_error(E_ERROR, "Unknown typehint"); zend_error(E_ERROR, "Unknown typehint");

View file

@ -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) /* {{{ */ 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; return NULL;
} }

View file

@ -359,7 +359,11 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|
zval *zptr; zval *zptr;
if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) { 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 { do {
@ -439,7 +443,11 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMPVAR|
SAVE_OPLINE(); SAVE_OPLINE();
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { 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); 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); var_ptr = Z_INDIRECT(rv);
if (UNEXPECTED(var_ptr == NULL)) { 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))) { 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); var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) { 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))) { 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); retval = EX_VAR(opline->result.var);
if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) { 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 { 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); retval = EX_VAR(opline->result.var);
if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) { 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 { 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); var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) { 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)) { 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); var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) { 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)) { 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); var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) { 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)) { 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); var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) { 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)) { 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); container = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { 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); zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE);
FREE_OP2(); 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); container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { 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); zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE);
FREE_OP2(); 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 (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) { 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); container = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { 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); 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)) { 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(); FREE_OP1_VAR_PTR();
} else { } else {
if (OP2_TYPE == IS_UNUSED) { 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); 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); 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); container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_UNSET);
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { 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); zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE);
FREE_OP2(); 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); container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { 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); 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); container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { 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); 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(); 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); property = GET_OP2_ZVAL_PTR(BP_VAR_R);
container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) { 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_OP2();
FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { 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); 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(); 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); property = GET_OP2_ZVAL_PTR(BP_VAR_R);
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { 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); 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(); 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); property_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) { 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)); 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(); 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); object_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(object_ptr == NULL)) { 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): 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); value_ptr = GET_OP2_ZVAL_PTR_PTR(BP_VAR_W);
if (OP2_TYPE == IS_VAR && UNEXPECTED(value_ptr == NULL)) { 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 && if (OP2_TYPE == IS_VAR &&
(value_ptr == &EG(uninitialized_zval) || (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); variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == NULL)) { 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 && if (OP1_TYPE == IS_VAR &&
UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) &&
UNEXPECTED(!Z_ISREF_P(variable_ptr))) { 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))) || if ((OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) ||
(OP2_TYPE == IS_VAR && UNEXPECTED(value_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)) { if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION(); 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(); 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); 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 { do {
if ((OP2_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { if ((OP2_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) {
function_name = Z_REFVAL_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)) { if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION(); 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); } while (0);
} }
object = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R); object = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R);
do { if (OP1_TYPE != IS_UNUSED) {
if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { ZVAL_DEREF(object);
uint32_t nesting = 1; if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
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 (UNEXPECTED(EG(exception) != NULL)) { if (UNEXPECTED(EG(exception) != NULL)) {
FREE_OP2();
HANDLE_EXCEPTION(); 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)));
FREE_OP2(); FREE_OP2();
FREE_OP1(); FREE_OP1();
HANDLE_EXCEPTION();
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);
} }
} while (0); }
obj = Z_OBJ_P(object); obj = Z_OBJ_P(object);
called_scope = obj->ce; 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; zend_object *orig_obj = obj;
if (UNEXPECTED(obj->handlers->get_method == NULL)) { 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. */ /* 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)); 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)) { 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 && if (OP2_TYPE == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && 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(); HANDLE_EXCEPTION();
} }
if (UNEXPECTED(ce == NULL)) { 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); 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)) { if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION(); 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)); 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)) { 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 && if (OP2_TYPE == IS_CONST &&
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && 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 { } else {
if (UNEXPECTED(ce->constructor == NULL)) { 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)) { 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; 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" : ""); object ? ", assuming $this from incompatible context" : "");
} else { } else {
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
zend_error_noreturn( zend_error(
E_ERROR, E_EXCEPTION | E_ERROR,
"Non-static method %s::%s() cannot be called statically%s", "Non-static method %s::%s() cannot be called statically%s",
fbc->common.scope->name->val, fbc->common.function_name->val, fbc->common.scope->name->val, fbc->common.function_name->val,
object ? ", assuming $this from incompatible context" : ""); 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); function_name = (zval*)(EX_CONSTANT(opline->op2)+1);
if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) { if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) {
SAVE_OPLINE(); 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 { } else {
fbc = Z_FUNC_P(func); fbc = Z_FUNC_P(func);
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc); 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)); lcname = zend_string_tolower(Z_STR_P(function_name));
} }
if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) { 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); zend_string_release(lcname);
FREE_OP2(); FREE_OP2();
@ -2650,17 +2702,23 @@ ZEND_VM_C_LABEL(try_function_name):
method = zend_hash_index_find(Z_ARRVAL_P(function_name), 1); method = zend_hash_index_find(Z_ARRVAL_P(function_name), 1);
if (!obj || !method) { 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); ZVAL_DEREF(obj);
if (Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_OBJECT) { 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); ZVAL_DEREF(method);
if (Z_TYPE_P(method) != IS_STRING) { 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) { 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); fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL);
} }
if (UNEXPECTED(fbc == 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_STATIC)) {
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_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", "Non-static method %s::%s() should not be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val); fbc->common.scope->name->val, fbc->common.function_name->val);
} else { } else {
zend_error_noreturn( zend_error(
E_ERROR, E_EXCEPTION | E_ERROR,
"Non-static method %s::%s() cannot be called statically", "Non-static method %s::%s() cannot be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val); fbc->common.scope->name->val, fbc->common.function_name->val);
FREE_OP2();
HANDLE_EXCEPTION();
} }
} }
} else { } 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); fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL);
if (UNEXPECTED(fbc == 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) { 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)) { if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION(); 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");
ZEND_VM_CONTINUE(); /* Never reached */ FREE_OP2();
HANDLE_EXCEPTION();
} }
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
fbc, opline->extended_value, called_scope, object, EX(call)); 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", "Non-static method %s::%s() should not be called statically",
func->common.scope->name->val, func->common.function_name->val); func->common.scope->name->val, func->common.function_name->val);
} else { } else {
zend_error_noreturn( zend_error(
E_ERROR, E_EXCEPTION | E_ERROR,
"Non-static method %s::%s() cannot be called statically", "Non-static method %s::%s() cannot be called statically",
func->common.scope->name->val, func->common.function_name->val); func->common.scope->name->val, func->common.function_name->val);
FREE_OP2();
HANDLE_EXCEPTION();
} }
} }
} else { } else {
@ -2792,7 +2859,8 @@ ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST)
func_name++; func_name++;
if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(func_name))) == NULL)) { if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(func_name))) == NULL)) {
SAVE_OPLINE(); 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 { } else {
fbc = Z_FUNC_P(func); fbc = Z_FUNC_P(func);
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc); 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)); fbc = CACHED_PTR(Z_CACHE_SLOT_P(fname));
} else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(fname))) == NULL)) { } else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(fname))) == NULL)) {
SAVE_OPLINE(); 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 { } else {
fbc = Z_FUNC_P(func); fbc = Z_FUNC_P(func);
CACHE_PTR(Z_CACHE_SLOT_P(fname), fbc); 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; 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|ZEND_ACC_DEPRECATED)) != 0)) {
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 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)) { if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated", zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
@ -3097,21 +3167,21 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
for (i = 0; i < num_args; ++i) { for (i = 0; i < num_args; ++i) {
zend_verify_internal_arg_type(fbc, i + 1, p); zend_verify_internal_arg_type(fbc, i + 1, 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);
}
}
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);
}
}
} }
ret = EX_VAR(opline->result.var); ret = EX_VAR(opline->result.var);
@ -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)); object->handlers->call_method(fbc->common.function_name, object, call, EX_VAR(opline->result.var));
EG(current_execute_data) = call->prev_execute_data; EG(current_execute_data) = call->prev_execute_data;
} else { } 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); 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); retval_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(retval_ptr == NULL)) { 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) { 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)) { if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION(); 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); } while (0);
@ -3438,7 +3513,9 @@ ZEND_VM_HANDLER(116, ZEND_SEND_VAL_EX, CONST|TMP, ANY)
SAVE_OPLINE(); SAVE_OPLINE();
if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) { 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); value = GET_OP1_ZVAL_PTR(BP_VAR_R);
arg = ZEND_CALL_VAR(EX(call), opline->result.var); 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); varptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(varptr == NULL)) { 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); 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) { ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) {
if (name) { 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(); FREE_OP1();
CHECK_EXCEPTION(); HANDLE_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} }
top = ZEND_CALL_ARG(EX(call), arg_num); top = ZEND_CALL_ARG(EX(call), arg_num);
@ -3680,7 +3758,7 @@ ZEND_VM_C_LABEL(send_again):
} }
if (Z_TYPE(key) == IS_STRING) { if (Z_TYPE(key) == IS_STRING) {
zend_error(E_RECOVERABLE_ERROR, zend_error(E_EXCEPTION | E_RECOVERABLE_ERROR,
"Cannot unpack Traversable with string keys"); "Cannot unpack Traversable with string keys");
zend_string_release(Z_STR(key)); zend_string_release(Z_STR(key));
ZEND_VM_C_GOTO(unpack_iter_dtor); 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 (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) { 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) { } 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 { } 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); object_init_ex(&object_zval, ce);
constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval)); 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)) { if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION(); 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); } 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; clone_call = Z_OBJ_HT_P(obj)->clone_obj;
if (UNEXPECTED(clone_call == NULL)) { if (UNEXPECTED(clone_call == NULL)) {
if (ce) { 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 { } 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) { 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. /* Ensure that if we're calling a private function, we're allowed to do so.
*/ */
if (UNEXPECTED(ce != EG(scope))) { 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)) { } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so. /* 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)))) { 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(); CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE(); ZEND_VM_NEXT_OPCODE();
} else { } 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 { } else {
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c); 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(); HANDLE_EXCEPTION();
} }
if (UNEXPECTED(ce == NULL)) { 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); 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 */ /* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */
ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name);
} else { } 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): 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)) { (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); expr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { 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); ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(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(); HANDLE_EXCEPTION();
} }
if (UNEXPECTED(ce == NULL)) { 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); 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(); SAVE_OPLINE();
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET); container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { 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); 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"); zend_error(E_WARNING, "Illegal offset type in unset");
break; break;
} }
FREE_OP2();
} else if (OP1_TYPE == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { } else if (OP1_TYPE == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) { 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) { //??? if (OP2_TYPE == IS_CONST) {
//??? zval_copy_ctor(offset); //??? zval_copy_ctor(offset);
//??? } //??? }
Z_OBJ_HT_P(container)->unset_dimension(container, offset); Z_OBJ_HT_P(container)->unset_dimension(container, offset);
FREE_OP2(); }
} else if (OP1_TYPE != IS_UNUSED && Z_ISREF_P(container)) { } else if (OP1_TYPE != IS_UNUSED && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container); container = Z_REFVAL_P(container);
ZEND_VM_C_GOTO(unset_dim_again); ZEND_VM_C_GOTO(unset_dim_again);
} else if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { } else if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
ZEND_VM_CONTINUE(); /* bailed out before */
} else {
FREE_OP2();
} }
FREE_OP2();
FREE_OP1_VAR_PTR(); FREE_OP1_VAR_PTR();
CHECK_EXCEPTION(); CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE(); ZEND_VM_NEXT_OPCODE();
@ -4858,7 +4954,10 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
SAVE_OPLINE(); SAVE_OPLINE();
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET); container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { 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); offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
@ -6417,10 +6516,8 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED)
SAVE_OPLINE(); SAVE_OPLINE();
if (UNEXPECTED((zfunc = zend_hash_find(EG(function_table), Z_STR_P(EX_CONSTANT(opline->op1)))) == NULL) || zfunc = zend_hash_find(EG(function_table), Z_STR_P(EX_CONSTANT(opline->op1)));
UNEXPECTED(Z_FUNC_P(zfunc)->type != ZEND_USER_FUNCTION)) { ZEND_ASSERT(zfunc != NULL && Z_FUNC_P(zfunc)->type == ZEND_USER_FUNCTION);
zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
}
closure_is_static = Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC; 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; 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); zend_generator *generator = (zend_generator *) EX(return_value);
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { 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 */ /* 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); zval *value_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(value_ptr == NULL)) { 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 /* If a function call result is yielded and the function did

File diff suppressed because it is too large Load diff

View file

@ -353,6 +353,26 @@ $op2_free_op_var_ptr = array(
"TMPVAR" => "???", "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 $list = array(); // list of opcode handlers and helpers in original order
$opcodes = array(); // opcode handlers by code $opcodes = array(); // opcode handlers by code
$helpers = array(); // opcode helpers by name $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_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, $op2_get_obj_zval_ptr_ptr,
$op1_get_obj_zval_ptr_ptr_undef, $op2_get_obj_zval_ptr_ptr_undef, $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, $op2_free_op, $op1_free_op_if_var, $op2_free_op_if_var,
$op1_free_op_var_ptr, $op2_free_op_var_ptr, $prefix; $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_OP2_IF_VAR\(\)/",
"/FREE_OP1_VAR_PTR\(\)/", "/FREE_OP1_VAR_PTR\(\)/",
"/FREE_OP2_VAR_PTR\(\)/", "/FREE_OP2_VAR_PTR\(\)/",
"/FREE_UNFETCHED_OP1\(\)/",
"/FREE_UNFETCHED_OP2\(\)/",
"/^#(\s*)ifdef\s+ZEND_VM_SPEC\s*\n/m", "/^#(\s*)ifdef\s+ZEND_VM_SPEC\s*\n/m",
"/^#(\s*)ifndef\s+ZEND_VM_SPEC\s*\n/m", "/^#(\s*)ifndef\s+ZEND_VM_SPEC\s*\n/m",
"/\!defined\(ZEND_VM_SPEC\)/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], $op2_free_op_if_var[$op2],
$op1_free_op_var_ptr[$op1], $op1_free_op_var_ptr[$op1],
$op2_free_op_var_ptr[$op2], $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 1\n":"#\\1if 0\n",
($op1!="ANY"||$op2!="ANY")?"#\\1if 0\n":"#\\1if 1\n", ($op1!="ANY"||$op2!="ANY")?"#\\1if 0\n":"#\\1if 1\n",
($op1!="ANY"||$op2!="ANY")?"0":"1", ($op1!="ANY"||$op2!="ANY")?"0":"1",

View file

@ -24,30 +24,75 @@ function err($errno, $errstr) {
echo "*** Testing timezone_offset_get() : error conditions ***\n"; echo "*** Testing timezone_offset_get() : error conditions ***\n";
echo "\n-- Testing timezone_offset_get() function with zero arguments --\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"; 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"; echo "\n-- Testing timezone_offset_get() function with more than expected no. of arguments --\n";
$extra_arg = 99; $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"; echo "\n-- Testing timezone_offset_get() function with an invalid values for \$object argument --\n";
$invalid_obj = new stdClass(); $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; $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; $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"; echo "\n-- Testing timezone_offset_get() function with an invalid values for \$datetime argument --\n";
$invalid_obj = new stdClass(); $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; $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; $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=== ===DONE===
--EXPECTF-- --EXPECTF--
@ -64,17 +109,17 @@ bool(false)
-- Testing timezone_offset_get() function with an invalid values for $object argument -- -- 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" 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" 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" 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 -- -- 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" 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" 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" string(%d) "Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, null given"
bool(false)
===DONE=== ===DONE===

View file

@ -107,7 +107,11 @@ $datetime = new DateTime("2009-01-31 15:14:10");
foreach($inputs as $variation =>$object) { foreach($inputs as $variation =>$object) {
echo "\n-- $variation --\n"; 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 // closing the resource
@ -120,113 +124,85 @@ fclose( $file_handle );
-- int 0 -- -- int 0 --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, integer given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, integer given
bool(false)
-- int 1 -- -- int 1 --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, integer given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, integer given
bool(false)
-- int 12345 -- -- int 12345 --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, integer given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, integer given
bool(false)
-- int -12345 -- -- int -12345 --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, integer given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, integer given
bool(false)
-- float 10.5 -- -- float 10.5 --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, float given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, float given
bool(false)
-- float -10.5 -- -- float -10.5 --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, float given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, float given
bool(false)
-- float .5 -- -- float .5 --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, float given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, float given
bool(false)
-- empty array -- -- empty array --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, array given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, array given
bool(false)
-- int indexed array -- -- int indexed array --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, array given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, array given
bool(false)
-- associative array -- -- associative array --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, array given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, array given
bool(false)
-- nested arrays -- -- nested arrays --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, array given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, array given
bool(false)
-- uppercase NULL -- -- uppercase NULL --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, null given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, null given
bool(false)
-- lowercase null -- -- lowercase null --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, null given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, null given
bool(false)
-- lowercase true -- -- lowercase true --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, boolean given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, boolean given
bool(false)
-- lowercase false -- -- lowercase false --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, boolean given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, boolean given
bool(false)
-- uppercase TRUE -- -- uppercase TRUE --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, boolean given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, boolean given
bool(false)
-- uppercase FALSE -- -- uppercase FALSE --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, boolean given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, boolean given
bool(false)
-- empty string DQ -- -- empty string DQ --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, string given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, string given
bool(false)
-- empty string SQ -- -- empty string SQ --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, string given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, string given
bool(false)
-- string DQ -- -- string DQ --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, string given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, string given
bool(false)
-- string SQ -- -- string SQ --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, string given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, string given
bool(false)
-- mixed case string -- -- mixed case string --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, string given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, string given
bool(false)
-- heredoc -- -- heredoc --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, string given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, string given
bool(false)
-- instance of classWithToString -- -- instance of classWithToString --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, instance of classWithToString given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, instance of classWithToString given
bool(false)
-- instance of classWithoutToString -- -- instance of classWithoutToString --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, instance of classWithoutToString given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, instance of classWithoutToString given
bool(false)
-- undefined var -- -- undefined var --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, null given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, null given
bool(false)
-- unset var -- -- unset var --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, null given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, null given
bool(false)
-- resource -- -- resource --
Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, resource given Argument 1 passed to timezone_offset_get() must be an instance of DateTimeZone, resource given
bool(false)
===DONE=== ===DONE===

View file

@ -107,7 +107,11 @@ $object = new DateTimezone("Europe/London");
foreach($inputs as $variation =>$datetime) { foreach($inputs as $variation =>$datetime) {
echo "\n-- $variation --\n"; 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 // closing the resource
@ -120,113 +124,85 @@ fclose( $file_handle );
-- int 0 -- -- int 0 --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, integer given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, integer given
bool(false)
-- int 1 -- -- int 1 --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, integer given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, integer given
bool(false)
-- int 12345 -- -- int 12345 --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, integer given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, integer given
bool(false)
-- int -12345 -- -- int -12345 --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, integer given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, integer given
bool(false)
-- float 10.5 -- -- float 10.5 --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, float given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, float given
bool(false)
-- float -10.5 -- -- float -10.5 --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, float given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, float given
bool(false)
-- float .5 -- -- float .5 --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, float given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, float given
bool(false)
-- empty array -- -- empty array --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, array given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, array given
bool(false)
-- int indexed array -- -- int indexed array --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, array given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, array given
bool(false)
-- associative array -- -- associative array --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, array given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, array given
bool(false)
-- nested arrays -- -- nested arrays --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, array given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, array given
bool(false)
-- uppercase NULL -- -- uppercase NULL --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, null given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, null given
bool(false)
-- lowercase null -- -- lowercase null --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, null given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, null given
bool(false)
-- lowercase true -- -- lowercase true --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, boolean given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, boolean given
bool(false)
-- lowercase false -- -- lowercase false --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, boolean given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, boolean given
bool(false)
-- uppercase TRUE -- -- uppercase TRUE --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, boolean given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, boolean given
bool(false)
-- uppercase FALSE -- -- uppercase FALSE --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, boolean given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, boolean given
bool(false)
-- empty string DQ -- -- empty string DQ --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, string given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, string given
bool(false)
-- empty string SQ -- -- empty string SQ --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, string given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, string given
bool(false)
-- string DQ -- -- string DQ --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, string given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, string given
bool(false)
-- string SQ -- -- string SQ --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, string given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, string given
bool(false)
-- mixed case string -- -- mixed case string --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, string given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, string given
bool(false)
-- heredoc -- -- heredoc --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, string given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, string given
bool(false)
-- instance of classWithToString -- -- instance of classWithToString --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, instance of classWithToString given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, instance of classWithToString given
bool(false)
-- instance of classWithoutToString -- -- instance of classWithoutToString --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, instance of classWithoutToString given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, instance of classWithoutToString given
bool(false)
-- undefined var -- -- undefined var --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, null given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, null given
bool(false)
-- unset var -- -- unset var --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, null given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, null given
bool(false)
-- resource -- -- resource --
Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, resource given Argument 2 passed to timezone_offset_get() must implement interface DateTimeInterface, resource given
bool(false)
===DONE=== ===DONE===

View file

@ -28,13 +28,13 @@ $rootNode->appendChild($rootNode);
object(DOMException)#%d (%d) { object(DOMException)#%d (%d) {
["message":protected]=> ["message":protected]=>
string(23) "Hierarchy Request Error" string(23) "Hierarchy Request Error"
["string":"Exception":private]=> ["string":"BaseException":private]=>
string(0) "" string(0) ""
["file":protected]=> ["file":protected]=>
string(%d) "%sdom003.php" string(%d) "%sdom003.php"
["line":protected]=> ["line":protected]=>
int(8) int(8)
["trace":"Exception":private]=> ["trace":"BaseException":private]=>
array(1) { array(1) {
[0]=> [0]=>
array(6) { array(6) {
@ -55,7 +55,7 @@ object(DOMException)#%d (%d) {
} }
} }
} }
["previous":"Exception":private]=> ["previous":"BaseException":private]=>
NULL NULL
["code"]=> ["code"]=>
int(3) int(3)

View file

@ -40,13 +40,13 @@ ob_start();
object(DOMException)#%d (7) { object(DOMException)#%d (7) {
["message":protected]=> ["message":protected]=>
string(20) "Wrong Document Error" string(20) "Wrong Document Error"
["string":"Exception":private]=> ["string":"BaseException":private]=>
string(0) "" string(0) ""
["file":protected]=> ["file":protected]=>
string(%d) "%sdom_set_attr_node.php" string(%d) "%sdom_set_attr_node.php"
["line":protected]=> ["line":protected]=>
int(%d) int(%d)
["trace":"Exception":private]=> ["trace":"BaseException":private]=>
array(1) { array(1) {
[0]=> [0]=>
array(6) { array(6) {
@ -67,7 +67,7 @@ object(DOMException)#%d (7) {
} }
} }
} }
["previous":"Exception":private]=> ["previous":"BaseException":private]=>
NULL NULL
["code"]=> ["code"]=>
int(4) int(4)

View file

@ -16,7 +16,11 @@ foreach($funcs as $func) {
try { try {
$res = $func($arg); $res = $func($arg);
} catch (Exception $e) { continue; } } catch (Exception $e) {
continue;
} catch (EngineException $e) {
continue;
}
if($res != false) { if($res != false) {
echo "$func: "; echo "$func: ";
var_dump($res); var_dump($res);

View file

@ -17,17 +17,49 @@ echo "error: $errno, $errstr\n";
} }
set_error_handler('eh'); set_error_handler('eh');
var_dump($c->after()); try {
var_dump($c->before()); 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)); try {
var_dump($c->before(1)); 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)); try{
var_dump($c->before($c, 1)); 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)); try {
var_dump(intlcal_before($c)); 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-- --EXPECT--
error: 2, IntlCalendar::after() expects exactly 1 parameter, 0 given error: 2, IntlCalendar::after() expects exactly 1 parameter, 0 given
error: 2, IntlCalendar::after(): intlcal_before/after: bad arguments 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 error: 2, IntlCalendar::before(): intlcal_before/after: bad arguments
bool(false) bool(false)
error: 4096, Argument 1 passed to IntlCalendar::after() must be an instance of IntlCalendar, integer given 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: 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() expects exactly 1 parameter, 2 given
error: 2, IntlCalendar::after(): intlcal_before/after: bad arguments error: 2, IntlCalendar::after(): intlcal_before/after: bad arguments
bool(false) bool(false)

View file

@ -17,30 +17,42 @@ echo "error: $errno, $errstr\n";
} }
set_error_handler('eh'); set_error_handler('eh');
var_dump($c->equals()); try {
var_dump($c->equals(new stdclass)); var_dump($c->equals());
var_dump($c->equals(1, 2)); } 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-- --EXPECT--
error: 2, IntlCalendar::equals() expects exactly 1 parameter, 0 given error: 2, IntlCalendar::equals() expects exactly 1 parameter, 0 given
error: 2, IntlCalendar::equals(): intlcal_equals: bad arguments error: 2, IntlCalendar::equals(): intlcal_equals: bad arguments
bool(false) bool(false)
error: 4096, Argument 1 passed to IntlCalendar::equals() must be an instance of IntlCalendar, instance of stdClass given 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: 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: 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: 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)

View file

@ -32,10 +32,26 @@ echo "error: $errno, $errstr\n";
} }
set_error_handler('eh'); set_error_handler('eh');
var_dump(intlcal_get_least_maximum(1, 1)); try {
var_dump(intlcal_get_maximum(1, 1)); var_dump(intlcal_get_least_maximum(1, 1));
var_dump(intlcal_get_greatest_minimum(1, -1)); } catch (EngineException $ex) {
var_dump(intlcal_get_minimum(1, -1)); 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-- --EXPECTF--
@ -83,18 +99,10 @@ bool(false)
Warning: intlcal_get_minimum(): intlcal_get_minimum: invalid field in %s on line %d Warning: intlcal_get_minimum(): intlcal_get_minimum: invalid field in %s on line %d
bool(false) bool(false)
error: 4096, Argument 1 passed to intlcal_get_least_maximum() must be an instance of IntlCalendar, integer given 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: 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: 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: 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)

View file

@ -17,21 +17,69 @@ echo "error: $errno, $errstr\n";
} }
set_error_handler('eh'); set_error_handler('eh');
var_dump(intlcal_get($c)); try {
var_dump(intlcal_get_actual_maximum($c)); var_dump(intlcal_get($c));
var_dump(intlcal_get_actual_minimum($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)); try {
var_dump(intlcal_get_actual_maximum($c, -1)); var_dump(intlcal_get($c, -1));
var_dump(intlcal_get_actual_minimum($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")); try {
var_dump(intlcal_get_actual_maximum($c, "s")); var_dump(intlcal_get($c, "s"));
var_dump(intlcal_get_actual_minimum($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)); try {
var_dump(intlcal_get_actual_maximum(1)); var_dump(intlcal_get(1));
var_dump(intlcal_get_actual_minimum(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-- --EXPECT--
error: 2, intlcal_get() expects exactly 2 parameters, 1 given error: 2, intlcal_get() expects exactly 2 parameters, 1 given
error: 2, intlcal_get(): intlcal_get: bad arguments 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 error: 2, intlcal_get_actual_minimum(): intlcal_get_actual_minimum: bad arguments
bool(false) bool(false)
error: 4096, Argument 1 passed to intlcal_get() must be an instance of IntlCalendar, integer given 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: 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: 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)

View file

@ -17,34 +17,49 @@ echo "error: $errno, $errstr\n";
} }
set_error_handler('eh'); set_error_handler('eh');
var_dump($c->isEquivalentTo(0)); try {
var_dump($c->isEquivalentTo($c, 1)); var_dump($c->isEquivalentTo(0));
var_dump($c->isEquivalentTo(1)); } 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)); try {
var_dump(intlcal_is_equivalent_to($c, 1)); var_dump(intlcal_is_equivalent_to($c));
var_dump(intlcal_is_equivalent_to(1, $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-- --EXPECT--
error: 4096, Argument 1 passed to IntlCalendar::isEquivalentTo() must be an instance of IntlCalendar, integer given 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() expects exactly 1 parameter, 2 given
error: 2, IntlCalendar::isEquivalentTo(): intlcal_is_equivalent_to: bad arguments error: 2, IntlCalendar::isEquivalentTo(): intlcal_is_equivalent_to: bad arguments
bool(false) bool(false)
error: 4096, Argument 1 passed to IntlCalendar::isEquivalentTo() must be an instance of IntlCalendar, integer given 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() expects exactly 2 parameters, 1 given
error: 2, intlcal_is_equivalent_to(): intlcal_is_equivalent_to: bad arguments error: 2, intlcal_is_equivalent_to(): intlcal_is_equivalent_to: bad arguments
bool(false) bool(false)
error: 4096, Argument 2 passed to intlcal_is_equivalent_to() must be an instance of IntlCalendar, integer given 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: 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)

View file

@ -19,11 +19,27 @@ echo "error: $errno, $errstr\n";
} }
set_error_handler('eh'); set_error_handler('eh');
var_dump($c->setTimeZone($gmt, 2)); try {
var_dump($c->setTimeZone()); 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)); try{
var_dump(intlcal_set_time_zone(1, $gmt)); 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-- --EXPECT--
error: 2, IntlCalendar::setTimeZone() expects exactly 1 parameter, 2 given 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 error: 2, intlcal_set_time_zone(): intlcal_set_time_zone: bad arguments
bool(false) bool(false)
error: 4096, Argument 1 passed to intlcal_set_time_zone() must be an instance of IntlCalendar, integer given 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)

View file

@ -16,22 +16,24 @@ function error_handler($errno, $errstr, $errfile, $errline)
set_error_handler("error_handler"); set_error_handler("error_handler");
$tz = IntlTimeZone::createTimeZone('Europe/Lisbon'); $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-- --EXPECT--
int(4096) int(4096)
string(99) "Argument 1 passed to IntlTimeZone::hasSameRules() must be an instance of IntlTimeZone, string given" 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) int(4096)
string(92) "Argument 1 passed to intltz_has_same_rules() must be an instance of IntlTimeZone, null given" 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)

View file

@ -101,8 +101,8 @@ require_once('skipifconnectfailure.inc');
try { try {
if (false !== ($obj = @mysqli_fetch_object($res, 'mysqli_fetch_object_construct', 'a'))) if (false !== ($obj = @mysqli_fetch_object($res, 'mysqli_fetch_object_construct', 'a')))
printf("[011] Should have failed\n"); printf("[011] Should have failed\n");
} catch (Exception $e) { } catch (EngineException $e) {
printf("%s\n", $e->getMessage()); handle_catchable_fatal($e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine());
} }
mysqli_free_result($res); mysqli_free_result($res);
@ -151,6 +151,5 @@ NULL
[E_WARNING] mysqli_fetch_object(): Couldn't fetch mysqli_result in %s on line %d [E_WARNING] mysqli_fetch_object(): Couldn't fetch mysqli_result in %s on line %d
NULL NULL
[E_RECOVERABLE_ERROR] Argument 3 passed to mysqli_fetch_object() must be of the type array, string given in %s on line %d [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 Fatal error: Class 'this_class_does_not_exist' not found in %s on line %d

View file

@ -31,11 +31,20 @@ require_once('skipifconnectfailure.inc');
if (!is_null($tmp = @$res->fetch_object($link))) if (!is_null($tmp = @$res->fetch_object($link)))
printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp); printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
if (!is_null($tmp = @$res->fetch_object($link, $link))) try {
printf("[005] 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);
} 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); $obj = mysqli_fetch_object($res);
if (($obj->ID !== "1") || ($obj->label !== "a") || (get_class($obj) != 'stdClass')) { 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')) { 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); printf("[009] Object seems wrong. [%d] %s\n", $mysqli->errno, $mysqli->error);
var_dump($obj); 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')); $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(): 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_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_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_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_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_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 [E_NOTICE] Undefined variable: b in %s on line %d
NULL NULL

View file

@ -18,10 +18,10 @@ $testClassInstance = new TestClass();
try { try {
var_dump($foo->invokeArgs($testClassInstance, true)); var_dump($foo->invokeArgs($testClassInstance, true));
} catch (Exception $e) { } catch (EngineException $e) {
var_dump($e->getMessage()); var_dump($e->getMessage());
} }
?> ?>
--EXPECTF-- --EXPECT--
Catchable fatal error: Argument 2 passed to ReflectionMethod::invokeArgs() must be of the type array, boolean given in %s on line %d string(92) "Argument 2 passed to ReflectionMethod::invokeArgs() must be of the type array, boolean given"

View file

@ -46,4 +46,3 @@ echo "um, hi\n";
write: goodbye cruel world write: goodbye cruel world
Fatal error: Call to undefined function undefined_function() in %s on line %d Fatal error: Call to undefined function undefined_function() in %s on line %d
close: goodbye cruel world

View file

@ -15,17 +15,23 @@ class Setting extends ReflectionObject
{ {
} }
Reflection::export(simplexml_load_string('<test/>', 'Setting')); try {
Reflection::export(simplexml_load_string('<test/>', 'Setting'));
} catch (EngineException $e) {
my_error_handler($e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine());
}
Reflection::export(simplexml_load_file('data:,<test/>', 'Setting')); try {
Reflection::export(simplexml_load_file('data:,<test/>', 'Setting'));
} catch (EngineException $e) {
my_error_handler($e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine());
}
?> ?>
===DONE=== ===DONE===
--EXPECTF-- --EXPECTF--
Error: simplexml_load_string() expects parameter 2 to be a class name derived from SimpleXMLElement, 'Setting' given 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: 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: 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: Argument 1 passed to Reflection::export() must implement interface Reflector, null given
Error: Reflection::export() expects parameter 1 to be Reflector, null given
===DONE=== ===DONE===

View file

@ -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]) /* {{{ proto void SoapServer::handle ( [string soap_request])
Handles a SOAP request */ Handles a SOAP request */
@ -1646,13 +1666,8 @@ PHP_METHOD(SoapServer, handle)
xmlFreeDoc(doc_request); xmlFreeDoc(doc_request);
if (EG(exception)) { if (EG(exception)) {
zval exception_object;
ZVAL_OBJ(&exception_object, EG(exception));
php_output_discard(); php_output_discard();
if (instanceof_function(Z_OBJCE(exception_object), soap_fault_class_entry)) { _soap_server_exception(service, function, getThis());
soap_server_fault_ex(function, &exception_object, NULL);
}
goto fail; goto fail;
} }
@ -1700,13 +1715,8 @@ PHP_METHOD(SoapServer, handle)
php_error_docref(NULL, E_ERROR, "Error calling constructor"); php_error_docref(NULL, E_ERROR, "Error calling constructor");
} }
if (EG(exception)) { if (EG(exception)) {
zval exception_object;
ZVAL_OBJ(&exception_object, EG(exception));
php_output_discard(); php_output_discard();
if (instanceof_function(Z_OBJCE(exception_object), soap_fault_class_entry)) { _soap_server_exception(service, function, getThis());
soap_server_fault_ex(function, &exception_object, NULL);
}
zval_dtor(&constructor); zval_dtor(&constructor);
zval_dtor(&c_ret); zval_dtor(&c_ret);
zval_ptr_dtor(&tmp_soap); zval_ptr_dtor(&tmp_soap);
@ -1728,13 +1738,8 @@ PHP_METHOD(SoapServer, handle)
} }
if (EG(exception)) { if (EG(exception)) {
zval exception_object;
ZVAL_OBJ(&exception_object, EG(exception));
php_output_discard(); php_output_discard();
if (instanceof_function(Z_OBJCE(exception_object), soap_fault_class_entry)) { _soap_server_exception(service, function, getThis());
soap_server_fault_ex(function, &exception_object, NULL);
}
zval_dtor(&constructor); zval_dtor(&constructor);
zval_dtor(&c_ret); zval_dtor(&c_ret);
efree(class_name); efree(class_name);
@ -1823,20 +1828,8 @@ PHP_METHOD(SoapServer, handle)
if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(soap_obj);} if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(soap_obj);}
goto fail; goto fail;
} else if (EG(exception)) { } else if (EG(exception)) {
zval exception_object;
ZVAL_OBJ(&exception_object, EG(exception));
php_output_discard(); php_output_discard();
if (instanceof_function(Z_OBJCE(exception_object), soap_fault_class_entry)) { _soap_server_exception(service, function, getThis());
//??? 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);
}
efree(fn_name); efree(fn_name);
if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(soap_obj);} if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(soap_obj);}
goto fail; goto fail;
@ -1874,13 +1867,8 @@ PHP_METHOD(SoapServer, handle)
efree(fn_name); efree(fn_name);
if (EG(exception)) { if (EG(exception)) {
zval exception_object;
ZVAL_OBJ(&exception_object, EG(exception));
php_output_discard(); php_output_discard();
if (instanceof_function(Z_OBJCE(exception_object), soap_fault_class_entry)) { _soap_server_exception(service, function, getThis());
soap_server_fault_ex(function, &exception_object, NULL);
}
if (service->type == SOAP_CLASS) { if (service->type == SOAP_CLASS) {
#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION) #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
if (soap_obj && service->soap_class.persistence != SOAP_PERSISTENCE_SESSION) { if (soap_obj && service->soap_class.persistence != SOAP_PERSISTENCE_SESSION) {
@ -1918,13 +1906,8 @@ PHP_METHOD(SoapServer, handle)
} }
if (EG(exception)) { if (EG(exception)) {
zval exception_object;
ZVAL_OBJ(&exception_object, EG(exception));
php_output_discard(); php_output_discard();
if (instanceof_function(Z_OBJCE(exception_object), soap_fault_class_entry)) { _soap_server_exception(service, function, getThis());
soap_server_fault_ex(function, &exception_object, NULL);
}
if (service->type == SOAP_CLASS) { if (service->type == SOAP_CLASS) {
#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION) #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
if (soap_obj && service->soap_class.persistence != SOAP_PERSISTENCE_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_response_code = SG(sapi_headers).http_response_code;
_old_http_status_line = SG(sapi_headers).http_status_line; _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); call_old_error_handler(error_num, error_filename, error_lineno, format, args);
return; return;
} }

View file

@ -35,3 +35,4 @@ echo "ok\n";
--EXPECT-- --EXPECT--
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Server</faultcode><faultstring>Call to undefined function undefined_function_x()</faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Server</faultcode><faultstring>Call to undefined function undefined_function_x()</faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>
ok

View file

@ -18,6 +18,8 @@ try {
new CallbackFilterIterator(null); new CallbackFilterIterator(null);
} catch(InvalidArgumentException $e) { } catch(InvalidArgumentException $e) {
echo $e->getMessage() . "\n"; echo $e->getMessage() . "\n";
} catch(EngineException $e) {
echo $e->getMessage() . "\n";
} }
try { try {
@ -44,7 +46,6 @@ try {
--EXPECT-- --EXPECT--
CallbackFilterIterator::__construct() expects exactly 2 parameters, 0 given CallbackFilterIterator::__construct() expects exactly 2 parameters, 0 given
Argument 1 passed to CallbackFilterIterator::__construct() must implement interface Iterator, null 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, no array or string given
CallbackFilterIterator::__construct() expects parameter 2 to be a valid callback, array must have exactly two members CallbackFilterIterator::__construct() expects parameter 2 to be a valid callback, array must have exactly two members
some message some message

View file

@ -3,7 +3,7 @@ SPL: AppendIterator and its ArrayIterator
--FILE-- --FILE--
<?php <?php
function test_error_handler($errno, $msg, $filename, $linenum, $vars) function test_error_handler($errno, $msg, $filename, $linenum)
{ {
echo "Error $msg in $filename on line $linenum\n"; echo "Error $msg in $filename on line $linenum\n";
return true; return true;
@ -13,7 +13,11 @@ set_error_handler('test_error_handler');
$it = new AppendIterator; $it = new AppendIterator;
$it->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(1)));
$it->append(new ArrayIterator(array(21, 22))); $it->append(new ArrayIterator(array(21, 22)));

View file

@ -42,7 +42,11 @@ $it = new RecursiveIteratorIterator($it);
var_dump(iterator_apply($it, 'test')); var_dump(iterator_apply($it, 'test'));
echo "===ERRORS===\n"; 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'));
var_dump(iterator_apply($it, 'non_existing_function', NULL, 2)); var_dump(iterator_apply($it, 'non_existing_function', NULL, 2));
@ -75,8 +79,6 @@ int(6)
int(4) int(4)
===ERRORS=== ===ERRORS===
Error: Argument 3 passed to iterator_apply() must be of the type array, integer given 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 Error: iterator_apply() expects parameter 2 to be a valid callback, function 'non_existing_function' not found or invalid function name
NULL NULL
Error: iterator_apply() expects at most 3 parameters, 4 given Error: iterator_apply() expects at most 3 parameters, 4 given

View file

@ -102,4 +102,6 @@ var_dump($myvar);
echo "Done\n"; echo "Done\n";
?> ?>
--EXPECTF-- --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 Catchable fatal error: Argument 1 passed to VariableStream::__construct() must be of the type array, none given in %s on line %d

View file

@ -19,5 +19,5 @@ Strict Standards: Non-static method foo::bar() should not be called statically i
ok ok
bool(false) 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

View file

@ -2540,6 +2540,10 @@ PHPAPI int php_execute_script(zend_file_handle *primary_file)
} }
} zend_end_try(); } zend_end_try();
if (EG(exception)) {
zend_exception_error(EG(exception), E_ERROR);
}
#if HAVE_BROKEN_GETCWD #if HAVE_BROKEN_GETCWD
if (old_cwd_fd != -1) { if (old_cwd_fd != -1) {
fchdir(old_cwd_fd); fchdir(old_cwd_fd);
@ -2665,6 +2669,9 @@ PHPAPI int php_lint_script(zend_file_handle *file)
retval = SUCCESS; retval = SUCCESS;
} }
} zend_end_try(); } zend_end_try();
if (EG(exception)) {
zend_exception_error(EG(exception), E_ERROR);
}
return retval; return retval;
} }

View file

@ -14,7 +14,7 @@ $php = getenv('TEST_PHP_EXECUTABLE');
var_dump(`"$php" -n --rc unknown`); var_dump(`"$php" -n --rc unknown`);
var_dump(`"$php" -n --rc stdclass`); var_dump(`"$php" -n --rc stdclass`);
var_dump(`"$php" -n --rc exception`); var_dump(`"$php" -n --rc baseexception`);
echo "Done\n"; echo "Done\n";
?> ?>
@ -40,7 +40,7 @@ string(183) "Class [ <internal:Core> class stdClass ] {
} }
" "
string(1355) "Class [ <internal:Core> class Exception ] { string(1368) "Class [ <internal:Core> abstract class BaseException ] {
- Constants [0] { - Constants [0] {
} }

View file

@ -16,13 +16,36 @@ Ensure type hints are enforced for functions invoked as callbacks.
function f2(A $a = null) { function f2(A $a = null) {
echo "in f2;\n"; echo "in f2;\n";
} }
call_user_func('f1', 1); try {
call_user_func('f1', new A); call_user_func('f1', 1);
call_user_func('f2', 1); } catch (EngineException $ex) {
call_user_func('f2'); echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n";
call_user_func('f2', new A); }
call_user_func('f2', null); 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"; echo "\n\n---> Type hints with callback static method:\n";
class C { 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"; echo "\n\n---> Type hints with callback instance method:\n";
class D { class D {
@ -67,43 +114,68 @@ Ensure type hints are enforced for functions invoked as callbacks.
} }
} }
$d = new D; $d = new D;
call_user_func(array($d, 'f1'), 1);
call_user_func(array($d, 'f1'), new A); try {
call_user_func(array($d, 'f2'), 1); call_user_func(array($d, 'f1'), 1);
call_user_func(array($d, 'f2')); } catch (EngineException $ex) {
call_user_func(array($d, 'f2'), new A); echo "{$ex->getCode()}: {$ex->getMessage()} - {$ex->getFile()}({$ex->getLine()})\n\n";
call_user_func(array($d, 'f2'), null); }
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-- --EXPECTF--
---> Type hints with callback function: ---> Type hints with callback function:
4096: Argument 1 passed to f1() must be an instance of A, integer given%s(10) 4096: Argument 1 passed to f1() must be an instance of A, integer given%s(%d)
in f1; in f1;
in f1; 4096: Argument 1 passed to f2() must be an instance of A, integer given%s(%d)
4096: Argument 1 passed to f2() must be an instance of A, integer given%s(13)
in f2;
in f2; in f2;
in f2; in f2;
in f2; in f2;
---> Type hints with callback static method: ---> Type hints with callback static method:
4096: Argument 1 passed to C::f1() must be an instance of A, integer given%s(26) 4096: Argument 1 passed to C::f1() must be an instance of A, integer given%s(%d)
in C::f1 (static); in C::f1 (static);
in C::f1 (static); 4096: Argument 1 passed to C::f2() must be an instance of A, integer given%s(%d)
4096: Argument 1 passed to C::f2() must be an instance of A, integer given%s(33)
in C::f2 (static);
in C::f2 (static); in C::f2 (static);
in C::f2 (static); in C::f2 (static);
in C::f2 (static); in C::f2 (static);
---> Type hints with callback instance method: ---> Type hints with callback instance method:
4096: Argument 1 passed to D::f1() must be an instance of A, integer given%s(51) 4096: Argument 1 passed to D::f1() must be an instance of A, integer given%s(%d)
in C::f1 (instance); in C::f1 (instance);
in C::f1 (instance); 4096: Argument 1 passed to D::f2() must be an instance of A, integer given%s(%d)
4096: Argument 1 passed to D::f2() must be an instance of A, integer given%s(58)
in C::f2 (instance);
in C::f2 (instance); in C::f2 (instance);
in C::f2 (instance); in C::f2 (instance);
in C::f2 (instance); in C::f2 (instance);

View file

@ -17,21 +17,13 @@ Catchable fatal error [2]
set_error_handler('error'); set_error_handler('error');
blah (new StdClass); try {
blah (new StdClass);
} catch (engineException $ex) {
echo $ex->getMessage(), "\n";
}
echo "ALIVE!\n"; echo "ALIVE!\n";
?> ?>
--EXPECTF-- --EXPECTF--
array(5) { 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
[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) {
}
}
ALIVE! ALIVE!