diff options
Diffstat (limited to 'Zend')
188 files changed, 3346 insertions, 4264 deletions
diff --git a/Zend/Zend.m4 b/Zend/Zend.m4 index 0755a58f14..36bf116042 100644 --- a/Zend/Zend.m4 +++ b/Zend/Zend.m4 @@ -74,11 +74,11 @@ int main() AC_DEFUN([LIBZEND_OTHER_CHECKS],[ -AC_ARG_ENABLE([maintainer-zts], - [AS_HELP_STRING([--enable-maintainer-zts], - [Enable thread safety - for code maintainers only!!])], - [ZEND_MAINTAINER_ZTS=$enableval], - [ZEND_MAINTAINER_ZTS=no]) +AC_ARG_ENABLE([zts], + [AS_HELP_STRING([--enable-zts], + [Enable thread safety])], + [ZEND_ZTS=$enableval], + [ZEND_ZTS=no]) AC_ARG_ENABLE([inline-optimization], [AS_HELP_STRING([--disable-inline-optimization], @@ -87,7 +87,7 @@ AC_ARG_ENABLE([inline-optimization], [ZEND_INLINE_OPTIMIZATION=yes]) AC_MSG_CHECKING(whether to enable thread-safety) -AC_MSG_RESULT($ZEND_MAINTAINER_ZTS) +AC_MSG_RESULT($ZEND_ZTS) AC_MSG_CHECKING(whether to enable inline optimization for GCC) AC_MSG_RESULT($ZEND_INLINE_OPTIMIZATION) @@ -110,7 +110,7 @@ fi test -n "$DEBUG_CFLAGS" && CFLAGS="$CFLAGS $DEBUG_CFLAGS" -if test "$ZEND_MAINTAINER_ZTS" = "yes"; then +if test "$ZEND_ZTS" = "yes"; then AC_DEFINE(ZTS,1,[ ]) CFLAGS="$CFLAGS -DZTS" fi diff --git a/Zend/tests/004.phpt b/Zend/tests/004.phpt index 179684d076..2f733f1bd8 100644 --- a/Zend/tests/004.phpt +++ b/Zend/tests/004.phpt @@ -3,7 +3,6 @@ strncmp() tests --FILE-- <?php -var_dump(strncmp("", "")); var_dump(strncmp("", "", 100)); var_dump(strncmp("aef", "dfsgbdf", -1)); var_dump(strncmp("fghjkl", "qwer", 0)); @@ -13,8 +12,6 @@ var_dump(strncmp("qwerty", "qwerty123", 7)); echo "Done\n"; ?> --EXPECTF-- -Warning: strncmp() expects exactly 3 parameters, 2 given in %s on line %d -NULL int(0) Warning: Length must be greater than or equal to 0 in %s on line %d diff --git a/Zend/tests/005.phpt b/Zend/tests/005.phpt index 6ad1b0f63d..f4abfb6c51 100644 --- a/Zend/tests/005.phpt +++ b/Zend/tests/005.phpt @@ -3,7 +3,6 @@ strcasecmp() tests --FILE-- <?php -var_dump(strcasecmp("")); var_dump(strcasecmp("", "")); var_dump(strcasecmp("aef", "dfsgbdf")); var_dump(strcasecmp("qwe", "qwer")); @@ -15,8 +14,6 @@ var_dump(strcasecmp("01", "01")); echo "Done\n"; ?> --EXPECTF-- -Warning: strcasecmp() expects exactly 2 parameters, 1 given in %s on line %d -NULL int(0) int(-3) int(-1) diff --git a/Zend/tests/006.phpt b/Zend/tests/006.phpt index 64c74ff134..12907fd36e 100644 --- a/Zend/tests/006.phpt +++ b/Zend/tests/006.phpt @@ -3,7 +3,6 @@ strncasecmp() tests --FILE-- <?php -var_dump(strncasecmp("")); var_dump(strncasecmp("", "", -1)); var_dump(strncasecmp("aef", "dfsgbdf", 0)); var_dump(strncasecmp("aef", "dfsgbdf", 10)); @@ -16,9 +15,6 @@ var_dump(strncasecmp("01", "01", 1000)); echo "Done\n"; ?> --EXPECTF-- -Warning: strncasecmp() expects exactly 3 parameters, 1 given in %s on line %d -NULL - Warning: Length must be greater than or equal to 0 in %s on line %d bool(false) int(0) diff --git a/Zend/tests/007.phpt b/Zend/tests/007.phpt deleted file mode 100644 index 6120181269..0000000000 --- a/Zend/tests/007.phpt +++ /dev/null @@ -1,65 +0,0 @@ ---TEST-- -each() tests ---FILE-- -<?php - -var_dump(each()); -$var = 1; -var_dump(each($var)); -$var = "string"; -var_dump(each($var)); -$var = array(1,2,3); -var_dump(each($var)); -$var = array("a"=>1,"b"=>2,"c"=>3); -var_dump(each($var)); - -$a = array(1); -$a [] =&$a[0]; - -var_dump(each($a)); - - -echo "Done\n"; -?> ---EXPECTF-- -Warning: each() expects exactly 1 parameter, 0 given in %s on line %d -NULL - -Deprecated: The each() function is deprecated. This message will be suppressed on further calls in %s on line %d - -Warning: Variable passed to each() is not an array or object in %s on line %d -NULL - -Warning: Variable passed to each() is not an array or object in %s on line %d -NULL -array(4) { - [1]=> - int(1) - ["value"]=> - int(1) - [0]=> - int(0) - ["key"]=> - int(0) -} -array(4) { - [1]=> - int(1) - ["value"]=> - int(1) - [0]=> - string(1) "a" - ["key"]=> - string(1) "a" -} -array(4) { - [1]=> - int(1) - ["value"]=> - int(1) - [0]=> - int(0) - ["key"]=> - int(0) -} -Done diff --git a/Zend/tests/008.phpt b/Zend/tests/008.phpt index 0766c3e1a4..6f885c0dc5 100644 --- a/Zend/tests/008.phpt +++ b/Zend/tests/008.phpt @@ -3,12 +3,13 @@ define() tests --FILE-- <?php -var_dump(define()); -var_dump(define("TRUE")); -var_dump(define("TRUE", 1)); -var_dump(define("TRUE", 1, array(1))); +try { + var_dump(define(array(1,2,3,4,5), 1)); +} catch (TypeError $e) { + echo "TypeError: ", $e->getMessage(), "\n"; +} -var_dump(define(array(1,2,3,4,5), 1)); +var_dump(define("TRUE", 1)); var_dump(define(" ", 1)); var_dump(define("[[[", 2)); var_dump(define("test const", 3)); @@ -24,18 +25,10 @@ var_dump(constant("test const")); echo "Done\n"; ?> --EXPECTF-- -Warning: define() expects at least 2 parameters, 0 given in %s on line %d -NULL - -Warning: define() expects at least 2 parameters, 1 given in %s on line %d -NULL -bool(true) - -Warning: define() expects parameter 3 to be bool, array given in %s on line %d -NULL +TypeError: define() expects parameter 1 to be string, array given -Warning: define() expects parameter 1 to be string, array given in %s on line %d -NULL +Notice: Constant TRUE already defined in %s on line %d +bool(false) bool(true) bool(true) bool(true) diff --git a/Zend/tests/009.phpt b/Zend/tests/009.phpt index 82cfabee49..4a34fe4c84 100644 --- a/Zend/tests/009.phpt +++ b/Zend/tests/009.phpt @@ -16,9 +16,6 @@ class foo { class foo2 extends foo { } -foo::bar(); -foo2::bar(); - $f1 = new foo; $f2 = new foo2; @@ -36,11 +33,6 @@ $f1->testNull(); echo "Done\n"; ?> --EXPECTF-- -Deprecated: Non-static method foo::bar() should not be called statically in %s on line %d -string(3) "foo" - -Deprecated: Non-static method foo::bar() should not be called statically in %s on line %d -string(3) "foo" string(3) "foo" string(3) "foo" diff --git a/Zend/tests/011.phpt b/Zend/tests/011.phpt index 7bcab0798f..d36ae80ae8 100644 --- a/Zend/tests/011.phpt +++ b/Zend/tests/011.phpt @@ -23,8 +23,6 @@ class bar extends foo { } } -var_dump(property_exists()); -var_dump(property_exists("")); var_dump(property_exists("foo","pp1")); var_dump(property_exists("foo","pp2")); var_dump(property_exists("foo","pp3")); @@ -53,11 +51,6 @@ $bar->test(); echo "Done\n"; ?> --EXPECTF-- -Warning: property_exists() expects exactly 2 parameters, 0 given in %s on line %d -NULL - -Warning: property_exists() expects exactly 2 parameters, 1 given in %s on line %d -NULL bool(true) bool(true) bool(true) diff --git a/Zend/tests/012.phpt b/Zend/tests/012.phpt index 40f68e9794..c238229066 100644 --- a/Zend/tests/012.phpt +++ b/Zend/tests/012.phpt @@ -6,10 +6,8 @@ class_exists() tests class foo { } -var_dump(class_exists()); var_dump(class_exists("qwerty")); var_dump(class_exists("")); -var_dump(class_exists(array())); var_dump(class_exists("test", false)); var_dump(class_exists("foo", false)); var_dump(class_exists("foo")); @@ -18,14 +16,9 @@ var_dump(class_exists("stdClass")); echo "Done\n"; ?> ---EXPECTF-- -Warning: class_exists() expects at least 1 parameter, 0 given in %s on line %d -NULL +--EXPECT-- bool(false) bool(false) - -Warning: class_exists() expects parameter 1 to be string, array given in %s on line %d -NULL bool(false) bool(true) bool(true) diff --git a/Zend/tests/013.phpt b/Zend/tests/013.phpt index aec10e53f1..fd8320b536 100644 --- a/Zend/tests/013.phpt +++ b/Zend/tests/013.phpt @@ -6,10 +6,8 @@ interface_exists() tests interface foo { } -var_dump(interface_exists()); var_dump(interface_exists("qwerty")); var_dump(interface_exists("")); -var_dump(interface_exists(array())); var_dump(interface_exists("test", false)); var_dump(interface_exists("foo", false)); var_dump(interface_exists("foo")); @@ -18,14 +16,9 @@ var_dump(interface_exists("stdClass")); echo "Done\n"; ?> ---EXPECTF-- -Warning: interface_exists() expects at least 1 parameter, 0 given in %s on line %d -NULL +--EXPECT-- bool(false) bool(false) - -Warning: interface_exists() expects parameter 1 to be string, array given in %s on line %d -NULL bool(false) bool(true) bool(true) diff --git a/Zend/tests/014.phpt b/Zend/tests/014.phpt index a2c5335923..c02fee9385 100644 --- a/Zend/tests/014.phpt +++ b/Zend/tests/014.phpt @@ -8,13 +8,9 @@ var_dump(get_included_files()); include(__DIR__."/014.inc"); var_dump(get_included_files()); -var_dump(get_included_files(1,1)); - include_once(__DIR__."/014.inc"); var_dump(get_included_files()); -var_dump(get_included_files(1)); - include(__DIR__."/014.inc"); var_dump(get_included_files()); @@ -31,18 +27,12 @@ array(2) { [1]=> string(%d) "%s" } - -Warning: get_included_files() expects exactly 0 parameters, 2 given in %s on line %d -NULL array(2) { [0]=> string(%d) "%s" [1]=> string(%d) "%s" } - -Warning: get_included_files() expects exactly 0 parameters, 1 given in %s on line %d -NULL array(2) { [0]=> string(%d) "%s" diff --git a/Zend/tests/015.phpt b/Zend/tests/015.phpt index ccf5e4ddb0..deea89d14d 100644 --- a/Zend/tests/015.phpt +++ b/Zend/tests/015.phpt @@ -3,9 +3,7 @@ trigger_error() tests --FILE-- <?php -var_dump(trigger_error()); var_dump(trigger_error("error")); -var_dump(trigger_error(array())); var_dump(trigger_error("error", -1)); var_dump(trigger_error("error", 0)); var_dump(trigger_error("error", E_USER_WARNING)); @@ -14,15 +12,9 @@ var_dump(trigger_error("error", E_USER_DEPRECATED)); echo "Done\n"; ?> --EXPECTF-- -Warning: trigger_error() expects at least 1 parameter, 0 given in %s on line %d -NULL - Notice: error in %s on line %d bool(true) -Warning: trigger_error() expects parameter 1 to be string, array given in %s on line %d -NULL - Warning: Invalid error type specified in %s on line %d bool(false) diff --git a/Zend/tests/017.phpt b/Zend/tests/017.phpt index ed1b2a38a5..619365cbce 100644 --- a/Zend/tests/017.phpt +++ b/Zend/tests/017.phpt @@ -3,8 +3,6 @@ builtin functions tests --FILE-- <?php -var_dump(get_resource_type()); -var_dump(get_resource_type("")); $fp = fopen(__FILE__, "r"); var_dump(get_resource_type($fp)); fclose($fp); @@ -14,11 +12,9 @@ var_dump(gettype(get_loaded_extensions())); var_dump(count(get_loaded_extensions())); var_dump(gettype(get_loaded_extensions(true))); var_dump(count(get_loaded_extensions(true))); -var_dump(get_loaded_extensions(true, true)); define("USER_CONSTANT", "test"); -var_dump(get_defined_constants(true, true)); var_dump(gettype(get_defined_constants(true))); var_dump(gettype(get_defined_constants())); var_dump(count(get_defined_constants())); @@ -29,11 +25,9 @@ function test () { var_dump(gettype(get_defined_functions())); var_dump(count(get_defined_functions())); -var_dump(get_declared_interfaces(true)); var_dump(gettype(get_declared_interfaces())); var_dump(count(get_declared_interfaces())); -var_dump(get_extension_funcs()); var_dump(get_extension_funcs(true)); var_dump(gettype(get_extension_funcs("standard"))); var_dump(count(get_extension_funcs("standard"))); @@ -44,36 +38,19 @@ var_dump(count(get_extension_funcs("zend"))); echo "Done\n"; ?> --EXPECTF-- -Warning: get_resource_type() expects exactly 1 parameter, 0 given in %s on line %d -NULL - -Warning: get_resource_type() expects parameter 1 to be resource, string given in %s on line %d -NULL string(6) "stream" string(7) "Unknown" string(5) "array" int(%d) string(5) "array" int(%d) - -Warning: get_loaded_extensions() expects at most 1 parameter, 2 given in %s on line %d -NULL - -Warning: get_defined_constants() expects at most 1 parameter, 2 given in %s on line %d -NULL string(5) "array" string(5) "array" int(%d) string(5) "array" int(%d) - -Warning: get_declared_interfaces() expects exactly 0 parameters, 1 given in %s on line %d -NULL string(5) "array" int(%d) - -Warning: get_extension_funcs() expects exactly 1 parameter, 0 given in %s on line %d -NULL bool(false) string(5) "array" int(%d) diff --git a/Zend/tests/018.phpt b/Zend/tests/018.phpt index 5ced729fce..97e53b1050 100644 --- a/Zend/tests/018.phpt +++ b/Zend/tests/018.phpt @@ -3,12 +3,8 @@ constant() tests --FILE-- <?php -var_dump(constant()); -var_dump(constant("", "")); var_dump(constant("")); -var_dump(constant(array())); - define("TEST_CONST", 1); var_dump(constant("TEST_CONST")); @@ -18,17 +14,8 @@ var_dump(constant("TEST_CONST2")); echo "Done\n"; ?> --EXPECTF-- -Warning: constant() expects exactly 1 parameter, 0 given in %s on line %d -NULL - -Warning: constant() expects exactly 1 parameter, 2 given in %s on line %d -NULL - Warning: constant(): Couldn't find constant in %s on line %d NULL - -Warning: constant() expects parameter 1 to be string, array given in %s on line %d -NULL int(1) string(4) "test" Done diff --git a/Zend/tests/020.phpt b/Zend/tests/020.phpt index 1e2bcff387..efc221cb4f 100644 --- a/Zend/tests/020.phpt +++ b/Zend/tests/020.phpt @@ -3,9 +3,7 @@ func_get_arg() invalid usage --FILE-- <?php -var_dump(func_get_arg(1,2,3)); var_dump(func_get_arg(1)); -var_dump(func_get_arg()); function bar() { var_dump(func_get_arg(1)); @@ -20,15 +18,9 @@ foo(1,2); echo "Done\n"; ?> --EXPECTF-- -Warning: func_get_arg() expects exactly 1 parameter, 3 given in %s on line %d -NULL - Warning: func_get_arg(): Called from the global scope - no function context in %s on line %d bool(false) -Warning: func_get_arg() expects exactly 1 parameter, 0 given in %s on line %d -NULL - Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d bool(false) Done diff --git a/Zend/tests/anonymous_func_001.phpt b/Zend/tests/anonymous_func_001.phpt deleted file mode 100644 index 97b91b6544..0000000000 --- a/Zend/tests/anonymous_func_001.phpt +++ /dev/null @@ -1,54 +0,0 @@ ---TEST-- -Testing calls to anonymous function ---FILE-- -<?php - -for ($i = 0; $i < 10; $i++) { - $a = create_function('', 'return '. $i .';'); - var_dump($a()); - - $b = "\0lambda_". ($i + 1); - var_dump($b()); -} - -?> ---EXPECTF-- -Deprecated: Function create_function() is deprecated in %s on line %d -int(0) -int(0) - -Deprecated: Function create_function() is deprecated in %s on line %d -int(1) -int(1) - -Deprecated: Function create_function() is deprecated in %s on line %d -int(2) -int(2) - -Deprecated: Function create_function() is deprecated in %s on line %d -int(3) -int(3) - -Deprecated: Function create_function() is deprecated in %s on line %d -int(4) -int(4) - -Deprecated: Function create_function() is deprecated in %s on line %d -int(5) -int(5) - -Deprecated: Function create_function() is deprecated in %s on line %d -int(6) -int(6) - -Deprecated: Function create_function() is deprecated in %s on line %d -int(7) -int(7) - -Deprecated: Function create_function() is deprecated in %s on line %d -int(8) -int(8) - -Deprecated: Function create_function() is deprecated in %s on line %d -int(9) -int(9) diff --git a/Zend/tests/anonymous_func_002.phpt b/Zend/tests/anonymous_func_002.phpt deleted file mode 100644 index 28adc357da..0000000000 --- a/Zend/tests/anonymous_func_002.phpt +++ /dev/null @@ -1,19 +0,0 @@ ---TEST-- -Testing anonymous function return as array key and accessing $GLOBALS ---FILE-- -<?php - -$test = create_function('$v', 'return $v;'); - -$arr = array(create_function('', 'return $GLOBALS["arr"];'), 2); - -var_dump($arr[$test(1)]); -var_dump($arr[$test(0)]() == $arr); - -?> ---EXPECTF-- -Deprecated: Function create_function() is deprecated in %s on line %d - -Deprecated: Function create_function() is deprecated in %s on line %d -int(2) -bool(true) diff --git a/Zend/tests/anonymous_func_003.phpt b/Zend/tests/anonymous_func_003.phpt deleted file mode 100644 index d2610310f7..0000000000 --- a/Zend/tests/anonymous_func_003.phpt +++ /dev/null @@ -1,16 +0,0 @@ ---TEST-- -Using throw $var with anonymous function return ---FILE-- -<?php - -try { - $a = create_function('', 'return new Exception("test");'); - throw $a(); -} catch (Exception $e) { - var_dump($e->getMessage() == 'test'); -} - -?> ---EXPECTF-- -Deprecated: Function create_function() is deprecated in %s on line %d -bool(true) diff --git a/Zend/tests/assert/bug70208.phpt b/Zend/tests/assert/bug70208.phpt deleted file mode 100644 index 6b7dfaeb33..0000000000 --- a/Zend/tests/assert/bug70208.phpt +++ /dev/null @@ -1,24 +0,0 @@ ---TEST-- -Bug #70208 (scope information must be preserved with assert()) ---FILE-- -<?php - -function non_class_scope() { - return true; -} - -class test { - protected $prop = 1; - - public function __construct() { - assert('non_class_scope();'); - var_dump($this->prop); - } -} - -new test; - -?> ---EXPECTF-- -Deprecated: assert(): Calling assert() with a string argument is deprecated in %s on line %d -int(1) diff --git a/Zend/tests/assert/indirect_var_access_misoptimization.phpt b/Zend/tests/assert/indirect_var_access_misoptimization.phpt deleted file mode 100644 index 02327f30c0..0000000000 --- a/Zend/tests/assert/indirect_var_access_misoptimization.phpt +++ /dev/null @@ -1,21 +0,0 @@ ---TEST-- -Misoptimization when variable is modified by assert() ---INI-- -zend.assertions=1 ---FILE-- -<?php - -function test() { - $i = 0; - assert('$i = new stdClass'); - $i += 1; - var_dump($i); -} -test(); - -?> ---EXPECTF-- -Deprecated: assert(): Calling assert() with a string argument is deprecated in %s on line %d - -Notice: Object of class stdClass could not be converted to number in %s on line %d -int(2) diff --git a/Zend/tests/bug26697.phpt b/Zend/tests/bug26697.phpt index fe269c0364..c0a4850e55 100644 --- a/Zend/tests/bug26697.phpt +++ b/Zend/tests/bug26697.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #26697 (calling class_exists on a nonexistent class in __autoload results in segfault) +Bug #26697 (calling class_exists on a nonexistent class in autoloader results in segfault) --FILE-- <?php diff --git a/Zend/tests/bug27669.phpt b/Zend/tests/bug27669.phpt index 97b15590e2..747593031f 100644 --- a/Zend/tests/bug27669.phpt +++ b/Zend/tests/bug27669.phpt @@ -3,7 +3,7 @@ Bug #27669 (PHP 5 didn't support all possibilities for calling static methods dy --FILE-- <?php class A { - function hello() { + static function hello() { echo "Hello World\n"; } } @@ -12,6 +12,5 @@ Bug #27669 (PHP 5 didn't support all possibilities for calling static methods dy ?> ===DONE=== --EXPECTF-- -Deprecated: Non-static method A::hello() should not be called statically in %s on line %d Hello World ===DONE=== diff --git a/Zend/tests/bug29890.phpt b/Zend/tests/bug29890.phpt index 1fdcdc4291..6f1e874882 100644 --- a/Zend/tests/bug29890.phpt +++ b/Zend/tests/bug29890.phpt @@ -2,7 +2,7 @@ Bug #29890 (crash if error handler fails) --FILE-- <?php -function customErrorHandler($fErrNo,$fErrStr,$fErrFile,$fErrLine,$fClass) { +function customErrorHandler($fErrNo,$fErrStr,$fErrFile,$fErrLine) { echo "error :".$fErrStr."\n"; } diff --git a/Zend/tests/bug29896.phpt b/Zend/tests/bug29896.phpt index 35a92d459c..d6ae8e7f7f 100644 --- a/Zend/tests/bug29896.phpt +++ b/Zend/tests/bug29896.phpt @@ -2,7 +2,7 @@ Bug #29896 (Backtrace argument list out of sync) --FILE-- <?php -function userErrorHandler($num, $msg, $file, $line, $vars) +function userErrorHandler($num, $msg, $file, $line) { debug_print_backtrace(); } @@ -22,6 +22,6 @@ function GenerateError2($A1) GenerateError2("Test2"); ?> --EXPECTF-- -#0 userErrorHandler(8, Undefined variable: b, %sbug29896.php, 11, Array ([A1] => Test1)) called at [%sbug29896.php:11] +#0 userErrorHandler(8, Undefined variable: b, %sbug29896.php, 11) called at [%sbug29896.php:11] #1 GenerateError1(Test1) called at [%sbug29896.php:16] #2 GenerateError2(Test2) called at [%sbug29896.php:19] diff --git a/Zend/tests/bug31102.phpt b/Zend/tests/bug31102.phpt index fd6da0f7c2..624eee52ba 100644 --- a/Zend/tests/bug31102.phpt +++ b/Zend/tests/bug31102.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #31102 (Exception not handled when thrown inside __autoload()) +Bug #31102 (Exception not handled when thrown inside autoloader) --FILE-- <?php diff --git a/Zend/tests/bug31720.phpt b/Zend/tests/bug31720.phpt index c4680a4789..9031dec030 100644 --- a/Zend/tests/bug31720.phpt +++ b/Zend/tests/bug31720.phpt @@ -4,11 +4,14 @@ Bug #31720 (Invalid object callbacks not caught in array_walk()) <?php $array = array('at least one element'); -array_walk($array, array($nonesuchvar,'show')); +try { + array_walk($array, array($nonesuchvar,'show')); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} ?> ===DONE=== --EXPECTF-- Notice: Undefined variable: nonesuchvar in %s on line %d - -Warning: array_walk() expects parameter 2 to be a valid callback, first array member is not a valid class name or object in %s on line %d +array_walk() expects parameter 2 to be a valid callback, first array member is not a valid class name or object ===DONE=== diff --git a/Zend/tests/bug33116.phpt b/Zend/tests/bug33116.phpt index 13aae6611e..b336171165 100644 --- a/Zend/tests/bug33116.phpt +++ b/Zend/tests/bug33116.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #33116 (crash when assigning class name to global variable in __autoload) +Bug #33116 (crash when assigning class name to global variable in autoloader) --FILE-- <?php spl_autoload_register(function ($class) { diff --git a/Zend/tests/bug34786.phpt b/Zend/tests/bug34786.phpt index 18642848d8..ef0627633f 100644 --- a/Zend/tests/bug34786.phpt +++ b/Zend/tests/bug34786.phpt @@ -10,13 +10,13 @@ function bar() { echo "bar: ".error_reporting()."\n"; } -error_reporting(1); +error_reporting(E_WARNING); echo "before: ".error_reporting()."\n"; @foo(1,@bar(),3); echo "after: ".error_reporting()."\n"; ?> --EXPECT-- -before: 1 +before: 2 bar: 0 foo: 0 -after: 1 +after: 2 diff --git a/Zend/tests/bug35017.phpt b/Zend/tests/bug35017.phpt index 9944df55e0..8a747be7e1 100644 --- a/Zend/tests/bug35017.phpt +++ b/Zend/tests/bug35017.phpt @@ -13,7 +13,7 @@ try { } catch(Exception $e) { echo "This Exception should be caught\n"; } -function errorHandler($errno, $errstr, $errfile, $errline, $vars) { +function errorHandler($errno, $errstr, $errfile, $errline) { throw new Exception('Some Exception'); } ?> diff --git a/Zend/tests/bug35437.phpt b/Zend/tests/bug35437.phpt deleted file mode 100644 index 4f61e4fbfd..0000000000 --- a/Zend/tests/bug35437.phpt +++ /dev/null @@ -1,27 +0,0 @@ ---TEST-- -Bug #35437 (Segfault or Invalid Opcode 137/1/4) ---FILE-- -<?php -function err2exception($errno, $errstr) -{ - throw new Exception("Error occuried: " . $errstr); -} - -set_error_handler('err2exception'); - -class TestClass -{ - function testMethod() - { - $GLOBALS['t'] = new stdClass; - } -} - -try { - TestClass::testMethod(); -} catch (Exception $e) { - echo "Caught: ".$e->getMessage()."\n"; -} -?> ---EXPECT-- -Caught: Error occuried: Non-static method TestClass::testMethod() should not be called statically diff --git a/Zend/tests/bug37138.phpt b/Zend/tests/bug37138.phpt index 4a084d4bb1..c0aa1fdfa8 100644 --- a/Zend/tests/bug37138.phpt +++ b/Zend/tests/bug37138.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #37138 (__autoload tries to load callback'ed self and parent) +Bug #37138 (autoloader tries to load callback'ed self and parent) --FILE-- <?php spl_autoload_register(function ($CN) { var_dump ($CN); }); diff --git a/Zend/tests/bug37811.phpt b/Zend/tests/bug37811.phpt index 96645d0354..8321459d5d 100644 --- a/Zend/tests/bug37811.phpt +++ b/Zend/tests/bug37811.phpt @@ -23,6 +23,7 @@ string(3) "Foo" Warning: Constants may only evaluate to scalar values, arrays or resources in %sbug37811.php on line %d -Warning: Use of undefined constant Baz - assumed 'Baz' (this will throw an Error in a future version of PHP) in %sbug37811.php on line %d -string(3) "Baz" -===DONE=== +Fatal error: Uncaught Error: Undefined constant 'Baz' in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/bug38047.phpt b/Zend/tests/bug38047.phpt deleted file mode 100644 index e6eeb6631d..0000000000 --- a/Zend/tests/bug38047.phpt +++ /dev/null @@ -1,51 +0,0 @@ ---TEST-- -Bug #38047 ("file" and "line" sometimes not set in backtrace from inside error handler) ---FILE-- -<?php -error_reporting(E_ALL); -set_error_handler('kalus_error_handler'); -ini_set("display_errors", "on"); - -class A { - function A_ftk($a) { - } -} - -function kalus_error_handler($error_code, $error_string, $filename, $line, $symbols) { - echo "$error_string\n"; - get_error_context(); -} - -function get_error_context() { - $backtrace = debug_backtrace(); - $n = 1; - foreach ($backtrace as $call) { - echo $n++." "; - if (isset($call["file"])) { - echo $call["file"]; - if (isset($call["line"])) { - echo ":".$call["line"]; - } - } - if (isset($call["function"])) { - echo " ".$call["function"]."()"; - } - echo "\n"; - } - echo "\n"; -} - -//This will not create file and line items for the call into the error handler -$page["name"] = A::A_ftk(); -?> ---EXPECTF-- -Non-static method A::A_ftk() should not be called statically -1 %sbug38047.php:13 get_error_context() -2 %sbug38047.php:36 kalus_error_handler() - - -Fatal error: Uncaught ArgumentCountError: Too few arguments to function A::A_ftk(), 0 passed in %sbug38047.php on line 36 and exactly 1 expected in %sbug38047.php:7 -Stack trace: -#0 %sbug38047.php(36): A::A_ftk() -#1 {main} - thrown in %sbug38047.php on line 7 diff --git a/Zend/tests/bug38942.phpt b/Zend/tests/bug38942.phpt deleted file mode 100644 index d0335b1071..0000000000 --- a/Zend/tests/bug38942.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -Bug #38942 (Double old-style-ctor inheritance) ---FILE-- -<?php -class foo { - public function foo() {} -} - -class bar extends foo { -} -print_r(get_class_methods("bar")); -?> ---EXPECTF-- -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; foo has a deprecated constructor in %s on line %d -Array -( - [0] => foo -) diff --git a/Zend/tests/bug39003.phpt b/Zend/tests/bug39003.phpt index dc1c69e8c7..791e11b614 100644 --- a/Zend/tests/bug39003.phpt +++ b/Zend/tests/bug39003.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #39003 (__autoload() is called for type hinting) +Bug #39003 (autoloader is called for type hinting) --FILE-- <?php diff --git a/Zend/tests/bug39127.phpt b/Zend/tests/bug39127.phpt deleted file mode 100644 index 31fb6d27d5..0000000000 --- a/Zend/tests/bug39127.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -Bug #39127 (Old-style constructor fallbacks produce strange results) ---FILE-- -<?php - -class a { function a() { var_dump("a::a() called"); } } -class b extends a {} - -$b = new b; -var_dump(is_callable(array($b,"a"))); -var_dump(is_callable(array($b,"b"))); -var_dump(is_callable(array($b,"__construct"))); - -echo "Done\n"; -?> ---EXPECTF-- -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; a has a deprecated constructor in %s on line %d -string(13) "a::a() called" -bool(true) -bool(false) -bool(false) -Done diff --git a/Zend/tests/bug40236.phpt b/Zend/tests/bug40236.phpt index 81cd56f71f..204b117099 100644 --- a/Zend/tests/bug40236.phpt +++ b/Zend/tests/bug40236.phpt @@ -2,7 +2,6 @@ Bug #40236 (php -a function allocation eats memory) --SKIPIF-- <?php -if (php_sapi_name() != "cli") die("skip CLI only"); if (extension_loaded("readline")) die("skip Test doesn't support readline"); ?> --FILE-- diff --git a/Zend/tests/bug40621.phpt b/Zend/tests/bug40621.phpt index b56a28e58b..8650fd56fa 100644 --- a/Zend/tests/bug40621.phpt +++ b/Zend/tests/bug40621.phpt @@ -15,10 +15,7 @@ Foo::get(); echo "Done\n"; ?> --EXPECTF-- -Deprecated: Non-static method Foo::get() should not be called statically in %s on line %d - -Fatal error: Uncaught Error: Non-static method Foo::__construct() cannot be called statically in %s:%d +Fatal error: Uncaught Error: Non-static method Foo::get() cannot be called statically in %s:%d Stack trace: -#0 %s(%d): Foo::get() -#1 {main} +#0 {main} thrown in %s on line %d diff --git a/Zend/tests/bug40784.phpt b/Zend/tests/bug40784.phpt deleted file mode 100644 index ac2b2331b2..0000000000 --- a/Zend/tests/bug40784.phpt +++ /dev/null @@ -1,25 +0,0 @@ ---TEST-- -Bug #40784 (Case sensivity in constructor's fallback) ---FILE-- -<?php - -class A { - function A () { echo "I'm A\n"; } -} - -class B extends A { - function __construct() { - parent::__construct(); - parent::__constrUct(); - } -} - -$b = new B; - -echo "Done\n"; -?> ---EXPECTF-- -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; A has a deprecated constructor in %s on line %d -I'm A -I'm A -Done diff --git a/Zend/tests/bug41209.phpt b/Zend/tests/bug41209.phpt index 3924f99ac8..f61df73d20 100644 --- a/Zend/tests/bug41209.phpt +++ b/Zend/tests/bug41209.phpt @@ -41,6 +41,6 @@ echo "Done\n"; --EXPECTF-- Fatal error: Uncaught ErrorException: Undefined variable: id in %s:%d Stack trace: -#0 %s(%d): env::errorHandler(8, '%s', '%s', 34, Array) +#0 %s(%d): env::errorHandler(8, '%s', '%s', 34) #1 {main} thrown in %s on line %d diff --git a/Zend/tests/bug43323.phpt b/Zend/tests/bug43323.phpt deleted file mode 100644 index 74abe766e5..0000000000 --- a/Zend/tests/bug43323.phpt +++ /dev/null @@ -1,14 +0,0 @@ ---TEST-- -Bug #43323 (Wrong count abstract methods) ---FILE-- -<?php -abstract class bar { - abstract public function bar(); -} - -class foo extends bar { -} ---EXPECTF-- -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; bar has a deprecated constructor in %s on line %d - -Fatal error: Class foo contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (bar::bar) in %sbug43323.php on line 7 diff --git a/Zend/tests/bug43344_1.phpt b/Zend/tests/bug43344_1.phpt index 4635240699..28af70dc67 100644 --- a/Zend/tests/bug43344_1.phpt +++ b/Zend/tests/bug43344_1.phpt @@ -3,6 +3,8 @@ Bug #43344.1 (Wrong error message for undefined namespace constant) --FILE-- <?php namespace Foo; +use Error; + function f1($a=bar) { return $a; } @@ -13,20 +15,31 @@ function f3($a=array(bar=>0)) { reset($a); return key($a); } -echo bar."\n"; -echo f1()."\n"; -echo f2()."\n"; -echo f3()."\n"; -?> ---EXPECTF-- -Warning: Use of undefined constant bar - assumed 'bar' (this will throw an Error in a future version of PHP) in %sbug43344_1.php on line 13 -bar -Warning: Use of undefined constant bar - assumed 'bar' (this will throw an Error in a future version of PHP) in %sbug43344_1.php on line 3 -bar - -Warning: Use of undefined constant bar - assumed 'bar' (this will throw an Error in a future version of PHP) in %sbug43344_1.php on line 6 -bar +try { + echo bar."\n"; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + echo f1()."\n"; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + echo f2()."\n"; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + echo f3()."\n"; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} -Warning: Use of undefined constant bar - assumed 'bar' (this will throw an Error in a future version of PHP) in %sbug43344_1.php on line 9 -bar +?> +--EXPECT-- +Undefined constant 'Foo\bar' +Undefined constant 'Foo\bar' +Undefined constant 'Foo\bar' +Undefined constant 'Foo\bar' diff --git a/Zend/tests/bug45186.phpt b/Zend/tests/bug45186.phpt index 411c2ea072..1c25a86921 100644 --- a/Zend/tests/bug45186.phpt +++ b/Zend/tests/bug45186.phpt @@ -31,10 +31,14 @@ $x->test(); call_user_func(array('BAR','x')); call_user_func('BAR::www'); -call_user_func('self::y'); +try { + call_user_func('self::y'); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} ?> ---EXPECTF-- +--EXPECT-- __call: string(3) "ABC" __call: @@ -50,5 +54,4 @@ string(1) "y" ok __callstatic: string(3) "www" - -Warning: call_user_func() expects parameter 1 to be a valid callback, cannot access self:: when no class scope is active in %sbug45186.php on line 31 +call_user_func() expects parameter 1 to be a valid callback, cannot access self:: when no class scope is active diff --git a/Zend/tests/bug45186_2.phpt b/Zend/tests/bug45186_2.phpt index 7c813a909c..cb098136a0 100644 --- a/Zend/tests/bug45186_2.phpt +++ b/Zend/tests/bug45186_2.phpt @@ -26,11 +26,19 @@ $x = new bar; $x->test(); call_user_func(array('BAR','x')); -call_user_func('BAR::www'); -call_user_func('self::y'); +try { + call_user_func('BAR::www'); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +try { + call_user_func('self::y'); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} ?> ---EXPECTF-- +--EXPECT-- __call: string(3) "ABC" __call: @@ -44,7 +52,5 @@ string(1) "y" __call: string(1) "y" ok - -Warning: call_user_func() expects parameter 1 to be a valid callback, class 'bar' does not have a method 'www' in %s on line %d - -Warning: call_user_func() expects parameter 1 to be a valid callback, cannot access self:: when no class scope is active in %sbug45186_2.php on line 27 +call_user_func() expects parameter 1 to be a valid callback, class 'bar' does not have a method 'www' +call_user_func() expects parameter 1 to be a valid callback, cannot access self:: when no class scope is active diff --git a/Zend/tests/bug45805.phpt b/Zend/tests/bug45805.phpt index d63e658868..86cea70373 100644 --- a/Zend/tests/bug45805.phpt +++ b/Zend/tests/bug45805.phpt @@ -38,7 +38,7 @@ $o->bar(); --EXPECTF-- Fatal error: Uncaught RuntimeException in %sbug45805.php:%d Stack trace: -#0 %sbug45805.php(%d): PHPUnit_Util_ErrorHandler::handleError(8, 'Only variables ...', '%s', %d, Array) +#0 %sbug45805.php(%d): PHPUnit_Util_ErrorHandler::handleError(8, 'Only variables ...', '%s', %d) #1 [internal function]: B->foo() #2 %sbug45805.php(%d): ReflectionMethod->invoke(Object(B)) #3 %sbug45805.php(%d): B->bar() diff --git a/Zend/tests/bug46106.phpt b/Zend/tests/bug46106.phpt index f18c25a6c2..b0e769e05a 100644 --- a/Zend/tests/bug46106.phpt +++ b/Zend/tests/bug46106.phpt @@ -15,8 +15,13 @@ function test($x) { } $x = new ReflectionFunction('str_pad'); -test($x); +try { + test($x); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} ?> DONE --EXPECT-- +str_pad() expects at least 2 parameters, 1 given DONE diff --git a/Zend/tests/bug46304.phpt b/Zend/tests/bug46304.phpt index 9898838907..f8b9a0b525 100644 --- a/Zend/tests/bug46304.phpt +++ b/Zend/tests/bug46304.phpt @@ -6,9 +6,6 @@ Bug #46304 (defining namespaced constant using define()) define('NS1\ns2\const1','value1'); define('ns1\ns2\const2','value2'); define('ns1\NS2\coNSt3','value3'); -define('NS1\ns2\const4','value4', true); -define('ns1\ns2\const5','value5', true); -define('ns1\NS2\coNSt6','value6', true); print NS1\ns2\const1 . "\n"; print ns1\ns2\const1 . "\n"; @@ -22,29 +19,9 @@ print NS1\ns2\coNSt3 . "\n"; print ns1\ns2\coNSt3 . "\n"; print ns1\ns2\coNSt3 . "\n"; -print NS1\ns2\const4 . "\n"; -print ns1\ns2\const4 . "\n"; -print ns1\NS2\const4 . "\n"; -print ns1\ns2\coNSt4 . "\n"; - -print NS1\ns2\const5 . "\n"; -print ns1\ns2\const5 . "\n"; -print ns1\NS2\const5 . "\n"; -print ns1\ns2\coNSt5 . "\n"; - -print NS1\ns2\const6 . "\n"; -print ns1\ns2\const6 . "\n"; -print ns1\NS2\const6 . "\n"; -print ns1\ns2\coNSt6 . "\n"; - print NS1\ns2\coNSt1 . "\n"; ?> --EXPECTF-- -Deprecated: define(): Declaration of case-insensitive constants is deprecated in %s on line 6 - -Deprecated: define(): Declaration of case-insensitive constants is deprecated in %s on line 7 - -Deprecated: define(): Declaration of case-insensitive constants is deprecated in %s on line 8 value1 value1 value1 @@ -54,28 +31,6 @@ value2 value3 value3 value3 -value4 -value4 -value4 - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "NS1\ns2\const4" in %s on line 25 -value4 -value5 -value5 -value5 - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "ns1\ns2\const5" in %s on line 30 -value5 - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "ns1\NS2\coNSt6" in %s on line 32 -value6 - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "ns1\NS2\coNSt6" in %s on line 33 -value6 - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "ns1\NS2\coNSt6" in %s on line 34 -value6 -value6 Fatal error: Uncaught Error: Undefined constant 'NS1\ns2\coNSt1' in %sbug46304.php:%d Stack trace: diff --git a/Zend/tests/bug47054.phpt b/Zend/tests/bug47054.phpt index 9e89c2c208..f607365bdc 100644 --- a/Zend/tests/bug47054.phpt +++ b/Zend/tests/bug47054.phpt @@ -24,8 +24,6 @@ $c->s(); get_called_class(); -D::m(); - ?> --EXPECTF-- Called class: D @@ -33,11 +31,3 @@ Called class: C Called class: C Warning: get_called_class() called from outside a class in %s on line %d - -Deprecated: Non-static method D::m() should not be called statically in %s on line %d - -Fatal error: Uncaught Error: Using $this when not in object context in %s:%d -Stack trace: -#0 %s(%d): D::m() -#1 {main} - thrown in %s on line %d diff --git a/Zend/tests/bug47320.phpt b/Zend/tests/bug47320.phpt deleted file mode 100644 index 47db35edac..0000000000 --- a/Zend/tests/bug47320.phpt +++ /dev/null @@ -1,26 +0,0 @@ ---TEST-- -Bug #47320 ($php_errormsg out of scope in functions) ---INI-- -display_errors=0 -track_errors=1 ---FILE-- -<?php -if (!@substr('no 2nd parameter')) { - echo '$php_errormsg in global: ' . $php_errormsg . "\n"; -} - -function foo() { - if (!@strpos('no 2nd parameter')) { - echo '$php_errormsg in function: ' . $php_errormsg . "\n"; - - echo '$GLOBALS[php_errormsg] in function: ' . - $GLOBALS['php_errormsg'] . "\n"; - } -} - -foo(); -?> ---EXPECT-- -$php_errormsg in global: substr() expects at least 2 parameters, 1 given -$php_errormsg in function: strpos() expects at least 2 parameters, 1 given -$GLOBALS[php_errormsg] in function: substr() expects at least 2 parameters, 1 given diff --git a/Zend/tests/bug47572.phpt b/Zend/tests/bug47572.phpt index 67bb3ec111..7a44cc6e7f 100644 --- a/Zend/tests/bug47572.phpt +++ b/Zend/tests/bug47572.phpt @@ -14,4 +14,7 @@ $foo = new Foo(); ?> --EXPECTF-- -Warning: Use of undefined constant FOO - assumed 'FOO' (this will throw an Error in a future version of PHP) in %s on line %d +Fatal error: Uncaught Error: Undefined constant 'FOO' in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/bug48004.phpt b/Zend/tests/bug48004.phpt index 5968876520..c8dd0b3880 100644 --- a/Zend/tests/bug48004.phpt +++ b/Zend/tests/bug48004.phpt @@ -2,7 +2,7 @@ Bug #48004 (Error handler prevents creation of default object) --FILE-- <?php -function error_handler($errno, $errstr, $errfile, $errline, $errcontext) { +function error_handler($errno, $errstr, $errfile, $errline) { return true; } diff --git a/Zend/tests/bug48533.phpt b/Zend/tests/bug48533.phpt index 4fa49a2f22..3dfbc658ec 100644 --- a/Zend/tests/bug48533.phpt +++ b/Zend/tests/bug48533.phpt @@ -26,8 +26,8 @@ $x->a(); $x->b(); $x->c(); $x::a(); -$x::b(); $x::c(); +$x::b(); ?> --EXPECTF-- @@ -35,7 +35,9 @@ string(9) "__call::a" int(2) string(9) "__call::c" string(15) "__callStatic::a" - -Deprecated: Non-static method foo::b() should not be called statically in %s on line %d -int(2) string(15) "__callStatic::c" + +Fatal error: Uncaught Error: Non-static method foo::b() cannot be called statically in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/bug48693.phpt b/Zend/tests/bug48693.phpt deleted file mode 100644 index f916b6407b..0000000000 --- a/Zend/tests/bug48693.phpt +++ /dev/null @@ -1,52 +0,0 @@ ---TEST-- -Bug #48693 (Double declaration of __lambda_func when lambda wrongly formatted) ---FILE-- -<?php - -try { - $x = create_function('', 'return 1; }'); -} catch (ParseError $e) { - echo "$e\n\n"; -} -try { - $y = create_function('', 'function a() { }; return 2;'); -} catch (ParseError $e) { - echo "$e\n\n"; -} -try { - $z = create_function('', '{'); -} catch (ParseError $e) { - echo "$e\n\n"; -} -try { - $w = create_function('', 'return 3;'); -} catch (ParseError $e) { - echo "$e\n\n"; -} - -var_dump( - $y(), - $w() -); - -?> ---EXPECTF-- -Deprecated: Function create_function() is deprecated in %s on line %d -ParseError: 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} - - -Deprecated: Function create_function() is deprecated in %s on line %d - -Deprecated: Function create_function() is deprecated in %s on line %d -ParseError: syntax error, unexpected end of file in %sbug48693.php(14) : runtime-created function:1 -Stack trace: -#0 %sbug48693.php(14): create_function('', '{') -#1 {main} - - -Deprecated: Function create_function() is deprecated in %s on line %d -int(2) -int(3) diff --git a/Zend/tests/bug49908.phpt b/Zend/tests/bug49908.phpt index 2f33080258..eda913b80e 100644 --- a/Zend/tests/bug49908.phpt +++ b/Zend/tests/bug49908.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #49908 (throwing exception in __autoload crashes when interface is not defined) +Bug #49908 (throwing exception in autoloader crashes when interface is not defined) --FILE-- <?php diff --git a/Zend/tests/bug50261.phpt b/Zend/tests/bug50261.phpt deleted file mode 100644 index 321e9cfb8b..0000000000 --- a/Zend/tests/bug50261.phpt +++ /dev/null @@ -1,39 +0,0 @@ ---TEST-- -Bug #50261 (Crash When Calling Parent Constructor with call_user_func()) ---FILE-- -<?php - -class testClass { - function testClass($x) { - echo __METHOD__, " (". $x . ")\n"; - } -} - -class testClass2 extends testClass { - function __construct() { - static $x = 0; - - if ($x) { - print "Infinite loop...\n"; - } else { - $x++; - - parent::__construct(1); - testclass::__construct(2); - call_user_func(array('parent', '__construct'), 3); - call_user_func(array('testclass', '__construct'), 4); - call_user_func(array('testclass', 'testclass'), 5); - } - } -} - -new testClass2; - -?> ---EXPECTF-- -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; testClass has a deprecated constructor in %s on line %d -testClass::testClass (1) -testClass::testClass (2) -testClass::testClass (3) -testClass::testClass (4) -testClass::testClass (5) diff --git a/Zend/tests/bug51394.phpt b/Zend/tests/bug51394.phpt index e2d260b2b2..f91d2720a1 100644 --- a/Zend/tests/bug51394.phpt +++ b/Zend/tests/bug51394.phpt @@ -15,6 +15,6 @@ $a = $empty($b); --EXPECTF-- Fatal error: Uncaught Exception: error! in %sbug51394.php:%d Stack trace: -#0 %sbug51394.php(%d): eh(8, 'Undefined varia%s', '%s', %d, Array) +#0 %sbug51394.php(%d): eh(8, 'Undefined varia%s', '%s', %d) #1 {main} thrown in %sbug51394.php on line %d diff --git a/Zend/tests/bug51827.phpt b/Zend/tests/bug51827.phpt index 0834749454..77bdc069c3 100644 --- a/Zend/tests/bug51827.phpt +++ b/Zend/tests/bug51827.phpt @@ -16,4 +16,8 @@ register_shutdown_function('exploDe'); --EXPECTF-- int(1) -Warning: explode() expects at least 2 parameters, 0 given in Unknown on line %d +Fatal error: Uncaught ArgumentCountError: explode() expects at least 2 parameters, 0 given in [no active file]:0 +Stack trace: +#0 [internal function]: explode() +#1 {main} + thrown in [no active file] on line 0 diff --git a/Zend/tests/bug52051.phpt b/Zend/tests/bug52051.phpt deleted file mode 100644 index acfddbc36d..0000000000 --- a/Zend/tests/bug52051.phpt +++ /dev/null @@ -1,34 +0,0 @@ ---TEST-- -Bug #52051 (handling of case sensitivity of old-style constructors changed in 5.3+) ---FILE-- -<?php - -class AA { - function AA() { echo "foo\n"; } -} -class bb extends AA {} -class CC extends bb { - function CC() { parent::bb(); } -} -new CC(); - -class A { - function A() { echo "bar\n"; } -} -class B extends A {} -class C extends B { - function C() { parent::B(); } -} -new C(); - -?> ---EXPECTF-- -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; AA has a deprecated constructor in %s on line %d - -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; CC has a deprecated constructor in %s on line %d - -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; A has a deprecated constructor in %s on line %d - -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; C has a deprecated constructor in %s on line %d -foo -bar diff --git a/Zend/tests/bug52160.phpt b/Zend/tests/bug52160.phpt deleted file mode 100644 index a0e5a9d7ae..0000000000 --- a/Zend/tests/bug52160.phpt +++ /dev/null @@ -1,34 +0,0 @@ ---TEST-- -Bug #52160 (Invalid E_STRICT redefined constructor error) ---FILE-- -<?php - -class bar { - function __construct() { } - static function bar() { - var_dump(1); - } -} - -bar::bar(); - -class foo { - static function foo() { - var_dump(2); - } - function __construct() { } -} - -foo::foo(); - -class baz { - static function baz() { - var_dump(3); - } -} - -?> ---EXPECTF-- -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; baz has a deprecated constructor in %s on line %d - -Fatal error: Constructor baz::baz() cannot be static in %s on line %d diff --git a/Zend/tests/bug54585.phpt b/Zend/tests/bug54585.phpt deleted file mode 100644 index deabe55af8..0000000000 --- a/Zend/tests/bug54585.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -Bug #54585 (track_errors causes segfault) ---INI-- -track_errors=On ---FILE-- -<?php -function testing($source) { - unset($source[$cos]); -} -testing($_GET); -echo "ok\n"; -?> ---EXPECTF-- -Deprecated: Directive 'track_errors' is deprecated in Unknown on line 0 - -Notice: Undefined variable: cos in %sbug54585.php on line 3 -ok diff --git a/Zend/tests/bug60909_1.phpt b/Zend/tests/bug60909_1.phpt index e4c07face1..d674490302 100644 --- a/Zend/tests/bug60909_1.phpt +++ b/Zend/tests/bug60909_1.phpt @@ -13,7 +13,7 @@ require 'notfound.php'; error(require(notfound.php): failed to open stream: %s) Warning: Uncaught Exception: Foo in %sbug60909_1.php:5 Stack trace: -#0 %sbug60909_1.php(8): {closure}(2, 'require(notfoun...', '%s', 8, Array) +#0 %sbug60909_1.php(8): {closure}(2, 'require(notfoun...', '%s', 8) #1 %sbug60909_1.php(8): require() #2 {main} thrown in %sbug60909_1.php on line 5 diff --git a/Zend/tests/bug60978.phpt b/Zend/tests/bug60978.phpt index 676808c7a3..5dc6fe31e7 100644 --- a/Zend/tests/bug60978.phpt +++ b/Zend/tests/bug60978.phpt @@ -1,11 +1,5 @@ --TEST-- Bug #60978 (exit code incorrect) ---SKIPIF-- -<?php - if ("cli" != php_sapi_name()) { - echo "skip CLI only"; - } -?> --FILE-- <?php $php = getenv('TEST_PHP_EXECUTABLE'); diff --git a/Zend/tests/bug61011.phpt b/Zend/tests/bug61011.phpt index dc0aca64f8..b9088c68f1 100644 --- a/Zend/tests/bug61011.phpt +++ b/Zend/tests/bug61011.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #61011 (Crash when an exception is thrown by __autoload accessing a static property) +Bug #61011 (Crash when an exception is thrown by autoloader accessing a static property) --FILE-- <?php spl_autoload_register(function ($name) { diff --git a/Zend/tests/bug61767.phpt b/Zend/tests/bug61767.phpt index 5e949706e8..3bc1e49d09 100644 --- a/Zend/tests/bug61767.phpt +++ b/Zend/tests/bug61767.phpt @@ -19,7 +19,7 @@ Error handler called (Undefined variable: undefined) Fatal error: Uncaught ErrorException: Undefined variable: undefined in %sbug61767.php:%d Stack trace: -#0 %sbug61767.php(%d): {closure}(%s, 'Undefined varia...', '%s', %d, Array) +#0 %sbug61767.php(%d): {closure}(%s, 'Undefined varia...', '%s', %d) #1 {main} thrown in %sbug61767.php on line %d Shutting down diff --git a/Zend/tests/bug64960.phpt b/Zend/tests/bug64960.phpt index 52af0bbe32..4ee4042617 100644 --- a/Zend/tests/bug64960.phpt +++ b/Zend/tests/bug64960.phpt @@ -33,7 +33,7 @@ Notice: ob_end_flush(): failed to delete and flush buffer. No buffer to delete o Fatal error: Uncaught Exception in %sbug64960.php:19 Stack trace: -#0 [internal function]: {closure}(8, 'ob_end_clean():...', '%s', 9, Array) +#0 [internal function]: {closure}(8, 'ob_end_clean():...', '%s', 9) #1 %sbug64960.php(9): ob_end_clean() #2 [internal function]: ExceptionHandler->__invoke(Object(Exception)) #3 {main} diff --git a/Zend/tests/bug66218.phpt b/Zend/tests/bug66218.phpt index d800605ac8..db3c7c655a 100644 --- a/Zend/tests/bug66218.phpt +++ b/Zend/tests/bug66218.phpt @@ -2,7 +2,6 @@ Bug #66218 zend_register_functions breaks reflection --SKIPIF-- <?php -if (PHP_SAPI != "cli") die("skip CLI only test"); if (!function_exists("dl")) die("skip need dl"); ?> --FILE-- diff --git a/Zend/tests/bug67858.phpt b/Zend/tests/bug67858.phpt deleted file mode 100644 index 1186cd6a6f..0000000000 --- a/Zend/tests/bug67858.phpt +++ /dev/null @@ -1,21 +0,0 @@ ---TEST-- -Bug #67858: Leak when $php_errormsg already set ---INI-- -track_errors=1 -error_reporting=E_ALL ---FILE-- -<?php - -function f() { - $php_errormsg = [1, 2, 3]; - echo $var; - var_dump($php_errormsg); -} -f(); - -?> ---EXPECTF-- -Deprecated: Directive 'track_errors' is deprecated in Unknown on line 0 - -Notice: Undefined variable: var in %s on line %d -string(23) "Undefined variable: var" diff --git a/Zend/tests/bug69388.phpt b/Zend/tests/bug69388.phpt index bf0c0a3c39..3846cca4ca 100644 --- a/Zend/tests/bug69388.phpt +++ b/Zend/tests/bug69388.phpt @@ -3,7 +3,7 @@ Bug #69388: Use after free on recursive calls to PHP compiler --FILE-- <?php -function handle_error($code, $message, $file, $line, $context) { +function handle_error($code, $message, $file, $line) { if (!function_exists("bla")) { eval('function bla($s) {echo "$s\n";}'); } diff --git a/Zend/tests/bug69388_2.phpt b/Zend/tests/bug69388_2.phpt index b55153b492..40b14e0257 100644 --- a/Zend/tests/bug69388_2.phpt +++ b/Zend/tests/bug69388_2.phpt @@ -2,7 +2,7 @@ Bug #69388 - Variation --FILE-- <?php -function handle_error($code, $message, $file, $line, $context) { +function handle_error($code, $message, $file, $line) { eval('namespace Foo;'); echo "$message\n"; } diff --git a/Zend/tests/bug69755.phpt b/Zend/tests/bug69755.phpt index 08432808e2..e419756d26 100644 --- a/Zend/tests/bug69755.phpt +++ b/Zend/tests/bug69755.phpt @@ -5,4 +5,7 @@ Bug #69755: segfault in ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDLER c . 10; ?> --EXPECTF-- -Warning: Use of undefined constant c - assumed 'c' (this will throw an Error in a future version of PHP) in %sbug69755.php on line 2 +Fatal error: Uncaught Error: Undefined constant 'c' in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/bug69788.phpt b/Zend/tests/bug69788.phpt index ff028411b1..e847b3b0a5 100644 --- a/Zend/tests/bug69788.phpt +++ b/Zend/tests/bug69788.phpt @@ -3,6 +3,7 @@ Bug #69788: Malformed script causes Uncaught Error in php-cgi, valgrind SIGILL --FILE-- <?php [t.[]]; ?> --EXPECTF-- -Warning: Use of undefined constant t - assumed 't' (this will throw an Error in a future version of PHP) in %s on line %d - -Notice: Array to string conversion in %s on line %d +Fatal error: Uncaught Error: Undefined constant 't' in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/bug70681.phpt b/Zend/tests/bug70681.phpt index 9dd09b07b8..d0cc9523a9 100644 --- a/Zend/tests/bug70681.phpt +++ b/Zend/tests/bug70681.phpt @@ -12,5 +12,5 @@ var_dump($c("foo")); ?> --EXPECTF-- -Warning: Cannot unbind $this of internal method in %s on line %d +Warning: Cannot unbind $this of method in %s on line %d int(3) diff --git a/Zend/tests/bug70895.phpt b/Zend/tests/bug70895.phpt index 896bf00a7b..71ff19a0b5 100644 --- a/Zend/tests/bug70895.phpt +++ b/Zend/tests/bug70895.phpt @@ -3,13 +3,23 @@ Bug #70895 null ptr deref and segfault with crafted callable --FILE-- <?php -array_map("%n", 0); -array_map("%n %i", 0); -array_map("%n %i aoeu %f aoeu %p", 0); +try { + array_map("%n", 0); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +try { + array_map("%n %i", 0); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +try { + array_map("%n %i aoeu %f aoeu %p", 0); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} ?> ---EXPECTREGEX-- -Warning: array_map\(\) expects parameter 1 to be a valid callback, function '%n' not found or invalid function name in .+ - -Warning: array_map\(\) expects parameter 1 to be a valid callback, function '%n %i' not found or invalid function name in .+ - -Warning: array_map\(\) expects parameter 1 to be a valid callback, function '%n %i aoeu %f aoeu %p' not found or invalid function name in .+bug70895.php on line \d+ +--EXPECT-- +array_map() expects parameter 1 to be a valid callback, function '%n' not found or invalid function name +array_map() expects parameter 1 to be a valid callback, function '%n %i' not found or invalid function name +array_map() expects parameter 1 to be a valid callback, function '%n %i aoeu %f aoeu %p' not found or invalid function name diff --git a/Zend/tests/bug70898.phpt b/Zend/tests/bug70898.phpt index e31ee894bf..fa6e96d83f 100644 --- a/Zend/tests/bug70898.phpt +++ b/Zend/tests/bug70898.phpt @@ -2,21 +2,15 @@ Bug #70895 null ptr deref and segfault with crafted callable --FILE-- <?php - function m($f,$a){ - return array_map($f,0); - } +function m($f,$a){ + return array_map($f,0); +} - echo implode(m("",m("",m("",m("",m("0000000000000000000000000000000000",(""))))))); +try { + echo implode(m("",m("",m("",m("",m("0000000000000000000000000000000000",(""))))))); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} ?> ---EXPECTF-- -Warning: array_map() expects parameter 1 to be a valid callback, function '0000000000000000000000000000000000' not found or invalid function name in %sbug70898.php on line %d - -Warning: array_map() expects parameter 1 to be a valid callback, function '' not found or invalid function name in %sbug70898.php on line %d - -Warning: array_map() expects parameter 1 to be a valid callback, function '' not found or invalid function name in %sbug70898.php on line %d - -Warning: array_map() expects parameter 1 to be a valid callback, function '' not found or invalid function name in %sbug70898.php on line %d - -Warning: array_map() expects parameter 1 to be a valid callback, function '' not found or invalid function name in %sbug70898.php on line %d - -Warning: implode(): Argument must be an array in %sbug70898.php on line %d +--EXPECT-- +array_map() expects parameter 1 to be a valid callback, function '0000000000000000000000000000000000' not found or invalid function name diff --git a/Zend/tests/bug72057.phpt b/Zend/tests/bug72057.phpt index 406efe3efc..a518d82948 100644 --- a/Zend/tests/bug72057.phpt +++ b/Zend/tests/bug72057.phpt @@ -13,7 +13,7 @@ set_error_handler( --EXPECTF-- Fatal error: Uncaught Exception: My custom error in %s:%d Stack trace: -#0 %s(%d): {closure}(8, 'A non well form...', '%s', %d, Array) +#0 %s(%d): {closure}(8, 'A non well form...', '%s', %d) #1 %s(%d): {closure}('7as') #2 {main} thrown in %s on line %d diff --git a/Zend/tests/bug72101.phpt b/Zend/tests/bug72101.phpt index 808627be3b..23861958fd 100644 --- a/Zend/tests/bug72101.phpt +++ b/Zend/tests/bug72101.phpt @@ -76,7 +76,7 @@ $foo->bar($a, $b, $c); --EXPECTF-- Fatal error: Uncaught Error: Class 'DoesNotExists' not found in %sbug72101.php:61 Stack trace: -#0 %sbug72101.php(8): {closure}(2, 'Parameter 1 to ...', '%s', 8, Array) +#0 %sbug72101.php(8): {closure}(2, 'Parameter 1 to ...', '%s', 8) #1 %sbug72101.php(27): PHPUnit_Framework_MockObject_Stub_ReturnCallback->invoke(Object(PHPUnit_Framework_MockObject_Invocation_Static)) #2 %sbug72101.php(19): PHPUnit_Framework_MockObject_Matcher->invoked(Object(PHPUnit_Framework_MockObject_Invocation_Static)) #3 %sbug72101.php(52): PHPUnit_Framework_MockObject_InvocationMocker->invoke(Object(PHPUnit_Framework_MockObject_Invocation_Static)) diff --git a/Zend/tests/bug72944.phpt b/Zend/tests/bug72944.phpt index 5f494beb40..75a4edb565 100644 --- a/Zend/tests/bug72944.phpt +++ b/Zend/tests/bug72944.phpt @@ -2,11 +2,10 @@ Bug #72944 (Null pointer deref in zval_delref_p). --FILE-- <?php +define('e', 'e'); "a"== e & $A = $A? 0 : 0 ?:0; echo "OK\n"; ?> --EXPECTF-- -Warning: Use of undefined constant e - assumed 'e' (this will throw an Error in a future version of PHP) in %sbug72944.php on line 2 - -Notice: Undefined variable: A in %sbug72944.php on line 2 +Notice: Undefined variable: A in %sbug72944.php on line 3 OK diff --git a/Zend/tests/bug73163.phpt b/Zend/tests/bug73163.phpt deleted file mode 100644 index 5c0560458d..0000000000 --- a/Zend/tests/bug73163.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -Bug #73163 (PHP hangs if error handler throws while accessing undef const in default value) ---FILE-- -<?php - -function doSomething(string $value = UNDEFINED) { -} - -set_error_handler(function($errno, $errstr) { - throw new Exception($errstr); -}); - -doSomething(); - -?> ---EXPECTF-- -Fatal error: Uncaught Exception: Use of undefined constant UNDEFINED - assumed 'UNDEFINED' (this will throw an Error in a future version of PHP) in %s:%d -Stack trace: -#0 %s(%d): {closure}(%s) -#1 %s(%d): doSomething() -#2 {main} - thrown in %s on line %d diff --git a/Zend/tests/bug73181.phpt b/Zend/tests/bug73181.phpt deleted file mode 100644 index 3ab93ebf5b..0000000000 --- a/Zend/tests/bug73181.phpt +++ /dev/null @@ -1,21 +0,0 @@ ---TEST-- -Bug #73181: parse_str() without a second argument leads to crash ---FILE-- -<?php - -function x() { - parse_str("1&x"); - var_dump(get_defined_vars()); -} - -x(); - -?> ---EXPECTF-- -Deprecated: parse_str(): Calling parse_str() without the result argument is deprecated in %s on line %d -array(2) { - [1]=> - string(0) "" - ["x"]=> - string(0) "" -} diff --git a/Zend/tests/bug73338.phpt b/Zend/tests/bug73338.phpt index df4c3b66e4..816a526445 100644 --- a/Zend/tests/bug73338.phpt +++ b/Zend/tests/bug73338.phpt @@ -14,5 +14,6 @@ try { (function() { call_user_func("fail"); })(); } catch (Error $e) {} try { [new class { static function foo() {} function __destruct () { throw new Error; } }, "foo"](); } catch (Error $e) {} ?> ---EXPECTF-- -Warning: call_user_func() expects parameter 1 to be a valid callback, no array or string given in %s on line %d +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/bug74408.phpt b/Zend/tests/bug74408.phpt deleted file mode 100644 index e770a51dc8..0000000000 --- a/Zend/tests/bug74408.phpt +++ /dev/null @@ -1,34 +0,0 @@ ---TEST-- -Bug #74408 (Endless loop bypassing execution time limit) ---FILE-- -<?php - - class ErrorHandling { - - public function error_handler($errno, $errstr, $errfile, $errline) { - $bla = new NonExistingClass2(); - } - - public function exception_handler(Error $e) { - echo "Caught, exception: " . $e->getMessage(); - } - } - - set_error_handler('ErrorHandling::error_handler'); - set_exception_handler('ErrorHandling::exception_handler'); - - $blubb = new NonExistingClass(); -?> ---EXPECTF-- -Deprecated: Non-static method ErrorHandling::error_handler() should not be called statically in %sbug74408.php on line %d - -Deprecated: Non-static method ErrorHandling::error_handler() should not be called statically in %sbug74408.php on line %d - -Deprecated: Non-static method ErrorHandling::error_handler() should not be called statically in Unknown on line 0 - -Fatal error: Uncaught Error: Class 'NonExistingClass2' not found in %sbug74408.php:%d -Stack trace: -#0 [internal function]: ErrorHandling::error_handler(8192, 'Non-static meth...', '%s', %d, Array) -#1 %sbug74408.php(%d): set_exception_handler('ErrorHandling::...') -#2 {main} - thrown in %sbug74408.php on line %d diff --git a/Zend/tests/bug76025.phpt b/Zend/tests/bug76025.phpt index 2619984d1e..c7958bd60e 100644 --- a/Zend/tests/bug76025.phpt +++ b/Zend/tests/bug76025.phpt @@ -13,6 +13,6 @@ $c = $b[$a]; --EXPECTF-- Fatal error: Uncaught Exception: blah in %sbug76025.php:%d Stack trace: -#0 %sbug76025.php(%d): handleError(8, 'Undefined varia...', '%s', %d, Array) +#0 %sbug76025.php(%d): handleError(8, 'Undefined varia...', '%s', %d) #1 {main} thrown in %sbug76025.php on line %d diff --git a/Zend/tests/bug76534.phpt b/Zend/tests/bug76534.phpt index 956a29ba2c..457d09f400 100644 --- a/Zend/tests/bug76534.phpt +++ b/Zend/tests/bug76534.phpt @@ -12,6 +12,6 @@ $y = &$x["bar"]; --EXPECTF-- Fatal error: Uncaught Exception: Illegal string offset 'bar' in %sbug76534.php:%d Stack trace: -#0 %sbug76534.php(%d): {closure}(2, 'Illegal string ...', '%s', %d, Array) +#0 %sbug76534.php(%d): {closure}(2, 'Illegal string ...', '%s', %d) #1 {main} thrown in %sbug76534.php on line %d diff --git a/Zend/tests/bug77738.phpt b/Zend/tests/bug77738.phpt index e3a453c405..c664a31344 100644 --- a/Zend/tests/bug77738.phpt +++ b/Zend/tests/bug77738.phpt @@ -5,4 +5,7 @@ Bug #77738 (Nullptr deref in zend_compile_expr) __COMPILER_HALT_OFFSET__; ; // <- important --EXPECTF-- -Warning: Use of undefined constant __COMPILER_HALT_OFFSET__ - assumed '__COMPILER_HALT_OFFSET__' %sbug77738.php on line %d +Fatal error: Uncaught Error: Undefined constant '__COMPILER_HALT_OFFSET__' in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/call_static_006.phpt b/Zend/tests/call_static_006.phpt index 2887afa355..946be2a3c9 100644 --- a/Zend/tests/call_static_006.phpt +++ b/Zend/tests/call_static_006.phpt @@ -4,29 +4,15 @@ Testing __callStatic <?php class foo { - public function aa() { - print "ok\n"; - } static function __callstatic($a, $b) { var_dump($a); } } -foo::aa(); - -$b = 'AA'; -foo::$b(); - foo::__construct(); ?> --EXPECTF-- -Deprecated: Non-static method foo::aa() should not be called statically in %s on line %d -ok - -Deprecated: Non-static method foo::aa() should not be called statically in %s on line %d -ok - Fatal error: Uncaught Error: Cannot call constructor in %s:%d Stack trace: #0 {main} diff --git a/Zend/tests/call_user_func_001.phpt b/Zend/tests/call_user_func_001.phpt index 15d0aec263..a6e43f3060 100644 --- a/Zend/tests/call_user_func_001.phpt +++ b/Zend/tests/call_user_func_001.phpt @@ -22,14 +22,20 @@ namespace testing { call_user_func(__NAMESPACE__ .'\foobar', 'foobar'); $class = __NAMESPACE__ .'\foo'; - call_user_func(array(new $class, 'priv'), 'foobar'); - call_user_func(array(new $class, 'prot'), 'foobar'); + try { + call_user_func(array(new $class, 'priv'), 'foobar'); + } catch (\TypeError $e) { + echo $e->getMessage(), "\n"; + } + try { + call_user_func(array(new $class, 'prot'), 'foobar'); + } catch (\TypeError $e) { + echo $e->getMessage(), "\n"; + } } ?> ---EXPECTF-- +--EXPECT-- string(6) "foobar" - -Warning: call_user_func() expects parameter 1 to be a valid callback, cannot access private method testing\foo::priv() in %s on line %d - -Warning: call_user_func() expects parameter 1 to be a valid callback, cannot access protected method testing\foo::prot() in %s on line %d +call_user_func() expects parameter 1 to be a valid callback, cannot access private method testing\foo::priv() +call_user_func() expects parameter 1 to be a valid callback, cannot access protected method testing\foo::prot() diff --git a/Zend/tests/call_user_func_002.phpt b/Zend/tests/call_user_func_002.phpt index 454c6fda96..9d007a8af3 100644 --- a/Zend/tests/call_user_func_002.phpt +++ b/Zend/tests/call_user_func_002.phpt @@ -4,26 +4,38 @@ Testing call_user_func() with autoload and passing invalid params <?php spl_autoload_register(function ($class) { - var_dump($class); + var_dump($class); }); -call_user_func(array('foo', 'bar')); -call_user_func(array('', 'bar')); -call_user_func(array($foo, 'bar')); -call_user_func(array($foo, '')); +try { + call_user_func(array('foo', 'bar')); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +try { + call_user_func(array('', 'bar')); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +try { + call_user_func(array($foo, 'bar')); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +try { + call_user_func(array($foo, '')); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} ?> --EXPECTF-- string(3) "foo" - -Warning: call_user_func() expects parameter 1 to be a valid callback, class 'foo' not found in %s on line %d - -Warning: call_user_func() expects parameter 1 to be a valid callback, class '' not found in %s on line %d +call_user_func() expects parameter 1 to be a valid callback, class 'foo' not found +call_user_func() expects parameter 1 to be a valid callback, class '' not found Notice: Undefined variable: foo in %s on line %d - -Warning: call_user_func() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in %s on line %d +call_user_func() expects parameter 1 to be a valid callback, first array member is not a valid class name or object Notice: Undefined variable: foo in %s on line %d - -Warning: call_user_func() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in %s on line %d +call_user_func() expects parameter 1 to be a valid callback, first array member is not a valid class name or object diff --git a/Zend/tests/call_user_func_004.phpt b/Zend/tests/call_user_func_004.phpt deleted file mode 100644 index 7a2c4b8ffd..0000000000 --- a/Zend/tests/call_user_func_004.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -Calling non-static method with call_user_func() ---FILE-- -<?php - -class foo { - public function teste() { - $this->a = 1; - } -} - -call_user_func(array('foo', 'teste')); - -?> ---EXPECTF-- -Deprecated: %son-static method foo::teste() should not be called statically in %s on line %d - -Fatal error: Uncaught Error: Using $this when not in object context in %s:%d -Stack trace: -#0 %s(%d): foo::teste() -#1 {main} - thrown in %s on line %d diff --git a/Zend/tests/call_user_func_005.phpt b/Zend/tests/call_user_func_005.phpt index 9305e5849c..13d69fd60d 100644 --- a/Zend/tests/call_user_func_005.phpt +++ b/Zend/tests/call_user_func_005.phpt @@ -9,7 +9,7 @@ class foo { return 1; } - public function teste() { + public static function teste() { return foo::x(function &($a=1,$b) { }); } } @@ -18,7 +18,6 @@ var_dump(call_user_func(array('foo', 'teste'))); ?> --EXPECTF-- -Deprecated: %son-static method foo::teste() should not be called statically in %s on line %d string(1) "x" array(1) { [0]=> diff --git a/Zend/tests/case_insensitive_constant_deprecation.phpt b/Zend/tests/case_insensitive_constant_deprecation.phpt deleted file mode 100644 index e7a92c8c4c..0000000000 --- a/Zend/tests/case_insensitive_constant_deprecation.phpt +++ /dev/null @@ -1,127 +0,0 @@ ---TEST-- -Case-insensitive constants are deprecated ---FILE-- -<?php - -namespace { - define('FOO', 42, true); // Deprecated - define('NS\FOO', 24, true); // Deprecated - - var_dump(FOO); // Ok - var_dump(foo); // Deprecated - - var_dump(NS\FOO); // Ok - var_dump(ns\FOO); // Ok - var_dump(ns\foo); // Deprecated - - var_dump(defined('FOO')); // Ok - var_dump(defined('foo')); // Ok - var_dump(defined('NS\FOO')); // Ok - var_dump(defined('ns\FOO')); // Ok - var_dump(defined('ns\foo')); // Ok - - var_dump(constant('FOO')); // Ok - var_dump(constant('foo')); // Deprecated - var_dump(constant('NS\FOO')); // Ok - var_dump(constant('ns\FOO')); // Ok - var_dump(constant('ns\foo')); // Deprecated -} - -namespace NS { - var_dump(FOO); // Ok - var_dump(foo); // Deprecated -} - -namespace ns { - var_dump(FOO); // Ok - var_dump(foo); // Deprecated -} - -namespace Other { - var_dump(FOO); // Ok - var_dump(foo); // Deprecated - - var_dump(defined('FOO')); // Ok - var_dump(defined('foo')); // Ok - var_dump(defined('NS\FOO')); // Ok - var_dump(defined('ns\FOO')); // Ok - var_dump(defined('ns\foo')); // Ok - - var_dump(constant('FOO')); // Ok - var_dump(constant('foo')); // Deprecated - var_dump(constant('NS\FOO')); // Ok - var_dump(constant('ns\FOO')); // Ok - var_dump(constant('ns\foo')); // Deprecated - - const C1 = FOO; // Ok - var_dump(C1); - const C2 = foo; // Deprecated - var_dump(C2); - const C3 = 1 + FOO; // Ok - var_dump(C3); - const C4 = 1 + foo; // Deprecated - var_dump(C4); -} - -?> ---EXPECTF-- -Deprecated: define(): Declaration of case-insensitive constants is deprecated in %s on line 4 - -Deprecated: define(): Declaration of case-insensitive constants is deprecated in %s on line 5 -int(42) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "FOO" in %s on line 8 -int(42) -int(24) -int(24) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "NS\FOO" in %s on line 12 -int(24) -bool(true) -bool(true) -bool(true) -bool(true) -bool(true) -int(42) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "FOO" in %s on line 21 -int(42) -int(24) -int(24) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "NS\FOO" in %s on line 24 -int(24) -int(24) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "NS\FOO" in %s on line 29 -int(24) -int(24) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "NS\FOO" in %s on line 34 -int(24) -int(42) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "FOO" in %s on line 39 -int(42) -bool(true) -bool(true) -bool(true) -bool(true) -bool(true) -int(42) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "FOO" in %s on line 48 -int(42) -int(24) -int(24) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "NS\FOO" in %s on line 51 -int(24) -int(42) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "FOO" in %s on line 55 -int(42) -int(43) - -Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "FOO" in %s on line 59 -int(43) diff --git a/Zend/tests/catch.phpt b/Zend/tests/catch.phpt index a83dd75baf..2e61fef935 100644 --- a/Zend/tests/catch.phpt +++ b/Zend/tests/catch.phpt @@ -1,5 +1,5 @@ --TEST-- -catch shouldn't call __autoload +catch shouldn't call autoloader --FILE-- <?php diff --git a/Zend/tests/class_exists_002.phpt b/Zend/tests/class_exists_002.phpt index ebe04575af..5e5df1d371 100644 --- a/Zend/tests/class_exists_002.phpt +++ b/Zend/tests/class_exists_002.phpt @@ -12,15 +12,11 @@ var_dump(class_exists(NULL)); var_dump(class_exists('FOO')); var_dump(class_exists('bar')); var_dump(class_exists(1)); -var_dump(class_exists(new stdClass)); ?> ---EXPECTF-- +--EXPECT-- bool(false) bool(false) bool(true) bool(false) bool(false) - -Warning: class_exists() expects parameter 1 to be string, object given in %s on line %d -NULL diff --git a/Zend/tests/closure_025.phpt b/Zend/tests/closure_025.phpt deleted file mode 100644 index b3d03a7ad9..0000000000 --- a/Zend/tests/closure_025.phpt +++ /dev/null @@ -1,13 +0,0 @@ ---TEST-- -Closure 025: Using closure in create_function() ---FILE-- -<?php - -$a = create_function('$x', 'return function($y) use ($x) { return $x * $y; };'); - -var_dump($a(2)->__invoke(4)); - -?> ---EXPECTF-- -Deprecated: Function create_function() is deprecated in %s on line %d -int(8) diff --git a/Zend/tests/closure_040.phpt b/Zend/tests/closure_040.phpt index 231ab4081c..531ecb271a 100644 --- a/Zend/tests/closure_040.phpt +++ b/Zend/tests/closure_040.phpt @@ -25,9 +25,6 @@ $ca = $a->getIncrementor(); $cas = $a->getStaticIncrementor(); $ca->bindTo($a, array()); -$ca->bindTo(array(), 'A'); -$ca->bindTo($a, array(), ""); -$ca->bindTo(); $cas->bindTo($a, 'A'); ?> @@ -36,10 +33,4 @@ Notice: Array to string conversion in %s on line %d Warning: Class 'Array' not found in %s on line %d -Warning: Closure::bindTo() expects parameter 1 to be object, array given in %s on line 25 - -Warning: Closure::bindTo() expects at most 2 parameters, 3 given in %s on line %d - -Warning: Closure::bindTo() expects at least 1 parameter, 0 given in %s on line %d - Warning: Cannot bind an instance to a static closure in %s on line %d diff --git a/Zend/tests/closure_061.phpt b/Zend/tests/closure_061.phpt index f01e393570..2c574c49c0 100644 --- a/Zend/tests/closure_061.phpt +++ b/Zend/tests/closure_061.phpt @@ -175,9 +175,7 @@ Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure ------------------- bindTo(null, Cls::class): -Unbinding $this of a method is deprecated - -Success! +Cannot unbind $this of method bindTo(new Cls, Cls::class): Success! @@ -210,10 +208,10 @@ bindTo(new ClsUnrelated, SplDoublyLinkedList::class): Cannot bind method SplDoublyLinkedList::count() to object of class ClsUnrelated bindTo(null, null): -Cannot unbind $this of internal method +Cannot unbind $this of method bindTo(null, SplDoublyLinkedList::class): -Cannot unbind $this of internal method +Cannot unbind $this of method bindTo(new SplDoublyLinkedList, null): Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() diff --git a/Zend/tests/closures/closure_from_callable_non_static_statically.phpt b/Zend/tests/closures/closure_from_callable_non_static_statically.phpt index 17d39c052e..24df1d186a 100644 --- a/Zend/tests/closures/closure_from_callable_non_static_statically.phpt +++ b/Zend/tests/closures/closure_from_callable_non_static_statically.phpt @@ -17,4 +17,4 @@ try { ?> --EXPECT-- -Failed to create closure from callable: non-static method A::method() should not be called statically +Failed to create closure from callable: non-static method A::method() cannot be called statically diff --git a/Zend/tests/constant_expressions_classes.phpt b/Zend/tests/constant_expressions_classes.phpt index eed006bfe1..89cabc0f91 100644 --- a/Zend/tests/constant_expressions_classes.phpt +++ b/Zend/tests/constant_expressions_classes.phpt @@ -4,8 +4,6 @@ Constant scalar expressions with autoloading and classes opcache.enable=1 opcache.enable_cli=1 opcache.optimization_level=-1 ---SKIPIF-- -<?php if (php_sapi_name() != "cli") die("skip CLI only"); ?> --FILE-- <?php diff --git a/Zend/tests/constants_002.phpt b/Zend/tests/constants_002.phpt index b0cf1db61f..ddb2e67307 100644 --- a/Zend/tests/constants_002.phpt +++ b/Zend/tests/constants_002.phpt @@ -4,7 +4,11 @@ Defining constants with non-scalar values <?php define('foo', new stdClass); -var_dump(foo); +try { + var_dump(foo); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} define('foo', fopen(__FILE__, 'r')); var_dump(foo); @@ -12,7 +16,5 @@ var_dump(foo); ?> --EXPECTF-- Warning: Constants may only evaluate to scalar values, arrays or resources in %s on line %d - -Warning: Use of undefined constant foo - assumed 'foo' (this will throw an Error in a future version of PHP) in %s on line %d -string(%d) "foo" -resource(%d) of type (stream) +Undefined constant 'foo' +resource(5) of type (stream) diff --git a/Zend/tests/constants_005.phpt b/Zend/tests/constants_005.phpt index b5a3a6bd38..27ab0259d1 100644 --- a/Zend/tests/constants_005.phpt +++ b/Zend/tests/constants_005.phpt @@ -2,11 +2,10 @@ Persistent case insensitive and user defined constants --FILE-- <?php -var_dump(ZEND_THREAD_safe); +var_dump(defined('ZEND_THREAD_safe')); define("ZEND_THREAD_safe", 123); var_dump(ZEND_THREAD_safe); ?> ---EXPECTF-- -Warning: Use of undefined constant ZEND_THREAD_safe - assumed 'ZEND_THREAD_safe' (this will throw an Error in a future version of PHP) in %s on line %d -string(16) "ZEND_THREAD_safe" +--EXPECT-- +bool(false) int(123) diff --git a/Zend/tests/custom_assert_deprecation.phpt b/Zend/tests/custom_assert_forbidden.phpt index b4e22843dd..492a656f39 100644 --- a/Zend/tests/custom_assert_deprecation.phpt +++ b/Zend/tests/custom_assert_forbidden.phpt @@ -9,4 +9,4 @@ function assert() {} ?> --EXPECTF-- -Deprecated: Defining a custom assert() function is deprecated, as the function has special semantics in %s on line %d +Fatal error: Defining a custom assert() function is not allowed, as the function has special semantics in %s on line %d diff --git a/Zend/tests/dynamic_call_001.phpt b/Zend/tests/dynamic_call_001.phpt deleted file mode 100644 index 7f8a6c0b3d..0000000000 --- a/Zend/tests/dynamic_call_001.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -Testing dynamic call to constructor (old-style) ---FILE-- -<?php - -class foo { - public function foo() { - } -} - -$a = 'foo'; - -$a::$a(); - -?> ---EXPECTF-- -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; foo has a deprecated constructor in %s on line %d - -Fatal error: Uncaught Error: Non-static method foo::foo() cannot be called statically in %s:%d -Stack trace: -#0 {main} - thrown in %s on line %d diff --git a/Zend/tests/dynamic_call_006.phpt b/Zend/tests/dynamic_call_006.phpt index 058e22fda0..7a2872bcca 100644 --- a/Zend/tests/dynamic_call_006.phpt +++ b/Zend/tests/dynamic_call_006.phpt @@ -9,15 +9,9 @@ function test() { $func = 'compact'; $func(['a']); - $func = 'parse_str'; - $func('a=b'); - $func = 'get_defined_vars'; $func(); - $func = 'assert'; - $func('1==2'); - $func = 'func_get_args'; $func(); @@ -35,12 +29,8 @@ Warning: Cannot call extract() dynamically in %s on line %d Warning: Cannot call compact() dynamically in %s on line %d -Warning: Cannot call parse_str() with a single argument dynamically in %s on line %d - Warning: Cannot call get_defined_vars() dynamically in %s on line %d -Warning: Cannot call assert() with string argument dynamically in %s on line %d - Warning: Cannot call func_get_args() dynamically in %s on line %d Warning: Cannot call func_get_arg() dynamically in %s on line %d diff --git a/Zend/tests/each_001.phpt b/Zend/tests/each_001.phpt deleted file mode 100644 index f2cae3d875..0000000000 --- a/Zend/tests/each_001.phpt +++ /dev/null @@ -1,12 +0,0 @@ ---TEST-- -Testing each() with an undefined variable ---FILE-- -<?php - -each($foo); - -?> ---EXPECTF-- -Deprecated: The each() function is deprecated. This message will be suppressed on further calls in %s on line %d - -Warning: Variable passed to each() is not an array or object in %s on line %d diff --git a/Zend/tests/each_002.phpt b/Zend/tests/each_002.phpt deleted file mode 100644 index 5454f5ce0f..0000000000 --- a/Zend/tests/each_002.phpt +++ /dev/null @@ -1,33 +0,0 @@ ---TEST-- -Testing each() with array and object ---FILE-- -<?php - -$a = new stdClass; -$foo = each($a); -var_dump($foo); - -$a = new stdClass; -var_dump(each($a)); - -$a = array(new stdClass); -var_dump(each($a)); - - -?> ---EXPECTF-- -Deprecated: The each() function is deprecated. This message will be suppressed on further calls in %s on line %d -bool(false) -bool(false) -array(4) { - [1]=> - object(stdClass)#1 (0) { - } - ["value"]=> - object(stdClass)#1 (0) { - } - [0]=> - int(0) - ["key"]=> - int(0) -} diff --git a/Zend/tests/each_003.phpt b/Zend/tests/each_003.phpt deleted file mode 100644 index d0038c0561..0000000000 --- a/Zend/tests/each_003.phpt +++ /dev/null @@ -1,27 +0,0 @@ ---TEST-- -Testing each() with recursion ---INI-- -zend.enable_gc=1 ---FILE-- -<?php - -$a = array(array()); -$a[] =& $a; - -var_dump(each($a[1])); - -?> ---EXPECTF-- -Deprecated: The each() function is deprecated. This message will be suppressed on further calls in %s on line %d -array(4) { - [1]=> - array(0) { - } - ["value"]=> - array(0) { - } - [0]=> - int(0) - ["key"]=> - int(0) -} diff --git a/Zend/tests/errmsg_012.phpt b/Zend/tests/errmsg_012.phpt deleted file mode 100644 index c914125af5..0000000000 --- a/Zend/tests/errmsg_012.phpt +++ /dev/null @@ -1,11 +0,0 @@ ---TEST-- -errmsg: __autoload() must take exactly 1 argument ---FILE-- -<?php - -function __autoload($a, $b) {} - -echo "Done\n"; -?> ---EXPECTF-- -Fatal error: __autoload() must take exactly 1 argument in %s on line %d diff --git a/Zend/tests/error_reporting10.phpt b/Zend/tests/error_reporting10.phpt index 8b0c7b9923..c18c04d8f0 100644 --- a/Zend/tests/error_reporting10.phpt +++ b/Zend/tests/error_reporting10.phpt @@ -8,7 +8,6 @@ error_reporting(E_ALL); function make_exception() { @$blah; - str_replace(); error_reporting(0); throw new Exception(); } diff --git a/Zend/tests/exception_012.phpt b/Zend/tests/exception_012.phpt deleted file mode 100644 index 4a1070330a..0000000000 --- a/Zend/tests/exception_012.phpt +++ /dev/null @@ -1,23 +0,0 @@ ---TEST-- -Test exception doesn't cause RSHUTDOWN bypass, variation 1 ---INI-- -assert.bail=1 -assert.exception=1 ---FILE-- -<?php - -$func = create_function('', 'define("Mommy", 1); assert(false);'); -$func(); - -?> ---EXPECTHEADERS-- -Content-type: text/html; charset=UTF-8 ---EXPECTF-- -Deprecated: Function create_function() is deprecated in %s on line %d - -Fatal error: Uncaught AssertionError: assert(false) in %sexception_012.php(%d) : runtime-created function:%d -Stack trace: -#0 %sexception_012.php(%d) : runtime-created function(%d): assert(false, 'assert(false)') -#1 %sexception_012.php(%d): __lambda_func() -#2 {main} - thrown in %sexception_012.php(%d) : runtime-created function on line %d diff --git a/Zend/tests/exception_017.phpt b/Zend/tests/exception_017.phpt index f980b297fb..77fbf2d844 100644 --- a/Zend/tests/exception_017.phpt +++ b/Zend/tests/exception_017.phpt @@ -12,28 +12,29 @@ function foo(callable $x) { try { C::foo(); } catch (Error $e) { - echo "\nException: " . $e->getMessage() . " in " , $e->getFile() . " on line " . $e->getLine() . "\n"; + echo $e, "\n\n"; } try { foo("C::foo"); } catch (Error $e) { - echo "\n"; - do { - echo "Exception: " . $e->getMessage() . "\n"; - $e = $e->getPrevious(); - } while ($e instanceof Error); + echo $e, "\n\n"; } C::foo(); ?> --EXPECTF-- -Exception: Cannot call abstract method C::foo() in %sexception_017.php on line %d +Error: Cannot call abstract method C::foo() in %s:%d +Stack trace: +#0 {main} + +TypeError: Argument 1 passed to foo() must be callable, string given, called in %s on line %d and defined in %s:%d +Stack trace: +#0 %s(%d): foo('C::foo') +#1 {main} -Exception: Argument 1 passed to foo() must be callable, string given, called in %sexception_017.php on line %d -Exception: Cannot call abstract method C::foo() -Fatal error: Uncaught Error: Cannot call abstract method C::foo() in %sexception_017.php:%d +Fatal error: Uncaught Error: Cannot call abstract method C::foo() in %s:%d Stack trace: #0 {main} - thrown in %sexception_017.php on line %d + thrown in %s on line %d diff --git a/Zend/tests/exception_handler_004.phpt b/Zend/tests/exception_handler_004.phpt index 69a4136b08..6552141b73 100644 --- a/Zend/tests/exception_handler_004.phpt +++ b/Zend/tests/exception_handler_004.phpt @@ -5,8 +5,6 @@ exception handler tests - 4 set_exception_handler("fo"); set_exception_handler(array("", "")); -set_exception_handler(); -set_exception_handler("foo", "bar"); echo "Done\n"; ?> @@ -14,8 +12,4 @@ echo "Done\n"; Warning: set_exception_handler() expects the argument (fo) to be a valid callback in %s on line %d Warning: set_exception_handler() expects the argument (::) to be a valid callback in %s on line %d - -Warning: set_exception_handler() expects exactly 1 parameter, 0 given in %s on line %d - -Warning: set_exception_handler() expects exactly 1 parameter, 2 given in %s on line %d Done diff --git a/Zend/tests/fr47160.phpt b/Zend/tests/fr47160.phpt index 786183c0c1..6567804902 100644 --- a/Zend/tests/fr47160.phpt +++ b/Zend/tests/fr47160.phpt @@ -36,20 +36,6 @@ class Magic3 { } } -$f = array('Hello','world'); -try { - var_dump($f('you')); -} catch (Throwable $e) { - echo "Exception: " . $e->getMessage() . "\n"; -} -try { - var_dump(call_user_func($f, 'you')); -} catch (Throwable $e) { - echo "Exception: " . $e->getMessage() . "\n"; -} - -printf("-----\n"); - $h= new Hello; $f = array($h,'world'); var_dump($f('again')); @@ -107,14 +93,6 @@ var_dump(call_user_func($f, 'you')); ?> --EXPECTF-- -Deprecated: Non-static method Hello::world() should not be called statically in %s on line %d -Hello, you -Exception: Using $this when not in object context - -Deprecated: %son-static method Hello::world() should not be called statically in %s on line %d -Hello, you -Exception: Using $this when not in object context ------ Hello, again object(Hello)#%d (0) { } diff --git a/Zend/tests/function_arguments/argument_count_incorrect_internal.phpt b/Zend/tests/function_arguments/argument_count_incorrect_internal.phpt index a8ba71c0bf..5c0770ff65 100644 --- a/Zend/tests/function_arguments/argument_count_incorrect_internal.phpt +++ b/Zend/tests/function_arguments/argument_count_incorrect_internal.phpt @@ -2,9 +2,10 @@ Call internal function with incorrect number of arguments --FILE-- <?php -substr("foo"); -array_diff([]); ---EXPECTF-- -Warning: substr() expects at least 2 parameters, 1 given in %s - -Warning: array_diff(): at least 2 parameters are required, 1 given in %s +try { + substr("foo"); +} catch (ArgumentCountError $e) { + echo $e->getMessage(), "\n"; +} +--EXPECT-- +substr() expects at least 2 parameters, 1 given diff --git a/Zend/tests/incompat_ctx_user.phpt b/Zend/tests/incompat_ctx_user.phpt index 25c95ba219..8c7461e4f7 100644 --- a/Zend/tests/incompat_ctx_user.phpt +++ b/Zend/tests/incompat_ctx_user.phpt @@ -4,18 +4,17 @@ Incompatible context call (non-internal function) <?php class A { - function foo() { var_dump(get_class($this)); } + function foo() { var_dump(get_class($this)); } } class B { - function bar() { A::foo(); } + function bar() { A::foo(); } } $b = new B; try { - $b->bar(); + $b->bar(); } catch (Throwable $e) { - echo "Exception: " . $e->getMessage() . "\n"; + echo "Exception: " . $e->getMessage() . "\n"; } ?> --EXPECTF-- -Deprecated: Non-static method A::foo() should not be called statically in %s on line %d -Exception: Using $this when not in object context +Exception: Non-static method A::foo() cannot be called statically diff --git a/Zend/tests/indirect_call_array_005.phpt b/Zend/tests/indirect_call_array_005.phpt index 4938856ed2..bd11df2d12 100644 --- a/Zend/tests/indirect_call_array_005.phpt +++ b/Zend/tests/indirect_call_array_005.phpt @@ -19,10 +19,7 @@ $callback = ['TestClass', 'method']; echo $callback(); ?> --EXPECTF-- -Deprecated: Non-static method TestClass::method() should not be called statically in %s on line %d - -Fatal error: Uncaught Error: Using $this when not in object context in %s:%d +Fatal error: Uncaught Error: Non-static method TestClass::method() cannot be called statically in %s:%d Stack trace: -#0 %s(%d): TestClass::method() -#1 {main} +#0 {main} thrown in %s on line %d diff --git a/Zend/tests/indirect_call_string_003.phpt b/Zend/tests/indirect_call_string_003.phpt index a6839df8a7..99289c4e1c 100644 --- a/Zend/tests/indirect_call_string_003.phpt +++ b/Zend/tests/indirect_call_string_003.phpt @@ -19,10 +19,7 @@ $callback = 'TestClass::method'; echo $callback(); ?> --EXPECTF-- -Deprecated: Non-static method TestClass::method() should not be called statically in %s on line %d - -Fatal error: Uncaught Error: Using $this when not in object context in %s:%d +Fatal error: Uncaught Error: Non-static method TestClass::method() cannot be called statically in %s:%d Stack trace: -#0 %s(%d): TestClass::method() -#1 {main} +#0 {main} thrown in %s on line %d diff --git a/Zend/tests/instanceof.phpt b/Zend/tests/instanceof.phpt index 97d67ff567..662185dcea 100644 --- a/Zend/tests/instanceof.phpt +++ b/Zend/tests/instanceof.phpt @@ -1,5 +1,5 @@ --TEST-- -instanceof shouldn't call __autoload +instanceof shouldn't call autoloader --FILE-- <?php spl_autoload_register(function ($name) { diff --git a/Zend/tests/instanceof_001.phpt b/Zend/tests/instanceof_001.phpt index 8c13a0478c..ae33dab4a5 100644 --- a/Zend/tests/instanceof_001.phpt +++ b/Zend/tests/instanceof_001.phpt @@ -8,7 +8,7 @@ var_dump($a instanceof stdClass); var_dump(new stdCLass instanceof stdClass); -$b = create_function('', 'return new stdClass;'); +$b = function() { return new stdClass; }; var_dump($b() instanceof stdClass); $c = array(new stdClass); @@ -22,8 +22,6 @@ var_dump("$a" instanceof stdClass); --EXPECTF-- bool(true) bool(true) - -Deprecated: Function create_function() is deprecated in %s on line %d bool(true) bool(true) bool(false) diff --git a/Zend/tests/interface_exists_001.phpt b/Zend/tests/interface_exists_001.phpt index ab20dd20ea..84e9c6df1e 100644 --- a/Zend/tests/interface_exists_001.phpt +++ b/Zend/tests/interface_exists_001.phpt @@ -9,13 +9,9 @@ interface foo { var_dump(interface_exists('foo')); var_dump(interface_exists(1)); var_dump(interface_exists(NULL)); -var_dump(interface_exists(new stdClass)); ?> ---EXPECTF-- +--EXPECT-- bool(true) bool(false) bool(false) - -Warning: interface_exists() expects parameter 1 to be string, object given in %s on line %d -NULL diff --git a/Zend/tests/is_a.phpt b/Zend/tests/is_a.phpt index 3714d50a62..f37c4638a8 100644 --- a/Zend/tests/is_a.phpt +++ b/Zend/tests/is_a.phpt @@ -1,5 +1,5 @@ --TEST-- -is_a() and is_subclass_of() shouldn't call __autoload +is_a() and is_subclass_of() shouldn't call autoloader --INI-- error_reporting=14335 --FILE-- diff --git a/Zend/tests/methods-on-non-objects-call-user-func.phpt b/Zend/tests/methods-on-non-objects-call-user-func.phpt index 027aa64c20..63884abc79 100644 --- a/Zend/tests/methods-on-non-objects-call-user-func.phpt +++ b/Zend/tests/methods-on-non-objects-call-user-func.phpt @@ -2,11 +2,12 @@ call_user_func() in combination with "Call to a member function method() on a non-object" --FILE-- <?php -$comparator= null; -var_dump(call_user_func([$comparator, 'compare'], 1, 2)); -echo "Alive\n"; +$comparator = null; +try { + var_dump(call_user_func([$comparator, 'compare'], 1, 2)); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} ?> ---EXPECTF-- -Warning: call_user_func() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in %s on line %d -NULL -Alive +--EXPECT-- +call_user_func() expects parameter 1 to be a valid callback, first array member is not a valid class name or object diff --git a/Zend/tests/nowdoc_015.phpt b/Zend/tests/nowdoc_015.phpt index 9eb83bd063..56de362dd5 100644 --- a/Zend/tests/nowdoc_015.phpt +++ b/Zend/tests/nowdoc_015.phpt @@ -2,7 +2,7 @@ Test nowdoc and line numbering --FILE-- <?php -function error_handler($num, $msg, $file, $line, $vars) { +function error_handler($num, $msg, $file, $line) { echo $line,"\n"; } set_error_handler('error_handler'); diff --git a/Zend/tests/ns_041.phpt b/Zend/tests/ns_041.phpt index bd9dfbd093..3a2fe7758b 100644 --- a/Zend/tests/ns_041.phpt +++ b/Zend/tests/ns_041.phpt @@ -17,5 +17,7 @@ ok ok ok -Warning: Use of undefined constant BAR - assumed 'BAR' (this will throw an Error in a future version of PHP) in %sns_041.php on line 9 -BAR +Fatal error: Uncaught Error: Undefined constant 'test\ns1\BAR' in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/ns_076.phpt b/Zend/tests/ns_076.phpt index ea97e924b1..0db8aeba62 100644 --- a/Zend/tests/ns_076.phpt +++ b/Zend/tests/ns_076.phpt @@ -3,26 +3,28 @@ --FILE-- <?php namespace foo; +use Error; -$a = array(unknown => unknown); - -echo unknown; -echo "\n"; -var_dump($a); -echo \unknown; ---EXPECTF-- -Warning: Use of undefined constant unknown - assumed 'unknown' (this will throw an Error in a future version of PHP) in %sns_076.php on line %d +try { + $a = array(unknown => unknown); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} -Warning: Use of undefined constant unknown - assumed 'unknown' (this will throw an Error in a future version of PHP) in %sns_076.php on line %d +try { + echo unknown; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} -Warning: Use of undefined constant unknown - assumed 'unknown' (this will throw an Error in a future version of PHP) in %sns_076.php on line %d -unknown -array(1) { - ["unknown"]=> - %s(7) "unknown" +try { + echo \unknown; +} catch (Error $e) { + echo $e->getMessage(), "\n"; } -Fatal error: Uncaught Error: Undefined constant 'unknown' in %sns_076.php:%d -Stack trace: -#0 {main} - thrown in %sns_076.php on line %d +?> +--EXPECT-- +Undefined constant 'foo\unknown' +Undefined constant 'foo\unknown' +Undefined constant 'unknown' diff --git a/Zend/tests/objects_027.phpt b/Zend/tests/objects_027.phpt index 6ee7d5a491..b579278f2e 100644 --- a/Zend/tests/objects_027.phpt +++ b/Zend/tests/objects_027.phpt @@ -17,26 +17,12 @@ class foo extends bar { $foo = new foo; $foo->test(); -$foo::test(); call_user_func(array($foo, 'test')); -call_user_func(array('foo', 'test')); ?> --EXPECTF-- object(foo)#%d (0) { } - -Deprecated: Non-static method foo::test() should not be called statically in %s on line %d - -Deprecated: Non-static method bar::show() should not be called statically in %s on line %d -object(foo)#%d (0) { -} -object(foo)#%d (0) { -} - -Deprecated: %son-static method foo::test() should not be called statically in %s on line %d - -Deprecated: Non-static method bar::show() should not be called statically in %s on line %d object(foo)#%d (0) { } diff --git a/Zend/tests/overloaded_func_001.phpt b/Zend/tests/overloaded_func_001.phpt index 31585d505a..7fc435f920 100644 --- a/Zend/tests/overloaded_func_001.phpt +++ b/Zend/tests/overloaded_func_001.phpt @@ -6,10 +6,10 @@ if (!extension_loaded('zend-test')) die('skip zend-test extension not loaded'); ?> --FILE-- <?php +$o = new _ZendTestChildClass(); +var_dump($o->test()); var_dump(_ZendTestClass::test()); ?> ---EXPECTF-- -Fatal error: Uncaught Error: Cannot call overloaded function for non-object in %soverloaded_func_001.php:%d -Stack trace: -#0 {main} - thrown in %soverloaded_func_001.php on line %d +--EXPECT-- +string(4) "test" +string(4) "test" diff --git a/Zend/tests/parse_str_with_unpack.phpt b/Zend/tests/parse_str_with_unpack.phpt deleted file mode 100644 index 8daa711374..0000000000 --- a/Zend/tests/parse_str_with_unpack.phpt +++ /dev/null @@ -1,16 +0,0 @@ ---TEST-- -Calling parse_str through argument unpacking ---FILE-- -<?php - -function test() { - $i = 0; - parse_str(...["i=41"]); - var_dump($i + 1); -} -test(); - -?> ---EXPECTF-- -Deprecated: parse_str(): Calling parse_str() without the result argument is deprecated in %s on line %d -int(42) diff --git a/Zend/tests/php_errormsg_misoptimization.phpt b/Zend/tests/php_errormsg_misoptimization.phpt deleted file mode 100644 index ae389db248..0000000000 --- a/Zend/tests/php_errormsg_misoptimization.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -The variable $php_errormsg shouldn't be optimized as it may be unpredictably modified ---INI-- -track_errors=1 ---FILE-- -<?php - -function test() { - $php_errormsg = 1; - echo $undef; - var_dump($php_errormsg + 1); -} -test(); - -?> ---EXPECTF-- -Deprecated: Directive 'track_errors' is deprecated in Unknown on line 0 - -Notice: Undefined variable: undef in %s on line %d - -Warning: A non-numeric value encountered in %s on line %d -int(1) diff --git a/Zend/tests/return_types/023.phpt b/Zend/tests/return_types/023.phpt deleted file mode 100644 index e8e8732ef1..0000000000 --- a/Zend/tests/return_types/023.phpt +++ /dev/null @@ -1,12 +0,0 @@ ---TEST-- -PHP 4 Constructors cannot declare a return type ---FILE-- -<?php - -class Foo { - function foo() : Foo {} -} ---EXPECTF-- -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; Foo has a deprecated constructor in %s on line %d - -Fatal error: Constructor %s::%s() cannot declare a return type in %s on line %d diff --git a/Zend/tests/this_in_mb_parse_str.phpt b/Zend/tests/this_in_mb_parse_str.phpt deleted file mode 100644 index 2d5af4794e..0000000000 --- a/Zend/tests/this_in_mb_parse_str.phpt +++ /dev/null @@ -1,21 +0,0 @@ ---TEST-- -$this re-assign in mb_parse_str() ---SKIPIF-- -<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?> ---FILE-- -<?php -function foo() { - mb_parse_str("this=42"); - var_dump($this); -} -foo(); -?> ---EXPECTF-- -Deprecated: mb_parse_str(): Calling mb_parse_str() without the result argument is deprecated in %s on line %d - -Fatal error: Uncaught Error: Cannot re-assign $this in %sthis_in_mb_parse_str.php:3 -Stack trace: -#0 %sthis_in_mb_parse_str.php(3): mb_parse_str('this=42') -#1 %sthis_in_mb_parse_str.php(6): foo() -#2 {main} - thrown in %sthis_in_mb_parse_str.php on line 3 diff --git a/Zend/tests/this_in_parse_str.phpt b/Zend/tests/this_in_parse_str.phpt deleted file mode 100644 index 0bd9064d60..0000000000 --- a/Zend/tests/this_in_parse_str.phpt +++ /dev/null @@ -1,19 +0,0 @@ ---TEST-- -$this re-assign in parse_str() ---FILE-- -<?php -function foo() { - parse_str("this=42"); - var_dump($this); -} -foo(); -?> ---EXPECTF-- -Deprecated: parse_str(): Calling parse_str() without the result argument is deprecated in %s on line %d - -Fatal error: Uncaught Error: Cannot re-assign $this in %sthis_in_parse_str.php:3 -Stack trace: -#0 %sthis_in_parse_str.php(3): parse_str('this=42') -#1 %sthis_in_parse_str.php(6): foo() -#2 {main} - thrown in %sthis_in_parse_str.php on line 3 diff --git a/Zend/tests/trait_exists_001.phpt b/Zend/tests/trait_exists_001.phpt index 10ce3fa0cb..8a7c55d586 100644 --- a/Zend/tests/trait_exists_001.phpt +++ b/Zend/tests/trait_exists_001.phpt @@ -9,13 +9,9 @@ trait foo { var_dump(trait_exists('foo')); var_dump(trait_exists(1)); var_dump(trait_exists(NULL)); -var_dump(trait_exists(new stdClass)); ?> ---EXPECTF-- +--EXPECT-- bool(true) bool(false) bool(false) - -Warning: trait_exists() expects parameter 1 to be string, object given in %s on line %d -NULL diff --git a/Zend/tests/traits/bug55554a.phpt b/Zend/tests/traits/bug55554a.phpt deleted file mode 100644 index dd844ba661..0000000000 --- a/Zend/tests/traits/bug55554a.phpt +++ /dev/null @@ -1,33 +0,0 @@ ---TEST-- -Bug #55137 (Legacy constructor not registered for class) ---FILE-- -<?php - -// All constructors should be registered as such - -trait TConstructor { - public function constructor() { - echo "ctor executed\n"; - } -} - -class NewConstructor { - use TConstructor { - constructor as __construct; - } -} - -class LegacyConstructor { - use TConstructor { - constructor as LegacyConstructor; - } -} - -echo "New constructor: "; -$o = new NewConstructor; - -echo "Legacy constructor: "; -$o = new LegacyConstructor; ---EXPECT-- -New constructor: ctor executed -Legacy constructor: ctor executed diff --git a/Zend/tests/traits/bug55554b.phpt b/Zend/tests/traits/bug55554b.phpt deleted file mode 100644 index 65ecb7adaf..0000000000 --- a/Zend/tests/traits/bug55554b.phpt +++ /dev/null @@ -1,55 +0,0 @@ ---TEST-- -Bug #55137 (Legacy constructor not registered for class) ---FILE-- -<?php - -trait TConstructor { - public function foo() { - echo "foo executed\n"; - } - public function bar() { - echo "bar executed\n"; - } -} - -class OverridingIsSilent1 { - use TConstructor { - foo as __construct; - } - - public function __construct() { - echo "OverridingIsSilent1 __construct\n"; - } -} - -$o = new OverridingIsSilent1; - -class OverridingIsSilent2 { - use TConstructor { - foo as OverridingIsSilent2; - } - - public function OverridingIsSilent2() { - echo "OverridingIsSilent2 OverridingIsSilent2\n"; - } -} - -$o = new OverridingIsSilent2; - -class ReportCollision { - use TConstructor { - bar as ReportCollision; - foo as __construct; - } -} - - -echo "ReportCollision: "; -$o = new ReportCollision; ---EXPECTF-- -OverridingIsSilent1 __construct - -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; OverridingIsSilent2 has a deprecated constructor in %s on line %d -OverridingIsSilent2 OverridingIsSilent2 - -Fatal error: ReportCollision has colliding constructor definitions coming from traits in %s on line %d diff --git a/Zend/tests/traits/bug55554c.phpt b/Zend/tests/traits/bug55554c.phpt deleted file mode 100644 index 420689259e..0000000000 --- a/Zend/tests/traits/bug55554c.phpt +++ /dev/null @@ -1,44 +0,0 @@ ---TEST-- -Bug #55137 (Legacy constructor not registered for class) ---FILE-- -<?php - -// Test that the behavior is consistent with the existing handling of new -// and legacy constructors. -// Here, the traits conflicts are overridden by local definitions, -// and the two constructor definitions do not directly collide in that case. - -trait TC1 { - public function __construct() { - echo "TC1 executed\n"; - } - public function ReportCollision() { - echo "TC1 executed\n"; - } -} - -trait TC2 { - public function __construct() { - echo "TC2 executed\n"; - } - public function ReportCollision() { - echo "TC1 executed\n"; - } -} - -class ReportCollision { - use TC1, TC2; - - public function __construct() { - echo "New constructor executed\n"; - } - public function ReportCollision() { - echo "Legacy constructor executed\n"; - } -} - - -echo "ReportCollision: "; -$o = new ReportCollision; ---EXPECT-- -ReportCollision: New constructor executed diff --git a/Zend/tests/traits/bug55554d.phpt b/Zend/tests/traits/bug55554d.phpt deleted file mode 100644 index 88564a83c1..0000000000 --- a/Zend/tests/traits/bug55554d.phpt +++ /dev/null @@ -1,29 +0,0 @@ ---TEST-- -Bug #55137 (Legacy constructor not registered for class) ---FILE-- -<?php - -// Test mixed constructors from different traits, we are more strict about -// these cases, since that can lead to un-expected behavior. -// It is not consistent with the normal constructor handling, but -// here we have a chance to be more strict for the new traits. - -trait TNew { - public function __construct() { - echo "TNew executed\n"; - } -} - -trait TLegacy { - public function ReportCollision() { - echo "ReportCollision executed\n"; - } -} - -class ReportCollision { - use TNew, TLegacy; -} - -$o = new ReportCollision; ---EXPECTF-- -Fatal error: ReportCollision has colliding constructor definitions coming from traits in %s on line %d diff --git a/Zend/tests/traits/bug55554e.phpt b/Zend/tests/traits/bug55554e.phpt deleted file mode 100644 index ed1c324831..0000000000 --- a/Zend/tests/traits/bug55554e.phpt +++ /dev/null @@ -1,28 +0,0 @@ ---TEST-- -Bug #55137 (Legacy constructor not registered for class) ---FILE-- -<?php - -// Ensuring that the collision still occurs as expected. - -trait TC1 { - public function ReportCollision() { - echo "TC1 executed\n"; - } -} - -trait TC2 { - public function ReportCollision() { - echo "TC1 executed\n"; - } -} - -class ReportCollision { - use TC1, TC2; -} - - -echo "ReportCollision: "; -$o = new ReportCollision; ---EXPECTF-- -Fatal error: Trait method ReportCollision has not been applied, because there are collisions with other trait methods on ReportCollision in %s on line %d diff --git a/Zend/tests/traits/bug55554f.phpt b/Zend/tests/traits/bug55554f.phpt deleted file mode 100644 index d7d4fc007d..0000000000 --- a/Zend/tests/traits/bug55554f.phpt +++ /dev/null @@ -1,27 +0,0 @@ ---TEST-- -Bug #55137 (Legacy constructor not registered for class) ---FILE-- -<?php - -// Ensuring that inconsistent constructor use results in an error to avoid -// problems creeping in. - -trait TNew { - public function __construct() { - echo "TNew executed\n"; - } -} - -class ReportCollision { - use TNew; - - public function ReportCollision() { - echo "ReportCollision executed\n"; - } -} - - -echo "ReportCollision: "; -$o = new ReportCollision; ---EXPECTF-- -Fatal error: ReportCollision has colliding constructor definitions coming from traits in %s on line %d diff --git a/Zend/tests/traits/bug55554g.phpt b/Zend/tests/traits/bug55554g.phpt deleted file mode 100644 index d7de8216b0..0000000000 --- a/Zend/tests/traits/bug55554g.phpt +++ /dev/null @@ -1,27 +0,0 @@ ---TEST-- -Bug #55137 (Legacy constructor not registered for class) ---FILE-- -<?php - -// Ensuring that inconsistent constructor use results in an error to avoid -// problems creeping in. - -trait TLegacy { - public function ReportCollision() { - echo "TLegacy executed\n"; - } -} - -class ReportCollision { - use TLegacy; - - public function __construct() { - echo "ReportCollision executed\n"; - } -} - - -echo "ReportCollision: "; -$o = new ReportCollision; ---EXPECTF-- -Fatal error: ReportCollision has colliding constructor definitions coming from traits in %s on line %d diff --git a/Zend/tests/traits/noctor001.phpt b/Zend/tests/traits/noctor001.phpt deleted file mode 100644 index 19fe8dbd0d..0000000000 --- a/Zend/tests/traits/noctor001.phpt +++ /dev/null @@ -1,29 +0,0 @@ ---TEST-- -Don't mark trait methods as constructor ---FILE-- -<?php -trait Foo { - public function Foo() { - } -} - -class Bar { - use Foo; - public function Bar() { - } -} - -$rfoofoo = new ReflectionMethod('Foo::Foo'); -var_dump($rfoofoo->isConstructor()); - -$rbarfoo = new ReflectionMethod('Bar::Foo'); -var_dump($rbarfoo->isConstructor()); - -$rbarbar = new ReflectionMethod('Bar::Bar'); -var_dump($rbarbar->isConstructor()); -?> ---EXPECTF-- -Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; Bar has a deprecated constructor in %s on line %d -bool(false) -bool(false) -bool(true) diff --git a/Zend/tests/type_declarations/callable_001.phpt b/Zend/tests/type_declarations/callable_001.phpt index 3113bedcf0..d93e70923a 100644 --- a/Zend/tests/type_declarations/callable_001.phpt +++ b/Zend/tests/type_declarations/callable_001.phpt @@ -14,19 +14,13 @@ $closure = function () {}; foo("strpos"); foo("foo"); -foo(array("bar", "baz")); -foo(array("bar", "foo")); foo($closure); +foo(array("bar", "foo")); +foo(array("bar", "baz")); --EXPECTF-- string(6) "strpos" string(3) "foo" - -Deprecated: Non-static method bar::baz() should not be called statically in %s on line %d -array(2) { - [0]=> - string(3) "bar" - [1]=> - string(3) "baz" +object(Closure)#1 (0) { } array(2) { [0]=> @@ -34,5 +28,9 @@ array(2) { [1]=> string(3) "foo" } -object(Closure)#%d (0) { -} + +Fatal error: Uncaught TypeError: Argument 1 passed to foo() must be callable, array given, called in %s on line %d and defined in %s:%d +Stack trace: +#0 %s(%d): foo(Array) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/unexpected_ref_bug.phpt b/Zend/tests/unexpected_ref_bug.phpt index ba61ee582a..c7f66f05a0 100644 --- a/Zend/tests/unexpected_ref_bug.phpt +++ b/Zend/tests/unexpected_ref_bug.phpt @@ -2,16 +2,17 @@ Crash when function parameter modified via unexpected reference --FILE-- <?php -function my_errorhandler($errno,$errormsg) { - global $my_var; - $my_var = 0; - return true; +class Test { + public function __toString() { + global $my_var; + $my_var = 0; + return ","; + } } -set_error_handler("my_errorhandler"); $my_var = str_repeat("A",64); -$data = call_user_func_array("explode",array(new StdClass(), &$my_var)); +$data = call_user_func_array("explode",array(new Test(), &$my_var)); $my_var=array(1,2,3); -$data = call_user_func_array("implode",array(&$my_var, new StdClass())); +$data = call_user_func_array("implode",array(&$my_var, new Test())); echo "Done.\n"; ?> --EXPECT-- diff --git a/Zend/tests/unset_cast_deprecated.phpt b/Zend/tests/unset_cast_deprecated.phpt deleted file mode 100644 index 6744c85f02..0000000000 --- a/Zend/tests/unset_cast_deprecated.phpt +++ /dev/null @@ -1,14 +0,0 @@ ---TEST-- -The (unset) cast is deprecated ---FILE-- -<?php - -$x = 1; -var_dump((unset) $x); -var_dump($x); - -?> ---EXPECTF-- -Deprecated: The (unset) cast is deprecated in %s on line %d -NULL -int(1) diff --git a/Zend/tests/unset_cast_removed.phpt b/Zend/tests/unset_cast_removed.phpt new file mode 100644 index 0000000000..9f2f798ed0 --- /dev/null +++ b/Zend/tests/unset_cast_removed.phpt @@ -0,0 +1,12 @@ +--TEST-- +The (unset) cast is removed +--FILE-- +<?php + +$x = 1; +var_dump((unset) $x); +var_dump($x); + +?> +--EXPECTF-- +Fatal error: The (unset) cast is no longer supported in %s on line %d diff --git a/Zend/zend.c b/Zend/zend.c index 36f47ee08f..3334481961 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -1244,14 +1244,13 @@ static ZEND_COLD void zend_error_va_list( const char *format, va_list args) { va_list usr_copy; - zval params[5]; + zval params[4]; zval retval; zval orig_user_error_handler; zend_bool in_compilation; zend_class_entry *saved_class_entry; zend_stack loop_var_stack; zend_stack delayed_oplines_stack; - zend_array *symbol_table; zend_class_entry *orig_fake_scope; /* Report about uncaught exception in case of fatal errors */ @@ -1326,15 +1325,6 @@ static ZEND_COLD void zend_error_va_list( ZVAL_LONG(¶ms[3], error_lineno); - symbol_table = zend_rebuild_symbol_table(); - - /* during shutdown the symbol table table can be still null */ - if (!symbol_table) { - ZVAL_NULL(¶ms[4]); - } else { - ZVAL_ARR(¶ms[4], zend_array_dup(symbol_table)); - } - ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler)); ZVAL_UNDEF(&EG(user_error_handler)); @@ -1355,7 +1345,7 @@ static ZEND_COLD void zend_error_va_list( orig_fake_scope = EG(fake_scope); EG(fake_scope) = NULL; - if (call_user_function(CG(function_table), NULL, &orig_user_error_handler, &retval, 5, params) == SUCCESS) { + if (call_user_function(CG(function_table), NULL, &orig_user_error_handler, &retval, 4, params) == SUCCESS) { if (Z_TYPE(retval) != IS_UNDEF) { if (Z_TYPE(retval) == IS_FALSE) { zend_error_cb(type, error_filename, error_lineno, format, args); @@ -1376,7 +1366,6 @@ static ZEND_COLD void zend_error_va_list( CG(in_compilation) = 1; } - zval_ptr_dtor(¶ms[4]); zval_ptr_dtor(¶ms[2]); zval_ptr_dtor(¶ms[1]); @@ -1552,35 +1541,14 @@ ZEND_API ZEND_COLD void zend_type_error(const char *format, ...) /* {{{ */ va_end(va); } /* }}} */ -ZEND_API ZEND_COLD void zend_internal_type_error(zend_bool throw_exception, const char *format, ...) /* {{{ */ +ZEND_API ZEND_COLD void zend_argument_count_error(const char *format, ...) /* {{{ */ { va_list va; char *message = NULL; va_start(va, format); zend_vspprintf(&message, 0, format, va); - if (throw_exception) { - zend_throw_exception(zend_ce_type_error, message, 0); - } else { - zend_error(E_WARNING, "%s", message); - } - efree(message); - - va_end(va); -} /* }}} */ - -ZEND_API ZEND_COLD void zend_internal_argument_count_error(zend_bool throw_exception, const char *format, ...) /* {{{ */ -{ - va_list va; - char *message = NULL; - - va_start(va, format); - zend_vspprintf(&message, 0, format, va); - if (throw_exception) { - zend_throw_exception(zend_ce_argument_count_error, message, 0); - } else { - zend_error(E_WARNING, "%s", message); - } + zend_throw_exception(zend_ce_argument_count_error, message, 0); efree(message); va_end(va); diff --git a/Zend/zend.h b/Zend/zend.h index 86b10ea58e..600db9204f 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "3.4.0-dev" +#define ZEND_VERSION "4.0.0-dev" #define ZEND_ENGINE_3 @@ -300,8 +300,7 @@ ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_at_noreturn(int type, const cha ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); ZEND_API ZEND_COLD void zend_type_error(const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 1, 2); -ZEND_API ZEND_COLD void zend_internal_type_error(zend_bool throw_exception, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); -ZEND_API ZEND_COLD void zend_internal_argument_count_error(zend_bool throw_exception, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); +ZEND_API ZEND_COLD void zend_argument_count_error(const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 1, 2); ZEND_COLD void zenderror(const char *error); diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 881ee27a03..00161da07e 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -90,7 +90,7 @@ ZEND_API ZEND_COLD void zend_wrong_param_count(void) /* {{{ */ const char *space; const char *class_name = get_active_class_name(&space); - zend_internal_argument_count_error(ZEND_ARG_USES_STRICT_TYPES(), "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name()); + zend_argument_count_error("Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name()); } /* }}} */ @@ -173,28 +173,7 @@ ZEND_API ZEND_COLD int ZEND_FASTCALL zend_wrong_parameters_none_error(void) /* { zend_function *active_function = EG(current_execute_data)->func; const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : ""; - zend_internal_argument_count_error( - ZEND_ARG_USES_STRICT_TYPES(), - "%s%s%s() expects %s %d parameter%s, %d given", - class_name, \ - class_name[0] ? "::" : "", \ - ZSTR_VAL(active_function->common.function_name), - "exactly", - 0, - "s", - num_args); - return FAILURE; -} -/* }}} */ - -ZEND_API ZEND_COLD int ZEND_FASTCALL zend_wrong_parameters_none_exception(void) /* {{{ */ -{ - int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data)); - zend_function *active_function = EG(current_execute_data)->func; - const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : ""; - - zend_internal_argument_count_error( - 1, + zend_argument_count_error( "%s%s%s() expects %s %d parameter%s, %d given", class_name, \ class_name[0] ? "::" : "", \ @@ -213,27 +192,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_error(int min_ zend_function *active_function = EG(current_execute_data)->func; const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : ""; - zend_internal_argument_count_error( - ZEND_ARG_USES_STRICT_TYPES(), - "%s%s%s() expects %s %d parameter%s, %d given", - class_name, \ - class_name[0] ? "::" : "", \ - ZSTR_VAL(active_function->common.function_name), - min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most", - num_args < min_num_args ? min_num_args : max_num_args, - (num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s", - num_args); -} -/* }}} */ - -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_exception(int min_num_args, int max_num_args) /* {{{ */ -{ - int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data)); - zend_function *active_function = EG(current_execute_data)->func; - const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : ""; - - zend_internal_argument_count_error( - 1, + zend_argument_count_error( "%s%s%s() expects %s %d parameter%s, %d given", class_name, \ class_name[0] ? "::" : "", \ @@ -254,21 +213,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(int num, z NULL }; - zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be %s, %s given", - class_name, space, get_active_function_name(), num, expected_error[expected_type], zend_zval_type_name(arg)); -} -/* }}} */ - -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_exception(int num, zend_expected_type expected_type, zval *arg) /* {{{ */ -{ - const char *space; - const char *class_name = get_active_class_name(&space); - static const char * const expected_error[] = { - Z_EXPECTED_TYPES(Z_EXPECTED_TYPE_STR) - NULL - }; - - zend_internal_type_error(1, "%s%s%s() expects parameter %d to be %s, %s given", + zend_type_error("%s%s%s() expects parameter %d to be %s, %s given", class_name, space, get_active_function_name(), num, expected_error[expected_type], zend_zval_type_name(arg)); } /* }}} */ @@ -278,17 +223,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(int num, const char *space; const char *class_name = get_active_class_name(&space); - zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be %s, %s given", - class_name, space, get_active_function_name(), num, name, zend_zval_type_name(arg)); -} -/* }}} */ - -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_exception(int num, char *name, zval *arg) /* {{{ */ -{ - const char *space; - const char *class_name = get_active_class_name(&space); - - zend_internal_type_error(1, "%s%s%s() expects parameter %d to be %s, %s given", + zend_type_error("%s%s%s() expects parameter %d to be %s, %s given", class_name, space, get_active_function_name(), num, name, zend_zval_type_name(arg)); } /* }}} */ @@ -298,29 +233,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(int num, char *e const char *space; const char *class_name = get_active_class_name(&space); - zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a valid callback, %s", - class_name, space, get_active_function_name(), num, error); - efree(error); -} -/* }}} */ - -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, char *error) /* {{{ */ -{ - const char *space; - const char *class_name = get_active_class_name(&space); - - zend_internal_type_error(1, "%s%s%s() expects parameter %d to be a valid callback, %s", - class_name, space, get_active_function_name(), num, error); - efree(error); -} -/* }}} */ - -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_deprecated(int num, char *error) /* {{{ */ -{ - const char *space; - const char *class_name = get_active_class_name(&space); - - zend_error(E_DEPRECATED, "%s%s%s() expects parameter %d to be a valid callback, %s", + zend_type_error("%s%s%s() expects parameter %d to be a valid callback, %s", class_name, space, get_active_function_name(), num, error); efree(error); } @@ -341,7 +254,7 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **pc const char *space; const char *class_name = get_active_class_name(&space); - zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a class name derived from %s, '%s' given", + zend_type_error("%s%s%s() expects parameter %d to be a class name derived from %s, '%s' given", class_name, space, get_active_function_name(), num, ZSTR_VAL(ce_base->name), Z_STRVAL_P(arg)); *pce = NULL; @@ -352,7 +265,7 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **pc const char *space; const char *class_name = get_active_class_name(&space); - zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a valid class name, '%s' given", + zend_type_error("%s%s%s() expects parameter %d to be a valid class name, '%s' given", class_name, space, get_active_function_name(), num, Z_STRVAL_P(arg)); return 0; @@ -515,20 +428,22 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest convert_to_string(arg); *dest = Z_STR_P(arg); } else if (UNEXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) { + zend_object *zobj = Z_OBJ_P(arg); + if (Z_OBJ_HANDLER_P(arg, cast_object)) { zval obj; - if (Z_OBJ_HANDLER_P(arg, cast_object)(arg, &obj, IS_STRING) == SUCCESS) { - zval_ptr_dtor(arg); + if (zobj->handlers->cast_object(zobj, &obj, IS_STRING) == SUCCESS) { + OBJ_RELEASE(zobj); ZVAL_COPY_VALUE(arg, &obj); *dest = Z_STR_P(arg); return 1; } - } else if (Z_OBJ_HANDLER_P(arg, get)) { + } else if (zobj->handlers->get) { zval rv; - zval *z = Z_OBJ_HANDLER_P(arg, get)(arg, &rv); + zval *z = zobj->handlers->get(zobj, &rv); if (Z_TYPE_P(z) != IS_OBJECT) { - zval_ptr_dtor(arg); + OBJ_RELEASE(zobj); if (Z_TYPE_P(z) == IS_STRING) { ZVAL_COPY_VALUE(arg, z); } else { @@ -557,7 +472,7 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, zend_string **dest } /* }}} */ -static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, const char **spec, char **error, int *severity) /* {{{ */ +static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, const char **spec, char **error) /* {{{ */ { const char *spec_walk = *spec; char c = *spec_walk++; @@ -768,23 +683,16 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons } if (zend_fcall_info_init(arg, 0, fci, fcc, NULL, &is_callable_error) == SUCCESS) { - if (is_callable_error) { - *severity = E_DEPRECATED; - zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error); - efree(is_callable_error); - *spec = spec_walk; - return ""; - } + ZEND_ASSERT(!is_callable_error); break; + } + + if (is_callable_error) { + zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error); + efree(is_callable_error); + return ""; } else { - if (is_callable_error) { - *severity = E_ERROR; - zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error); - efree(is_callable_error); - return ""; - } else { - return "valid callback"; - } + return "valid callback"; } } @@ -813,30 +721,24 @@ static int zend_parse_arg(int arg_num, zval *arg, va_list *va, const char **spec { const char *expected_type = NULL; char *error = NULL; - int severity = 0; - expected_type = zend_parse_arg_impl(arg_num, arg, va, spec, &error, &severity); + expected_type = zend_parse_arg_impl(arg_num, arg, va, spec, &error); if (expected_type) { if (!(flags & ZEND_PARSE_PARAMS_QUIET) && (*expected_type || error)) { const char *space; const char *class_name = get_active_class_name(&space); - zend_bool throw_exception = - ZEND_ARG_USES_STRICT_TYPES() || (flags & ZEND_PARSE_PARAMS_THROW); if (error) { - zend_internal_type_error(throw_exception, "%s%s%s() expects parameter %d %s", + zend_type_error("%s%s%s() expects parameter %d %s", class_name, space, get_active_function_name(), arg_num, error); efree(error); } else { - zend_internal_type_error(throw_exception, - "%s%s%s() expects parameter %d to be %s, %s given", + zend_type_error("%s%s%s() expects parameter %d to be %s, %s given", class_name, space, get_active_function_name(), arg_num, expected_type, zend_zval_type_name(arg)); } } - if (severity != E_DEPRECATED) { - return FAILURE; - } + return FAILURE; } return SUCCESS; @@ -938,8 +840,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, if (!(flags & ZEND_PARSE_PARAMS_QUIET)) { zend_function *active_function = EG(current_execute_data)->func; const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : ""; - zend_bool throw_exception = ZEND_ARG_USES_STRICT_TYPES() || (flags & ZEND_PARSE_PARAMS_THROW); - zend_internal_argument_count_error(throw_exception, "%s%s%s() expects %s %d parameter%s, %d given", + zend_argument_count_error("%s%s%s() expects %s %d parameter%s, %d given", class_name, class_name[0] ? "::" : "", ZSTR_VAL(active_function->common.function_name), @@ -1032,7 +933,7 @@ ZEND_API int zend_parse_parameters_throw(int num_args, const char *type_spec, .. { va_list va; int retval; - int flags = ZEND_PARSE_PARAMS_THROW; + int flags = 0; va_start(va, type_spec); retval = zend_parse_va_args(num_args, type_spec, &va, flags); @@ -1122,7 +1023,8 @@ ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args, zval *this * because it may call __set from the uninitialized object otherwise. */ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */ { - const zend_object_handlers *obj_ht = Z_OBJ_HT_P(obj); + zend_object *zobj = Z_OBJ_P(obj); + zend_object_write_property_t write_property = zobj->handlers->write_property; zend_class_entry *old_scope = EG(fake_scope); zend_string *key; zval *value; @@ -1130,10 +1032,7 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */ EG(fake_scope) = Z_OBJCE_P(obj); ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, value) { if (key) { - zval member; - - ZVAL_STR(&member, key); - obj_ht->write_property(obj, &member, value, NULL); + write_property(zobj, key, value, NULL); } } ZEND_HASH_FOREACH_END(); EG(fake_scope) = old_scope; @@ -1749,11 +1648,11 @@ ZEND_API int add_property_stringl_ex(zval *arg, const char *key, size_t key_len, ZEND_API int add_property_zval_ex(zval *arg, const char *key, size_t key_len, zval *value) /* {{{ */ { - zval z_key; + zend_string *str; - ZVAL_STRINGL(&z_key, key, key_len); - Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, value, NULL); - zval_ptr_dtor(&z_key); + str = zend_string_init(key, key_len, 0); + Z_OBJ_HANDLER_P(arg, write_property)(Z_OBJ_P(arg), str, value, NULL); + zend_string_release_ex(str, 0); return SUCCESS; } /* }}} */ @@ -2262,13 +2161,8 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio } if (scope) { - /* Look for ctor, dtor, clone - * If it's an old-style constructor, store it only if we don't have - * a constructor already. - */ - if ((fname_len == class_name_len) && !ctor && !memcmp(ZSTR_VAL(lowercase_name), lc_class_name, class_name_len+1)) { - ctor = reg_function; - } else if (zend_string_equals_literal(lowercase_name, "serialize")) { + /* Look for ctor, dtor, clone */ + if (zend_string_equals_literal(lowercase_name, "serialize")) { serialize_func = reg_function; } else if (zend_string_equals_literal(lowercase_name, "unserialize")) { unserialize_func = reg_function; @@ -2350,26 +2244,22 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio if (ctor->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Constructor %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(ctor->common.function_name)); } - ctor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (dtor) { dtor->common.fn_flags |= ZEND_ACC_DTOR; if (dtor->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Destructor %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(dtor->common.function_name)); } - dtor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (clone) { if (clone->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "%s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(clone->common.function_name)); } - clone->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__call) { if (__call->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__call->common.function_name)); } - __call->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__callstatic) { if (!(__callstatic->common.fn_flags & ZEND_ACC_STATIC)) { @@ -2381,31 +2271,26 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio if (__tostring->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__tostring->common.function_name)); } - __tostring->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__get) { if (__get->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__get->common.function_name)); } - __get->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__set) { if (__set->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__set->common.function_name)); } - __set->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__unset) { if (__unset->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__unset->common.function_name)); } - __unset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__isset) { if (__isset->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__isset->common.function_name)); } - __isset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (__debugInfo) { if (__debugInfo->common.fn_flags & ZEND_ACC_STATIC) { @@ -2909,11 +2794,8 @@ static int zend_is_callable_check_class(zend_string *name, zend_class_entry *sco ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc) { if (fcc->function_handler && - ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) || - fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY || - fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) { - if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION && - fcc->function_handler->common.function_name) { + (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) { + if (fcc->function_handler->common.function_name) { zend_string_release_ex(fcc->function_handler->common.function_name, 0); } zend_free_trampoline(fcc->function_handler); @@ -3071,8 +2953,7 @@ get_function_via_handler: (!fcc->function_handler->common.scope || !instanceof_function(ce_org, fcc->function_handler->common.scope))) { if (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) { - if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION && - fcc->function_handler->common.function_name) { + if (fcc->function_handler->common.function_name) { zend_string_release_ex(fcc->function_handler->common.function_name, 0); } zend_free_trampoline(fcc->function_handler); @@ -3106,38 +2987,14 @@ get_function_via_handler: if (retval) { if (fcc->calling_scope && !call_via_handler) { if (fcc->function_handler->common.fn_flags & ZEND_ACC_ABSTRACT) { + retval = 0; if (error) { zend_spprintf(error, 0, "cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name)); - retval = 0; - } else { - zend_throw_error(NULL, "Cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name)); - retval = 0; } } else if (!fcc->object && !(fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) { - int severity; - char *verb; - if (fcc->function_handler->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - severity = E_DEPRECATED; - verb = "should not"; - } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - severity = E_ERROR; - verb = "cannot"; - } - if ((check_flags & IS_CALLABLE_CHECK_IS_STATIC) != 0) { - retval = 0; - } + retval = 0; if (error) { - zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name), verb); - if (severity != E_DEPRECATED) { - retval = 0; - } - } else if (retval) { - if (severity == E_ERROR) { - zend_throw_error(NULL, "Non-static method %s::%s() %s be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name), verb); - } else { - zend_error(severity, "Non-static method %s::%s() %s be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name), verb); - } + zend_spprintf(error, 0, "non-static method %s::%s() cannot be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name)); } } if (retval @@ -3224,16 +3081,18 @@ try_again: zend_class_entry *calling_scope; zend_function *fptr; zend_object *object; - if (Z_OBJ_HANDLER_P(callable, get_closure) - && Z_OBJ_HANDLER_P(callable, get_closure)(callable, &calling_scope, &fptr, &object) == SUCCESS) { - zend_class_entry *ce = Z_OBJCE_P(callable); + zend_object *zobj = Z_OBJ_P(callable); + + if (zobj->handlers->get_closure + && zobj->handlers->get_closure(zobj, &calling_scope, &fptr, &object) == SUCCESS) { + zend_class_entry *ce = zobj->ce; zend_string *callable_name = zend_string_alloc( ZSTR_LEN(ce->name) + sizeof("::__invoke") - 1, 0); memcpy(ZSTR_VAL(callable_name), ZSTR_VAL(ce->name), ZSTR_LEN(ce->name)); memcpy(ZSTR_VAL(callable_name) + ZSTR_LEN(ce->name), "::__invoke", sizeof("::__invoke")); return callable_name; } - return zval_get_string(callable); + return zval_get_string_func(callable); } case IS_REFERENCE: callable = Z_REFVAL_P(callable); @@ -3350,7 +3209,7 @@ check_func: } return 0; case IS_OBJECT: - if (Z_OBJ_HANDLER_P(callable, get_closure) && Z_OBJ_HANDLER_P(callable, get_closure)(callable, &fcc->calling_scope, &fcc->function_handler, &fcc->object) == SUCCESS) { + if (Z_OBJ_HANDLER_P(callable, get_closure) && Z_OBJ_HANDLER_P(callable, get_closure)(Z_OBJ_P(callable), &fcc->calling_scope, &fcc->function_handler, &fcc->object) == SUCCESS) { fcc->called_scope = fcc->calling_scope; if (fcc == &fcc_local) { zend_release_fcall_info_cache(fcc); @@ -3388,7 +3247,7 @@ ZEND_API zend_bool zend_make_callable(zval *callable, zend_string **callable_nam { zend_fcall_info_cache fcc; - if (zend_is_callable_ex(callable, NULL, IS_CALLABLE_STRICT, callable_name, &fcc, NULL)) { + if (zend_is_callable_ex(callable, NULL, 0, callable_name, &fcc, NULL)) { if (Z_TYPE_P(callable) == IS_STRING && fcc.calling_scope) { zval_ptr_dtor_str(callable); array_init(callable); @@ -4012,13 +3871,11 @@ ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char ZEND_API void zend_update_property_ex(zend_class_entry *scope, zval *object, zend_string *name, zval *value) /* {{{ */ { - zval property; zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = scope; - ZVAL_STR(&property, name); - Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL); + Z_OBJ_HT_P(object)->write_property(Z_OBJ_P(object), name, value, NULL); EG(fake_scope) = old_scope; } @@ -4026,14 +3883,14 @@ ZEND_API void zend_update_property_ex(zend_class_entry *scope, zval *object, zen ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zval *value) /* {{{ */ { - zval property; + zend_string *property; zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = scope; - ZVAL_STRINGL(&property, name, name_length); - Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL); - zval_ptr_dtor(&property); + property = zend_string_init(name, name_length, 0); + Z_OBJ_HT_P(object)->write_property(Z_OBJ_P(object), property, value, NULL); + zend_string_release_ex(property, 0); EG(fake_scope) = old_scope; } @@ -4050,14 +3907,14 @@ ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, c ZEND_API void zend_unset_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length) /* {{{ */ { - zval property; + zend_string *property; zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = scope; - ZVAL_STRINGL(&property, name, name_length); - Z_OBJ_HT_P(object)->unset_property(object, &property, 0); - zval_ptr_dtor(&property); + property = zend_string_init(name, name_length, 0); + Z_OBJ_HT_P(object)->unset_property(Z_OBJ_P(object), property, 0); + zend_string_release_ex(property, 0); EG(fake_scope) = old_scope; } @@ -4216,13 +4073,12 @@ ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const ZEND_API zval *zend_read_property_ex(zend_class_entry *scope, zval *object, zend_string *name, zend_bool silent, zval *rv) /* {{{ */ { - zval property, *value; + zval *value; zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = scope; - ZVAL_STR(&property, name); - value = Z_OBJ_HT_P(object)->read_property(object, &property, silent?BP_VAR_IS:BP_VAR_R, NULL, rv); + value = Z_OBJ_HT_P(object)->read_property(Z_OBJ_P(object), name, silent?BP_VAR_IS:BP_VAR_R, NULL, rv); EG(fake_scope) = old_scope; return value; diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 00a39f6624..30b24d10af 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -248,12 +248,12 @@ ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array); #define zend_parse_parameters_none() \ (EXPECTED(ZEND_NUM_ARGS() == 0) ? SUCCESS : zend_wrong_parameters_none_error()) #define zend_parse_parameters_none_throw() \ - (EXPECTED(ZEND_NUM_ARGS() == 0) ? SUCCESS : zend_wrong_parameters_none_exception()) + zend_parse_parameters_none() /* Parameter parsing API -- andrei */ +#define ZEND_PARSE_PARAMS_THROW 0 /* No longer used, zpp always uses exceptions */ #define ZEND_PARSE_PARAMS_QUIET (1<<1) -#define ZEND_PARSE_PARAMS_THROW (1<<2) ZEND_API int zend_parse_parameters(int num_args, const char *type_spec, ...); ZEND_API int zend_parse_parameters_ex(int flags, int num_args, const char *type_spec, ...); ZEND_API int zend_parse_parameters_throw(int num_args, const char *type_spec, ...); @@ -297,11 +297,8 @@ ZEND_API ZEND_COLD void zend_wrong_param_count(void); #define IS_CALLABLE_CHECK_SYNTAX_ONLY (1<<0) #define IS_CALLABLE_CHECK_NO_ACCESS (1<<1) -#define IS_CALLABLE_CHECK_IS_STATIC (1<<2) #define IS_CALLABLE_CHECK_SILENT (1<<3) -#define IS_CALLABLE_STRICT (IS_CALLABLE_CHECK_IS_STATIC) - ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc); ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *object); ZEND_API zend_string *zend_get_callable_name(zval *callable); @@ -472,7 +469,6 @@ ZEND_API extern const zend_fcall_info_cache empty_fcall_info_cache; * fci->param_count = 0; * fci->params = NULL; * The callable_name argument may be NULL. - * Set check_flags to IS_CALLABLE_STRICT for every new usage! */ ZEND_API int zend_fcall_info_init(zval *callable, uint32_t check_flags, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string **callable_name, char **error); @@ -637,7 +633,7 @@ END_EXTERN_C() #define RETURN_FALSE { RETVAL_FALSE; return; } #define RETURN_TRUE { RETVAL_TRUE; return; } -#define HASH_OF(p) (Z_TYPE_P(p)==IS_ARRAY ? Z_ARRVAL_P(p) : ((Z_TYPE_P(p)==IS_OBJECT ? Z_OBJ_HT_P(p)->get_properties((p)) : NULL))) +#define HASH_OF(p) (Z_TYPE_P(p)==IS_ARRAY ? Z_ARRVAL_P(p) : ((Z_TYPE_P(p)==IS_OBJECT ? Z_OBJ_HT_P(p)->get_properties(Z_OBJ_P(p)) : NULL))) #define ZVAL_IS_NULL(z) (Z_TYPE_P(z) == IS_NULL) /* For compatibility */ @@ -962,16 +958,10 @@ typedef enum _zend_expected_type { } zend_expected_type; ZEND_API ZEND_COLD int ZEND_FASTCALL zend_wrong_parameters_none_error(void); -ZEND_API ZEND_COLD int ZEND_FASTCALL zend_wrong_parameters_none_exception(void); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_error(int min_num_args, int max_num_args); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_exception(int min_num_args, int max_num_args); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(int num, zend_expected_type expected_type, zval *arg); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_exception(int num, zend_expected_type expected_type, zval *arg); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(int num, char *name, zval *arg); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_exception(int num, char *name, zval *arg); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(int num, char *error); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_deprecated(int num, char *error); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, char *error); #define ZPP_ERROR_OK 0 #define ZPP_ERROR_FAILURE 1 @@ -1005,11 +995,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, cha (UNEXPECTED(_num_args > _max_num_args) && \ EXPECTED(_max_num_args >= 0))) { \ if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \ - if (_flags & ZEND_PARSE_PARAMS_THROW) { \ - zend_wrong_parameters_count_exception(_min_num_args, _max_num_args); \ - } else { \ - zend_wrong_parameters_count_error(_min_num_args, _max_num_args); \ - } \ + zend_wrong_parameters_count_error(_min_num_args, _max_num_args); \ } \ _error_code = ZPP_ERROR_FAILURE; \ break; \ @@ -1032,23 +1018,11 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, cha if (UNEXPECTED(_error_code != ZPP_ERROR_OK)) { \ if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \ if (_error_code == ZPP_ERROR_WRONG_CALLBACK) { \ - if (_flags & ZEND_PARSE_PARAMS_THROW) { \ - zend_wrong_callback_exception(_i, _error); \ - } else { \ - zend_wrong_callback_error(_i, _error); \ - } \ + zend_wrong_callback_error(_i, _error); \ } else if (_error_code == ZPP_ERROR_WRONG_CLASS) { \ - if (_flags & ZEND_PARSE_PARAMS_THROW) { \ - zend_wrong_parameter_class_exception(_i, _error, _arg); \ - } else { \ - zend_wrong_parameter_class_error(_i, _error, _arg); \ - } \ + zend_wrong_parameter_class_error(_i, _error, _arg); \ } else if (_error_code == ZPP_ERROR_WRONG_ARG) { \ - if (_flags & ZEND_PARSE_PARAMS_THROW) { \ - zend_wrong_parameter_type_exception(_i, _expected_type, _arg); \ - } else { \ - zend_wrong_parameter_type_error(_i, _expected_type, _arg); \ - } \ + zend_wrong_parameter_type_error(_i, _expected_type, _arg); \ } \ } \ failure; \ @@ -1161,14 +1135,11 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, cha if (!_error) { \ _expected_type = Z_EXPECTED_FUNC; \ _error_code = ZPP_ERROR_WRONG_ARG; \ - break; \ } else { \ _error_code = ZPP_ERROR_WRONG_CALLBACK; \ - break; \ } \ - } else if (UNEXPECTED(_error != NULL)) { \ - zend_wrong_callback_deprecated(_i, _error); \ - } + break; \ + } \ #define Z_PARAM_FUNC_EX(dest_fci, dest_fcc, check_null, separate) \ Z_PARAM_FUNC_EX2(dest_fci, dest_fcc, check_null, separate, separate) @@ -1524,15 +1495,16 @@ static zend_always_inline int zend_parse_arg_array_ht(zval *arg, HashTable **des if (EXPECTED(Z_TYPE_P(arg) == IS_ARRAY)) { *dest = Z_ARRVAL_P(arg); } else if (or_object && EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) { + zend_object *zobj = Z_OBJ_P(arg); if (separate - && Z_OBJ_P(arg)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(arg)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(arg)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(arg)->properties); + && zobj->properties + && UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); } - Z_OBJ_P(arg)->properties = zend_array_dup(Z_OBJ_P(arg)->properties); + zobj->properties = zend_array_dup(zobj->properties); } - *dest = Z_OBJ_HT_P(arg)->get_properties(arg); + *dest = zobj->handlers->get_properties(zobj); } else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) { *dest = NULL; } else { diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index cfc78db4ea..b00b35ccb4 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -37,7 +37,6 @@ static ZEND_FUNCTION(strcmp); static ZEND_FUNCTION(strncmp); static ZEND_FUNCTION(strcasecmp); static ZEND_FUNCTION(strncasecmp); -static ZEND_FUNCTION(each); static ZEND_FUNCTION(error_reporting); static ZEND_FUNCTION(define); static ZEND_FUNCTION(defined); @@ -67,7 +66,6 @@ static ZEND_FUNCTION(get_declared_traits); static ZEND_FUNCTION(get_declared_interfaces); static ZEND_FUNCTION(get_defined_functions); static ZEND_FUNCTION(get_defined_vars); -static ZEND_FUNCTION(create_function); static ZEND_FUNCTION(get_resource_type); static ZEND_FUNCTION(get_resources); static ZEND_FUNCTION(get_loaded_extensions); @@ -109,10 +107,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_strncmp, 0, 0, 3) ZEND_ARG_INFO(0, len) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_each, 0, 0, 1) - ZEND_ARG_INFO(1, arr) -ZEND_END_ARG_INFO() - ZEND_BEGIN_ARG_INFO_EX(arginfo_error_reporting, 0, 0, 0) ZEND_ARG_INFO(0, new_error_level) ZEND_END_ARG_INFO() @@ -197,11 +191,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_get_defined_functions, 0, 0, 0) ZEND_ARG_INFO(0, exclude_disabled) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_create_function, 0, 0, 2) - ZEND_ARG_INFO(0, args) - ZEND_ARG_INFO(0, code) -ZEND_END_ARG_INFO() - ZEND_BEGIN_ARG_INFO_EX(arginfo_get_resource_type, 0, 0, 1) ZEND_ARG_INFO(0, res) ZEND_END_ARG_INFO() @@ -244,7 +233,6 @@ static const zend_function_entry builtin_functions[] = { /* {{{ */ ZEND_FE(strncmp, arginfo_strncmp) ZEND_FE(strcasecmp, arginfo_strcmp) ZEND_FE(strncasecmp, arginfo_strncmp) - ZEND_FE(each, arginfo_each) ZEND_FE(error_reporting, arginfo_error_reporting) ZEND_FE(define, arginfo_define) ZEND_FE(defined, arginfo_defined) @@ -276,7 +264,6 @@ static const zend_function_entry builtin_functions[] = { /* {{{ */ ZEND_FE(get_declared_interfaces, arginfo_zend__void) ZEND_FE(get_defined_functions, arginfo_get_defined_functions) ZEND_FE(get_defined_vars, arginfo_zend__void) - ZEND_DEP_FE(create_function, arginfo_create_function) ZEND_FE(get_resource_type, arginfo_get_resource_type) ZEND_FE(get_resources, arginfo_get_resources) ZEND_FE(get_loaded_extensions, arginfo_get_loaded_extensions) @@ -660,66 +647,6 @@ ZEND_FUNCTION(strncasecmp) } /* }}} */ -/* {{{ proto mixed each(array &arr) - Return the currently pointed key..value pair in the passed array, and advance the pointer to the next element, or false if there is no element at this place */ -ZEND_FUNCTION(each) -{ - zval *array, *entry, tmp; - zend_ulong num_key; - HashTable *target_hash; - zend_string *key; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "z/", &array) == FAILURE) { - return; - } - - if (!EG(each_deprecation_thrown)) { - zend_error(E_DEPRECATED, "The each() function is deprecated. This message will be suppressed on further calls"); - EG(each_deprecation_thrown) = 1; - } - - target_hash = HASH_OF(array); - if (!target_hash) { - zend_error(E_WARNING,"Variable passed to each() is not an array or object"); - return; - } - while (1) { - entry = zend_hash_get_current_data(target_hash); - if (!entry) { - RETURN_FALSE; - } else if (Z_TYPE_P(entry) == IS_INDIRECT) { - entry = Z_INDIRECT_P(entry); - if (Z_TYPE_P(entry) == IS_UNDEF) { - zend_hash_move_forward(target_hash); - continue; - } - } - break; - } - array_init_size(return_value, 4); - zend_hash_real_init_mixed(Z_ARRVAL_P(return_value)); - - /* add value elements */ - ZVAL_DEREF(entry); - if (Z_REFCOUNTED_P(entry)) { - GC_ADDREF_EX(Z_COUNTED_P(entry), 2); - } - zend_hash_index_add_new(Z_ARRVAL_P(return_value), 1, entry); - zend_hash_add_new(Z_ARRVAL_P(return_value), ZSTR_KNOWN(ZEND_STR_VALUE), entry); - - /* add the key elements */ - if (zend_hash_get_current_key(target_hash, &key, &num_key) == HASH_KEY_IS_STRING) { - ZVAL_STR_COPY(&tmp, key); - Z_TRY_ADDREF(tmp); - } else { - ZVAL_LONG(&tmp, num_key); - } - zend_hash_index_add_new(Z_ARRVAL_P(return_value), 0, &tmp); - zend_hash_add_new(Z_ARRVAL_P(return_value), ZSTR_KNOWN(ZEND_STR_KEY), &tmp); - zend_hash_move_forward(target_hash); -} -/* }}} */ - /* {{{ proto int error_reporting([int new_error_level]) Return the current error_reporting level, and if an argument was passed - change to the new level */ ZEND_FUNCTION(error_reporting) @@ -838,7 +765,6 @@ ZEND_FUNCTION(define) zend_string *name; zval *val, val_free; zend_bool non_cs = 0; - int case_sensitive = CONST_CS; zend_constant c; ZEND_PARSE_PARAMETERS_START(2, 3) @@ -848,15 +774,17 @@ ZEND_FUNCTION(define) Z_PARAM_BOOL(non_cs) ZEND_PARSE_PARAMETERS_END(); - if (non_cs) { - case_sensitive = 0; - } - if (zend_memnstr(ZSTR_VAL(name), "::", sizeof("::") - 1, ZSTR_VAL(name) + ZSTR_LEN(name))) { zend_error(E_WARNING, "Class constants cannot be defined or redefined"); RETURN_FALSE; } + if (non_cs) { + zend_error(E_WARNING, + "define(): Declaration of case-insensitive constants is no longer supported"); + RETURN_FALSE; + } + ZVAL_UNDEF(&val_free); repeat: @@ -883,11 +811,11 @@ repeat: if (Z_TYPE(val_free) == IS_UNDEF) { if (Z_OBJ_HT_P(val)->get) { zval rv; - val = Z_OBJ_HT_P(val)->get(val, &rv); + val = Z_OBJ_HT_P(val)->get(Z_OBJ_P(val), &rv); ZVAL_COPY_VALUE(&val_free, val); goto repeat; } else if (Z_OBJ_HT_P(val)->cast_object) { - if (Z_OBJ_HT_P(val)->cast_object(val, &val_free, IS_STRING) == SUCCESS) { + if (Z_OBJ_HT_P(val)->cast_object(Z_OBJ_P(val), &val_free, IS_STRING) == SUCCESS) { val = &val_free; break; } @@ -904,13 +832,8 @@ repeat: zval_ptr_dtor(&val_free); register_constant: - if (non_cs) { - zend_error(E_DEPRECATED, - "define(): Declaration of case-insensitive constants is deprecated"); - } - /* non persistent */ - ZEND_CONSTANT_SET_FLAGS(&c, case_sensitive, PHP_USER_CONSTANT); + ZEND_CONSTANT_SET_FLAGS(&c, CONST_CS, PHP_USER_CONSTANT); c.name = zend_string_copy(name); if (zend_register_constant(&c) == SUCCESS) { RETURN_TRUE; @@ -931,7 +854,7 @@ ZEND_FUNCTION(defined) Z_PARAM_STR(name) ZEND_PARSE_PARAMETERS_END(); - if (zend_get_constant_ex(name, zend_get_executed_scope(), ZEND_FETCH_CLASS_SILENT | ZEND_GET_CONSTANT_NO_DEPRECATION_CHECK)) { + if (zend_get_constant_ex(name, zend_get_executed_scope(), ZEND_FETCH_CLASS_SILENT)) { RETURN_TRUE; } else { RETURN_FALSE; @@ -1174,13 +1097,12 @@ ZEND_FUNCTION(get_object_vars) Z_PARAM_OBJECT(obj) ZEND_PARSE_PARAMETERS_END(); - properties = Z_OBJ_HT_P(obj)->get_properties(obj); + zobj = Z_OBJ_P(obj); + properties = zobj->handlers->get_properties(zobj); if (properties == NULL) { RETURN_FALSE; } - zobj = Z_OBJ_P(obj); - if (!zobj->ce->default_properties_count && properties == zobj->properties && !GC_IS_RECURSIVE(properties)) { /* fast copy */ if (EXPECTED(zobj->handlers == &std_object_handlers)) { @@ -1359,7 +1281,6 @@ ZEND_FUNCTION(property_exists) zend_string *property; zend_class_entry *ce; zend_property_info *property_info; - zval property_z; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zS", &object, &property) == FAILURE) { return; @@ -1388,10 +1309,8 @@ ZEND_FUNCTION(property_exists) RETURN_TRUE; } - ZVAL_STR(&property_z, property); - if (Z_TYPE_P(object) == IS_OBJECT && - Z_OBJ_HANDLER_P(object, has_property)(object, &property_z, 2, NULL)) { + Z_OBJ_HANDLER_P(object, has_property)(Z_OBJ_P(object), property, 2, NULL)) { RETURN_TRUE; } RETURN_FALSE; @@ -1813,78 +1732,6 @@ ZEND_FUNCTION(get_defined_vars) } /* }}} */ -#define LAMBDA_TEMP_FUNCNAME "__lambda_func" -/* {{{ proto string create_function(string args, string code) - Creates an anonymous function, and returns its name (funny, eh?) */ -ZEND_FUNCTION(create_function) -{ - zend_string *function_name; - char *eval_code, *function_args, *function_code; - size_t eval_code_length, function_args_len, function_code_len; - int retval; - char *eval_name; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &function_args, &function_args_len, &function_code, &function_code_len) == FAILURE) { - return; - } - - eval_code = (char *) emalloc(sizeof("function " LAMBDA_TEMP_FUNCNAME) - +function_args_len - +2 /* for the args parentheses */ - +2 /* for the curly braces */ - +function_code_len); - - eval_code_length = sizeof("function " LAMBDA_TEMP_FUNCNAME "(") - 1; - memcpy(eval_code, "function " LAMBDA_TEMP_FUNCNAME "(", eval_code_length); - - memcpy(eval_code + eval_code_length, function_args, function_args_len); - eval_code_length += function_args_len; - - eval_code[eval_code_length++] = ')'; - eval_code[eval_code_length++] = '{'; - - memcpy(eval_code + eval_code_length, function_code, function_code_len); - eval_code_length += function_code_len; - - eval_code[eval_code_length++] = '}'; - eval_code[eval_code_length] = '\0'; - - eval_name = zend_make_compiled_string_description("runtime-created function"); - retval = zend_eval_stringl(eval_code, eval_code_length, NULL, eval_name); - efree(eval_code); - efree(eval_name); - - if (retval==SUCCESS) { - zend_op_array *func; - HashTable *static_variables; - - func = zend_hash_str_find_ptr(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1); - if (!func) { - zend_error_noreturn(E_CORE_ERROR, "Unexpected inconsistency in create_function()"); - RETURN_FALSE; - } - if (func->refcount) { - (*func->refcount)++; - } - static_variables = func->static_variables; - func->static_variables = NULL; - zend_hash_str_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1); - func->static_variables = static_variables; - - function_name = zend_string_alloc(sizeof("0lambda_")+MAX_LENGTH_OF_LONG, 0); - ZSTR_VAL(function_name)[0] = '\0'; - - do { - ZSTR_LEN(function_name) = snprintf(ZSTR_VAL(function_name) + 1, sizeof("lambda_")+MAX_LENGTH_OF_LONG, "lambda_%d", ++EG(lambda_count)) + 1; - } while (zend_hash_add_ptr(EG(function_table), function_name, func) == NULL); - RETURN_NEW_STR(function_name); - } else { - zend_hash_str_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1); - RETURN_FALSE; - } -} -/* }}} */ - #if ZEND_DEBUG && defined(ZTS) ZEND_FUNCTION(zend_thread_id) { diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 70b70d9723..98a78904fc 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -84,12 +84,8 @@ static zend_bool zend_valid_closure_binding( } } else if (is_fake_closure && func->common.scope && !(func->common.fn_flags & ZEND_ACC_STATIC)) { - if (func->type == ZEND_INTERNAL_FUNCTION) { - zend_error(E_WARNING, "Cannot unbind $this of internal method"); - return 0; - } else { - zend_error(E_DEPRECATED, "Unbinding $this of a method is deprecated"); - } + zend_error(E_WARNING, "Cannot unbind $this of method"); + return 0; } if (scope && scope != func->common.scope && scope->type == ZEND_INTERNAL_CLASS) { @@ -336,7 +332,7 @@ ZEND_METHOD(Closure, fromCallable) success = zend_create_closure_from_callable(return_value, callable, &error); EG(current_execute_data) = execute_data; - if (success == FAILURE || error) { + if (success == FAILURE) { if (error) { zend_type_error("Failed to create closure from callable: %s", error); efree(error); @@ -412,28 +408,28 @@ static zend_function *zend_closure_get_method(zend_object **object, zend_string } /* }}} */ -static zval *zend_closure_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv) /* {{{ */ +static zval *zend_closure_read_property(zend_object *object, zend_string *member, int type, void **cache_slot, zval *rv) /* {{{ */ { ZEND_CLOSURE_PROPERTY_ERROR(); return &EG(uninitialized_zval); } /* }}} */ -static zval *zend_closure_write_property(zval *object, zval *member, zval *value, void **cache_slot) /* {{{ */ +static zval *zend_closure_write_property(zend_object *object, zend_string *member, zval *value, void **cache_slot) /* {{{ */ { ZEND_CLOSURE_PROPERTY_ERROR(); return value; } /* }}} */ -static zval *zend_closure_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot) /* {{{ */ +static zval *zend_closure_get_property_ptr_ptr(zend_object *object, zend_string *member, int type, void **cache_slot) /* {{{ */ { ZEND_CLOSURE_PROPERTY_ERROR(); return NULL; } /* }}} */ -static int zend_closure_has_property(zval *object, zval *member, int has_set_exists, void **cache_slot) /* {{{ */ +static int zend_closure_has_property(zend_object *object, zend_string *member, int has_set_exists, void **cache_slot) /* {{{ */ { if (has_set_exists != ZEND_PROPERTY_EXISTS) { ZEND_CLOSURE_PROPERTY_ERROR(); @@ -442,7 +438,7 @@ static int zend_closure_has_property(zval *object, zval *member, int has_set_exi } /* }}} */ -static void zend_closure_unset_property(zval *object, zval *member, void **cache_slot) /* {{{ */ +static void zend_closure_unset_property(zend_object *object, zend_string *member, void **cache_slot) /* {{{ */ { ZEND_CLOSURE_PROPERTY_ERROR(); } @@ -478,9 +474,9 @@ static zend_object *zend_closure_new(zend_class_entry *class_type) /* {{{ */ } /* }}} */ -static zend_object *zend_closure_clone(zval *zobject) /* {{{ */ +static zend_object *zend_closure_clone(zend_object *zobject) /* {{{ */ { - zend_closure *closure = (zend_closure *)Z_OBJ_P(zobject); + zend_closure *closure = (zend_closure *)zobject; zval result; zend_create_closure(&result, &closure->func, @@ -489,9 +485,9 @@ static zend_object *zend_closure_clone(zval *zobject) /* {{{ */ } /* }}} */ -int zend_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr) /* {{{ */ +int zend_closure_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr) /* {{{ */ { - zend_closure *closure = (zend_closure *)Z_OBJ_P(obj); + zend_closure *closure = (zend_closure *)obj; *fptr_ptr = &closure->func; *ce_ptr = closure->called_scope; @@ -505,9 +501,9 @@ int zend_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function } /* }}} */ -static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp) /* {{{ */ +static HashTable *zend_closure_get_debug_info(zend_object *object, int *is_temp) /* {{{ */ { - zend_closure *closure = (zend_closure *)Z_OBJ_P(object); + zend_closure *closure = (zend_closure *)object; zval val; struct _zend_arg_info *arg_info = closure->func.common.arg_info; HashTable *debug_info; @@ -570,9 +566,9 @@ static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp) /* {{{ } /* }}} */ -static HashTable *zend_closure_get_gc(zval *obj, zval **table, int *n) /* {{{ */ +static HashTable *zend_closure_get_gc(zend_object *obj, zval **table, int *n) /* {{{ */ { - zend_closure *closure = (zend_closure *)Z_OBJ_P(obj); + zend_closure *closure = (zend_closure *)obj; *table = Z_TYPE(closure->this_ptr) != IS_NULL ? &closure->this_ptr : NULL; *n = Z_TYPE(closure->this_ptr) != IS_NULL ? 1 : 0; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index ccdbd8a1b7..0b9a50cdb1 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -585,10 +585,6 @@ static int zend_add_const_name_literal(zend_string *name, zend_bool unqualified) zend_str_tolower(ZSTR_VAL(tmp_name), ns_len); zend_add_literal_string(&tmp_name); - /* lowercased namespace name & lowercased constant name */ - tmp_name = zend_string_tolower(name); - zend_add_literal_string(&tmp_name); - if (!unqualified) { return ret; } @@ -600,11 +596,6 @@ static int zend_add_const_name_literal(zend_string *name, zend_bool unqualified) tmp_name = zend_string_init(after_ns, after_ns_len, 0); zend_add_literal_string(&tmp_name); - /* lowercased unqualified constant name */ - tmp_name = zend_string_alloc(after_ns_len, 0); - zend_str_tolower_copy(ZSTR_VAL(tmp_name), after_ns, after_ns_len); - zend_add_literal_string(&tmp_name); - return ret; } /* }}} */ @@ -986,10 +977,9 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */ if (op_array->refcount) { (*op_array->refcount)++; } - if (op_array->static_variables) { - if (!(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) { - GC_ADDREF(op_array->static_variables); - } + if (op_array->static_variables + && !(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(op_array->static_variables); } ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables); ZEND_MAP_PTR_INIT(op_array->run_time_cache, zend_arena_alloc(&CG(arena), sizeof(void*))); @@ -1213,26 +1203,13 @@ ZEND_API int zend_unmangle_property_name_ex(const zend_string *name, const char } /* }}} */ -static zend_constant *zend_lookup_reserved_const(const char *name, size_t len) /* {{{ */ -{ - zend_constant *c = zend_hash_find_ptr_lc(EG(zend_constants), name, len); - if (c && !(ZEND_CONSTANT_FLAGS(c) & CONST_CS) && (ZEND_CONSTANT_FLAGS(c) & CONST_CT_SUBST)) { - return c; - } - return NULL; -} -/* }}} */ - static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool is_fully_qualified) /* {{{ */ { - zend_constant *c; - - /* Substitute case-sensitive (or lowercase) constants */ - c = zend_hash_find_ptr(EG(zend_constants), name); + zend_constant *c = zend_hash_find_ptr(EG(zend_constants), name); if (c && ( ((ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) && !(CG(compiler_options) & ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION) - && (!(ZEND_CONSTANT_FLAGS(c) & CONST_NO_FILE_CACHE) || !(CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE))) + && !((ZEND_CONSTANT_FLAGS(c) & CONST_NO_FILE_CACHE) && (CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE))) || (Z_TYPE(c->value) < IS_OBJECT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) )) { ZVAL_COPY_OR_DUP(zv, &c->value); @@ -1243,19 +1220,19 @@ static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool i /* Substitute true, false and null (including unqualified usage in namespaces) */ const char *lookup_name = ZSTR_VAL(name); size_t lookup_len = ZSTR_LEN(name); + zval *val; if (!is_fully_qualified) { zend_get_unqualified_name(name, &lookup_name, &lookup_len); } - c = zend_lookup_reserved_const(lookup_name, lookup_len); - if (c) { - ZVAL_COPY_OR_DUP(zv, &c->value); + if ((val = zend_get_special_const(lookup_name, lookup_len))) { + ZVAL_COPY_VALUE(zv, val); return 1; } - } - return 0; + return 0; + } } /* }}} */ @@ -2943,26 +2920,26 @@ uint32_t zend_compile_args(zend_ast *ast, zend_function *fbc) /* {{{ */ } arg_count++; - if (zend_is_variable_or_call(arg)) { - if (zend_is_call(arg)) { - zend_compile_var(&arg_node, arg, BP_VAR_R, 0); - if (arg_node.op_type & (IS_CONST|IS_TMP_VAR)) { - /* Function call was converted into builtin instruction */ - opcode = ZEND_SEND_VAL; - } else { - if (fbc) { - if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) { - opcode = ZEND_SEND_VAR_NO_REF; - } else if (ARG_MAY_BE_SENT_BY_REF(fbc, arg_num)) { - opcode = ZEND_SEND_VAL; - } else { - opcode = ZEND_SEND_VAR; - } + if (zend_is_call(arg)) { + zend_compile_var(&arg_node, arg, BP_VAR_R, 0); + if (arg_node.op_type & (IS_CONST|IS_TMP_VAR)) { + /* Function call was converted into builtin instruction */ + opcode = ZEND_SEND_VAL; + } else { + if (fbc) { + if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) { + opcode = ZEND_SEND_VAR_NO_REF; + } else if (ARG_MAY_BE_SENT_BY_REF(fbc, arg_num)) { + opcode = ZEND_SEND_VAL; } else { - opcode = ZEND_SEND_VAR_NO_REF_EX; + opcode = ZEND_SEND_VAR; } + } else { + opcode = ZEND_SEND_VAR_NO_REF_EX; } - } else if (fbc) { + } + } else if (zend_is_variable(arg)) { + if (fbc) { if (ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) { zend_compile_var(&arg_node, arg, BP_VAR_W, 1); opcode = ZEND_SEND_REF; @@ -3163,9 +3140,7 @@ int zend_compile_func_strlen(znode *result, zend_ast_list *args) /* {{{ */ { znode arg_node; - if ((CG(compiler_options) & ZEND_COMPILE_NO_BUILTIN_STRLEN) - || args->children != 1 - ) { + if (args->children != 1) { return FAILURE; } @@ -3245,13 +3220,6 @@ int zend_compile_func_defined(znode *result, zend_ast_list *args) /* {{{ */ LITERAL_STR(opline->op1, name); opline->extended_value = zend_alloc_cache_slot(); - /* Lowercase constant name in a separate literal */ - { - zval c; - zend_string *lcname = zend_string_tolower(name); - ZVAL_NEW_STR(&c, lcname); - zend_add_literal(&c); - } return SUCCESS; } /* }}} */ @@ -3893,6 +3861,24 @@ static zend_bool zend_is_constructor(zend_string *name) /* {{{ */ } /* }}} */ +static zend_function *zend_get_compatible_func_or_null(zend_class_entry *ce, zend_string *lcname) /* {{{ */ +{ + zend_function *fbc = zend_hash_find_ptr(&ce->function_table, lcname); + if (!fbc || (fbc->common.fn_flags & ZEND_ACC_PUBLIC) || ce == CG(active_class_entry)) { + return fbc; + } + + if (!(fbc->common.fn_flags & ZEND_ACC_PRIVATE) + && (fbc->common.scope->ce_flags & ZEND_ACC_LINKED) + && (!CG(active_class_entry) || (CG(active_class_entry)->ce_flags & ZEND_ACC_LINKED)) + && zend_check_protected(zend_get_function_root_class(fbc), CG(active_class_entry))) { + return fbc; + } + + return NULL; +} +/* }}} */ + void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ { zend_ast *class_ast = ast->child[0]; @@ -3951,18 +3937,7 @@ void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{ } if (ce) { zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op2) + 1); - fbc = zend_hash_find_ptr(&ce->function_table, lcname); - if (fbc && !(fbc->common.fn_flags & ZEND_ACC_PUBLIC)) { - if (ce != CG(active_class_entry) - && ((fbc->common.fn_flags & ZEND_ACC_PRIVATE) - || !(fbc->common.scope->ce_flags & ZEND_ACC_LINKED) - || (CG(active_class_entry) - && !(CG(active_class_entry)->ce_flags & ZEND_ACC_LINKED)) - || !zend_check_protected(zend_get_function_root_class(fbc), CG(active_class_entry)))) { - /* incompatibe function */ - fbc = NULL; - } - } + fbc = zend_get_compatible_func_or_null(ce, lcname); } } @@ -5364,82 +5339,77 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ arg_info->type = ZEND_TYPE_ENCODE(0, 1); if (type_ast) { - zend_bool has_null_default = default_ast - && (Z_TYPE(default_node.u.constant) == IS_NULL - || (Z_TYPE(default_node.u.constant) == IS_CONSTANT_AST - && Z_ASTVAL(default_node.u.constant)->kind == ZEND_AST_CONSTANT - && strcasecmp(ZSTR_VAL(zend_ast_get_constant_name(Z_ASTVAL(default_node.u.constant))), "NULL") == 0)); + uint32_t default_type = Z_TYPE(default_node.u.constant); + + uint32_t arg_type; + zend_bool is_class; op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS; - arg_info->type = zend_compile_typename(type_ast, has_null_default); + arg_info->type = zend_compile_typename(type_ast, default_ast && default_type == IS_NULL); - if (ZEND_TYPE_CODE(arg_info->type) == IS_VOID) { + is_class = ZEND_TYPE_IS_CLASS(arg_info->type); + arg_type = ZEND_TYPE_CODE(arg_info->type); + + if (arg_type == IS_VOID) { zend_error_noreturn(E_COMPILE_ERROR, "void cannot be used as a parameter type"); } - if (type_ast->kind == ZEND_AST_TYPE) { - if (ZEND_TYPE_CODE(arg_info->type) == IS_ARRAY) { - if (default_ast && !has_null_default - && Z_TYPE(default_node.u.constant) != IS_ARRAY - && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST - ) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with array type can only be an array or NULL"); - } - } else if (ZEND_TYPE_CODE(arg_info->type) == IS_CALLABLE && default_ast) { - if (!has_null_default && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST) { + if (default_ast && default_type != IS_NULL && default_type != IS_CONSTANT_AST) { + if (is_class) { + zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " + "with a class type can only be NULL"); + } else switch (arg_type) { + case IS_CALLABLE: zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with callable type can only be NULL"); - } - } - } else { - if (default_ast && !has_null_default && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST) { - if (ZEND_TYPE_IS_CLASS(arg_info->type)) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with a class type can only be NULL"); - } else switch (ZEND_TYPE_CODE(arg_info->type)) { - case IS_DOUBLE: - if (Z_TYPE(default_node.u.constant) != IS_DOUBLE && Z_TYPE(default_node.u.constant) != IS_LONG) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with a float type can only be float, integer, or NULL"); - } - break; + break; - case IS_ITERABLE: - if (Z_TYPE(default_node.u.constant) != IS_ARRAY) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with iterable type can only be an array or NULL"); - } - break; + case IS_ARRAY: + if (default_type != IS_ARRAY) { + zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " + "with array type can only be an array or NULL"); + } + break; - case IS_OBJECT: + case IS_DOUBLE: + if (default_type != IS_DOUBLE && default_type != IS_LONG) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with an object type can only be NULL"); - break; + "with a float type can only be float, integer, or NULL"); + } + break; - default: - if (!ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(arg_info->type), Z_TYPE(default_node.u.constant))) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with a %s type can only be %s or NULL", - zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type)), zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type))); - } - break; - } + case IS_ITERABLE: + if (default_type != IS_ARRAY) { + zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " + "with iterable type can only be an array or NULL"); + } + break; + + case IS_OBJECT: + zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " + "with an object type can only be NULL"); + break; + + default: + if (!ZEND_SAME_FAKE_TYPE(arg_type, default_type)) { + zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " + "with a %s type can only be %s or NULL", + zend_get_type_by_const(arg_type), zend_get_type_by_const(arg_type)); + } + break; } } /* Allocate cache slot to speed-up run-time class resolution */ if (opline->opcode == ZEND_RECV_INIT) { - if (ZEND_TYPE_IS_CLASS(arg_info->type)) { + if (is_class) { opline->extended_value = zend_alloc_cache_slot(); } + } else if (is_class) { + opline->op2.num = op_array->cache_size; + op_array->cache_size += sizeof(void*); } else { - if (ZEND_TYPE_IS_CLASS(arg_info->type)) { - opline->op2.num = op_array->cache_size; - op_array->cache_size += sizeof(void*); - } else { - opline->op2.num = -1; - } + opline->op2.num = -1; } } else { if (opline->opcode != ZEND_RECV_INIT) { @@ -5530,18 +5500,30 @@ void zend_compile_closure_uses(zend_ast *ast) /* {{{ */ } /* }}} */ +static void zend_check_magic_method_attr(uint32_t attr, const char* method, zend_bool is_static) /* {{{ */ +{ + if (is_static) { + if (!(attr & ZEND_ACC_PUBLIC) || !(attr & ZEND_ACC_STATIC)) { + zend_error(E_WARNING, "The magic method %s() must have public visibility and be static", method); + } + } else if (!(attr & ZEND_ACC_PUBLIC) || (attr & ZEND_ACC_STATIC)) { + zend_error(E_WARNING, + "The magic method %s() must have public visibility and cannot be static", + method); + } +} +/* }}} */ + void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_bool has_body) /* {{{ */ { zend_class_entry *ce = CG(active_class_entry); zend_bool in_interface = (ce->ce_flags & ZEND_ACC_INTERFACE) != 0; - zend_bool in_trait = (ce->ce_flags & ZEND_ACC_TRAIT) != 0; - zend_bool is_public = (op_array->fn_flags & ZEND_ACC_PUBLIC) != 0; - zend_bool is_static = (op_array->fn_flags & ZEND_ACC_STATIC) != 0; + uint32_t fn_flags = op_array->fn_flags; zend_string *lcname; if (in_interface) { - if (!is_public || (op_array->fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_ABSTRACT))) { + if (!(fn_flags & ZEND_ACC_PUBLIC) || (fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_ABSTRACT))) { zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method " "%s::%s() must be omitted", ZSTR_VAL(ce->name), ZSTR_VAL(name)); } @@ -5576,134 +5558,48 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo ZSTR_VAL(ce->name), ZSTR_VAL(name)); } - if (in_interface) { - if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') { - /* pass */ - } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __call() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) { - if (!is_public || !is_static) { - zend_error(E_WARNING, "The magic method __callStatic() must have " - "public visibility and be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __get() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __set() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __unset() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __isset() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __toString() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __invoke() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __debugInfo() must have " - "public visibility and cannot be static"); - } - } - } else { - if (!in_trait && zend_string_equals_ci(lcname, ce->name)) { - if (!ce->constructor) { - ce->constructor = (zend_function *) op_array; - } - } else if (zend_string_equals_literal(lcname, "serialize")) { - ce->serialize_func = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, "unserialize")) { - ce->unserialize_func = (zend_function *) op_array; - } else if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') { - if (!is_static) { - op_array->fn_flags |= ZEND_ACC_ALLOW_STATIC; - } - } else if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) { - ce->constructor = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) { - ce->destructor = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) { - ce->clone = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __call() must have " - "public visibility and cannot be static"); - } - ce->__call = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) { - if (!is_public || !is_static) { - zend_error(E_WARNING, "The magic method __callStatic() must have " - "public visibility and be static"); - } - ce->__callstatic = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __get() must have " - "public visibility and cannot be static"); - } - ce->__get = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; - } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __set() must have " - "public visibility and cannot be static"); - } - ce->__set = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; - } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __unset() must have " - "public visibility and cannot be static"); - } - ce->__unset = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; - } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __isset() must have " - "public visibility and cannot be static"); - } - ce->__isset = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; - } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __toString() must have " - "public visibility and cannot be static"); - } - ce->__tostring = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __invoke() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __debugInfo() must have " - "public visibility and cannot be static"); - } - ce->__debugInfo = (zend_function *) op_array; - } else if (!is_static) { - op_array->fn_flags |= ZEND_ACC_ALLOW_STATIC; - } + if (zend_string_equals_literal(lcname, "serialize")) { + ce->serialize_func = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, "unserialize")) { + ce->unserialize_func = (zend_function *) op_array; + } else if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') { + /* pass */ + } else if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) { + ce->constructor = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) { + ce->destructor = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) { + ce->clone = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__call", 0); + ce->__call = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__callStatic", 1); + ce->__callstatic = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__get", 0); + ce->__get = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; + } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__set", 0); + ce->__set = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; + } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__unset", 0); + ce->__unset = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; + } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__isset", 0); + ce->__isset = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; + } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__toString", 0); + ce->__tostring = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__invoke", 0); + } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__debugInfo", 0); + ce->__debugInfo = (zend_function *) op_array; } zend_string_release_ex(lcname, 0); @@ -5712,7 +5608,6 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo static void zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_ast_decl *decl, zend_bool toplevel) /* {{{ */ { - zend_ast *params_ast = decl->child[0]; zend_string *unqualified_name, *name, *lcname, *key; zend_op *opline; @@ -5729,18 +5624,14 @@ static void zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_as } } - if (zend_string_equals_literal(lcname, ZEND_AUTOLOAD_FUNC_NAME)) { - if (zend_ast_get_list(params_ast)->children != 1) { - zend_error_noreturn(E_COMPILE_ERROR, "%s() must take exactly 1 argument", - ZEND_AUTOLOAD_FUNC_NAME); - } - - zend_error(E_DEPRECATED, "__autoload() is deprecated, use spl_autoload_register() instead"); + if (zend_string_equals_literal(lcname, "__autoload")) { + zend_error_noreturn(E_COMPILE_ERROR, + "__autoload() is no longer supported, use spl_autoload_register() instead"); } if (zend_string_equals_literal_ci(unqualified_name, "assert")) { - zend_error(E_DEPRECATED, - "Defining a custom assert() function is deprecated, " + zend_error(E_COMPILE_ERROR, + "Defining a custom assert() function is not allowed, " "as the function has special semantics"); } @@ -5978,6 +5869,18 @@ void zend_compile_prop_group(zend_ast *list) /* {{{ */ } /* }}} */ +static void zend_check_const_and_trait_alias_attr(uint32_t attr, const char* entity) /* {{{ */ +{ + if (attr & ZEND_ACC_STATIC) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as %s modifier", entity); + } else if (attr & ZEND_ACC_ABSTRACT) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as %s modifier", entity); + } else if (attr & ZEND_ACC_FINAL) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as %s modifier", entity); + } +} +/* }}} */ + void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */ { zend_ast_list *list = zend_ast_get_list(ast); @@ -5999,13 +5902,7 @@ void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */ zval value_zv; if (UNEXPECTED(ast->attr & (ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_FINAL))) { - if (ast->attr & ZEND_ACC_STATIC) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as constant modifier"); - } else if (ast->attr & ZEND_ACC_ABSTRACT) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as constant modifier"); - } else if (ast->attr & ZEND_ACC_FINAL) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as constant modifier"); - } + zend_check_const_and_trait_alias_attr(ast->attr, "constant"); } zend_const_expr_to_zval(&value_zv, value_ast); @@ -6057,13 +5954,7 @@ static void zend_compile_trait_alias(zend_ast *ast) /* {{{ */ zend_trait_alias *alias; - if (modifiers == ZEND_ACC_STATIC) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as method modifier"); - } else if (modifiers == ZEND_ACC_ABSTRACT) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as method modifier"); - } else if (modifiers == ZEND_ACC_FINAL) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as method modifier"); - } + zend_check_const_and_trait_alias_attr(modifiers, "method"); alias = emalloc(sizeof(zend_trait_alias)); zend_compile_method_ref(method_ref_ast, &alias->trait_method); @@ -6261,11 +6152,6 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ /* Reset lineno for final opcodes and errors */ CG(zend_lineno) = ast->lineno; - if (!(ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS)) { - /* For traits this check is delayed until after trait binding */ - zend_check_deprecated_constructor(ce); - } - if (ce->constructor) { ce->constructor->common.fn_flags |= ZEND_ACC_CTOR; if (ce->constructor->common.fn_flags & ZEND_ACC_STATIC) { @@ -6337,13 +6223,11 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ return NULL; } } - } else { - if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) { - zend_string_release(lcname); - zend_build_properties_info_table(ce); - ce->ce_flags |= ZEND_ACC_LINKED; - return NULL; - } + } else if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) { + zend_string_release(lcname); + zend_build_properties_info_table(ce); + ce->ce_flags |= ZEND_ACC_LINKED; + return NULL; } } @@ -6515,10 +6399,8 @@ void zend_compile_use(zend_ast *ast) /* {{{ */ } zend_string_efree(ns_name); - } else { - if (zend_have_seen_symbol(lookup_name, type)) { - zend_check_already_in_use(type, old_name, new_name, lookup_name); - } + } else if (zend_have_seen_symbol(lookup_name, type)) { + zend_check_already_in_use(type, old_name, new_name, lookup_name); } zend_string_addref(old_name); @@ -6570,7 +6452,7 @@ void zend_compile_const_decl(zend_ast *ast) /* {{{ */ value_node.op_type = IS_CONST; zend_const_expr_to_zval(value_zv, value_ast); - if (zend_lookup_reserved_const(ZSTR_VAL(unqualified_name), ZSTR_LEN(unqualified_name))) { + if (zend_get_special_const(ZSTR_VAL(unqualified_name), ZSTR_LEN(unqualified_name))) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare constant '%s'", ZSTR_VAL(unqualified_name)); } @@ -6951,12 +6833,10 @@ static zend_bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */ zend_error_noreturn(E_COMPILE_ERROR, "Illegal offset type"); break; } - } else { - if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), value)) { - zval_ptr_dtor_nogc(value); - zval_ptr_dtor(result); - return 0; - } + } else if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), value)) { + zval_ptr_dtor_nogc(value); + zval_ptr_dtor(result); + return 0; } } @@ -7092,12 +6972,11 @@ void zend_compile_unary_pm(znode *result, zend_ast *ast) /* {{{ */ zend_compile_expr(&expr_node, expr_ast); - if (expr_node.op_type == IS_CONST) { - if (zend_try_ct_eval_unary_pm(&result->u.constant, ast->kind, &expr_node.u.constant)) { - result->op_type = IS_CONST; - zval_ptr_dtor(&expr_node.u.constant); - return; - } + if (expr_node.op_type == IS_CONST + && zend_try_ct_eval_unary_pm(&result->u.constant, ast->kind, &expr_node.u.constant)) { + result->op_type = IS_CONST; + zval_ptr_dtor(&expr_node.u.constant); + return; } lefthand_node.op_type = IS_CONST; @@ -7220,7 +7099,7 @@ void zend_compile_cast(znode *result, zend_ast *ast) /* {{{ */ opline->extended_value = ast->attr; if (ast->attr == IS_NULL) { - zend_error(E_DEPRECATED, "The (unset) cast is deprecated"); + zend_error(E_COMPILE_ERROR, "The (unset) cast is no longer supported"); } } /* }}} */ @@ -7729,19 +7608,13 @@ void zend_compile_const(znode *result, zend_ast *ast) /* {{{ */ opline = zend_emit_op_tmp(result, ZEND_FETCH_CONSTANT, NULL, NULL); opline->op2_type = IS_CONST; - if (is_fully_qualified) { + if (is_fully_qualified || !FC(current_namespace)) { opline->op2.constant = zend_add_const_name_literal( resolved_name, 0); } else { - opline->op1.num = IS_CONSTANT_UNQUALIFIED; - if (FC(current_namespace)) { - opline->op1.num |= IS_CONSTANT_IN_NAMESPACE; - opline->op2.constant = zend_add_const_name_literal( - resolved_name, 1); - } else { - opline->op2.constant = zend_add_const_name_literal( - resolved_name, 0); - } + opline->op1.num = IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE; + opline->op2.constant = zend_add_const_name_literal( + resolved_name, 1); } opline->extended_value = zend_alloc_cache_slot(); } @@ -8071,7 +7944,8 @@ void zend_compile_const_expr_const(zend_ast **ast_ptr) /* {{{ */ } zend_ast_destroy(ast); - *ast_ptr = zend_ast_create_constant(resolved_name, !is_fully_qualified ? IS_CONSTANT_UNQUALIFIED : 0); + *ast_ptr = zend_ast_create_constant(resolved_name, + !is_fully_qualified && FC(current_namespace) ? IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE : 0); } /* }}} */ @@ -8519,11 +8393,10 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */ int i; for (i = 0; i <= 1; i++) { zend_eval_const_expr(&ast->child[i]); - if (ast->child[i]->kind == ZEND_AST_ZVAL) { - if (zend_is_true(zend_ast_get_zval(ast->child[i])) == (ast->kind == ZEND_AST_OR)) { - ZVAL_BOOL(&result, ast->kind == ZEND_AST_OR); - return; - } + if (ast->child[i]->kind == ZEND_AST_ZVAL + && zend_is_true(zend_ast_get_zval(ast->child[i])) == (ast->kind == ZEND_AST_OR)) { + ZVAL_BOOL(&result, ast->kind == ZEND_AST_OR); + return; } } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 82d70fd4b0..a882d4f675 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -206,7 +206,7 @@ typedef struct _zend_oparray_context { /* Property or method overrides private one | | | */ #define ZEND_ACC_CHANGED (1 << 3) /* | X | X | */ /* | | | */ -/* Staic method or property | | | */ +/* Static method or property | | | */ #define ZEND_ACC_STATIC (1 << 4) /* | X | X | */ /* | | | */ /* Final class or method | | | */ @@ -234,10 +234,10 @@ typedef struct _zend_oparray_context { #define ZEND_ACC_TRAIT (1 << 1) /* X | | | */ #define ZEND_ACC_ANON_CLASS (1 << 2) /* X | | | */ /* | | | */ -/* Class linked with parent, interfacs and traits | | | */ +/* Class linked with parent, interfaces and traits | | | */ #define ZEND_ACC_LINKED (1 << 3) /* X | | | */ /* | | | */ -/* class is abstarct, since it is set by any | | | */ +/* Class is abstract, since it is set by any | | | */ /* abstract method | | | */ #define ZEND_ACC_IMPLICIT_ABSTRACT_CLASS (1 << 4) /* X | | | */ /* | | | */ @@ -288,10 +288,6 @@ typedef struct _zend_oparray_context { /* ZEND_DECLARE_INHERITED_CLASS_DELAYED opcodes | | | */ #define ZEND_ACC_EARLY_BINDING (1 << 15) /* | X | | */ /* | | | */ -/* method flag (bc only), any method that has this | | | */ -/* flag can be used statically and non statically. | | | */ -#define ZEND_ACC_ALLOW_STATIC (1 << 16) /* | X | | */ -/* | | | */ /* call through user function trampoline. e.g. | | | */ /* __call, __callstatic | | | */ #define ZEND_ACC_CALL_VIA_TRAMPOLINE (1 << 17) /* | X | | */ @@ -481,13 +477,6 @@ union _zend_function { zend_internal_function internal_function; }; -typedef enum _zend_call_kind { - ZEND_CALL_NESTED_FUNCTION, /* stackless VM call to function */ - ZEND_CALL_NESTED_CODE, /* stackless VM call to include/require/eval */ - ZEND_CALL_TOP_FUNCTION, /* direct VM call to function from external C code */ - ZEND_CALL_TOP_CODE /* direct VM call to "main" code from external C code */ -} zend_call_kind; - struct _zend_execute_data { const zend_op *opline; /* executed opline */ zend_execute_data *call; /* current call */ @@ -501,25 +490,31 @@ struct _zend_execute_data { #endif }; -#define ZEND_CALL_FUNCTION (0 << 0) -#define ZEND_CALL_CODE (1 << 0) -#define ZEND_CALL_NESTED (0 << 1) -#define ZEND_CALL_TOP (1 << 1) -#define ZEND_CALL_FREE_EXTRA_ARGS (1 << 2) -#define ZEND_CALL_CTOR (1 << 3) -#define ZEND_CALL_HAS_SYMBOL_TABLE (1 << 4) -#define ZEND_CALL_CLOSURE (1 << 5) -#define ZEND_CALL_RELEASE_THIS (1 << 6) -#define ZEND_CALL_ALLOCATED (1 << 7) -#define ZEND_CALL_GENERATOR (1 << 8) -#define ZEND_CALL_DYNAMIC (1 << 9) -#define ZEND_CALL_FAKE_CLOSURE (1 << 10) -#define ZEND_CALL_SEND_ARG_BY_REF (1 << 11) - -#define ZEND_CALL_INFO_SHIFT 16 +#define ZEND_CALL_HAS_THIS IS_OBJECT_EX + +/* Top 16 bits of Z_TYPE_INFO(EX(This)) are used as call_info flags */ +#define ZEND_CALL_FUNCTION (0 << 16) +#define ZEND_CALL_CODE (1 << 16) +#define ZEND_CALL_NESTED (0 << 17) +#define ZEND_CALL_TOP (1 << 17) +#define ZEND_CALL_ALLOCATED (1 << 18) +#define ZEND_CALL_FREE_EXTRA_ARGS (1 << 19) +#define ZEND_CALL_HAS_SYMBOL_TABLE (1 << 20) +#define ZEND_CALL_RELEASE_THIS (1 << 21) +#define ZEND_CALL_CTOR (1 << 22) +#define ZEND_CALL_CLOSURE (1 << 23) +#define ZEND_CALL_FAKE_CLOSURE (1 << 24) +#define ZEND_CALL_GENERATOR (1 << 25) +#define ZEND_CALL_DYNAMIC (1 << 26) +#define ZEND_CALL_SEND_ARG_BY_REF (1 << 31) + +#define ZEND_CALL_NESTED_FUNCTION (ZEND_CALL_FUNCTION | ZEND_CALL_NESTED) +#define ZEND_CALL_NESTED_CODE (ZEND_CALL_CODE | ZEND_CALL_NESTED) +#define ZEND_CALL_TOP_FUNCTION (ZEND_CALL_TOP | ZEND_CALL_FUNCTION) +#define ZEND_CALL_TOP_CODE (ZEND_CALL_CODE | ZEND_CALL_TOP) #define ZEND_CALL_INFO(call) \ - (Z_TYPE_INFO((call)->This) >> ZEND_CALL_INFO_SHIFT) + Z_TYPE_INFO((call)->This) #define ZEND_CALL_KIND_EX(call_info) \ (call_info & (ZEND_CALL_CODE | ZEND_CALL_TOP)) @@ -527,16 +522,12 @@ struct _zend_execute_data { #define ZEND_CALL_KIND(call) \ ZEND_CALL_KIND_EX(ZEND_CALL_INFO(call)) -#define ZEND_SET_CALL_INFO(call, object, info) do { \ - Z_TYPE_INFO((call)->This) = ((object) ? IS_OBJECT_EX : IS_UNDEF) | ((info) << ZEND_CALL_INFO_SHIFT); \ - } while (0) - #define ZEND_ADD_CALL_FLAG_EX(call_info, flag) do { \ - call_info |= ((flag) << ZEND_CALL_INFO_SHIFT); \ + call_info |= (flag); \ } while (0) #define ZEND_DEL_CALL_FLAG_EX(call_info, flag) do { \ - call_info &= ~((flag) << ZEND_CALL_INFO_SHIFT); \ + call_info &= ~(flag); \ } while (0) #define ZEND_ADD_CALL_FLAG(call, flag) do { \ @@ -889,14 +880,11 @@ void zend_assert_valid_class_name(const zend_string *const_name); #define BP_VAR_FUNC_ARG 4 #define BP_VAR_UNSET 5 -#define ZEND_INTERNAL_FUNCTION 1 -#define ZEND_USER_FUNCTION 2 -#define ZEND_OVERLOADED_FUNCTION 3 -#define ZEND_EVAL_CODE 4 -#define ZEND_OVERLOADED_FUNCTION_TEMPORARY 5 +#define ZEND_INTERNAL_FUNCTION 1 +#define ZEND_USER_FUNCTION 2 +#define ZEND_EVAL_CODE 4 -/* A quick check (type == ZEND_USER_FUNCTION || type == ZEND_EVAL_CODE) */ -#define ZEND_USER_CODE(type) ((type & 1) == 0) +#define ZEND_USER_CODE(type) ((type) != ZEND_INTERNAL_FUNCTION) #define ZEND_INTERNAL_CLASS 1 #define ZEND_USER_CLASS 2 @@ -933,9 +921,8 @@ void zend_assert_valid_class_name(const zend_string *const_name); #define ZEND_DIM_IS 1 -#define IS_CONSTANT_UNQUALIFIED 0x010 #define IS_CONSTANT_CLASS 0x080 /* __CLASS__ in trait */ -#define IS_CONSTANT_IN_NAMESPACE 0x100 +#define IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE 0x100 static zend_always_inline int zend_check_arg_send_type(const zend_function *zf, uint32_t arg_num, uint32_t mask) { @@ -1020,7 +1007,6 @@ END_EXTERN_C() #define ZEND_CALL_FUNC_NAME "__call" #define ZEND_CALLSTATIC_FUNC_NAME "__callstatic" #define ZEND_TOSTRING_FUNC_NAME "__tostring" -#define ZEND_AUTOLOAD_FUNC_NAME "__autoload" #define ZEND_INVOKE_FUNC_NAME "__invoke" #define ZEND_DEBUGINFO_FUNC_NAME "__debuginfo" @@ -1049,9 +1035,6 @@ END_EXTERN_C() /* disable constant substitution at compile-time */ #define ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION (1<<6) -/* disable usage of builtin instruction for strlen() */ -#define ZEND_COMPILE_NO_BUILTIN_STRLEN (1<<7) - /* disable substitution of persistent constants at compile-time */ #define ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION (1<<8) diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index 49ee762c60..2c0d8e2725 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -33,6 +33,9 @@ #define MARK_CONSTANT_VISITED(zv) Z_ACCESS_FLAGS_P(zv) |= IS_CONSTANT_VISITED_MARK #define RESET_CONSTANT_VISITED(zv) Z_ACCESS_FLAGS_P(zv) &= ~IS_CONSTANT_VISITED_MARK +/* Use for special null/true/false constants. */ +static zval null_value, true_value, false_value; + void free_zend_constant(zval *zv) { zend_constant *c = Z_PTR_P(zv); @@ -99,7 +102,6 @@ void clean_module_constants(int module_number) int zend_startup_constants(void) { EG(zend_constants) = (HashTable *) malloc(sizeof(HashTable)); - zend_hash_init(EG(zend_constants), 128, NULL, ZEND_CONSTANT_DTOR, 1); return SUCCESS; } @@ -128,14 +130,17 @@ void zend_register_standard_constants(void) REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_PROVIDE_OBJECT", DEBUG_BACKTRACE_PROVIDE_OBJECT, CONST_PERSISTENT | CONST_CS); REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_IGNORE_ARGS", DEBUG_BACKTRACE_IGNORE_ARGS, CONST_PERSISTENT | CONST_CS); - /* true/false constants */ - { - REGISTER_MAIN_BOOL_CONSTANT("TRUE", 1, CONST_PERSISTENT | CONST_CT_SUBST); - REGISTER_MAIN_BOOL_CONSTANT("FALSE", 0, CONST_PERSISTENT | CONST_CT_SUBST); - REGISTER_MAIN_BOOL_CONSTANT("ZEND_THREAD_SAFE", ZTS_V, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_BOOL_CONSTANT("ZEND_DEBUG_BUILD", ZEND_DEBUG, CONST_PERSISTENT | CONST_CS); - } - REGISTER_MAIN_NULL_CONSTANT("NULL", CONST_PERSISTENT | CONST_CT_SUBST); + REGISTER_MAIN_BOOL_CONSTANT("ZEND_THREAD_SAFE", ZTS_V, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_BOOL_CONSTANT("ZEND_DEBUG_BUILD", ZEND_DEBUG, CONST_PERSISTENT | CONST_CS); + + /* Special constants true/false/null. */ + REGISTER_MAIN_BOOL_CONSTANT("TRUE", 1, CONST_PERSISTENT); + REGISTER_MAIN_BOOL_CONSTANT("FALSE", 0, CONST_PERSISTENT); + REGISTER_MAIN_NULL_CONSTANT("NULL", CONST_PERSISTENT); + + ZVAL_NULL(&null_value); + ZVAL_TRUE(&true_value); + ZVAL_FALSE(&false_value); } @@ -204,7 +209,7 @@ ZEND_API void zend_register_string_constant(const char *name, size_t name_len, c zend_register_stringl_constant(name, name_len, strval, strlen(strval), flags, module_number); } -static zend_constant *zend_get_special_constant(const char *name, size_t name_len) +static zend_constant *zend_get_halt_offset_constant(const char *name, size_t name_len) { zend_constant *c; static const char haltoff[] = "__COMPILER_HALT_OFFSET__"; @@ -230,6 +235,37 @@ static zend_constant *zend_get_special_constant(const char *name, size_t name_le } } +ZEND_API zval *_zend_get_special_const(const char *name, size_t len) /* {{{ */ +{ + if (len == 4) { + if ((name[0] == 'n' || name[0] == 'N') && + (name[1] == 'u' || name[1] == 'U') && + (name[2] == 'l' || name[2] == 'L') && + (name[3] == 'l' || name[3] == 'L') + ) { + return &null_value; + } + if ((name[0] == 't' || name[0] == 'T') && + (name[1] == 'r' || name[1] == 'R') && + (name[2] == 'u' || name[2] == 'U') && + (name[3] == 'e' || name[3] == 'E') + ) { + return &true_value; + } + } else { + if ((name[0] == 'f' || name[0] == 'F') && + (name[1] == 'a' || name[1] == 'A') && + (name[2] == 'l' || name[2] == 'L') && + (name[3] == 's' || name[3] == 'S') && + (name[4] == 'e' || name[4] == 'E') + ) { + return &false_value; + } + } + return 0; +} +/* }}} */ + ZEND_API int zend_verify_const_access(zend_class_constant *c, zend_class_entry *scope) /* {{{ */ { if (Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PUBLIC) { @@ -243,80 +279,34 @@ ZEND_API int zend_verify_const_access(zend_class_constant *c, zend_class_entry * } /* }}} */ -static inline zend_constant *zend_get_constant_str_impl(const char *name, size_t name_len) -{ - zend_constant *c; - ALLOCA_FLAG(use_heap) - - if ((c = zend_hash_str_find_ptr(EG(zend_constants), name, name_len)) == NULL) { - char *lcname = do_alloca(name_len + 1, use_heap); - zend_str_tolower_copy(lcname, name, name_len); - if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, name_len)) != NULL) { - if (ZEND_CONSTANT_FLAGS(c) & CONST_CS) { - c = NULL; - } - } else { - c = zend_get_special_constant(name, name_len); - } - free_alloca(lcname, use_heap); - } - - return c; -} - ZEND_API zval *zend_get_constant_str(const char *name, size_t name_len) { - zend_constant *c = zend_get_constant_str_impl(name, name_len); - return c ? &c->value : NULL; -} + zend_constant *c = zend_hash_str_find_ptr(EG(zend_constants), name, name_len); + if (c) { + return &c->value; + } -static inline zend_constant *zend_get_constant_impl(zend_string *name) -{ - zval *zv; - zend_constant *c; - ALLOCA_FLAG(use_heap) - - zv = zend_hash_find(EG(zend_constants), name); - if (zv == NULL) { - char *lcname = do_alloca(ZSTR_LEN(name) + 1, use_heap); - zend_str_tolower_copy(lcname, ZSTR_VAL(name), ZSTR_LEN(name)); - zv = zend_hash_str_find(EG(zend_constants), lcname, ZSTR_LEN(name)); - if (zv != NULL) { - c = Z_PTR_P(zv); - if (ZEND_CONSTANT_FLAGS(c) & CONST_CS) { - c = NULL; - } - } else { - c = zend_get_special_constant(ZSTR_VAL(name), ZSTR_LEN(name)); - } - free_alloca(lcname, use_heap); - return c; - } else { - return (zend_constant *) Z_PTR_P(zv); + c = zend_get_halt_offset_constant(name, name_len); + if (c) { + return &c->value; } + + return zend_get_special_const(name, name_len); } ZEND_API zval *zend_get_constant(zend_string *name) { - zend_constant *c = zend_get_constant_impl(name); - return c ? &c->value : NULL; -} + zend_constant *c = zend_hash_find_ptr(EG(zend_constants), name); + if (c) { + return &c->value; + } -static zend_bool is_access_deprecated(const zend_constant *c, const char *access_name) { - const char *ns_sep = zend_memrchr(ZSTR_VAL(c->name), '\\', ZSTR_LEN(c->name)); - if (ns_sep) { - /* Namespaces are always case-insensitive. Only compare shortname. */ - size_t shortname_offset = ns_sep - ZSTR_VAL(c->name) + 1; - size_t shortname_len = ZSTR_LEN(c->name) - shortname_offset; - return memcmp( - access_name + shortname_offset, - ZSTR_VAL(c->name) + shortname_offset, - shortname_len - ) != 0; - } else { - /* No namespace, compare whole name */ - return memcmp(access_name, ZSTR_VAL(c->name), ZSTR_LEN(c->name)) != 0; + c = zend_get_halt_offset_constant(ZSTR_VAL(name), ZSTR_LEN(name)); + if (c) { + return &c->value; } + + return zend_get_special_const(ZSTR_VAL(name), ZSTR_LEN(name)); } ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, uint32_t flags) @@ -421,56 +411,34 @@ failure: size_t lcname_len; ALLOCA_FLAG(use_heap) + /* Lowercase the namespace portion */ lcname_len = prefix_len + 1 + const_name_len; lcname = do_alloca(lcname_len + 1, use_heap); zend_str_tolower_copy(lcname, name, prefix_len); - /* Check for namespace constant */ lcname[prefix_len] = '\\'; memcpy(lcname + prefix_len + 1, constant_name, const_name_len + 1); - if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) == NULL) { - /* try lowercase */ - zend_str_tolower(lcname + prefix_len + 1, const_name_len); - if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) != NULL) { - if ((ZEND_CONSTANT_FLAGS(c) & CONST_CS) != 0) { - c = NULL; - } - } - } + c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len); free_alloca(lcname, use_heap); - if (!c) { - if (!(flags & IS_CONSTANT_UNQUALIFIED)) { - return NULL; - } + if (c) { + return &c->value; + } - /* name requires runtime resolution, need to check non-namespaced name */ - c = zend_get_constant_str_impl(constant_name, const_name_len); - name = constant_name; + if (!(flags & IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE)) { + return NULL; } + + /* name requires runtime resolution, need to check non-namespaced name */ + return zend_get_constant_str(constant_name, const_name_len); } else { if (cname) { - c = zend_get_constant_impl(cname); + return zend_get_constant(cname); } else { - c = zend_get_constant_str_impl(name, name_len); - } - } - - if (!c) { - return NULL; - } - - if (!(flags & ZEND_GET_CONSTANT_NO_DEPRECATION_CHECK)) { - if (!(ZEND_CONSTANT_FLAGS(c) & (CONST_CS|CONST_CT_SUBST)) && is_access_deprecated(c, name)) { - zend_error(E_DEPRECATED, - "Case-insensitive constants are deprecated. " - "The correct casing for this constant is \"%s\"", - ZSTR_VAL(c->name)); + return zend_get_constant_str(name, name_len); } } - - return &c->value; } static void* zend_hash_add_constant(HashTable *ht, zend_string *key, zend_constant *c) @@ -491,38 +459,30 @@ ZEND_API int zend_register_constant(zend_constant *c) zend_string *lowercase_name = NULL; zend_string *name; int ret = SUCCESS; + zend_bool persistent = (ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) != 0; #if 0 printf("Registering constant for module %d\n", c->module_number); #endif - if (!(ZEND_CONSTANT_FLAGS(c) & CONST_CS)) { - lowercase_name = zend_string_tolower_ex(c->name, ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT); + char *slash = strrchr(ZSTR_VAL(c->name), '\\'); + if (slash) { + lowercase_name = zend_string_init(ZSTR_VAL(c->name), ZSTR_LEN(c->name), persistent); + zend_str_tolower(ZSTR_VAL(lowercase_name), slash - ZSTR_VAL(c->name)); lowercase_name = zend_new_interned_string(lowercase_name); name = lowercase_name; } else { - char *slash = strrchr(ZSTR_VAL(c->name), '\\'); - if (slash) { - lowercase_name = zend_string_init(ZSTR_VAL(c->name), ZSTR_LEN(c->name), ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT); - zend_str_tolower(ZSTR_VAL(lowercase_name), slash - ZSTR_VAL(c->name)); - lowercase_name = zend_new_interned_string(lowercase_name); - name = lowercase_name; - } else { - name = c->name; - } + name = c->name; } - /* Check if the user is trying to define the internal pseudo constant name __COMPILER_HALT_OFFSET__ */ + /* Check if the user is trying to define any special constant */ if (zend_string_equals_literal(name, "__COMPILER_HALT_OFFSET__") - || zend_hash_add_constant(EG(zend_constants), name, c) == NULL) { - - /* The internal __COMPILER_HALT_OFFSET__ is prefixed by NULL byte */ - if (ZSTR_VAL(c->name)[0] == '\0' && ZSTR_LEN(c->name) > sizeof("\0__COMPILER_HALT_OFFSET__")-1 - && memcmp(ZSTR_VAL(name), "\0__COMPILER_HALT_OFFSET__", sizeof("\0__COMPILER_HALT_OFFSET__")) == 0) { - } + || (!persistent && zend_get_special_const(ZSTR_VAL(name), ZSTR_LEN(name))) + || zend_hash_add_constant(EG(zend_constants), name, c) == NULL + ) { zend_error(E_NOTICE,"Constant %s already defined", ZSTR_VAL(name)); zend_string_release(c->name); - if (!(ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT)) { + if (!persistent) { zval_ptr_dtor_nogc(&c->value); } ret = FAILURE; diff --git a/Zend/zend_constants.h b/Zend/zend_constants.h index ba0c798dc6..4d3335a490 100644 --- a/Zend/zend_constants.h +++ b/Zend/zend_constants.h @@ -22,16 +22,12 @@ #include "zend_globals.h" -#define CONST_CS (1<<0) /* Case Sensitive */ -#define CONST_PERSISTENT (1<<1) /* Persistent */ -#define CONST_CT_SUBST (1<<2) /* Allow compile-time substitution */ -#define CONST_NO_FILE_CACHE (1<<3) /* Can't be saved in file cache */ +#define CONST_CS 0 /* No longer used -- always case sensitive */ +#define CONST_PERSISTENT (1<<0) /* Persistent */ +#define CONST_NO_FILE_CACHE (1<<1) /* Can't be saved in file cache */ #define PHP_USER_CONSTANT 0x7fffff /* a constant defined in user space */ -/* Flag for zend_get_constant_ex(). Must not class with ZEND_FETCH_CLASS_* flags. */ -#define ZEND_GET_CONSTANT_NO_DEPRECATION_CHECK 0x1000 - typedef struct _zend_constant { zval value; zend_string *name; @@ -89,6 +85,16 @@ ZEND_API int zend_register_constant(zend_constant *c); #ifdef ZTS void zend_copy_constants(HashTable *target, HashTable *sourc); #endif + +ZEND_API zval *_zend_get_special_const(const char *name, size_t name_len); + +static zend_always_inline zval *zend_get_special_const(const char *name, size_t name_len) { + if (name_len == 4 || name_len == 5) { + return _zend_get_special_const(name, name_len); + } + return NULL; +} + END_EXTERN_C() #define ZEND_CONSTANT_DTOR free_zend_constant diff --git a/Zend/zend_cpuinfo.h b/Zend/zend_cpuinfo.h index 87bc75c39a..10ba97b3d2 100644 --- a/Zend/zend_cpuinfo.h +++ b/Zend/zend_cpuinfo.h @@ -12,7 +12,7 @@ | obtain it through the world-wide-web, please send a note to | | license@zend.com so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Authors: Xinchen Hui <xinchen.h@zend.com> | + | Authors: Xinchen Hui <laruence@php.net> | +----------------------------------------------------------------------+ */ diff --git a/Zend/zend_errors.h b/Zend/zend_errors.h index 441458c033..6fda0f843e 100644 --- a/Zend/zend_errors.h +++ b/Zend/zend_errors.h @@ -39,4 +39,9 @@ #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) +/* Fatal errors that are ignored by the silence operator */ +#define E_FATAL_ERRORS (E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR | E_PARSE) + +#define E_HAS_ONLY_FATAL_ERRORS(mask) !((mask) & ~E_FATAL_ERRORS) + #endif /* ZEND_ERRORS_H */ diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index e53ea1f1c7..f758b96bf9 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -994,7 +994,7 @@ ZEND_API ZEND_COLD void zend_exception_error(zend_object *ex, int severity) /* { zend_string *str, *file = NULL; zend_long line = 0; - zend_call_method_with_0_params(&exception, ce_exception, &ex->ce->__tostring, "__tostring", &tmp); + zend_call_method_with_0_params(Z_OBJ(exception), ce_exception, &ex->ce->__tostring, "__tostring", &tmp); if (!EG(exception)) { if (Z_TYPE(tmp) != IS_STRING) { zend_error(E_WARNING, "%s::__toString() must return a string", ZSTR_VAL(ce_exception->name)); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index bb3ca87b04..1d626a0def 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -738,8 +738,8 @@ static zend_never_inline ZEND_COLD zval* ZEND_FASTCALL make_real_object(zval *ob zval_ptr_dtor_nogc(object); object_init(object); - Z_ADDREF_P(object); obj = Z_OBJ_P(object); + GC_ADDREF(obj); zend_error(E_WARNING, "Creating default object from empty value"); if (GC_REFCOUNT(obj) == 1) { /* the enclosing container was deleted, obj is unreferenced */ @@ -749,7 +749,7 @@ static zend_never_inline ZEND_COLD zval* ZEND_FASTCALL make_real_object(zval *ob } return NULL; } - Z_DELREF_P(object); + GC_DELREF(obj); return object; } @@ -1288,7 +1288,7 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_offset(void) static zend_never_inline void zend_assign_to_object_dim(zval *object, zval *dim, zval *value OPLINE_DC EXECUTE_DATA_DC) { - Z_OBJ_HT_P(object)->write_dimension(object, dim, value); + Z_OBJ_HT_P(object)->write_dimension(Z_OBJ_P(object), dim, value); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); @@ -1300,11 +1300,11 @@ static zend_never_inline void zend_binary_assign_op_obj_dim(zval *object, zval * zval *z; zval rv, res; - if ((z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R, &rv)) != NULL) { + if ((z = Z_OBJ_HT_P(object)->read_dimension(Z_OBJ_P(object), property, BP_VAR_R, &rv)) != NULL) { if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { zval rv2; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv2); + zval *value = Z_OBJ_HT_P(z)->get(Z_OBJ_P(z), &rv2); if (z == &rv) { zval_ptr_dtor(&rv); @@ -1312,7 +1312,7 @@ static zend_never_inline void zend_binary_assign_op_obj_dim(zval *object, zval * ZVAL_COPY_VALUE(z, value); } if (binary_op(&res, z, value) == SUCCESS) { - Z_OBJ_HT_P(object)->write_dimension(object, property, &res); + Z_OBJ_HT_P(object)->write_dimension(Z_OBJ_P(object), property, &res); } if (z == &rv) { zval_ptr_dtor(&rv); @@ -1775,24 +1775,23 @@ static void zend_post_incdec_property_zval(zval *prop, zend_property_info *prop_ } } -static zend_never_inline void zend_post_incdec_overloaded_property(zval *object, zval *property, void **cache_slot, int inc OPLINE_DC EXECUTE_DATA_DC) +static zend_never_inline void zend_post_incdec_overloaded_property(zend_object *object, zend_string *name, void **cache_slot, int inc OPLINE_DC EXECUTE_DATA_DC) { - zval rv, obj; + zval rv; zval *z; zval z_copy; - ZVAL_OBJ(&obj, Z_OBJ_P(object)); - Z_ADDREF(obj); - z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv); + GC_ADDREF(object); + z =object->handlers->read_property(object, name, BP_VAR_R, cache_slot, &rv); if (UNEXPECTED(EG(exception))) { - OBJ_RELEASE(Z_OBJ(obj)); + OBJ_RELEASE(object); ZVAL_UNDEF(EX_VAR(opline->result.var)); return; } if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { zval rv2; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv2); + zval *value = Z_OBJ_HT_P(z)->get(Z_OBJ_P(z), &rv2); if (z == &rv) { zval_ptr_dtor(&rv); } @@ -1806,23 +1805,22 @@ static zend_never_inline void zend_post_incdec_overloaded_property(zval *object, } else { decrement_function(&z_copy); } - Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, cache_slot); - OBJ_RELEASE(Z_OBJ(obj)); + object->handlers->write_property(object, name, &z_copy, cache_slot); + OBJ_RELEASE(object); zval_ptr_dtor(&z_copy); zval_ptr_dtor(z); } -static zend_never_inline void zend_pre_incdec_overloaded_property(zval *object, zval *property, void **cache_slot, int inc OPLINE_DC EXECUTE_DATA_DC) +static zend_never_inline void zend_pre_incdec_overloaded_property(zend_object *object, zend_string *name, void **cache_slot, int inc OPLINE_DC EXECUTE_DATA_DC) { zval rv; - zval *z, obj; + zval *z; zval z_copy; - ZVAL_OBJ(&obj, Z_OBJ_P(object)); - Z_ADDREF(obj); - z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv); + GC_ADDREF(object); + z = object->handlers->read_property(object, name, BP_VAR_R, cache_slot, &rv); if (UNEXPECTED(EG(exception))) { - OBJ_RELEASE(Z_OBJ(obj)); + OBJ_RELEASE(object); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -1831,7 +1829,7 @@ static zend_never_inline void zend_pre_incdec_overloaded_property(zval *object, if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) { zval rv2; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv2); + zval *value = Z_OBJ_HT_P(z)->get(Z_OBJ_P(z), &rv2); if (z == &rv) { zval_ptr_dtor(&rv); @@ -1847,22 +1845,21 @@ static zend_never_inline void zend_pre_incdec_overloaded_property(zval *object, if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), &z_copy); } - Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, cache_slot); - OBJ_RELEASE(Z_OBJ(obj)); + object->handlers->write_property(object, name, &z_copy, cache_slot); + OBJ_RELEASE(object); zval_ptr_dtor(&z_copy); zval_ptr_dtor(z); } -static zend_never_inline void zend_assign_op_overloaded_property(zval *object, zval *property, void **cache_slot, zval *value, binary_op_type binary_op OPLINE_DC EXECUTE_DATA_DC) +static zend_never_inline void zend_assign_op_overloaded_property(zend_object *object, zend_string *name, void **cache_slot, zval *value, binary_op_type binary_op OPLINE_DC EXECUTE_DATA_DC) { zval *z; - zval rv, obj, res; + zval rv, res; - ZVAL_OBJ(&obj, Z_OBJ_P(object)); - Z_ADDREF(obj); - z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv); + GC_ADDREF(object); + z = object->handlers->read_property(object, name, BP_VAR_R, cache_slot, &rv); if (UNEXPECTED(EG(exception))) { - OBJ_RELEASE(Z_OBJ(obj)); + OBJ_RELEASE(object); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_UNDEF(EX_VAR(opline->result.var)); } @@ -1870,7 +1867,7 @@ static zend_never_inline void zend_assign_op_overloaded_property(zval *object, z } if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { zval rv2; - zval *value = Z_OBJ_HT_P(z)->get(z, &rv2); + zval *value = Z_OBJ_HT_P(z)->get(Z_OBJ_P(z), &rv2); if (z == &rv) { zval_ptr_dtor(&rv); @@ -1878,14 +1875,14 @@ static zend_never_inline void zend_assign_op_overloaded_property(zval *object, z ZVAL_COPY_VALUE(z, value); } if (binary_op(&res, z, value) == SUCCESS) { - Z_OBJ_HT(obj)->write_property(&obj, property, &res, cache_slot); + object->handlers->write_property(object, name, &res, cache_slot); } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), &res); } zval_ptr_dtor(z); zval_ptr_dtor(&res); - OBJ_RELEASE(Z_OBJ(obj)); + OBJ_RELEASE(object); } /* Utility Functions for Extensions */ @@ -1951,16 +1948,10 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_invalid_method_call(z static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_non_static_method_call(const zend_function *fbc) { - if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_DEPRECATED, - "Non-static method %s::%s() should not be called statically", - ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name)); - } else { - zend_throw_error( - zend_ce_error, - "Non-static method %s::%s() cannot be called statically", - ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name)); - } + zend_throw_error( + zend_ce_error, + "Non-static method %s::%s() cannot be called statically", + ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name)); } static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_param_must_be_ref(const zend_function *func, uint32_t arg_num) @@ -2184,7 +2175,7 @@ fetch_from_array: if (dim_type == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result); + retval = Z_OBJ_HT_P(container)->read_dimension(Z_OBJ_P(container), dim, type, result); if (UNEXPECTED(retval == &EG(uninitialized_zval))) { zend_class_entry *ce = Z_OBJCE_P(container); @@ -2339,7 +2330,7 @@ try_string_offset: if (dim_type == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result); + retval = Z_OBJ_HT_P(container)->read_dimension(Z_OBJ_P(container), dim, type, result); ZEND_ASSERT(result != NULL); if (retval) { @@ -2427,7 +2418,7 @@ static zend_never_inline int ZEND_FASTCALL zend_isset_dim_slow(zval *container, } if (/*OP1_TYPE != IS_CONST &&*/ EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - return Z_OBJ_HT_P(container)->has_dimension(container, offset, 0); + return Z_OBJ_HT_P(container)->has_dimension(Z_OBJ_P(container), offset, 0); } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zend_long lval; @@ -2466,7 +2457,7 @@ static zend_never_inline int ZEND_FASTCALL zend_isempty_dim_slow(zval *container } if (/*OP1_TYPE != IS_CONST &&*/ EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - return !Z_OBJ_HT_P(container)->has_dimension(container, offset, 1); + return !Z_OBJ_HT_P(container)->has_dimension(Z_OBJ_P(container), offset, 1); } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */ zend_long lval; @@ -2544,7 +2535,7 @@ static zend_never_inline uint32_t ZEND_FASTCALL zend_array_key_exists_slow(zval if (UNEXPECTED(Z_TYPE_INFO_P(subject) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); } - zend_internal_type_error(EX_USES_STRICT_TYPES(), "array_key_exists() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(subject))); + zend_type_error("array_key_exists() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(subject))); return IS_NULL; } } @@ -2696,8 +2687,10 @@ static zend_never_inline zend_bool zend_handle_fetch_obj_flags( static zend_always_inline void zend_fetch_property_address(zval *result, zval *container, uint32_t container_op_type, zval *prop_ptr, uint32_t prop_op_type, void **cache_slot, int type, uint32_t flags, zend_bool init_undef OPLINE_DC EXECUTE_DATA_DC) { zval *ptr; + zend_object *zobj; + zend_string *name, *tmp_name; - if (container_op_type != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + if (container_op_type != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { do { if (Z_ISREF_P(container) && Z_TYPE_P(Z_REFVAL_P(container)) == IS_OBJECT) { container = Z_REFVAL_P(container); @@ -2716,10 +2709,11 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c } } while (0); } + + zobj = Z_OBJ_P(container); if (prop_op_type == IS_CONST && - EXPECTED(Z_OBJCE_P(container) == CACHED_PTR_EX(cache_slot))) { + EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); - zend_object *zobj = Z_OBJ_P(container); if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { ptr = OBJ_PROP(zobj, prop_offset); @@ -2747,9 +2741,15 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c } } } - ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr, type, cache_slot); + + if (prop_op_type == IS_CONST) { + name = Z_STR_P(prop_ptr); + } else { + name = zval_get_tmp_string(prop_ptr, &tmp_name); + } + ptr = zobj->handlers->get_property_ptr_ptr(zobj, name, type, cache_slot); if (NULL == ptr) { - ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result); + ptr = zobj->handlers->read_property(zobj, name, type, cache_slot, result); if (ptr == result) { if (UNEXPECTED(Z_ISREF_P(ptr) && Z_REFCOUNT_P(ptr) == 1)) { ZVAL_UNREF(ptr); @@ -3752,7 +3752,8 @@ static void cleanup_live_vars(zend_execute_data *execute_data, uint32_t op_num, } } else if (kind == ZEND_LIVE_SILENCE) { /* restore previous error_reporting value */ - if (!EG(error_reporting) && Z_LVAL_P(var) != 0) { + if (E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting)) + && !E_HAS_ONLY_FATAL_ERRORS(Z_LVAL_P(var))) { EG(error_reporting) = Z_LVAL_P(var); } } @@ -3826,9 +3827,7 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_s if (UNEXPECTED(!(fbc->common.fn_flags & ZEND_ACC_STATIC))) { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - return NULL; - } + return NULL; } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -3855,20 +3854,22 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_s } return zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC, - fbc, num_args, called_scope, NULL); + fbc, num_args, called_scope); } /* }}} */ -static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zval *function, uint32_t num_args) /* {{{ */ +static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zend_object *function, uint32_t num_args) /* {{{ */ { zend_function *fbc; + void *object_or_called_scope; zend_class_entry *called_scope; zend_object *object; uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; - if (EXPECTED(Z_OBJ_HANDLER_P(function, get_closure)) && - EXPECTED(Z_OBJ_HANDLER_P(function, get_closure)(function, &called_scope, &fbc, &object) == SUCCESS)) { + if (EXPECTED(function->handlers->get_closure) && + EXPECTED(function->handlers->get_closure(function, &called_scope, &fbc, &object) == SUCCESS)) { + object_or_called_scope = called_scope; if (fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ GC_ADDREF(ZEND_CLOSURE_OBJECT(fbc)); @@ -3876,9 +3877,14 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zval * if (fbc->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { call_info |= ZEND_CALL_FAKE_CLOSURE; } + if (object) { + call_info |= ZEND_CALL_HAS_THIS; + object_or_called_scope = object; + } } else if (object) { - call_info |= ZEND_CALL_RELEASE_THIS; + call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; GC_ADDREF(object); /* For $this pointer */ + object_or_called_scope = object; } } else { zend_throw_error(NULL, "Function name must be a string"); @@ -3890,15 +3896,14 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zval * } return zend_vm_stack_push_call_frame(call_info, - fbc, num_args, called_scope, object); + fbc, num_args, object_or_called_scope); } /* }}} */ static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_array *function, uint32_t num_args) /* {{{ */ { zend_function *fbc; - zend_class_entry *called_scope; - zend_object *object; + void *object_or_called_scope; uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; if (zend_hash_num_elements(function) == 2) { @@ -3925,8 +3930,8 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_ar } if (Z_TYPE_P(obj) == IS_STRING) { - object = NULL; - called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + zend_class_entry *called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(called_scope == NULL)) { return NULL; } @@ -3944,13 +3949,11 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_ar } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - return NULL; - } + return NULL; } + object_or_called_scope = called_scope; } else { - called_scope = Z_OBJCE_P(obj); - object = Z_OBJ_P(obj); + zend_object *object = Z_OBJ_P(obj); fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL); if (UNEXPECTED(fbc == NULL)) { @@ -3961,10 +3964,11 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_ar } if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { - object = NULL; + object_or_called_scope = object->ce; } else { - call_info |= ZEND_CALL_RELEASE_THIS; + call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; GC_ADDREF(object); /* For $this pointer */ + object_or_called_scope = object; } } } else { @@ -3977,7 +3981,7 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_ar } return zend_vm_stack_push_call_frame(call_info, - fbc, num_args, called_scope, object); + fbc, num_args, object_or_called_scope); } /* }}} */ @@ -4070,43 +4074,6 @@ already_compiled: } /* }}} */ -ZEND_API int ZEND_FASTCALL zend_do_fcall_overloaded(zend_execute_data *call, zval *ret) /* {{{ */ -{ - zend_function *fbc = call->func; - zend_object *object; - - /* Not sure what should be done here if it's a static method */ - if (UNEXPECTED(Z_TYPE(call->This) != IS_OBJECT)) { - zend_vm_stack_free_args(call); - if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { - zend_string_release_ex(fbc->common.function_name, 0); - } - efree(fbc); - zend_vm_stack_free_call_frame(call); - - zend_throw_error(NULL, "Cannot call overloaded function for non-object"); - return 0; - } - - object = Z_OBJ(call->This); - - ZVAL_NULL(ret); - - EG(current_execute_data) = call; - object->handlers->call_method(fbc->common.function_name, object, call, ret); - EG(current_execute_data) = call->prev_execute_data; - - zend_vm_stack_free_args(call); - - if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { - zend_string_release_ex(fbc->common.function_name, 0); - } - efree(fbc); - - return 1; -} -/* }}} */ - static zend_never_inline zend_bool ZEND_FASTCALL zend_fe_reset_iterator(zval *array_ptr, int by_ref OPLINE_DC EXECUTE_DATA_DC) /* {{{ */ { zend_class_entry *ce = Z_OBJCE_P(array_ptr); @@ -4154,96 +4121,30 @@ static zend_always_inline int _zend_quick_get_constant( const zval *key, uint32_t flags, int check_defined_only OPLINE_DC EXECUTE_DATA_DC) /* {{{ */ { zval *zv; - const zval *orig_key = key; zend_constant *c = NULL; + /* null/true/false are resolved during compilation, so don't check for them here. */ zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1); if (zv) { c = (zend_constant*)Z_PTR_P(zv); - } else { + } else if (flags & IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE) { key++; zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1); - if (zv && (ZEND_CONSTANT_FLAGS((zend_constant*)Z_PTR_P(zv)) & CONST_CS) == 0) { + if (zv) { c = (zend_constant*)Z_PTR_P(zv); - } else { - if ((flags & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) { - key++; - zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1); - if (zv) { - c = (zend_constant*)Z_PTR_P(zv); - } else { - key++; - zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1); - if (zv && (ZEND_CONSTANT_FLAGS((zend_constant*)Z_PTR_P(zv)) & CONST_CS) == 0) { - c = (zend_constant*)Z_PTR_P(zv); - } - } - } } } if (!c) { if (!check_defined_only) { - if ((opline->op1.num & IS_CONSTANT_UNQUALIFIED) != 0) { - char *actual = (char *)zend_memrchr(Z_STRVAL_P(RT_CONSTANT(opline, opline->op2)), '\\', Z_STRLEN_P(RT_CONSTANT(opline, opline->op2))); - if (!actual) { - ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_STR_P(RT_CONSTANT(opline, opline->op2))); - } else { - actual++; - ZVAL_STRINGL(EX_VAR(opline->result.var), - actual, Z_STRLEN_P(RT_CONSTANT(opline, opline->op2)) - (actual - Z_STRVAL_P(RT_CONSTANT(opline, opline->op2)))); - } - /* non-qualified constant - allow text substitution */ - zend_error(E_WARNING, "Use of undefined constant %s - assumed '%s' (this will throw an Error in a future version of PHP)", - Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var))); - } else { - zend_throw_error(NULL, "Undefined constant '%s'", Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - } + zend_throw_error(NULL, "Undefined constant '%s'", Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } return FAILURE; } if (!check_defined_only) { ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value); - if (!(ZEND_CONSTANT_FLAGS(c) & (CONST_CS|CONST_CT_SUBST))) { - const char *ns_sep; - size_t shortname_offset; - size_t shortname_len; - zend_bool is_deprecated; - - if (flags & IS_CONSTANT_UNQUALIFIED) { - const zval *access_key; - - if (!(flags & IS_CONSTANT_IN_NAMESPACE)) { - access_key = orig_key - 1; - } else { - if (key < orig_key + 2) { - goto check_short_name; - } else { - access_key = orig_key + 2; - } - } - is_deprecated = !zend_string_equals(c->name, Z_STR_P(access_key)); - } else { -check_short_name: - ns_sep = zend_memrchr(ZSTR_VAL(c->name), '\\', ZSTR_LEN(c->name)); - ZEND_ASSERT(ns_sep); - /* Namespaces are always case-insensitive. Only compare shortname. */ - shortname_offset = ns_sep - ZSTR_VAL(c->name) + 1; - shortname_len = ZSTR_LEN(c->name) - shortname_offset; - - is_deprecated = memcmp(ZSTR_VAL(c->name) + shortname_offset, Z_STRVAL_P(orig_key - 1) + shortname_offset, shortname_len) != 0; - } - - if (is_deprecated) { - zend_error(E_DEPRECATED, - "Case-insensitive constants are deprecated. " - "The correct casing for this constant is \"%s\"", - ZSTR_VAL(c->name)); - return SUCCESS; - } - } } CACHE_PTR(opline->extended_value, c); diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index effeec6577..4abdaca9fd 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -118,7 +118,7 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval } if (Z_TYPE_P(variable_ptr) == IS_OBJECT && UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) { - Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr, value); + Z_OBJ_HANDLER_P(variable_ptr, set)(Z_OBJ_P(variable_ptr), value); return variable_ptr; } garbage = Z_COUNTED_P(variable_ptr); @@ -206,20 +206,15 @@ ZEND_API void zend_vm_stack_init_ex(size_t page_size); ZEND_API void zend_vm_stack_destroy(void); ZEND_API void* zend_vm_stack_extend(size_t size); -static zend_always_inline void zend_vm_init_call_frame(zend_execute_data *call, uint32_t call_info, zend_function *func, uint32_t num_args, zend_class_entry *called_scope, zend_object *object) +static zend_always_inline void zend_vm_init_call_frame(zend_execute_data *call, uint32_t call_info, zend_function *func, uint32_t num_args, void *object_or_called_scope) { call->func = func; - if (object) { - Z_OBJ(call->This) = object; - ZEND_SET_CALL_INFO(call, 1, call_info); - } else { - Z_CE(call->This) = called_scope; - ZEND_SET_CALL_INFO(call, 0, call_info); - } + Z_PTR(call->This) = object_or_called_scope; + ZEND_CALL_INFO(call) = call_info; ZEND_CALL_NUM_ARGS(call) = num_args; } -static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame_ex(uint32_t used_stack, uint32_t call_info, zend_function *func, uint32_t num_args, zend_class_entry *called_scope, zend_object *object) +static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame_ex(uint32_t used_stack, uint32_t call_info, zend_function *func, uint32_t num_args, void *object_or_called_scope) { zend_execute_data *call = (zend_execute_data*)EG(vm_stack_top); @@ -228,11 +223,11 @@ static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame_ex(ui if (UNEXPECTED(used_stack > (size_t)(((char*)EG(vm_stack_end)) - (char*)call))) { call = (zend_execute_data*)zend_vm_stack_extend(used_stack); ZEND_ASSERT_VM_STACK_GLOBAL; - zend_vm_init_call_frame(call, call_info | ZEND_CALL_ALLOCATED, func, num_args, called_scope, object); + zend_vm_init_call_frame(call, call_info | ZEND_CALL_ALLOCATED, func, num_args, object_or_called_scope); return call; } else { EG(vm_stack_top) = (zval*)((char*)call + used_stack); - zend_vm_init_call_frame(call, call_info, func, num_args, called_scope, object); + zend_vm_init_call_frame(call, call_info, func, num_args, object_or_called_scope); return call; } } @@ -247,12 +242,12 @@ static zend_always_inline uint32_t zend_vm_calc_used_stack(uint32_t num_args, ze return used_stack * sizeof(zval); } -static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(uint32_t call_info, zend_function *func, uint32_t num_args, zend_class_entry *called_scope, zend_object *object) +static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(uint32_t call_info, zend_function *func, uint32_t num_args, void *object_or_called_scope) { uint32_t used_stack = zend_vm_calc_used_stack(num_args, func); return zend_vm_stack_push_call_frame_ex(used_stack, call_info, - func, num_args, called_scope, object); + func, num_args, object_or_called_scope); } static zend_always_inline void zend_vm_stack_free_extra_args_ex(uint32_t call_info, zend_execute_data *call) @@ -367,8 +362,6 @@ ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table); ZEND_API void zend_free_compiled_variables(zend_execute_data *execute_data); ZEND_API void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num); -ZEND_API int ZEND_FASTCALL zend_do_fcall_overloaded(zend_execute_data *call, zval *ret); - #define CACHE_ADDR(num) \ ((void**)((char*)EX_RUN_TIME_CACHE() + (num))) diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index ab1ef9fa49..d1ed1174a6 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -178,8 +178,6 @@ void init_executor(void) /* {{{ */ EG(ht_iterators) = EG(ht_iterators_slots); memset(EG(ht_iterators), 0, sizeof(EG(ht_iterators_slots))); - EG(each_deprecation_thrown) = 0; - EG(persistent_constants_count) = EG(zend_constants)->nNumUsed; EG(persistent_functions_count) = EG(function_table)->nNumUsed; EG(persistent_classes_count) = EG(class_table)->nNumUsed; @@ -573,29 +571,10 @@ ZEND_API int zend_use_undefined_constant(zend_string *name, zend_ast_attr attr, } else if ((colon = (char*)zend_memrchr(ZSTR_VAL(name), ':', ZSTR_LEN(name)))) { zend_throw_error(NULL, "Undefined class constant '%s'", ZSTR_VAL(name)); return FAILURE; - } else if ((attr & IS_CONSTANT_UNQUALIFIED) == 0) { + } else { zend_throw_error(NULL, "Undefined constant '%s'", ZSTR_VAL(name)); return FAILURE; - } else { - char *actual = ZSTR_VAL(name); - size_t actual_len = ZSTR_LEN(name); - char *slash = (char *) zend_memrchr(actual, '\\', actual_len); - - if (slash) { - actual = slash + 1; - actual_len -= (actual - ZSTR_VAL(name)); - } - - zend_error(E_WARNING, "Use of undefined constant %s - assumed '%s' (this will throw an Error in a future version of PHP)", actual, actual); - if (EG(exception)) { - return FAILURE; - } else { - zend_string *result_str = zend_string_init(actual, actual_len, 0); - zval_ptr_dtor_nogc(result); - ZVAL_NEW_STR(result, result_str); - } } - return SUCCESS; } /* }}} */ @@ -655,6 +634,8 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / zend_execute_data *call, dummy_execute_data; zend_fcall_info_cache fci_cache_local; zend_function *func; + uint32_t call_info; + void *object_or_called_scope; ZVAL_UNDEF(fci->retval); @@ -710,28 +691,24 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / EG(current_execute_data) = dummy_execute_data.prev_execute_data; } return FAILURE; - } else if (error) { - /* Capitalize the first latter of the error message */ - if (error[0] >= 'a' && error[0] <= 'z') { - error[0] += ('A' - 'a'); - } - zend_error(E_DEPRECATED, "%s", error); - efree(error); - if (UNEXPECTED(EG(exception))) { - if (EG(current_execute_data) == &dummy_execute_data) { - EG(current_execute_data) = dummy_execute_data.prev_execute_data; - } - return FAILURE; - } } + + ZEND_ASSERT(!error); } func = fci_cache->function_handler; - fci->object = (func->common.fn_flags & ZEND_ACC_STATIC) ? - NULL : fci_cache->object; + if ((func->common.fn_flags & ZEND_ACC_STATIC) || !fci_cache->object) { + fci->object = NULL; + object_or_called_scope = fci_cache->called_scope; + call_info = ZEND_CALL_TOP_FUNCTION | ZEND_CALL_DYNAMIC; + } else { + fci->object = fci_cache->object; + object_or_called_scope = fci->object; + call_info = ZEND_CALL_TOP_FUNCTION | ZEND_CALL_DYNAMIC | ZEND_CALL_HAS_THIS; + } - call = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_FUNCTION | ZEND_CALL_DYNAMIC, - func, fci->param_count, fci_cache->called_scope, fci->object); + call = zend_vm_stack_push_call_frame(call_info, + func, fci->param_count, object_or_called_scope); if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_DEPRECATED)) { zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated", @@ -809,8 +786,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / /* We must re-initialize function again */ fci_cache->function_handler = NULL; } - } else if (func->type == ZEND_INTERNAL_FUNCTION) { + } else { int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0; + + ZEND_ASSERT(func->type == ZEND_INTERNAL_FUNCTION); ZVAL_NULL(fci->retval); call->prev_execute_data = EG(current_execute_data); call->return_value = NULL; /* this is not a constructor call */ @@ -833,30 +812,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / /* We must re-initialize function again */ fci_cache->function_handler = NULL; } - } else { /* ZEND_OVERLOADED_FUNCTION */ - ZVAL_NULL(fci->retval); - - /* Not sure what should be done here if it's a static method */ - if (fci->object) { - call->prev_execute_data = EG(current_execute_data); - EG(current_execute_data) = call; - fci->object->handlers->call_method(func->common.function_name, fci->object, call, fci->retval); - EG(current_execute_data) = call->prev_execute_data; - } else { - zend_throw_error(NULL, "Cannot call overloaded function for non-object"); - } - - zend_vm_stack_free_args(call); - - if (func->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { - zend_string_release_ex(func->common.function_name, 0); - } - efree(func); - - if (EG(exception)) { - zval_ptr_dtor(fci->retval); - ZVAL_UNDEF(fci->retval); - } } zend_vm_stack_free_call_frame(call); @@ -921,16 +876,10 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string * } if (!EG(autoload_func)) { - zend_function *func = zend_fetch_function(ZSTR_KNOWN(ZEND_STR_MAGIC_AUTOLOAD)); - - if (func) { - EG(autoload_func) = func; - } else { - if (!key) { - zend_string_release_ex(lc_name, 0); - } - return NULL; + if (!key) { + zend_string_release_ex(lc_name, 0); } + return NULL; } diff --git a/Zend/zend_extensions.h b/Zend/zend_extensions.h index a5c9a6f8bc..87c7748c36 100644 --- a/Zend/zend_extensions.h +++ b/Zend/zend_extensions.h @@ -44,7 +44,7 @@ You can use the following macro to check the extension API version for compatibi /* The first number is the engine version and the rest is the date (YYYYMMDD). * This way engine 2/3 API no. is always greater than engine 1 API no.. */ -#define ZEND_EXTENSION_API_NO 320180731 +#define ZEND_EXTENSION_API_NO 420190128 typedef struct _zend_extension_version_info { int zend_extension_api_no; diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c index 7ed3078ed1..af1052d450 100644 --- a/Zend/zend_gc.c +++ b/Zend/zend_gc.c @@ -689,10 +689,8 @@ tail_call: if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED))) { int n; zval *zv, *end; - zval tmp; - ZVAL_OBJ(&tmp, obj); - ht = obj->handlers->get_gc(&tmp, &zv, &n); + ht = obj->handlers->get_gc(obj, &zv, &n); end = zv + n; if (EXPECTED(!ht)) { if (!n) goto next; @@ -806,10 +804,8 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack) if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED))) { int n; zval *zv, *end; - zval tmp; - ZVAL_OBJ(&tmp, obj); - ht = obj->handlers->get_gc(&tmp, &zv, &n); + ht = obj->handlers->get_gc(obj, &zv, &n); end = zv + n; if (EXPECTED(!ht)) { if (!n) goto next; @@ -989,10 +985,8 @@ tail_call: if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED))) { int n; zval *zv, *end; - zval tmp; - ZVAL_OBJ(&tmp, obj); - ht = obj->handlers->get_gc(&tmp, &zv, &n); + ht = obj->handlers->get_gc(obj, &zv, &n); end = zv + n; if (EXPECTED(!ht)) { if (!n) goto next; @@ -1149,7 +1143,6 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED))) { int n; zval *zv, *end; - zval tmp; /* optimization: color is GC_BLACK (0) */ if (!GC_INFO(ref)) { @@ -1159,8 +1152,7 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta obj->ce->destructor != NULL) { *flags |= GC_HAS_DESTRUCTORS; } - ZVAL_OBJ(&tmp, obj); - ht = obj->handlers->get_gc(&tmp, &zv, &n); + ht = obj->handlers->get_gc(obj, &zv, &n); end = zv + n; if (EXPECTED(!ht)) { if (!n) goto next; @@ -1337,10 +1329,8 @@ tail_call: if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED))) { int n; zval *zv, *end; - zval tmp; - ZVAL_OBJ(&tmp, obj); - ht = obj->handlers->get_gc(&tmp, &zv, &n); + ht = obj->handlers->get_gc(obj, &zv, &n); end = zv + n; if (EXPECTED(!ht)) { if (!n) return; diff --git a/Zend/zend_gdb.c b/Zend/zend_gdb.c new file mode 100644 index 0000000000..199589f5b8 --- /dev/null +++ b/Zend/zend_gdb.c @@ -0,0 +1,140 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Dmitry Stogov <dmitry@zend.com> | + | Xinchen Hui <xinchen.h@zend.com> | + +----------------------------------------------------------------------+ +*/ + +#include "zend.h" +#include "zend_gdb.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +enum { + ZEND_GDBJIT_NOACTION, + ZEND_GDBJIT_REGISTER, + ZEND_GDBJIT_UNREGISTER +}; + +typedef struct _zend_gdbjit_code_entry { + struct _zend_gdbjit_code_entry *next_entry; + struct _zend_gdbjit_code_entry *prev_entry; + const char *symfile_addr; + uint64_t symfile_size; +} zend_gdbjit_code_entry; + +typedef struct _zend_gdbjit_descriptor { + uint32_t version; + uint32_t action_flag; + struct _zend_gdbjit_code_entry *relevant_entry; + struct _zend_gdbjit_code_entry *first_entry; +} zend_gdbjit_descriptor; + +ZEND_API zend_gdbjit_descriptor __jit_debug_descriptor = { + 1, ZEND_GDBJIT_NOACTION, NULL, NULL +}; + +ZEND_API zend_never_inline void __jit_debug_register_code() +{ + __asm__ __volatile__(""); +} + +ZEND_API int zend_gdb_register_code(const void *object, size_t size) +{ + zend_gdbjit_code_entry *entry; + + entry = malloc(sizeof(zend_gdbjit_code_entry) + size); + if (entry == NULL) { + return 0; + } + + entry->symfile_addr = ((char*)entry) + sizeof(zend_gdbjit_code_entry); + entry->symfile_size = size; + + memcpy((char *)entry->symfile_addr, object, size); + + entry->prev_entry = NULL; + entry->next_entry = __jit_debug_descriptor.first_entry; + + if (entry->next_entry) { + entry->next_entry->prev_entry = entry; + } + __jit_debug_descriptor.first_entry = entry; + + /* Notify GDB */ + __jit_debug_descriptor.relevant_entry = entry; + __jit_debug_descriptor.action_flag = ZEND_GDBJIT_REGISTER; + __jit_debug_register_code(); + + return 1; +} + +ZEND_API void zend_gdb_unregister_all(void) +{ + zend_gdbjit_code_entry *entry; + + __jit_debug_descriptor.action_flag = ZEND_GDBJIT_UNREGISTER; + while ((entry = __jit_debug_descriptor.first_entry)) { + __jit_debug_descriptor.first_entry = entry->next_entry; + if (entry->next_entry) { + entry->next_entry->prev_entry = NULL; + } + /* Notify GDB */ + __jit_debug_descriptor.relevant_entry = entry; + __jit_debug_register_code(); + + free(entry); + } +} + +ZEND_API int zend_gdb_present(void) +{ + int ret = 0; + int fd = open("/proc/self/status", O_RDONLY); + + if (fd > 0) { + char buf[1024]; + ssize_t n = read(fd, buf, sizeof(buf) - 1); + char *s; + pid_t pid; + + if (n > 0) { + buf[n] = 0; + s = strstr(buf, "TracerPid:"); + if (s) { + s += sizeof("TracerPid:") - 1; + while (*s == ' ' || *s == '\t') { + s++; + } + pid = atoi(s); + if (pid) { + sprintf(buf, "/proc/%d/exe", (int)pid); + if (readlink(buf, buf, sizeof(buf) - 1) > 0) { + if (strstr(buf, "gdb")) { + ret = 1; + } + } + } + } + } + + close(fd); + } + + return ret; +} diff --git a/Zend/zend_gdb.h b/Zend/zend_gdb.h new file mode 100644 index 0000000000..220b70888f --- /dev/null +++ b/Zend/zend_gdb.h @@ -0,0 +1,27 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Dmitry Stogov <dmitry@zend.com> | + | Xinchen Hui <laruence@php.net> | + +----------------------------------------------------------------------+ +*/ + +#ifndef ZEND_GDB +#define ZEND_GDB + +ZEND_API int zend_gdb_register_code(const void *object, size_t size); +ZEND_API void zend_gdb_unregister_all(void); +ZEND_API int zend_gdb_present(void); + +#endif diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index a59d84cda7..841489eca7 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -40,10 +40,7 @@ ZEND_API void zend_generator_restore_call_stack(zend_generator *generator) /* {{ (ZEND_CALL_INFO(call) & ~ZEND_CALL_ALLOCATED), call->func, ZEND_CALL_NUM_ARGS(call), - (Z_TYPE(call->This) == IS_UNDEF) ? - (zend_class_entry*)Z_OBJ(call->This) : NULL, - (Z_TYPE(call->This) != IS_UNDEF) ? - Z_OBJ(call->This) : NULL); + Z_PTR(call->This)); memcpy(((zval*)new_call) + ZEND_CALL_FRAME_SLOT, ((zval*)call) + ZEND_CALL_FRAME_SLOT, ZEND_CALL_NUM_ARGS(call) * sizeof(zval)); new_call->prev_execute_data = prev_call; prev_call = new_call; @@ -306,9 +303,9 @@ static uint32_t calc_gc_buffer_size(zend_generator *generator) /* {{{ */ } /* }}} */ -static HashTable *zend_generator_get_gc(zval *object, zval **table, int *n) /* {{{ */ +static HashTable *zend_generator_get_gc(zend_object *object, zval **table, int *n) /* {{{ */ { - zend_generator *generator = (zend_generator*) Z_OBJ_P(object); + zend_generator *generator = (zend_generator*)object; zend_execute_data *execute_data = generator->execute_data; zend_op_array *op_array; zval *gc_buffer; diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index c95faef22b..6644e735ca 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -227,8 +227,6 @@ struct _zend_executor_globals { zend_function trampoline; zend_op call_trampoline_op; - zend_bool each_deprecation_thrown; - HashTable weakrefs; void *reserved[ZEND_MAX_RESERVED_RESOURCES]; diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 36d8ecf15d..c6ad84ae2d 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -220,7 +220,7 @@ static zend_always_inline void _zend_hash_init_int(HashTable *ht, uint32_t nSize ht->nNumUsed = 0; ht->nNumOfElements = 0; ht->nInternalPointer = 0; - ht->nNextFreeElement = 0; + ht->nNextFreeElement = ZEND_LONG_MIN; ht->pDestructor = pDestructor; ht->nTableSize = zend_hash_check_size(nSize); } @@ -935,6 +935,10 @@ static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht, IS_CONSISTENT(ht); HT_ASSERT_RC1(ht); + if (h == ZEND_LONG_MIN && (flag & HASH_ADD_NEXT)) { + h = 0; + } + if (HT_FLAGS(ht) & HASH_FLAG_PACKED) { if (h < ht->nNumUsed) { p = ht->arData + h; @@ -998,8 +1002,8 @@ convert_to_hash: p = ht->arData + idx; Z_NEXT(p->val) = HT_HASH(ht, nIndex); HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx); - if ((zend_long)h >= (zend_long)ht->nNextFreeElement) { - ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX; + if ((zend_long)h >= ht->nNextFreeElement) { + ht->nNextFreeElement = (zend_long)h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX; } add: ht->nNumOfElements++; @@ -1665,7 +1669,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_clean(HashTable *ht) } ht->nNumUsed = 0; ht->nNumOfElements = 0; - ht->nNextFreeElement = 0; + ht->nNextFreeElement = ZEND_LONG_MIN; ht->nInternalPointer = 0; } @@ -1704,7 +1708,7 @@ ZEND_API void ZEND_FASTCALL zend_symtable_clean(HashTable *ht) } ht->nNumUsed = 0; ht->nNumOfElements = 0; - ht->nNextFreeElement = 0; + ht->nNextFreeElement = ZEND_LONG_MIN; ht->nInternalPointer = 0; } @@ -2018,7 +2022,7 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source) target->nTableMask = HT_MIN_MASK; target->nNumUsed = 0; target->nNumOfElements = 0; - target->nNextFreeElement = 0; + target->nNextFreeElement = ZEND_LONG_MIN; target->nInternalPointer = 0; target->nTableSize = HT_MIN_SIZE; HT_SET_DATA_ADDR(target, &uninitialized_bucket); @@ -2455,7 +2459,7 @@ ZEND_API void zend_hash_bucket_packed_swap(Bucket *p, Bucket *q) q->h = h; } -ZEND_API int ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, compare_func_t compar, zend_bool renumber) +ZEND_API void ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, compare_func_t compar, zend_bool renumber) { Bucket *p; uint32_t i, j; @@ -2464,7 +2468,7 @@ ZEND_API int ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, co HT_ASSERT_RC1(ht); if (!(ht->nNumOfElements>1) && !(renumber && ht->nNumOfElements>0)) { /* Doesn't require sorting */ - return SUCCESS; + return; } if (HT_IS_WITHOUT_HOLES(ht)) { @@ -2519,8 +2523,6 @@ ZEND_API int ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, co zend_hash_rehash(ht); } } - - return SUCCESS; } static zend_always_inline int zend_hash_compare_impl(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered) { diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 0cc34ddd47..af1340b785 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -262,7 +262,7 @@ ZEND_API void zend_hash_bucket_swap(Bucket *p, Bucket *q); ZEND_API void zend_hash_bucket_renum_swap(Bucket *p, Bucket *q); ZEND_API void zend_hash_bucket_packed_swap(Bucket *p, Bucket *q); ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered); -ZEND_API int ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort_func, compare_func_t compare_func, zend_bool renumber); +ZEND_API void ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort_func, compare_func_t compare_func, zend_bool renumber); ZEND_API zval* ZEND_FASTCALL zend_hash_minmax(const HashTable *ht, compare_func_t compar, uint32_t flag); #define zend_hash_sort(ht, compare_func, renumber) \ diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 0916d91f77..a4e437f271 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1316,14 +1316,11 @@ static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zen ce->serialize_func = fe; } else if (zend_string_equals_literal(mname, "unserialize")) { ce->unserialize_func = fe; - } else if (ZSTR_LEN(ce->name) != ZSTR_LEN(mname) && (ZSTR_VAL(mname)[0] != '_' || ZSTR_VAL(mname)[1] != '_')) { + } else if (ZSTR_VAL(mname)[0] != '_' || ZSTR_VAL(mname)[1] != '_') { /* pass */ } else if (zend_string_equals_literal(mname, ZEND_CLONE_FUNC_NAME)) { ce->clone = fe; } else if (zend_string_equals_literal(mname, ZEND_CONSTRUCTOR_FUNC_NAME)) { - if (ce->constructor && (!ce->parent || ce->constructor != ce->parent->constructor)) { - zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ZSTR_VAL(ce->name)); - } ce->constructor = fe; } else if (zend_string_equals_literal(mname, ZEND_DESTRUCTOR_FUNC_NAME)) { ce->destructor = fe; @@ -1347,17 +1344,6 @@ static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zen ce->__tostring = fe; } else if (zend_string_equals_literal(mname, ZEND_DEBUGINFO_FUNC_NAME)) { ce->__debugInfo = fe; - } else if (ZSTR_LEN(ce->name) == ZSTR_LEN(mname)) { - zend_string *lowercase_name = zend_string_tolower(ce->name); - lowercase_name = zend_new_interned_string(lowercase_name); - if (!memcmp(ZSTR_VAL(mname), ZSTR_VAL(lowercase_name), ZSTR_LEN(mname))) { - if (ce->constructor && (!ce->parent || ce->constructor != ce->parent->constructor)) { - zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ZSTR_VAL(ce->name)); - } - ce->constructor = fe; - fe->common.fn_flags |= ZEND_ACC_CTOR; - } - zend_string_release_ex(lowercase_name, 0); } } /* }}} */ @@ -1967,32 +1953,6 @@ static void zend_do_bind_traits(zend_class_entry *ce) /* {{{ */ zend_do_traits_property_binding(ce, traits); efree(traits); - - /* Emit E_DEPRECATED for PHP 4 constructors */ - zend_check_deprecated_constructor(ce); -} -/* }}} */ - - -static zend_bool zend_has_deprecated_constructor(const zend_class_entry *ce) /* {{{ */ -{ - const zend_string *constructor_name; - if (!ce->constructor) { - return 0; - } - constructor_name = ce->constructor->common.function_name; - return !zend_binary_strcasecmp( - ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), - ZSTR_VAL(constructor_name), ZSTR_LEN(constructor_name) - ); -} -/* }}} */ - -void zend_check_deprecated_constructor(const zend_class_entry *ce) /* {{{ */ -{ - if (zend_has_deprecated_constructor(ce)) { - zend_error(E_DEPRECATED, "Methods with the same name as their class will not be constructors in a future version of PHP; %s has a deprecated constructor", ZSTR_VAL(ce->name)); - } } /* }}} */ diff --git a/Zend/zend_inheritance.h b/Zend/zend_inheritance.h index 9f3668191a..eb68a6d278 100644 --- a/Zend/zend_inheritance.h +++ b/Zend/zend_inheritance.h @@ -30,7 +30,6 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_class_entry *parent_ce); void zend_verify_abstract_class(zend_class_entry *ce); -void zend_check_deprecated_constructor(const zend_class_entry *ce); void zend_build_properties_info_table(zend_class_entry *ce); END_EXTERN_C() diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index fe4c9ed9a3..4c9bb28310 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -30,7 +30,7 @@ ZEND_API zend_class_entry *zend_ce_countable; /* {{{ zend_call_method Only returns the returned zval if retval_ptr != NULL */ -ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, size_t function_name_len, zval *retval_ptr, int param_count, zval* arg1, zval* arg2) +ZEND_API zval* zend_call_method(zend_object *object, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, size_t function_name_len, zval *retval_ptr, int param_count, zval* arg1, zval* arg2) { int result; zend_fcall_info fci; @@ -45,7 +45,7 @@ ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_fun } fci.size = sizeof(fci); - fci.object = object ? Z_OBJ_P(object) : NULL; + fci.object = object; fci.retval = retval_ptr ? retval_ptr : &retval; fci.param_count = param_count; fci.params = params; @@ -62,7 +62,7 @@ ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_fun ZVAL_UNDEF(&fci.function_name); /* Unused */ if (!obj_ce) { - obj_ce = object ? Z_OBJCE_P(object) : NULL; + obj_ce = object ? object->ce : NULL; } if (!fn_proxy || !*fn_proxy) { if (EXPECTED(obj_ce)) { @@ -87,7 +87,7 @@ ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_fun } if (object) { - fcic.called_scope = Z_OBJCE_P(object); + fcic.called_scope = object->ce; } else { zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data)); @@ -99,13 +99,13 @@ ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_fun fcic.called_scope = called_scope; } } - fcic.object = object ? Z_OBJ_P(object) : NULL; + fcic.object = object; result = zend_call_function(&fci, &fcic); } if (result == FAILURE) { /* error at c-level */ if (!obj_ce) { - obj_ce = object ? Z_OBJCE_P(object) : NULL; + obj_ce = object ? object->ce : NULL; } if (!EG(exception)) { zend_error_noreturn(E_CORE_ERROR, "Couldn't execute method %s%s%s", obj_ce ? ZSTR_VAL(obj_ce->name) : "", obj_ce ? "::" : "", function_name); @@ -124,7 +124,7 @@ ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_fun /* {{{ zend_user_it_new_iterator */ ZEND_API void zend_user_it_new_iterator(zend_class_entry *ce, zval *object, zval *retval) { - zend_call_method_with_0_params(object, ce, &ce->iterator_funcs_ptr->zf_new_iterator, "getiterator", retval); + zend_call_method_with_0_params(Z_OBJ_P(object), ce, &ce->iterator_funcs_ptr->zf_new_iterator, "getiterator", retval); } /* }}} */ @@ -160,7 +160,7 @@ ZEND_API int zend_user_it_valid(zend_object_iterator *_iter) zval more; int result; - zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_valid, "valid", &more); + zend_call_method_with_0_params(Z_OBJ_P(object), iter->ce, &iter->ce->iterator_funcs_ptr->zf_valid, "valid", &more); result = i_zend_is_true(&more); zval_ptr_dtor(&more); return result ? SUCCESS : FAILURE; @@ -176,7 +176,7 @@ ZEND_API zval *zend_user_it_get_current_data(zend_object_iterator *_iter) zval *object = &iter->it.data; if (Z_ISUNDEF(iter->value)) { - zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_current, "current", &iter->value); + zend_call_method_with_0_params(Z_OBJ_P(object), iter->ce, &iter->ce->iterator_funcs_ptr->zf_current, "current", &iter->value); } return &iter->value; } @@ -189,7 +189,7 @@ ZEND_API void zend_user_it_get_current_key(zend_object_iterator *_iter, zval *ke zval *object = &iter->it.data; zval retval; - zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_key, "key", &retval); + zend_call_method_with_0_params(Z_OBJ_P(object), iter->ce, &iter->ce->iterator_funcs_ptr->zf_key, "key", &retval); if (Z_TYPE(retval) != IS_UNDEF) { ZVAL_ZVAL(key, &retval, 1, 1); @@ -210,7 +210,7 @@ ZEND_API void zend_user_it_move_forward(zend_object_iterator *_iter) zval *object = &iter->it.data; zend_user_it_invalidate_current(_iter); - zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_next, "next", NULL); + zend_call_method_with_0_params(Z_OBJ_P(object), iter->ce, &iter->ce->iterator_funcs_ptr->zf_next, "next", NULL); } /* }}} */ @@ -221,7 +221,7 @@ ZEND_API void zend_user_it_rewind(zend_object_iterator *_iter) zval *object = &iter->it.data; zend_user_it_invalidate_current(_iter); - zend_call_method_with_0_params(object, iter->ce, &iter->ce->iterator_funcs_ptr->zf_rewind, "rewind", NULL); + zend_call_method_with_0_params(Z_OBJ_P(object), iter->ce, &iter->ce->iterator_funcs_ptr->zf_rewind, "rewind", NULL); } /* }}} */ @@ -437,7 +437,7 @@ ZEND_API int zend_user_serialize(zval *object, unsigned char **buffer, size_t *b zval retval; int result; - zend_call_method_with_0_params(object, ce, &ce->serialize_func, "serialize", &retval); + zend_call_method_with_0_params(Z_OBJ_P(object), ce, &ce->serialize_func, "serialize", &retval); if (Z_TYPE(retval) == IS_UNDEF || EG(exception)) { @@ -478,7 +478,7 @@ ZEND_API int zend_user_unserialize(zval *object, zend_class_entry *ce, const uns ZVAL_STRINGL(&zdata, (char*)buf, buf_len); - zend_call_method_with_1_params(object, ce, &ce->unserialize_func, "unserialize", NULL, &zdata); + zend_call_method_with_1_params(Z_OBJ_P(object), ce, &ce->unserialize_func, "unserialize", NULL, &zdata); zval_ptr_dtor(&zdata); diff --git a/Zend/zend_interfaces.h b/Zend/zend_interfaces.h index 44770a1813..e7d0315ac5 100644 --- a/Zend/zend_interfaces.h +++ b/Zend/zend_interfaces.h @@ -37,7 +37,7 @@ typedef struct _zend_user_iterator { zval value; } zend_user_iterator; -ZEND_API zval* zend_call_method(zval *object_pp, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, size_t function_name_len, zval *retval, int param_count, zval* arg1, zval* arg2); +ZEND_API zval* zend_call_method(zend_object *object, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, size_t function_name_len, zval *retval, int param_count, zval* arg1, zval* arg2); #define zend_call_method_with_0_params(obj, obj_ce, fn_proxy, function_name, retval) \ zend_call_method(obj, obj_ce, fn_proxy, function_name, sizeof(function_name)-1, retval, 0, NULL, NULL) diff --git a/Zend/zend_iterators.c b/Zend/zend_iterators.c index 379a316c38..7e920c00d8 100644 --- a/Zend/zend_iterators.c +++ b/Zend/zend_iterators.c @@ -24,7 +24,7 @@ static zend_class_entry zend_iterator_class_entry; static void iter_wrapper_free(zend_object *object); static void iter_wrapper_dtor(zend_object *object); -static HashTable *iter_wrapper_get_gc(zval *object, zval **table, int *n); +static HashTable *iter_wrapper_get_gc(zend_object *object, zval **table, int *n); static const zend_object_handlers iterator_object_handlers = { 0, @@ -44,7 +44,6 @@ static const zend_object_handlers iterator_object_handlers = { NULL, /* unset dim */ NULL, /* props get */ NULL, /* method get */ - NULL, /* call */ NULL, /* get ctor */ NULL, /* get class name */ NULL, /* compare */ @@ -72,7 +71,7 @@ static void iter_wrapper_dtor(zend_object *object) { } -static HashTable *iter_wrapper_get_gc(zval *object, zval **table, int *n) { +static HashTable *iter_wrapper_get_gc(zend_object *object, zval **table, int *n) { /* TODO: We need a get_gc iterator handler */ *table = NULL; *n = 0; diff --git a/Zend/zend_list.c b/Zend/zend_list.c index 293eeadd04..b37c98185a 100644 --- a/Zend/zend_list.c +++ b/Zend/zend_list.c @@ -209,6 +209,7 @@ void plist_entry_destructor(zval *zv) int zend_init_rsrc_list(void) { zend_hash_init(&EG(regular_list), 8, NULL, list_entry_destructor, 0); + EG(regular_list).nNextFreeElement = 0; return SUCCESS; } diff --git a/Zend/zend_modules.h b/Zend/zend_modules.h index 2558b475cd..047d9d77ce 100644 --- a/Zend/zend_modules.h +++ b/Zend/zend_modules.h @@ -31,7 +31,7 @@ #define ZEND_MODULE_INFO_FUNC_ARGS zend_module_entry *zend_module #define ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU zend_module -#define ZEND_MODULE_API_NO 20180731 +#define ZEND_MODULE_API_NO 20190128 #ifdef ZTS #define USING_ZTS 1 #else diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 8a75c51de6..a526c38044 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -104,10 +104,8 @@ ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */ } /* }}} */ -ZEND_API HashTable *zend_std_get_properties(zval *object) /* {{{ */ +ZEND_API HashTable *zend_std_get_properties(zend_object *zobj) /* {{{ */ { - zend_object *zobj; - zobj = Z_OBJ_P(object); if (!zobj->properties) { rebuild_object_properties(zobj); } @@ -115,15 +113,13 @@ ZEND_API HashTable *zend_std_get_properties(zval *object) /* {{{ */ } /* }}} */ -ZEND_API HashTable *zend_std_get_gc(zval *object, zval **table, int *n) /* {{{ */ +ZEND_API HashTable *zend_std_get_gc(zend_object *zobj, zval **table, int *n) /* {{{ */ { - if (Z_OBJ_HANDLER_P(object, get_properties) != zend_std_get_properties) { + if (zobj->handlers->get_properties != zend_std_get_properties) { *table = NULL; *n = 0; - return Z_OBJ_HANDLER_P(object, get_properties)(object); + return zobj->handlers->get_properties(zobj); } else { - zend_object *zobj = Z_OBJ_P(object); - if (zobj->properties) { *table = NULL; *n = 0; @@ -137,15 +133,15 @@ ZEND_API HashTable *zend_std_get_gc(zval *object, zval **table, int *n) /* {{{ * } /* }}} */ -ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp) /* {{{ */ +ZEND_API HashTable *zend_std_get_debug_info(zend_object *object, int *is_temp) /* {{{ */ { - zend_class_entry *ce = Z_OBJCE_P(object); + zend_class_entry *ce = object->ce; zval retval; HashTable *ht; if (!ce->__debugInfo) { *is_temp = 0; - return Z_OBJ_HANDLER_P(object, get_properties)(object); + return object->handlers->get_properties(object); } zend_call_method_with_0_params(object, ce, &ce->__debugInfo, ZEND_DEBUGINFO_FUNC_NAME, &retval); @@ -647,20 +643,16 @@ ZEND_API uint32_t *zend_get_property_guard(zend_object *zobj, zend_string *membe } /* }}} */ -ZEND_API zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv) /* {{{ */ +ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int type, void **cache_slot, zval *rv) /* {{{ */ { - zend_object *zobj; - zend_string *name, *tmp_name; zval *retval; uintptr_t property_offset; zend_property_info *prop_info = NULL; uint32_t *guard = NULL; - - zobj = Z_OBJ_P(object); - name = zval_get_tmp_string(member, &tmp_name); + zend_string *tmp_name = NULL; #if DEBUG_OBJECT_HANDLERS - fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), ZSTR_VAL(name)); + fprintf(stderr, "Read object #%d property: %s\n", zobj->handle, ZSTR_VAL(name)); #endif /* make zend_get_property_info silent if we have getter - we may want to use it */ @@ -792,18 +784,13 @@ exit: } /* }}} */ -ZEND_API zval *zend_std_write_property(zval *object, zval *member, zval *value, void **cache_slot) /* {{{ */ +ZEND_API zval *zend_std_write_property(zend_object *zobj, zend_string *name, zval *value, void **cache_slot) /* {{{ */ { - zend_object *zobj; - zend_string *name, *tmp_name; zval *variable_ptr, tmp; uintptr_t property_offset; zend_property_info *prop_info = NULL; ZEND_ASSERT(!Z_ISREF_P(value)); - zobj = Z_OBJ_P(object); - name = zval_get_tmp_string(member, &tmp_name); - property_offset = zend_get_property_offset(zobj->ce, name, (zobj->ce->__set != NULL), cache_slot, &prop_info); if (EXPECTED(IS_VALID_PROPERTY_OFFSET(property_offset))) { @@ -891,7 +878,6 @@ write_std_property: } exit: - zend_tmp_string_release(tmp_name); return variable_ptr; } /* }}} */ @@ -902,10 +888,10 @@ static ZEND_COLD zend_never_inline void zend_bad_array_access(zend_class_entry * } /* }}} */ -ZEND_API zval *zend_std_read_dimension(zval *object, zval *offset, int type, zval *rv) /* {{{ */ +ZEND_API zval *zend_std_read_dimension(zend_object *object, zval *offset, int type, zval *rv) /* {{{ */ { - zend_class_entry *ce = Z_OBJCE_P(object); - zval tmp_offset, tmp_object; + zend_class_entry *ce = object->ce; + zval tmp_offset; if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) { if (offset == NULL) { @@ -915,16 +901,16 @@ ZEND_API zval *zend_std_read_dimension(zval *object, zval *offset, int type, zva ZVAL_COPY_DEREF(&tmp_offset, offset); } - ZVAL_COPY(&tmp_object, object); + GC_ADDREF(object); if (type == BP_VAR_IS) { - zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetexists", rv, &tmp_offset); + zend_call_method_with_1_params(object, ce, NULL, "offsetexists", rv, &tmp_offset); if (UNEXPECTED(Z_ISUNDEF_P(rv))) { - zval_ptr_dtor(&tmp_object); + OBJ_RELEASE(object); zval_ptr_dtor(&tmp_offset); return NULL; } if (!i_zend_is_true(rv)) { - zval_ptr_dtor(&tmp_object); + OBJ_RELEASE(object); zval_ptr_dtor(&tmp_offset); zval_ptr_dtor(rv); return &EG(uninitialized_zval); @@ -932,9 +918,9 @@ ZEND_API zval *zend_std_read_dimension(zval *object, zval *offset, int type, zva zval_ptr_dtor(rv); } - zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetget", rv, &tmp_offset); + zend_call_method_with_1_params(object, ce, NULL, "offsetget", rv, &tmp_offset); - zval_ptr_dtor(&tmp_object); + OBJ_RELEASE(object); zval_ptr_dtor(&tmp_offset); if (UNEXPECTED(Z_TYPE_P(rv) == IS_UNDEF)) { @@ -951,10 +937,10 @@ ZEND_API zval *zend_std_read_dimension(zval *object, zval *offset, int type, zva } /* }}} */ -ZEND_API void zend_std_write_dimension(zval *object, zval *offset, zval *value) /* {{{ */ +ZEND_API void zend_std_write_dimension(zend_object *object, zval *offset, zval *value) /* {{{ */ { - zend_class_entry *ce = Z_OBJCE_P(object); - zval tmp_offset, tmp_object; + zend_class_entry *ce = object->ce; + zval tmp_offset; if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) { if (!offset) { @@ -962,9 +948,9 @@ ZEND_API void zend_std_write_dimension(zval *object, zval *offset, zval *value) } else { ZVAL_COPY_DEREF(&tmp_offset, offset); } - ZVAL_COPY(&tmp_object, object); - zend_call_method_with_2_params(&tmp_object, ce, NULL, "offsetset", NULL, &tmp_offset, value); - zval_ptr_dtor(&tmp_object); + GC_ADDREF(object); + zend_call_method_with_2_params(object, ce, NULL, "offsetset", NULL, &tmp_offset, value); + OBJ_RELEASE(object); zval_ptr_dtor(&tmp_offset); } else { zend_bad_array_access(ce); @@ -972,24 +958,24 @@ ZEND_API void zend_std_write_dimension(zval *object, zval *offset, zval *value) } /* }}} */ -ZEND_API int zend_std_has_dimension(zval *object, zval *offset, int check_empty) /* {{{ */ +ZEND_API int zend_std_has_dimension(zend_object *object, zval *offset, int check_empty) /* {{{ */ { - zend_class_entry *ce = Z_OBJCE_P(object); - zval retval, tmp_offset, tmp_object; + zend_class_entry *ce = object->ce; + zval retval, tmp_offset; int result; if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1) != 0)) { ZVAL_COPY_DEREF(&tmp_offset, offset); - ZVAL_COPY(&tmp_object, object); - zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetexists", &retval, &tmp_offset); + GC_ADDREF(object); + zend_call_method_with_1_params(object, ce, NULL, "offsetexists", &retval, &tmp_offset); result = i_zend_is_true(&retval); zval_ptr_dtor(&retval); if (check_empty && result && EXPECTED(!EG(exception))) { - zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetget", &retval, &tmp_offset); + zend_call_method_with_1_params(object, ce, NULL, "offsetget", &retval, &tmp_offset); result = i_zend_is_true(&retval); zval_ptr_dtor(&retval); } - zval_ptr_dtor(&tmp_object); + OBJ_RELEASE(object); zval_ptr_dtor(&tmp_offset); } else { zend_bad_array_access(ce); @@ -999,19 +985,14 @@ ZEND_API int zend_std_has_dimension(zval *object, zval *offset, int check_empty) } /* }}} */ -ZEND_API zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot) /* {{{ */ +ZEND_API zval *zend_std_get_property_ptr_ptr(zend_object *zobj, zend_string *name, int type, void **cache_slot) /* {{{ */ { - zend_object *zobj; - zend_string *name, *tmp_name; zval *retval = NULL; uintptr_t property_offset; zend_property_info *prop_info = NULL; - zobj = Z_OBJ_P(object); - name = zval_get_tmp_string(member, &tmp_name); - #if DEBUG_OBJECT_HANDLERS - fprintf(stderr, "Ptr object #%d property: %s\n", Z_OBJ_HANDLE_P(object), ZSTR_VAL(name)); + fprintf(stderr, "Ptr object #%d property: %s\n", object->handle, ZSTR_VAL(name)); #endif property_offset = zend_get_property_offset(zobj->ce, name, (zobj->ce->__get != NULL), cache_slot, &prop_info); @@ -1039,7 +1020,6 @@ ZEND_API zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int typ zobj->properties = zend_array_dup(zobj->properties); } if (EXPECTED((retval = zend_hash_find(zobj->properties, name)) != NULL)) { - zend_tmp_string_release(tmp_name); return retval; } } @@ -1057,21 +1037,15 @@ ZEND_API zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int typ } } - zend_tmp_string_release(tmp_name); return retval; } /* }}} */ -ZEND_API void zend_std_unset_property(zval *object, zval *member, void **cache_slot) /* {{{ */ +ZEND_API void zend_std_unset_property(zend_object *zobj, zend_string *name, void **cache_slot) /* {{{ */ { - zend_object *zobj; - zend_string *name, *tmp_name; uintptr_t property_offset; zend_property_info *prop_info = NULL; - zobj = Z_OBJ_P(object); - name = zval_get_tmp_string(member, &tmp_name); - property_offset = zend_get_property_offset(zobj->ce, name, (zobj->ce->__unset != NULL), cache_slot, &prop_info); if (EXPECTED(IS_VALID_PROPERTY_OFFSET(property_offset))) { @@ -1089,7 +1063,7 @@ ZEND_API void zend_std_unset_property(zval *object, zval *member, void **cache_s if (zobj->properties) { HT_FLAGS(zobj->properties) |= HASH_FLAG_HAS_EMPTY_IND; } - goto exit; + return; } } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(property_offset)) && EXPECTED(zobj->properties != NULL)) { @@ -1100,10 +1074,10 @@ ZEND_API void zend_std_unset_property(zval *object, zval *member, void **cache_s zobj->properties = zend_array_dup(zobj->properties); } if (EXPECTED(zend_hash_del(zobj->properties, name) != FAILURE)) { - goto exit; + return; } } else if (UNEXPECTED(EG(exception))) { - goto exit; + return; } /* magic unset */ @@ -1118,27 +1092,24 @@ ZEND_API void zend_std_unset_property(zval *object, zval *member, void **cache_s /* Trigger the correct error */ zend_wrong_offset(zobj->ce, name); ZEND_ASSERT(EG(exception)); - goto exit; + return; } else { /* Nothing to do: The property already does not exist. */ } } - -exit: - zend_tmp_string_release(tmp_name); } /* }}} */ -ZEND_API void zend_std_unset_dimension(zval *object, zval *offset) /* {{{ */ +ZEND_API void zend_std_unset_dimension(zend_object *object, zval *offset) /* {{{ */ { - zend_class_entry *ce = Z_OBJCE_P(object); - zval tmp_offset, tmp_object; + zend_class_entry *ce = object->ce; + zval tmp_offset; if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1)) { ZVAL_COPY_DEREF(&tmp_offset, offset); - ZVAL_COPY(&tmp_object, object); - zend_call_method_with_1_params(&tmp_object, ce, NULL, "offsetunset", NULL, &tmp_offset); - zval_ptr_dtor(&tmp_object); + GC_ADDREF(object); + zend_call_method_with_1_params(object, ce, NULL, "offsetunset", NULL, &tmp_offset); + OBJ_RELEASE(object); zval_ptr_dtor(&tmp_offset); } else { zend_bad_array_access(ce); @@ -1626,17 +1597,13 @@ ZEND_API int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */ } /* }}} */ -ZEND_API int zend_std_has_property(zval *object, zval *member, int has_set_exists, void **cache_slot) /* {{{ */ +ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has_set_exists, void **cache_slot) /* {{{ */ { - zend_object *zobj; int result; zval *value = NULL; - zend_string *name, *tmp_name; uintptr_t property_offset; zend_property_info *prop_info = NULL; - - zobj = Z_OBJ_P(object); - name = zval_get_tmp_string(member, &tmp_name); + zend_string *tmp_name = NULL; property_offset = zend_get_property_offset(zobj->ce, name, 1, cache_slot, &prop_info); @@ -1733,14 +1700,14 @@ ZEND_API zend_string *zend_std_get_class_name(const zend_object *zobj) /* {{{ */ } /* }}} */ -ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type) /* {{{ */ +ZEND_API int zend_std_cast_object_tostring(zend_object *readobj, zval *writeobj, int type) /* {{{ */ { zval retval; zend_class_entry *ce; switch (type) { case IS_STRING: - ce = Z_OBJCE_P(readobj); + ce = readobj->ce; if (ce->__tostring && (zend_call_method_with_0_params(readobj, ce, &ce->__tostring, "__tostring", &retval) || EG(exception))) { if (UNEXPECTED(EG(exception) != NULL)) { @@ -1773,17 +1740,17 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty ZVAL_TRUE(writeobj); return SUCCESS; case IS_LONG: - ce = Z_OBJCE_P(readobj); + ce = readobj->ce; zend_error(E_NOTICE, "Object of class %s could not be converted to int", ZSTR_VAL(ce->name)); ZVAL_LONG(writeobj, 1); return SUCCESS; case IS_DOUBLE: - ce = Z_OBJCE_P(readobj); + ce = readobj->ce; zend_error(E_NOTICE, "Object of class %s could not be converted to float", ZSTR_VAL(ce->name)); ZVAL_DOUBLE(writeobj, 1); return SUCCESS; case _IS_NUMBER: - ce = Z_OBJCE_P(readobj); + ce = readobj->ce; zend_error(E_NOTICE, "Object of class %s could not be converted to number", ZSTR_VAL(ce->name)); ZVAL_LONG(writeobj, 1); return SUCCESS; @@ -1795,10 +1762,10 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty } /* }}} */ -ZEND_API int zend_std_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr) /* {{{ */ +ZEND_API int zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr) /* {{{ */ { zval *func; - zend_class_entry *ce = Z_OBJCE_P(obj); + zend_class_entry *ce = obj->ce; if ((func = zend_hash_find_ex(&ce->function_table, ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE), 1)) == NULL) { return FAILURE; @@ -1812,20 +1779,20 @@ ZEND_API int zend_std_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_fun } } else { if (obj_ptr) { - *obj_ptr = Z_OBJ_P(obj); + *obj_ptr = obj; } } return SUCCESS; } /* }}} */ -ZEND_API HashTable *zend_std_get_properties_for(zval *obj, zend_prop_purpose purpose) { +ZEND_API HashTable *zend_std_get_properties_for(zend_object *obj, zend_prop_purpose purpose) { HashTable *ht; switch (purpose) { case ZEND_PROP_PURPOSE_DEBUG: - if (Z_OBJ_HT_P(obj)->get_debug_info) { + if (obj->handlers->get_debug_info) { int is_temp; - ht = Z_OBJ_HT_P(obj)->get_debug_info(obj, &is_temp); + ht = obj->handlers->get_debug_info(obj, &is_temp); if (ht && !is_temp && !(GC_FLAGS(ht) & GC_IMMUTABLE)) { GC_ADDREF(ht); } @@ -1837,7 +1804,7 @@ ZEND_API HashTable *zend_std_get_properties_for(zval *obj, zend_prop_purpose pur case ZEND_PROP_PURPOSE_VAR_EXPORT: case ZEND_PROP_PURPOSE_JSON: case _ZEND_PROP_PURPOSE_ARRAY_KEY_EXISTS: - ht = Z_OBJ_HT_P(obj)->get_properties(obj); + ht = obj->handlers->get_properties(obj); if (ht && !(GC_FLAGS(ht) & GC_IMMUTABLE)) { GC_ADDREF(ht); } @@ -1849,11 +1816,13 @@ ZEND_API HashTable *zend_std_get_properties_for(zval *obj, zend_prop_purpose pur } ZEND_API HashTable *zend_get_properties_for(zval *obj, zend_prop_purpose purpose) { - if (Z_OBJ_HT_P(obj)->get_properties_for) { - return Z_OBJ_HT_P(obj)->get_properties_for(obj, purpose); + zend_object *zobj = Z_OBJ_P(obj); + + if (zobj->handlers->get_properties_for) { + return zobj->handlers->get_properties_for(zobj, purpose); } - return zend_std_get_properties_for(obj, purpose); + return zend_std_get_properties_for(zobj, purpose); } ZEND_API const zend_object_handlers std_object_handlers = { @@ -1876,7 +1845,6 @@ ZEND_API const zend_object_handlers std_object_handlers = { zend_std_unset_dimension, /* unset_dimension */ zend_std_get_properties, /* get_properties */ zend_std_get_method, /* get_method */ - NULL, /* call_method */ zend_std_get_constructor, /* get_constructor */ zend_std_get_class_name, /* get_class_name */ zend_std_compare_objects, /* compare_objects */ diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index 770a67cbdd..e59d7c8fcf 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -41,10 +41,10 @@ struct _zend_property_info; symbol table, its reference count should be 0. */ /* Used to fetch property from the object, read-only */ -typedef zval *(*zend_object_read_property_t)(zval *object, zval *member, int type, void **cache_slot, zval *rv); +typedef zval *(*zend_object_read_property_t)(zend_object *object, zend_string *member, int type, void **cache_slot, zval *rv); /* Used to fetch dimension from the object, read-only */ -typedef zval *(*zend_object_read_dimension_t)(zval *object, zval *offset, int type, zval *rv); +typedef zval *(*zend_object_read_dimension_t)(zend_object *object, zval *offset, int type, zval *rv); /* The following rule applies to write_property() and write_dimension() implementations: @@ -54,23 +54,23 @@ typedef zval *(*zend_object_read_dimension_t)(zval *object, zval *offset, int ty You must return the final value of the assigned property. */ /* Used to set property of the object */ -typedef zval *(*zend_object_write_property_t)(zval *object, zval *member, zval *value, void **cache_slot); +typedef zval *(*zend_object_write_property_t)(zend_object *object, zend_string *member, zval *value, void **cache_slot); /* Used to set dimension of the object */ -typedef void (*zend_object_write_dimension_t)(zval *object, zval *offset, zval *value); +typedef void (*zend_object_write_dimension_t)(zend_object *object, zval *offset, zval *value); /* Used to create pointer to the property of the object, for future direct r/w access */ -typedef zval *(*zend_object_get_property_ptr_ptr_t)(zval *object, zval *member, int type, void **cache_slot); +typedef zval *(*zend_object_get_property_ptr_ptr_t)(zend_object *object, zend_string *member, int type, void **cache_slot); /* Used to set object value. Can be used to override assignments and scalar write ops (like ++, +=) on the object */ -typedef void (*zend_object_set_t)(zval *object, zval *value); +typedef void (*zend_object_set_t)(zend_object *object, zval *value); /* Used to get object value. Can be used when converting object value to * one of the basic types and when using scalar ops (like ++, +=) on the object */ -typedef zval* (*zend_object_get_t)(zval *object, zval *rv); +typedef zval* (*zend_object_get_t)(zend_object *object, zval *rv); /* Used to check if a property of the object exists */ /* param has_set_exists: @@ -78,21 +78,21 @@ typedef zval* (*zend_object_get_t)(zval *object, zval *rv); * 1 (set) whether property exists and is true * 2 (exists) whether property exists */ -typedef int (*zend_object_has_property_t)(zval *object, zval *member, int has_set_exists, void **cache_slot); +typedef int (*zend_object_has_property_t)(zend_object *object, zend_string *member, int has_set_exists, void **cache_slot); /* Used to check if a dimension of the object exists */ -typedef int (*zend_object_has_dimension_t)(zval *object, zval *member, int check_empty); +typedef int (*zend_object_has_dimension_t)(zend_object *object, zval *member, int check_empty); /* Used to remove a property of the object */ -typedef void (*zend_object_unset_property_t)(zval *object, zval *member, void **cache_slot); +typedef void (*zend_object_unset_property_t)(zend_object *object, zend_string *member, void **cache_slot); /* Used to remove a dimension of the object */ -typedef void (*zend_object_unset_dimension_t)(zval *object, zval *offset); +typedef void (*zend_object_unset_dimension_t)(zend_object *object, zval *offset); /* Used to get hash of the properties of the object, as hash of zval's */ -typedef HashTable *(*zend_object_get_properties_t)(zval *object); +typedef HashTable *(*zend_object_get_properties_t)(zend_object *object); -typedef HashTable *(*zend_object_get_debug_info_t)(zval *object, int *is_temp); +typedef HashTable *(*zend_object_get_debug_info_t)(zend_object *object, int *is_temp); typedef enum _zend_prop_purpose { /* Used for debugging. Supersedes get_debug_info handler. */ @@ -114,20 +114,19 @@ typedef enum _zend_prop_purpose { } zend_prop_purpose; /* The return value must be released using zend_release_properties(). */ -typedef zend_array *(*zend_object_get_properties_for_t)(zval *object, zend_prop_purpose purpose); +typedef zend_array *(*zend_object_get_properties_for_t)(zend_object *object, zend_prop_purpose purpose); /* Used to call methods */ /* args on stack! */ /* Andi - EX(fbc) (function being called) needs to be initialized already in the INIT fcall opcode so that the parameters can be parsed the right way. We need to add another callback for this. */ -typedef int (*zend_object_call_method_t)(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS); typedef zend_function *(*zend_object_get_method_t)(zend_object **object, zend_string *method, const zval *key); typedef zend_function *(*zend_object_get_constructor_t)(zend_object *object); /* Object maintenance/destruction */ typedef void (*zend_object_dtor_obj_t)(zend_object *object); typedef void (*zend_object_free_obj_t)(zend_object *object); -typedef zend_object* (*zend_object_clone_obj_t)(zval *object); +typedef zend_object* (*zend_object_clone_obj_t)(zend_object *object); /* Get class name for display in var_dump and other debugging functions. * Must be defined and must return a non-NULL value. */ @@ -139,15 +138,15 @@ typedef int (*zend_object_compare_zvals_t)(zval *result, zval *op1, zval *op2); /* Cast an object to some other type. * readobj and retval must point to distinct zvals. */ -typedef int (*zend_object_cast_t)(zval *readobj, zval *retval, int type); +typedef int (*zend_object_cast_t)(zend_object *readobj, zval *retval, int type); /* updates *count to hold the number of elements present and returns SUCCESS. * Returns FAILURE if the object does not have any sense of overloaded dimensions */ -typedef int (*zend_object_count_elements_t)(zval *object, zend_long *count); +typedef int (*zend_object_count_elements_t)(zend_object *object, zend_long *count); -typedef int (*zend_object_get_closure_t)(zval *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr); +typedef int (*zend_object_get_closure_t)(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr); -typedef HashTable *(*zend_object_get_gc_t)(zval *object, zval **table, int *n); +typedef HashTable *(*zend_object_get_gc_t)(zend_object *object, zval **table, int *n); typedef int (*zend_object_do_operation_t)(zend_uchar opcode, zval *result, zval *op1, zval *op2); @@ -171,7 +170,6 @@ struct _zend_object_handlers { zend_object_unset_dimension_t unset_dimension; /* required */ zend_object_get_properties_t get_properties; /* required */ zend_object_get_method_t get_method; /* required */ - zend_object_call_method_t call_method; /* optional */ zend_object_get_constructor_t get_constructor; /* required */ zend_object_get_class_name_t get_class_name; /* required */ zend_object_compare_t compare_objects; /* optional */ @@ -205,23 +203,23 @@ ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *p ZEND_API ZEND_COLD zend_bool zend_std_unset_static_property(zend_class_entry *ce, zend_string *property_name); ZEND_API zend_function *zend_std_get_constructor(zend_object *object); ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zend_string *member, int silent); -ZEND_API HashTable *zend_std_get_properties(zval *object); -ZEND_API HashTable *zend_std_get_gc(zval *object, zval **table, int *n); -ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp); -ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type); -ZEND_API zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot); -ZEND_API zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv); -ZEND_API zval *zend_std_write_property(zval *object, zval *member, zval *value, void **cache_slot); -ZEND_API int zend_std_has_property(zval *object, zval *member, int has_set_exists, void **cache_slot); -ZEND_API void zend_std_unset_property(zval *object, zval *member, void **cache_slot); -ZEND_API zval *zend_std_read_dimension(zval *object, zval *offset, int type, zval *rv); -ZEND_API void zend_std_write_dimension(zval *object, zval *offset, zval *value); -ZEND_API int zend_std_has_dimension(zval *object, zval *offset, int check_empty); -ZEND_API void zend_std_unset_dimension(zval *object, zval *offset); +ZEND_API HashTable *zend_std_get_properties(zend_object *object); +ZEND_API HashTable *zend_std_get_gc(zend_object *object, zval **table, int *n); +ZEND_API HashTable *zend_std_get_debug_info(zend_object *object, int *is_temp); +ZEND_API int zend_std_cast_object_tostring(zend_object *object, zval *writeobj, int type); +ZEND_API zval *zend_std_get_property_ptr_ptr(zend_object *object, zend_string *member, int type, void **cache_slot); +ZEND_API zval *zend_std_read_property(zend_object *object, zend_string *member, int type, void **cache_slot, zval *rv); +ZEND_API zval *zend_std_write_property(zend_object *object, zend_string *member, zval *value, void **cache_slot); +ZEND_API int zend_std_has_property(zend_object *object, zend_string *member, int has_set_exists, void **cache_slot); +ZEND_API void zend_std_unset_property(zend_object *object, zend_string *member, void **cache_slot); +ZEND_API zval *zend_std_read_dimension(zend_object *object, zval *offset, int type, zval *rv); +ZEND_API void zend_std_write_dimension(zend_object *object, zval *offset, zval *value); +ZEND_API int zend_std_has_dimension(zend_object *object, zval *offset, int check_empty); +ZEND_API void zend_std_unset_dimension(zend_object *object, zval *offset); ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *method_name, const zval *key); ZEND_API zend_string *zend_std_get_class_name(const zend_object *zobj); ZEND_API int zend_std_compare_objects(zval *o1, zval *o2); -ZEND_API int zend_std_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr); +ZEND_API int zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr); ZEND_API void rebuild_object_properties(zend_object *zobj); ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope); @@ -234,7 +232,7 @@ ZEND_API uint32_t *zend_get_property_guard(zend_object *zobj, zend_string *membe /* Default behavior for get_properties_for. For use as a fallback in custom * get_properties_for implementations. */ -ZEND_API HashTable *zend_std_get_properties_for(zval *obj, zend_prop_purpose purpose); +ZEND_API HashTable *zend_std_get_properties_for(zend_object *obj, zend_prop_purpose purpose); /* Will call get_properties_for handler or use default behavior. For use by * consumers of the get_properties_for API. */ diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index e3efb26ddc..fca24d209d 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -289,14 +289,12 @@ ZEND_API void ZEND_FASTCALL zend_objects_clone_members(zend_object *new_object, } } -ZEND_API zend_object *zend_objects_clone_obj(zval *zobject) +ZEND_API zend_object *zend_objects_clone_obj(zend_object *old_object) { - zend_object *old_object; zend_object *new_object; /* assume that create isn't overwritten, so when clone depends on the * overwritten one then it must itself be overwritten */ - old_object = Z_OBJ_P(zobject); new_object = zend_objects_new(old_object->ce); /* zend_objects_clone_members() expect the properties to be initialized. */ diff --git a/Zend/zend_objects.h b/Zend/zend_objects.h index cb0015599b..91d388154d 100644 --- a/Zend/zend_objects.h +++ b/Zend/zend_objects.h @@ -29,7 +29,7 @@ ZEND_API void ZEND_FASTCALL zend_objects_clone_members(zend_object *new_object, ZEND_API void zend_object_std_dtor(zend_object *object); ZEND_API void zend_objects_destroy_object(zend_object *object); -ZEND_API zend_object *zend_objects_clone_obj(zval *object); +ZEND_API zend_object *zend_objects_clone_obj(zend_object *object); END_EXTERN_C() #endif /* ZEND_OBJECTS_H */ diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 170599be74..361223a7c0 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -138,13 +138,13 @@ ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len) /* { #define convert_object_to_type(op, dst, ctype, conv_func) \ ZVAL_UNDEF(dst); \ if (Z_OBJ_HT_P(op)->cast_object) { \ - if (Z_OBJ_HT_P(op)->cast_object(op, dst, ctype) == FAILURE) { \ + if (Z_OBJ_HT_P(op)->cast_object(Z_OBJ_P(op), dst, ctype) == FAILURE) { \ zend_error(E_RECOVERABLE_ERROR, \ "Object of class %s could not be converted to %s", ZSTR_VAL(Z_OBJCE_P(op)->name),\ zend_get_type_by_const(ctype)); \ } \ } else if (Z_OBJ_HT_P(op)->get) { \ - zval *newop = Z_OBJ_HT_P(op)->get(op, dst); \ + zval *newop = Z_OBJ_HT_P(op)->get(Z_OBJ_P(op), dst); \ if (Z_TYPE_P(newop) != IS_OBJECT) { \ /* for safety - avoid loop */ \ ZVAL_COPY_VALUE(dst, newop); \ @@ -863,11 +863,11 @@ try_again: case IS_OBJECT: { zval tmp; if (Z_OBJ_HT_P(op)->cast_object) { - if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, IS_STRING) == SUCCESS) { + if (Z_OBJ_HT_P(op)->cast_object(Z_OBJ_P(op), &tmp, IS_STRING) == SUCCESS) { return Z_STR(tmp); } } else if (Z_OBJ_HT_P(op)->get) { - zval *z = Z_OBJ_HT_P(op)->get(op, &tmp); + zval *z = Z_OBJ_HT_P(op)->get(Z_OBJ_P(op), &tmp); if (Z_TYPE_P(z) != IS_OBJECT) { zend_string *str = zval_get_string(z); zval_ptr_dtor(z); @@ -2078,13 +2078,13 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2) if (Z_TYPE_P(op1) == IS_OBJECT) { if (Z_OBJ_HT_P(op1)->get) { zval rv; - op_free = Z_OBJ_HT_P(op1)->get(op1, &rv); + op_free = Z_OBJ_HT_P(op1)->get(Z_OBJ_P(op1), &rv); ret = compare_function(result, op_free, op2); zend_free_obj_get_result(op_free); return ret; } else if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) { ZVAL_UNDEF(&tmp_free); - if (Z_OBJ_HT_P(op1)->cast_object(op1, &tmp_free, ((Z_TYPE_P(op2) == IS_FALSE || Z_TYPE_P(op2) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(op2))) == FAILURE) { + if (Z_OBJ_HT_P(op1)->cast_object(Z_OBJ_P(op1), &tmp_free, ((Z_TYPE_P(op2) == IS_FALSE || Z_TYPE_P(op2) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(op2))) == FAILURE) { ZVAL_LONG(result, 1); zend_free_obj_get_result(&tmp_free); return SUCCESS; @@ -2097,13 +2097,13 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2) if (Z_TYPE_P(op2) == IS_OBJECT) { if (Z_OBJ_HT_P(op2)->get) { zval rv; - op_free = Z_OBJ_HT_P(op2)->get(op2, &rv); + op_free = Z_OBJ_HT_P(op2)->get(Z_OBJ_P(op2), &rv); ret = compare_function(result, op1, op_free); zend_free_obj_get_result(op_free); return ret; } else if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) { ZVAL_UNDEF(&tmp_free); - if (Z_OBJ_HT_P(op2)->cast_object(op2, &tmp_free, ((Z_TYPE_P(op1) == IS_FALSE || Z_TYPE_P(op1) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(op1))) == FAILURE) { + if (Z_OBJ_HT_P(op2)->cast_object(Z_OBJ_P(op2), &tmp_free, ((Z_TYPE_P(op1) == IS_FALSE || Z_TYPE_P(op1) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(op1))) == FAILURE) { ZVAL_LONG(result, -1); zend_free_obj_get_result(&tmp_free); return SUCCESS; @@ -2462,10 +2462,10 @@ try_again: zval rv; zval *val; - val = Z_OBJ_HANDLER_P(op1, get)(op1, &rv); + val = Z_OBJ_HANDLER_P(op1, get)(Z_OBJ_P(op1), &rv); Z_TRY_ADDREF_P(val); increment_function(val); - Z_OBJ_HANDLER_P(op1, set)(op1, val); + Z_OBJ_HANDLER_P(op1, set)(Z_OBJ_P(op1), val); zval_ptr_dtor(val); } else if (Z_OBJ_HANDLER_P(op1, do_operation)) { zval op2; @@ -2529,10 +2529,10 @@ try_again: zval rv; zval *val; - val = Z_OBJ_HANDLER_P(op1, get)(op1, &rv); + val = Z_OBJ_HANDLER_P(op1, get)(Z_OBJ_P(op1), &rv); Z_TRY_ADDREF_P(val); decrement_function(val); - Z_OBJ_HANDLER_P(op1, set)(op1, val); + Z_OBJ_HANDLER_P(op1, set)(Z_OBJ_P(op1), val); zval_ptr_dtor(val); } else if (Z_OBJ_HANDLER_P(op1, do_operation)) { zval op2; @@ -2563,16 +2563,18 @@ ZEND_API int ZEND_FASTCALL zend_is_true(zval *op) /* {{{ */ ZEND_API int ZEND_FASTCALL zend_object_is_true(zval *op) /* {{{ */ { - if (Z_OBJ_HT_P(op)->cast_object) { + zend_object *zobj = Z_OBJ_P(op); + + if (zobj->handlers->cast_object) { zval tmp; - if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, _IS_BOOL) == SUCCESS) { + if (zobj->handlers->cast_object(zobj, &tmp, _IS_BOOL) == SUCCESS) { return Z_TYPE(tmp) == IS_TRUE; } - zend_error(E_RECOVERABLE_ERROR, "Object of class %s could not be converted to bool", ZSTR_VAL(Z_OBJ_P(op)->ce->name)); - } else if (Z_OBJ_HT_P(op)->get) { + zend_error(E_RECOVERABLE_ERROR, "Object of class %s could not be converted to bool", ZSTR_VAL(zobj->ce->name)); + } else if (zobj->handlers->get) { int result; zval rv; - zval *tmp = Z_OBJ_HT_P(op)->get(op, &rv); + zval *tmp = zobj->handlers->get(zobj, &rv); if (Z_TYPE_P(tmp) != IS_OBJECT) { /* for safety - avoid loop */ diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index 6fe0bddc3d..9443977c8a 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -801,14 +801,14 @@ static zend_always_inline zend_bool fast_is_not_identical_function(zval *op1, zv #define ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(opcode, binary_op) \ if (UNEXPECTED(Z_TYPE_P(op1) == IS_OBJECT) \ && op1 == result \ - && UNEXPECTED(Z_OBJ_HANDLER_P(op1, get)) \ - && EXPECTED(Z_OBJ_HANDLER_P(op1, set))) { \ + && UNEXPECTED(Z_OBJ_HANDLER_P(op1, get)) \ + && EXPECTED(Z_OBJ_HANDLER_P(op1, set))) { \ int ret; \ zval rv; \ - zval *objval = Z_OBJ_HANDLER_P(op1, get)(op1, &rv); \ - Z_TRY_ADDREF_P(objval); \ - ret = binary_op(objval, objval, op2); \ - Z_OBJ_HANDLER_P(op1, set)(op1, objval); \ + zval *objval = Z_OBJ_HANDLER_P(op1, get)(Z_OBJ_P(op1), &rv); \ + Z_TRY_ADDREF_P(objval); \ + ret = binary_op(objval, objval, op2); \ + Z_OBJ_HANDLER_P(op1, set)(Z_OBJ_P(op1), objval); \ zval_ptr_dtor(objval); \ return ret; \ } else if (UNEXPECTED(Z_TYPE_P(op1) == IS_OBJECT) \ diff --git a/Zend/zend_string.h b/Zend/zend_string.h index 4ede3f0381..21aca78ca4 100644 --- a/Zend/zend_string.h +++ b/Zend/zend_string.h @@ -416,7 +416,6 @@ EMPTY_SWITCH_DEFAULT_CASE() _(ZEND_STR_THIS, "this") \ _(ZEND_STR_VALUE, "value") \ _(ZEND_STR_KEY, "key") \ - _(ZEND_STR_MAGIC_AUTOLOAD, "__autoload") \ _(ZEND_STR_MAGIC_INVOKE, "__invoke") \ _(ZEND_STR_PREVIOUS, "previous") \ _(ZEND_STR_CODE, "code") \ diff --git a/Zend/zend_ts_hash.c b/Zend/zend_ts_hash.c index 3cff54bf6c..e475f532d4 100644 --- a/Zend/zend_ts_hash.c +++ b/Zend/zend_ts_hash.c @@ -264,15 +264,11 @@ ZEND_API void zend_ts_hash_merge_ex(TsHashTable *target, TsHashTable *source, co end_read(source); } -ZEND_API int zend_ts_hash_sort(TsHashTable *ht, sort_func_t sort_func, compare_func_t compare_func, int renumber) +ZEND_API void zend_ts_hash_sort(TsHashTable *ht, sort_func_t sort_func, compare_func_t compare_func, int renumber) { - int retval; - begin_write(ht); - retval = zend_hash_sort_ex(TS_HASH(ht), sort_func, compare_func, renumber); + zend_hash_sort_ex(TS_HASH(ht), sort_func, compare_func, renumber); end_write(ht); - - return retval; } ZEND_API int zend_ts_hash_compare(TsHashTable *ht1, TsHashTable *ht2, compare_func_t compar, zend_bool ordered) diff --git a/Zend/zend_ts_hash.h b/Zend/zend_ts_hash.h index 35a4250d34..195dba6bbd 100644 --- a/Zend/zend_ts_hash.h +++ b/Zend/zend_ts_hash.h @@ -73,7 +73,7 @@ ZEND_API void zend_ts_hash_copy(TsHashTable *target, TsHashTable *source, copy_c ZEND_API void zend_ts_hash_copy_to_hash(HashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor); ZEND_API void zend_ts_hash_merge(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, int overwrite); ZEND_API void zend_ts_hash_merge_ex(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, merge_checker_func_t pMergeSource, void *pParam); -ZEND_API int zend_ts_hash_sort(TsHashTable *ht, sort_func_t sort_func, compare_func_t compare_func, int renumber); +ZEND_API void zend_ts_hash_sort(TsHashTable *ht, sort_func_t sort_func, compare_func_t compare_func, int renumber); ZEND_API int zend_ts_hash_compare(TsHashTable *ht1, TsHashTable *ht2, compare_func_t compar, zend_bool ordered); ZEND_API zval *zend_ts_hash_minmax(TsHashTable *ht, compare_func_t compar, int flag); diff --git a/Zend/zend_types.h b/Zend/zend_types.h index a5ca56e0cf..6ba488d88b 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -15,7 +15,7 @@ | Authors: Andi Gutmans <andi@php.net> | | Zeev Suraski <zeev@php.net> | | Dmitry Stogov <dmitry@php.net> | - | Xinchen Hui <xinchen.h@zend.com> | + | Xinchen Hui <laruence@php.net> | +----------------------------------------------------------------------+ */ @@ -201,7 +201,6 @@ struct _zval_struct { zend_uchar type, /* active type */ zend_uchar type_flags, union { - uint16_t call_info; /* call info for EX(This) */ uint16_t extra; /* not further specified */ } u) } v; @@ -709,7 +708,7 @@ static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) { #define Z_OBJCE(zval) (Z_OBJ(zval)->ce) #define Z_OBJCE_P(zval_p) Z_OBJCE(*(zval_p)) -#define Z_OBJPROP(zval) Z_OBJ_HT((zval))->get_properties(&(zval)) +#define Z_OBJPROP(zval) Z_OBJ_HT((zval))->get_properties(Z_OBJ(zval)) #define Z_OBJPROP_P(zval_p) Z_OBJPROP(*(zval_p)) #define Z_RES(zval) (zval).value.res diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index d71694223f..d47ce83913 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -859,6 +859,8 @@ ZEND_VM_HELPER(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); @@ -885,8 +887,14 @@ ZEND_VM_HELPER(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, ZEND_VM_C_LABEL(assign_op_object): /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (OP2_TYPE == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -923,7 +931,10 @@ ZEND_VM_C_LABEL(assign_op_object): } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -1224,6 +1235,8 @@ ZEND_VM_HELPER(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); @@ -1248,8 +1261,14 @@ ZEND_VM_HELPER(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, ZEND_VM_C_LABEL(pre_incdec_object): /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -1263,7 +1282,10 @@ ZEND_VM_C_LABEL(pre_incdec_object): zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -1291,6 +1313,8 @@ ZEND_VM_HELPER(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); @@ -1315,8 +1339,14 @@ ZEND_VM_HELPER(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, ZEND_VM_C_LABEL(post_incdec_object): /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -1329,7 +1359,10 @@ ZEND_VM_C_LABEL(post_incdec_object): zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -1978,9 +2011,11 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -1999,17 +2034,17 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; ZEND_VM_C_GOTO(fetch_obj_r_copy); } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -2017,11 +2052,18 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST } } } - } else if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { ZEND_VM_C_LABEL(fetch_obj_r_copy): @@ -2120,9 +2162,11 @@ ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, C /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -2141,17 +2185,17 @@ ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, C Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; ZEND_VM_C_GOTO(fetch_obj_is_copy); } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -2159,9 +2203,15 @@ ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, C } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { ZEND_VM_C_LABEL(fetch_obj_is_copy): @@ -2253,6 +2303,8 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE USE_OPLINE zend_free_op free_op1, free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); @@ -2277,8 +2329,9 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE } ZEND_VM_C_LABEL(assign_object): + zobj = Z_OBJ_P(object); if (OP2_TYPE == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -2368,7 +2421,17 @@ ZEND_VM_C_LABEL(fast_assign_obj): ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -3427,7 +3490,6 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV, HANDLE_EXCEPTION(); } if (OP2_TYPE == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -3445,27 +3507,29 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV, FREE_OP2(); } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; FREE_OP1(); if ((OP1_TYPE & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (OP1_TYPE & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (OP1_TYPE == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ FREE_OP1(); } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -3477,7 +3541,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -3553,7 +3617,6 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, HANDLE_EXCEPTION(); } if (OP2_TYPE == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -3578,33 +3641,30 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } + HANDLE_EXCEPTION(); } - } - - if (OP1_TYPE == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (OP1_TYPE == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -3632,7 +3692,7 @@ ZEND_VM_HOT_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT) CACHE_PTR(opline->result.num, fbc); } call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, NULL, NULL); + fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call); EX(call) = call; @@ -3653,7 +3713,7 @@ ZEND_VM_C_LABEL(try_function_name): if (OP2_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { call = zend_init_dynamic_call_string(Z_STR_P(function_name), opline->extended_value); } else if (OP2_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT)) { - call = zend_init_dynamic_call_object(function_name, opline->extended_value); + call = zend_init_dynamic_call_object(Z_OBJ_P(function_name), opline->extended_value); } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY)) { call = zend_init_dynamic_call_array(Z_ARRVAL_P(function_name), opline->extended_value); } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(function_name) == IS_REFERENCE)) { @@ -3704,26 +3764,16 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM) zend_fcall_info_cache fcc; char *error = NULL; zend_function *func; - zend_class_entry *called_scope; - zend_object *object; + void *object_or_called_scope; zend_execute_data *call; uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; SAVE_OPLINE(); function_name = GET_OP2_ZVAL_PTR(BP_VAR_R); if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { + ZEND_ASSERT(!error); func = fcc.function_handler; - called_scope = fcc.called_scope; - object = fcc.object; - if (error) { - efree(error); - /* This is the only soft error is_callable() can generate */ - zend_non_static_method_call(func); - if (UNEXPECTED(EG(exception) != NULL)) { - FREE_OP2(); - HANDLE_EXCEPTION(); - } - } + object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ GC_ADDREF(ZEND_CLOSURE_OBJECT(func)); @@ -3731,9 +3781,14 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM) if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { call_info |= ZEND_CALL_FAKE_CLOSURE; } - } else if (object) { - call_info |= ZEND_CALL_RELEASE_THIS; - GC_ADDREF(object); /* For $this pointer */ + if (fcc.object) { + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_HAS_THIS; + } + } else if (fcc.object) { + GC_ADDREF(fcc.object); /* For $this pointer */ + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; } FREE_OP2(); @@ -3742,7 +3797,7 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM) zend_object_release(ZEND_CLOSURE_OBJECT(func)); } if (call_info & ZEND_CALL_RELEASE_THIS) { - zend_object_release(object); + zend_object_release(fcc.object); } HANDLE_EXCEPTION(); } @@ -3751,19 +3806,14 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM) init_func_run_time_cache(&func->op_array); } } else { - zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); + zend_type_error("%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); efree(error); FREE_OP2(); - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - func = (zend_function*)&zend_pass_function; - called_scope = NULL; - object = NULL; + HANDLE_EXCEPTION(); } call = zend_vm_stack_push_call_frame(call_info, - func, opline->extended_value, called_scope, object); + func, opline->extended_value, object_or_called_scope); call->prev_execute_data = EX(call); EX(call) = call; @@ -3796,7 +3846,7 @@ ZEND_VM_HOT_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT) } call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, NULL, NULL); + fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call); EX(call) = call; @@ -3827,7 +3877,7 @@ ZEND_VM_HOT_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM|CACHE_SLOT) call = zend_vm_stack_push_call_frame_ex( opline->op1.num, ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, NULL, NULL); + fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call); EX(call) = call; @@ -4022,9 +4072,10 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); zend_execute_ex(call); } - } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { + } else { zval retval; + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); call->prev_execute_data = execute_data; EG(current_execute_data) = call; @@ -4059,22 +4110,6 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) if (!RETURN_VALUE_USED(opline)) { zval_ptr_dtor(ret); } - - } else { /* ZEND_OVERLOADED_FUNCTION */ - zval retval; - - ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; - - call->prev_execute_data = execute_data; - - if (UNEXPECTED(!zend_do_fcall_overloaded(call, ret))) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(ret); - } } ZEND_VM_C_LABEL(fcall_end): @@ -4326,7 +4361,7 @@ ZEND_VM_HANDLER(41, ZEND_GENERATOR_CREATE, ANY, ANY) gen_execute_data->return_value = (zval*)generator; call_info = Z_TYPE_INFO(EX(This)); if ((call_info & Z_TYPE_MASK) == IS_OBJECT - && (!(call_info & ((ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS) << ZEND_CALL_INFO_SHIFT)) + && (!(call_info & (ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS)) /* Bug #72523 */ || UNEXPECTED(zend_execute_ex != execute_ex))) { ZEND_ADD_CALL_FLAG_EX(call_info, ZEND_CALL_RELEASE_THIS); @@ -4941,17 +4976,16 @@ ZEND_VM_HANDLER(119, ZEND_SEND_ARRAY, ANY, ANY, NUM) ZEND_VM_C_GOTO(send_array); } } - zend_internal_type_error(EX_USES_STRICT_TYPES(), "call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args))); + zend_type_error("call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args))); if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(call)->func)); } if (Z_TYPE(EX(call)->This) == IS_OBJECT) { OBJ_RELEASE(Z_OBJ(EX(call)->This)); } - EX(call)->func = (zend_function*)&zend_pass_function; - Z_OBJ(EX(call)->This) = NULL; - ZEND_SET_CALL_INFO(EX(call), 0, ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS); FREE_UNFETCHED_OP2(); + FREE_OP1(); + HANDLE_EXCEPTION(); } else { uint32_t arg_num; HashTable *ht; @@ -5315,17 +5349,16 @@ ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, UNUSED|CACHE_SLOT, N /* Perform a dummy function call */ call = zend_vm_stack_push_call_frame( ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, - opline->extended_value, NULL, NULL); + opline->extended_value, NULL); } else { if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { init_func_run_time_cache(&constructor->op_array); } /* We are not handling overloaded classes right now */ call = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR, + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR | ZEND_CALL_HAS_THIS, constructor, opline->extended_value, - ce, Z_OBJ_P(result)); Z_ADDREF_P(result); } @@ -5340,6 +5373,7 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) USE_OPLINE zend_free_op free_op1; zval *obj; + zend_object *zobj; zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -5373,9 +5407,10 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) } } while (0); - ce = Z_OBJCE_P(obj); + zobj = Z_OBJ_P(obj); + ce = zobj->ce; clone = ce->clone; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; + clone_call = zobj->handlers->clone_obj; if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); FREE_OP1(); @@ -5396,7 +5431,7 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) } } - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj)); + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); FREE_OP1(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -5732,10 +5767,10 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY, EVAL) new_op_array->scope = EX(func)->op_array.scope; - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, + call = zend_vm_stack_push_call_frame( + (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)new_op_array, 0, - Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL, - Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL); + Z_PTR(EX(This))); if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { call->symbol_table = EX(symbol_table); @@ -5956,7 +5991,7 @@ ZEND_VM_C_LABEL(num_index_dim): if (OP2_TYPE == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } @@ -5973,6 +6008,7 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_S zend_free_op free_op1, free_op2; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET); @@ -5992,7 +6028,15 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_S break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); FREE_OP2(); @@ -6020,20 +6064,27 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, JMP_ADDR) FREE_OP1_IF_VAR(); ZEND_VM_NEXT_OPCODE(); } else if (OP1_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties; + result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); + ZVAL_OBJ(result, zobj); if (OP1_TYPE != IS_TMP_VAR) { - Z_ADDREF_P(array_ptr); + GC_ADDREF(zobj); } - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); FREE_OP1_IF_VAR(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -6673,6 +6724,7 @@ ZEND_VM_COLD_CONST_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_IS); @@ -6697,9 +6749,19 @@ ZEND_VM_COLD_CONST_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED } } + if (OP2_TYPE == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (OP2_TYPE != IS_CONST) { + zend_tmp_string_release(tmp_name); + } ZEND_VM_C_LABEL(isset_object_finish): FREE_OP2(); @@ -6779,9 +6841,10 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY) ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting)); - if (EG(error_reporting)) { + if (!E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting))) { do { - EG(error_reporting) = 0; + /* Do not silence fatal errors */ + EG(error_reporting) &= E_FATAL_ERRORS; if (!EG(error_reporting_ini_entry)) { zval *zv = zend_hash_find_ex(EG(ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING), 1); if (zv) { @@ -6810,7 +6873,8 @@ ZEND_VM_HANDLER(58, ZEND_END_SILENCE, TMP, ANY) { USE_OPLINE - if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(opline->op1.var)) != 0) { + if (E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting)) + && !E_HAS_ONLY_FATAL_ERRORS(Z_LVAL_P(EX_VAR(opline->op1.var)))) { EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var)); } ZEND_VM_NEXT_OPCODE(); @@ -7820,8 +7884,8 @@ ZEND_VM_COLD_CONST_HANDLER(121, ZEND_STRLEN, CONST|TMPVAR|CV, ANY) } zval_ptr_dtor(&tmp); } - zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); - ZVAL_NULL(EX_VAR(opline->result.var)); + zend_type_error("strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } while (0); } FREE_OP1(); @@ -8355,18 +8419,20 @@ ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMP|VAR|CV, UNUSED) count = zend_array_count(Z_ARRVAL_P(op1)); break; } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + /* first, we check if the handler is defined */ - if (Z_OBJ_HT_P(op1)->count_elements) { - if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) { + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { break; } } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) { + if (instanceof_function(zobj->ce, zend_ce_countable)) { zval retval; - zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval); + zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); count = zval_get_long(&retval); zval_ptr_dtor(&retval); break; diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 7977a2a4a0..99e28f750b 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1244,9 +1244,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); zend_execute_ex(call); } - } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { + } else { zval retval; + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); call->prev_execute_data = execute_data; EG(current_execute_data) = call; @@ -1281,22 +1282,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV if (!0) { zval_ptr_dtor(ret); } - - } else { /* ZEND_OVERLOADED_FUNCTION */ - zval retval; - - ret = 0 ? EX_VAR(opline->result.var) : &retval; - - call->prev_execute_data = execute_data; - - if (UNEXPECTED(!zend_do_fcall_overloaded(call, ret))) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - if (!0) { - zval_ptr_dtor(ret); - } } fcall_end: @@ -1365,9 +1350,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); zend_execute_ex(call); } - } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { + } else { zval retval; + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); call->prev_execute_data = execute_data; EG(current_execute_data) = call; @@ -1402,22 +1388,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV if (!1) { zval_ptr_dtor(ret); } - - } else { /* ZEND_OVERLOADED_FUNCTION */ - zval retval; - - ret = 1 ? EX_VAR(opline->result.var) : &retval; - - call->prev_execute_data = execute_data; - - if (UNEXPECTED(!zend_do_fcall_overloaded(call, ret))) { - UNDEF_RESULT(); - HANDLE_EXCEPTION(); - } - - if (!1) { - zval_ptr_dtor(ret); - } } fcall_end: @@ -1489,7 +1459,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_CREATE_SPEC_HANDLER( gen_execute_data->return_value = (zval*)generator; call_info = Z_TYPE_INFO(EX(This)); if ((call_info & Z_TYPE_MASK) == IS_OBJECT - && (!(call_info & ((ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS) << ZEND_CALL_INFO_SHIFT)) + && (!(call_info & (ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS)) /* Bug #72523 */ || UNEXPECTED(zend_execute_ex != execute_ex))) { ZEND_ADD_CALL_FLAG_EX(call_info, ZEND_CALL_RELEASE_THIS); @@ -1703,17 +1673,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_O goto send_array; } } - zend_internal_type_error(EX_USES_STRICT_TYPES(), "call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args))); + zend_type_error("call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args))); if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(call)->func)); } if (Z_TYPE(EX(call)->This) == IS_OBJECT) { OBJ_RELEASE(Z_OBJ(EX(call)->This)); } - EX(call)->func = (zend_function*)&zend_pass_function; - Z_OBJ(EX(call)->This) = NULL; - ZEND_SET_CALL_INFO(EX(call), 0, ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS); FREE_UNFETCHED_OP(opline->op2_type, opline->op2.var); + FREE_OP(free_op1); + HANDLE_EXCEPTION(); } else { uint32_t arg_num; HashTable *ht; @@ -1826,9 +1795,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEN ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting)); - if (EG(error_reporting)) { + if (!E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting))) { do { - EG(error_reporting) = 0; + /* Do not silence fatal errors */ + EG(error_reporting) &= E_FATAL_ERRORS; if (!EG(error_reporting_ini_entry)) { zval *zv = zend_hash_find_ex(EG(ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING), 1); if (zv) { @@ -2337,7 +2307,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME CACHE_PTR(opline->result.num, fbc); } call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, NULL, NULL); + fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call); EX(call) = call; @@ -2358,7 +2328,7 @@ try_function_name: if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { call = zend_init_dynamic_call_string(Z_STR_P(function_name), opline->extended_value); } else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT)) { - call = zend_init_dynamic_call_object(function_name, opline->extended_value); + call = zend_init_dynamic_call_object(Z_OBJ_P(function_name), opline->extended_value); } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY)) { call = zend_init_dynamic_call_array(Z_ARRVAL_P(function_name), opline->extended_value); } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(function_name) == IS_REFERENCE)) { @@ -2426,7 +2396,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_N } call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, NULL, NULL); + fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call); EX(call) = call; @@ -2457,7 +2427,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_SPEC_CO call = zend_vm_stack_push_call_frame_ex( opline->op1.num, ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, NULL, NULL); + fbc, opline->extended_value, NULL); call->prev_execute_data = EX(call); EX(call) = call; @@ -2527,7 +2497,7 @@ try_function_name: if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { call = zend_init_dynamic_call_string(Z_STR_P(function_name), opline->extended_value); } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT)) { - call = zend_init_dynamic_call_object(function_name, opline->extended_value); + call = zend_init_dynamic_call_object(Z_OBJ_P(function_name), opline->extended_value); } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY)) { call = zend_init_dynamic_call_array(Z_ARRVAL_P(function_name), opline->extended_value); } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(function_name) == IS_REFERENCE)) { @@ -2645,7 +2615,7 @@ try_function_name: if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { call = zend_init_dynamic_call_string(Z_STR_P(function_name), opline->extended_value); } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT)) { - call = zend_init_dynamic_call_object(function_name, opline->extended_value); + call = zend_init_dynamic_call_object(Z_OBJ_P(function_name), opline->extended_value); } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY)) { call = zend_init_dynamic_call_array(Z_ARRVAL_P(function_name), opline->extended_value); } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(function_name) == IS_REFERENCE)) { @@ -3311,6 +3281,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ USE_OPLINE zval *obj; + zend_object *zobj; zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -3344,9 +3315,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ } } while (0); - ce = Z_OBJCE_P(obj); + zobj = Z_OBJ_P(obj); + ce = zobj->ce; clone = ce->clone; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; + clone_call = zobj->handlers->clone_obj; if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); @@ -3367,7 +3339,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ } } - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj)); + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -3498,10 +3470,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN new_op_array->scope = EX(func)->op_array.scope; - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, + call = zend_vm_stack_push_call_frame( + (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)new_op_array, 0, - Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL, - Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL); + Z_PTR(EX(This))); if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { call->symbol_table = EX(symbol_table); @@ -3551,20 +3523,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER( ZEND_VM_NEXT_OPCODE(); } else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties; + result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); + ZVAL_OBJ(result, zobj); if (IS_CONST != IS_TMP_VAR) { - Z_ADDREF_P(array_ptr); + GC_ADDREF(zobj); } - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { @@ -3991,8 +3970,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CONST } zval_ptr_dtor(&tmp); } - zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); - ZVAL_NULL(EX_VAR(opline->result.var)); + zend_type_error("strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } while (0); } @@ -5047,9 +5026,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -5068,17 +5049,17 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -5086,11 +5067,18 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ } } } - } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -5141,9 +5129,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -5162,17 +5152,17 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -5180,9 +5170,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -5432,7 +5428,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -5450,26 +5445,28 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_CONST == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -5481,7 +5478,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -5557,7 +5554,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -5582,33 +5578,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } + HANDLE_EXCEPTION(); } - } - - if (IS_CONST == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_CONST == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -5623,26 +5616,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS zend_fcall_info_cache fcc; char *error = NULL; zend_function *func; - zend_class_entry *called_scope; - zend_object *object; + void *object_or_called_scope; zend_execute_data *call; uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; SAVE_OPLINE(); function_name = RT_CONSTANT(opline, opline->op2); if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { + ZEND_ASSERT(!error); func = fcc.function_handler; - called_scope = fcc.called_scope; - object = fcc.object; - if (error) { - efree(error); - /* This is the only soft error is_callable() can generate */ - zend_non_static_method_call(func); - if (UNEXPECTED(EG(exception) != NULL)) { - - HANDLE_EXCEPTION(); - } - } + object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ GC_ADDREF(ZEND_CLOSURE_OBJECT(func)); @@ -5650,9 +5633,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { call_info |= ZEND_CALL_FAKE_CLOSURE; } - } else if (object) { - call_info |= ZEND_CALL_RELEASE_THIS; - GC_ADDREF(object); /* For $this pointer */ + if (fcc.object) { + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_HAS_THIS; + } + } else if (fcc.object) { + GC_ADDREF(fcc.object); /* For $this pointer */ + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; } if ((IS_CONST & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) { @@ -5660,7 +5648,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS zend_object_release(ZEND_CLOSURE_OBJECT(func)); } if (call_info & ZEND_CALL_RELEASE_THIS) { - zend_object_release(object); + zend_object_release(fcc.object); } HANDLE_EXCEPTION(); } @@ -5669,19 +5657,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS init_func_run_time_cache(&func->op_array); } } else { - zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); + zend_type_error("%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); efree(error); - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - func = (zend_function*)&zend_pass_function; - called_scope = NULL; - object = NULL; + HANDLE_EXCEPTION(); } call = zend_vm_stack_push_call_frame(call_info, - func, opline->extended_value, called_scope, object); + func, opline->extended_value, object_or_called_scope); call->prev_execute_data = EX(call); EX(call) = call; @@ -6015,6 +5998,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); @@ -6039,9 +6023,19 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO } } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: @@ -7294,9 +7288,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -7315,17 +7311,17 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -7333,11 +7329,18 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ } } } - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -7388,9 +7391,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -7409,17 +7414,17 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -7427,9 +7432,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -7679,7 +7690,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -7697,26 +7707,28 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ zval_ptr_dtor_nogc(free_op2); } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_CONST == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -7728,7 +7740,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -7804,7 +7816,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -7829,33 +7840,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } + HANDLE_EXCEPTION(); } - } - - if (IS_CONST == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_CONST == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -7870,26 +7878,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV zend_fcall_info_cache fcc; char *error = NULL; zend_function *func; - zend_class_entry *called_scope; - zend_object *object; + void *object_or_called_scope; zend_execute_data *call; uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; SAVE_OPLINE(); function_name = _get_zval_ptr_var(opline->op2.var, &free_op2 EXECUTE_DATA_CC); if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { + ZEND_ASSERT(!error); func = fcc.function_handler; - called_scope = fcc.called_scope; - object = fcc.object; - if (error) { - efree(error); - /* This is the only soft error is_callable() can generate */ - zend_non_static_method_call(func); - if (UNEXPECTED(EG(exception) != NULL)) { - zval_ptr_dtor_nogc(free_op2); - HANDLE_EXCEPTION(); - } - } + object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ GC_ADDREF(ZEND_CLOSURE_OBJECT(func)); @@ -7897,9 +7895,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { call_info |= ZEND_CALL_FAKE_CLOSURE; } - } else if (object) { - call_info |= ZEND_CALL_RELEASE_THIS; - GC_ADDREF(object); /* For $this pointer */ + if (fcc.object) { + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_HAS_THIS; + } + } else if (fcc.object) { + GC_ADDREF(fcc.object); /* For $this pointer */ + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; } zval_ptr_dtor_nogc(free_op2); @@ -7908,7 +7911,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV zend_object_release(ZEND_CLOSURE_OBJECT(func)); } if (call_info & ZEND_CALL_RELEASE_THIS) { - zend_object_release(object); + zend_object_release(fcc.object); } HANDLE_EXCEPTION(); } @@ -7917,19 +7920,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV init_func_run_time_cache(&func->op_array); } } else { - zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); + zend_type_error("%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); efree(error); zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - func = (zend_function*)&zend_pass_function; - called_scope = NULL; - object = NULL; + HANDLE_EXCEPTION(); } call = zend_vm_stack_push_call_frame(call_info, - func, opline->extended_value, called_scope, object); + func, opline->extended_value, object_or_called_scope); call->prev_execute_data = EX(call); EX(call) = call; @@ -8138,6 +8136,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); @@ -8162,9 +8161,19 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO } } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: zval_ptr_dtor_nogc(free_op2); @@ -8879,7 +8888,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -8955,7 +8964,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C HANDLE_EXCEPTION(); } if (IS_UNUSED == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -8980,33 +8988,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } + HANDLE_EXCEPTION(); } - } - - if (IS_CONST == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_CONST == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -9115,17 +9120,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_UNUSED_HANDLER( /* Perform a dummy function call */ call = zend_vm_stack_push_call_frame( ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, - opline->extended_value, NULL, NULL); + opline->extended_value, NULL); } else { if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { init_func_run_time_cache(&constructor->op_array); } /* We are not handling overloaded classes right now */ call = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR, + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR | ZEND_CALL_HAS_THIS, constructor, opline->extended_value, - ce, Z_OBJ_P(result)); Z_ADDREF_P(result); } @@ -9564,18 +9568,20 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CONST_ count = zend_array_count(Z_ARRVAL_P(op1)); break; } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + /* first, we check if the handler is defined */ - if (Z_OBJ_HT_P(op1)->count_elements) { - if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) { + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { break; } } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) { + if (instanceof_function(zobj->ce, zend_ce_countable)) { zval retval; - zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval); + zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); count = zval_get_long(&retval); zval_ptr_dtor(&retval); break; @@ -10237,9 +10243,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -10258,17 +10266,17 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -10276,11 +10284,18 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ } } } - } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -10331,9 +10346,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -10352,17 +10369,17 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -10370,9 +10387,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -10622,7 +10645,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -10640,26 +10662,28 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_CONST == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -10671,7 +10695,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -10747,7 +10771,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -10772,33 +10795,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } + HANDLE_EXCEPTION(); } - } - - if (IS_CONST == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_CONST == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -10813,26 +10833,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H zend_fcall_info_cache fcc; char *error = NULL; zend_function *func; - zend_class_entry *called_scope; - zend_object *object; + void *object_or_called_scope; zend_execute_data *call; uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; SAVE_OPLINE(); function_name = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { + ZEND_ASSERT(!error); func = fcc.function_handler; - called_scope = fcc.called_scope; - object = fcc.object; - if (error) { - efree(error); - /* This is the only soft error is_callable() can generate */ - zend_non_static_method_call(func); - if (UNEXPECTED(EG(exception) != NULL)) { - - HANDLE_EXCEPTION(); - } - } + object_or_called_scope = fcc.called_scope; if (func->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ GC_ADDREF(ZEND_CLOSURE_OBJECT(func)); @@ -10840,9 +10850,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { call_info |= ZEND_CALL_FAKE_CLOSURE; } - } else if (object) { - call_info |= ZEND_CALL_RELEASE_THIS; - GC_ADDREF(object); /* For $this pointer */ + if (fcc.object) { + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_HAS_THIS; + } + } else if (fcc.object) { + GC_ADDREF(fcc.object); /* For $this pointer */ + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; } if ((IS_CV & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) { @@ -10850,7 +10865,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H zend_object_release(ZEND_CLOSURE_OBJECT(func)); } if (call_info & ZEND_CALL_RELEASE_THIS) { - zend_object_release(object); + zend_object_release(fcc.object); } HANDLE_EXCEPTION(); } @@ -10859,19 +10874,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H init_func_run_time_cache(&func->op_array); } } else { - zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); + zend_type_error("%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); efree(error); - if (UNEXPECTED(EG(exception))) { - HANDLE_EXCEPTION(); - } - func = (zend_function*)&zend_pass_function; - called_scope = NULL; - object = NULL; + HANDLE_EXCEPTION(); } call = zend_vm_stack_push_call_frame(call_info, - func, opline->extended_value, called_scope, object); + func, opline->extended_value, object_or_called_scope); call->prev_execute_data = EX(call); EX(call) = call; @@ -11080,6 +11090,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = RT_CONSTANT(opline, opline->op1); @@ -11104,9 +11115,19 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO } } + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: @@ -12862,6 +12883,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND USE_OPLINE zend_free_op free_op1; zval *obj; + zend_object *zobj; zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -12895,9 +12917,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND } } while (0); - ce = Z_OBJCE_P(obj); + zobj = Z_OBJ_P(obj); + ce = zobj->ce; clone = ce->clone; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; + clone_call = zobj->handlers->clone_obj; if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); zval_ptr_dtor_nogc(free_op1); @@ -12918,7 +12941,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND } } - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj)); + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); zval_ptr_dtor_nogc(free_op1); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -12957,10 +12980,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HA new_op_array->scope = EX(func)->op_array.scope; - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, + call = zend_vm_stack_push_call_frame( + (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)new_op_array, 0, - Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL, - Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL); + Z_PTR(EX(This))); if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { call->symbol_table = EX(symbol_table); @@ -13102,8 +13125,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_TMPVAR_HANDLER(ZEN } zval_ptr_dtor(&tmp); } - zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); - ZVAL_NULL(EX_VAR(opline->result.var)); + zend_type_error("strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } while (0); } zval_ptr_dtor_nogc(free_op1); @@ -13998,9 +14021,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_ /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -14019,17 +14044,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_ Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -14037,11 +14062,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_ } } } - } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -14092,9 +14124,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -14113,17 +14147,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -14131,9 +14165,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -14357,7 +14397,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -14375,27 +14414,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; zval_ptr_dtor_nogc(free_op1); if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if ((IS_TMP_VAR|IS_VAR) == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ zval_ptr_dtor_nogc(free_op1); } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -14615,6 +14656,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -14639,9 +14681,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM } } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: @@ -15633,9 +15685,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -15654,17 +15708,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -15672,11 +15726,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR } } } - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -15727,9 +15788,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVA /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -15748,17 +15811,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVA Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -15766,9 +15829,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVA } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -15992,7 +16061,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -16010,27 +16078,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T zval_ptr_dtor_nogc(free_op2); } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; zval_ptr_dtor_nogc(free_op1); if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if ((IS_TMP_VAR|IS_VAR) == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ zval_ptr_dtor_nogc(free_op1); } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -16196,6 +16266,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -16220,9 +16291,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM } } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: zval_ptr_dtor_nogc(free_op2); @@ -17296,9 +17377,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HAN /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -17317,17 +17400,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HAN Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -17335,11 +17418,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HAN } } } - } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -17390,9 +17480,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HA /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -17411,17 +17503,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HA Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -17429,9 +17521,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HA } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -17655,7 +17753,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -17673,27 +17770,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; zval_ptr_dtor_nogc(free_op1); if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if ((IS_TMP_VAR|IS_VAR) == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ zval_ptr_dtor_nogc(free_op1); } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -17859,6 +17958,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -17883,9 +17983,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM } } + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: @@ -18327,20 +18437,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE ZEND_VM_NEXT_OPCODE(); } else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties; + result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); + ZVAL_OBJ(result, zobj); if (IS_TMP_VAR != IS_TMP_VAR) { - Z_ADDREF_P(array_ptr); + GC_ADDREF(zobj); } - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { @@ -18461,7 +18578,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_END_SILENCE_SPEC_TMP_HANDLER(Z { USE_OPLINE - if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(opline->op1.var)) != 0) { + if (E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting)) + && !E_HAS_ONLY_FATAL_ERRORS(Z_LVAL_P(EX_VAR(opline->op1.var)))) { EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var)); } ZEND_VM_NEXT_OPCODE(); @@ -20269,18 +20387,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMP_UNUSED_HANDLER( count = zend_array_count(Z_ARRVAL_P(op1)); break; } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + /* first, we check if the handler is defined */ - if (Z_OBJ_HT_P(op1)->count_elements) { - if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) { + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { break; } } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) { + if (instanceof_function(zobj->ce, zend_ce_countable)) { zval retval; - zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval); + zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); count = zval_get_long(&retval); zval_ptr_dtor(&retval); break; @@ -21681,20 +21801,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZE zval_ptr_dtor_nogc(free_op1); ZEND_VM_NEXT_OPCODE(); } else if (IS_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties; + result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); + ZVAL_OBJ(result, zobj); if (IS_VAR != IS_TMP_VAR) { - Z_ADDREF_P(array_ptr); + GC_ADDREF(zobj); } - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); zval_ptr_dtor_nogc(free_op1); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -22428,6 +22555,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -22454,8 +22583,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -22492,7 +22627,10 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -23025,6 +23163,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -23049,8 +23189,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -23064,7 +23210,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -23091,6 +23240,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -23115,8 +23266,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -23129,7 +23286,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -23326,6 +23486,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D USE_OPLINE zend_free_op free_op1; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -23350,8 +23512,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -23441,7 +23604,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -23460,6 +23633,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D USE_OPLINE zend_free_op free_op1, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -23484,8 +23659,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -23575,7 +23751,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -23594,6 +23780,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D USE_OPLINE zend_free_op free_op1, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -23618,8 +23806,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -23709,7 +23898,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -23728,6 +23927,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D USE_OPLINE zend_free_op free_op1; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -23752,8 +23953,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -23843,7 +24045,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -24548,7 +24760,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -24624,7 +24836,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -24649,33 +24860,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } + HANDLE_EXCEPTION(); } - } - - if (IS_VAR == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_VAR == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -24948,7 +25156,7 @@ num_index_dim: if (IS_CONST == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } @@ -24964,6 +25172,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDL zend_free_op free_op1; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -24983,7 +25192,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDL break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; @@ -25178,6 +25395,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -25204,8 +25423,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -25242,7 +25467,10 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -25777,6 +26005,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -25801,8 +26031,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -25816,7 +26052,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -25844,6 +26083,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -25868,8 +26109,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -25882,7 +26129,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -26081,6 +26331,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ USE_OPLINE zend_free_op free_op1, free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -26105,8 +26357,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -26196,7 +26449,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -26215,6 +26478,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ USE_OPLINE zend_free_op free_op1, free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -26239,8 +26504,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -26330,7 +26596,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -26349,6 +26625,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ USE_OPLINE zend_free_op free_op1, free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -26373,8 +26651,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -26464,7 +26743,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -26483,6 +26772,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ USE_OPLINE zend_free_op free_op1, free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -26507,8 +26798,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -26598,7 +26890,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -27247,7 +27549,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -27323,7 +27625,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -27348,33 +27649,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } + HANDLE_EXCEPTION(); } - } - - if (IS_VAR == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_VAR == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -27576,7 +27874,7 @@ num_index_dim: if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } @@ -27593,6 +27891,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HAND zend_free_op free_op1, free_op2; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -27612,7 +27911,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HAND break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); zval_ptr_dtor_nogc(free_op2); @@ -28927,7 +29234,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -29003,7 +29310,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V HANDLE_EXCEPTION(); } if (IS_UNUSED == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -29028,33 +29334,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } + HANDLE_EXCEPTION(); } - } - - if (IS_VAR == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_VAR == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -29163,17 +29466,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_UNUSED_HANDLER(ZE /* Perform a dummy function call */ call = zend_vm_stack_push_call_frame( ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, - opline->extended_value, NULL, NULL); + opline->extended_value, NULL); } else { if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { init_func_run_time_cache(&constructor->op_array); } /* We are not handling overloaded classes right now */ call = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR, + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR | ZEND_CALL_HAS_THIS, constructor, opline->extended_value, - ce, Z_OBJ_P(result)); Z_ADDREF_P(result); } @@ -29498,18 +29800,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_VAR_UNUSED_HANDLER( count = zend_array_count(Z_ARRVAL_P(op1)); break; } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + /* first, we check if the handler is defined */ - if (Z_OBJ_HT_P(op1)->count_elements) { - if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) { + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { break; } } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) { + if (instanceof_function(zobj->ce, zend_ce_countable)) { zval retval; - zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval); + zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); count = zval_get_long(&retval); zval_ptr_dtor(&retval); break; @@ -29590,6 +29894,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -29616,8 +29922,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -29654,7 +29966,10 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -30093,6 +30408,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -30117,8 +30434,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -30132,7 +30455,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -30159,6 +30485,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -30183,8 +30511,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -30197,7 +30531,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -30394,6 +30731,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA USE_OPLINE zend_free_op free_op1; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -30418,8 +30757,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -30509,7 +30849,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -30528,6 +30878,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA USE_OPLINE zend_free_op free_op1, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -30552,8 +30904,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -30643,7 +30996,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -30662,6 +31025,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA USE_OPLINE zend_free_op free_op1, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -30686,8 +31051,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -30777,7 +31143,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -30796,6 +31172,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA USE_OPLINE zend_free_op free_op1; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -30820,8 +31198,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -30911,7 +31290,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -31655,7 +32044,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -31731,7 +32120,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -31756,33 +32144,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } + HANDLE_EXCEPTION(); } - } - - if (IS_VAR == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_VAR == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -31984,7 +32369,7 @@ num_index_dim: if (IS_CV == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } @@ -32000,6 +32385,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER( zend_free_op free_op1; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); @@ -32019,7 +32405,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER( break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; @@ -32311,6 +32705,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND USE_OPLINE zval *obj; + zend_object *zobj; zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -32344,9 +32739,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND } } while (0); - ce = Z_OBJCE_P(obj); + zobj = Z_OBJ_P(obj); + ce = zobj->ce; clone = ce->clone; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; + clone_call = zobj->handlers->clone_obj; if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); @@ -32367,7 +32763,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND } } - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj)); + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -32456,6 +32852,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -32482,8 +32880,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -32520,7 +32924,10 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -32635,6 +33042,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -32659,8 +33068,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -32674,7 +33089,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -32701,6 +33119,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -32725,8 +33145,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -32739,7 +33165,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -32800,9 +33229,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_U /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -32821,17 +33252,17 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_U Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -32839,11 +33270,18 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_U } } } - } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -32942,9 +33380,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -32963,17 +33403,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -32981,9 +33421,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -33038,6 +33484,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O USE_OPLINE zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -33062,8 +33510,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -33153,7 +33602,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -33172,6 +33631,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O USE_OPLINE zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -33196,8 +33657,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -33287,7 +33749,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -33306,6 +33778,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O USE_OPLINE zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -33330,8 +33804,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -33421,7 +33896,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -33440,6 +33925,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O USE_OPLINE zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -33464,8 +33951,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -33555,7 +34043,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -33909,7 +34407,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -33927,26 +34424,28 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_UNUSED == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -33958,7 +34457,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -34034,7 +34533,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -34059,33 +34557,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } + HANDLE_EXCEPTION(); } - } - - if (IS_UNUSED == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_UNUSED == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -34185,6 +34680,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HA zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); @@ -34204,7 +34700,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HA break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); @@ -34218,6 +34722,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); @@ -34242,9 +34747,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN } } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: @@ -34401,6 +34916,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -34427,8 +34944,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -34465,7 +34988,10 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -34580,6 +35106,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -34604,8 +35132,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -34619,7 +35153,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -34647,6 +35184,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -34671,8 +35210,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -34685,7 +35230,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -34747,9 +35295,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -34768,17 +35318,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -34786,11 +35336,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR } } } - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -34889,9 +35446,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVA /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -34910,17 +35469,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVA Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -34928,9 +35487,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVA } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -34985,6 +35550,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ USE_OPLINE zend_free_op free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -35009,8 +35576,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -35100,7 +35668,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -35119,6 +35697,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ USE_OPLINE zend_free_op free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -35143,8 +35723,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -35234,7 +35815,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -35253,6 +35844,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ USE_OPLINE zend_free_op free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -35277,8 +35870,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -35368,7 +35962,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -35387,6 +35991,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ USE_OPLINE zend_free_op free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -35411,8 +36017,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -35502,7 +36109,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -35857,7 +36474,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -35875,26 +36491,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T zval_ptr_dtor_nogc(free_op2); } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_UNUSED == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -35906,7 +36524,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -35982,7 +36600,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -36007,33 +36624,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } + HANDLE_EXCEPTION(); } - } - - if (IS_UNUSED == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_UNUSED == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -36046,6 +36660,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_H zend_free_op free_op2; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); @@ -36065,7 +36680,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_H break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); zval_ptr_dtor_nogc(free_op2); @@ -36080,6 +36703,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); @@ -36104,9 +36728,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN } } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: zval_ptr_dtor_nogc(free_op2); @@ -36438,7 +37072,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -36514,7 +37148,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U HANDLE_EXCEPTION(); } if (IS_UNUSED == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -36539,33 +37172,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } + HANDLE_EXCEPTION(); } - } - - if (IS_UNUSED == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_UNUSED == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -36674,17 +37304,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_UNUSED_UNUSED_HANDLER /* Perform a dummy function call */ call = zend_vm_stack_push_call_frame( ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, - opline->extended_value, NULL, NULL); + opline->extended_value, NULL); } else { if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { init_func_run_time_cache(&constructor->op_array); } /* We are not handling overloaded classes right now */ call = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR, + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR | ZEND_CALL_HAS_THIS, constructor, opline->extended_value, - ce, Z_OBJ_P(result)); Z_ADDREF_P(result); } @@ -36997,6 +37626,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -37023,8 +37654,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -37061,7 +37698,10 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -37176,6 +37816,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -37200,8 +37842,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -37215,7 +37863,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -37242,6 +37893,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -37266,8 +37919,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -37280,7 +37939,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -37341,9 +38003,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HAN /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -37362,17 +38026,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HAN Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -37380,11 +38044,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HAN } } } - } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -37483,9 +38154,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HA /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -37504,17 +38177,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HA Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -37522,9 +38195,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HA } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -37579,6 +38258,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D USE_OPLINE zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -37603,8 +38284,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -37694,7 +38376,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -37713,6 +38405,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D USE_OPLINE zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -37737,8 +38431,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -37828,7 +38523,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -37847,6 +38552,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D USE_OPLINE zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -37871,8 +38578,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -37962,7 +38670,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -37981,6 +38699,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D USE_OPLINE zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = &EX(This); @@ -38005,8 +38725,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -38096,7 +38817,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -38450,7 +39181,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -38468,26 +39198,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_UNUSED == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -38499,7 +39231,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U USE_OPLINE zval *function_name; zend_class_entry *ce; - zend_object *object; + uint32_t call_info; zend_function *fbc; zend_execute_data *call; @@ -38575,7 +39307,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) { CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); } @@ -38600,33 +39331,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } } - object = NULL; if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { - object = Z_OBJ(EX(This)); - ce = object->ce; + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { zend_non_static_method_call(fbc); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } + HANDLE_EXCEPTION(); } - } - - if (IS_UNUSED == IS_UNUSED) { + } else { /* previous opcode is ZEND_FETCH_CLASS */ - if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || - (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { + if (IS_UNUSED == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else { ce = Z_CE(EX(This)); } } + call_info = ZEND_CALL_NESTED_FUNCTION; } - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, ce, object); + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); call->prev_execute_data = EX(call); EX(call) = call; @@ -38639,6 +39367,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDL zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); @@ -38658,7 +39387,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDL break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); @@ -38672,6 +39409,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = &EX(This); @@ -38696,9 +39434,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN } } + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: @@ -39787,6 +40535,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC USE_OPLINE zval *obj; + zend_object *zobj; zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -39820,9 +40569,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC } } while (0); - ce = Z_OBJCE_P(obj); + zobj = Z_OBJ_P(obj); + ce = zobj->ce; clone = ce->clone; - clone_call = Z_OBJ_HT_P(obj)->clone_obj; + clone_call = zobj->handlers->clone_obj; if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); @@ -39843,7 +40593,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC } } - ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj)); + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -39974,10 +40724,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLE new_op_array->scope = EX(func)->op_array.scope; - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, + call = zend_vm_stack_push_call_frame( + (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)new_op_array, 0, - Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL, - Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL); + Z_PTR(EX(This))); if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { call->symbol_table = EX(symbol_table); @@ -40027,20 +40777,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEN ZEND_VM_NEXT_OPCODE(); } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties; + result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); + ZVAL_OBJ(result, zobj); if (IS_CV != IS_TMP_VAR) { - Z_ADDREF_P(array_ptr); + GC_ADDREF(zobj); } - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { @@ -40458,8 +41215,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OP } zval_ptr_dtor(&tmp); } - zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); - ZVAL_NULL(EX_VAR(opline->result.var)); + zend_type_error("strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); } while (0); } @@ -41295,6 +42052,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); @@ -41321,8 +42080,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -41359,7 +42124,10 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -41892,6 +42660,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); @@ -41916,8 +42686,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -41931,7 +42707,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -41958,6 +42737,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); @@ -41982,8 +42763,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -41996,7 +42783,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -42227,9 +43017,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_C /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -42248,17 +43040,17 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_C Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -42266,11 +43058,18 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_C } } } - } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -42369,9 +43168,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HAN /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -42390,17 +43191,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HAN Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -42408,9 +43209,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HAN } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -42465,6 +43272,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA USE_OPLINE zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -42489,8 +43298,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -42580,7 +43390,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -42599,6 +43419,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA USE_OPLINE zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -42623,8 +43445,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -42714,7 +43537,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -42733,6 +43566,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA USE_OPLINE zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -42757,8 +43592,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -42848,7 +43684,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -42867,6 +43713,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA USE_OPLINE zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -42891,8 +43739,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } assign_object: + zobj = Z_OBJ_P(object); if (IS_CONST == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -42982,7 +43831,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -43890,7 +44749,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -43908,26 +44766,28 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_CV == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -44183,7 +45043,7 @@ num_index_dim: if (IS_CONST == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } @@ -44199,6 +45059,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLE zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(opline->op1.var EXECUTE_DATA_CC); @@ -44218,7 +45079,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLE break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); @@ -44312,6 +45181,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); @@ -44336,9 +45206,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV } } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: @@ -45508,6 +46388,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); @@ -45534,8 +46416,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -45572,7 +46460,10 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -46107,6 +46998,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); @@ -46131,8 +47024,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -46146,7 +47045,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -46174,6 +47076,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); @@ -46198,8 +47102,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -46212,7 +47122,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -46390,9 +47303,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HAN /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -46411,17 +47326,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HAN Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -46429,11 +47344,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HAN } } } - } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -46532,9 +47454,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HA /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -46553,17 +47477,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HA Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -46571,9 +47495,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HA } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -46628,6 +47558,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D USE_OPLINE zend_free_op free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -46652,8 +47584,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -46743,7 +47676,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -46762,6 +47705,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D USE_OPLINE zend_free_op free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -46786,8 +47731,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -46877,7 +47823,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -46896,6 +47852,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D USE_OPLINE zend_free_op free_op2, free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -46920,8 +47878,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -47011,7 +47970,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -47030,6 +47999,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D USE_OPLINE zend_free_op free_op2; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -47054,8 +48025,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } assign_object: + zobj = Z_OBJ_P(object); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -47145,7 +48117,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -47997,7 +48979,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -48015,26 +48996,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA zval_ptr_dtor_nogc(free_op2); } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_CV == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -48236,7 +49219,7 @@ num_index_dim: if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } @@ -48253,6 +49236,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDL zend_free_op free_op2; zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(opline->op1.var EXECUTE_DATA_CC); @@ -48272,7 +49256,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDL break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); zval_ptr_dtor_nogc(free_op2); @@ -48367,6 +49359,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); @@ -48391,9 +49384,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV } } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: zval_ptr_dtor_nogc(free_op2); @@ -50755,18 +51758,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CV_UNUSED_HANDLER(Z count = zend_array_count(Z_ARRVAL_P(op1)); break; } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + /* first, we check if the handler is defined */ - if (Z_OBJ_HT_P(op1)->count_elements) { - if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) { + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { break; } } /* if not and the object implements Countable we call its count() method */ - if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) { + if (instanceof_function(zobj->ce, zend_ce_countable)) { zval retval; - zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval); + zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval); count = zval_get_long(&retval); zval_ptr_dtor(&retval); break; @@ -51584,6 +52589,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); @@ -51610,8 +52617,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP assign_op_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -51648,7 +52661,10 @@ assign_op_object: } } } else { - zend_assign_op_overloaded_property(object, property, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + zend_assign_op_overloaded_property(zobj, name, cache_slot, value, binary_op OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -52087,6 +53103,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); @@ -52111,8 +53129,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE pre_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -52126,7 +53150,10 @@ pre_incdec_object: zend_pre_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_pre_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_pre_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -52153,6 +53180,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP zval *zptr; void **cache_slot; zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); @@ -52177,8 +53206,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP post_incdec_object: /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; - if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) { + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { if (UNEXPECTED(Z_ISERROR_P(zptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); } else { @@ -52191,7 +53226,10 @@ post_incdec_object: zend_post_incdec_property_zval(zptr, prop_info, inc OPLINE_CC EXECUTE_DATA_CC); } } else { - zend_post_incdec_overloaded_property(object, property, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + zend_post_incdec_overloaded_property(zobj, name, cache_slot, inc OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } } while (0); @@ -52368,9 +53406,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -52389,17 +53429,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_r_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -52407,11 +53447,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER } } } - } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { - ZVAL_UNDEFINED_OP2(); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_r_copy: @@ -52510,9 +53557,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLE /* here we are sure we are dealing with an object */ do { zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; zval *retval; if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); cache_slot = CACHE_ADDR(opline->extended_value); if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { @@ -52531,17 +53580,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLE Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { + EXPECTED(zend_string_equal_content(p->key, name))))) { retval = &p->val; goto fetch_obj_is_copy; } } CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); } - retval = zend_hash_find_ex(zobj->properties, Z_STR_P(offset), 1); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); @@ -52549,9 +53598,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLE } } } + } else { + name = zval_get_tmp_string(offset, &tmp_name); } - retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (retval != EX_VAR(opline->result.var)) { fetch_obj_is_copy: @@ -52606,6 +53661,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ USE_OPLINE zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -52630,8 +53687,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -52721,7 +53779,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -52740,6 +53808,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ USE_OPLINE zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -52764,8 +53834,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -52855,7 +53926,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -52874,6 +53955,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ USE_OPLINE zend_free_op free_op_data; zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -52898,8 +53981,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -52989,7 +54073,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -53008,6 +54102,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ USE_OPLINE zval *object, *property, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; SAVE_OPLINE(); object = EX_VAR(opline->op1.var); @@ -53032,8 +54128,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } assign_object: + zobj = Z_OBJ_P(object); if (IS_CV == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) { + EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { void **cache_slot = CACHE_ADDR(opline->extended_value); uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); zend_object *zobj = Z_OBJ_P(object); @@ -53123,7 +54220,17 @@ fast_assign_obj: ZVAL_DEREF(value); } - property = Z_OBJ_HT_P(object)->write_property(object, property, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_get_tmp_string(property, &tmp_name); + } + + property = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), property); @@ -54070,7 +55177,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && - EXPECTED(fbc->type <= ZEND_USER_FUNCTION) && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(obj == orig_obj)) { CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); @@ -54088,26 +55194,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA } - call_info = ZEND_CALL_NESTED_FUNCTION; + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { - obj = NULL; if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) { - /* CV may be changed indirectly (e.g. when it's a reference) */ - call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; if (IS_CV == IS_CV) { GC_ADDREF(obj); /* For $this pointer */ } else if (free_op1 != object) { GC_ADDREF(obj); /* For $this pointer */ } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; } call = zend_vm_stack_push_call_frame(call_info, - fbc, opline->extended_value, called_scope, obj); + fbc, opline->extended_value, obj); call->prev_execute_data = EX(call); EX(call) = call; @@ -54309,7 +55417,7 @@ num_index_dim: if (IS_CV == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { offset++; } - Z_OBJ_HT_P(container)->unset_dimension(container, offset); + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { zend_throw_error(NULL, "Cannot unset string offsets"); } @@ -54325,6 +55433,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(Z zval *container; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(opline->op1.var EXECUTE_DATA_CC); @@ -54344,7 +55453,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(Z break; } } - Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } } while (0); @@ -54438,6 +55555,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV zval *container; int result; zval *offset; + zend_string *name, *tmp_name; SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); @@ -54462,9 +55580,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV } } + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_get_tmp_string(offset, &tmp_name); + } + result = (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } isset_object_finish: @@ -65512,13 +66640,22 @@ zend_leave_helper_SPEC_LABEL: ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value) { zend_execute_data *execute_data; + void *object_or_called_scope; + uint32_t call_info; if (EG(exception) != NULL) { return; } - execute_data = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, - (zend_function*)op_array, 0, zend_get_called_scope(EG(current_execute_data)), zend_get_this_object(EG(current_execute_data))); + object_or_called_scope = zend_get_this_object(EG(current_execute_data)); + if (EXPECTED(!object_or_called_scope)) { + object_or_called_scope = zend_get_called_scope(EG(current_execute_data)); + call_info = ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE; + } else { + call_info = ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE | ZEND_CALL_HAS_THIS; + } + execute_data = zend_vm_stack_push_call_frame(call_info, + (zend_function*)op_array, 0, object_or_called_scope); if (EG(current_execute_data)) { execute_data->symbol_table = zend_rebuild_symbol_table(); } else { diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index 30f0017cbd..5e6e98bb24 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -24,13 +24,22 @@ ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *ex) ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array, zval *return_value) { zend_execute_data *execute_data; + void *object_or_called_scope; + uint32_t call_info; if (EG(exception) != NULL) { return; } - execute_data = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, - (zend_function*)op_array, 0, zend_get_called_scope(EG(current_execute_data)), zend_get_this_object(EG(current_execute_data))); + object_or_called_scope = zend_get_this_object(EG(current_execute_data)); + if (EXPECTED(!object_or_called_scope)) { + object_or_called_scope = zend_get_called_scope(EG(current_execute_data)); + call_info = ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE; + } else { + call_info = ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE | ZEND_CALL_HAS_THIS; + } + execute_data = zend_vm_stack_push_call_frame(call_info, + (zend_function*)op_array, 0, object_or_called_scope); if (EG(current_execute_data)) { execute_data->symbol_table = zend_rebuild_symbol_table(); } else { diff --git a/Zend/zend_weakrefs.c b/Zend/zend_weakrefs.c index b4eaf437c8..f9918d1af3 100644 --- a/Zend/zend_weakrefs.c +++ b/Zend/zend_weakrefs.c @@ -112,13 +112,13 @@ static void zend_weakref_free(zend_object *zo) { #define zend_weakref_unsupported(thing) \ zend_throw_error(NULL, "WeakReference objects do not support " thing); -static zval* zend_weakref_no_write(zval *object, zval *member, zval *value, void **rtc) { +static zval* zend_weakref_no_write(zend_object *object, zend_string *member, zval *value, void **rtc) { zend_weakref_unsupported("properties"); return &EG(uninitialized_zval); } -static zval* zend_weakref_no_read(zval *object, zval *member, int type, void **rtc, zval *rv) { +static zval* zend_weakref_no_read(zend_object *object, zend_string *member, int type, void **rtc, zval *rv) { if (!EG(exception)) { zend_weakref_unsupported("properties"); } @@ -126,19 +126,19 @@ static zval* zend_weakref_no_read(zval *object, zval *member, int type, void **r return &EG(uninitialized_zval); } -static zval *zend_weakref_no_read_ptr(zval *object, zval *member, int type, void **rtc) { +static zval *zend_weakref_no_read_ptr(zend_object *object, zend_string *member, int type, void **rtc) { zend_weakref_unsupported("property references"); return NULL; } -static int zend_weakref_no_isset(zval *object, zval *member, int hse, void **rtc) { +static int zend_weakref_no_isset(zend_object *object, zend_string *member, int hse, void **rtc) { if (hse != 2) { zend_weakref_unsupported("properties"); } return 0; } -static void zend_weakref_no_unset(zval *object, zval *member, void **rtc) { +static void zend_weakref_no_unset(zend_object *object, zend_string *member, void **rtc) { zend_weakref_unsupported("properties"); } |