mirror of
https://github.com/php/php-src.git
synced 2024-11-25 02:44:58 +08:00
Merge branch 'phpng' into ast
Conflicts: Zend/zend_compile.c Zend/zend_compile.h Zend/zend_vm_def.h Zend/zend_vm_execute.h Some of dmitry's optimizations are not merged in yet!
This commit is contained in:
commit
d4d4b69e72
154
.gdbinit
154
.gdbinit
@ -48,104 +48,80 @@ define print_cvs
|
||||
end
|
||||
|
||||
define dump_bt
|
||||
set $t = $arg0
|
||||
while $t
|
||||
printf "[%p] ", $t
|
||||
set $fst = $t->function_state
|
||||
if $fst.function->common.function_name
|
||||
if $fst.arguments
|
||||
set $count = $fst.arguments->value.lval
|
||||
|
||||
if $t->object
|
||||
if $fst.function.common.scope
|
||||
printf "%s->", $fst.function.common.scope->name->val
|
||||
else
|
||||
if !$eg
|
||||
____executor_globals
|
||||
end
|
||||
|
||||
set $known_class = 0
|
||||
if $eg
|
||||
set $handlers = $t->object->handlers
|
||||
|
||||
if $handlers->get_class_entry == &zend_std_object_get_class
|
||||
set $known_class = 1
|
||||
|
||||
if $handlers.get_class_name
|
||||
if $handlers.get_class_name != &zend_std_object_get_class_name
|
||||
set $known_class = 0
|
||||
end
|
||||
end
|
||||
|
||||
if $known_class
|
||||
printf "%s->", $t->object->ce.name->val
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if !$known_class
|
||||
printf "(Unknown)->"
|
||||
end
|
||||
end
|
||||
set $ex = $arg0->prev_execute_data
|
||||
while $ex
|
||||
printf "[%p] ", $ex
|
||||
set $func = $ex->func
|
||||
if $func
|
||||
if $ex->object
|
||||
if $func->common.scope
|
||||
printf "%s->", $func->common.scope->name->val
|
||||
else
|
||||
if $fst.function.common.scope
|
||||
printf "%s::", $fst.function.common.scope->name->val
|
||||
end
|
||||
printf "%s->", $ex->object->ce.name->val
|
||||
end
|
||||
else
|
||||
if $func->common.scope
|
||||
printf "%s::", $func->common.scope->name->val
|
||||
end
|
||||
end
|
||||
|
||||
printf "%s(", $func->common.function_name->val
|
||||
|
||||
set $callFrameSize = (sizeof(zend_execute_data) + sizeof(zval) - 1) / sizeof(zval)
|
||||
|
||||
set $count = $ex->num_args
|
||||
set $arg = 0
|
||||
while $arg < $count
|
||||
if $arg > 0
|
||||
printf ", "
|
||||
end
|
||||
|
||||
printf "%s(", $fst.function->common.function_name->val
|
||||
while $count > 0
|
||||
set $zvalue = $fst.arguments - $count
|
||||
set $type = $zvalue->u1.v.type
|
||||
if $type == 1
|
||||
printf "NULL"
|
||||
end
|
||||
if $type == 2
|
||||
printf "false"
|
||||
end
|
||||
if $type == 3
|
||||
printf "true"
|
||||
end
|
||||
if $type == 4
|
||||
printf "%ld", $zvalue->value.lval
|
||||
end
|
||||
if $type == 5
|
||||
printf "%f", $zvalue->value.dval
|
||||
end
|
||||
if $type == 6
|
||||
____print_str $zvalue->value.str->val $zvalue->value.str->len
|
||||
end
|
||||
if $type == 7
|
||||
printf "array(%d)[%p]", $zvalue->value.arr->ht->nNumOfElements, $zvalue
|
||||
end
|
||||
if $type == 8
|
||||
printf "object[%p]", $zvalue
|
||||
end
|
||||
if $type == 9
|
||||
printf "resource(#%d)", $zvalue->value.lval
|
||||
end
|
||||
if $type == 10
|
||||
printf "reference"
|
||||
end
|
||||
if $type > 10
|
||||
printf "unknown type %d", $type
|
||||
end
|
||||
set $count = $count -1
|
||||
if $count > 0
|
||||
printf ", "
|
||||
end
|
||||
set $zvalue = (zval *) $ex + $callFrameSize + $arg
|
||||
set $type = $zvalue->u1.v.type
|
||||
if $type == 1
|
||||
printf "NULL"
|
||||
end
|
||||
printf ") "
|
||||
else
|
||||
printf "%s() ", $fst.function->common.function_name->val
|
||||
if $type == 2
|
||||
printf "false"
|
||||
end
|
||||
if $type == 3
|
||||
printf "true"
|
||||
end
|
||||
if $type == 4
|
||||
printf "%ld", $zvalue->value.lval
|
||||
end
|
||||
if $type == 5
|
||||
printf "%f", $zvalue->value.dval
|
||||
end
|
||||
if $type == 6
|
||||
____print_str $zvalue->value.str->val $zvalue->value.str->len
|
||||
end
|
||||
if $type == 7
|
||||
printf "array(%d)[%p]", $zvalue->value.arr->ht->nNumOfElements, $zvalue
|
||||
end
|
||||
if $type == 8
|
||||
printf "object[%p]", $zvalue
|
||||
end
|
||||
if $type == 9
|
||||
printf "resource(#%d)", $zvalue->value.lval
|
||||
end
|
||||
if $type == 10
|
||||
printf "reference"
|
||||
end
|
||||
if $type > 10
|
||||
printf "unknown type %d", $type
|
||||
end
|
||||
set $arg = $arg + 1
|
||||
end
|
||||
|
||||
printf ") "
|
||||
else
|
||||
printf "??? "
|
||||
end
|
||||
if $t->op_array != 0
|
||||
printf "%s:%d ", $t->op_array->filename->val, $t->opline->lineno
|
||||
if $func != 0
|
||||
printf "%s:%d ", $func->op_array.filename->val, $ex->opline->lineno
|
||||
end
|
||||
set $t = $t->prev_execute_data
|
||||
set $ex = $ex->prev_execute_data
|
||||
printf "\n"
|
||||
end
|
||||
end
|
||||
|
4
.gitattributes
vendored
4
.gitattributes
vendored
@ -22,6 +22,10 @@ sapi/nsapi/nsapi.c ident
|
||||
sapi/continuity/capi.c ident
|
||||
Zend/RFCs/002.txt ident
|
||||
Zend/RFCs/003.txt ident
|
||||
ext/exif/exif.c ident
|
||||
ext/ldap/ldap.c ident
|
||||
ext/pdo_pgsql/pdo_pgsql.c ident
|
||||
ext/tidy/tidy.c ident
|
||||
NEWS merge=NEWS
|
||||
UPGRADING merge=NEWS
|
||||
UPGRADING.INTERNALS merge=NEWS
|
||||
|
13
.travis.yml
13
.travis.yml
@ -12,6 +12,9 @@ notifications:
|
||||
email:
|
||||
on_failure: change
|
||||
|
||||
cache:
|
||||
- apt
|
||||
|
||||
env:
|
||||
global:
|
||||
- MYSQL_TEST_HOST=127.0.0.1
|
||||
@ -25,6 +28,12 @@ env:
|
||||
- ENABLE_MAINTAINER_ZTS=0 ENABLE_DEBUG=0
|
||||
- ENABLE_MAINTAINER_ZTS=1 ENABLE_DEBUG=1
|
||||
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -y libenchant-dev libaspell-dev libpspell-dev librecode-dev
|
||||
- sudo cp ./travis/de /var/lib/locales/supported.d/de
|
||||
- sudo dpkg-reconfigure locales
|
||||
|
||||
before_script:
|
||||
# Compile PHP
|
||||
- ./travis/compile.sh
|
||||
@ -36,4 +45,6 @@ before_script:
|
||||
- . ./travis/ext/pdo_pgsql/setup.sh
|
||||
|
||||
# Run PHPs run-tests.php
|
||||
script: ./sapi/cli/php run-tests.php -p `pwd`/sapi/cli/php -g "FAIL,XFAIL,BORK,WARN,LEAK,SKIP" --show-diff --set-timeout 120
|
||||
script:
|
||||
- ./sapi/cli/php run-tests.php -p `pwd`/sapi/cli/php -g "FAIL,XFAIL,BORK,WARN,LEAK,SKIP" --show-diff --set-timeout 120
|
||||
- ./sapi/cli/php sapi/phpdbg/tests/run-tests.php -diff2stdout --phpdbg sapi/phpdbg/phpdbg
|
||||
|
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
--------------------------------------------------------------------
|
||||
The PHP License, version 3.01
|
||||
Copyright (c) 1999 - 2012 The PHP Group. All rights reserved.
|
||||
Copyright (c) 1999 - 2014 The PHP Group. All rights reserved.
|
||||
--------------------------------------------------------------------
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -14,7 +14,7 @@ php_lcov.info: lcov-test
|
||||
@rm -rf lcov_data/
|
||||
@$(mkinstalldirs) lcov_data/
|
||||
@echo
|
||||
-@files=`find . -name \*.gcda -o -name \*.gcno -o -name \*.da -o -name \*.c -o -name \*.h | sed -e 's/^\.\///' | sed -e 's/\.gcda//g' -e 's/\.gcno//g' -e 's/\.da//g' | $(EGREP) $(LCOV_INCLUDE) | sed -e 's/.libs/ZZZZ/g' | sort | sed -e 's/ZZZZ/.libs/g' | uniq` ;\
|
||||
-@files=`find . -name \*.gcda -o -name \*.gcno -o -name \*.da -o -name \*.c -o -name \*.h | sed -e 's/^\.\///' | sed -e 's/\.gcda//g' -e 's/\.gcno//g' -e 's/\.da//g' | $(EGREP) $(LCOV_INCLUDE) | sed -e 's/.libs/zzzz/g' | sort | sed -e 's/zzzz/.libs/g' | uniq` ;\
|
||||
for x in $$files; do \
|
||||
echo -n . ;\
|
||||
y=`echo $$x | sed -e 's!\.libs/!!'`; \
|
||||
|
6
NEWS
6
NEWS
@ -2,11 +2,17 @@ PHP NEWS
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
?? ??? 20??, PHP 5.7.0
|
||||
|
||||
- CLI server:
|
||||
. Refactor MIME type handling to use a hash table instead of linear search.
|
||||
(Adam)
|
||||
. Update the MIME type list from the one shipped by Apache HTTPD. (Adam)
|
||||
|
||||
- DBA:
|
||||
. Fixed bug #62490 (dba_delete returns true on missing item (inifile)). (Mike)
|
||||
|
||||
- Standard:
|
||||
. Removed call_user_method() and call_user_method_array() functions. (Kalle)
|
||||
. Fix user session handlers (See rfc:session.user.return-value). (Sara)
|
||||
|
||||
- XSL:
|
||||
. Fixed bug #64776 (The XSLT extension is not thread safe). (Mike)
|
||||
|
0
README.namespaces
Executable file → Normal file
0
README.namespaces
Executable file → Normal file
@ -44,7 +44,7 @@ int(0)
|
||||
int(2)
|
||||
int(0)
|
||||
|
||||
Warning: Missing argument 2 for test3() in %s on line %d
|
||||
Warning: Missing argument 2 for test3()%s
|
||||
int(1)
|
||||
int(2)
|
||||
int(1)
|
||||
|
@ -85,7 +85,7 @@ bool(false)
|
||||
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: Missing argument 2 for test3() in %s on line %d
|
||||
Warning: Missing argument 2 for test3()%s
|
||||
int(1)
|
||||
|
||||
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
|
||||
|
@ -60,7 +60,7 @@ array(2) {
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: Missing argument 2 for test3() in %s on line %d
|
||||
Warning: Missing argument 2 for test3()%s
|
||||
array(1) {
|
||||
[0]=>
|
||||
int(1)
|
||||
|
11
Zend/tests/67468.phpt
Normal file
11
Zend/tests/67468.phpt
Normal file
@ -0,0 +1,11 @@
|
||||
--TEST--
|
||||
Bug #67468 (Segfault in highlight_file()/highlight_string())
|
||||
--SKIPIF--
|
||||
<?php if(!function_exists("leak")) print "skip only for debug builds"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
highlight_string("<?php __CLASS__;", true);
|
||||
echo "done";
|
||||
?>
|
||||
--EXPECT--
|
||||
done
|
@ -42,7 +42,6 @@ $page["name"] = A::A_ftk();
|
||||
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()
|
||||
3 %sbug38047.php:36 A_ftk()
|
||||
|
||||
Missing argument 1 for A::A_ftk(), called in %sbug38047.php on line 36 and defined
|
||||
1 %sbug38047.php:13 get_error_context()
|
||||
|
@ -25,7 +25,7 @@ try {
|
||||
--EXPECTF--
|
||||
1. exception 'Exception' with message 'aaa' in %sbug52361.php:5
|
||||
Stack trace:
|
||||
#0 %sbug52361.php(16): aaa->__destruct()
|
||||
#0 %sbug52361.php(13): aaa->__destruct()
|
||||
#1 %sbug52361.php(16): bbb()
|
||||
#2 {main}
|
||||
2. exception 'Exception' with message 'bbb' in %sbug52361.php:13
|
||||
|
73
Zend/tests/bug66608.phpt
Normal file
73
Zend/tests/bug66608.phpt
Normal file
@ -0,0 +1,73 @@
|
||||
--TEST--
|
||||
Bug #66608 (Incorrect behavior with nested "finally" blocks)
|
||||
--FILE--
|
||||
<?php
|
||||
function bar() {
|
||||
try {
|
||||
echo "1\n";
|
||||
try {
|
||||
} finally {
|
||||
try {
|
||||
} finally {
|
||||
}
|
||||
echo "2\n";
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
throw new Exception ("");
|
||||
} catch (Exception $ab) {
|
||||
echo "3\n";
|
||||
} finally {
|
||||
try {
|
||||
} finally {
|
||||
echo "4\n";
|
||||
try {
|
||||
} finally {
|
||||
}
|
||||
echo "5\n";
|
||||
}
|
||||
}
|
||||
echo "6\n";
|
||||
try {
|
||||
} finally {
|
||||
while (1) {
|
||||
try {
|
||||
echo "7\n";
|
||||
break;
|
||||
} finally {
|
||||
echo "8\n";
|
||||
}
|
||||
echo "bad";
|
||||
}
|
||||
echo "9\n";
|
||||
while (1) {
|
||||
try {
|
||||
throw new Exception("");
|
||||
} catch(Exception $e) {
|
||||
echo "10\n";
|
||||
break;
|
||||
} finally {
|
||||
echo "11\n";
|
||||
}
|
||||
echo "bak\n";
|
||||
}
|
||||
}
|
||||
echo "12\n";
|
||||
}
|
||||
echo "13\n";
|
||||
}
|
||||
bar();
|
||||
--EXPECT--
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
12
Zend/tests/bug67368.phpt
Normal file
12
Zend/tests/bug67368.phpt
Normal file
@ -0,0 +1,12 @@
|
||||
--TEST--
|
||||
Bug #67368 (Memory leak with immediately dereferenced array in class constant)
|
||||
--INI--
|
||||
report_memleaks=1
|
||||
--FILE--
|
||||
<?php
|
||||
class FooBar {
|
||||
const bar = ["bar" => 3]["bar"];
|
||||
}
|
||||
echo "okey";
|
||||
--EXPECTF--
|
||||
okey
|
10
Zend/tests/bug67436/a.php
Normal file
10
Zend/tests/bug67436/a.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
class a {
|
||||
public function test($arg = c::TESTCONSTANT) {
|
||||
echo __METHOD__ . "($arg)\n";
|
||||
}
|
||||
|
||||
static public function staticTest() {
|
||||
}
|
||||
}
|
8
Zend/tests/bug67436/b.php
Normal file
8
Zend/tests/bug67436/b.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
class b extends a {
|
||||
public function test() {
|
||||
echo __METHOD__ . "()\n";
|
||||
parent::test();
|
||||
}
|
||||
}
|
26
Zend/tests/bug67436/bug67436.phpt
Normal file
26
Zend/tests/bug67436/bug67436.phpt
Normal file
@ -0,0 +1,26 @@
|
||||
--TEST--
|
||||
bug67436: Autoloader isn't called if user defined error handler is present
|
||||
|
||||
--INI--
|
||||
error_reporting=
|
||||
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
spl_autoload_register(function($classname) {
|
||||
if (in_array($classname, array('a','b','c'))) {
|
||||
require_once ($classname . '.php');
|
||||
}
|
||||
});
|
||||
|
||||
set_error_handler(function ($errno, $errstr, $errfile, $errline) {
|
||||
}, error_reporting());
|
||||
|
||||
a::staticTest();
|
||||
|
||||
$b = new b();
|
||||
$b->test();
|
||||
|
||||
--EXPECT--
|
||||
b::test()
|
||||
a::test(c::TESTCONSTANT)
|
24
Zend/tests/bug67436/bug67436_nohandler.phpt
Normal file
24
Zend/tests/bug67436/bug67436_nohandler.phpt
Normal file
@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
bug67436: E_STRICT instead of custom error handler
|
||||
|
||||
--INI--
|
||||
error_reporting=-1
|
||||
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
spl_autoload_register(function($classname) {
|
||||
if (in_array($classname, array('a','b','c'))) {
|
||||
require_once ($classname . '.php');
|
||||
}
|
||||
});
|
||||
|
||||
a::staticTest();
|
||||
|
||||
$b = new b();
|
||||
$b->test();
|
||||
|
||||
--EXPECTF--
|
||||
Strict Standards: Declaration of b::test() should be compatible with a::test($arg = c::TESTCONSTANT) in %s/bug67436/b.php on line %d
|
||||
b::test()
|
||||
a::test(c::TESTCONSTANT)
|
5
Zend/tests/bug67436/c.php
Normal file
5
Zend/tests/bug67436/c.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
class c {
|
||||
const TESTCONSTANT = "c::TESTCONSTANT";
|
||||
}
|
@ -13,6 +13,6 @@ call_user_func(array('foo', 'teste'));
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Strict Standards: call_user_func() expects parameter 1 to be a valid callback, non-static method foo::teste() should not be called statically in %s on line %d
|
||||
Strict Standards: %son-static method foo::teste() should not be called statically in %s on line %d
|
||||
|
||||
Fatal error: Using $this when not in object context in %s on line %d
|
||||
|
@ -18,7 +18,7 @@ var_dump(call_user_func(array('foo', 'teste')));
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Strict Standards: call_user_func() expects parameter 1 to be a valid callback, non-static method foo::teste() should not be called statically in %s on line %d
|
||||
Strict Standards: %son-static method foo::teste() should not be called statically in %s on line %d
|
||||
%string|unicode%(1) "x"
|
||||
array(1) {
|
||||
[0]=>
|
||||
|
22
Zend/tests/closure_049.phpt
Normal file
22
Zend/tests/closure_049.phpt
Normal file
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Closure 049: static::class in static closure in non-static method.
|
||||
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class A {
|
||||
function foo() {
|
||||
$f = static function() {
|
||||
return static::class;
|
||||
};
|
||||
return $f();
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {}
|
||||
|
||||
$b = new B;
|
||||
|
||||
var_dump($b->foo());
|
||||
--EXPECT--
|
||||
string(1) "B"
|
22
Zend/tests/closure_050.phpt
Normal file
22
Zend/tests/closure_050.phpt
Normal file
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Closure 050: static::class in non-static closure in non-static method.
|
||||
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class A {
|
||||
function foo() {
|
||||
$f = function() {
|
||||
return static::class;
|
||||
};
|
||||
return $f();
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {}
|
||||
|
||||
$b = new B;
|
||||
var_dump($b->foo());
|
||||
|
||||
--EXPECT--
|
||||
string(1) "B"
|
21
Zend/tests/closure_051.phpt
Normal file
21
Zend/tests/closure_051.phpt
Normal file
@ -0,0 +1,21 @@
|
||||
--TEST--
|
||||
Closure 051: static::class in static closure in static method.
|
||||
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class A {
|
||||
static function foo() {
|
||||
$f = static function() {
|
||||
return static::class;
|
||||
};
|
||||
return $f();
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {}
|
||||
|
||||
var_dump(B::foo());
|
||||
|
||||
--EXPECT--
|
||||
string(1) "B"
|
21
Zend/tests/closure_052.phpt
Normal file
21
Zend/tests/closure_052.phpt
Normal file
@ -0,0 +1,21 @@
|
||||
--TEST--
|
||||
Closure 052: static::class in non-static closure in static method.
|
||||
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class A {
|
||||
static function foo() {
|
||||
$f = function() {
|
||||
return static::class;
|
||||
};
|
||||
return $f();
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {}
|
||||
|
||||
var_dump(B::foo());
|
||||
|
||||
--EXPECT--
|
||||
string(1) "B"
|
22
Zend/tests/closure_053.phpt
Normal file
22
Zend/tests/closure_053.phpt
Normal file
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Closure 053: self::class in static closure in non-static method.
|
||||
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class A {
|
||||
function foo() {
|
||||
$f = static function() {
|
||||
return self::class;
|
||||
};
|
||||
return $f();
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {}
|
||||
|
||||
$b = new B;
|
||||
var_dump($b->foo());
|
||||
|
||||
--EXPECT--
|
||||
string(1) "A"
|
22
Zend/tests/closure_054.phpt
Normal file
22
Zend/tests/closure_054.phpt
Normal file
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Closure 054: self::class in non-static closure in non-static method.
|
||||
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class A {
|
||||
function foo() {
|
||||
$f = function() {
|
||||
return self::class;
|
||||
};
|
||||
return $f();
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {}
|
||||
|
||||
$b = new B;
|
||||
var_dump($b->foo());
|
||||
|
||||
--EXPECT--
|
||||
string(1) "A"
|
21
Zend/tests/closure_055.phpt
Normal file
21
Zend/tests/closure_055.phpt
Normal file
@ -0,0 +1,21 @@
|
||||
--TEST--
|
||||
Closure 055: self::class in static closure in static method.
|
||||
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class A {
|
||||
static function foo() {
|
||||
$f = static function() {
|
||||
return self::class;
|
||||
};
|
||||
return $f();
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {}
|
||||
|
||||
var_dump(B::foo());
|
||||
|
||||
--EXPECT--
|
||||
string(1) "A"
|
21
Zend/tests/closure_056.phpt
Normal file
21
Zend/tests/closure_056.phpt
Normal file
@ -0,0 +1,21 @@
|
||||
--TEST--
|
||||
Closure 056: self::class in non-static closure in static method.
|
||||
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class A {
|
||||
static function foo() {
|
||||
$f = function() {
|
||||
return self::class;
|
||||
};
|
||||
return $f();
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {}
|
||||
|
||||
var_dump(B::foo());
|
||||
|
||||
--EXPECT--
|
||||
string(1) "A"
|
37
Zend/tests/closure_bug66622.phpt
Normal file
37
Zend/tests/closure_bug66622.phpt
Normal file
@ -0,0 +1,37 @@
|
||||
--TEST--
|
||||
Bug 66622: Closures do not correctly capture the late bound class (static::) in some cases
|
||||
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
static function name() { return 'A'; }
|
||||
function foo() {
|
||||
$fn = function() { return static::name(); };
|
||||
echo static::name() . ' vs ' . $fn() . "\n";
|
||||
}
|
||||
function bar() {
|
||||
$fn = static function() { return static::name(); };
|
||||
echo static::name() . ' vs ' . $fn() . "\n";
|
||||
}
|
||||
static function baz() {
|
||||
$fn = function() { return static::name(); };
|
||||
echo static::name() . ' vs ' . $fn() . "\n";
|
||||
}
|
||||
}
|
||||
class B extends A {
|
||||
static function name() { return 'B'; }
|
||||
}
|
||||
|
||||
function test() {
|
||||
(new B)->foo();
|
||||
(new B)->bar();
|
||||
(new B)->baz();
|
||||
B::baz();
|
||||
}
|
||||
test();
|
||||
|
||||
--EXPECT--
|
||||
B vs B
|
||||
B vs B
|
||||
B vs B
|
||||
B vs B
|
35
Zend/tests/constant_expressions_arrays.phpt
Normal file
35
Zend/tests/constant_expressions_arrays.phpt
Normal file
@ -0,0 +1,35 @@
|
||||
--TEST--
|
||||
Constant expressions with arrays
|
||||
--FILE--
|
||||
<?php
|
||||
const a = [1,2,[3,[4]]];
|
||||
const b = a[0];
|
||||
const c = a[2][0];
|
||||
const d = a[2];
|
||||
const e = ["string" => [1]]["string"][0];
|
||||
|
||||
var_dump(b, c, e);
|
||||
|
||||
function test ($a = d[1][0]) {
|
||||
var_dump($a);
|
||||
}
|
||||
|
||||
test();
|
||||
|
||||
class foo {
|
||||
const bar = [1][0];
|
||||
}
|
||||
|
||||
var_dump(foo::bar);
|
||||
|
||||
var_dump(a); // Eventually allow that later with array dereferencing of constants
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
int(1)
|
||||
int(3)
|
||||
int(1)
|
||||
int(4)
|
||||
int(1)
|
||||
|
||||
Fatal error: Arrays are not allowed in constants at run-time in %s on line %d
|
15
Zend/tests/constant_expressions_self_referencing_array.phpt
Normal file
15
Zend/tests/constant_expressions_self_referencing_array.phpt
Normal file
@ -0,0 +1,15 @@
|
||||
--TEST--
|
||||
Self-referencing constant expression (part of a constant AST)
|
||||
--XFAIL--
|
||||
Not yet fixed, to be fixed for PHP 5.6
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
const FOO = [self::BAR];
|
||||
const BAR = [self::FOO];
|
||||
}
|
||||
var_dump(A::FOO);
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot declare self-referencing constant 'self::FOO' in %s on line %d
|
||||
|
@ -76,4 +76,4 @@ NULL
|
||||
|
||||
Notice: Undefined offset: 3 in %s on line %d
|
||||
|
||||
Fatal error: Call to a member function bar() on a non-object in %s on line %d
|
||||
Fatal error: Call to a member function bar() on null in %s on line %d
|
||||
|
@ -105,7 +105,7 @@ Hello, you
|
||||
Notice: Undefined variable: this in %s on line %d
|
||||
NULL
|
||||
|
||||
Strict Standards: call_user_func() expects parameter 1 to be a valid callback, non-static method Hello::world() should not be called statically in %s on line %d
|
||||
Strict Standards: %son-static method Hello::world() should not be called statically in %s on line %d
|
||||
Hello, you
|
||||
|
||||
Notice: Undefined variable: this in %s on line %d
|
||||
|
@ -34,4 +34,4 @@ unset($bar);
|
||||
var_dump(gc_collect_cycles());
|
||||
?>
|
||||
--EXPECT--
|
||||
int(2)
|
||||
int(3)
|
||||
|
@ -28,6 +28,7 @@ Stack trace:
|
||||
|
||||
Next exception 'Exception' with message 'foobar' in %sgc_030.php:%d
|
||||
Stack trace:
|
||||
#0 %sgc_030.php(%d): foo->__destruct()
|
||||
#1 {main}
|
||||
#0 [internal function]: foo->__destruct()
|
||||
#1 %sgc_030.php(%d): gc_collect_cycles()
|
||||
#2 {main}
|
||||
thrown in %sgc_030.php on line %d
|
||||
|
@ -11,26 +11,26 @@ $b =& $a;
|
||||
$a[0][0] = $a;
|
||||
debug_zval_dump($a);
|
||||
?>
|
||||
--EXPECT--
|
||||
array(1) refcount(1){
|
||||
--EXPECTF--
|
||||
array(1) refcount(%d){
|
||||
[0]=>
|
||||
array(1) refcount(3){
|
||||
array(1) refcount(%d){
|
||||
[0]=>
|
||||
array(1) refcount(3){
|
||||
array(1) refcount(%d){
|
||||
[0]=>
|
||||
*RECURSION*
|
||||
}
|
||||
}
|
||||
}
|
||||
array(1) refcount(1){
|
||||
array(1) refcount(%d){
|
||||
[0]=>
|
||||
array(1) refcount(3){
|
||||
array(1) refcount(%d){
|
||||
[0]=>
|
||||
array(1) refcount(1){
|
||||
array(1) refcount(%d){
|
||||
[0]=>
|
||||
array(1) refcount(3){
|
||||
array(1) refcount(%d){
|
||||
[0]=>
|
||||
array(1) refcount(1){
|
||||
array(1) refcount(%d){
|
||||
[0]=>
|
||||
*RECURSION*
|
||||
}
|
||||
|
19
Zend/tests/generators/bug67497.phpt
Normal file
19
Zend/tests/generators/bug67497.phpt
Normal file
@ -0,0 +1,19 @@
|
||||
--TEST--
|
||||
Bug #67467: eval with parse error causes segmentation fault in generator
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function gen() {
|
||||
$a = 1;
|
||||
yield $a;
|
||||
}
|
||||
|
||||
@eval('abc');
|
||||
|
||||
$values = gen();
|
||||
$values->next();
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECT--
|
||||
===DONE===
|
@ -12,7 +12,6 @@ foreach ($gen as &$value) { }
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught exception 'Exception' with message 'You can only iterate a generator by-reference if it declared that it yields by-reference' in %s:%d
|
||||
Stack trace:
|
||||
#0 %s(%d): unknown()
|
||||
#1 {main}
|
||||
#0 {main}
|
||||
thrown in %s on line %d
|
||||
|
||||
|
@ -56,7 +56,6 @@ Stack trace:
|
||||
|
||||
exception 'Exception' with message 'Cannot traverse an already closed generator' in %s:%d
|
||||
Stack trace:
|
||||
#0 %s(%d): unknown()
|
||||
#1 {main}
|
||||
#0 {main}
|
||||
|
||||
in generator
|
||||
|
@ -35,7 +35,7 @@ object(foo)#%d (0) {
|
||||
object(foo)#%d (0) {
|
||||
}
|
||||
|
||||
Strict Standards: call_user_func() expects parameter 1 to be a valid callback, non-static method foo::test() should not be called statically in %s on line %d
|
||||
Strict Standards: %son-static method foo::test() should not be called statically in %s on line %d
|
||||
|
||||
Strict Standards: Non-static method bar::show() should not be called statically in %s on line %d
|
||||
object(foo)#%d (0) {
|
||||
|
15
Zend/tests/try_finally_011.phpt
Normal file
15
Zend/tests/try_finally_011.phpt
Normal file
@ -0,0 +1,15 @@
|
||||
--TEST--
|
||||
Try finally (segfault with empty break)
|
||||
--FILE--
|
||||
<?php
|
||||
function foo () {
|
||||
try {
|
||||
break;
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
|
||||
foo();
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot break/continue 1 level in %stry_finally_011.php on line %d
|
82
Zend/zend.c
82
Zend/zend.c
@ -212,11 +212,10 @@ static void print_flat_hash(HashTable *ht TSRMLS_DC) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy) /* {{{ */
|
||||
ZEND_API int zend_make_printable_zval(zval *expr, zval *expr_copy) /* {{{ */
|
||||
{
|
||||
if (Z_TYPE_P(expr) == IS_STRING) {
|
||||
*use_copy = 0;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
again:
|
||||
@ -249,14 +248,12 @@ again:
|
||||
TSRMLS_FETCH();
|
||||
|
||||
if (Z_OBJ_HANDLER_P(expr, cast_object)) {
|
||||
zval val;
|
||||
|
||||
ZVAL_DUP_DEREF(&val, expr);
|
||||
if (Z_OBJ_HANDLER_P(expr, cast_object)(&val, expr_copy, IS_STRING TSRMLS_CC) == SUCCESS) {
|
||||
zval_ptr_dtor(&val);
|
||||
Z_ADDREF_P(expr);
|
||||
if (Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING TSRMLS_CC) == SUCCESS) {
|
||||
zval_ptr_dtor(expr);
|
||||
break;
|
||||
}
|
||||
zval_ptr_dtor(&val);
|
||||
zval_ptr_dtor(expr);
|
||||
}
|
||||
if (!Z_OBJ_HANDLER_P(expr, cast_object) && Z_OBJ_HANDLER_P(expr, get)) {
|
||||
zval rv;
|
||||
@ -264,14 +261,12 @@ again:
|
||||
|
||||
Z_ADDREF_P(z);
|
||||
if (Z_TYPE_P(z) != IS_OBJECT) {
|
||||
zend_make_printable_zval(z, expr_copy, use_copy);
|
||||
if (*use_copy) {
|
||||
if (zend_make_printable_zval(z, expr_copy)) {
|
||||
zval_ptr_dtor(z);
|
||||
} else {
|
||||
ZVAL_ZVAL(expr_copy, z, 0, 1);
|
||||
*use_copy = 1;
|
||||
}
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
zval_ptr_dtor(z);
|
||||
}
|
||||
@ -287,8 +282,7 @@ again:
|
||||
expr = Z_REFVAL_P(expr);
|
||||
if (Z_TYPE_P(expr) == IS_STRING) {
|
||||
ZVAL_STR(expr_copy, STR_COPY(Z_STR_P(expr)));
|
||||
*use_copy = 1;
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
goto again;
|
||||
break;
|
||||
@ -297,7 +291,7 @@ again:
|
||||
convert_to_string(expr_copy);
|
||||
break;
|
||||
}
|
||||
*use_copy = 1;
|
||||
return 1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -561,7 +555,6 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals TSRMLS
|
||||
EG(lambda_count) = 0;
|
||||
ZVAL_UNDEF(&EG(user_error_handler));
|
||||
ZVAL_UNDEF(&EG(user_exception_handler));
|
||||
EG(in_execution) = 0;
|
||||
EG(in_autoload) = NULL;
|
||||
EG(current_execute_data) = NULL;
|
||||
EG(current_module) = NULL;
|
||||
@ -882,7 +875,7 @@ ZEND_API void _zend_bailout(char *filename, uint lineno) /* {{{ */
|
||||
}
|
||||
CG(unclean_shutdown) = 1;
|
||||
CG(active_class_entry) = NULL;
|
||||
CG(in_compilation) = EG(in_execution) = 0;
|
||||
CG(in_compilation) = 0;
|
||||
EG(current_execute_data) = NULL;
|
||||
LONGJMP(*EG(bailout), FAILURE);
|
||||
}
|
||||
@ -940,8 +933,7 @@ void zend_call_destructors(TSRMLS_D) /* {{{ */
|
||||
ZEND_API void zend_deactivate(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
/* we're no longer executing anything */
|
||||
EG(opline_ptr) = NULL;
|
||||
EG(active_symbol_table) = NULL;
|
||||
EG(current_execute_data) = NULL;
|
||||
|
||||
zend_try {
|
||||
shutdown_scanner(TSRMLS_C);
|
||||
@ -1038,10 +1030,14 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
|
||||
zend_stack foreach_copy_stack;
|
||||
zend_stack list_stack;
|
||||
zend_stack context_stack;
|
||||
zend_array *symbol_table;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
/* Report about uncaught exception in case of fatal errors */
|
||||
if (EG(exception)) {
|
||||
zend_execute_data *ex;
|
||||
zend_op *opline;
|
||||
|
||||
switch (type) {
|
||||
case E_CORE_ERROR:
|
||||
case E_ERROR:
|
||||
@ -1049,13 +1045,19 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
|
||||
case E_PARSE:
|
||||
case E_COMPILE_ERROR:
|
||||
case E_USER_ERROR:
|
||||
if (zend_is_executing(TSRMLS_C)) {
|
||||
error_lineno = zend_get_executed_lineno(TSRMLS_C);
|
||||
ex = EG(current_execute_data);
|
||||
opline = NULL;
|
||||
while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
|
||||
ex = ex->prev_execute_data;
|
||||
}
|
||||
if (ex && ex->opline->opcode == ZEND_HANDLE_EXCEPTION &&
|
||||
EG(opline_before_exception)) {
|
||||
opline = EG(opline_before_exception);
|
||||
}
|
||||
zend_exception_error(EG(exception), E_WARNING TSRMLS_CC);
|
||||
EG(exception) = NULL;
|
||||
if (zend_is_executing(TSRMLS_C) && EG(opline_ptr)) {
|
||||
active_opline->lineno = error_lineno;
|
||||
if (opline) {
|
||||
ex->opline = opline;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -1088,7 +1090,12 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
|
||||
error_lineno = zend_get_compiled_lineno(TSRMLS_C);
|
||||
} else if (zend_is_executing(TSRMLS_C)) {
|
||||
error_filename = zend_get_executed_filename(TSRMLS_C);
|
||||
error_lineno = zend_get_executed_lineno(TSRMLS_C);
|
||||
if (error_filename[0] == '[') { /* [no active file] */
|
||||
error_filename = NULL;
|
||||
error_lineno = 0;
|
||||
} else {
|
||||
error_lineno = zend_get_executed_lineno(TSRMLS_C);
|
||||
}
|
||||
} else {
|
||||
error_filename = NULL;
|
||||
error_lineno = 0;
|
||||
@ -1162,16 +1169,14 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
|
||||
|
||||
ZVAL_LONG(¶ms[3], error_lineno);
|
||||
|
||||
if (!EG(active_symbol_table)) {
|
||||
zend_rebuild_symbol_table(TSRMLS_C);
|
||||
}
|
||||
symbol_table = zend_rebuild_symbol_table(TSRMLS_C);
|
||||
|
||||
/* during shutdown the symbol table table can be still null */
|
||||
if (!EG(active_symbol_table)) {
|
||||
if (!symbol_table) {
|
||||
ZVAL_NULL(¶ms[4]);
|
||||
} else {
|
||||
ZVAL_NEW_ARR(¶ms[4]);
|
||||
zend_array_dup(Z_ARRVAL(params[4]), &EG(active_symbol_table)->ht);
|
||||
zend_array_dup(Z_ARRVAL(params[4]), &symbol_table->ht);
|
||||
}
|
||||
|
||||
ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler));
|
||||
@ -1238,7 +1243,8 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
|
||||
if (type == E_PARSE) {
|
||||
/* eval() errors do not affect exit_status */
|
||||
if (!(EG(current_execute_data) &&
|
||||
EG(current_execute_data)->opline &&
|
||||
EG(current_execute_data)->func &&
|
||||
ZEND_USER_CODE(EG(current_execute_data)->func->type) &&
|
||||
EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL &&
|
||||
EG(current_execute_data)->opline->extended_value == ZEND_EVAL)) {
|
||||
EG(exit_status) = 255;
|
||||
@ -1283,7 +1289,7 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval *retval, int file_cou
|
||||
va_list files;
|
||||
int i;
|
||||
zend_file_handle *file_handle;
|
||||
zend_op_array *orig_op_array = EG(active_op_array);
|
||||
zend_op_array *op_array;
|
||||
long orig_interactive = CG(interactive);
|
||||
|
||||
va_start(files, file_count);
|
||||
@ -1301,13 +1307,13 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval *retval, int file_cou
|
||||
}
|
||||
}
|
||||
|
||||
EG(active_op_array) = zend_compile_file(file_handle, type TSRMLS_CC);
|
||||
op_array = zend_compile_file(file_handle, type TSRMLS_CC);
|
||||
if (file_handle->opened_path) {
|
||||
zend_hash_str_add_empty_element(&EG(included_files), file_handle->opened_path, strlen(file_handle->opened_path));
|
||||
}
|
||||
zend_destroy_file_handle(file_handle TSRMLS_CC);
|
||||
if (EG(active_op_array)) {
|
||||
zend_execute(EG(active_op_array), retval TSRMLS_CC);
|
||||
if (op_array) {
|
||||
zend_execute(op_array, retval TSRMLS_CC);
|
||||
zend_exception_restore(TSRMLS_C);
|
||||
if (EG(exception)) {
|
||||
if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
|
||||
@ -1334,17 +1340,15 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval *retval, int file_cou
|
||||
zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
destroy_op_array(EG(active_op_array) TSRMLS_CC);
|
||||
efree(EG(active_op_array));
|
||||
destroy_op_array(op_array TSRMLS_CC);
|
||||
efree(op_array);
|
||||
} else if (type==ZEND_REQUIRE) {
|
||||
va_end(files);
|
||||
EG(active_op_array) = orig_op_array;
|
||||
CG(interactive) = orig_interactive;
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
va_end(files);
|
||||
EG(active_op_array) = orig_op_array;
|
||||
CG(interactive) = orig_interactive;
|
||||
|
||||
return SUCCESS;
|
||||
|
141
Zend/zend.h
141
Zend/zend.h
@ -179,6 +179,14 @@ char *alloca ();
|
||||
# define ZEND_ATTRIBUTE_DEPRECATED
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && ZEND_GCC_VERSION >= 4003
|
||||
# define ZEND_ATTRIBUTE_UNUSED __attribute__((unused))
|
||||
# define ZEND_ATTRIBUTE_UNUSED_LABEL __attribute__((cold, unused));
|
||||
#else
|
||||
# define ZEND_ATTRIBUTE_UNUSED
|
||||
# define ZEND_ATTRIBUTE_UNUSED_LABEL
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && ZEND_GCC_VERSION >= 3004 && defined(__i386__)
|
||||
# define ZEND_FASTCALL __attribute__((fastcall))
|
||||
#elif defined(_MSC_VER) && defined(_M_IX86)
|
||||
@ -290,8 +298,9 @@ typedef enum {
|
||||
|
||||
#define USED_RET() \
|
||||
(!EG(current_execute_data) || \
|
||||
!EG(current_execute_data)->opline || \
|
||||
!(EG(current_execute_data)->opline->result_type & EXT_TYPE_UNUSED))
|
||||
!EG(current_execute_data)->prev_execute_data || \
|
||||
!ZEND_USER_CODE(EG(current_execute_data)->prev_execute_data->func->common.type) || \
|
||||
!(EG(current_execute_data)->prev_execute_data->opline->result_type & EXT_TYPE_UNUSED))
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 3 && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX) && !defined(__osf__)
|
||||
void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((noreturn));
|
||||
@ -317,6 +326,21 @@ void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((nore
|
||||
#define Z_ADDREF(z) Z_ADDREF_P(&(z))
|
||||
#define Z_DELREF(z) Z_DELREF_P(&(z))
|
||||
|
||||
#define Z_TRY_ADDREF_P(pz) do { \
|
||||
if (Z_REFCOUNTED_P((pz))) { \
|
||||
Z_ADDREF_P((pz)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define Z_TRY_DELREF_P(pz) do { \
|
||||
if (Z_REFCOUNTED_P((pz))) { \
|
||||
Z_DELREF_P((pz)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define Z_TRY_ADDREF(z) Z_TRY_ADDREF_P(&(z))
|
||||
#define Z_TRY_DELREF(z) Z_TRY_DELREF_P(&(z))
|
||||
|
||||
#if ZEND_DEBUG
|
||||
#define zend_always_inline inline
|
||||
#define zend_never_inline
|
||||
@ -339,8 +363,8 @@ void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((nore
|
||||
#endif /* ZEND_DEBUG */
|
||||
|
||||
#if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX)
|
||||
# define EXPECTED(condition) __builtin_expect(condition, 1)
|
||||
# define UNEXPECTED(condition) __builtin_expect(condition, 0)
|
||||
# define EXPECTED(condition) __builtin_expect(!(!(condition)), 1)
|
||||
# define UNEXPECTED(condition) __builtin_expect(!(!(condition)), 0)
|
||||
#else
|
||||
# define EXPECTED(condition) (condition)
|
||||
# define UNEXPECTED(condition) (condition)
|
||||
@ -379,7 +403,7 @@ void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((nore
|
||||
#include "zend_string.h"
|
||||
|
||||
static zend_always_inline zend_uint zval_refcount_p(zval* pz) {
|
||||
ZEND_ASSERT(Z_REFCOUNTED_P(pz));
|
||||
ZEND_ASSERT(Z_REFCOUNTED_P(pz) || Z_IMMUTABLE_P(pz));
|
||||
return GC_REFCOUNT(Z_COUNTED_P(pz));
|
||||
}
|
||||
|
||||
@ -585,7 +609,7 @@ END_EXTERN_C()
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
ZEND_API char *get_zend_version(void);
|
||||
ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy);
|
||||
ZEND_API int zend_make_printable_zval(zval *expr, zval *expr_copy);
|
||||
ZEND_API int zend_print_zval(zval *expr, int indent TSRMLS_DC);
|
||||
ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC);
|
||||
ZEND_API void zend_print_zval_r(zval *expr, int indent TSRMLS_DC);
|
||||
@ -707,13 +731,11 @@ END_EXTERN_C()
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ZVAL_DUP_DEREF(z, v) \
|
||||
do { \
|
||||
zval *__z1 = (z); \
|
||||
zval *__z2 = (v); \
|
||||
ZVAL_DEREF(__z2); \
|
||||
ZVAL_COPY_VALUE(__z1, __z2); \
|
||||
zval_opt_copy_ctor(__z1); \
|
||||
#define ZVAL_MAKE_REF(zv) do { \
|
||||
zval *__zv = (zv); \
|
||||
if (!Z_ISREF_P(__zv)) { \
|
||||
ZVAL_NEW_REF(__zv, __zv); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ZVAL_UNREF(z) do { \
|
||||
@ -725,19 +747,52 @@ END_EXTERN_C()
|
||||
efree(ref); \
|
||||
} while (0)
|
||||
|
||||
#define SEPARATE_STRING(zv) do { \
|
||||
zval *_zv = (zv); \
|
||||
if (Z_REFCOUNTED_P(_zv) && \
|
||||
Z_REFCOUNT_P(_zv) > 1) { \
|
||||
Z_DELREF_P(_zv); \
|
||||
zval_copy_ctor_func(_zv); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SEPARATE_ARRAY(zv) do { \
|
||||
zval *_zv = (zv); \
|
||||
if (Z_REFCOUNT_P(_zv) > 1) { \
|
||||
if (!Z_IMMUTABLE_P(_zv)) { \
|
||||
Z_DELREF_P(_zv); \
|
||||
} \
|
||||
zval_copy_ctor_func(_zv); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SEPARATE_ZVAL_NOREF(zv) do { \
|
||||
zval *_zv = (zv); \
|
||||
if (Z_COPYABLE_P(_zv) || \
|
||||
Z_IMMUTABLE_P(_zv)) { \
|
||||
if (Z_REFCOUNT_P(_zv) > 1) { \
|
||||
if (!Z_IMMUTABLE_P(_zv)) { \
|
||||
Z_DELREF_P(_zv); \
|
||||
} \
|
||||
zval_copy_ctor_func(_zv); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SEPARATE_ZVAL(zv) do { \
|
||||
zval *_zv = (zv); \
|
||||
if (Z_REFCOUNTED_P(_zv) || \
|
||||
Z_IMMUTABLE_P(_zv)) { \
|
||||
if (Z_IMMUTABLE_P(_zv)) { \
|
||||
zval_copy_ctor_func(_zv); \
|
||||
} else if (Z_REFCOUNT_P(_zv) > 1) { \
|
||||
if (Z_ISREF_P(_zv)) { \
|
||||
if (Z_REFCOUNT_P(_zv) > 1) { \
|
||||
if (Z_COPYABLE_P(_zv) || \
|
||||
Z_IMMUTABLE_P(_zv)) { \
|
||||
if (!Z_IMMUTABLE_P(_zv)) { \
|
||||
Z_DELREF_P(_zv); \
|
||||
} \
|
||||
zval_copy_ctor_func(_zv); \
|
||||
} else if (Z_ISREF_P(_zv)) { \
|
||||
Z_DELREF_P(_zv); \
|
||||
ZVAL_DUP(_zv, Z_REFVAL_P(_zv)); \
|
||||
} else if (Z_COPYABLE_P(_zv)) { \
|
||||
Z_DELREF_P(_zv); \
|
||||
zval_copy_ctor_func(_zv); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
@ -745,51 +800,21 @@ END_EXTERN_C()
|
||||
|
||||
#define SEPARATE_ZVAL_IF_NOT_REF(zv) do { \
|
||||
zval *_zv = (zv); \
|
||||
if (!Z_ISREF_P(_zv)) { \
|
||||
if (Z_COPYABLE_P(_zv) || \
|
||||
Z_IMMUTABLE_P(_zv)) { \
|
||||
if (Z_IMMUTABLE_P(_zv)) { \
|
||||
zval_copy_ctor_func(_zv); \
|
||||
} else if (Z_REFCOUNT_P(_zv) > 1) { \
|
||||
if (Z_COPYABLE_P(_zv) || \
|
||||
Z_IMMUTABLE_P(_zv)) { \
|
||||
if (Z_REFCOUNT_P(_zv) > 1) { \
|
||||
if (!Z_IMMUTABLE_P(_zv)) { \
|
||||
Z_DELREF_P(_zv); \
|
||||
zval_copy_ctor_func(_zv); \
|
||||
} \
|
||||
zval_copy_ctor_func(_zv); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SEPARATE_ZVAL_IF_REF(zv) do { \
|
||||
zval *__zv = (zv); \
|
||||
if (Z_ISREF_P(__zv)) { \
|
||||
if (Z_REFCOUNT_P(__zv) == 1) { \
|
||||
ZVAL_UNREF(__zv); \
|
||||
} else { \
|
||||
Z_DELREF_P(__zv); \
|
||||
ZVAL_DUP(__zv, Z_REFVAL_P(__zv)); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SEPARATE_ZVAL_TO_MAKE_IS_REF(zv) do { \
|
||||
zval *__zv = (zv); \
|
||||
if (!Z_ISREF_P(__zv)) { \
|
||||
if (Z_COPYABLE_P(__zv) && \
|
||||
Z_REFCOUNT_P(__zv) > 1) { \
|
||||
Z_DELREF_P(__zv); \
|
||||
zval_copy_ctor_func(__zv); \
|
||||
} \
|
||||
ZVAL_NEW_REF(__zv, __zv); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SEPARATE_ARG_IF_REF(varptr) do { \
|
||||
zval *_varptr = (varptr); \
|
||||
if (Z_ISREF_P(_varptr)) { \
|
||||
zval tmp; \
|
||||
ZVAL_DUP(&tmp, Z_REFVAL_P(_varptr)); \
|
||||
varptr = &tmp; \
|
||||
} else if (Z_REFCOUNTED_P(_varptr)) { \
|
||||
Z_ADDREF_P(_varptr); \
|
||||
ZVAL_DEREF(varptr); \
|
||||
if (Z_REFCOUNTED_P(varptr)) { \
|
||||
Z_ADDREF_P(varptr); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
442
Zend/zend_API.c
442
Zend/zend_API.c
@ -44,14 +44,13 @@ static zend_class_entry **class_cleanup_handlers;
|
||||
/* this function doesn't check for too many parameters */
|
||||
ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
|
||||
{
|
||||
zval *p;
|
||||
int arg_count;
|
||||
va_list ptr;
|
||||
zval **param, *param_ptr;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
p = zend_vm_stack_top(TSRMLS_C) - 1;
|
||||
arg_count = Z_LVAL_P(p);
|
||||
param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1);
|
||||
arg_count = EG(current_execute_data)->num_args;
|
||||
|
||||
if (param_count>arg_count) {
|
||||
return FAILURE;
|
||||
@ -61,7 +60,6 @@ ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
|
||||
|
||||
while (param_count-->0) {
|
||||
param = va_arg(ptr, zval **);
|
||||
param_ptr = (p-arg_count);
|
||||
if (!Z_ISREF_P(param_ptr) && Z_REFCOUNT_P(param_ptr) > 1) {
|
||||
zval new_tmp;
|
||||
|
||||
@ -70,7 +68,7 @@ ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
|
||||
ZVAL_COPY_VALUE(param_ptr, &new_tmp);
|
||||
}
|
||||
*param = param_ptr;
|
||||
arg_count--;
|
||||
param_ptr++;
|
||||
}
|
||||
va_end(ptr);
|
||||
|
||||
@ -78,52 +76,17 @@ ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval *argument_array TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval *p;
|
||||
int arg_count;
|
||||
zval *param_ptr;
|
||||
|
||||
p = zend_vm_stack_top(TSRMLS_C) - 1;
|
||||
arg_count = Z_LVAL_P(p);
|
||||
|
||||
if (param_count>arg_count) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
while (param_count-->0) {
|
||||
param_ptr = (p-arg_count);
|
||||
if (Z_REFCOUNTED_P(param_ptr) &&
|
||||
!Z_ISREF_P(param_ptr) &&
|
||||
Z_REFCOUNT_P(param_ptr) > 1) {
|
||||
zval new_tmp;
|
||||
|
||||
ZVAL_DUP(&new_tmp, param_ptr);
|
||||
Z_DELREF_P(param_ptr);
|
||||
ZVAL_COPY_VALUE(argument_array, &new_tmp);
|
||||
} else {
|
||||
ZVAL_COPY_VALUE(argument_array, param_ptr);
|
||||
}
|
||||
argument_array++;
|
||||
arg_count--;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* Zend-optimized Extended functions */
|
||||
/* this function doesn't check for too many parameters */
|
||||
ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */
|
||||
{
|
||||
zval *p;
|
||||
int arg_count;
|
||||
va_list ptr;
|
||||
zval **param;
|
||||
zval **param, *param_ptr;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
p = zend_vm_stack_top(TSRMLS_C) - 1;
|
||||
arg_count = Z_LVAL_P(p);
|
||||
param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1);
|
||||
arg_count = EG(current_execute_data)->num_args;
|
||||
|
||||
if (param_count>arg_count) {
|
||||
return FAILURE;
|
||||
@ -132,7 +95,8 @@ ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */
|
||||
va_start(ptr, param_count);
|
||||
while (param_count-->0) {
|
||||
param = va_arg(ptr, zval **);
|
||||
*param = p-(arg_count--);
|
||||
*param = param_ptr;
|
||||
param_ptr++;
|
||||
}
|
||||
va_end(ptr);
|
||||
|
||||
@ -142,22 +106,20 @@ ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */
|
||||
|
||||
ZEND_API int _zend_get_parameters_array_ex(int param_count, zval *argument_array TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval *p;
|
||||
zval *param_ptr;
|
||||
int arg_count;
|
||||
|
||||
p = zend_vm_stack_top(TSRMLS_C) - 1;
|
||||
arg_count = Z_LVAL_P(p);
|
||||
param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1);
|
||||
arg_count = EG(current_execute_data)->num_args;
|
||||
|
||||
if (param_count>arg_count) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
while (param_count-->0) {
|
||||
zval *value = (p-arg_count);
|
||||
|
||||
ZVAL_COPY_VALUE(argument_array, value);
|
||||
ZVAL_COPY_VALUE(argument_array, param_ptr);
|
||||
argument_array++;
|
||||
arg_count--;
|
||||
param_ptr++;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
@ -166,22 +128,22 @@ ZEND_API int _zend_get_parameters_array_ex(int param_count, zval *argument_array
|
||||
|
||||
ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval *p;
|
||||
zval *param_ptr;
|
||||
int arg_count;
|
||||
|
||||
p = zend_vm_stack_top(TSRMLS_C) - 1;
|
||||
arg_count = Z_LVAL_P(p);
|
||||
param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1);
|
||||
arg_count = EG(current_execute_data)->num_args;
|
||||
|
||||
if (param_count>arg_count) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
while (param_count-->0) {
|
||||
zval *param = p-(arg_count--);
|
||||
if (Z_REFCOUNTED_P(param)) {
|
||||
Z_ADDREF_P(param);
|
||||
if (Z_REFCOUNTED_P(param_ptr)) {
|
||||
Z_ADDREF_P(param_ptr);
|
||||
}
|
||||
add_next_index_zval(argument_array, param);
|
||||
zend_hash_next_index_insert_new(Z_ARRVAL_P(argument_array), param_ptr);
|
||||
param_ptr++;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
@ -273,7 +235,7 @@ static int parse_arg_object_to_string(zval *arg, char **p, int *pl, int type TSR
|
||||
}
|
||||
/* Standard PHP objects */
|
||||
if (Z_OBJ_HT_P(arg) == &std_object_handlers || !Z_OBJ_HANDLER_P(arg, cast_object)) {
|
||||
SEPARATE_ZVAL_IF_NOT_REF(arg);
|
||||
SEPARATE_ZVAL_NOREF(arg);
|
||||
if (zend_std_cast_object_tostring(arg, arg, type TSRMLS_CC) == SUCCESS) {
|
||||
*pl = Z_STRLEN_P(arg);
|
||||
*p = Z_STRVAL_P(arg);
|
||||
@ -281,15 +243,13 @@ static int parse_arg_object_to_string(zval *arg, char **p, int *pl, int type TSR
|
||||
}
|
||||
}
|
||||
if (!Z_OBJ_HANDLER_P(arg, cast_object) && Z_OBJ_HANDLER_P(arg, get)) {
|
||||
int use_copy;
|
||||
zval rv;
|
||||
zval *z = Z_OBJ_HANDLER_P(arg, get)(arg, &rv TSRMLS_CC);
|
||||
Z_ADDREF_P(z);
|
||||
if(Z_TYPE_P(z) != IS_OBJECT) {
|
||||
zval_dtor(arg);
|
||||
ZVAL_NULL(arg);
|
||||
zend_make_printable_zval(z, arg, &use_copy);
|
||||
if (!use_copy) {
|
||||
if (!zend_make_printable_zval(z, arg)) {
|
||||
ZVAL_ZVAL(arg, z, 1, 1);
|
||||
}
|
||||
*pl = Z_STRLEN_P(arg);
|
||||
@ -302,7 +262,7 @@ static int parse_arg_object_to_string(zval *arg, char **p, int *pl, int type TSR
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int parse_arg_object_to_str(zval *arg, zend_string **str, int type TSRMLS_DC) /* {{{ */
|
||||
ZEND_API int parse_arg_object_to_str(zval *arg, zend_string **str, int type TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
if (Z_OBJ_HANDLER_P(arg, cast_object)) {
|
||||
zval obj;
|
||||
@ -315,22 +275,20 @@ static int parse_arg_object_to_str(zval *arg, zend_string **str, int type TSRMLS
|
||||
}
|
||||
/* Standard PHP objects */
|
||||
if (Z_OBJ_HT_P(arg) == &std_object_handlers || !Z_OBJ_HANDLER_P(arg, cast_object)) {
|
||||
SEPARATE_ZVAL_IF_NOT_REF(arg);
|
||||
SEPARATE_ZVAL_NOREF(arg);
|
||||
if (zend_std_cast_object_tostring(arg, arg, type TSRMLS_CC) == SUCCESS) {
|
||||
*str = Z_STR_P(arg);
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
if (!Z_OBJ_HANDLER_P(arg, cast_object) && Z_OBJ_HANDLER_P(arg, get)) {
|
||||
int use_copy;
|
||||
zval rv;
|
||||
zval *z = Z_OBJ_HANDLER_P(arg, get)(arg, &rv TSRMLS_CC);
|
||||
Z_ADDREF_P(z);
|
||||
if(Z_TYPE_P(z) != IS_OBJECT) {
|
||||
zval_dtor(arg);
|
||||
ZVAL_NULL(arg);
|
||||
zend_make_printable_zval(z, arg, &use_copy);
|
||||
if (!use_copy) {
|
||||
if (!zend_make_printable_zval(z, arg)) {
|
||||
ZVAL_ZVAL(arg, z, 1, 1);
|
||||
}
|
||||
*str = Z_STR_P(arg);
|
||||
@ -342,6 +300,94 @@ static int parse_arg_object_to_str(zval *arg, zend_string **str, int type TSRMLS
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
#ifdef FAST_ZPP
|
||||
ZEND_API void zend_wrong_paramers_count_error(int num_args, int min_num_args, int max_num_args TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_function *active_function = EG(current_execute_data)->func;
|
||||
const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : "";
|
||||
|
||||
zend_error(E_WARNING, "%s%s%s() expects %s %d parameter%s, %d given",
|
||||
class_name, \
|
||||
class_name[0] ? "::" : "", \
|
||||
active_function->common.function_name->val,
|
||||
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 void zend_wrong_paramer_type_error(int num, zend_expected_type expected_type, zval *arg TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
const char *space;
|
||||
const char *class_name = get_active_class_name(&space TSRMLS_CC);
|
||||
static const char * const expected_error[] = {
|
||||
Z_EXPECTED_TYPES(Z_EXPECTED_TYPE_STR)
|
||||
NULL
|
||||
};
|
||||
|
||||
zend_error(E_WARNING, "%s%s%s() expects parameter %d to be %s, %s given",
|
||||
class_name, space, get_active_function_name(TSRMLS_C), num, expected_error[expected_type], zend_zval_type_name(arg));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API void zend_wrong_paramer_class_error(int num, char *name, zval *arg TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
const char *space;
|
||||
const char *class_name = get_active_class_name(&space TSRMLS_CC);
|
||||
|
||||
zend_error(E_WARNING, "%s%s%s() expects parameter %d to be %s, %s given",
|
||||
class_name, space, get_active_function_name(TSRMLS_C), num, name, zend_zval_type_name(arg));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API void zend_wrong_callback_error(int severity, int num, char *error TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
const char *space;
|
||||
const char *class_name = get_active_class_name(&space TSRMLS_CC);
|
||||
|
||||
zend_error(severity, "%s%s%s() expects parameter %d to be a valid callback, %s",
|
||||
class_name, space, get_active_function_name(TSRMLS_C), num, error);
|
||||
efree(error);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API int _z_param_class(zval *arg, zend_class_entry **pce, int num, int check_null TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_class_entry *ce_base = *pce;
|
||||
|
||||
if (check_null && Z_TYPE_P(arg) == IS_NULL) {
|
||||
*pce = NULL;
|
||||
return 1;
|
||||
}
|
||||
convert_to_string_ex(arg);
|
||||
*pce = zend_lookup_class(Z_STR_P(arg) TSRMLS_CC);
|
||||
if (ce_base) {
|
||||
if ((!*pce || !instanceof_function(*pce, ce_base TSRMLS_CC))) {
|
||||
const char *space;
|
||||
const char *class_name = get_active_class_name(&space TSRMLS_CC);
|
||||
|
||||
zend_error(E_WARNING, "%s%s%s() expects parameter %d to be a class name derived from %s, '%s' given",
|
||||
class_name, space, get_active_function_name(TSRMLS_C), num,
|
||||
ce_base->name->val, Z_STRVAL_P(arg));
|
||||
*pce = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!*pce) {
|
||||
const char *space;
|
||||
const char *class_name = get_active_class_name(&space TSRMLS_CC);
|
||||
|
||||
zend_error(E_WARNING, "%s%s%s() expects parameter %d to be a valid class name, '%s' given",
|
||||
class_name, space, get_active_function_name(TSRMLS_C), num,
|
||||
Z_STRVAL_P(arg));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/* }}} */
|
||||
#endif
|
||||
|
||||
static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, const char **spec, char **error, int *severity TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
const char *spec_walk = *spec;
|
||||
@ -350,9 +396,11 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
|
||||
zval *real_arg = arg;
|
||||
|
||||
/* scan through modifiers */
|
||||
ZVAL_DEREF(arg);
|
||||
while (1) {
|
||||
if (*spec_walk == '/') {
|
||||
SEPARATE_ZVAL_IF_NOT_REF(arg);
|
||||
SEPARATE_ZVAL(arg);
|
||||
real_arg = arg;
|
||||
} else if (*spec_walk == '!') {
|
||||
check_null = 1;
|
||||
} else {
|
||||
@ -361,8 +409,6 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
|
||||
spec_walk++;
|
||||
}
|
||||
|
||||
ZVAL_DEREF(arg);
|
||||
|
||||
switch (c) {
|
||||
case 'l':
|
||||
case 'L':
|
||||
@ -486,12 +532,6 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
|
||||
case IS_TRUE:
|
||||
convert_to_string_ex(arg);
|
||||
case IS_STRING:
|
||||
if (UNEXPECTED(Z_ISREF_P(arg))) {
|
||||
/* it's dangerous to return pointers to string
|
||||
buffer of referenced variable, because it can
|
||||
be clobbered throug magic callbacks */
|
||||
SEPARATE_ZVAL(arg);
|
||||
}
|
||||
*p = Z_STRVAL_P(arg);
|
||||
*pl = Z_STRLEN_P(arg);
|
||||
if (c == 'p' && CHECK_ZVAL_NULL_PATH(arg)) {
|
||||
@ -533,12 +573,6 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
|
||||
case IS_TRUE:
|
||||
convert_to_string_ex(arg);
|
||||
case IS_STRING:
|
||||
if (UNEXPECTED(Z_ISREF_P(arg))) {
|
||||
/* it's dangerous to return pointers to string
|
||||
buffer of referenced variable, because it can
|
||||
be clobbered throug magic callbacks */
|
||||
SEPARATE_ZVAL(arg);
|
||||
}
|
||||
*str = Z_STR_P(arg);
|
||||
if (c == 'P' && CHECK_ZVAL_NULL_PATH(arg)) {
|
||||
return "a valid path";
|
||||
@ -853,7 +887,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
|
||||
case '+':
|
||||
if (have_varargs) {
|
||||
if (!quiet) {
|
||||
zend_function *active_function = EG(current_execute_data)->function_state.function;
|
||||
zend_function *active_function = EG(current_execute_data)->func;
|
||||
const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : "";
|
||||
zend_error(E_WARNING, "%s%s%s(): only one varargs specifier (* or +) is permitted",
|
||||
class_name,
|
||||
@ -873,7 +907,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
|
||||
|
||||
default:
|
||||
if (!quiet) {
|
||||
zend_function *active_function = EG(current_execute_data)->function_state.function;
|
||||
zend_function *active_function = EG(current_execute_data)->func;
|
||||
const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : "";
|
||||
zend_error(E_WARNING, "%s%s%s(): bad type specifier while parsing parameters",
|
||||
class_name,
|
||||
@ -896,7 +930,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
|
||||
|
||||
if (num_args < min_num_args || (num_args > max_num_args && max_num_args > 0)) {
|
||||
if (!quiet) {
|
||||
zend_function *active_function = EG(current_execute_data)->function_state.function;
|
||||
zend_function *active_function = EG(current_execute_data)->func;
|
||||
const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : "";
|
||||
zend_error(E_WARNING, "%s%s%s() expects %s %d parameter%s, %d given",
|
||||
class_name,
|
||||
@ -910,7 +944,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
arg_count = Z_LVAL_P(zend_vm_stack_top(TSRMLS_C) - 1);
|
||||
arg_count = EG(current_execute_data)->num_args;
|
||||
|
||||
if (num_args > arg_count) {
|
||||
zend_error(E_WARNING, "%s(): could not obtain parameters for parsing",
|
||||
@ -934,7 +968,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
|
||||
|
||||
if (num_varargs > 0) {
|
||||
*n_varargs = num_varargs;
|
||||
*varargs = (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count - i));
|
||||
*varargs = ZEND_CALL_ARG(EG(current_execute_data), i + 1);
|
||||
/* adjust how many args we have left and restart loop */
|
||||
num_args += 1 - num_varargs;
|
||||
i += num_varargs;
|
||||
@ -945,7 +979,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
|
||||
}
|
||||
}
|
||||
|
||||
arg = zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count-i);
|
||||
arg = ZEND_CALL_ARG(EG(current_execute_data), i + 1);
|
||||
|
||||
if (zend_parse_arg(i+1, arg, va, &type_spec, quiet TSRMLS_CC) == FAILURE) {
|
||||
/* clean up varargs array if it was used */
|
||||
@ -1016,7 +1050,7 @@ ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr
|
||||
* Z_OBJ(EG(This)) to NULL when calling an internal function with common.scope == NULL.
|
||||
* In that case EG(This) would still be the $this from the calling code and we'd take the
|
||||
* wrong branch here. */
|
||||
zend_bool is_method = EG(current_execute_data)->function_state.function->common.scope != NULL;
|
||||
zend_bool is_method = EG(current_execute_data)->func->common.scope != NULL;
|
||||
if (!is_method || !this_ptr || Z_TYPE_P(this_ptr) != IS_OBJECT) {
|
||||
RETURN_IF_ZERO_ARGS(num_args, p, 0);
|
||||
|
||||
@ -1097,7 +1131,7 @@ ZEND_API int _array_init(zval *arg, uint size ZEND_FILE_LINE_DC) /* {{{ */
|
||||
|
||||
/* This function should be called after the constructor has been called
|
||||
* because it may call __set from the uninitialized object otherwise. */
|
||||
ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destroy_ht TSRMLS_DC) /* {{{ */
|
||||
ZEND_API void zend_merge_properties(zval *obj, HashTable *properties TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
const zend_object_handlers *obj_ht = Z_OBJ_HT_P(obj);
|
||||
zend_class_entry *old_scope = EG(scope);
|
||||
@ -1110,16 +1144,11 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destro
|
||||
zval member;
|
||||
|
||||
ZVAL_STR(&member, STR_COPY(key));
|
||||
obj_ht->write_property(obj, &member, value, -1 TSRMLS_CC);
|
||||
obj_ht->write_property(obj, &member, value, NULL TSRMLS_CC);
|
||||
zval_ptr_dtor(&member);
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
EG(scope) = old_scope;
|
||||
|
||||
if (destroy_ht) {
|
||||
zend_hash_destroy(properties);
|
||||
FREE_HASHTABLE(properties);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -1127,7 +1156,7 @@ static int zval_update_class_constant(zval *pp, int is_static, int offset TSRMLS
|
||||
{
|
||||
ZVAL_DEREF(pp);
|
||||
if (Z_CONSTANT_P(pp)) {
|
||||
zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
|
||||
zend_class_entry **scope = EG(current_execute_data) ? &EG(scope) : &CG(active_class_entry);
|
||||
|
||||
if ((*scope)->parent) {
|
||||
zend_class_entry *ce = *scope;
|
||||
@ -1157,13 +1186,49 @@ static int zval_update_class_constant(zval *pp, int is_static, int offset TSRMLS
|
||||
|
||||
ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
if ((class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED) == 0 || (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count)) {
|
||||
zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
|
||||
int i;
|
||||
|
||||
/* initialize static members of internal class */
|
||||
if (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count) {
|
||||
zval *p;
|
||||
|
||||
if (class_type->parent) {
|
||||
zend_update_class_constants(class_type->parent TSRMLS_CC);
|
||||
}
|
||||
#if ZTS
|
||||
CG(static_members_table)[(zend_intptr_t)(class_type->static_members_table)] = emalloc(sizeof(zval*) * class_type->default_static_members_count);
|
||||
#else
|
||||
class_type->static_members_table = emalloc(sizeof(zval*) * class_type->default_static_members_count);
|
||||
#endif
|
||||
for (i = 0; i < class_type->default_static_members_count; i++) {
|
||||
p = &class_type->default_static_members_table[i];
|
||||
if (Z_ISREF_P(p) &&
|
||||
class_type->parent &&
|
||||
i < class_type->parent->default_static_members_count &&
|
||||
p == &class_type->parent->default_static_members_table[i] &&
|
||||
Z_TYPE(CE_STATIC_MEMBERS(class_type->parent)[i]) != IS_UNDEF
|
||||
) {
|
||||
zval *q = &CE_STATIC_MEMBERS(class_type->parent)[i];
|
||||
|
||||
ZVAL_NEW_REF(q, q);
|
||||
ZVAL_COPY_VALUE(&CE_STATIC_MEMBERS(class_type)[i], q);
|
||||
Z_ADDREF_P(q);
|
||||
} else {
|
||||
ZVAL_DUP(&CE_STATIC_MEMBERS(class_type)[i], p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED) == 0) {
|
||||
zend_class_entry **scope = EG(current_execute_data) ? &EG(scope) : &CG(active_class_entry);
|
||||
zend_class_entry *old_scope = *scope;
|
||||
int i;
|
||||
zval *val;
|
||||
|
||||
*scope = class_type;
|
||||
zend_hash_apply_with_argument(&class_type->constants_table, (apply_func_arg_t) zval_update_constant, (void *)1 TSRMLS_CC);
|
||||
|
||||
ZEND_HASH_FOREACH_VAL(&class_type->constants_table, val) {
|
||||
zval_update_constant(val, 1 TSRMLS_CC);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
for (i = 0; i < class_type->default_properties_count; i++) {
|
||||
if (Z_TYPE(class_type->default_properties_table[i]) != IS_UNDEF) {
|
||||
@ -1171,36 +1236,6 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC
|
||||
}
|
||||
}
|
||||
|
||||
if (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count) {
|
||||
zval *p;
|
||||
|
||||
if (class_type->parent) {
|
||||
zend_update_class_constants(class_type->parent TSRMLS_CC);
|
||||
}
|
||||
#if ZTS
|
||||
CG(static_members_table)[(zend_intptr_t)(class_type->static_members_table)] = emalloc(sizeof(zval*) * class_type->default_static_members_count);
|
||||
#else
|
||||
class_type->static_members_table = emalloc(sizeof(zval*) * class_type->default_static_members_count);
|
||||
#endif
|
||||
for (i = 0; i < class_type->default_static_members_count; i++) {
|
||||
p = &class_type->default_static_members_table[i];
|
||||
if (Z_ISREF_P(p) &&
|
||||
class_type->parent &&
|
||||
i < class_type->parent->default_static_members_count &&
|
||||
p == &class_type->parent->default_static_members_table[i] &&
|
||||
Z_TYPE(CE_STATIC_MEMBERS(class_type->parent)[i]) != IS_UNDEF
|
||||
) {
|
||||
zval *q = &CE_STATIC_MEMBERS(class_type->parent)[i];
|
||||
|
||||
ZVAL_NEW_REF(q, q);
|
||||
ZVAL_COPY_VALUE(&CE_STATIC_MEMBERS(class_type)[i], q);
|
||||
Z_ADDREF_P(q);
|
||||
} else {
|
||||
ZVAL_DUP(&CE_STATIC_MEMBERS(class_type)[i], p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < class_type->default_static_members_count; i++) {
|
||||
zval_update_class_constant(&CE_STATIC_MEMBERS(class_type)[i], 1, i TSRMLS_CC);
|
||||
}
|
||||
@ -1688,7 +1723,7 @@ ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, long
|
||||
|
||||
ZVAL_LONG(&tmp, n);
|
||||
ZVAL_STRINGL(&z_key, key, key_len);
|
||||
Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, -1 TSRMLS_CC);
|
||||
Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL TSRMLS_CC);
|
||||
zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
|
||||
zval_ptr_dtor(&z_key);
|
||||
return SUCCESS;
|
||||
@ -1702,7 +1737,7 @@ ZEND_API int add_property_bool_ex(zval *arg, const char *key, uint key_len, int
|
||||
|
||||
ZVAL_BOOL(&tmp, b);
|
||||
ZVAL_STRINGL(&z_key, key, key_len);
|
||||
Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, -1 TSRMLS_CC);
|
||||
Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL TSRMLS_CC);
|
||||
zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
|
||||
zval_ptr_dtor(&z_key);
|
||||
return SUCCESS;
|
||||
@ -1716,7 +1751,7 @@ ZEND_API int add_property_null_ex(zval *arg, const char *key, uint key_len TSRML
|
||||
|
||||
ZVAL_NULL(&tmp);
|
||||
ZVAL_STRINGL(&z_key, key, key_len);
|
||||
Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, -1 TSRMLS_CC);
|
||||
Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL TSRMLS_CC);
|
||||
zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
|
||||
zval_ptr_dtor(&z_key);
|
||||
return SUCCESS;
|
||||
@ -1730,7 +1765,7 @@ ZEND_API int add_property_resource_ex(zval *arg, const char *key, uint key_len,
|
||||
|
||||
ZVAL_RES(&tmp, r);
|
||||
ZVAL_STRINGL(&z_key, key, key_len);
|
||||
Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, -1 TSRMLS_CC);
|
||||
Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL TSRMLS_CC);
|
||||
zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
|
||||
zval_ptr_dtor(&z_key);
|
||||
return SUCCESS;
|
||||
@ -1744,7 +1779,7 @@ ZEND_API int add_property_double_ex(zval *arg, const char *key, uint key_len, do
|
||||
|
||||
ZVAL_DOUBLE(&tmp, d);
|
||||
ZVAL_STRINGL(&z_key, key, key_len);
|
||||
Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, -1 TSRMLS_CC);
|
||||
Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL TSRMLS_CC);
|
||||
zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
|
||||
zval_ptr_dtor(&z_key);
|
||||
return SUCCESS;
|
||||
@ -1758,7 +1793,7 @@ ZEND_API int add_property_str_ex(zval *arg, const char *key, uint key_len, zend_
|
||||
|
||||
ZVAL_STR(&tmp, str);
|
||||
ZVAL_STRINGL(&z_key, key, key_len);
|
||||
Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, -1 TSRMLS_CC);
|
||||
Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL TSRMLS_CC);
|
||||
zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
|
||||
zval_ptr_dtor(&z_key);
|
||||
return SUCCESS;
|
||||
@ -1772,7 +1807,7 @@ ZEND_API int add_property_string_ex(zval *arg, const char *key, uint key_len, co
|
||||
|
||||
ZVAL_STRING(&tmp, str);
|
||||
ZVAL_STRINGL(&z_key, key, key_len);
|
||||
Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, -1 TSRMLS_CC);
|
||||
Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL TSRMLS_CC);
|
||||
zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
|
||||
zval_ptr_dtor(&z_key);
|
||||
return SUCCESS;
|
||||
@ -1786,7 +1821,7 @@ ZEND_API int add_property_stringl_ex(zval *arg, const char *key, uint key_len, c
|
||||
|
||||
ZVAL_STRINGL(&tmp, str, length);
|
||||
ZVAL_STRINGL(&z_key, key, key_len);
|
||||
Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, -1 TSRMLS_CC);
|
||||
Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL TSRMLS_CC);
|
||||
zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
|
||||
zval_ptr_dtor(&z_key);
|
||||
return SUCCESS;
|
||||
@ -1798,7 +1833,7 @@ ZEND_API int add_property_zval_ex(zval *arg, const char *key, uint key_len, zval
|
||||
zval z_key;
|
||||
|
||||
ZVAL_STRINGL(&z_key, key, key_len);
|
||||
Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, value, -1 TSRMLS_CC);
|
||||
Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, value, NULL TSRMLS_CC);
|
||||
zval_ptr_dtor(&z_key);
|
||||
return SUCCESS;
|
||||
}
|
||||
@ -2543,7 +2578,7 @@ static int module_registry_cleanup(zval *zv TSRMLS_DC) /* {{{ */
|
||||
|
||||
ZEND_API void zend_deactivate_modules(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
EG(opline_ptr) = NULL; /* we're no longer executing anything */
|
||||
EG(current_execute_data) = NULL; /* we're no longer executing anything */
|
||||
|
||||
zend_try {
|
||||
if (EG(full_tables_cleanup)) {
|
||||
@ -2629,7 +2664,7 @@ static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class
|
||||
|
||||
class_entry->type = ZEND_INTERNAL_CLASS;
|
||||
zend_initialize_class_data(class_entry, 0 TSRMLS_CC);
|
||||
class_entry->ce_flags = ce_flags;
|
||||
class_entry->ce_flags = ce_flags | ZEND_ACC_CONSTANTS_UPDATED;
|
||||
class_entry->info.internal.module = EG(current_module);
|
||||
|
||||
if (class_entry->info.internal.builtin_functions) {
|
||||
@ -2719,8 +2754,8 @@ ZEND_API int zend_set_hash_symbol(zval *symbol, const char *name, int name_lengt
|
||||
|
||||
if (num_symbol_tables <= 0) return FAILURE;
|
||||
|
||||
if (is_ref && !Z_ISREF_P(symbol)) {
|
||||
ZVAL_NEW_REF(symbol, symbol);
|
||||
if (is_ref) {
|
||||
ZVAL_MAKE_REF(symbol);
|
||||
}
|
||||
|
||||
va_start(symbol_table_list, num_symbol_tables);
|
||||
@ -2808,9 +2843,10 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache
|
||||
zend_class_entry *ce;
|
||||
int name_len = name->len;
|
||||
zend_string *lcname;
|
||||
|
||||
lcname = STR_ALLOC(name_len, 0);
|
||||
zend_str_tolower_copy(lcname->val, name->val, name_len);
|
||||
ALLOCA_FLAG(use_heap);
|
||||
|
||||
STR_ALLOCA_ALLOC(lcname, name_len, use_heap);
|
||||
zend_str_tolower_copy(lcname->val, name->val, name_len + 1);
|
||||
|
||||
*strict_class = 0;
|
||||
if (name_len == sizeof("self") - 1 &&
|
||||
@ -2818,7 +2854,7 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache
|
||||
if (!EG(scope)) {
|
||||
if (error) *error = estrdup("cannot access self:: when no class scope is active");
|
||||
} else {
|
||||
fcc->called_scope = EG(called_scope);
|
||||
fcc->called_scope = EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL;
|
||||
fcc->calling_scope = EG(scope);
|
||||
if (!fcc->object && Z_OBJ(EG(This))) {
|
||||
fcc->object = Z_OBJ(EG(This));
|
||||
@ -2832,7 +2868,7 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache
|
||||
} else if (!EG(scope)->parent) {
|
||||
if (error) *error = estrdup("cannot access parent:: when current class scope has no parent");
|
||||
} else {
|
||||
fcc->called_scope = EG(called_scope);
|
||||
fcc->called_scope = EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL;
|
||||
fcc->calling_scope = EG(scope)->parent;
|
||||
if (!fcc->object && Z_OBJ(EG(This))) {
|
||||
fcc->object = Z_OBJ(EG(This));
|
||||
@ -2842,11 +2878,11 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache
|
||||
}
|
||||
} else if (name_len == sizeof("static") - 1 &&
|
||||
!memcmp(lcname->val, "static", sizeof("static") - 1)) {
|
||||
if (!EG(called_scope)) {
|
||||
if (!EG(current_execute_data) || !EG(current_execute_data)->called_scope) {
|
||||
if (error) *error = estrdup("cannot access static:: when no class scope is active");
|
||||
} else {
|
||||
fcc->called_scope = EG(called_scope);
|
||||
fcc->calling_scope = EG(called_scope);
|
||||
fcc->called_scope = EG(current_execute_data)->called_scope;
|
||||
fcc->calling_scope = EG(current_execute_data)->called_scope;
|
||||
if (!fcc->object && Z_OBJ(EG(This))) {
|
||||
fcc->object = Z_OBJ(EG(This));
|
||||
}
|
||||
@ -2854,8 +2890,13 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache
|
||||
ret = 1;
|
||||
}
|
||||
} else if ((ce = zend_lookup_class_ex(name, NULL, 1 TSRMLS_CC)) != NULL) {
|
||||
zend_class_entry *scope = EG(active_op_array) ? EG(active_op_array)->scope : NULL;
|
||||
zend_class_entry *scope;
|
||||
zend_execute_data *ex = EG(current_execute_data);
|
||||
|
||||
while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
|
||||
ex = ex->prev_execute_data;
|
||||
}
|
||||
scope = ex ? ex->func->common.scope : NULL;
|
||||
fcc->calling_scope = ce;
|
||||
if (scope && !fcc->object && Z_OBJ(EG(This)) &&
|
||||
instanceof_function(Z_OBJCE(EG(This)), scope TSRMLS_CC) &&
|
||||
@ -2870,7 +2911,7 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache
|
||||
} else {
|
||||
if (error) zend_spprintf(error, 0, "class '%.*s' not found", name_len, name->val);
|
||||
}
|
||||
STR_FREE(lcname);
|
||||
STR_ALLOCA_FREE(lcname, use_heap);
|
||||
return ret;
|
||||
}
|
||||
/* }}} */
|
||||
@ -2896,27 +2937,36 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca
|
||||
fcc->function_handler = NULL;
|
||||
|
||||
if (!ce_org) {
|
||||
char *lmname;
|
||||
int lmname_len;
|
||||
zend_string *lmname;
|
||||
|
||||
/* Skip leading \ */
|
||||
if (Z_STRVAL_P(callable)[0] == '\\') {
|
||||
lmname = do_alloca(Z_STRLEN_P(callable), use_heap);
|
||||
lmname_len = Z_STRLEN_P(callable) - 1;
|
||||
zend_str_tolower_copy(lmname, Z_STRVAL_P(callable) + 1, lmname_len);
|
||||
if (UNEXPECTED(Z_STRVAL_P(callable)[0] == '\\')) {
|
||||
STR_ALLOCA_INIT(lmname, Z_STRVAL_P(callable) + 1, Z_STRLEN_P(callable) - 1, use_heap);
|
||||
} else {
|
||||
lmname = do_alloca(Z_STRLEN_P(callable) + 1, use_heap);
|
||||
lmname_len = Z_STRLEN_P(callable);
|
||||
zend_str_tolower_copy(lmname, Z_STRVAL_P(callable), lmname_len);
|
||||
lmname = Z_STR_P(callable);
|
||||
}
|
||||
/* Check if function with given name exists.
|
||||
* This may be a compound name that includes namespace name */
|
||||
fcc->function_handler = zend_hash_str_find_ptr(EG(function_table), lmname, lmname_len);
|
||||
if (fcc->function_handler != NULL) {
|
||||
free_alloca(lmname, use_heap);
|
||||
if (EXPECTED((fcc->function_handler = zend_hash_find_ptr(EG(function_table), lmname)) != NULL)) {
|
||||
if (lmname != Z_STR_P(callable)) {
|
||||
STR_ALLOCA_FREE(lmname, use_heap);
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
if (lmname == Z_STR_P(callable)) {
|
||||
STR_ALLOCA_INIT(lmname, Z_STRVAL_P(callable), Z_STRLEN_P(callable), use_heap);
|
||||
} else {
|
||||
STR_FORGET_HASH_VAL(lmname);
|
||||
}
|
||||
zend_str_tolower(lmname->val, lmname->len);
|
||||
if ((fcc->function_handler = zend_hash_find_ptr(EG(function_table), lmname)) != NULL) {
|
||||
STR_ALLOCA_FREE(lmname, use_heap);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (lmname != Z_STR_P(callable)) {
|
||||
STR_ALLOCA_FREE(lmname, use_heap);
|
||||
}
|
||||
free_alloca(lmname, use_heap);
|
||||
}
|
||||
|
||||
/* Split name into class/namespace and method/function names */
|
||||
@ -3559,36 +3609,45 @@ ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */
|
||||
|
||||
ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_property_info property_info, *property_info_ptr;
|
||||
zend_property_info *property_info, *property_info_ptr;
|
||||
|
||||
if (ce->type == ZEND_INTERNAL_CLASS) {
|
||||
property_info = pemalloc(sizeof(zend_property_info), 1);
|
||||
} else {
|
||||
property_info = zend_arena_alloc(&CG(arena), sizeof(zend_property_info));
|
||||
}
|
||||
|
||||
if (Z_CONSTANT_P(property)) {
|
||||
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
|
||||
}
|
||||
if (!(access_type & ZEND_ACC_PPP_MASK)) {
|
||||
access_type |= ZEND_ACC_PUBLIC;
|
||||
}
|
||||
if (access_type & ZEND_ACC_STATIC) {
|
||||
if ((property_info_ptr = zend_hash_find_ptr(&ce->properties_info, name)) != NULL &&
|
||||
(property_info_ptr->flags & ZEND_ACC_STATIC) != 0) {
|
||||
property_info.offset = property_info_ptr->offset;
|
||||
zval_ptr_dtor(&ce->default_static_members_table[property_info.offset]);
|
||||
property_info->offset = property_info_ptr->offset;
|
||||
zval_ptr_dtor(&ce->default_static_members_table[property_info->offset]);
|
||||
zend_hash_del(&ce->properties_info, name);
|
||||
} else {
|
||||
property_info.offset = ce->default_static_members_count++;
|
||||
property_info->offset = ce->default_static_members_count++;
|
||||
ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
|
||||
}
|
||||
ZVAL_COPY_VALUE(&ce->default_static_members_table[property_info.offset], property);
|
||||
ZVAL_COPY_VALUE(&ce->default_static_members_table[property_info->offset], property);
|
||||
if (ce->type == ZEND_USER_CLASS) {
|
||||
ce->static_members_table = ce->default_static_members_table;
|
||||
}
|
||||
} else {
|
||||
if ((property_info_ptr = zend_hash_find_ptr(&ce->properties_info, name)) != NULL &&
|
||||
(property_info_ptr->flags & ZEND_ACC_STATIC) == 0) {
|
||||
property_info.offset = property_info_ptr->offset;
|
||||
zval_ptr_dtor(&ce->default_properties_table[property_info.offset]);
|
||||
property_info->offset = property_info_ptr->offset;
|
||||
zval_ptr_dtor(&ce->default_properties_table[property_info->offset]);
|
||||
zend_hash_del(&ce->properties_info, name);
|
||||
} else {
|
||||
property_info.offset = ce->default_properties_count++;
|
||||
property_info->offset = ce->default_properties_count++;
|
||||
ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
|
||||
}
|
||||
ZVAL_COPY_VALUE(&ce->default_properties_table[property_info.offset], property);
|
||||
ZVAL_COPY_VALUE(&ce->default_properties_table[property_info->offset], property);
|
||||
}
|
||||
if (ce->type & ZEND_INTERNAL_CLASS) {
|
||||
switch(Z_TYPE_P(property)) {
|
||||
@ -3603,27 +3662,23 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, z
|
||||
}
|
||||
switch (access_type & ZEND_ACC_PPP_MASK) {
|
||||
case ZEND_ACC_PRIVATE: {
|
||||
property_info.name = zend_mangle_property_name(ce->name->val, ce->name->len, name->val, name->len, ce->type & ZEND_INTERNAL_CLASS);
|
||||
property_info->name = zend_mangle_property_name(ce->name->val, ce->name->len, name->val, name->len, ce->type & ZEND_INTERNAL_CLASS);
|
||||
}
|
||||
break;
|
||||
case ZEND_ACC_PROTECTED: {
|
||||
property_info.name = zend_mangle_property_name("*", 1, name->val, name->len, ce->type & ZEND_INTERNAL_CLASS);
|
||||
property_info->name = zend_mangle_property_name("*", 1, name->val, name->len, ce->type & ZEND_INTERNAL_CLASS);
|
||||
}
|
||||
break;
|
||||
case ZEND_ACC_PUBLIC:
|
||||
property_info.name = STR_COPY(name);
|
||||
property_info->name = STR_COPY(name);
|
||||
break;
|
||||
}
|
||||
|
||||
property_info.name = zend_new_interned_string(property_info.name TSRMLS_CC);
|
||||
|
||||
property_info.flags = access_type;
|
||||
|
||||
property_info.doc_comment = doc_comment;
|
||||
|
||||
property_info.ce = ce;
|
||||
|
||||
zend_hash_update_mem(&ce->properties_info, name, &property_info, sizeof(zend_property_info));
|
||||
property_info->name = zend_new_interned_string(property_info->name TSRMLS_CC);
|
||||
property_info->flags = access_type;
|
||||
property_info->doc_comment = doc_comment;
|
||||
property_info->ce = ce;
|
||||
zend_hash_update_ptr(&ce->properties_info, name, property_info);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
@ -3694,6 +3749,9 @@ ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *nam
|
||||
|
||||
ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
if (Z_CONSTANT_P(value)) {
|
||||
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
|
||||
}
|
||||
return zend_hash_str_update(&ce->constants_table, name, name_length, value) ?
|
||||
SUCCESS : FAILURE;
|
||||
}
|
||||
@ -3762,7 +3820,7 @@ ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const
|
||||
zend_error(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, class_name->val);
|
||||
}
|
||||
ZVAL_STRINGL(&property, name, name_length);
|
||||
Z_OBJ_HT_P(object)->write_property(object, &property, value, -1 TSRMLS_CC);
|
||||
Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL TSRMLS_CC);
|
||||
zval_ptr_dtor(&property);
|
||||
|
||||
EG(scope) = old_scope;
|
||||
@ -3841,7 +3899,7 @@ ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *na
|
||||
zend_string *key = STR_INIT(name, name_length, 0);
|
||||
|
||||
EG(scope) = scope;
|
||||
property = zend_std_get_static_property(scope, key, 0, -1 TSRMLS_CC);
|
||||
property = zend_std_get_static_property(scope, key, 0, NULL TSRMLS_CC);
|
||||
EG(scope) = old_scope;
|
||||
STR_FREE(key);
|
||||
if (!property) {
|
||||
@ -3941,7 +3999,7 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const c
|
||||
}
|
||||
|
||||
ZVAL_STRINGL(&property, name, name_length);
|
||||
value = Z_OBJ_HT_P(object)->read_property(object, &property, silent?BP_VAR_IS:BP_VAR_R, -1, &rv TSRMLS_CC);
|
||||
value = Z_OBJ_HT_P(object)->read_property(object, &property, silent?BP_VAR_IS:BP_VAR_R, NULL, &rv TSRMLS_CC);
|
||||
zval_ptr_dtor(&property);
|
||||
|
||||
EG(scope) = old_scope;
|
||||
@ -3956,7 +4014,7 @@ ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *na
|
||||
zend_string *key = STR_INIT(name, name_length, 0);
|
||||
|
||||
EG(scope) = scope;
|
||||
property = zend_std_get_static_property(scope, key, silent, -1 TSRMLS_CC);
|
||||
property = zend_std_get_static_property(scope, key, silent, NULL TSRMLS_CC);
|
||||
EG(scope) = old_scope;
|
||||
STR_FREE(key);
|
||||
|
||||
|
632
Zend/zend_API.h
632
Zend/zend_API.h
@ -233,7 +233,6 @@ int zend_next_free_module(void);
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
ZEND_API int zend_get_parameters(int ht, int param_count, ...);
|
||||
ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval *argument_array TSRMLS_DC);
|
||||
ZEND_API ZEND_ATTRIBUTE_DEPRECATED int zend_get_parameters_ex(int param_count, ...);
|
||||
ZEND_API int _zend_get_parameters_array_ex(int param_count, zval *argument_array TSRMLS_DC);
|
||||
|
||||
@ -241,7 +240,7 @@ ZEND_API int _zend_get_parameters_array_ex(int param_count, zval *argument_array
|
||||
ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TSRMLS_DC);
|
||||
|
||||
#define zend_get_parameters_array(ht, param_count, argument_array) \
|
||||
_zend_get_parameters_array(ht, param_count, argument_array TSRMLS_CC)
|
||||
_zend_get_parameters_array_ex(param_count, argument_array TSRMLS_CC)
|
||||
#define zend_get_parameters_array_ex(param_count, argument_array) \
|
||||
_zend_get_parameters_array_ex(param_count, argument_array TSRMLS_CC)
|
||||
#define zend_parse_parameters_none() \
|
||||
@ -370,7 +369,7 @@ ZEND_API void object_properties_init(zend_object *object, zend_class_entry *clas
|
||||
ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properties TSRMLS_DC);
|
||||
ZEND_API void object_properties_load(zend_object *object, HashTable *properties TSRMLS_DC);
|
||||
|
||||
ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destroy_ht TSRMLS_DC);
|
||||
ZEND_API void zend_merge_properties(zval *obj, HashTable *properties TSRMLS_DC);
|
||||
|
||||
/* no longer supported */
|
||||
ZEND_API int add_assoc_function(zval *arg, const char *key, void (*function_ptr)(INTERNAL_FUNCTION_PARAMETERS));
|
||||
@ -522,7 +521,7 @@ ZEND_API int zend_set_hash_symbol(zval *symbol, const char *name, int name_lengt
|
||||
|
||||
ZEND_API int zend_delete_global_variable(zend_string *name TSRMLS_DC);
|
||||
|
||||
ZEND_API void zend_rebuild_symbol_table(TSRMLS_D);
|
||||
ZEND_API zend_array *zend_rebuild_symbol_table(TSRMLS_D);
|
||||
ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data);
|
||||
ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data);
|
||||
ZEND_API int zend_set_local_var(zend_string *name, zval *value, int force TSRMLS_DC);
|
||||
@ -638,6 +637,27 @@ END_EXTERN_C()
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* May be used in internal constructors to make them return NULL */
|
||||
#if 1 // support for directly called constructors only ???
|
||||
#define ZEND_CTOR_MAKE_NULL() do { \
|
||||
if (EG(current_execute_data)->return_value) { \
|
||||
zval_ptr_dtor(EG(current_execute_data)->return_value); \
|
||||
ZVAL_NULL(EG(current_execute_data)->return_value); \
|
||||
} \
|
||||
} while (0)
|
||||
#else // attempt to support calls to parent::__construct() ???
|
||||
#define ZEND_CTOR_MAKE_NULL() do { \
|
||||
if (EG(current_execute_data)->return_value) { \
|
||||
zval_ptr_dtor(EG(current_execute_data)->return_value); \
|
||||
ZVAL_NULL(EG(current_execute_data)->return_value); \
|
||||
} else if (EG(current_execute_data)->prev_execute_data && \
|
||||
EG(current_execute_data)->prev_execute_data->object == \
|
||||
EG(current_execute_data)->object) { \
|
||||
EG(current_execute_data)->prev_execute_data->object = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define RETURN_ZVAL_FAST(z) { RETVAL_ZVAL_FAST(z); 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) TSRMLS_CC) : NULL)))
|
||||
@ -660,6 +680,610 @@ END_EXTERN_C()
|
||||
#define ZEND_GINIT_FUNCTION ZEND_MODULE_GLOBALS_CTOR_D
|
||||
#define ZEND_GSHUTDOWN_FUNCTION ZEND_MODULE_GLOBALS_DTOR_D
|
||||
|
||||
/* Fast parameter parsing API */
|
||||
|
||||
/* TODO: This API is experemental. It may be changed or removed ???
|
||||
* It should be used only for really often used functions.
|
||||
* (Keep the original parsing code and wrap usage with #ifndef FAST_ZPP)
|
||||
*/
|
||||
#define FAST_ZPP 1
|
||||
|
||||
#ifdef FAST_ZPP
|
||||
|
||||
#define Z_EXPECTED_TYPES(_) \
|
||||
_(Z_EXPECTED_LONG, "long") \
|
||||
_(Z_EXPECTED_BOOL, "boolean") \
|
||||
_(Z_EXPECTED_STRING, "string") \
|
||||
_(Z_EXPECTED_ARRAY, "array") \
|
||||
_(Z_EXPECTED_FUNC, "valid callback") \
|
||||
_(Z_EXPECTED_RESOURCE, "resource") \
|
||||
_(Z_EXPECTED_PATH, "a valid path") \
|
||||
_(Z_EXPECTED_OBJECT, "object") \
|
||||
_(Z_EXPECTED_DOUBLE, "double")
|
||||
|
||||
#define Z_EXPECTED_TYPE_ENUM(id, str) id,
|
||||
#define Z_EXPECTED_TYPE_STR(id, str) str,
|
||||
|
||||
typedef enum _zend_expected_type {
|
||||
Z_EXPECTED_TYPES(Z_EXPECTED_TYPE_ENUM)
|
||||
Z_EXPECTED_LAST
|
||||
} zend_expected_type;
|
||||
|
||||
ZEND_API int parse_arg_object_to_str(zval *arg, zend_string **str, int type TSRMLS_DC);
|
||||
ZEND_API void zend_wrong_paramers_count_error(int num_args, int min_num_args, int max_num_args TSRMLS_DC);
|
||||
ZEND_API void zend_wrong_paramer_type_error(int num, zend_expected_type expected_type, zval *arg TSRMLS_DC);
|
||||
ZEND_API void zend_wrong_paramer_class_error(int num, char *name, zval *arg TSRMLS_DC);
|
||||
ZEND_API void zend_wrong_callback_error(int severity, int num, char *error TSRMLS_DC);
|
||||
ZEND_API int _z_param_class(zval *arg, zend_class_entry **pce, int num, int check_null TSRMLS_DC);
|
||||
|
||||
#define ZEND_PARSE_PARAMETERS_START_EX(flags, min_num_args, max_num_args) do { \
|
||||
const int _flags = (flags); \
|
||||
int _min_num_args = (min_num_args); \
|
||||
int _max_num_args = (max_num_args); \
|
||||
int _num_args = EG(current_execute_data)->num_args; \
|
||||
int _i; \
|
||||
zval *_real_arg, *_arg; \
|
||||
zend_expected_type _expected_type; \
|
||||
char *_error; \
|
||||
zend_bool _dummy; \
|
||||
((void)_i); \
|
||||
((void)_real_arg); \
|
||||
((void)_arg); \
|
||||
((void)_expected_type); \
|
||||
((void)_error); \
|
||||
((void)_dummy); \
|
||||
if (UNEXPECTED(_num_args < _min_num_args) || \
|
||||
(UNEXPECTED(_num_args > _max_num_args) && \
|
||||
EXPECTED(_max_num_args >= 0))) { \
|
||||
if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \
|
||||
zend_wrong_paramers_count_error(_num_args, _min_num_args, _max_num_args TSRMLS_CC); \
|
||||
} \
|
||||
goto zend_parse_params_failure; \
|
||||
} \
|
||||
_i = 0; \
|
||||
_real_arg = ZEND_CALL_ARG(EG(current_execute_data), 0);
|
||||
|
||||
#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args) \
|
||||
ZEND_PARSE_PARAMETERS_START_EX(0, min_num_args, max_num_args)
|
||||
|
||||
#define ZEND_PARSE_PARAMETERS_END_EX(failure) \
|
||||
if (0) { \
|
||||
zend_parse_params_wrong_callback: ZEND_ATTRIBUTE_UNUSED_LABEL \
|
||||
if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \
|
||||
zend_wrong_callback_error(E_WARNING, _i, _error TSRMLS_CC); \
|
||||
} \
|
||||
goto zend_parse_params_failure; \
|
||||
zend_parse_params_wrong_class: ZEND_ATTRIBUTE_UNUSED_LABEL \
|
||||
if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \
|
||||
zend_wrong_paramer_class_error(_i, _error, _arg TSRMLS_CC); \
|
||||
} \
|
||||
goto zend_parse_params_failure; \
|
||||
zend_parse_params_wrong_arg: ZEND_ATTRIBUTE_UNUSED_LABEL \
|
||||
if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \
|
||||
zend_wrong_paramer_type_error(_i, _expected_type, _arg TSRMLS_CC); \
|
||||
} \
|
||||
zend_parse_params_failure: ZEND_ATTRIBUTE_UNUSED_LABEL \
|
||||
failure; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ZEND_PARSE_PARAMETERS_END() \
|
||||
ZEND_PARSE_PARAMETERS_END_EX(return)
|
||||
|
||||
#define Z_PARAM_PROLOGUE(separate) \
|
||||
if (UNEXPECTED(++_i >_num_args)) break; \
|
||||
_real_arg++; \
|
||||
_arg = _real_arg; \
|
||||
ZVAL_DEREF(_arg); \
|
||||
if (separate) { \
|
||||
SEPARATE_ZVAL_NOREF(_arg); \
|
||||
}
|
||||
|
||||
/* old "|" */
|
||||
#define Z_PARAM_OPTIONAL
|
||||
|
||||
/* old "a" */
|
||||
#define Z_PARAM_ARRAY_EX(dest, check_null, separate) do { \
|
||||
Z_PARAM_PROLOGUE(separate); \
|
||||
if (!_z_param_array(_arg, &dest, check_null, 0)) { \
|
||||
_expected_type = Z_EXPECTED_ARRAY; \
|
||||
goto zend_parse_params_wrong_arg; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define Z_PARAM_ARRAY(dest) \
|
||||
Z_PARAM_ARRAY_EX(dest, 0, 0)
|
||||
|
||||
/* old "A" */
|
||||
#define Z_PARAM_ARRAY_OR_OBJECT_EX(dest, check_null, separate) do { \
|
||||
Z_PARAM_PROLOGUE(separate); \
|
||||
if (!_z_param_array(_arg, &dest, check_null, 1)) { \
|
||||
_expected_type = Z_EXPECTED_ARRAY; \
|
||||
goto zend_parse_params_wrong_arg; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define Z_PARAM_ARRAY_OR_OBJECT(dest, check_null, separate) \
|
||||
Z_PARAM_ARRAY_OR_OBJECT_EX(dest, 0, 0)
|
||||
|
||||
/* old "b" */
|
||||
#define Z_PARAM_BOOL_EX(dest, is_null, check_null, separate) do { \
|
||||
Z_PARAM_PROLOGUE(separate); \
|
||||
if (!_z_param_bool(_arg, &dest, &is_null, check_null TSRMLS_CC)) { \
|
||||
_expected_type = Z_EXPECTED_BOOL; \
|
||||
goto zend_parse_params_wrong_arg; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define Z_PARAM_BOOL(dest) \
|
||||
Z_PARAM_BOOL_EX(dest, _dummy, 0, 0)
|
||||
|
||||
/* old "C" */
|
||||
#define Z_PARAM_CLASS_EX(dest, check_null, separate) do { \
|
||||
Z_PARAM_PROLOGUE(separate); \
|
||||
if (!_z_param_class(_arg, &dest, _i, check_null TSRMLS_CC)) { \
|
||||
goto zend_parse_params_failure; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define Z_PARAM_CLASS(dest) \
|
||||
Z_PARAM_CLASS_EX(dest, 0, 0)
|
||||
|
||||
/* old "d" */
|
||||
#define Z_PARAM_DOUBLE_EX(dest, is_null, check_null, separate) do { \
|
||||
Z_PARAM_PROLOGUE(separate); \
|
||||
if (!_z_param_double(_arg, &dest, &is_null, check_null)) { \
|
||||
_expected_type = Z_EXPECTED_DOUBLE; \
|
||||
goto zend_parse_params_wrong_arg; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define Z_PARAM_DOUBLE(dest) \
|
||||
Z_PARAM_DOUBLE_EX(dest, _dummy, 0, 0)
|
||||
|
||||
/* old "f" */
|
||||
#define Z_PARAM_FUNC_EX(dest_fci, dest_fcc, check_null, separate) do { \
|
||||
Z_PARAM_PROLOGUE(separate); \
|
||||
if (!_z_param_func(_arg, &dest_fci, &dest_fcc, check_null, &_error TSRMLS_CC)) { \
|
||||
if (!_error) { \
|
||||
_expected_type = Z_EXPECTED_FUNC; \
|
||||
goto zend_parse_params_wrong_arg; \
|
||||
} else { \
|
||||
goto zend_parse_params_wrong_callback; \
|
||||
} \
|
||||
} else if (_error) { \
|
||||
zend_wrong_callback_error(E_STRICT, _i, _error TSRMLS_CC); \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define Z_PARAM_FUNC(dest_fci, dest_fcc) \
|
||||
Z_PARAM_FUNC_EX(dest_fci, dest_fcc, 0, 0)
|
||||
|
||||
/* old "h" */
|
||||
#define Z_PARAM_ARRAY_HT_EX(dest, check_null, separate) do { \
|
||||
Z_PARAM_PROLOGUE(separate); \
|
||||
if (!_z_param_array_ht(_arg, &dest, check_null, 0 TSRMLS_CC)) { \
|
||||
_expected_type = Z_EXPECTED_ARRAY; \
|
||||
goto zend_parse_params_wrong_arg; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define Z_PARAM_ARRAY_HT(dest) \
|
||||
Z_PARAM_ARRAY_HT_EX(dest, 0, 0)
|
||||
|
||||
/* old "H" */
|
||||
#define Z_PARAM_ARRAY_OR_OBJECT_HT_EX(dest, check_null, separate) do { \
|
||||
Z_PARAM_PROLOGUE(separate); \
|
||||
if (!_z_param_array_ht(_arg, &dest, check_null, 1 TSRMLS_CC)) { \
|
||||
_expected_type = Z_EXPECTED_ARRAY; \
|
||||
goto zend_parse_params_wrong_arg; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define Z_PARAM_ARRAY_OR_OBJECT_HT(dest) \
|
||||
Z_PARAM_ARRAY_OR_OBJECT_HT_EX(dest, 0, 0)
|
||||
|
||||
/* old "l" */
|
||||
#define Z_PARAM_LONG_EX(dest, is_null, check_null, separate) do { \
|
||||
Z_PARAM_PROLOGUE(separate); \
|
||||
if (!_z_param_long(_arg, &dest, &is_null, check_null, 0)) { \
|
||||
_expected_type = Z_EXPECTED_LONG; \
|
||||
goto zend_parse_params_wrong_arg; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define Z_PARAM_LONG(dest) \
|
||||
Z_PARAM_LONG_EX(dest, _dummy, 0, 0)
|
||||
|
||||
/* old "L" */
|
||||
#define Z_PARAM_STRICT_LONG_EX(dest, is_null, check_null, separate) do { \
|
||||
Z_PARAM_PROLOGUE(separate); \
|
||||
if (!_z_param_long(_arg, &dest, &is_null, check_null, 1)) { \
|
||||
_expected_type = Z_EXPECTED_LONG; \
|
||||
goto zend_parse_params_wrong_arg; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define Z_PARAM_STRICT_LONG(dest) \
|
||||
Z_PARAM_STRICT_LONG_EX(dest, _dummy, 0, 0)
|
||||
|
||||
/* old "o" */
|
||||
#define Z_PARAM_OBJECT_EX(dest, check_null, separate) do { \
|
||||
Z_PARAM_PROLOGUE(separate); \
|
||||
if (!_z_param_object(_arg, &dest, NULL, check_null TSRMLS_CC)) { \
|
||||
_expected_type = Z_EXPECTED_OBJECT; \
|
||||
goto zend_parse_params_wrong_arg; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define Z_PARAM_OBJECT(dest) \
|
||||
Z_PARAM_OBJECT_EX(dest, 0, 0)
|
||||
|
||||
/* old "O" */
|
||||
#define Z_PARAM_OBJECT_OF_CLASS_EX(dest, _ce, check_null, separate) do { \
|
||||
Z_PARAM_PROLOGUE(separate); \
|
||||
if (!_z_param_object(_arg, &dest, _ce, check_null TSRMLS_CC)) { \
|
||||
if (_ce) { \
|
||||
_error = (_ce)->name->val; \
|
||||
goto zend_parse_params_wrong_class; \
|
||||
} else { \
|
||||
_expected_type = Z_EXPECTED_OBJECT; \
|
||||
goto zend_parse_params_wrong_arg; \
|
||||
} \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define Z_PARAM_OBJECT_OF_CLASS(dest, _ce) \
|
||||
Z_PARAM_OBJECT_OF_CLASS_EX(dest, _ce, 0, 0)
|
||||
|
||||
/* old "p" */
|
||||
#define Z_PARAM_PATH_EX(dest, dest_len, check_null, separate) do { \
|
||||
Z_PARAM_PROLOGUE(separate); \
|
||||
if (!_z_param_path(_arg, &dest, &dest_len, check_null TSRMLS_CC)) { \
|
||||
_expected_type = Z_EXPECTED_PATH; \
|
||||
goto zend_parse_params_wrong_arg; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define Z_PARAM_PATH(dest, dest_len) \
|
||||
Z_PARAM_PATH_EX(dest, dest_len, 0, 0)
|
||||
|
||||
/* old "P" */
|
||||
#define Z_PARAM_PATH_STR_EX(dest, check_null, separate) do { \
|
||||
Z_PARAM_PROLOGUE(separate); \
|
||||
if (!_z_param_path_str(_arg, &dest, check_null TSRMLS_CC)) { \
|
||||
_expected_type = Z_EXPECTED_PATH; \
|
||||
goto zend_parse_params_wrong_arg; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define Z_PARAM_PATH_STR(dest) \
|
||||
Z_PARAM_PATH_STR_EX(dest, 0, 0)
|
||||
|
||||
/* old "r" */
|
||||
#define Z_PARAM_RESOURCE_EX(dest, check_null, separate) do { \
|
||||
Z_PARAM_PROLOGUE(separate); \
|
||||
if (!_z_param_resource(_arg, &dest, check_null)) { \
|
||||
_expected_type = Z_EXPECTED_RESOURCE; \
|
||||
goto zend_parse_params_wrong_arg; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define Z_PARAM_RESOURCE(dest) \
|
||||
Z_PARAM_RESOURCE_EX(dest, 0, 0)
|
||||
|
||||
/* old "s" */
|
||||
#define Z_PARAM_STRING_EX(dest, dest_len, check_null, separate) do { \
|
||||
Z_PARAM_PROLOGUE(separate); \
|
||||
if (!_z_param_string(_arg, &dest, &dest_len, check_null TSRMLS_CC)) { \
|
||||
_expected_type = Z_EXPECTED_STRING; \
|
||||
goto zend_parse_params_wrong_arg; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define Z_PARAM_STRING(dest, dest_len) \
|
||||
Z_PARAM_STRING_EX(dest, dest_len, 0, 0)
|
||||
|
||||
/* old "S" */
|
||||
#define Z_PARAM_STR_EX(dest, check_null, separate) do { \
|
||||
Z_PARAM_PROLOGUE(separate); \
|
||||
if (!_z_param_str(_arg, &dest, check_null TSRMLS_CC)) { \
|
||||
_expected_type = Z_EXPECTED_STRING; \
|
||||
goto zend_parse_params_wrong_arg; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define Z_PARAM_STR(dest) \
|
||||
Z_PARAM_STR_EX(dest, 0, 0)
|
||||
|
||||
/* old "z" */
|
||||
#define Z_PARAM_ZVAL_EX(dest, check_null, separate) do { \
|
||||
if (separate) { \
|
||||
Z_PARAM_PROLOGUE(separate); \
|
||||
_z_param_zval_deref(_arg, &dest, check_null); \
|
||||
} else { \
|
||||
if (UNEXPECTED(++_i >_num_args)) break; \
|
||||
_real_arg++; \
|
||||
_z_param_zval(_real_arg, &dest, check_null); \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define Z_PARAM_ZVAL(dest) \
|
||||
Z_PARAM_ZVAL_EX(dest, 0, 0)
|
||||
|
||||
/* old "z" (with dereference) */
|
||||
#define Z_PARAM_ZVAL_DEREF_EX(dest, check_null, separate) do { \
|
||||
Z_PARAM_PROLOGUE(separate); \
|
||||
_z_param_zval_deref(_arg, &dest, check_null); \
|
||||
} while (0);
|
||||
|
||||
#define Z_PARAM_ZVAL_DEREF(dest) \
|
||||
Z_PARAM_ZVAL_DEREF_EX(dest, 0, 0)
|
||||
|
||||
/* old "+" and "*" */
|
||||
#define Z_PARAM_VARIADIC_EX(spec, dest, dest_num, post_varargs) do { \
|
||||
int _num_varargs = _num_args - _i - (post_varargs); \
|
||||
if (_num_varargs > 0) { \
|
||||
dest = _real_arg + 1; \
|
||||
dest_num = _num_varargs; \
|
||||
_i += _num_varargs; \
|
||||
_real_arg += _num_varargs; \
|
||||
} else { \
|
||||
dest = NULL; \
|
||||
dest_num = 0; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define Z_PARAM_VARIADIC(spec, dest, dest_num) \
|
||||
Z_PARAM_VARIADIC_EX(spec, dest, dest_num, 0)
|
||||
|
||||
/* Private part of new parameter parsing API */
|
||||
|
||||
static zend_always_inline int _z_param_bool(zval *arg, zend_bool *dest, zend_bool *is_null, int check_null TSRMLS_DC)
|
||||
{
|
||||
if (check_null) {
|
||||
*is_null = 0;
|
||||
}
|
||||
if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
|
||||
*dest = 1;
|
||||
} else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
|
||||
if (check_null) {
|
||||
*is_null = (Z_TYPE_P(arg) == IS_NULL);
|
||||
}
|
||||
*dest = 0;
|
||||
} else if (EXPECTED(Z_TYPE_P(arg) <= IS_STRING)) {
|
||||
*dest = zend_is_true(arg TSRMLS_CC);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static zend_always_inline int _z_param_long(zval *arg, long *dest, zend_bool *is_null, int check_null, int strict)
|
||||
{
|
||||
if (check_null) {
|
||||
*is_null = 0;
|
||||
}
|
||||
if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
|
||||
if (strict && UNEXPECTED(Z_DVAL_P(arg) > LONG_MAX)) {
|
||||
*dest = LONG_MAX;
|
||||
} else if (strict && UNEXPECTED(Z_DVAL_P(arg) < LONG_MIN)) {
|
||||
*dest = LONG_MIN;
|
||||
} else {
|
||||
*dest = Z_LVAL_P(arg);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(arg) == IS_DOUBLE)) {
|
||||
*dest = zend_dval_to_lval(Z_DVAL_P(arg));
|
||||
} else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
|
||||
double d;
|
||||
int type;
|
||||
|
||||
if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), dest, &d)) != IS_LONG)) {
|
||||
if (EXPECTED(type != 0)) {
|
||||
if (strict && UNEXPECTED(d > LONG_MAX)) {
|
||||
*dest = LONG_MAX;
|
||||
} else if (strict && UNEXPECTED(d < LONG_MIN)) {
|
||||
*dest = LONG_MIN;
|
||||
} else {
|
||||
*dest = zend_dval_to_lval(d);
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
|
||||
if (check_null) {
|
||||
*is_null = (Z_TYPE_P(arg) == IS_NULL);
|
||||
}
|
||||
*dest = 0;
|
||||
} else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
|
||||
*dest = 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static zend_always_inline int _z_param_double(zval *arg, double *dest, zend_bool *is_null, int check_null)
|
||||
{
|
||||
if (check_null) {
|
||||
*is_null = 0;
|
||||
}
|
||||
if (EXPECTED(Z_TYPE_P(arg) == IS_DOUBLE)) {
|
||||
*dest = Z_DVAL_P(arg);
|
||||
} else if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
|
||||
*dest = (double)Z_LVAL_P(arg);
|
||||
} else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
|
||||
long l;
|
||||
int type;
|
||||
|
||||
if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), &l, dest)) != IS_DOUBLE)) {
|
||||
if (EXPECTED(type != 0)) {
|
||||
*dest = (double)(l);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
|
||||
if (check_null) {
|
||||
*is_null = (Z_TYPE_P(arg) == IS_NULL);
|
||||
}
|
||||
*dest = 0.0;
|
||||
} else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
|
||||
*dest = 1.0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static zend_always_inline int _z_param_str(zval *arg, zend_string **dest, int check_null TSRMLS_DC)
|
||||
{
|
||||
if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
|
||||
*dest = Z_STR_P(arg);
|
||||
} else if (EXPECTED(Z_TYPE_P(arg) < IS_STRING)) {
|
||||
if (check_null && UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
|
||||
*dest = NULL;
|
||||
} else {
|
||||
if (Z_COPYABLE_P(arg) && Z_REFCOUNT_P(arg) > 1) {
|
||||
Z_DELREF_P(arg);
|
||||
zval_copy_ctor_func(arg);
|
||||
}
|
||||
convert_to_string(arg);
|
||||
*dest = Z_STR_P(arg);
|
||||
}
|
||||
} else if (UNEXPECTED(Z_TYPE_P(arg) != IS_OBJECT) ||
|
||||
UNEXPECTED(parse_arg_object_to_str(arg, dest, IS_STRING TSRMLS_CC) != SUCCESS)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static zend_always_inline int _z_param_string(zval *arg, char **dest, int *dest_len, int check_null TSRMLS_DC)
|
||||
{
|
||||
zend_string *str;
|
||||
|
||||
if (!_z_param_str(arg, &str, check_null TSRMLS_CC)) {
|
||||
return 0;
|
||||
}
|
||||
if (check_null && UNEXPECTED(!str)) {
|
||||
*dest = NULL;
|
||||
*dest_len = 0;
|
||||
} else {
|
||||
*dest = str->val;
|
||||
*dest_len = str->len;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static zend_always_inline int _z_param_path_str(zval *arg, zend_string **dest, int check_null TSRMLS_DC)
|
||||
{
|
||||
if (!_z_param_str(arg, dest, check_null TSRMLS_CC) ||
|
||||
(check_null && UNEXPECTED(!(*dest)->val)) ||
|
||||
UNEXPECTED(CHECK_NULL_PATH((*dest)->val, (*dest)->len))) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static zend_always_inline int _z_param_path(zval *arg, char **dest, int *dest_len, int check_null TSRMLS_DC)
|
||||
{
|
||||
zend_string *str;
|
||||
|
||||
if (!_z_param_path_str(arg, &str, check_null TSRMLS_CC)) {
|
||||
return 0;
|
||||
}
|
||||
if (check_null && UNEXPECTED(!str)) {
|
||||
*dest = NULL;
|
||||
*dest_len = 0;
|
||||
} else {
|
||||
*dest = str->val;
|
||||
*dest_len = str->len;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static zend_always_inline int _z_param_array(zval *arg, zval **dest, int check_null, int or_object)
|
||||
{
|
||||
if (EXPECTED(Z_TYPE_P(arg) == IS_ARRAY) ||
|
||||
(or_object && EXPECTED(Z_TYPE_P(arg) == IS_OBJECT))) {
|
||||
*dest = arg;
|
||||
} else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
|
||||
*dest = NULL;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static zend_always_inline int _z_param_array_ht(zval *arg, HashTable **dest, int check_null, int or_object TSRMLS_DC)
|
||||
{
|
||||
if (EXPECTED(Z_TYPE_P(arg) == IS_ARRAY)) {
|
||||
*dest = Z_ARRVAL_P(arg);
|
||||
} else if (or_object && EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
|
||||
*dest = Z_OBJ_HT_P(arg)->get_properties(arg TSRMLS_CC);
|
||||
} else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
|
||||
*dest = NULL;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static zend_always_inline int _z_param_object(zval *arg, zval **dest, zend_class_entry *ce, int check_null TSRMLS_DC)
|
||||
{
|
||||
if (EXPECTED(Z_TYPE_P(arg) == IS_OBJECT) &&
|
||||
(!ce || EXPECTED(instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC) != 0))) {
|
||||
*dest = arg;
|
||||
} else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
|
||||
*dest = NULL;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static zend_always_inline int _z_param_resource(zval *arg, zval **dest, int check_null)
|
||||
{
|
||||
if (EXPECTED(Z_TYPE_P(arg) == IS_RESOURCE)) {
|
||||
*dest = arg;
|
||||
} else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
|
||||
*dest = NULL;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static zend_always_inline int _z_param_func(zval *arg, zend_fcall_info *dest_fci, zend_fcall_info_cache *dest_fcc, int check_null, char **error TSRMLS_DC)
|
||||
{
|
||||
if (check_null && UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
|
||||
dest_fci->size = 0;
|
||||
dest_fcc->initialized = 0;
|
||||
*error = NULL;
|
||||
} else if (UNEXPECTED(zend_fcall_info_init(arg, 0, dest_fci, dest_fcc, NULL, error TSRMLS_CC) != SUCCESS)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static zend_always_inline void _z_param_zval(zval *arg, zval **dest, int check_null)
|
||||
{
|
||||
*dest = (check_null &&
|
||||
(UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) ||
|
||||
(UNEXPECTED(Z_ISREF_P(arg)) &&
|
||||
UNEXPECTED(Z_TYPE_P(Z_REFVAL_P(arg)) == IS_NULL)))) ? NULL : arg;
|
||||
}
|
||||
|
||||
static zend_always_inline void _z_param_zval_deref(zval *arg, zval **dest, int check_null)
|
||||
{
|
||||
*dest = (check_null && UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) ? NULL : arg;
|
||||
}
|
||||
|
||||
#endif /* FAST_ZPP */
|
||||
|
||||
/* End of new parameter parsing API */
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
#endif /* ZEND_API_H */
|
||||
|
@ -1761,9 +1761,19 @@ static void zend_mm_safe_error(zend_mm_heap *heap,
|
||||
zend_string *str = zend_get_compiled_filename(TSRMLS_C);
|
||||
error_filename = str ? str->val : NULL;
|
||||
error_lineno = zend_get_compiled_lineno(TSRMLS_C);
|
||||
} else if (EG(in_execution)) {
|
||||
error_filename = EG(active_op_array)?EG(active_op_array)->filename->val:NULL;
|
||||
error_lineno = EG(opline_ptr)?(*EG(opline_ptr))->lineno:0;
|
||||
} else if (EG(current_execute_data)) {
|
||||
zend_execute_data *ex = EG(current_execute_data);
|
||||
|
||||
while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
|
||||
ex = ex->prev_execute_data;
|
||||
}
|
||||
if (ex) {
|
||||
error_filename = ex->func->op_array.filename->val;
|
||||
error_lineno = ex->opline->lineno;
|
||||
} else {
|
||||
error_filename = NULL;
|
||||
error_lineno = 0;
|
||||
}
|
||||
} else {
|
||||
error_filename = NULL;
|
||||
error_lineno = 0;
|
||||
|
118
Zend/zend_arena.h
Normal file
118
Zend/zend_arena.h
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend Engine |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1998-2014 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> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id:$ */
|
||||
|
||||
#ifndef _ZEND_ARENA_H_
|
||||
#define _ZEND_ARENA_H_
|
||||
|
||||
#include "zend.h"
|
||||
|
||||
typedef struct _zend_arena zend_arena;
|
||||
|
||||
struct _zend_arena {
|
||||
char *ptr;
|
||||
char *end;
|
||||
zend_arena *prev;
|
||||
};
|
||||
|
||||
static zend_always_inline zend_arena* zend_arena_create(size_t size)
|
||||
{
|
||||
zend_arena *arena = (zend_arena*)emalloc(size);
|
||||
|
||||
arena->ptr = (char*) arena + ZEND_MM_ALIGNED_SIZE(sizeof(zend_arena));
|
||||
arena->end = (char*) arena + size;
|
||||
arena->prev = NULL;
|
||||
return arena;
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_arena_destroy(zend_arena *arena)
|
||||
{
|
||||
do {
|
||||
zend_arena *prev = arena->prev;
|
||||
efree(arena);
|
||||
arena = prev;
|
||||
} while (arena);
|
||||
}
|
||||
|
||||
#define ZEND_ARENA_ALIGNMENT 8U
|
||||
|
||||
static zend_always_inline void* zend_arena_alloc(zend_arena **arena_ptr, size_t size)
|
||||
{
|
||||
zend_arena *arena = *arena_ptr;
|
||||
char *ptr = arena->ptr;
|
||||
|
||||
size = ZEND_MM_ALIGNED_SIZE(size);
|
||||
|
||||
if (EXPECTED(size <= (size_t)(arena->end - ptr))) {
|
||||
arena->ptr = ptr + size;
|
||||
} else {
|
||||
size_t arena_size =
|
||||
UNEXPECTED((size + ZEND_MM_ALIGNED_SIZE(sizeof(zend_arena))) > (size_t)(arena->end - (char*) arena)) ?
|
||||
(size + ZEND_MM_ALIGNED_SIZE(sizeof(zend_arena))) :
|
||||
(arena->end - (char*) arena);
|
||||
zend_arena *new_arena = (zend_arena*)emalloc(arena_size);
|
||||
|
||||
ptr = (char*) new_arena + ZEND_MM_ALIGNED_SIZE(sizeof(zend_arena));
|
||||
new_arena->ptr = (char*) new_arena + ZEND_MM_ALIGNED_SIZE(sizeof(zend_arena)) + size;
|
||||
new_arena->end = (char*) new_arena + arena_size;
|
||||
new_arena->prev = arena;
|
||||
*arena_ptr = new_arena;
|
||||
}
|
||||
|
||||
return (void*) ptr;
|
||||
}
|
||||
|
||||
static zend_always_inline void* zend_arena_calloc(zend_arena **arena_ptr, size_t count, size_t unit_size)
|
||||
{
|
||||
size_t size = unit_size * count;
|
||||
void *ret;
|
||||
|
||||
ZEND_ASSERT(size >= unit_size && size >= count);
|
||||
ret = zend_arena_alloc(arena_ptr, size);
|
||||
memset(ret, 0, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static zend_always_inline void* zend_arena_checkpoint(zend_arena *arena)
|
||||
{
|
||||
return arena->ptr;
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_arena_release(zend_arena **arena_ptr, void *checkpoint)
|
||||
{
|
||||
zend_arena *arena = *arena_ptr;
|
||||
|
||||
while (UNEXPECTED((char*)checkpoint > arena->end) ||
|
||||
UNEXPECTED((char*)checkpoint < (char*)arena)) {
|
||||
zend_arena *prev = arena->prev;
|
||||
efree(arena);
|
||||
*arena_ptr = arena = prev;
|
||||
}
|
||||
arena->ptr = (char*)checkpoint;
|
||||
}
|
||||
|
||||
#endif /* _ZEND_ARENA_H_ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
@ -308,6 +308,20 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s
|
||||
}
|
||||
}
|
||||
break;
|
||||
//???
|
||||
#if 0
|
||||
case ZEND_FETCH_DIM_R:
|
||||
zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
|
||||
zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
|
||||
{
|
||||
zval *tmp;
|
||||
zend_fetch_dimension_by_zval(&tmp, &op1, &op2 TSRMLS_CC);
|
||||
ZVAL_ZVAL(result, tmp, 1, 1);
|
||||
}
|
||||
zval_dtor(&op1);
|
||||
zval_dtor(&op2);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
zend_error(E_ERROR, "Unsupported constant expression");
|
||||
}
|
||||
|
@ -245,16 +245,16 @@ static const zend_function_entry builtin_functions[] = { /* {{{ */
|
||||
ZEND_FE(func_num_args, arginfo_zend__void)
|
||||
ZEND_FE(func_get_arg, arginfo_func_get_arg)
|
||||
ZEND_FE(func_get_args, arginfo_zend__void)
|
||||
ZEND_FE(strlen, arginfo_strlen)
|
||||
ZEND_FE(strcmp, arginfo_strcmp)
|
||||
ZEND_FE(strncmp, arginfo_strncmp)
|
||||
ZEND_FE(strcasecmp, arginfo_strcmp)
|
||||
ZEND_FE(strlen, arginfo_strlen)
|
||||
ZEND_FE(strcmp, arginfo_strcmp)
|
||||
ZEND_FE(strncmp, arginfo_strncmp)
|
||||
ZEND_FE(strcasecmp, arginfo_strcmp)
|
||||
ZEND_FE(strncasecmp, arginfo_strncmp)
|
||||
ZEND_FE(each, arginfo_each)
|
||||
ZEND_FE(each, arginfo_each)
|
||||
ZEND_FE(error_reporting, arginfo_error_reporting)
|
||||
ZEND_FE(define, arginfo_define)
|
||||
ZEND_FE(defined, arginfo_defined)
|
||||
ZEND_FE(get_class, arginfo_get_class)
|
||||
ZEND_FE(define, arginfo_define)
|
||||
ZEND_FE(defined, arginfo_defined)
|
||||
ZEND_FE(get_class, arginfo_get_class)
|
||||
ZEND_FE(get_called_class, arginfo_zend__void)
|
||||
ZEND_FE(get_parent_class, arginfo_get_class)
|
||||
ZEND_FE(method_exists, arginfo_method_exists)
|
||||
@ -274,13 +274,13 @@ static const zend_function_entry builtin_functions[] = { /* {{{ */
|
||||
ZEND_FE(get_included_files, arginfo_zend__void)
|
||||
ZEND_FALIAS(get_required_files, get_included_files, arginfo_zend__void)
|
||||
ZEND_FE(is_subclass_of, arginfo_is_subclass_of)
|
||||
ZEND_FE(is_a, arginfo_is_subclass_of)
|
||||
ZEND_FE(is_a, arginfo_is_subclass_of)
|
||||
ZEND_FE(get_class_vars, arginfo_get_class_vars)
|
||||
ZEND_FE(get_object_vars, arginfo_get_object_vars)
|
||||
ZEND_FE(get_class_methods, arginfo_get_class_methods)
|
||||
ZEND_FE(trigger_error, arginfo_trigger_error)
|
||||
ZEND_FALIAS(user_error, trigger_error, arginfo_trigger_error)
|
||||
ZEND_FE(set_error_handler, arginfo_set_error_handler)
|
||||
ZEND_FE(set_error_handler, arginfo_set_error_handler)
|
||||
ZEND_FE(restore_error_handler, arginfo_zend__void)
|
||||
ZEND_FE(set_exception_handler, arginfo_set_exception_handler)
|
||||
ZEND_FE(restore_exception_handler, arginfo_zend__void)
|
||||
@ -288,14 +288,14 @@ static const zend_function_entry builtin_functions[] = { /* {{{ */
|
||||
ZEND_FE(get_declared_traits, arginfo_zend__void)
|
||||
ZEND_FE(get_declared_interfaces, arginfo_zend__void)
|
||||
ZEND_FE(get_defined_functions, arginfo_zend__void)
|
||||
ZEND_FE(get_defined_vars, arginfo_zend__void)
|
||||
ZEND_FE(create_function, arginfo_create_function)
|
||||
ZEND_FE(get_resource_type, arginfo_get_resource_type)
|
||||
ZEND_FE(get_defined_vars, arginfo_zend__void)
|
||||
ZEND_FE(create_function, arginfo_create_function)
|
||||
ZEND_FE(get_resource_type, arginfo_get_resource_type)
|
||||
ZEND_FE(get_loaded_extensions, arginfo_get_loaded_extensions)
|
||||
ZEND_FE(extension_loaded, arginfo_extension_loaded)
|
||||
ZEND_FE(extension_loaded, arginfo_extension_loaded)
|
||||
ZEND_FE(get_extension_funcs, arginfo_extension_loaded)
|
||||
ZEND_FE(get_defined_constants, arginfo_get_defined_constants)
|
||||
ZEND_FE(debug_backtrace, arginfo_debug_backtrace)
|
||||
ZEND_FE(debug_backtrace, arginfo_debug_backtrace)
|
||||
ZEND_FE(debug_print_backtrace, arginfo_debug_print_backtrace)
|
||||
#if ZEND_DEBUG
|
||||
ZEND_FE(zend_test_func, NULL)
|
||||
@ -305,7 +305,7 @@ static const zend_function_entry builtin_functions[] = { /* {{{ */
|
||||
#endif
|
||||
ZEND_FE(gc_collect_cycles, arginfo_zend__void)
|
||||
ZEND_FE(gc_enabled, arginfo_zend__void)
|
||||
ZEND_FE(gc_enable, arginfo_zend__void)
|
||||
ZEND_FE(gc_enable, arginfo_zend__void)
|
||||
ZEND_FE(gc_disable, arginfo_zend__void)
|
||||
ZEND_FE_END
|
||||
};
|
||||
@ -396,8 +396,8 @@ ZEND_FUNCTION(func_num_args)
|
||||
{
|
||||
zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
|
||||
|
||||
if (ex && ex->function_state.arguments) {
|
||||
RETURN_LONG(Z_LVAL_P(ex->function_state.arguments));
|
||||
if (ex->frame_kind == VM_FRAME_NESTED_FUNCTION || ex->frame_kind == VM_FRAME_TOP_FUNCTION) {
|
||||
RETURN_LONG(ex->num_args);
|
||||
} else {
|
||||
zend_error(E_WARNING, "func_num_args(): Called from the global scope - no function context");
|
||||
RETURN_LONG(-1);
|
||||
@ -409,11 +409,10 @@ ZEND_FUNCTION(func_num_args)
|
||||
Get the $arg_num'th argument that was passed to the function */
|
||||
ZEND_FUNCTION(func_get_arg)
|
||||
{
|
||||
zval *p;
|
||||
int arg_count;
|
||||
int arg_count, first_extra_arg;
|
||||
zval *arg;
|
||||
long requested_offset;
|
||||
zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
|
||||
zend_execute_data *ex;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &requested_offset) == FAILURE) {
|
||||
return;
|
||||
@ -424,20 +423,28 @@ ZEND_FUNCTION(func_get_arg)
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (!ex || !ex->function_state.arguments) {
|
||||
ex = EG(current_execute_data)->prev_execute_data;
|
||||
if (ex->frame_kind != VM_FRAME_NESTED_FUNCTION && ex->frame_kind != VM_FRAME_TOP_FUNCTION) {
|
||||
zend_error(E_WARNING, "func_get_arg(): Called from the global scope - no function context");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
p = ex->function_state.arguments;
|
||||
arg_count = Z_LVAL_P(p); /* this is the amount of arguments passed to func_get_arg(); */
|
||||
arg_count = ex->num_args;
|
||||
|
||||
if (requested_offset >= arg_count) {
|
||||
zend_error(E_WARNING, "func_get_arg(): Argument %ld not passed to function", requested_offset);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
arg = p-(arg_count-requested_offset);
|
||||
first_extra_arg = ex->func->op_array.num_args;
|
||||
if (ex->func->op_array.fn_flags & ZEND_ACC_VARIADIC) {
|
||||
first_extra_arg--;
|
||||
}
|
||||
if (requested_offset >= first_extra_arg && (ex->num_args > first_extra_arg)) {
|
||||
arg = EX_VAR_NUM_2(ex, ex->func->op_array.last_var + ex->func->op_array.T) + (requested_offset - first_extra_arg);
|
||||
} else {
|
||||
arg = ZEND_CALL_ARG(ex, requested_offset + 1);
|
||||
}
|
||||
RETURN_ZVAL_FAST(arg);
|
||||
}
|
||||
/* }}} */
|
||||
@ -447,26 +454,45 @@ ZEND_FUNCTION(func_get_arg)
|
||||
ZEND_FUNCTION(func_get_args)
|
||||
{
|
||||
zval *p;
|
||||
int arg_count;
|
||||
int arg_count, first_extra_arg;
|
||||
int i;
|
||||
zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
|
||||
|
||||
if (!ex || !ex->function_state.arguments) {
|
||||
if (ex->frame_kind != VM_FRAME_NESTED_FUNCTION && ex->frame_kind != VM_FRAME_TOP_FUNCTION) {
|
||||
zend_error(E_WARNING, "func_get_args(): Called from the global scope - no function context");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
p = ex->function_state.arguments;
|
||||
arg_count = Z_LVAL_P(p); /* this is the amount of arguments passed to func_get_args(); */
|
||||
arg_count = ex->num_args;
|
||||
|
||||
array_init_size(return_value, arg_count);
|
||||
if (arg_count) {
|
||||
Bucket *q;
|
||||
|
||||
p -= arg_count;
|
||||
first_extra_arg = ex->func->op_array.num_args;
|
||||
if (ex->func->op_array.fn_flags & ZEND_ACC_VARIADIC) {
|
||||
first_extra_arg--;
|
||||
}
|
||||
zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
|
||||
i = 0;
|
||||
q = Z_ARRVAL_P(return_value)->arData;
|
||||
for (i=0; i<arg_count; i++) {
|
||||
p = ZEND_CALL_ARG(ex, 1);
|
||||
if (ex->num_args > first_extra_arg) {
|
||||
while (i < first_extra_arg) {
|
||||
q->h = i;
|
||||
q->key = NULL;
|
||||
if (!Z_ISREF_P(p)) {
|
||||
ZVAL_COPY(&q->val, p);
|
||||
} else {
|
||||
ZVAL_DUP(&q->val, Z_REFVAL_P(p));
|
||||
}
|
||||
p++;
|
||||
q++;
|
||||
i++;
|
||||
}
|
||||
p = EX_VAR_NUM_2(ex, ex->func->op_array.last_var + ex->func->op_array.T);
|
||||
}
|
||||
while (i < arg_count) {
|
||||
q->h = i;
|
||||
q->key = NULL;
|
||||
if (!Z_ISREF_P(p)) {
|
||||
@ -476,6 +502,7 @@ ZEND_FUNCTION(func_get_args)
|
||||
}
|
||||
p++;
|
||||
q++;
|
||||
i++;
|
||||
}
|
||||
Z_ARRVAL_P(return_value)->nNumUsed = i;
|
||||
Z_ARRVAL_P(return_value)->nNumOfElements = i;
|
||||
@ -491,9 +518,15 @@ ZEND_FUNCTION(strlen)
|
||||
{
|
||||
zend_string *s;
|
||||
|
||||
#ifndef FAST_ZPP
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S", &s) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||
Z_PARAM_STR(s)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
#endif
|
||||
|
||||
RETVAL_LONG(s->len);
|
||||
}
|
||||
@ -585,11 +618,10 @@ ZEND_FUNCTION(each)
|
||||
HashTable *target_hash;
|
||||
zend_string *key;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &array) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &array) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
ZVAL_DEREF(array);
|
||||
target_hash = HASH_OF(array);
|
||||
if (!target_hash) {
|
||||
zend_error(E_WARNING,"Variable passed to each() is not an array or object");
|
||||
@ -671,9 +703,18 @@ ZEND_FUNCTION(define)
|
||||
int case_sensitive = CONST_CS;
|
||||
zend_constant c;
|
||||
|
||||
#ifndef FAST_ZPP
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Sz|b", &name, &val, &non_cs) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
ZEND_PARSE_PARAMETERS_START(2, 3)
|
||||
Z_PARAM_STR(name)
|
||||
Z_PARAM_ZVAL(val)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_BOOL(non_cs)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
#endif
|
||||
|
||||
if(non_cs) {
|
||||
case_sensitive = 0;
|
||||
@ -738,9 +779,15 @@ ZEND_FUNCTION(defined)
|
||||
{
|
||||
zend_string *name;
|
||||
|
||||
#ifndef FAST_ZPP
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S", &name) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||
Z_PARAM_STR(name)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
#endif
|
||||
|
||||
if (zend_get_constant_ex(name, NULL, ZEND_FETCH_CLASS_SILENT TSRMLS_CC)) {
|
||||
RETURN_TRUE;
|
||||
@ -783,8 +830,8 @@ ZEND_FUNCTION(get_called_class)
|
||||
return;
|
||||
}
|
||||
|
||||
if (EG(called_scope)) {
|
||||
RETURN_STR(STR_COPY(EG(called_scope)->name));
|
||||
if (EG(current_execute_data)->called_scope) {
|
||||
RETURN_STR(STR_COPY(EG(current_execute_data)->called_scope->name));
|
||||
} else if (!EG(scope)) {
|
||||
zend_error(E_WARNING, "get_called_class() called from outside a class");
|
||||
}
|
||||
@ -843,9 +890,18 @@ static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass)
|
||||
zend_bool allow_string = only_subclass;
|
||||
zend_bool retval;
|
||||
|
||||
#ifndef FAST_ZPP
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zS|b", &obj, &class_name, &allow_string) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
ZEND_PARSE_PARAMETERS_START(2, 3)
|
||||
Z_PARAM_ZVAL(obj)
|
||||
Z_PARAM_STR(class_name)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_BOOL(allow_string)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
#endif
|
||||
/*
|
||||
* allow_string - is_a default is no, is_subclass_of is yes.
|
||||
* if it's allowed, then the autoloader will be called if the class does not exist.
|
||||
@ -927,15 +983,19 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value
|
||||
}
|
||||
|
||||
/* copy: enforce read only access */
|
||||
ZVAL_DUP_DEREF(&prop_copy, prop);
|
||||
ZVAL_DEREF(prop);
|
||||
if (UNEXPECTED(Z_COPYABLE_P(prop))) {
|
||||
ZVAL_DUP(&prop_copy, prop);
|
||||
prop = &prop_copy;
|
||||
}
|
||||
|
||||
/* this is necessary to make it able to work with default array
|
||||
* properties, returned to user */
|
||||
if (Z_OPT_CONSTANT(prop_copy)) {
|
||||
zval_update_constant(&prop_copy, 0 TSRMLS_CC);
|
||||
if (Z_OPT_CONSTANT_P(prop)) {
|
||||
zval_update_constant(prop, 0 TSRMLS_CC);
|
||||
}
|
||||
|
||||
zend_hash_add_new(Z_ARRVAL_P(return_value), key, &prop_copy);
|
||||
zend_hash_add_new(Z_ARRVAL_P(return_value), key, prop);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
/* }}} */
|
||||
@ -977,9 +1037,15 @@ ZEND_FUNCTION(get_object_vars)
|
||||
uint prop_len;
|
||||
zend_object *zobj;
|
||||
|
||||
#ifndef FAST_ZPP
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||
Z_PARAM_OBJECT(obj)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
#endif
|
||||
|
||||
if (Z_OBJ_HT_P(obj)->get_properties == NULL) {
|
||||
RETURN_FALSE;
|
||||
@ -1062,8 +1128,7 @@ ZEND_FUNCTION(get_class_methods)
|
||||
|
||||
/* Do not display old-style inherited constructors */
|
||||
if (!key) {
|
||||
// TODO: we have to duplicate it, becaise it may be stored in opcache SHM ???
|
||||
ZVAL_STR(&method_name, STR_DUP(mptr->common.function_name, 0));
|
||||
ZVAL_STR(&method_name, STR_COPY(mptr->common.function_name));
|
||||
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
|
||||
} else if ((mptr->common.fn_flags & ZEND_ACC_CTOR) == 0 ||
|
||||
mptr->common.scope == ce ||
|
||||
@ -1076,8 +1141,7 @@ ZEND_FUNCTION(get_class_methods)
|
||||
ZVAL_STR(&method_name, STR_COPY(zend_find_alias_name(mptr->common.scope, key)));
|
||||
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
|
||||
} else {
|
||||
// TODO: we have to duplicate it, becaise it may be stored in opcache SHM ???
|
||||
ZVAL_STR(&method_name, STR_DUP(mptr->common.function_name, 0));
|
||||
ZVAL_STR(&method_name, STR_COPY(mptr->common.function_name));
|
||||
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
|
||||
}
|
||||
}
|
||||
@ -1096,9 +1160,16 @@ ZEND_FUNCTION(method_exists)
|
||||
zend_string *lcname;
|
||||
zend_class_entry * ce;
|
||||
|
||||
#ifndef FAST_ZPP
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zS", &klass, &method_name) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
ZEND_PARSE_PARAMETERS_START(2, 2)
|
||||
Z_PARAM_ZVAL(klass)
|
||||
Z_PARAM_STR(method_name)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
#endif
|
||||
if (Z_TYPE_P(klass) == IS_OBJECT) {
|
||||
ce = Z_OBJCE_P(klass);
|
||||
} else if (Z_TYPE_P(klass) == IS_STRING) {
|
||||
@ -1182,7 +1253,7 @@ ZEND_FUNCTION(property_exists)
|
||||
|
||||
if (Z_TYPE_P(object) == IS_OBJECT &&
|
||||
Z_OBJ_HANDLER_P(object, has_property) &&
|
||||
Z_OBJ_HANDLER_P(object, has_property)(object, &property_z, 2, -1 TSRMLS_CC)) {
|
||||
Z_OBJ_HANDLER_P(object, has_property)(object, &property_z, 2, NULL TSRMLS_CC)) {
|
||||
RETURN_TRUE;
|
||||
}
|
||||
RETURN_FALSE;
|
||||
@ -1199,9 +1270,17 @@ ZEND_FUNCTION(class_exists)
|
||||
zend_class_entry *ce;
|
||||
zend_bool autoload = 1;
|
||||
|
||||
#ifndef FAST_ZPP
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S|b", &class_name, &autoload) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
ZEND_PARSE_PARAMETERS_START(1, 2)
|
||||
Z_PARAM_STR(class_name)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_BOOL(autoload)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
#endif
|
||||
|
||||
if (!autoload) {
|
||||
if (class_name->val[0] == '\\') {
|
||||
@ -1234,9 +1313,17 @@ ZEND_FUNCTION(interface_exists)
|
||||
zend_class_entry *ce;
|
||||
zend_bool autoload = 1;
|
||||
|
||||
#ifndef FAST_ZPP
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S|b", &iface_name, &autoload) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
ZEND_PARSE_PARAMETERS_START(1, 2)
|
||||
Z_PARAM_STR(iface_name)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_BOOL(autoload)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
#endif
|
||||
|
||||
if (!autoload) {
|
||||
if (iface_name->val[0] == '\\') {
|
||||
@ -1269,9 +1356,17 @@ ZEND_FUNCTION(trait_exists)
|
||||
zend_class_entry *ce;
|
||||
zend_bool autoload = 1;
|
||||
|
||||
#ifndef FAST_ZPP
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S|b", &trait_name, &autoload) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
ZEND_PARSE_PARAMETERS_START(1, 2)
|
||||
Z_PARAM_STR(trait_name)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_BOOL(autoload)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
#endif
|
||||
|
||||
if (!autoload) {
|
||||
if (trait_name->val[0] == '\\') {
|
||||
@ -1306,9 +1401,15 @@ ZEND_FUNCTION(function_exists)
|
||||
zend_function *func;
|
||||
zend_string *lcname;
|
||||
|
||||
#ifndef FAST_ZPP
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||
Z_PARAM_STRING(name, name_len)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
#endif
|
||||
|
||||
if (name[0] == '\\') {
|
||||
/* Ignore leading "\" */
|
||||
@ -1719,12 +1820,10 @@ ZEND_FUNCTION(get_defined_functions)
|
||||
Returns an associative array of names and values of all currently defined variable names (variables in the current scope) */
|
||||
ZEND_FUNCTION(get_defined_vars)
|
||||
{
|
||||
if (!EG(active_symbol_table)) {
|
||||
zend_rebuild_symbol_table(TSRMLS_C);
|
||||
}
|
||||
zend_array *symbol_table = zend_rebuild_symbol_table(TSRMLS_C);
|
||||
|
||||
ZVAL_NEW_ARR(return_value);
|
||||
zend_array_dup(Z_ARRVAL_P(return_value), &EG(active_symbol_table)->ht);
|
||||
zend_array_dup(Z_ARRVAL_P(return_value), &symbol_table->ht);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -1771,24 +1870,26 @@ ZEND_FUNCTION(create_function)
|
||||
efree(eval_name);
|
||||
|
||||
if (retval==SUCCESS) {
|
||||
zend_op_array *new_function, *func;
|
||||
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(E_ERROR, "Unexpected inconsistency in create_function()");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
new_function = emalloc(sizeof(zend_op_array));
|
||||
memcpy(new_function, func, sizeof(zend_op_array));
|
||||
function_add_ref((zend_function*)new_function);
|
||||
(*func->refcount)++;
|
||||
|
||||
function_name = STR_ALLOC(sizeof("0lambda_")+MAX_LENGTH_OF_LONG, 0);
|
||||
function_name->val[0] = '\0';
|
||||
|
||||
do {
|
||||
function_name->len = snprintf(function_name->val + 1, sizeof("lambda_")+MAX_LENGTH_OF_LONG, "lambda_%d", ++EG(lambda_count)) + 1;
|
||||
} while (zend_hash_add_ptr(EG(function_table), function_name, new_function) == NULL);
|
||||
} while (zend_hash_add_ptr(EG(function_table), function_name, func) == NULL);
|
||||
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;
|
||||
RETURN_STR(function_name);
|
||||
} else {
|
||||
zend_hash_str_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1);
|
||||
@ -1904,7 +2005,7 @@ ZEND_FUNCTION(get_defined_constants)
|
||||
if (categorize) {
|
||||
zend_constant *val;
|
||||
int module_number;
|
||||
zval *modules;
|
||||
zval *modules, const_val;
|
||||
char **module_names;
|
||||
zend_module_entry *module;
|
||||
int i = 1;
|
||||
@ -1920,8 +2021,6 @@ ZEND_FUNCTION(get_defined_constants)
|
||||
module_names[i] = "user";
|
||||
|
||||
ZEND_HASH_FOREACH_PTR(EG(zend_constants), val) {
|
||||
zval const_val;
|
||||
|
||||
if (!val->name) {
|
||||
/* skip special constants */
|
||||
continue;
|
||||
@ -1941,8 +2040,7 @@ ZEND_FUNCTION(get_defined_constants)
|
||||
add_assoc_zval(return_value, module_names[module_number], &modules[module_number]);
|
||||
}
|
||||
|
||||
ZVAL_DUP_DEREF(&const_val, &val->value);
|
||||
|
||||
ZVAL_DUP(&const_val, &val->value);
|
||||
zend_hash_add_new(Z_ARRVAL(modules[module_number]), val->name, &const_val);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
@ -1955,22 +2053,37 @@ ZEND_FUNCTION(get_defined_constants)
|
||||
/* }}} */
|
||||
|
||||
|
||||
static void debug_backtrace_get_args(zval *curpos, zval *arg_array TSRMLS_DC)
|
||||
static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array TSRMLS_DC)
|
||||
{
|
||||
zval *p = curpos;
|
||||
zval *arg;
|
||||
int arg_count = Z_LVAL_P(p);
|
||||
int num_args = call->num_args;
|
||||
|
||||
array_init_size(arg_array, arg_count);
|
||||
p -= arg_count;
|
||||
array_init_size(arg_array, num_args);
|
||||
if (num_args) {
|
||||
int i = 0;
|
||||
zval *p = ZEND_CALL_ARG(call, 1);
|
||||
|
||||
while (--arg_count >= 0) {
|
||||
arg = p++;
|
||||
if (arg) {
|
||||
if (Z_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
|
||||
add_next_index_zval(arg_array, arg);
|
||||
} else {
|
||||
add_next_index_null(arg_array);
|
||||
if (call->func->type == ZEND_USER_FUNCTION) {
|
||||
int first_extra_arg = call->func->op_array.num_args;
|
||||
|
||||
if (call->func->op_array.fn_flags & ZEND_ACC_VARIADIC) {
|
||||
first_extra_arg--;
|
||||
}
|
||||
if (call->num_args > first_extra_arg) {
|
||||
while (i < first_extra_arg) {
|
||||
if (Z_REFCOUNTED_P(p)) Z_ADDREF_P(p);
|
||||
zend_hash_next_index_insert_new(Z_ARRVAL_P(arg_array), p);
|
||||
p++;
|
||||
i++;
|
||||
}
|
||||
p = EX_VAR_NUM_2(call, call->func->op_array.last_var + call->func->op_array.T);
|
||||
}
|
||||
}
|
||||
|
||||
while (i < num_args) {
|
||||
if (Z_REFCOUNTED_P(p)) Z_ADDREF_P(p);
|
||||
zend_hash_next_index_insert_new(Z_ARRVAL_P(arg_array), p);
|
||||
p++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1991,9 +2104,10 @@ void debug_print_backtrace_args(zval *arg_array TSRMLS_DC)
|
||||
/* {{{ proto void debug_print_backtrace([int options[, int limit]]) */
|
||||
ZEND_FUNCTION(debug_print_backtrace)
|
||||
{
|
||||
zend_execute_data *ptr, *skip;
|
||||
zend_execute_data *call, *ptr, *skip;
|
||||
zend_object *object;
|
||||
int lineno, frameno = 0;
|
||||
zend_function *func;
|
||||
const char *function_name;
|
||||
const char *filename;
|
||||
zend_string *class_name = NULL;
|
||||
@ -2009,10 +2123,10 @@ ZEND_FUNCTION(debug_print_backtrace)
|
||||
}
|
||||
|
||||
ZVAL_UNDEF(&arg_array);
|
||||
ptr = EG(current_execute_data);
|
||||
ptr = EG(current_execute_data)->prev_execute_data;
|
||||
|
||||
/* skip debug_backtrace() */
|
||||
object = ptr->object;
|
||||
call = ptr;
|
||||
ptr = ptr->prev_execute_data;
|
||||
|
||||
while (ptr && (limit == 0 || frameno < limit)) {
|
||||
@ -2023,67 +2137,81 @@ ZEND_FUNCTION(debug_print_backtrace)
|
||||
|
||||
skip = ptr;
|
||||
/* skip internal handler */
|
||||
if (!skip->op_array &&
|
||||
if ((!skip->func || !ZEND_USER_CODE(skip->func->common.type)) &&
|
||||
skip->prev_execute_data &&
|
||||
skip->prev_execute_data->opline &&
|
||||
skip->prev_execute_data->func &&
|
||||
ZEND_USER_CODE(skip->prev_execute_data->func->common.type) &&
|
||||
skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
|
||||
skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
|
||||
skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
|
||||
skip = skip->prev_execute_data;
|
||||
}
|
||||
|
||||
if (skip->op_array) {
|
||||
filename = skip->op_array->filename->val;
|
||||
lineno = skip->opline->lineno;
|
||||
if (skip->func && ZEND_USER_CODE(skip->func->common.type)) {
|
||||
filename = skip->func->op_array.filename->val;
|
||||
if (skip->opline->opcode == ZEND_HANDLE_EXCEPTION) {
|
||||
if (EG(opline_before_exception)) {
|
||||
lineno = EG(opline_before_exception)->lineno;
|
||||
} else {
|
||||
lineno = skip->func->op_array.line_end;
|
||||
}
|
||||
} else {
|
||||
lineno = skip->opline->lineno;
|
||||
}
|
||||
} else {
|
||||
filename = NULL;
|
||||
lineno = 0;
|
||||
}
|
||||
|
||||
/* $this may be passed into regular internal functions */
|
||||
object = call->object;
|
||||
if (object &&
|
||||
ptr->function_state.function->type == ZEND_INTERNAL_FUNCTION &&
|
||||
!ptr->function_state.function->common.scope) {
|
||||
call &&
|
||||
call->func->type == ZEND_INTERNAL_FUNCTION &&
|
||||
!call->func->common.scope) {
|
||||
object = NULL;
|
||||
}
|
||||
|
||||
function_name = (ptr->function_state.function->common.scope &&
|
||||
ptr->function_state.function->common.scope->trait_aliases) ?
|
||||
if (call->func) {
|
||||
func = call->func;
|
||||
function_name = (func->common.scope &&
|
||||
func->common.scope->trait_aliases) ?
|
||||
zend_resolve_method_name(
|
||||
object ?
|
||||
(object ?
|
||||
zend_get_class_entry(object TSRMLS_CC) :
|
||||
ptr->function_state.function->common.scope,
|
||||
ptr->function_state.function)->val :
|
||||
(ptr->function_state.function->common.function_name ?
|
||||
ptr->function_state.function->common.function_name->val :
|
||||
NULL);
|
||||
func->common.scope), func)->val :
|
||||
(func->common.function_name ?
|
||||
func->common.function_name->val : NULL);
|
||||
} else {
|
||||
func = NULL;
|
||||
function_name = NULL;
|
||||
}
|
||||
|
||||
if (function_name) {
|
||||
if (object) {
|
||||
if (ptr->function_state.function->common.scope) {
|
||||
class_name = ptr->function_state.function->common.scope->name;
|
||||
if (func->common.scope) {
|
||||
class_name = func->common.scope->name;
|
||||
} else {
|
||||
class_name = zend_get_object_classname(object TSRMLS_CC);
|
||||
}
|
||||
|
||||
call_type = "->";
|
||||
} else if (ptr->function_state.function->common.scope) {
|
||||
class_name = ptr->function_state.function->common.scope->name;
|
||||
} else if (func->common.scope) {
|
||||
class_name = func->common.scope->name;
|
||||
call_type = "::";
|
||||
} else {
|
||||
class_name = NULL;
|
||||
call_type = NULL;
|
||||
}
|
||||
if ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL))) {
|
||||
if (ptr->function_state.arguments && (options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) {
|
||||
debug_backtrace_get_args(ptr->function_state.arguments, &arg_array TSRMLS_CC);
|
||||
if (func->type != ZEND_EVAL_CODE) {
|
||||
if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) {
|
||||
debug_backtrace_get_args(call, &arg_array TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
|
||||
zend_bool build_filename_arg = 1;
|
||||
|
||||
if (!ptr->opline || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
|
||||
if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type) || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
|
||||
/* can happen when calling eval from a custom sapi */
|
||||
function_name = "unknown";
|
||||
build_filename_arg = 0;
|
||||
@ -2132,18 +2260,21 @@ ZEND_FUNCTION(debug_print_backtrace)
|
||||
if (filename) {
|
||||
zend_printf(") called at [%s:%d]\n", filename, lineno);
|
||||
} else {
|
||||
zend_execute_data *prev_call = skip;
|
||||
zend_execute_data *prev = skip->prev_execute_data;
|
||||
|
||||
while (prev) {
|
||||
if (prev->function_state.function &&
|
||||
prev->function_state.function->common.type != ZEND_USER_FUNCTION) {
|
||||
if (prev_call &&
|
||||
prev_call->func &&
|
||||
!ZEND_USER_CODE(prev_call->func->common.type)) {
|
||||
prev = NULL;
|
||||
break;
|
||||
}
|
||||
if (prev->op_array) {
|
||||
zend_printf(") called at [%s:%d]\n", prev->op_array->filename->val, prev->opline->lineno);
|
||||
if (prev->func && ZEND_USER_CODE(prev->func->common.type)) {
|
||||
zend_printf(") called at [%s:%d]\n", prev->func->op_array.filename->val, prev->opline->lineno);
|
||||
break;
|
||||
}
|
||||
prev_call = prev;
|
||||
prev = prev->prev_execute_data;
|
||||
}
|
||||
if (!prev) {
|
||||
@ -2151,7 +2282,7 @@ ZEND_FUNCTION(debug_print_backtrace)
|
||||
}
|
||||
}
|
||||
include_filename = filename;
|
||||
object = skip->object;
|
||||
call = skip;
|
||||
ptr = skip->prev_execute_data;
|
||||
++indent;
|
||||
}
|
||||
@ -2161,26 +2292,38 @@ ZEND_FUNCTION(debug_print_backtrace)
|
||||
|
||||
ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int options, int limit TSRMLS_DC)
|
||||
{
|
||||
zend_execute_data *ptr, *skip;
|
||||
zend_object *object = Z_OBJ(EG(This));
|
||||
zend_execute_data *call, *ptr, *skip;
|
||||
zend_object *object;
|
||||
int lineno, frameno = 0;
|
||||
zend_function *func;
|
||||
const char *function_name;
|
||||
const char *filename;
|
||||
zend_string *class_name;
|
||||
const char *include_filename = NULL;
|
||||
zval stack_frame;
|
||||
|
||||
call = NULL;
|
||||
ptr = EG(current_execute_data);
|
||||
|
||||
/* skip "new Exception()" */
|
||||
if (ptr && (skip_last == 0) && ptr->opline && (ptr->opline->opcode == ZEND_NEW)) {
|
||||
object = ptr->object;
|
||||
if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type)) {
|
||||
call = ptr;
|
||||
ptr = ptr->prev_execute_data;
|
||||
}
|
||||
|
||||
/* skip debug_backtrace() */
|
||||
if (skip_last-- && ptr) {
|
||||
object = ptr->object;
|
||||
if (ptr) {
|
||||
if (skip_last) {
|
||||
/* skip debug_backtrace() */
|
||||
call = ptr;
|
||||
ptr = ptr->prev_execute_data;
|
||||
} else {
|
||||
/* skip "new Exception()" */
|
||||
if (ptr->func && ZEND_USER_CODE(ptr->func->common.type) && (ptr->opline->opcode == ZEND_NEW)) {
|
||||
call = ptr;
|
||||
ptr = ptr->prev_execute_data;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!call) {
|
||||
call = ptr;
|
||||
ptr = ptr->prev_execute_data;
|
||||
}
|
||||
|
||||
@ -2192,18 +2335,26 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
|
||||
|
||||
skip = ptr;
|
||||
/* skip internal handler */
|
||||
if (!skip->op_array &&
|
||||
if ((!skip->func || !ZEND_USER_CODE(skip->func->common.type)) &&
|
||||
skip->prev_execute_data &&
|
||||
skip->prev_execute_data->opline &&
|
||||
skip->prev_execute_data->func &&
|
||||
ZEND_USER_CODE(skip->prev_execute_data->func->common.type) &&
|
||||
skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
|
||||
skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
|
||||
skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
|
||||
skip = skip->prev_execute_data;
|
||||
}
|
||||
|
||||
if (skip->op_array) {
|
||||
filename = skip->op_array->filename->val;
|
||||
lineno = skip->opline->lineno;
|
||||
if (skip->func && ZEND_USER_CODE(skip->func->common.type)) {
|
||||
filename = skip->func->op_array.filename->val;
|
||||
if (skip->opline->opcode == ZEND_HANDLE_EXCEPTION) {
|
||||
if (EG(opline_before_exception)) {
|
||||
lineno = EG(opline_before_exception)->lineno;
|
||||
} else {
|
||||
lineno = skip->func->op_array.line_end;
|
||||
}
|
||||
} else {
|
||||
lineno = skip->opline->lineno;
|
||||
}
|
||||
add_assoc_string_ex(&stack_frame, "file", sizeof("file")-1, (char*)filename);
|
||||
add_assoc_long_ex(&stack_frame, "line", sizeof("line")-1, lineno);
|
||||
|
||||
@ -2211,50 +2362,57 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
|
||||
* and debug_baktrace() might have been called by the error_handler. in this case we don't
|
||||
* want to pop anything of the argument-stack */
|
||||
} else {
|
||||
zend_execute_data *prev_call = skip;
|
||||
zend_execute_data *prev = skip->prev_execute_data;
|
||||
|
||||
while (prev) {
|
||||
if (prev->function_state.function &&
|
||||
prev->function_state.function->common.type != ZEND_USER_FUNCTION &&
|
||||
!(prev->function_state.function->common.type == ZEND_INTERNAL_FUNCTION &&
|
||||
(prev->function_state.function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER))) {
|
||||
if (prev_call &&
|
||||
prev_call->func &&
|
||||
!ZEND_USER_CODE(prev_call->func->common.type) &&
|
||||
!(prev_call->func->common.type == ZEND_INTERNAL_FUNCTION &&
|
||||
(prev_call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER))) {
|
||||
break;
|
||||
}
|
||||
if (prev->op_array) {
|
||||
// TODO: we have to duplicate it, becaise it may be stored in opcache SHM ???
|
||||
add_assoc_str_ex(&stack_frame, "file", sizeof("file")-1, STR_DUP(prev->op_array->filename, 0));
|
||||
if (prev->func && ZEND_USER_CODE(prev->func->common.type)) {
|
||||
add_assoc_str_ex(&stack_frame, "file", sizeof("file")-1, STR_COPY(prev->func->op_array.filename));
|
||||
add_assoc_long_ex(&stack_frame, "line", sizeof("line")-1, prev->opline->lineno);
|
||||
break;
|
||||
}
|
||||
prev_call = prev;
|
||||
prev = prev->prev_execute_data;
|
||||
}
|
||||
filename = NULL;
|
||||
}
|
||||
|
||||
/* $this may be passed into regular internal functions */
|
||||
object = call ? call->object : NULL;
|
||||
if (object &&
|
||||
ptr->function_state.function->type == ZEND_INTERNAL_FUNCTION &&
|
||||
!ptr->function_state.function->common.scope) {
|
||||
call->func->type == ZEND_INTERNAL_FUNCTION &&
|
||||
!call->func->common.scope) {
|
||||
object = NULL;
|
||||
}
|
||||
|
||||
function_name = (ptr->function_state.function->common.scope &&
|
||||
ptr->function_state.function->common.scope->trait_aliases) ?
|
||||
if (call && call->func) {
|
||||
func = call->func;
|
||||
function_name = (func->common.scope &&
|
||||
func->common.scope->trait_aliases) ?
|
||||
zend_resolve_method_name(
|
||||
object ?
|
||||
(object ?
|
||||
zend_get_class_entry(object TSRMLS_CC) :
|
||||
ptr->function_state.function->common.scope,
|
||||
ptr->function_state.function)->val :
|
||||
(ptr->function_state.function->common.function_name ?
|
||||
ptr->function_state.function->common.function_name->val :
|
||||
NULL);
|
||||
func->common.scope), func)->val :
|
||||
(func->common.function_name ?
|
||||
func->common.function_name->val : NULL);
|
||||
} else {
|
||||
func = NULL;
|
||||
function_name = NULL;
|
||||
}
|
||||
|
||||
if (function_name) {
|
||||
add_assoc_string_ex(&stack_frame, "function", sizeof("function")-1, (char*)function_name);
|
||||
|
||||
if (object) {
|
||||
if (ptr->function_state.function->common.scope) {
|
||||
add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(ptr->function_state.function->common.scope->name));
|
||||
if (func->common.scope) {
|
||||
add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(func->common.scope->name));
|
||||
} else {
|
||||
class_name = zend_get_object_classname(object TSRMLS_CC);
|
||||
add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(class_name));
|
||||
@ -2268,24 +2426,23 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
|
||||
}
|
||||
|
||||
add_assoc_string_ex(&stack_frame, "type", sizeof("type")-1, "->");
|
||||
} else if (ptr->function_state.function->common.scope) {
|
||||
add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(ptr->function_state.function->common.scope->name));
|
||||
} else if (func->common.scope) {
|
||||
add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(func->common.scope->name));
|
||||
add_assoc_string_ex(&stack_frame, "type", sizeof("type")-1, "::");
|
||||
}
|
||||
|
||||
if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0 &&
|
||||
((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL)))) {
|
||||
if (ptr->function_state.arguments) {
|
||||
zval args;
|
||||
debug_backtrace_get_args(ptr->function_state.arguments, &args TSRMLS_CC);
|
||||
add_assoc_zval_ex(&stack_frame, "args", sizeof("args")-1, &args);
|
||||
}
|
||||
func->type != ZEND_EVAL_CODE) {
|
||||
zval args;
|
||||
|
||||
debug_backtrace_get_args(call, &args TSRMLS_CC);
|
||||
add_assoc_zval_ex(&stack_frame, "args", sizeof("args")-1, &args);
|
||||
}
|
||||
} else {
|
||||
/* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
|
||||
zend_bool build_filename_arg = 1;
|
||||
|
||||
if (!ptr->opline || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
|
||||
if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type) || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
|
||||
/* can happen when calling eval from a custom sapi */
|
||||
function_name = "unknown";
|
||||
build_filename_arg = 0;
|
||||
@ -2331,11 +2488,11 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
|
||||
add_assoc_string_ex(&stack_frame, "function", sizeof("function")-1, (char*)function_name);
|
||||
}
|
||||
|
||||
add_next_index_zval(return_value, &stack_frame);
|
||||
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &stack_frame);
|
||||
|
||||
include_filename = filename;
|
||||
|
||||
object = skip->object;
|
||||
call = skip;
|
||||
ptr = skip->prev_execute_data;
|
||||
}
|
||||
}
|
||||
@ -2421,8 +2578,7 @@ ZEND_FUNCTION(get_extension_funcs)
|
||||
array_init(return_value);
|
||||
array = 1;
|
||||
}
|
||||
// TODO: we have to duplicate it, becaise it may be stored in opcache SHM ???
|
||||
add_next_index_str(return_value, STR_DUP(zif->common.function_name, 0));
|
||||
add_next_index_str(return_value, STR_COPY(zif->common.function_name));
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
|
@ -47,7 +47,7 @@ static zend_object_handlers closure_handlers;
|
||||
|
||||
ZEND_METHOD(Closure, __invoke) /* {{{ */
|
||||
{
|
||||
zend_function *func = EG(current_execute_data)->function_state.function;
|
||||
zend_function *func = EG(current_execute_data)->func;
|
||||
zval *arguments;
|
||||
|
||||
arguments = emalloc(sizeof(zval) * ZEND_NUM_ARGS());
|
||||
@ -169,27 +169,27 @@ static zend_function *zend_closure_get_method(zend_object **object, zend_string
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zval *zend_closure_read_property(zval *object, zval *member, int type, zend_uint cache_slot, zval *rv TSRMLS_DC) /* {{{ */
|
||||
static zval *zend_closure_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
ZEND_CLOSURE_PROPERTY_ERROR();
|
||||
return &EG(uninitialized_zval);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void zend_closure_write_property(zval *object, zval *member, zval *value, zend_uint cache_slot TSRMLS_DC) /* {{{ */
|
||||
static void zend_closure_write_property(zval *object, zval *member, zval *value, void **cache_slot TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
ZEND_CLOSURE_PROPERTY_ERROR();
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zval *zend_closure_get_property_ptr_ptr(zval *object, zval *member, int type, zend_uint cache_slot TSRMLS_DC) /* {{{ */
|
||||
static zval *zend_closure_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
ZEND_CLOSURE_PROPERTY_ERROR();
|
||||
return NULL;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int zend_closure_has_property(zval *object, zval *member, int has_set_exists, zend_uint cache_slot TSRMLS_DC) /* {{{ */
|
||||
static int zend_closure_has_property(zval *object, zval *member, int has_set_exists, void **cache_slot TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
if (has_set_exists != 2) {
|
||||
ZEND_CLOSURE_PROPERTY_ERROR();
|
||||
@ -198,7 +198,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, zend_uint cache_slot TSRMLS_DC) /* {{{ */
|
||||
static void zend_closure_unset_property(zval *object, zval *member, void **cache_slot TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
ZEND_CLOSURE_PROPERTY_ERROR();
|
||||
}
|
||||
@ -213,7 +213,7 @@ static void zend_closure_free_storage(zend_object *object TSRMLS_DC) /* {{{ */
|
||||
if (closure->func.type == ZEND_USER_FUNCTION) {
|
||||
zend_execute_data *ex = EG(current_execute_data);
|
||||
while (ex) {
|
||||
if (ex->op_array == &closure->func.op_array) {
|
||||
if (ex->func == &closure->func) {
|
||||
zend_error(E_ERROR, "Cannot destroy active lambda function");
|
||||
}
|
||||
ex = ex->prev_execute_data;
|
||||
@ -456,6 +456,7 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent
|
||||
}
|
||||
}
|
||||
|
||||
ZVAL_UNDEF(&closure->this_ptr);
|
||||
/* Invariants:
|
||||
* If the closure is unscoped, it has no bound object.
|
||||
* The the closure is scoped, it's either static or it's bound */
|
||||
@ -466,10 +467,7 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent
|
||||
ZVAL_COPY(&closure->this_ptr, this_ptr);
|
||||
} else {
|
||||
closure->func.common.fn_flags |= ZEND_ACC_STATIC;
|
||||
ZVAL_UNDEF(&closure->this_ptr);
|
||||
}
|
||||
} else {
|
||||
ZVAL_UNDEF(&closure->this_ptr);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -97,9 +97,11 @@ ZEND_API zend_compiler_globals compiler_globals;
|
||||
ZEND_API zend_executor_globals executor_globals;
|
||||
#endif
|
||||
|
||||
static zend_property_info *zend_duplicate_property_info(zend_property_info *property_info) /* {{{ */
|
||||
static zend_property_info *zend_duplicate_property_info(zend_property_info *property_info TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_property_info* new_property_info = emalloc(sizeof(zend_property_info));
|
||||
zend_property_info* new_property_info;
|
||||
|
||||
new_property_info = zend_arena_alloc(&CG(arena), sizeof(zend_property_info));
|
||||
memcpy(new_property_info, property_info, sizeof(zend_property_info));
|
||||
STR_ADDREF(new_property_info->name);
|
||||
if (new_property_info->doc_comment) {
|
||||
@ -126,7 +128,6 @@ static void zend_destroy_property_info(zval *zv) /* {{{ */
|
||||
if (property_info->doc_comment) {
|
||||
STR_RELEASE(property_info->doc_comment);
|
||||
}
|
||||
efree(property_info);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -174,8 +175,6 @@ void zend_init_compiler_context(TSRMLS_D) /* {{{ */
|
||||
CG(context).literals_size = 0;
|
||||
CG(context).current_brk_cont = -1;
|
||||
CG(context).backpatch_count = 0;
|
||||
CG(context).nested_calls = 0;
|
||||
CG(context).used_stack = 0;
|
||||
CG(context).in_finally = 0;
|
||||
CG(context).labels = NULL;
|
||||
}
|
||||
@ -217,6 +216,7 @@ ZEND_API void file_handle_dtor(zend_file_handle *fh) /* {{{ */
|
||||
|
||||
void init_compiler(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
CG(arena) = zend_arena_create(64 * 1024);
|
||||
CG(active_op_array) = NULL;
|
||||
memset(&CG(context), 0, sizeof(CG(context)));
|
||||
zend_init_compiler_data_structures(TSRMLS_C);
|
||||
@ -237,6 +237,7 @@ void shutdown_compiler(TSRMLS_D) /* {{{ */
|
||||
zend_hash_destroy(&CG(filenames_table));
|
||||
zend_hash_destroy(&CG(const_filenames));
|
||||
zend_stack_destroy(&CG(context_stack));
|
||||
zend_arena_destroy(CG(arena));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -296,7 +297,7 @@ static int lookup_cv(zend_op_array *op_array, zend_string* name TSRMLS_DC) /* {{
|
||||
op_array->vars[i]->len == name->len &&
|
||||
memcmp(op_array->vars[i]->val, name->val, name->len) == 0)) {
|
||||
STR_RELEASE(name);
|
||||
return (int)EX_VAR_NUM_2(NULL, i);
|
||||
return (int)(zend_intptr_t)EX_VAR_NUM_2(NULL, i);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
@ -308,7 +309,7 @@ static int lookup_cv(zend_op_array *op_array, zend_string* name TSRMLS_DC) /* {{
|
||||
}
|
||||
|
||||
op_array->vars[i] = zend_new_interned_string(name TSRMLS_CC);
|
||||
return (int)EX_VAR_NUM_2(NULL, i);
|
||||
return (int)(zend_intptr_t)EX_VAR_NUM_2(NULL, i);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -672,6 +673,11 @@ void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
|
||||
&& opline->result.var == op1->u.op.var) {
|
||||
if (opline->opcode == ZEND_NEW) {
|
||||
opline->result_type |= EXT_TYPE_UNUSED;
|
||||
opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
|
||||
while (opline->opcode != ZEND_DO_FCALL || opline->op1.num != ZEND_CALL_CTOR) {
|
||||
opline--;
|
||||
}
|
||||
opline->op1.num |= ZEND_CALL_CTOR_RESULT_UNUSED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -995,53 +1001,6 @@ void zend_do_build_full_name(znode *result, znode *prefix, znode *name, int is_c
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_do_end_function_call(znode *function_name, znode *result, int is_method, int is_dynamic_fcall TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_op *opline;
|
||||
zend_function_call_entry *fcall = zend_stack_top(&CG(function_call_stack));
|
||||
|
||||
if (is_method && function_name && function_name->op_type == IS_UNUSED) {
|
||||
/* clone */
|
||||
if (fcall->arg_num != 0) {
|
||||
zend_error(E_WARNING, "Clone method does not require arguments");
|
||||
}
|
||||
opline = &CG(active_op_array)->opcodes[Z_LVAL(function_name->u.constant)];
|
||||
} else {
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
if (fcall->fbc) {
|
||||
opline->opcode = ZEND_DO_FCALL;
|
||||
SET_NODE(opline->op1, function_name);
|
||||
SET_UNUSED(opline->op2);
|
||||
opline->op2.num = CG(context).nested_calls;
|
||||
GET_CACHE_SLOT(opline->op1.constant);
|
||||
} else {
|
||||
opline->opcode = ZEND_DO_FCALL_BY_NAME;
|
||||
SET_UNUSED(opline->op1);
|
||||
SET_UNUSED(opline->op2);
|
||||
opline->op2.num = --CG(context).nested_calls;
|
||||
|
||||
/* This would normally be a ZEND_DO_FCALL, but was forced to use
|
||||
* ZEND_DO_FCALL_BY_NAME due to a ... argument. In this case we need to
|
||||
* free the function_name */
|
||||
if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) {
|
||||
zval_dtor(&function_name->u.constant);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
opline->result.var = get_temporary_variable(CG(active_op_array));
|
||||
opline->result_type = IS_VAR;
|
||||
GET_NODE(result, opline->result);
|
||||
opline->extended_value = fcall->arg_num;
|
||||
|
||||
if (CG(context).used_stack + 1 > CG(active_op_array)->used_stack) {
|
||||
CG(active_op_array)->used_stack = CG(context).used_stack + 1;
|
||||
}
|
||||
CG(context).used_stack -= fcall->arg_num;
|
||||
zend_stack_del_top(&CG(function_call_stack));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_bool zend_is_call(zend_ast *ast);
|
||||
|
||||
static int generate_free_switch_expr(zend_switch_entry *switch_entry TSRMLS_DC) /* {{{ */
|
||||
@ -1183,7 +1142,7 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */
|
||||
static void do_inherit_parent_constructor(zend_class_entry *ce TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_function *function, *new_function;
|
||||
|
||||
@ -1253,7 +1212,7 @@ static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */
|
||||
new_function = pemalloc(sizeof(zend_internal_function), 1);
|
||||
memcpy(new_function, function, sizeof(zend_internal_function));
|
||||
} else {
|
||||
new_function = emalloc(sizeof(zend_op_array));
|
||||
new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
|
||||
memcpy(new_function, function, sizeof(zend_op_array));
|
||||
}
|
||||
zend_hash_str_update_ptr(&ce->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1, new_function);
|
||||
@ -1301,7 +1260,7 @@ char *zend_visibility_string(zend_uint fn_flags) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_function *do_inherit_method(zend_function *old_function) /* {{{ */
|
||||
static zend_function *do_inherit_method(zend_function *old_function TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_function *new_function;
|
||||
|
||||
@ -1309,7 +1268,7 @@ static zend_function *do_inherit_method(zend_function *old_function) /* {{{ */
|
||||
new_function = pemalloc(sizeof(zend_internal_function), 1);
|
||||
memcpy(new_function, old_function, sizeof(zend_internal_function));
|
||||
} else {
|
||||
new_function = emalloc(sizeof(zend_op_array));
|
||||
new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
|
||||
memcpy(new_function, old_function, sizeof(zend_op_array));
|
||||
}
|
||||
/* The class entry of the derived function intentionally remains the same
|
||||
@ -1462,7 +1421,7 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
|
||||
buf = erealloc(buf, length); \
|
||||
}
|
||||
|
||||
static char * zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{{ */
|
||||
static char *zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char *offset, *buf;
|
||||
zend_uint length = 1024;
|
||||
@ -1568,41 +1527,45 @@ static char * zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{
|
||||
}
|
||||
}
|
||||
if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2_type != IS_UNUSED) {
|
||||
zval zv;
|
||||
zval *zv = precv->op2.zv;
|
||||
|
||||
ZVAL_DUP(&zv, precv->op2.zv);
|
||||
zval_update_constant_ex(&zv, 1, fptr->common.scope TSRMLS_CC);
|
||||
if (Z_TYPE(zv) == IS_FALSE) {
|
||||
if (Z_TYPE_P(zv) == IS_CONSTANT) {
|
||||
REALLOC_BUF_IF_EXCEED(buf, offset, length, Z_STRLEN_P(zv));
|
||||
memcpy(offset, Z_STRVAL_P(zv), Z_STRLEN_P(zv));
|
||||
offset += Z_STRLEN_P(zv);
|
||||
} else if (Z_TYPE_P(zv) == IS_FALSE) {
|
||||
memcpy(offset, "false", 5);
|
||||
offset += 5;
|
||||
} else if (Z_TYPE(zv) == IS_TRUE) {
|
||||
} else if (Z_TYPE_P(zv) == IS_TRUE) {
|
||||
memcpy(offset, "true", 4);
|
||||
offset += 4;
|
||||
} else if (Z_TYPE(zv) == IS_NULL) {
|
||||
} else if (Z_TYPE_P(zv) == IS_NULL) {
|
||||
memcpy(offset, "NULL", 4);
|
||||
offset += 4;
|
||||
} else if (Z_TYPE(zv) == IS_STRING) {
|
||||
} else if (Z_TYPE_P(zv) == IS_STRING) {
|
||||
*(offset++) = '\'';
|
||||
REALLOC_BUF_IF_EXCEED(buf, offset, length, MIN(Z_STRLEN(zv), 10));
|
||||
memcpy(offset, Z_STRVAL(zv), MIN(Z_STRLEN(zv), 10));
|
||||
offset += MIN(Z_STRLEN(zv), 10);
|
||||
if (Z_STRLEN(zv) > 10) {
|
||||
REALLOC_BUF_IF_EXCEED(buf, offset, length, MIN(Z_STRLEN_P(zv), 10));
|
||||
memcpy(offset, Z_STRVAL_P(zv), MIN(Z_STRLEN_P(zv), 10));
|
||||
offset += MIN(Z_STRLEN_P(zv), 10);
|
||||
if (Z_STRLEN_P(zv) > 10) {
|
||||
*(offset++) = '.';
|
||||
*(offset++) = '.';
|
||||
*(offset++) = '.';
|
||||
}
|
||||
*(offset++) = '\'';
|
||||
} else if (Z_TYPE(zv) == IS_ARRAY) {
|
||||
} else if (Z_TYPE_P(zv) == IS_ARRAY) {
|
||||
memcpy(offset, "Array", 5);
|
||||
offset += 5;
|
||||
} else if (Z_TYPE_P(zv) == IS_CONSTANT_AST) {
|
||||
memcpy(offset, "<expression>", 12);
|
||||
offset += 12;
|
||||
} else {
|
||||
zend_string *str = zval_get_string(&zv);
|
||||
zend_string *str = zval_get_string(zv);
|
||||
REALLOC_BUF_IF_EXCEED(buf, offset, length, str->len);
|
||||
memcpy(offset, str->val, str->len);
|
||||
offset += str->len;
|
||||
STR_RELEASE(str);
|
||||
}
|
||||
zval_ptr_dtor(&zv);
|
||||
}
|
||||
} else {
|
||||
memcpy(offset, "NULL", 4);
|
||||
@ -1716,7 +1679,7 @@ static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_f
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_property_info *parent_info, zend_string *key, zend_class_entry *ce) /* {{{ */
|
||||
static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_property_info *parent_info, zend_string *key, zend_class_entry *ce TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_property_info *child_info;
|
||||
zend_class_entry *parent_ce = ce->parent;
|
||||
@ -1728,7 +1691,7 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
|
||||
if(ce->type & ZEND_INTERNAL_CLASS) {
|
||||
child_info = zend_duplicate_property_info_internal(parent_info);
|
||||
} else {
|
||||
child_info = zend_duplicate_property_info(parent_info);
|
||||
child_info = zend_duplicate_property_info(parent_info TSRMLS_CC);
|
||||
}
|
||||
zend_hash_update_ptr(&ce->properties_info, key, child_info);
|
||||
child_info->flags &= ~ZEND_ACC_PRIVATE; /* it's not private anymore */
|
||||
@ -1820,24 +1783,21 @@ ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_
|
||||
zval_add_ref
|
||||
#endif
|
||||
|
||||
static int do_inherit_class_constant(zval *zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
|
||||
static void do_inherit_class_constant(zend_string *name, zval *zv, zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_class_entry *ce = va_arg(args, zend_class_entry *);
|
||||
zend_class_entry *parent_ce = va_arg(args, zend_class_entry *);
|
||||
|
||||
if (hash_key->key) {
|
||||
if (!Z_ISREF_P(zv)) {
|
||||
if (parent_ce->type == ZEND_INTERNAL_CLASS) {
|
||||
ZVAL_NEW_PERSISTENT_REF(zv, zv);
|
||||
} else {
|
||||
ZVAL_NEW_REF(zv, zv);
|
||||
}
|
||||
}
|
||||
if (zend_hash_add(&ce->constants_table, hash_key->key, zv)) {
|
||||
Z_ADDREF_P(zv);
|
||||
if (!Z_ISREF_P(zv)) {
|
||||
if (parent_ce->type == ZEND_INTERNAL_CLASS) {
|
||||
ZVAL_NEW_PERSISTENT_REF(zv, zv);
|
||||
} else {
|
||||
ZVAL_NEW_REF(zv, zv);
|
||||
}
|
||||
}
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
if (Z_CONSTANT_P(Z_REFVAL_P(zv))) {
|
||||
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
|
||||
}
|
||||
if (zend_hash_add(&ce->constants_table, name, zv)) {
|
||||
Z_ADDREF_P(zv);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -1846,6 +1806,7 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
|
||||
zend_property_info *property_info;
|
||||
zend_function *func;
|
||||
zend_string *key;
|
||||
zval *zv;
|
||||
|
||||
if ((ce->ce_flags & ZEND_ACC_INTERFACE)
|
||||
&& !(parent_ce->ce_flags & ZEND_ACC_INTERFACE)) {
|
||||
@ -1881,11 +1842,17 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
|
||||
#ifdef ZTS
|
||||
if (parent_ce->type != ce->type) {
|
||||
ZVAL_DUP(&ce->default_properties_table[i], &parent_ce->default_properties_table[i]);
|
||||
if (Z_OPT_CONSTANT(ce->default_properties_table[i])) {
|
||||
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
ZVAL_COPY(&ce->default_properties_table[i], &parent_ce->default_properties_table[i]);
|
||||
if (Z_OPT_CONSTANT(ce->default_properties_table[i])) {
|
||||
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
|
||||
}
|
||||
}
|
||||
ce->default_properties_count += parent_ce->default_properties_count;
|
||||
}
|
||||
@ -1903,9 +1870,12 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
|
||||
}
|
||||
}
|
||||
for (i = 0; i < parent_ce->default_static_members_count; i++) {
|
||||
SEPARATE_ZVAL_TO_MAKE_IS_REF(&CE_STATIC_MEMBERS(parent_ce)[i]);
|
||||
ZVAL_MAKE_REF(&CE_STATIC_MEMBERS(parent_ce)[i]);
|
||||
ce->default_static_members_table[i] = CE_STATIC_MEMBERS(parent_ce)[i];
|
||||
Z_ADDREF(ce->default_static_members_table[i]);
|
||||
if (Z_CONSTANT_P(Z_REFVAL(ce->default_static_members_table[i]))) {
|
||||
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
|
||||
}
|
||||
}
|
||||
ce->default_static_members_count += parent_ce->default_static_members_count;
|
||||
ce->static_members_table = ce->default_static_members_table;
|
||||
@ -1921,9 +1891,12 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
|
||||
}
|
||||
}
|
||||
for (i = 0; i < parent_ce->default_static_members_count; i++) {
|
||||
SEPARATE_ZVAL_TO_MAKE_IS_REF(&parent_ce->default_static_members_table[i]);
|
||||
ZVAL_MAKE_REF(&parent_ce->default_static_members_table[i]);
|
||||
ce->default_static_members_table[i] = parent_ce->default_static_members_table[i];
|
||||
Z_ADDREF(ce->default_static_members_table[i]);
|
||||
if (Z_CONSTANT_P(Z_REFVAL(ce->default_static_members_table[i]))) {
|
||||
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
|
||||
}
|
||||
}
|
||||
ce->default_static_members_count += parent_ce->default_static_members_count;
|
||||
if (ce->type == ZEND_USER_CLASS) {
|
||||
@ -1943,26 +1916,28 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->properties_info, key, property_info) {
|
||||
if (do_inherit_property_access_check(&ce->properties_info, property_info, key, ce)) {
|
||||
if (do_inherit_property_access_check(&ce->properties_info, property_info, key, ce TSRMLS_CC)) {
|
||||
if (ce->type & ZEND_INTERNAL_CLASS) {
|
||||
property_info = zend_duplicate_property_info_internal(property_info);
|
||||
} else {
|
||||
property_info = zend_duplicate_property_info(property_info);
|
||||
property_info = zend_duplicate_property_info(property_info TSRMLS_CC);
|
||||
}
|
||||
zend_hash_add_new_ptr(&ce->properties_info, key, property_info);
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
zend_hash_apply_with_arguments(&parent_ce->constants_table TSRMLS_CC, do_inherit_class_constant, 2, ce, parent_ce);
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL(&parent_ce->constants_table, key, zv) {
|
||||
do_inherit_class_constant(key, zv, ce, parent_ce TSRMLS_CC);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, func) {
|
||||
if (do_inherit_method_check(&ce->function_table, func, key, ce)) {
|
||||
zend_function *new_func = do_inherit_method(func);
|
||||
zend_function *new_func = do_inherit_method(func TSRMLS_CC);
|
||||
zend_hash_add_new_ptr(&ce->function_table, key, new_func);
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
do_inherit_parent_constructor(ce);
|
||||
do_inherit_parent_constructor(ce TSRMLS_CC);
|
||||
|
||||
if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS && ce->type == ZEND_INTERNAL_CLASS) {
|
||||
ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
|
||||
@ -1974,15 +1949,15 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_bool do_inherit_constant_check(HashTable *child_constants_table, zval *parent_constant, const zend_hash_key *hash_key, const zend_class_entry *iface) /* {{{ */
|
||||
static zend_bool do_inherit_constant_check(HashTable *child_constants_table, zval *parent_constant, zend_string *name, const zend_class_entry *iface) /* {{{ */
|
||||
{
|
||||
zval *old_constant;
|
||||
|
||||
if ((old_constant = zend_hash_find(child_constants_table, hash_key->key)) != NULL) {
|
||||
if ((old_constant = zend_hash_find(child_constants_table, name)) != NULL) {
|
||||
if (!Z_ISREF_P(old_constant) ||
|
||||
!Z_ISREF_P(parent_constant) ||
|
||||
Z_REFVAL_P(old_constant) != Z_REFVAL_P(parent_constant)) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot inherit previously-inherited or override constant %s from interface %s", hash_key->key->val, iface->name->val);
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot inherit previously-inherited or override constant %s from interface %s", name->val, iface->name->val);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1990,29 +1965,16 @@ static zend_bool do_inherit_constant_check(HashTable *child_constants_table, zva
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int do_interface_constant_check(zval *val TSRMLS_DC, int num_args, va_list args, zend_hash_key *key) /* {{{ */
|
||||
static void do_inherit_iface_constant(zend_string *name, zval *zv, zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_class_entry **iface = va_arg(args, zend_class_entry**);
|
||||
|
||||
do_inherit_constant_check(&(*iface)->constants_table, val, key, *iface);
|
||||
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int do_inherit_iface_constant(zval *zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
|
||||
{
|
||||
zend_class_entry *ce = va_arg(args, zend_class_entry *);
|
||||
zend_class_entry *iface = va_arg(args, zend_class_entry *);
|
||||
|
||||
if (hash_key->key && do_inherit_constant_check(&ce->constants_table, zv, hash_key, iface)) {
|
||||
if (!Z_ISREF_P(zv)) {
|
||||
ZVAL_NEW_REF(zv, zv);
|
||||
}
|
||||
if (do_inherit_constant_check(&ce->constants_table, zv, name, iface)) {
|
||||
ZVAL_MAKE_REF(zv);
|
||||
Z_ADDREF_P(zv);
|
||||
zend_hash_update(&ce->constants_table, hash_key->key, zv);
|
||||
if (Z_CONSTANT_P(Z_REFVAL_P(zv))) {
|
||||
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
|
||||
}
|
||||
zend_hash_update(&ce->constants_table, name, zv);
|
||||
}
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -2023,6 +1985,7 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry
|
||||
zend_uint parent_iface_num = ce->parent ? ce->parent->num_interfaces : 0;
|
||||
zend_function *func;
|
||||
zend_string *key;
|
||||
zval *zv;
|
||||
|
||||
for (i = 0; i < ce->num_interfaces; i++) {
|
||||
if (ce->interfaces[i] == NULL) {
|
||||
@ -2038,7 +2001,9 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry
|
||||
}
|
||||
if (ignore) {
|
||||
/* Check for attempt to redeclare interface constants */
|
||||
zend_hash_apply_with_arguments(&ce->constants_table TSRMLS_CC, do_interface_constant_check, 1, &iface);
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL(&ce->constants_table, key, zv) {
|
||||
do_inherit_constant_check(&iface->constants_table, zv, key, iface);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
} else {
|
||||
if (ce->num_interfaces >= current_iface_num) {
|
||||
if (ce->type == ZEND_INTERNAL_CLASS) {
|
||||
@ -2049,11 +2014,13 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry
|
||||
}
|
||||
ce->interfaces[ce->num_interfaces++] = iface;
|
||||
|
||||
zend_hash_apply_with_arguments(&iface->constants_table TSRMLS_CC, do_inherit_iface_constant, 2, ce, iface);
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL(&iface->constants_table, key, zv) {
|
||||
do_inherit_iface_constant(key, zv, ce, iface TSRMLS_CC);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
ZEND_HASH_FOREACH_STR_KEY_PTR(&iface->function_table, key, func) {
|
||||
if (do_inherit_method_check(&ce->function_table, func, key, ce)) {
|
||||
zend_function *new_func = do_inherit_method(func);
|
||||
zend_function *new_func = do_inherit_method(func TSRMLS_CC);
|
||||
zend_hash_add_new_ptr(&ce->function_table, key, new_func);
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
@ -2151,6 +2118,7 @@ static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zen
|
||||
static void zend_add_trait_method(zend_class_entry *ce, const char *name, zend_string *key, zend_function *fn, HashTable **overriden TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_function *existing_fn = NULL;
|
||||
zend_function *new_fn;
|
||||
|
||||
if ((existing_fn = zend_hash_find_ptr(&ce->function_table, key)) != NULL) {
|
||||
if (existing_fn->common.scope == ce) {
|
||||
@ -2215,16 +2183,15 @@ static void zend_add_trait_method(zend_class_entry *ce, const char *name, zend_s
|
||||
}
|
||||
|
||||
function_add_ref(fn);
|
||||
fn = zend_hash_update_mem(&ce->function_table, key, fn, sizeof(zend_function));
|
||||
new_fn = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
|
||||
memcpy(new_fn, fn, sizeof(zend_op_array));
|
||||
fn = zend_hash_update_ptr(&ce->function_table, key, new_fn);
|
||||
zend_add_magic_methods(ce, key, fn TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int zend_fixup_trait_method(zval *zv, void *arg TSRMLS_DC) /* {{{ */
|
||||
static void zend_fixup_trait_method(zend_function *fn, zend_class_entry *ce) /* {{{ */
|
||||
{
|
||||
zend_function *fn = Z_PTR_P(zv);
|
||||
zend_class_entry *ce = (zend_class_entry *)arg;
|
||||
|
||||
if ((fn->common.scope->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
|
||||
|
||||
fn->common.scope = ce;
|
||||
@ -2236,27 +2203,15 @@ static int zend_fixup_trait_method(zval *zv, void *arg TSRMLS_DC) /* {{{ */
|
||||
ce->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
|
||||
}
|
||||
}
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int zend_traits_copy_functions(zval *zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
|
||||
static int zend_traits_copy_functions(zend_string *fnname, zend_function *fn, zend_class_entry *ce, HashTable **overriden, HashTable *exclude_table TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_function *fn = Z_PTR_P(zv);
|
||||
zend_class_entry *ce;
|
||||
HashTable **overriden;
|
||||
zend_trait_alias *alias, **alias_ptr;
|
||||
HashTable *exclude_table;
|
||||
zend_string *lcname;
|
||||
unsigned int fnname_len;
|
||||
zend_function fn_copy;
|
||||
|
||||
ce = va_arg(args, zend_class_entry*);
|
||||
overriden = va_arg(args, HashTable**);
|
||||
exclude_table = va_arg(args, HashTable*);
|
||||
|
||||
fnname_len = hash_key->key->len;
|
||||
|
||||
/* apply aliases which are qualified with a class name, there should not be any ambiguity */
|
||||
if (ce->trait_aliases) {
|
||||
alias_ptr = ce->trait_aliases;
|
||||
@ -2265,8 +2220,8 @@ static int zend_traits_copy_functions(zval *zv TSRMLS_DC, int num_args, va_list
|
||||
/* Scope unset or equal to the function we compare to, and the alias applies to fn */
|
||||
if (alias->alias != NULL
|
||||
&& (!alias->trait_method->ce || fn->common.scope == alias->trait_method->ce)
|
||||
&& alias->trait_method->method_name->len == fnname_len
|
||||
&& (zend_binary_strcasecmp(alias->trait_method->method_name->val, alias->trait_method->method_name->len, hash_key->key->val, fnname_len) == 0)) {
|
||||
&& alias->trait_method->method_name->len == fnname->len
|
||||
&& (zend_binary_strcasecmp(alias->trait_method->method_name->val, alias->trait_method->method_name->len, fnname->val, fnname->len) == 0)) {
|
||||
fn_copy = *fn;
|
||||
|
||||
/* if it is 0, no modifieres has been changed */
|
||||
@ -2289,9 +2244,7 @@ static int zend_traits_copy_functions(zval *zv TSRMLS_DC, int num_args, va_list
|
||||
}
|
||||
}
|
||||
|
||||
lcname = hash_key->key;
|
||||
|
||||
if (exclude_table == NULL || zend_hash_find(exclude_table, lcname) == NULL) {
|
||||
if (exclude_table == NULL || zend_hash_find(exclude_table, fnname) == NULL) {
|
||||
/* is not in hashtable, thus, function is not to be excluded */
|
||||
fn_copy = *fn;
|
||||
|
||||
@ -2303,8 +2256,8 @@ static int zend_traits_copy_functions(zval *zv TSRMLS_DC, int num_args, va_list
|
||||
/* Scope unset or equal to the function we compare to, and the alias applies to fn */
|
||||
if (alias->alias == NULL && alias->modifiers != 0
|
||||
&& (!alias->trait_method->ce || fn->common.scope == alias->trait_method->ce)
|
||||
&& (alias->trait_method->method_name->len == fnname_len)
|
||||
&& (zend_binary_strcasecmp(alias->trait_method->method_name->val, alias->trait_method->method_name->len, lcname->val, fnname_len) == 0)) {
|
||||
&& (alias->trait_method->method_name->len == fnname->len)
|
||||
&& (zend_binary_strcasecmp(alias->trait_method->method_name->val, alias->trait_method->method_name->len, fnname->val, fnname->len) == 0)) {
|
||||
|
||||
fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags ^ (fn->common.fn_flags & ZEND_ACC_PPP_MASK));
|
||||
|
||||
@ -2318,7 +2271,7 @@ static int zend_traits_copy_functions(zval *zv TSRMLS_DC, int num_args, va_list
|
||||
}
|
||||
}
|
||||
|
||||
zend_add_trait_method(ce, fn->common.function_name->val, lcname, &fn_copy, overriden TSRMLS_CC);
|
||||
zend_add_trait_method(ce, fn->common.function_name->val, fnname, &fn_copy, overriden TSRMLS_CC);
|
||||
}
|
||||
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
@ -2477,6 +2430,8 @@ static void zend_do_traits_method_binding(zend_class_entry *ce TSRMLS_DC) /* {{{
|
||||
{
|
||||
zend_uint i;
|
||||
HashTable *overriden = NULL;
|
||||
zend_string *key;
|
||||
zend_function *fn;
|
||||
|
||||
for (i = 0; i < ce->num_traits; i++) {
|
||||
if (ce->trait_precedences) {
|
||||
@ -2488,15 +2443,21 @@ static void zend_do_traits_method_binding(zend_class_entry *ce TSRMLS_DC) /* {{{
|
||||
zend_traits_compile_exclude_table(&exclude_table, ce->trait_precedences, ce->traits[i]);
|
||||
|
||||
/* copies functions, applies defined aliasing, and excludes unused trait methods */
|
||||
zend_hash_apply_with_arguments(&ce->traits[i]->function_table TSRMLS_CC, zend_traits_copy_functions, 3, ce, &overriden, &exclude_table);
|
||||
ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->traits[i]->function_table, key, fn) {
|
||||
zend_traits_copy_functions(key, fn, ce, &overriden, &exclude_table TSRMLS_CC);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
zend_hash_destroy(&exclude_table);
|
||||
} else {
|
||||
zend_hash_apply_with_arguments(&ce->traits[i]->function_table TSRMLS_CC, zend_traits_copy_functions, 3, ce, &overriden, NULL);
|
||||
ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->traits[i]->function_table, key, fn) {
|
||||
zend_traits_copy_functions(key, fn, ce, &overriden, NULL TSRMLS_CC);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
}
|
||||
|
||||
zend_hash_apply_with_argument(&ce->function_table, zend_fixup_trait_method, ce TSRMLS_CC);
|
||||
ZEND_HASH_FOREACH_PTR(&ce->function_table, fn) {
|
||||
zend_fixup_trait_method(fn, ce);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
if (overriden) {
|
||||
zend_hash_destroy(overriden);
|
||||
@ -2702,7 +2663,7 @@ ZEND_API void zend_do_bind_traits(zend_class_entry *ce TSRMLS_DC) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, HashTable *function_table, zend_bool compile_time) /* {{{ */
|
||||
ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, HashTable *function_table, zend_bool compile_time TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_function *function, *new_function;
|
||||
zval *op1, *op2;
|
||||
@ -2716,7 +2677,7 @@ ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, Ha
|
||||
}
|
||||
|
||||
function = zend_hash_find_ptr(function_table, Z_STR_P(op1));
|
||||
new_function = emalloc(sizeof(zend_op_array));
|
||||
new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
|
||||
memcpy(new_function, function, sizeof(zend_op_array));
|
||||
if (zend_hash_add_ptr(function_table, Z_STR_P(op2), new_function) == NULL) {
|
||||
int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
|
||||
@ -2835,7 +2796,7 @@ void zend_do_early_binding(TSRMLS_D) /* {{{ */
|
||||
|
||||
switch (opline->opcode) {
|
||||
case ZEND_DECLARE_FUNCTION:
|
||||
if (do_bind_function(CG(active_op_array), opline, CG(function_table), 1) == FAILURE) {
|
||||
if (do_bind_function(CG(active_op_array), opline, CG(function_table), 1 TSRMLS_CC) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
table = CG(function_table);
|
||||
@ -3176,24 +3137,19 @@ int zend_register_auto_global(zend_string *name, zend_bool jit, zend_auto_global
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int zend_auto_global_init(zval *zv TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_auto_global *auto_global = Z_PTR_P(zv);
|
||||
|
||||
if (auto_global->jit) {
|
||||
auto_global->armed = 1;
|
||||
} else if (auto_global->auto_global_callback) {
|
||||
auto_global->armed = auto_global->auto_global_callback(auto_global->name TSRMLS_CC);
|
||||
} else {
|
||||
auto_global->armed = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API void zend_activate_auto_globals(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
zend_hash_apply(CG(auto_globals), zend_auto_global_init TSRMLS_CC);
|
||||
zend_auto_global *auto_global;
|
||||
|
||||
ZEND_HASH_FOREACH_PTR(CG(auto_globals), auto_global) {
|
||||
if (auto_global->jit) {
|
||||
auto_global->armed = 1;
|
||||
} else if (auto_global->auto_global_callback) {
|
||||
auto_global->armed = auto_global->auto_global_callback(auto_global->name TSRMLS_CC);
|
||||
} else {
|
||||
auto_global->armed = 0;
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -3241,7 +3197,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
|
||||
dtor_func_t zval_ptr_dtor_func = ((persistent_hashes) ? ZVAL_INTERNAL_PTR_DTOR : ZVAL_PTR_DTOR);
|
||||
|
||||
ce->refcount = 1;
|
||||
ce->ce_flags = 0;
|
||||
ce->ce_flags = ZEND_ACC_CONSTANTS_UPDATED;
|
||||
|
||||
ce->default_properties_table = NULL;
|
||||
ce->default_static_members_table = NULL;
|
||||
@ -3404,6 +3360,7 @@ ZEND_API void zend_make_immutable_array(zval *zv TSRMLS_DC) /* {{{ */
|
||||
}
|
||||
|
||||
Z_TYPE_FLAGS_P(zv) = IS_TYPE_IMMUTABLE;
|
||||
GC_REFCOUNT(Z_COUNTED_P(zv)) = 2;
|
||||
Z_ARRVAL_P(zv)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
|
||||
|
||||
/* store as an anonymous constant */
|
||||
@ -3728,10 +3685,8 @@ static zend_bool zend_is_const_default_class_ref(zend_ast *name_ast) {
|
||||
static void zend_handle_numeric_op2(zend_op *opline TSRMLS_DC) {
|
||||
if (opline->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline->op2.constant)) == IS_STRING) {
|
||||
ulong index;
|
||||
int numeric = 0;
|
||||
|
||||
ZEND_HANDLE_NUMERIC_EX(Z_STRVAL(CONSTANT(opline->op2.constant)), Z_STRLEN(CONSTANT(opline->op2.constant))+1, index, numeric = 1);
|
||||
if (numeric) {
|
||||
if (ZEND_HANDLE_NUMERIC(Z_STR(CONSTANT(opline->op2.constant)), index)) {
|
||||
zval_dtor(&CONSTANT(opline->op2.constant));
|
||||
ZVAL_LONG(&CONSTANT(opline->op2.constant), index);
|
||||
}
|
||||
@ -4219,7 +4174,7 @@ zend_uint zend_compile_args(zend_ast *args, zend_function *fbc TSRMLS_DC) {
|
||||
} else {
|
||||
zend_compile_var(&arg_node, arg,
|
||||
BP_VAR_FUNC_ARG | (arg_num << BP_VAR_SHIFT) TSRMLS_CC);
|
||||
opcode = ZEND_SEND_VAR;
|
||||
opcode = ZEND_SEND_VAR_EX;
|
||||
}
|
||||
} else {
|
||||
zend_compile_expr(&arg_node, arg TSRMLS_CC);
|
||||
@ -4229,9 +4184,13 @@ zend_uint zend_compile_args(zend_ast *args, zend_function *fbc TSRMLS_DC) {
|
||||
flags |= ZEND_ARG_SEND_BY_REF;
|
||||
}
|
||||
} else {
|
||||
opcode = ZEND_SEND_VAL;
|
||||
if (fbc && ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Only variables can be passed by reference");
|
||||
if (fbc) {
|
||||
opcode = ZEND_SEND_VAL;
|
||||
if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Only variables can be passed by reference");
|
||||
}
|
||||
} else {
|
||||
opcode = ZEND_SEND_VAL_EX;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4247,49 +4206,32 @@ zend_uint zend_compile_args(zend_ast *args, zend_function *fbc TSRMLS_DC) {
|
||||
flags |= ZEND_ARG_COMPILE_TIME_BOUND;
|
||||
}
|
||||
opline->extended_value = flags;
|
||||
} else {
|
||||
opline->extended_value = fbc ? ZEND_DO_FCALL : ZEND_DO_FCALL_BY_NAME;
|
||||
}
|
||||
|
||||
if (++CG(context).used_stack > CG(active_op_array)->used_stack) {
|
||||
CG(active_op_array)->used_stack = CG(context).used_stack;
|
||||
} else if (fbc) {
|
||||
opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
|
||||
}
|
||||
}
|
||||
|
||||
return arg_count;
|
||||
}
|
||||
|
||||
zend_op *zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *fbc TSRMLS_DC) {
|
||||
void zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *fbc TSRMLS_DC) {
|
||||
zend_op *opline;
|
||||
zend_uint opnum_init = get_next_op_number(CG(active_op_array)) - 1;
|
||||
zend_uint arg_count;
|
||||
zend_uint call_flags;
|
||||
|
||||
zend_do_extended_fcall_begin(TSRMLS_C);
|
||||
|
||||
if (!fbc) {
|
||||
CG(context).nested_calls++;
|
||||
}
|
||||
|
||||
arg_count = zend_compile_args(args_ast, fbc TSRMLS_CC);
|
||||
|
||||
opline = emit_op(result, fbc ? ZEND_DO_FCALL : ZEND_DO_FCALL_BY_NAME, NULL, NULL TSRMLS_CC);
|
||||
opline->op2.num = CG(context).nested_calls;
|
||||
opline = &CG(active_op_array)->opcodes[opnum_init];
|
||||
opline->extended_value = arg_count;
|
||||
|
||||
if (!fbc) {
|
||||
CG(context).nested_calls--;
|
||||
}
|
||||
call_flags = (opline->opcode == ZEND_NEW ? ZEND_CALL_CTOR : 0);
|
||||
opline = emit_op(result, ZEND_DO_FCALL, NULL, NULL TSRMLS_CC);
|
||||
opline->op1.num = call_flags;
|
||||
|
||||
zend_do_extended_fcall_end(TSRMLS_C);
|
||||
|
||||
if (CG(context).nested_calls + 1 > CG(active_op_array)->nested_calls) {
|
||||
CG(active_op_array)->nested_calls = CG(context).nested_calls + 1;
|
||||
}
|
||||
if (CG(context).used_stack + 1 > CG(active_op_array)->used_stack) {
|
||||
CG(active_op_array)->used_stack = CG(context).used_stack + 1;
|
||||
}
|
||||
CG(context).used_stack -= arg_count;
|
||||
|
||||
return opline;
|
||||
}
|
||||
|
||||
zend_bool zend_compile_function_name(znode *name_node, zend_ast *name_ast TSRMLS_DC) {
|
||||
@ -4306,7 +4248,6 @@ zend_bool zend_compile_function_name(znode *name_node, zend_ast *name_ast TSRMLS
|
||||
void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast TSRMLS_DC) {
|
||||
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
|
||||
opline->result.num = CG(context).nested_calls;
|
||||
SET_UNUSED(opline->op1);
|
||||
opline->op2_type = IS_CONST;
|
||||
opline->op2.constant = zend_add_ns_func_name_literal(
|
||||
@ -4319,7 +4260,6 @@ void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast TS
|
||||
void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_ast TSRMLS_DC) {
|
||||
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_INIT_FCALL_BY_NAME;
|
||||
opline->result.num = CG(context).nested_calls;
|
||||
SET_UNUSED(opline->op1);
|
||||
if (name_node->op_type == IS_CONST && Z_TYPE(name_node->u.constant) == IS_STRING) {
|
||||
opline->op2_type = IS_CONST;
|
||||
@ -4388,9 +4328,10 @@ void zend_compile_call(znode *result, zend_ast *ast, int type TSRMLS_DC) {
|
||||
zval_ptr_dtor(&name_node.u.constant);
|
||||
ZVAL_NEW_STR(&name_node.u.constant, lcname);
|
||||
|
||||
opline = zend_compile_call_common(result, args_ast, fbc TSRMLS_CC);
|
||||
SET_NODE(opline->op1, &name_node);
|
||||
GET_CACHE_SLOT(opline->op1.constant);
|
||||
opline = emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node TSRMLS_CC);
|
||||
GET_CACHE_SLOT(opline->op2.constant);
|
||||
|
||||
zend_compile_call_common(result, args_ast, fbc TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4404,7 +4345,6 @@ void zend_compile_method_call(znode *result, zend_ast *ast, int type TSRMLS_DC)
|
||||
// TODO.AST using an evil overload from AST_METHOD to AST_PROP here ...
|
||||
zend_op *opline = zend_compile_prop_common(NULL, ast, BP_VAR_R TSRMLS_CC);
|
||||
opline->opcode = ZEND_INIT_METHOD_CALL;
|
||||
opline->result.num = CG(context).nested_calls;
|
||||
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
zval name;
|
||||
@ -4461,7 +4401,6 @@ void zend_compile_static_call(znode *result, zend_ast *ast, int type TSRMLS_DC)
|
||||
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
|
||||
opline->result.num = CG(context).nested_calls;
|
||||
opline->extended_value = extended_value;
|
||||
|
||||
zend_set_class_name_op1(opline, &class_node TSRMLS_CC);
|
||||
@ -4494,7 +4433,6 @@ void zend_compile_new(znode *result, zend_ast *ast TSRMLS_DC) {
|
||||
|
||||
opnum = get_next_op_number(CG(active_op_array));
|
||||
opline = emit_op(result, ZEND_NEW, &class_node, NULL TSRMLS_CC);
|
||||
opline->extended_value = CG(context).nested_calls;
|
||||
|
||||
zend_compile_call_common(&ctor_result, args_ast, NULL TSRMLS_CC);
|
||||
zend_do_free(&ctor_result TSRMLS_CC);
|
||||
@ -5277,7 +5215,12 @@ void zend_compile_params(zend_ast *ast TSRMLS_DC) {
|
||||
var_node.op_type = IS_CV;
|
||||
var_node.u.op.var = lookup_cv(CG(active_op_array), STR_COPY(name) TSRMLS_CC);
|
||||
|
||||
if (name->len == sizeof("this") - 1 && !memcmp(name->val, "this", sizeof("this") - 1)) {
|
||||
if (EX_VAR_TO_NUM(var_node.u.op.var) != i) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Redefinition of parameter %s",
|
||||
name->val);
|
||||
} else if (name->len == sizeof("this") - 1
|
||||
&& !memcmp(name->val, "this", sizeof("this") - 1)
|
||||
) {
|
||||
if (op_array->scope && (op_array->fn_flags & ZEND_ACC_STATIC) == 0) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
|
||||
}
|
||||
@ -5655,7 +5598,7 @@ void zend_compile_func_decl(znode *result, zend_ast *ast TSRMLS_DC) {
|
||||
zend_bool is_method = decl->kind == ZEND_AST_METHOD;
|
||||
|
||||
zend_op_array *orig_op_array = CG(active_op_array);
|
||||
zend_op_array *op_array = emalloc(sizeof(zend_op_array));
|
||||
zend_op_array *op_array = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
|
||||
|
||||
// TODO.AST interactive (not just here - also bpc etc!)
|
||||
|
||||
@ -5800,6 +5743,10 @@ void zend_compile_class_const_decl(zend_ast *ast TSRMLS_DC) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s",
|
||||
ce->name->val, name);
|
||||
}
|
||||
|
||||
if (Z_CONSTANT(value_zv)) {
|
||||
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5964,7 +5911,7 @@ void zend_compile_class_decl(zend_ast *ast TSRMLS_DC) {
|
||||
zend_ast *stmt_ast = decl->child[2];
|
||||
|
||||
zend_string *name = decl->name, *lcname, *import_name = NULL;
|
||||
zend_class_entry *ce = emalloc(sizeof(zend_class_entry));
|
||||
zend_class_entry *ce = zend_arena_alloc(&CG(arena), sizeof(zend_class_entry));
|
||||
zend_op *opline;
|
||||
znode declare_node, extends_node;
|
||||
|
||||
|
@ -59,8 +59,6 @@ typedef struct _zend_compiler_context {
|
||||
int literals_size;
|
||||
int current_brk_cont;
|
||||
int backpatch_count;
|
||||
int nested_calls;
|
||||
int used_stack;
|
||||
int in_finally;
|
||||
HashTable *labels;
|
||||
} zend_compiler_context;
|
||||
@ -289,9 +287,6 @@ struct _zend_op_array {
|
||||
|
||||
zend_uint T;
|
||||
|
||||
zend_uint nested_calls;
|
||||
zend_uint used_stack;
|
||||
|
||||
zend_brk_cont_element *brk_cont_array;
|
||||
int last_brk_cont;
|
||||
|
||||
@ -359,14 +354,9 @@ union _zend_function {
|
||||
zend_internal_function internal_function;
|
||||
};
|
||||
|
||||
|
||||
typedef struct _zend_function_state {
|
||||
zend_function *function;
|
||||
zval *arguments;
|
||||
} zend_function_state;
|
||||
|
||||
typedef struct _zend_function_call_entry {
|
||||
zend_function *fbc;
|
||||
zend_uint op_number;
|
||||
zend_uint arg_num;
|
||||
zend_bool uses_argument_unpacking;
|
||||
} zend_function_call_entry;
|
||||
@ -384,15 +374,6 @@ typedef struct _list_llist_element {
|
||||
znode value;
|
||||
} list_llist_element;
|
||||
|
||||
typedef struct _call_slot {
|
||||
zend_function *fbc;
|
||||
zend_class_entry *called_scope;
|
||||
zend_object *object;
|
||||
zend_uint num_additional_args;
|
||||
zend_bool is_ctor_call;
|
||||
zend_bool is_ctor_result_used;
|
||||
} call_slot;
|
||||
|
||||
typedef enum _vm_frame_kind {
|
||||
VM_FRAME_NESTED_FUNCTION, /* stackless VM call to function */
|
||||
VM_FRAME_NESTED_CODE, /* stackless VM call to include/require/eval */
|
||||
@ -402,28 +383,37 @@ typedef enum _vm_frame_kind {
|
||||
|
||||
struct _zend_execute_data {
|
||||
struct _zend_op *opline; /* executed opline */
|
||||
zend_op_array *op_array; /* executed op_array */
|
||||
zend_function_state function_state; /* called function and arguments */
|
||||
zend_object *object; /* current $this */
|
||||
zend_class_entry *scope; /* function scope (self) */
|
||||
zend_class_entry *called_scope; /* function called scope (static) */
|
||||
zend_array *symbol_table;
|
||||
zend_execute_data *call; /* current call */
|
||||
void **run_time_cache;
|
||||
zend_function *func; /* executed op_array */
|
||||
zend_uint num_args;
|
||||
zend_uchar flags;
|
||||
zend_uchar frame_kind;
|
||||
zend_class_entry *called_scope;
|
||||
zend_object *object;
|
||||
zend_execute_data *prev_nested_call;
|
||||
zend_execute_data *prev_execute_data;
|
||||
zval *return_value;
|
||||
vm_frame_kind frame_kind;
|
||||
// TODO: simplify call sequence and remove call_* ???
|
||||
zval old_error_reporting;
|
||||
struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
|
||||
zend_object *delayed_exception;
|
||||
call_slot *call_slots;
|
||||
call_slot *call;
|
||||
zend_class_entry *scope; /* function scope (self) */
|
||||
zend_array *symbol_table;
|
||||
struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
|
||||
zend_object *delayed_exception;
|
||||
zval old_error_reporting;
|
||||
};
|
||||
|
||||
#define ZEND_CALL_CTOR (1 << 0)
|
||||
#define ZEND_CALL_CTOR_RESULT_UNUSED (1 << 1)
|
||||
|
||||
#define ZEND_CALL_FRAME_SLOT \
|
||||
((ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / ZEND_MM_ALIGNED_SIZE(sizeof(zval)))
|
||||
|
||||
#define ZEND_CALL_ARG(call, n) \
|
||||
(((zval*)(call)) + ((n) + (ZEND_CALL_FRAME_SLOT - 1)))
|
||||
|
||||
#define EX(element) execute_data.element
|
||||
|
||||
#define EX_VAR_2(ex, n) ((zval*)(((char*)(ex)) + ((int)(n))))
|
||||
#define EX_VAR_NUM_2(ex, n) (((zval*)(((char*)(ex))+ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data))))+(n))
|
||||
#define EX_VAR_NUM_2(ex, n) (((zval*)(ex)) + (ZEND_CALL_FRAME_SLOT + ((int)(n))))
|
||||
|
||||
#define EX_VAR(n) EX_VAR_2(execute_data, n)
|
||||
#define EX_VAR_NUM(n) EX_VAR_NUM_2(execute_data, n)
|
||||
@ -485,7 +475,7 @@ void zend_do_build_full_name(znode *result, znode *prefix, znode *name, int is_c
|
||||
void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC);
|
||||
void zend_do_handle_exception(TSRMLS_D);
|
||||
|
||||
ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, HashTable *function_table, zend_bool compile_time);
|
||||
ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, HashTable *function_table, zend_bool compile_time TSRMLS_DC);
|
||||
ZEND_API zend_class_entry *do_bind_class(const zend_op_array *op_array, const zend_op *opline, HashTable *class_table, zend_bool compile_time TSRMLS_DC);
|
||||
ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op_array *op_array, const zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time TSRMLS_DC);
|
||||
ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_entry *iface TSRMLS_DC);
|
||||
@ -598,8 +588,8 @@ int zend_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC);
|
||||
#define ZEND_FETCH_CLASS_DEFAULT 0
|
||||
#define ZEND_FETCH_CLASS_SELF 1
|
||||
#define ZEND_FETCH_CLASS_PARENT 2
|
||||
#define ZEND_FETCH_CLASS_MAIN 3 /* unused */
|
||||
#define ZEND_FETCH_CLASS_GLOBAL 4 /* unused */
|
||||
#define ZEND_FETCH_CLASS_MAIN 3 /* unused ??? */
|
||||
#define ZEND_FETCH_CLASS_GLOBAL 4 /* unused ??? */
|
||||
#define ZEND_FETCH_CLASS_AUTO 5
|
||||
#define ZEND_FETCH_CLASS_INTERFACE 6
|
||||
#define ZEND_FETCH_CLASS_STATIC 7
|
||||
@ -648,6 +638,9 @@ int zend_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC);
|
||||
#define ZEND_EVAL_CODE 4
|
||||
#define ZEND_OVERLOADED_FUNCTION_TEMPORARY 5
|
||||
|
||||
/* A quick check (type == ZEND_USER_FUNCTION || type == ZEND_EVAL_CODE) */
|
||||
#define ZEND_USER_CODE(type) ((type & 1) == 0)
|
||||
|
||||
#define ZEND_INTERNAL_CLASS 1
|
||||
#define ZEND_USER_CLASS 2
|
||||
|
||||
@ -726,6 +719,9 @@ int zend_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC);
|
||||
#define ZEND_FAST_RET_TO_CATCH 1
|
||||
#define ZEND_FAST_RET_TO_FINALLY 2
|
||||
|
||||
#define ZEND_FAST_CALL_FROM_CATCH 1
|
||||
#define ZEND_FAST_CALL_FROM_FINALLY 2
|
||||
|
||||
#define ZEND_ARRAY_ELEMENT_REF (1<<0)
|
||||
#define ZEND_ARRAY_NOT_PACKED (1<<1)
|
||||
#define ZEND_ARRAY_SIZE_SHIFT 2
|
||||
@ -755,7 +751,7 @@ END_EXTERN_C()
|
||||
/* call op_array handler of extendions */
|
||||
#define ZEND_COMPILE_HANDLE_OP_ARRAY (1<<1)
|
||||
|
||||
/* generate ZEND_DO_FCALL_BY_NAME for internal functions instead of ZEND_DO_FCALL */
|
||||
/* generate ZEND_INIT_FCALL_BY_NAME for internal functions instead of ZEND_INIT_FCALL */
|
||||
#define ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS (1<<2)
|
||||
|
||||
/* don't perform early binding for classes inherited form internal ones;
|
||||
@ -769,6 +765,9 @@ END_EXTERN_C()
|
||||
/* disable constant substitution at compile-time */
|
||||
#define ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION (1<<5)
|
||||
|
||||
/* disable usage of builtin instruction for strlen() */
|
||||
#define ZEND_COMPILE_NO_BUILTIN_STRLEN (1<<6)
|
||||
|
||||
/* The default value for CG(compiler_options) */
|
||||
#define ZEND_COMPILE_DEFAULT ZEND_COMPILE_HANDLE_OP_ARRAY
|
||||
|
||||
|
@ -231,7 +231,7 @@ static zend_constant *zend_get_special_constant(const char *name, uint name_len
|
||||
zend_constant *c;
|
||||
static char haltoff[] = "__COMPILER_HALT_OFFSET__";
|
||||
|
||||
if (!EG(in_execution)) {
|
||||
if (!EG(current_execute_data)) {
|
||||
return NULL;
|
||||
} else if (name_len == sizeof("__CLASS__")-1 &&
|
||||
!memcmp(name, "__CLASS__", sizeof("__CLASS__")-1)) {
|
||||
@ -354,7 +354,7 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope,
|
||||
lcname = do_alloca(class_name_len + 1, use_heap);
|
||||
zend_str_tolower_copy(lcname, name, class_name_len);
|
||||
if (!scope) {
|
||||
if (EG(in_execution)) {
|
||||
if (EG(current_execute_data)) {
|
||||
scope = EG(scope);
|
||||
} else {
|
||||
scope = CG(active_class_entry);
|
||||
@ -379,8 +379,8 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope,
|
||||
}
|
||||
} else if (class_name_len == sizeof("static")-1 &&
|
||||
!memcmp(lcname, "static", sizeof("static")-1)) {
|
||||
if (EG(called_scope)) {
|
||||
ce = EG(called_scope);
|
||||
if (EG(current_execute_data) && EG(current_execute_data)->called_scope) {
|
||||
ce = EG(current_execute_data)->called_scope;
|
||||
} else {
|
||||
zend_error(E_ERROR, "Cannot access static:: when no class scope is active");
|
||||
}
|
||||
|
@ -26,8 +26,13 @@
|
||||
/* PHP DTrace probes {{{ */
|
||||
static inline const char *dtrace_get_executed_filename(TSRMLS_D)
|
||||
{
|
||||
if (EG(current_execute_data) && EG(current_execute_data)->op_array) {
|
||||
return EG(current_execute_data)->op_array->filename;
|
||||
zend_execute_data *ex = EG(current_execute_data);
|
||||
|
||||
while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
|
||||
ex = ex->prev_execute_data;
|
||||
}
|
||||
if (ex) {
|
||||
return ex->func->op_array.filename->val;
|
||||
} else {
|
||||
return zend_get_executed_filename(TSRMLS_C);
|
||||
}
|
||||
@ -81,7 +86,7 @@ ZEND_API void dtrace_execute_ex(zend_execute_data *execute_data TSRMLS_DC)
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci TSRMLS_DC)
|
||||
ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data, zval *return_value TSRMLS_DC)
|
||||
{
|
||||
int lineno;
|
||||
const char *filename;
|
||||
@ -94,7 +99,7 @@ ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data_ptr, zend_
|
||||
DTRACE_EXECUTE_ENTRY((char *)filename, lineno);
|
||||
}
|
||||
|
||||
execute_internal(execute_data_ptr, fci TSRMLS_CC);
|
||||
execute_internal(execute_data, return_value TSRMLS_CC);
|
||||
|
||||
if (DTRACE_EXECUTE_RETURN_ENABLED()) {
|
||||
DTRACE_EXECUTE_RETURN((char *)filename, lineno);
|
||||
|
@ -32,11 +32,11 @@ extern "C" {
|
||||
#ifdef HAVE_DTRACE
|
||||
ZEND_API zend_op_array *(*zend_dtrace_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
|
||||
ZEND_API void (*zend_dtrace_execute)(zend_op_array *op_array TSRMLS_DC);
|
||||
ZEND_API void (*zend_dtrace_execute_internal)(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC);
|
||||
ZEND_API void (*zend_dtrace_execute_internal)(zend_execute_data *execute_data, zval *return_value TSRMLS_DC);
|
||||
|
||||
ZEND_API zend_op_array *dtrace_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC);
|
||||
ZEND_API void dtrace_execute_ex(zend_execute_data *execute_data TSRMLS_DC);
|
||||
ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC);
|
||||
ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data, zval *return_value TSRMLS_DC);
|
||||
#include <zend_dtrace_gen.h>
|
||||
|
||||
#endif /* HAVE_DTRACE */
|
||||
|
@ -88,12 +88,11 @@ void zend_throw_exception_internal(zval *exception TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
#ifdef HAVE_DTRACE
|
||||
if (DTRACE_EXCEPTION_THROWN_ENABLED()) {
|
||||
const char *classname;
|
||||
zend_uint name_len;
|
||||
zend_string *classname;
|
||||
|
||||
if (exception != NULL) {
|
||||
zend_get_object_classname(Z_OBJ_P(exception), &classname, &name_len TSRMLS_CC);
|
||||
DTRACE_EXCEPTION_THROWN((char *)classname);
|
||||
classname = zend_get_object_classname(Z_OBJ_P(exception) TSRMLS_CC);
|
||||
DTRACE_EXCEPTION_THROWN(classname->val);
|
||||
} else {
|
||||
DTRACE_EXCEPTION_THROWN(NULL);
|
||||
}
|
||||
@ -119,7 +118,8 @@ void zend_throw_exception_internal(zval *exception TSRMLS_DC) /* {{{ */
|
||||
zend_throw_exception_hook(exception TSRMLS_CC);
|
||||
}
|
||||
|
||||
if (EG(current_execute_data)->opline == NULL ||
|
||||
if (!EG(current_execute_data)->func ||
|
||||
!ZEND_USER_CODE(EG(current_execute_data)->func->common.type) ||
|
||||
(EG(current_execute_data)->opline+1)->opcode == ZEND_HANDLE_EXCEPTION) {
|
||||
/* no need to rethrow the exception */
|
||||
return;
|
||||
@ -269,8 +269,7 @@ static void _default_exception_get_entry(zval *object, char *name, int name_len,
|
||||
zval *value;
|
||||
|
||||
value = zend_read_property(default_exception_ce, object, name, name_len, 0 TSRMLS_CC);
|
||||
|
||||
ZVAL_DUP_DEREF(return_value, value);
|
||||
ZVAL_COPY(return_value, value);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -30,15 +30,16 @@
|
||||
BEGIN_EXTERN_C()
|
||||
struct _zend_fcall_info;
|
||||
ZEND_API extern void (*zend_execute_ex)(zend_execute_data *execute_data TSRMLS_DC);
|
||||
ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, struct _zend_fcall_info *fci TSRMLS_DC);
|
||||
ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data, zval *return_value TSRMLS_DC);
|
||||
|
||||
void init_executor(TSRMLS_D);
|
||||
void shutdown_executor(TSRMLS_D);
|
||||
void shutdown_destructors(TSRMLS_D);
|
||||
ZEND_API zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC);
|
||||
ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC);
|
||||
ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data *call, zend_op_array *op_array, zval *return_value TSRMLS_DC);
|
||||
ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value TSRMLS_DC);
|
||||
ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC);
|
||||
ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, struct _zend_fcall_info *fci TSRMLS_DC);
|
||||
ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value TSRMLS_DC);
|
||||
ZEND_API int zend_is_true(zval *op TSRMLS_DC);
|
||||
ZEND_API zend_class_entry *zend_lookup_class(zend_string *name TSRMLS_DC);
|
||||
ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *key, int use_autoload TSRMLS_DC);
|
||||
@ -48,7 +49,7 @@ ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name,
|
||||
ZEND_API int zend_eval_stringl_ex(char *str, int str_len, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
|
||||
|
||||
ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ulong fetch_type, char **class_name, zend_class_entry **pce TSRMLS_DC);
|
||||
ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind TSRMLS_DC);
|
||||
ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC);
|
||||
|
||||
static zend_always_inline void i_zval_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC TSRMLS_DC)
|
||||
{
|
||||
@ -149,7 +150,7 @@ ZEND_API int zval_update_constant_no_inline_change(zval *pp, zend_class_entry *s
|
||||
ZEND_API int zval_update_constant_ex(zval *pp, zend_bool inline_change, zend_class_entry *scope TSRMLS_DC);
|
||||
|
||||
/* dedicated Zend executor functions - do not use! */
|
||||
#define ZEND_VM_STACK_PAGE_SIZE ((16 * 1024) - 16)
|
||||
#define ZEND_VM_STACK_PAGE_SIZE (16 * 1024) /* should be a power of 2 */
|
||||
|
||||
struct _zend_vm_stack {
|
||||
zval *top;
|
||||
@ -157,22 +158,26 @@ struct _zend_vm_stack {
|
||||
zend_vm_stack prev;
|
||||
};
|
||||
|
||||
#define ZEND_VM_STACK_ELEMETS(stack) \
|
||||
((zval*)(((char*)(stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(struct _zend_vm_stack))))
|
||||
#define ZEND_VM_STACK_HEADER_SLOT \
|
||||
((ZEND_MM_ALIGNED_SIZE(sizeof(struct _zend_vm_stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / ZEND_MM_ALIGNED_SIZE(sizeof(zval)))
|
||||
|
||||
#define ZEND_VM_STACK_GROW_IF_NEEDED(count) \
|
||||
do { \
|
||||
if (UNEXPECTED((count) > \
|
||||
EG(argument_stack)->end - EG(argument_stack)->top)) { \
|
||||
zend_vm_stack_extend((count) TSRMLS_CC); \
|
||||
} \
|
||||
#define ZEND_VM_STACK_ELEMETS(stack) \
|
||||
(((zval*)(stack)) + ZEND_VM_STACK_HEADER_SLOT)
|
||||
|
||||
#define ZEND_VM_STACK_GROW_IF_NEEDED(count) \
|
||||
do { \
|
||||
if (UNEXPECTED(((count) * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) > \
|
||||
(size_t)(((char*)EG(argument_stack)->end) - \
|
||||
((char*)EG(argument_stack)->top)))) { \
|
||||
zend_vm_stack_extend((count) TSRMLS_CC); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static zend_always_inline zend_vm_stack zend_vm_stack_new_page(int count) {
|
||||
zend_vm_stack page = (zend_vm_stack)emalloc(ZEND_MM_ALIGNED_SIZE(sizeof(*page)) + sizeof(zval) * count);
|
||||
zend_vm_stack page = (zend_vm_stack)emalloc(count * ZEND_MM_ALIGNED_SIZE(sizeof(zval)));
|
||||
|
||||
page->top = ZEND_VM_STACK_ELEMETS(page);
|
||||
page->end = page->top + count;
|
||||
page->end = (zval*)page + count;
|
||||
page->prev = NULL;
|
||||
return page;
|
||||
}
|
||||
@ -180,6 +185,7 @@ static zend_always_inline zend_vm_stack zend_vm_stack_new_page(int count) {
|
||||
static zend_always_inline void zend_vm_stack_init(TSRMLS_D)
|
||||
{
|
||||
EG(argument_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE);
|
||||
EG(argument_stack)->top++;
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_vm_stack_destroy(TSRMLS_D)
|
||||
@ -195,108 +201,77 @@ static zend_always_inline void zend_vm_stack_destroy(TSRMLS_D)
|
||||
|
||||
static zend_always_inline void zend_vm_stack_extend(int count TSRMLS_DC)
|
||||
{
|
||||
zend_vm_stack p = zend_vm_stack_new_page(count >= ZEND_VM_STACK_PAGE_SIZE ? count : ZEND_VM_STACK_PAGE_SIZE);
|
||||
int size = count * ZEND_MM_ALIGNED_SIZE(sizeof(zval));
|
||||
zend_vm_stack p = zend_vm_stack_new_page(
|
||||
(size >= (ZEND_VM_STACK_PAGE_SIZE - ZEND_VM_STACK_HEADER_SLOT) * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) ?
|
||||
(size + ((ZEND_VM_STACK_HEADER_SLOT + ZEND_VM_STACK_PAGE_SIZE) * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) - 1) &
|
||||
~((ZEND_VM_STACK_PAGE_SIZE * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) - 1) :
|
||||
ZEND_VM_STACK_PAGE_SIZE);
|
||||
p->prev = EG(argument_stack);
|
||||
EG(argument_stack) = p;
|
||||
}
|
||||
|
||||
static zend_always_inline zval *zend_vm_stack_top(TSRMLS_D)
|
||||
static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(zend_function *func, zend_uint num_args, zend_uchar flags, zend_class_entry *called_scope, zend_object *object, zend_execute_data *prev TSRMLS_DC)
|
||||
{
|
||||
return EG(argument_stack)->top;
|
||||
int used_stack = ZEND_CALL_FRAME_SLOT + num_args;
|
||||
zend_execute_data *call;
|
||||
|
||||
if (ZEND_USER_CODE(func->type)) {
|
||||
used_stack += func->op_array.last_var + func->op_array.T - MIN(func->op_array.num_args, num_args);
|
||||
}
|
||||
ZEND_VM_STACK_GROW_IF_NEEDED(used_stack);
|
||||
call = (zend_execute_data*)EG(argument_stack)->top;
|
||||
EG(argument_stack)->top += used_stack;
|
||||
call->func = func;
|
||||
call->num_args = 0;
|
||||
call->flags = flags;
|
||||
call->called_scope = called_scope;
|
||||
call->object = object;
|
||||
call->prev_nested_call = prev;
|
||||
return call;
|
||||
}
|
||||
|
||||
static zend_always_inline zval *zend_vm_stack_top_inc(TSRMLS_D)
|
||||
static zend_always_inline void zend_vm_stack_free_extra_args(zend_execute_data *call TSRMLS_DC)
|
||||
{
|
||||
return EG(argument_stack)->top++;
|
||||
zend_uint first_extra_arg = call->func->op_array.num_args - ((call->func->common.fn_flags & ZEND_ACC_VARIADIC) != 0);
|
||||
|
||||
if (UNEXPECTED(call->num_args > first_extra_arg)) {
|
||||
zval *end = EX_VAR_NUM_2(call, call->func->op_array.last_var + call->func->op_array.T);
|
||||
zval *p = end + (call->num_args - first_extra_arg);
|
||||
do {
|
||||
p--;
|
||||
i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC);
|
||||
} while (p != end);
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_vm_stack_push(zval *ptr TSRMLS_DC)
|
||||
static zend_always_inline void zend_vm_stack_free_args(zend_execute_data *call TSRMLS_DC)
|
||||
{
|
||||
ZVAL_COPY_VALUE(EG(argument_stack)->top, ptr);
|
||||
EG(argument_stack)->top++;
|
||||
zend_uint num_args = call->num_args;
|
||||
|
||||
if (num_args > 0) {
|
||||
zval *end = ZEND_CALL_ARG(call, 1);
|
||||
zval *p = end + num_args;
|
||||
|
||||
do {
|
||||
p--;
|
||||
i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC);
|
||||
} while (p != end);
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline zval *zend_vm_stack_pop(TSRMLS_D)
|
||||
static zend_always_inline void zend_vm_stack_free_call_frame(zend_execute_data *call TSRMLS_DC)
|
||||
{
|
||||
return --EG(argument_stack)->top;
|
||||
}
|
||||
|
||||
static zend_always_inline void *zend_vm_stack_alloc(size_t size TSRMLS_DC)
|
||||
{
|
||||
zval *ret;
|
||||
int count = (size + (sizeof(zval) - 1)) / sizeof(zval);
|
||||
|
||||
ZEND_VM_STACK_GROW_IF_NEEDED(count);
|
||||
ret = (void*)EG(argument_stack)->top;
|
||||
EG(argument_stack)->top += count;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static zend_always_inline zval* zend_vm_stack_frame_base(zend_execute_data *ex)
|
||||
{
|
||||
return (zval*)((char*)ex->call_slots +
|
||||
ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * ex->op_array->nested_calls);
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_vm_stack_free(void *ptr TSRMLS_DC)
|
||||
{
|
||||
if (UNEXPECTED((void*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == ptr)) {
|
||||
if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (zval*)call)) {
|
||||
zend_vm_stack p = EG(argument_stack);
|
||||
|
||||
EG(argument_stack) = p->prev;
|
||||
efree(p);
|
||||
} else {
|
||||
EG(argument_stack)->top = (zval*)ptr;
|
||||
EG(argument_stack)->top = (zval*)call;
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_vm_stack_clear_multiple(int nested TSRMLS_DC)
|
||||
{
|
||||
zval *p = EG(argument_stack)->top - 1;
|
||||
zval *end = p - Z_LVAL_P(p);
|
||||
|
||||
while (p != end) {
|
||||
p--;
|
||||
i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC);
|
||||
}
|
||||
if (nested) {
|
||||
EG(argument_stack)->top = p;
|
||||
} else {
|
||||
zend_vm_stack_free(p TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline int zend_vm_stack_get_args_count_ex(zend_execute_data *ex)
|
||||
{
|
||||
zval *p = ex->function_state.arguments;
|
||||
return Z_LVAL_P(p);
|
||||
}
|
||||
|
||||
static zend_always_inline zval* zend_vm_stack_get_arg_ex(zend_execute_data *ex, int requested_arg)
|
||||
{
|
||||
zval *p = ex->function_state.arguments;
|
||||
int arg_count = Z_LVAL_P(p);
|
||||
|
||||
if (UNEXPECTED(requested_arg > arg_count)) {
|
||||
return NULL;
|
||||
}
|
||||
return p - arg_count + requested_arg - 1;
|
||||
}
|
||||
|
||||
static zend_always_inline int zend_vm_stack_get_args_count(TSRMLS_D)
|
||||
{
|
||||
if (EG(current_execute_data)->prev_execute_data) {
|
||||
return zend_vm_stack_get_args_count_ex(EG(current_execute_data)->prev_execute_data);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline zval* zend_vm_stack_get_arg(int requested_arg TSRMLS_DC)
|
||||
{
|
||||
return zend_vm_stack_get_arg_ex(EG(current_execute_data)->prev_execute_data, requested_arg);
|
||||
}
|
||||
|
||||
void execute_new_code(TSRMLS_D);
|
||||
|
||||
|
||||
@ -321,8 +296,6 @@ void zend_shutdown_timeout_thread(void);
|
||||
#define WM_UNREGISTER_ZEND_TIMEOUT (WM_USER+2)
|
||||
#endif
|
||||
|
||||
#define active_opline (*EG(opline_ptr))
|
||||
|
||||
/* The following tries to resolve the classname of a zval of type object.
|
||||
* Since it is slow it should be only used in error messages.
|
||||
*/
|
||||
@ -371,21 +344,19 @@ void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC);
|
||||
EX(run_time_cache)[(num) + 1] = (ptr); \
|
||||
} while (0)
|
||||
|
||||
#define CACHED_PTR_EX(op_array, num) \
|
||||
(op_array)->run_time_cache[(num)]
|
||||
#define CACHED_PTR_EX(slot) \
|
||||
(slot)[0]
|
||||
|
||||
#define CACHE_PTR_EX(op_array, num, ptr) do { \
|
||||
(op_array)->run_time_cache[(num)] = (ptr); \
|
||||
#define CACHE_PTR_EX(slot, ptr) do { \
|
||||
(slot)[0] = (ptr); \
|
||||
} while (0)
|
||||
|
||||
#define CACHED_POLYMORPHIC_PTR_EX(op_array, num, ce) \
|
||||
(((op_array)->run_time_cache[(num)] == (ce)) ? \
|
||||
(op_array)->run_time_cache[(num) + 1] : \
|
||||
NULL)
|
||||
#define CACHED_POLYMORPHIC_PTR_EX(slot, ce) \
|
||||
(((slot)[0] == (ce)) ? (slot)[1] : NULL)
|
||||
|
||||
#define CACHE_POLYMORPHIC_PTR_EX(op_array, num, ce, ptr) do { \
|
||||
(op_array)->run_time_cache[(num)] = (ce); \
|
||||
(op_array)->run_time_cache[(num) + 1] = (ptr); \
|
||||
#define CACHE_POLYMORPHIC_PTR_EX(slot, ce, ptr) do { \
|
||||
(slot)[0] = (ce); \
|
||||
(slot)[1] = (ptr); \
|
||||
} while (0)
|
||||
|
||||
END_EXTERN_C()
|
||||
|
@ -39,7 +39,7 @@
|
||||
#endif
|
||||
|
||||
ZEND_API void (*zend_execute_ex)(zend_execute_data *execute_data TSRMLS_DC);
|
||||
ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, zend_fcall_info *fci TSRMLS_DC);
|
||||
ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data, zval *return_value TSRMLS_DC);
|
||||
|
||||
/* true globals */
|
||||
ZEND_API const zend_fcall_info empty_fcall_info = { 0, NULL, {{0},0}, NULL, NULL, 0, NULL, NULL, 0 };
|
||||
@ -150,20 +150,18 @@ void init_executor(TSRMLS_D) /* {{{ */
|
||||
EG(function_table) = CG(function_table);
|
||||
EG(class_table) = CG(class_table);
|
||||
|
||||
EG(in_execution) = 0;
|
||||
EG(in_autoload) = NULL;
|
||||
EG(autoload_func) = NULL;
|
||||
EG(error_handling) = EH_NORMAL;
|
||||
|
||||
zend_vm_stack_init(TSRMLS_C);
|
||||
ZVAL_LONG(zend_vm_stack_top_inc(TSRMLS_C), 0);
|
||||
|
||||
zend_hash_init(&EG(symbol_table).ht, 64, NULL, ZVAL_PTR_DTOR, 0);
|
||||
GC_REFCOUNT(&EG(symbol_table)) = 1;
|
||||
GC_TYPE_INFO(&EG(symbol_table)) = IS_ARRAY;
|
||||
EG(active_symbol_table) = &EG(symbol_table);
|
||||
EG(valid_symbol_table) = 1;
|
||||
|
||||
zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_activator TSRMLS_CC);
|
||||
EG(opline_ptr) = NULL;
|
||||
|
||||
zend_hash_init(&EG(included_files), 8, NULL, NULL, 0);
|
||||
|
||||
@ -188,12 +186,9 @@ void init_executor(TSRMLS_D) /* {{{ */
|
||||
EG(prev_exception) = NULL;
|
||||
|
||||
EG(scope) = NULL;
|
||||
EG(called_scope) = NULL;
|
||||
|
||||
ZVAL_OBJ(&EG(This), NULL);
|
||||
|
||||
EG(active_op_array) = NULL;
|
||||
|
||||
EG(active) = 1;
|
||||
EG(start_op) = NULL;
|
||||
}
|
||||
@ -271,6 +266,7 @@ void shutdown_executor(TSRMLS_D) /* {{{ */
|
||||
}
|
||||
zend_hash_graceful_reverse_destroy(&EG(symbol_table).ht);
|
||||
} zend_end_try();
|
||||
EG(valid_symbol_table) = 0;
|
||||
|
||||
zend_try {
|
||||
zval *zeh;
|
||||
@ -392,17 +388,21 @@ void shutdown_executor(TSRMLS_D) /* {{{ */
|
||||
/* return class name and "::" or "". */
|
||||
ZEND_API const char *get_active_class_name(const char **space TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_function *func;
|
||||
|
||||
if (!zend_is_executing(TSRMLS_C)) {
|
||||
if (space) {
|
||||
*space = "";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
switch (EG(current_execute_data)->function_state.function->type) {
|
||||
|
||||
func = EG(current_execute_data)->func;
|
||||
switch (func->type) {
|
||||
case ZEND_USER_FUNCTION:
|
||||
case ZEND_INTERNAL_FUNCTION:
|
||||
{
|
||||
zend_class_entry *ce = EG(current_execute_data)->function_state.function->common.scope;
|
||||
zend_class_entry *ce = func->common.scope;
|
||||
|
||||
if (space) {
|
||||
*space = ce ? "::" : "";
|
||||
@ -420,12 +420,15 @@ ZEND_API const char *get_active_class_name(const char **space TSRMLS_DC) /* {{{
|
||||
|
||||
ZEND_API const char *get_active_function_name(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
zend_function *func;
|
||||
|
||||
if (!zend_is_executing(TSRMLS_C)) {
|
||||
return NULL;
|
||||
}
|
||||
switch (EG(current_execute_data)->function_state.function->type) {
|
||||
func = EG(current_execute_data)->func;
|
||||
switch (func->type) {
|
||||
case ZEND_USER_FUNCTION: {
|
||||
zend_string *function_name = ((zend_op_array *) EG(current_execute_data)->function_state.function)->function_name;
|
||||
zend_string *function_name = func->common.function_name;
|
||||
|
||||
if (function_name) {
|
||||
return function_name->val;
|
||||
@ -435,7 +438,7 @@ ZEND_API const char *get_active_function_name(TSRMLS_D) /* {{{ */
|
||||
}
|
||||
break;
|
||||
case ZEND_INTERNAL_FUNCTION:
|
||||
return ((zend_internal_function *) EG(current_execute_data)->function_state.function)->function_name->val;
|
||||
return func->common.function_name->val;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
@ -445,8 +448,13 @@ ZEND_API const char *get_active_function_name(TSRMLS_D) /* {{{ */
|
||||
|
||||
ZEND_API const char *zend_get_executed_filename(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
if (EG(active_op_array)) {
|
||||
return EG(active_op_array)->filename->val;
|
||||
zend_execute_data *ex = EG(current_execute_data);
|
||||
|
||||
while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
|
||||
ex = ex->prev_execute_data;
|
||||
}
|
||||
if (ex) {
|
||||
return ex->func->op_array.filename->val;
|
||||
} else {
|
||||
return "[no active file]";
|
||||
}
|
||||
@ -455,12 +463,17 @@ ZEND_API const char *zend_get_executed_filename(TSRMLS_D) /* {{{ */
|
||||
|
||||
ZEND_API uint zend_get_executed_lineno(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
if(EG(exception) && EG(opline_ptr) && active_opline->opcode == ZEND_HANDLE_EXCEPTION &&
|
||||
active_opline->lineno == 0 && EG(opline_before_exception)) {
|
||||
return EG(opline_before_exception)->lineno;
|
||||
zend_execute_data *ex = EG(current_execute_data);
|
||||
|
||||
while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
|
||||
ex = ex->prev_execute_data;
|
||||
}
|
||||
if (EG(opline_ptr)) {
|
||||
return active_opline->lineno;
|
||||
if (ex) {
|
||||
if (EG(exception) && ex->opline->opcode == ZEND_HANDLE_EXCEPTION &&
|
||||
ex->opline->lineno == 0 && EG(opline_before_exception)) {
|
||||
return EG(opline_before_exception)->lineno;
|
||||
}
|
||||
return ex->opline->lineno;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
@ -469,7 +482,7 @@ ZEND_API uint zend_get_executed_lineno(TSRMLS_D) /* {{{ */
|
||||
|
||||
ZEND_API zend_bool zend_is_executing(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
return EG(in_execution);
|
||||
return EG(current_execute_data) != 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -497,11 +510,8 @@ ZEND_API int zend_is_true(zval *op TSRMLS_DC) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
#include "../TSRM/tsrm_strtok_r.h"
|
||||
|
||||
#define IS_VISITED_CONSTANT 0x80
|
||||
#define IS_CONSTANT_VISITED(p) (Z_TYPE_P(p) & IS_VISITED_CONSTANT)
|
||||
#define Z_REAL_TYPE_P(p) (Z_TYPE_P(p) & ~IS_VISITED_CONSTANT)
|
||||
#define MARK_CONSTANT_VISITED(p) Z_TYPE_INFO_P(p) |= IS_VISITED_CONSTANT
|
||||
|
||||
ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_class_entry *scope TSRMLS_DC) /* {{{ */
|
||||
@ -582,7 +592,6 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas
|
||||
if (inline_change) {
|
||||
STR_RELEASE(Z_STR_P(p));
|
||||
}
|
||||
//???!
|
||||
ZVAL_COPY_VALUE(p, const_value);
|
||||
if (Z_OPT_CONSTANT_P(p)) {
|
||||
zval_update_constant_ex(p, 1, NULL TSRMLS_CC);
|
||||
@ -651,13 +660,12 @@ int call_user_function_ex(HashTable *function_table, zval *object, zval *functio
|
||||
int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_uint i;
|
||||
zend_array *calling_symbol_table;
|
||||
zend_op_array *original_op_array;
|
||||
zend_op **original_opline_ptr;
|
||||
zend_class_entry *calling_scope = NULL;
|
||||
zend_class_entry *called_scope = NULL;
|
||||
zend_execute_data execute_data;
|
||||
zend_execute_data *call, dummy_execute_data;
|
||||
zend_fcall_info_cache fci_cache_local;
|
||||
zend_function *func;
|
||||
zend_object *orig_object;
|
||||
zend_class_entry *orig_scope;
|
||||
zval tmp;
|
||||
|
||||
ZVAL_UNDEF(fci->retval);
|
||||
@ -678,20 +686,28 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
break;
|
||||
}
|
||||
|
||||
orig_object = Z_OBJ(EG(This));
|
||||
orig_scope = EG(scope);
|
||||
|
||||
/* Initialize execute_data */
|
||||
if (EG(current_execute_data)) {
|
||||
execute_data = *EG(current_execute_data);
|
||||
EX(object) = Z_OBJ(EG(This));
|
||||
EX(scope) = EG(scope);
|
||||
EX(called_scope) = EG(called_scope);
|
||||
EX(op_array) = NULL;
|
||||
EX(opline) = NULL;
|
||||
} else {
|
||||
if (!EG(current_execute_data)) {
|
||||
/* This only happens when we're called outside any execute()'s
|
||||
* It shouldn't be strictly necessary to NULL execute_data out,
|
||||
* but it may make bugs easier to spot
|
||||
*/
|
||||
memset(&execute_data, 0, sizeof(zend_execute_data));
|
||||
memset(&dummy_execute_data, 0, sizeof(zend_execute_data));
|
||||
EG(current_execute_data) = &dummy_execute_data;
|
||||
} else if (EG(current_execute_data)->func &&
|
||||
ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
|
||||
EG(current_execute_data)->opline->opcode != ZEND_DO_FCALL) {
|
||||
/* Insert fake frame in case of include or magic calls */
|
||||
dummy_execute_data = *EG(current_execute_data);
|
||||
dummy_execute_data.prev_execute_data = EG(current_execute_data);
|
||||
dummy_execute_data.call = NULL;
|
||||
dummy_execute_data.prev_nested_call = NULL;
|
||||
dummy_execute_data.opline = NULL;
|
||||
dummy_execute_data.func = NULL;
|
||||
EG(current_execute_data) = &dummy_execute_data;
|
||||
}
|
||||
|
||||
if (!fci_cache || !fci_cache->initialized) {
|
||||
@ -710,6 +726,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
if (callable_name) {
|
||||
STR_RELEASE(callable_name);
|
||||
}
|
||||
if (EG(current_execute_data) == &dummy_execute_data) {
|
||||
EG(current_execute_data) = dummy_execute_data.prev_execute_data;
|
||||
}
|
||||
return FAILURE;
|
||||
} else if (error) {
|
||||
/* Capitalize the first latter of the error message */
|
||||
@ -722,34 +741,35 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
STR_RELEASE(callable_name);
|
||||
}
|
||||
|
||||
EX(function_state).function = fci_cache->function_handler;
|
||||
func = fci_cache->function_handler;
|
||||
call = zend_vm_stack_push_call_frame(func, fci->param_count, 0, fci_cache->called_scope, fci_cache->object, NULL TSRMLS_CC);
|
||||
calling_scope = fci_cache->calling_scope;
|
||||
called_scope = fci_cache->called_scope;
|
||||
fci->object = fci_cache->object;
|
||||
if (fci->object &&
|
||||
(!EG(objects_store).object_buckets ||
|
||||
!IS_OBJ_VALID(EG(objects_store).object_buckets[fci->object->handle]))) {
|
||||
if (EG(current_execute_data) == &dummy_execute_data) {
|
||||
EG(current_execute_data) = dummy_execute_data.prev_execute_data;
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (EX(function_state).function->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) {
|
||||
if (EX(function_state).function->common.fn_flags & ZEND_ACC_ABSTRACT) {
|
||||
zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EX(function_state).function->common.scope->name->val, EX(function_state).function->common.function_name->val);
|
||||
if (func->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) {
|
||||
if (func->common.fn_flags & ZEND_ACC_ABSTRACT) {
|
||||
zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", func->common.scope->name->val, func->common.function_name->val);
|
||||
}
|
||||
if (EX(function_state).function->common.fn_flags & ZEND_ACC_DEPRECATED) {
|
||||
if (func->common.fn_flags & ZEND_ACC_DEPRECATED) {
|
||||
zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
|
||||
EX(function_state).function->common.scope ? EX(function_state).function->common.scope->name->val : "",
|
||||
EX(function_state).function->common.scope ? "::" : "",
|
||||
EX(function_state).function->common.function_name->val);
|
||||
func->common.scope ? func->common.scope->name->val : "",
|
||||
func->common.scope ? "::" : "",
|
||||
func->common.function_name->val);
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_VM_STACK_GROW_IF_NEEDED(fci->param_count + 1);
|
||||
|
||||
for (i=0; i<fci->param_count; i++) {
|
||||
zval *param;
|
||||
|
||||
if (ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i + 1)) {
|
||||
if (ARG_SHOULD_BE_SENT_BY_REF(func, i + 1)) {
|
||||
// TODO: Scalar values don't have reference counters anymore.
|
||||
// They are assumed to be 1, and they may be easily passed by
|
||||
// reference now. However, previously scalars with refcount==1
|
||||
@ -769,19 +789,22 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
(!Z_ISREF(fci->params[i]) && Z_REFCOUNT(fci->params[i]) > 1)) {
|
||||
|
||||
if (fci->no_separation &&
|
||||
!ARG_MAY_BE_SENT_BY_REF(EX(function_state).function, i + 1)) {
|
||||
if (i || UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (EG(argument_stack)->top))) {
|
||||
!ARG_MAY_BE_SENT_BY_REF(func, i + 1)) {
|
||||
if (i) {
|
||||
/* hack to clean up the stack */
|
||||
ZVAL_LONG(&tmp, i);
|
||||
zend_vm_stack_push(&tmp TSRMLS_CC);
|
||||
zend_vm_stack_clear_multiple(0 TSRMLS_CC);
|
||||
call->num_args = i;
|
||||
zend_vm_stack_free_args(call TSRMLS_CC);
|
||||
}
|
||||
zend_vm_stack_free_call_frame(call TSRMLS_CC);
|
||||
|
||||
zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
|
||||
i+1,
|
||||
EX(function_state).function->common.scope ? EX(function_state).function->common.scope->name->val : "",
|
||||
EX(function_state).function->common.scope ? "::" : "",
|
||||
EX(function_state).function->common.function_name->val);
|
||||
func->common.scope ? func->common.scope->name->val : "",
|
||||
func->common.scope ? "::" : "",
|
||||
func->common.function_name->val);
|
||||
if (EG(current_execute_data) == &dummy_execute_data) {
|
||||
EG(current_execute_data) = dummy_execute_data.prev_execute_data;
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
@ -797,72 +820,56 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
} else if (Z_REFCOUNTED(fci->params[i])) {
|
||||
Z_ADDREF(fci->params[i]);
|
||||
}
|
||||
param = &fci->params[i];
|
||||
param = ZEND_CALL_ARG(call, i+1);
|
||||
ZVAL_COPY_VALUE(param, &fci->params[i]);
|
||||
} else if (Z_ISREF(fci->params[i]) &&
|
||||
/* don't separate references for __call */
|
||||
(EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0 ) {
|
||||
param = &tmp;
|
||||
(func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0 ) {
|
||||
param = ZEND_CALL_ARG(call, i+1);
|
||||
ZVAL_DUP(param, Z_REFVAL(fci->params[i]));
|
||||
} else {
|
||||
param = &tmp;
|
||||
param = ZEND_CALL_ARG(call, i+1);
|
||||
ZVAL_COPY(param, &fci->params[i]);
|
||||
}
|
||||
zend_vm_stack_push(param TSRMLS_CC);
|
||||
}
|
||||
|
||||
EX(function_state).arguments = zend_vm_stack_top_inc(TSRMLS_C);
|
||||
ZVAL_LONG(EX(function_state).arguments, fci->param_count);
|
||||
call->num_args = fci->param_count;
|
||||
|
||||
EG(scope) = calling_scope;
|
||||
EG(called_scope) = called_scope;
|
||||
if (!fci->object ||
|
||||
(EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) {
|
||||
Z_OBJ(EG(This)) = NULL;
|
||||
(func->common.fn_flags & ZEND_ACC_STATIC)) {
|
||||
Z_OBJ(EG(This)) = call->object = NULL;
|
||||
} else {
|
||||
Z_OBJ(EG(This)) = fci->object;
|
||||
Z_ADDREF(EG(This));
|
||||
}
|
||||
|
||||
EX(prev_execute_data) = EG(current_execute_data);
|
||||
EG(current_execute_data) = &execute_data;
|
||||
|
||||
if (EX(function_state).function->type == ZEND_USER_FUNCTION) {
|
||||
calling_symbol_table = EG(active_symbol_table);
|
||||
EG(scope) = EX(function_state).function->common.scope;
|
||||
if (fci->symbol_table) {
|
||||
EG(active_symbol_table) = fci->symbol_table;
|
||||
if (func->type == ZEND_USER_FUNCTION) {
|
||||
EG(scope) = func->common.scope;
|
||||
call->symbol_table = fci->symbol_table;
|
||||
if (EXPECTED((func->op_array.fn_flags & ZEND_ACC_GENERATOR) == 0)) {
|
||||
zend_init_execute_data(call, &func->op_array, fci->retval, VM_FRAME_TOP_FUNCTION TSRMLS_CC);
|
||||
zend_execute_ex(call TSRMLS_CC);
|
||||
} else {
|
||||
EG(active_symbol_table) = NULL;
|
||||
zend_generator_create_zval(call, &func->op_array, fci->retval TSRMLS_CC);
|
||||
}
|
||||
|
||||
original_op_array = EG(active_op_array);
|
||||
EG(active_op_array) = (zend_op_array *) EX(function_state).function;
|
||||
original_opline_ptr = EG(opline_ptr);
|
||||
|
||||
if (EXPECTED((EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) == 0)) {
|
||||
zend_execute(EG(active_op_array), fci->retval TSRMLS_CC);
|
||||
} else {
|
||||
zend_generator_create_zval(EG(active_op_array), fci->retval TSRMLS_CC);
|
||||
}
|
||||
|
||||
EG(active_op_array) = original_op_array;
|
||||
EG(opline_ptr) = original_opline_ptr;
|
||||
if (!fci->symbol_table && EG(active_symbol_table)) {
|
||||
zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
|
||||
}
|
||||
EG(active_symbol_table) = calling_symbol_table;
|
||||
} else if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) {
|
||||
int call_via_handler = (EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
|
||||
} else if (func->type == ZEND_INTERNAL_FUNCTION) {
|
||||
int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
|
||||
ZVAL_NULL(fci->retval);
|
||||
if (EX(function_state).function->common.scope) {
|
||||
EG(scope) = EX(function_state).function->common.scope;
|
||||
if (func->common.scope) {
|
||||
EG(scope) = func->common.scope;
|
||||
}
|
||||
call->prev_execute_data = EG(current_execute_data);
|
||||
EG(current_execute_data) = call;
|
||||
if (EXPECTED(zend_execute_internal == NULL)) {
|
||||
/* saves one function call if zend_execute_internal is not used */
|
||||
EX(function_state).function->internal_function.handler(fci->param_count, fci->retval TSRMLS_CC);
|
||||
func->internal_function.handler(fci->param_count, fci->retval TSRMLS_CC);
|
||||
} else {
|
||||
zend_execute_internal(&execute_data, fci TSRMLS_CC);
|
||||
zend_execute_internal(call, fci->retval TSRMLS_CC);
|
||||
}
|
||||
EG(current_execute_data) = call->prev_execute_data;
|
||||
zend_vm_stack_free_args(call TSRMLS_CC);
|
||||
zend_vm_stack_free_call_frame(call TSRMLS_CC);
|
||||
|
||||
/* We shouldn't fix bad extensions here,
|
||||
because it can break proper ones (Bug #34045)
|
||||
if (!EX(function_state).function->common.return_reference)
|
||||
@ -883,31 +890,37 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
|
||||
/* Not sure what should be done here if it's a static method */
|
||||
if (fci->object) {
|
||||
fci->object->handlers->call_method(EX(function_state).function->common.function_name, fci->object, fci->param_count, fci->retval TSRMLS_CC);
|
||||
call->prev_execute_data = EG(current_execute_data);
|
||||
EG(current_execute_data) = call;
|
||||
fci->object->handlers->call_method(func->common.function_name, fci->object, fci->param_count, fci->retval TSRMLS_CC);
|
||||
EG(current_execute_data) = call->prev_execute_data;
|
||||
} else {
|
||||
zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
|
||||
}
|
||||
|
||||
if (EX(function_state).function->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
|
||||
efree((char*)EX(function_state).function->common.function_name);
|
||||
zend_vm_stack_free_args(call TSRMLS_CC);
|
||||
zend_vm_stack_free_call_frame(call TSRMLS_CC);
|
||||
|
||||
if (func->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
|
||||
STR_RELEASE(func->common.function_name);
|
||||
}
|
||||
efree(EX(function_state).function);
|
||||
efree(func);
|
||||
|
||||
if (EG(exception)) {
|
||||
zval_ptr_dtor(fci->retval);
|
||||
ZVAL_UNDEF(fci->retval);
|
||||
}
|
||||
}
|
||||
zend_vm_stack_clear_multiple(0 TSRMLS_CC);
|
||||
|
||||
if (Z_OBJ(EG(This))) {
|
||||
zval_ptr_dtor(&EG(This));
|
||||
}
|
||||
|
||||
Z_OBJ(EG(This)) = EX(object);
|
||||
EG(scope) = EX(scope);
|
||||
EG(called_scope) = EX(called_scope);
|
||||
EG(current_execute_data) = EX(prev_execute_data);
|
||||
Z_OBJ(EG(This)) = orig_object;
|
||||
EG(scope) = orig_scope;
|
||||
if (EG(current_execute_data) == &dummy_execute_data) {
|
||||
EG(current_execute_data) = dummy_execute_data.prev_execute_data;
|
||||
}
|
||||
|
||||
if (EG(exception)) {
|
||||
zend_throw_exception_internal(NULL TSRMLS_CC);
|
||||
@ -1048,7 +1061,6 @@ ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *s
|
||||
{
|
||||
zval pv;
|
||||
zend_op_array *new_op_array;
|
||||
zend_op_array *original_active_op_array = EG(active_op_array);
|
||||
zend_uint original_compiler_options;
|
||||
int retval;
|
||||
|
||||
@ -1071,14 +1083,9 @@ ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *s
|
||||
|
||||
if (new_op_array) {
|
||||
zval local_retval;
|
||||
zend_op **original_opline_ptr = EG(opline_ptr);
|
||||
int orig_interactive = CG(interactive);
|
||||
|
||||
EG(active_op_array) = new_op_array;
|
||||
EG(no_extensions)=1;
|
||||
if (!EG(active_symbol_table)) {
|
||||
zend_rebuild_symbol_table(TSRMLS_C);
|
||||
}
|
||||
EG(no_extensions)=1;
|
||||
CG(interactive) = 0;
|
||||
|
||||
zend_try {
|
||||
@ -1104,8 +1111,6 @@ ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *s
|
||||
}
|
||||
|
||||
EG(no_extensions)=0;
|
||||
EG(opline_ptr) = original_opline_ptr;
|
||||
EG(active_op_array) = original_active_op_array;
|
||||
destroy_op_array(new_op_array TSRMLS_CC);
|
||||
efree(new_op_array);
|
||||
retval = SUCCESS;
|
||||
@ -1194,6 +1199,9 @@ void execute_new_code(TSRMLS_D) /* {{{ */
|
||||
case ZEND_JMPNZ_EX:
|
||||
case ZEND_JMP_SET:
|
||||
case ZEND_JMP_SET_VAR:
|
||||
case ZEND_NEW:
|
||||
case ZEND_FE_RESET:
|
||||
case ZEND_FE_FETCH:
|
||||
opline->op2.jmp_addr = &CG(active_op_array)->opcodes[opline->op2.opline_num];
|
||||
break;
|
||||
}
|
||||
@ -1203,7 +1211,6 @@ void execute_new_code(TSRMLS_D) /* {{{ */
|
||||
|
||||
zend_release_labels(1 TSRMLS_CC);
|
||||
|
||||
EG(active_op_array) = CG(active_op_array);
|
||||
orig_interactive = CG(interactive);
|
||||
CG(interactive) = 0;
|
||||
zend_execute(CG(active_op_array), NULL TSRMLS_CC);
|
||||
@ -1455,10 +1462,10 @@ check_fetch_type:
|
||||
}
|
||||
return EG(scope)->parent;
|
||||
case ZEND_FETCH_CLASS_STATIC:
|
||||
if (!EG(called_scope)) {
|
||||
if (!EG(current_execute_data) || !EG(current_execute_data)->called_scope) {
|
||||
zend_error(E_ERROR, "Cannot access static:: when no class scope is active");
|
||||
}
|
||||
return EG(called_scope);
|
||||
return EG(current_execute_data)->called_scope;
|
||||
case ZEND_FETCH_CLASS_AUTO: {
|
||||
fetch_type = zend_get_class_fetch_type(class_name->val, class_name->len);
|
||||
if (fetch_type!=ZEND_FETCH_CLASS_DEFAULT) {
|
||||
@ -1523,11 +1530,8 @@ typedef struct _zend_abstract_info {
|
||||
int ctor;
|
||||
} zend_abstract_info;
|
||||
|
||||
static int zend_verify_abstract_class_function(zval *zv, void *arg TSRMLS_DC) /* {{{ */
|
||||
static void zend_verify_abstract_class_function(zend_function *fn, zend_abstract_info *ai TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_function *fn = (zend_function *)Z_PTR_P(zv);
|
||||
zend_abstract_info *ai = (zend_abstract_info *)arg;
|
||||
|
||||
if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
|
||||
if (ai->cnt < MAX_ABSTRACT_INFO_CNT) {
|
||||
ai->afn[ai->cnt] = fn;
|
||||
@ -1543,18 +1547,20 @@ static int zend_verify_abstract_class_function(zval *zv, void *arg TSRMLS_DC) /*
|
||||
ai->cnt++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_function *func;
|
||||
zend_abstract_info ai;
|
||||
|
||||
if ((ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) && !(ce->ce_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
|
||||
memset(&ai, 0, sizeof(ai));
|
||||
|
||||
zend_hash_apply_with_argument(&ce->function_table, zend_verify_abstract_class_function, &ai TSRMLS_CC);
|
||||
ZEND_HASH_FOREACH_PTR(&ce->function_table, func) {
|
||||
zend_verify_abstract_class_function(func, &ai TSRMLS_CC);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
if (ai.cnt) {
|
||||
zend_error(E_ERROR, "Class %s contains %d abstract method%s and must therefore be declared abstract or implement the remaining methods (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")",
|
||||
@ -1575,51 +1581,49 @@ ZEND_API int zend_delete_global_variable(zend_string *name TSRMLS_DC) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
|
||||
ZEND_API zend_array *zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
zend_uint i;
|
||||
zend_execute_data *ex;
|
||||
zend_array *symbol_table;
|
||||
|
||||
if (!EG(active_symbol_table)) {
|
||||
|
||||
/* Search for last called user function */
|
||||
ex = EG(current_execute_data);
|
||||
while (ex && !ex->op_array) {
|
||||
ex = ex->prev_execute_data;
|
||||
}
|
||||
if (ex && ex->symbol_table) {
|
||||
EG(active_symbol_table) = ex->symbol_table;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ex && ex->op_array) {
|
||||
if (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
|
||||
/*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/
|
||||
EG(active_symbol_table) = *(EG(symtable_cache_ptr)--);
|
||||
} else {
|
||||
EG(active_symbol_table) = emalloc(sizeof(zend_array));
|
||||
GC_REFCOUNT(EG(active_symbol_table)) = 0;
|
||||
GC_TYPE_INFO(EG(active_symbol_table)) = IS_ARRAY;
|
||||
zend_hash_init(&EG(active_symbol_table)->ht, ex->op_array->last_var, NULL, ZVAL_PTR_DTOR, 0);
|
||||
/*printf("Cache miss! Initialized %x\n", EG(active_symbol_table));*/
|
||||
}
|
||||
ex->symbol_table = EG(active_symbol_table);
|
||||
for (i = 0; i < ex->op_array->last_var; i++) {
|
||||
zval zv;
|
||||
|
||||
ZVAL_INDIRECT(&zv, EX_VAR_NUM_2(ex, i));
|
||||
zend_hash_add_new(&EG(active_symbol_table)->ht,
|
||||
ex->op_array->vars[i], &zv);
|
||||
}
|
||||
}
|
||||
/* Search for last called user function */
|
||||
ex = EG(current_execute_data);
|
||||
while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->common.type))) {
|
||||
ex = ex->prev_execute_data;
|
||||
}
|
||||
if (!ex) {
|
||||
return NULL;
|
||||
}
|
||||
if (ex->symbol_table) {
|
||||
return ex->symbol_table;
|
||||
}
|
||||
|
||||
if (EG(symtable_cache_ptr) >= EG(symtable_cache)) {
|
||||
/*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/
|
||||
symbol_table = ex->symbol_table = *(EG(symtable_cache_ptr)--);
|
||||
} else {
|
||||
symbol_table = ex->symbol_table = emalloc(sizeof(zend_array));
|
||||
GC_REFCOUNT(symbol_table) = 0;
|
||||
GC_TYPE_INFO(symbol_table) = IS_ARRAY;
|
||||
zend_hash_init(&symbol_table->ht, ex->func->op_array.last_var, NULL, ZVAL_PTR_DTOR, 0);
|
||||
/*printf("Cache miss! Initialized %x\n", EG(active_symbol_table));*/
|
||||
}
|
||||
for (i = 0; i < ex->func->op_array.last_var; i++) {
|
||||
zval zv;
|
||||
|
||||
ZVAL_INDIRECT(&zv, EX_VAR_NUM_2(ex, i));
|
||||
zend_hash_add_new(&symbol_table->ht,
|
||||
ex->func->op_array.vars[i], &zv);
|
||||
}
|
||||
return symbol_table;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ */
|
||||
{
|
||||
int i;
|
||||
zend_op_array *op_array = execute_data->op_array;
|
||||
zend_op_array *op_array = &execute_data->func->op_array;
|
||||
HashTable *ht = &execute_data->symbol_table->ht;
|
||||
|
||||
/* copy real values from symbol table into CV slots and create
|
||||
@ -1650,7 +1654,7 @@ ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ *
|
||||
ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data) /* {{{ */
|
||||
{
|
||||
int i;
|
||||
zend_op_array *op_array = execute_data->op_array;
|
||||
zend_op_array *op_array = &execute_data->func->op_array;
|
||||
HashTable *ht = &execute_data->symbol_table->ht;
|
||||
|
||||
/* copy real values from CV slots into symbol table */
|
||||
@ -1667,13 +1671,18 @@ ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data) /* {{{ *
|
||||
|
||||
ZEND_API int zend_set_local_var(zend_string *name, zval *value, int force TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
if (!EG(active_symbol_table)) {
|
||||
int i;
|
||||
zend_execute_data *execute_data = EG(current_execute_data);
|
||||
zend_op_array *op_array = execute_data->op_array;
|
||||
zend_ulong h = STR_HASH_VAL(name);
|
||||
zend_execute_data *execute_data = EG(current_execute_data);
|
||||
|
||||
while (execute_data && (!execute_data->func || !ZEND_USER_CODE(execute_data->func->common.type))) {
|
||||
execute_data = execute_data->prev_execute_data;
|
||||
}
|
||||
|
||||
if (execute_data) {
|
||||
if (!execute_data->symbol_table) {
|
||||
zend_ulong h = STR_HASH_VAL(name);
|
||||
zend_op_array *op_array = &execute_data->func->op_array;
|
||||
int i;
|
||||
|
||||
if (op_array) {
|
||||
for (i = 0; i < op_array->last_var; i++) {
|
||||
if (op_array->vars[i]->h == h &&
|
||||
op_array->vars[i]->len == name->len &&
|
||||
@ -1682,31 +1691,34 @@ ZEND_API int zend_set_local_var(zend_string *name, zval *value, int force TSRMLS
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (force) {
|
||||
zend_rebuild_symbol_table(TSRMLS_C);
|
||||
if (EG(active_symbol_table)) {
|
||||
zend_hash_update(&EG(active_symbol_table)->ht, name, value);
|
||||
if (force) {
|
||||
zend_array *symbol_table = zend_rebuild_symbol_table(TSRMLS_C);
|
||||
if (symbol_table) {
|
||||
return zend_hash_update(&symbol_table->ht, name, value) ? SUCCESS : FAILURE;;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return FAILURE;
|
||||
return (zend_hash_update_ind(&execute_data->symbol_table->ht, name, value) != NULL) ? SUCCESS : FAILURE;
|
||||
}
|
||||
} else {
|
||||
return (zend_hash_update_ind(&EG(active_symbol_table)->ht, name, value) != NULL) ? SUCCESS : FAILURE;
|
||||
}
|
||||
return SUCCESS;
|
||||
return FAILURE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API int zend_set_local_var_str(const char *name, int len, zval *value, int force TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
if (!EG(active_symbol_table)) {
|
||||
int i;
|
||||
zend_execute_data *execute_data = EG(current_execute_data);
|
||||
zend_op_array *op_array = execute_data->op_array;
|
||||
zend_ulong h = zend_hash_func(name, len);
|
||||
zend_execute_data *execute_data = EG(current_execute_data);
|
||||
|
||||
while (execute_data && (!execute_data->func || !ZEND_USER_CODE(execute_data->func->common.type))) {
|
||||
execute_data = execute_data->prev_execute_data;
|
||||
}
|
||||
|
||||
if (execute_data) {
|
||||
if (!execute_data->symbol_table) {
|
||||
zend_ulong h = zend_hash_func(name, len);
|
||||
zend_op_array *op_array = &execute_data->func->op_array;
|
||||
int i;
|
||||
|
||||
if (op_array) {
|
||||
for (i = 0; i < op_array->last_var; i++) {
|
||||
if (op_array->vars[i]->h == h &&
|
||||
op_array->vars[i]->len == len &&
|
||||
@ -1715,19 +1727,18 @@ ZEND_API int zend_set_local_var_str(const char *name, int len, zval *value, int
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (force) {
|
||||
zend_rebuild_symbol_table(TSRMLS_C);
|
||||
if (EG(active_symbol_table)) {
|
||||
zend_hash_str_update(&EG(active_symbol_table)->ht, name, len, value);
|
||||
|
||||
if (force) {
|
||||
zend_array *symbol_table = zend_rebuild_symbol_table(TSRMLS_C);
|
||||
if (symbol_table) {
|
||||
return zend_hash_str_update(&symbol_table->ht, name, len, value) ? SUCCESS : FAILURE;;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return FAILURE;
|
||||
return (zend_hash_str_update_ind(&execute_data->symbol_table->ht, name, len, value) != NULL) ? SUCCESS : FAILURE;
|
||||
}
|
||||
} else {
|
||||
return (zend_hash_str_update_ind(&EG(active_symbol_table)->ht, name, len, value) != NULL) ? SUCCESS : FAILURE;
|
||||
}
|
||||
return SUCCESS;
|
||||
return FAILURE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -32,7 +32,7 @@ static zend_object *zend_generator_create(zend_class_entry *class_type TSRMLS_DC
|
||||
static void zend_generator_cleanup_unfinished_execution(zend_generator *generator TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_execute_data *execute_data = generator->execute_data;
|
||||
zend_op_array *op_array = execute_data->op_array;
|
||||
zend_op_array *op_array = &execute_data->func->op_array;
|
||||
|
||||
if (generator->send_target) {
|
||||
if (Z_REFCOUNTED_P(generator->send_target)) Z_DELREF_P(generator->send_target);
|
||||
@ -75,23 +75,13 @@ static void zend_generator_cleanup_unfinished_execution(zend_generator *generato
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear any backed up stack arguments */
|
||||
{
|
||||
zval *ptr = generator->stack->top - 1;
|
||||
zval *end = zend_vm_stack_frame_base(execute_data);
|
||||
|
||||
for (; ptr >= end; --ptr) {
|
||||
zval_ptr_dtor((zval*) ptr);
|
||||
}
|
||||
}
|
||||
|
||||
/* If yield was used as a function argument there may be active
|
||||
* method calls those objects need to be freed */
|
||||
while (execute_data->call >= execute_data->call_slots) {
|
||||
while (execute_data->call) {
|
||||
if (execute_data->call->object) {
|
||||
OBJ_RELEASE(execute_data->call->object);
|
||||
}
|
||||
execute_data->call--;
|
||||
execute_data->call = execute_data->call->prev_nested_call;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
@ -110,7 +100,7 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
|
||||
|
||||
if (generator->execute_data) {
|
||||
zend_execute_data *execute_data = generator->execute_data;
|
||||
zend_op_array *op_array = execute_data->op_array;
|
||||
zend_op_array *op_array = &execute_data->func->op_array;
|
||||
|
||||
if (!execute_data->symbol_table) {
|
||||
zend_free_compiled_variables(execute_data TSRMLS_CC);
|
||||
@ -125,26 +115,11 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
|
||||
/* A fatal error / die occurred during the generator execution. Trying to clean
|
||||
* up the stack may not be safe in this case. */
|
||||
if (CG(unclean_shutdown)) {
|
||||
generator->execute_data = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* We have added an additional stack frame in prev_execute_data, so we
|
||||
* have to free it. It also contains the arguments passed to the
|
||||
* generator (for func_get_args) so those have to be freed too. */
|
||||
{
|
||||
zend_execute_data *prev_execute_data = execute_data->prev_execute_data;
|
||||
zval *arguments = prev_execute_data->function_state.arguments;
|
||||
|
||||
if (arguments) {
|
||||
int arguments_count = Z_LVAL_P(arguments);
|
||||
zval *arguments_start = arguments - arguments_count;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < arguments_count; ++i) {
|
||||
zval_ptr_dtor(arguments_start + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
zend_vm_stack_free_extra_args(generator->execute_data TSRMLS_CC);
|
||||
|
||||
/* Some cleanups are only necessary if the generator was closued
|
||||
* before it could finish execution (reach a return statement). */
|
||||
@ -171,18 +146,18 @@ static void zend_generator_dtor_storage(zend_object *object TSRMLS_DC) /* {{{ */
|
||||
zend_uint op_num, finally_op_num;
|
||||
int i;
|
||||
|
||||
if (!ex || !ex->op_array->has_finally_block) {
|
||||
if (!ex || !ex->func->op_array.has_finally_block) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* -1 required because we want the last run opcode, not the
|
||||
* next to-be-run one. */
|
||||
op_num = ex->opline - ex->op_array->opcodes - 1;
|
||||
op_num = ex->opline - ex->func->op_array.opcodes - 1;
|
||||
|
||||
/* Find next finally block */
|
||||
finally_op_num = 0;
|
||||
for (i = 0; i < ex->op_array->last_try_catch; i++) {
|
||||
zend_try_catch_element *try_catch = &ex->op_array->try_catch_array[i];
|
||||
for (i = 0; i < ex->func->op_array.last_try_catch; i++) {
|
||||
zend_try_catch_element *try_catch = &ex->func->op_array.try_catch_array[i];
|
||||
|
||||
if (op_num < try_catch->try_op) {
|
||||
break;
|
||||
@ -196,7 +171,7 @@ static void zend_generator_dtor_storage(zend_object *object TSRMLS_DC) /* {{{ */
|
||||
/* If a finally block was found we jump directly to it and
|
||||
* resume the generator. */
|
||||
if (finally_op_num) {
|
||||
ex->opline = &ex->op_array->opcodes[finally_op_num];
|
||||
ex->opline = &ex->func->op_array.opcodes[finally_op_num];
|
||||
ex->fast_ret = NULL;
|
||||
generator->flags |= ZEND_GENERATOR_FORCED_CLOSE;
|
||||
zend_generator_resume(generator TSRMLS_CC);
|
||||
@ -239,21 +214,18 @@ static int copy_closure_static_var(zval *var TSRMLS_DC, int num_args, va_list ar
|
||||
{
|
||||
HashTable *target = va_arg(args, HashTable *);
|
||||
|
||||
SEPARATE_ZVAL_TO_MAKE_IS_REF(var);
|
||||
ZVAL_MAKE_REF(var);
|
||||
Z_ADDREF_P(var);
|
||||
zend_hash_update(target, key->key, var);
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* Requires globals EG(scope), EG(current_scope), EG(This),
|
||||
* EG(active_symbol_table) and EG(current_execute_data). */
|
||||
ZEND_API void zend_generator_create_zval(zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */
|
||||
/* Requires globals EG(scope), EG(This) and EG(current_execute_data). */
|
||||
ZEND_API void zend_generator_create_zval(zend_execute_data *call, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_generator *generator;
|
||||
zend_execute_data *current_execute_data;
|
||||
zend_op **opline_ptr;
|
||||
zend_array *current_symbol_table;
|
||||
zend_execute_data *execute_data;
|
||||
zend_vm_stack current_stack = EG(argument_stack);
|
||||
|
||||
@ -282,16 +254,10 @@ ZEND_API void zend_generator_create_zval(zend_op_array *op_array, zval *return_v
|
||||
}
|
||||
|
||||
/* Create new execution context. We have to back up and restore
|
||||
* EG(current_execute_data), EG(opline_ptr) and EG(active_symbol_table)
|
||||
* here because the function modifies or uses them */
|
||||
* EG(current_execute_data) here. */
|
||||
current_execute_data = EG(current_execute_data);
|
||||
opline_ptr = EG(opline_ptr);
|
||||
current_symbol_table = EG(active_symbol_table);
|
||||
EG(active_symbol_table) = NULL;
|
||||
execute_data = zend_create_execute_data_from_op_array(op_array, return_value, VM_FRAME_TOP_FUNCTION TSRMLS_CC);
|
||||
EG(active_symbol_table) = current_symbol_table;
|
||||
execute_data = zend_create_generator_execute_data(call, op_array, return_value TSRMLS_CC);
|
||||
EG(current_execute_data) = current_execute_data;
|
||||
EG(opline_ptr) = opline_ptr;
|
||||
|
||||
object_init_ex(return_value, zend_ce_generator);
|
||||
|
||||
@ -300,8 +266,8 @@ ZEND_API void zend_generator_create_zval(zend_op_array *op_array, zval *return_v
|
||||
}
|
||||
|
||||
/* Save execution context in generator object. */
|
||||
execute_data->prev_execute_data->object = Z_OBJ_P(return_value);
|
||||
generator = (zend_generator *) Z_OBJ_P(return_value);
|
||||
execute_data->prev_execute_data = NULL;
|
||||
generator->execute_data = execute_data;
|
||||
generator->stack = EG(argument_stack);
|
||||
EG(argument_stack) = current_stack;
|
||||
@ -336,47 +302,38 @@ ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{
|
||||
{
|
||||
/* Backup executor globals */
|
||||
zend_execute_data *original_execute_data = EG(current_execute_data);
|
||||
zend_op **original_opline_ptr = EG(opline_ptr);
|
||||
zend_op_array *original_active_op_array = EG(active_op_array);
|
||||
zend_array *original_active_symbol_table = EG(active_symbol_table);
|
||||
zend_object *original_This;
|
||||
zend_class_entry *original_scope = EG(scope);
|
||||
zend_class_entry *original_called_scope = EG(called_scope);
|
||||
zend_vm_stack original_stack = EG(argument_stack);
|
||||
|
||||
original_This = Z_OBJ(EG(This));
|
||||
|
||||
/* Set executor globals */
|
||||
EG(current_execute_data) = generator->execute_data;
|
||||
EG(opline_ptr) = &generator->execute_data->opline;
|
||||
EG(active_op_array) = generator->execute_data->op_array;
|
||||
EG(active_symbol_table) = generator->execute_data->symbol_table;
|
||||
Z_OBJ(EG(This)) = generator->execute_data->object;
|
||||
EG(scope) = generator->execute_data->scope;
|
||||
EG(called_scope) = generator->execute_data->called_scope;
|
||||
EG(argument_stack) = generator->stack;
|
||||
|
||||
/* We want the backtrace to look as if the generator function was
|
||||
* called from whatever method we are current running (e.g. next()).
|
||||
* The first prev_execute_data contains an additional stack frame,
|
||||
* which makes the generator function show up in the backtrace and
|
||||
* makes the arguments available to func_get_args(). So we have to
|
||||
* set the prev_execute_data of that prev_execute_data :) */
|
||||
generator->execute_data->prev_execute_data->prev_execute_data = original_execute_data;
|
||||
* So we have to link generator call frame with caller call frames */
|
||||
|
||||
generator->execute_data->prev_execute_data = original_execute_data;
|
||||
|
||||
/* Resume execution */
|
||||
generator->flags |= ZEND_GENERATOR_CURRENTLY_RUNNING;
|
||||
zend_execute_ex(generator->execute_data TSRMLS_CC);
|
||||
generator->flags &= ~ZEND_GENERATOR_CURRENTLY_RUNNING;
|
||||
|
||||
/* Unlink generator call_frame from the caller */
|
||||
if (generator->execute_data) {
|
||||
generator->execute_data->prev_execute_data = NULL;
|
||||
}
|
||||
|
||||
/* Restore executor globals */
|
||||
EG(current_execute_data) = original_execute_data;
|
||||
EG(opline_ptr) = original_opline_ptr;
|
||||
EG(active_op_array) = original_active_op_array;
|
||||
EG(active_symbol_table) = original_active_symbol_table;
|
||||
Z_OBJ(EG(This)) = original_This;
|
||||
EG(scope) = original_scope;
|
||||
EG(called_scope) = original_called_scope;
|
||||
EG(argument_stack) = original_stack;
|
||||
|
||||
/* If an exception was thrown in the generator we have to internally
|
||||
@ -670,7 +627,7 @@ zend_object_iterator *zend_generator_get_iterator(zend_class_entry *ce, zval *ob
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (by_ref && !(generator->execute_data->op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
|
||||
if (by_ref && !(generator->execute_data->func->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
|
||||
zend_throw_exception(NULL, "You can only iterate a generator by-reference if it declared that it yields by-reference", 0 TSRMLS_CC);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ static const zend_uchar ZEND_GENERATOR_FORCED_CLOSE = 0x2;
|
||||
static const zend_uchar ZEND_GENERATOR_AT_FIRST_YIELD = 0x4;
|
||||
|
||||
void zend_register_generator_ce(TSRMLS_D);
|
||||
ZEND_API void zend_generator_create_zval(zend_op_array *op_array, zval *return_value TSRMLS_DC);
|
||||
ZEND_API void zend_generator_create_zval(zend_execute_data *call, zend_op_array *op_array, zval *return_value TSRMLS_DC);
|
||||
ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished_execution TSRMLS_DC);
|
||||
ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC);
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "zend_modules.h"
|
||||
#include "zend_float.h"
|
||||
#include "zend_multibyte.h"
|
||||
#include "zend_arena.h"
|
||||
|
||||
/* Define ZTS if you want a thread-safe Zend */
|
||||
/*#undef ZTS*/
|
||||
@ -139,6 +140,8 @@ struct _zend_compiler_globals {
|
||||
zend_compiler_context context;
|
||||
zend_stack context_stack;
|
||||
|
||||
zend_arena *arena;
|
||||
|
||||
zend_string *empty_string;
|
||||
zend_string *one_char_string[256];
|
||||
|
||||
@ -166,9 +169,6 @@ struct _zend_executor_globals {
|
||||
zend_array **symtable_cache_limit;
|
||||
zend_array **symtable_cache_ptr;
|
||||
|
||||
zend_op **opline_ptr;
|
||||
|
||||
zend_array *active_symbol_table;
|
||||
zend_array symbol_table; /* main symbol table */
|
||||
|
||||
HashTable included_files; /* files already included */
|
||||
@ -179,14 +179,11 @@ struct _zend_executor_globals {
|
||||
int orig_error_reporting;
|
||||
int exit_status;
|
||||
|
||||
zend_op_array *active_op_array;
|
||||
|
||||
HashTable *function_table; /* function symbol table */
|
||||
HashTable *class_table; /* class table */
|
||||
HashTable *zend_constants; /* constants table */
|
||||
|
||||
zend_class_entry *scope;
|
||||
zend_class_entry *called_scope; /* Scope of the calling class */
|
||||
|
||||
zval This;
|
||||
|
||||
@ -194,7 +191,6 @@ struct _zend_executor_globals {
|
||||
|
||||
int ticks_count;
|
||||
|
||||
zend_bool in_execution;
|
||||
HashTable *in_autoload;
|
||||
zend_function *autoload_func;
|
||||
zend_bool full_tables_cleanup;
|
||||
@ -242,7 +238,8 @@ struct _zend_executor_globals {
|
||||
|
||||
zend_property_info std_property_info;
|
||||
|
||||
zend_bool active;
|
||||
zend_bool active;
|
||||
zend_bool valid_symbol_table;
|
||||
|
||||
zend_op *start_op;
|
||||
|
||||
|
@ -1207,7 +1207,7 @@ ZEND_API void zend_array_dup(HashTable *target, HashTable *source)
|
||||
q->key = NULL;
|
||||
if (Z_OPT_REFCOUNTED_P(data)) {
|
||||
if (Z_ISREF_P(data) && Z_REFCOUNT_P(data) == 1) {
|
||||
ZVAL_DUP(&q->val, Z_REFVAL_P(data));
|
||||
ZVAL_COPY(&q->val, Z_REFVAL_P(data));
|
||||
} else {
|
||||
ZVAL_COPY(&q->val, data);
|
||||
}
|
||||
@ -1256,7 +1256,7 @@ ZEND_API void zend_array_dup(HashTable *target, HashTable *source)
|
||||
target->arHash[nIndex] = target_idx;
|
||||
if (Z_OPT_REFCOUNTED_P(data)) {
|
||||
if (Z_ISREF_P(data) && Z_REFCOUNT_P(data) == 1) {
|
||||
ZVAL_DUP(&q->val, Z_REFVAL_P(data));
|
||||
ZVAL_COPY(&q->val, Z_REFVAL_P(data));
|
||||
} else {
|
||||
ZVAL_COPY(&q->val, data);
|
||||
}
|
||||
@ -1495,14 +1495,15 @@ ZEND_API int zend_hash_set_pointer(HashTable *ht, const HashPointer *ptr)
|
||||
} else if (ht->nInternalPointer != ptr->pos) {
|
||||
IS_CONSISTENT(ht);
|
||||
if (ht->u.flags & HASH_FLAG_PACKED) {
|
||||
if (Z_TYPE(ht->arData[ptr->h].val) != IS_UNDEF) {
|
||||
if (ptr->h < ht->nNumUsed &&
|
||||
Z_TYPE(ht->arData[ptr->h].val) != IS_UNDEF) {
|
||||
ht->nInternalPointer = ptr->h;
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
idx = ht->arHash[ptr->h & ht->nTableMask];
|
||||
while (idx != INVALID_IDX) {
|
||||
if (idx == ptr->pos) {
|
||||
if (ht->arData[idx].h == ptr->h && idx == ptr->pos) {
|
||||
ht->nInternalPointer = idx;
|
||||
return 1;
|
||||
}
|
||||
|
210
Zend/zend_hash.h
210
Zend/zend_hash.h
@ -235,46 +235,61 @@ END_EXTERN_C()
|
||||
#define ZEND_INIT_SYMTABLE_EX(ht, n, persistent) \
|
||||
zend_hash_init(ht, n, NULL, ZVAL_PTR_DTOR, persistent)
|
||||
|
||||
#define ZEND_HANDLE_NUMERIC_EX(key, length, idx, func) do { \
|
||||
register const char *tmp = key; \
|
||||
\
|
||||
if (*tmp == '-') { \
|
||||
tmp++; \
|
||||
} \
|
||||
if (*tmp >= '0' && *tmp <= '9') { /* possibly a numeric index */ \
|
||||
const char *end = key + length - 1; \
|
||||
\
|
||||
if ((*end != '\0') /* not a null terminated string */ \
|
||||
|| (*tmp == '0' && length > 2) /* numbers with leading zeros */ \
|
||||
|| (end - tmp > MAX_LENGTH_OF_LONG - 1) /* number too long */ \
|
||||
|| (SIZEOF_LONG == 4 && \
|
||||
end - tmp == MAX_LENGTH_OF_LONG - 1 && \
|
||||
*tmp > '2')) { /* overflow */ \
|
||||
break; \
|
||||
} \
|
||||
idx = (*tmp - '0'); \
|
||||
while (++tmp != end && *tmp >= '0' && *tmp <= '9') { \
|
||||
idx = (idx * 10) + (*tmp - '0'); \
|
||||
} \
|
||||
if (tmp == end) { \
|
||||
if (*key == '-') { \
|
||||
if (idx-1 > LONG_MAX) { /* overflow */ \
|
||||
break; \
|
||||
} \
|
||||
idx = 0 - idx; \
|
||||
} else if (idx > LONG_MAX) { /* overflow */ \
|
||||
break; \
|
||||
} \
|
||||
func; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
static inline int _zend_handle_numeric_str(const char *key, int length, ulong *idx)
|
||||
{
|
||||
register const char *tmp = key;
|
||||
const char *end;
|
||||
|
||||
#define ZEND_HANDLE_NUMERIC(key, length, func) do { \
|
||||
ulong idx; \
|
||||
\
|
||||
ZEND_HANDLE_NUMERIC_EX(key, length, idx, return func); \
|
||||
} while (0)
|
||||
if (*tmp > '9') {
|
||||
return 0;
|
||||
} else if (*tmp < '0') {
|
||||
if (*tmp != '-') {
|
||||
return 0;
|
||||
}
|
||||
tmp++;
|
||||
if (*tmp > '9' || *tmp < '0') {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* possibly a numeric index */
|
||||
end = key + length;
|
||||
|
||||
if ((*end != '\0') /* not a null terminated string */
|
||||
|| (*tmp == '0' && length > 1) /* numbers with leading zeros */
|
||||
|| (end - tmp > MAX_LENGTH_OF_LONG - 1) /* number too long */
|
||||
|| (SIZEOF_LONG == 4 &&
|
||||
end - tmp == MAX_LENGTH_OF_LONG - 1 &&
|
||||
*tmp > '2')) { /* overflow */
|
||||
return 0;
|
||||
}
|
||||
*idx = (*tmp - '0');
|
||||
while (1) {
|
||||
++tmp;
|
||||
if (tmp == end) {
|
||||
if (*key == '-') {
|
||||
if (*idx-1 > LONG_MAX) { /* overflow */
|
||||
return 0;
|
||||
}
|
||||
*idx = 0 - *idx;
|
||||
} else if (*idx > LONG_MAX) { /* overflow */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (*tmp <= '9' && *tmp >= '0') {
|
||||
*idx = (*idx * 10) + (*tmp - '0');
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define ZEND_HANDLE_NUMERIC_STR(key, length, idx) \
|
||||
_zend_handle_numeric_str(key, length, &idx)
|
||||
|
||||
#define ZEND_HANDLE_NUMERIC(key, idx) \
|
||||
_zend_handle_numeric_str((key)->val, (key)->len, &idx)
|
||||
|
||||
|
||||
static inline zval *zend_hash_find_ind(const HashTable *ht, zend_string *key)
|
||||
@ -307,92 +322,157 @@ static inline zval *zend_hash_str_find_ind(const HashTable *ht, const char *str,
|
||||
|
||||
static inline zval *zend_symtable_update(HashTable *ht, zend_string *key, zval *pData)
|
||||
{
|
||||
ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_update(ht, idx, pData));
|
||||
return zend_hash_update(ht, key, pData);
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(key, idx)) {
|
||||
return zend_hash_index_update(ht, idx, pData);
|
||||
} else {
|
||||
return zend_hash_update(ht, key, pData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline zval *zend_symtable_update_ind(HashTable *ht, zend_string *key, zval *pData)
|
||||
{
|
||||
ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_update(ht, idx, pData));
|
||||
return zend_hash_update_ind(ht, key, pData);
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(key, idx)) {
|
||||
return zend_hash_index_update(ht, idx, pData);
|
||||
} else {
|
||||
return zend_hash_update_ind(ht, key, pData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline int zend_symtable_del(HashTable *ht, zend_string *key)
|
||||
{
|
||||
ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_del(ht, idx));
|
||||
return zend_hash_del(ht, key);
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(key, idx)) {
|
||||
return zend_hash_index_del(ht, idx);
|
||||
} else {
|
||||
return zend_hash_del(ht, key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline int zend_symtable_del_ind(HashTable *ht, zend_string *key)
|
||||
{
|
||||
ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_del(ht, idx));
|
||||
return zend_hash_del_ind(ht, key);
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(key, idx)) {
|
||||
return zend_hash_index_del(ht, idx);
|
||||
} else {
|
||||
return zend_hash_del_ind(ht, key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline zval *zend_symtable_find(const HashTable *ht, zend_string *key)
|
||||
{
|
||||
ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_find(ht, idx));
|
||||
return zend_hash_find(ht, key);
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(key, idx)) {
|
||||
return zend_hash_index_find(ht, idx);
|
||||
} else {
|
||||
return zend_hash_find(ht, key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline zval *zend_symtable_find_ind(const HashTable *ht, zend_string *key)
|
||||
{
|
||||
ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_find(ht, idx));
|
||||
return zend_hash_find_ind(ht, key);
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(key, idx)) {
|
||||
return zend_hash_index_find(ht, idx);
|
||||
} else {
|
||||
return zend_hash_find_ind(ht, key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline int zend_symtable_exists(HashTable *ht, zend_string *key)
|
||||
{
|
||||
ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_exists(ht, idx));
|
||||
return zend_hash_exists(ht, key);
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(key, idx)) {
|
||||
return zend_hash_index_exists(ht, idx);
|
||||
} else {
|
||||
return zend_hash_exists(ht, key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline zval *zend_symtable_str_update(HashTable *ht, const char *str, int len, zval *pData)
|
||||
{
|
||||
ZEND_HANDLE_NUMERIC(str, len+1, zend_hash_index_update(ht, idx, pData));
|
||||
return zend_hash_str_update(ht, str, len, pData);
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
|
||||
return zend_hash_index_update(ht, idx, pData);
|
||||
} else {
|
||||
return zend_hash_str_update(ht, str, len, pData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline zval *zend_symtable_str_update_ind(HashTable *ht, const char *str, int len, zval *pData)
|
||||
{
|
||||
ZEND_HANDLE_NUMERIC(str, len+1, zend_hash_index_update(ht, idx, pData));
|
||||
return zend_hash_str_update_ind(ht, str, len, pData);
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
|
||||
return zend_hash_index_update(ht, idx, pData);
|
||||
} else {
|
||||
return zend_hash_str_update_ind(ht, str, len, pData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline int zend_symtable_str_del(HashTable *ht, const char *str, int len)
|
||||
{
|
||||
ZEND_HANDLE_NUMERIC(str, len+1, zend_hash_index_del(ht, idx));
|
||||
return zend_hash_str_del(ht, str, len);
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
|
||||
return zend_hash_index_del(ht, idx);
|
||||
} else {
|
||||
return zend_hash_str_del(ht, str, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline int zend_symtable_str_del_ind(HashTable *ht, const char *str, int len)
|
||||
{
|
||||
ZEND_HANDLE_NUMERIC(str, len+1, zend_hash_index_del(ht, idx));
|
||||
return zend_hash_str_del_ind(ht, str, len);
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
|
||||
return zend_hash_index_del(ht, idx);
|
||||
} else {
|
||||
return zend_hash_str_del_ind(ht, str, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline zval *zend_symtable_str_find(HashTable *ht, const char *str, int len)
|
||||
{
|
||||
ZEND_HANDLE_NUMERIC(str, len+1, zend_hash_index_find(ht, idx));
|
||||
return zend_hash_str_find(ht, str, len);
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
|
||||
return zend_hash_index_find(ht, idx);
|
||||
} else {
|
||||
return zend_hash_str_find(ht, str, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline int zend_symtable_str_exists(HashTable *ht, const char *str, int len)
|
||||
{
|
||||
ZEND_HANDLE_NUMERIC(str, len+1, zend_hash_index_exists(ht, idx));
|
||||
return zend_hash_str_exists(ht, str, len);
|
||||
ulong idx;
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC_STR(str, len, idx)) {
|
||||
return zend_hash_index_exists(ht, idx);
|
||||
} else {
|
||||
return zend_hash_str_exists(ht, str, len);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void *zend_hash_add_ptr(HashTable *ht, zend_string *key, void *pData)
|
||||
|
@ -90,11 +90,12 @@ ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_fun
|
||||
if (object) {
|
||||
fcic.called_scope = Z_OBJCE_P(object);
|
||||
} else if (obj_ce &&
|
||||
!(EG(called_scope) &&
|
||||
instanceof_function(EG(called_scope), obj_ce TSRMLS_CC))) {
|
||||
!(EG(current_execute_data) &&
|
||||
EG(current_execute_data)->called_scope &&
|
||||
instanceof_function(EG(current_execute_data)->called_scope, obj_ce TSRMLS_CC))) {
|
||||
fcic.called_scope = obj_ce;
|
||||
} else {
|
||||
fcic.called_scope = EG(called_scope);
|
||||
fcic.called_scope = EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL;
|
||||
}
|
||||
fcic.object = object ? Z_OBJ_P(object) : NULL;
|
||||
result = zend_call_function(&fci, &fcic TSRMLS_CC);
|
||||
|
@ -75,7 +75,7 @@ ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
|
||||
zend_class_entry *ce = zobj->ce;
|
||||
|
||||
ALLOC_HASHTABLE(zobj->properties);
|
||||
zend_hash_init(zobj->properties, 8, NULL, ZVAL_PTR_DTOR, 0);
|
||||
zend_hash_init(zobj->properties, ce->default_properties_count, NULL, ZVAL_PTR_DTOR, 0);
|
||||
if (ce->default_properties_count) {
|
||||
ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
|
||||
if (/*prop_info->ce == ce &&*/
|
||||
@ -85,7 +85,7 @@ ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
|
||||
zval zv;
|
||||
|
||||
ZVAL_INDIRECT(&zv, &zobj->properties_table[prop_info->offset]);
|
||||
zend_hash_add(zobj->properties, prop_info->name, &zv);
|
||||
zend_hash_add_new(zobj->properties, prop_info->name, &zv);
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
while (ce->parent && ce->parent->default_properties_count) {
|
||||
@ -150,7 +150,12 @@ ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC
|
||||
|
||||
zend_call_method_with_0_params(object, ce, &ce->__debugInfo, ZEND_DEBUGINFO_FUNC_NAME, &retval);
|
||||
if (Z_TYPE(retval) == IS_ARRAY) {
|
||||
if (Z_REFCOUNT(retval) <= 1) {
|
||||
if (Z_IMMUTABLE(retval)) {
|
||||
*is_temp = 1;
|
||||
ALLOC_HASHTABLE(ht);
|
||||
zend_array_dup(ht, Z_ARRVAL(retval));
|
||||
return ht;
|
||||
} else if (Z_REFCOUNT(retval) <= 1) {
|
||||
*is_temp = 1;
|
||||
ALLOC_HASHTABLE(ht);
|
||||
*ht = *Z_ARRVAL(retval);
|
||||
@ -159,6 +164,7 @@ ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC
|
||||
} else {
|
||||
*is_temp = 0;
|
||||
zval_ptr_dtor(&retval);
|
||||
return Z_ARRVAL(retval);
|
||||
}
|
||||
} else if (Z_TYPE(retval) == IS_NULL) {
|
||||
*is_temp = 1;
|
||||
@ -182,7 +188,7 @@ static void zend_std_call_getter(zval *object, zval *member, zval *retval TSRMLS
|
||||
|
||||
it should return whether the call was successfull or not
|
||||
*/
|
||||
SEPARATE_ARG_IF_REF(member);
|
||||
if (Z_REFCOUNTED_P(member)) Z_ADDREF_P(member);
|
||||
|
||||
zend_call_method_with_1_params(object, ce, &ce->__get, ZEND_GET_FUNC_NAME, retval, member);
|
||||
|
||||
@ -196,7 +202,7 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_D
|
||||
int result;
|
||||
zend_class_entry *ce = Z_OBJCE_P(object);
|
||||
|
||||
SEPARATE_ARG_IF_REF(member);
|
||||
if (Z_REFCOUNTED_P(member)) Z_ADDREF_P(member);
|
||||
if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
||||
|
||||
/* __set handler is called with two arguments:
|
||||
@ -228,7 +234,7 @@ static void zend_std_call_unsetter(zval *object, zval *member TSRMLS_DC) /* {{{
|
||||
property name
|
||||
*/
|
||||
|
||||
SEPARATE_ARG_IF_REF(member);
|
||||
if (Z_REFCOUNTED_P(member)) Z_ADDREF_P(member);
|
||||
|
||||
zend_call_method_with_1_params(object, ce, &ce->__unset, ZEND_UNSET_FUNC_NAME, NULL, member);
|
||||
|
||||
@ -246,7 +252,7 @@ static void zend_std_call_issetter(zval *object, zval *member, zval *retval TSRM
|
||||
it should return whether the property is set or not
|
||||
*/
|
||||
|
||||
SEPARATE_ARG_IF_REF(member);
|
||||
if (Z_REFCOUNTED_P(member)) Z_ADDREF_P(member);
|
||||
|
||||
zend_call_method_with_1_params(object, ce, &ce->__isset, ZEND_ISSET_FUNC_NAME, retval, member);
|
||||
|
||||
@ -287,15 +293,15 @@ static zend_always_inline zend_bool is_derived_class(zend_class_entry *child_cla
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_always_inline struct _zend_property_info *zend_get_property_info_quick(zend_class_entry *ce, zend_string *member, int silent, zend_uint cache_slot TSRMLS_DC) /* {{{ */
|
||||
static zend_always_inline struct _zend_property_info *zend_get_property_info_quick(zend_class_entry *ce, zend_string *member, int silent, void **cache_slot TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_property_info *property_info;
|
||||
zend_property_info *scope_property_info;
|
||||
zend_bool denied_access = 0;
|
||||
|
||||
if (cache_slot != -1 && ce == CACHED_PTR_EX(EG(active_op_array), cache_slot)) {
|
||||
property_info = CACHED_PTR_EX(EG(active_op_array), cache_slot + 1);
|
||||
if (!property_info) {
|
||||
if (cache_slot && EXPECTED(ce == CACHED_PTR_EX(cache_slot))) {
|
||||
property_info = CACHED_PTR_EX(cache_slot + 1);
|
||||
if (UNEXPECTED(!property_info)) {
|
||||
EG(std_property_info).flags = ZEND_ACC_PUBLIC;
|
||||
EG(std_property_info).name = member;
|
||||
EG(std_property_info).ce = ce;
|
||||
@ -332,8 +338,8 @@ static zend_always_inline struct _zend_property_info *zend_get_property_info_qui
|
||||
if (UNEXPECTED((property_info->flags & ZEND_ACC_STATIC) != 0) && !silent) {
|
||||
zend_error(E_STRICT, "Accessing static property %s::$%s as non static", ce->name->val, member->val);
|
||||
}
|
||||
if (cache_slot != -1) {
|
||||
CACHE_POLYMORPHIC_PTR_EX(EG(active_op_array), cache_slot, ce, property_info);
|
||||
if (cache_slot) {
|
||||
CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, property_info);
|
||||
}
|
||||
return property_info;
|
||||
}
|
||||
@ -348,8 +354,8 @@ static zend_always_inline struct _zend_property_info *zend_get_property_info_qui
|
||||
&& is_derived_class(ce, EG(scope))
|
||||
&& (scope_property_info = zend_hash_find_ptr(&EG(scope)->properties_info, member)) != NULL
|
||||
&& scope_property_info->flags & ZEND_ACC_PRIVATE) {
|
||||
if (cache_slot != -1) {
|
||||
CACHE_POLYMORPHIC_PTR_EX(EG(active_op_array), cache_slot, ce, scope_property_info);
|
||||
if (cache_slot) {
|
||||
CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, scope_property_info);
|
||||
}
|
||||
return scope_property_info;
|
||||
} else if (property_info) {
|
||||
@ -361,13 +367,13 @@ static zend_always_inline struct _zend_property_info *zend_get_property_info_qui
|
||||
return NULL;
|
||||
} else {
|
||||
/* fall through, return property_info... */
|
||||
if (cache_slot != -1) {
|
||||
CACHE_POLYMORPHIC_PTR_EX(EG(active_op_array), cache_slot, ce, property_info);
|
||||
if (cache_slot) {
|
||||
CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, property_info);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (cache_slot != -1) {
|
||||
CACHE_POLYMORPHIC_PTR_EX(EG(active_op_array), cache_slot, ce, NULL);
|
||||
if (cache_slot) {
|
||||
CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, NULL);
|
||||
}
|
||||
EG(std_property_info).flags = ZEND_ACC_PUBLIC;
|
||||
EG(std_property_info).name = member;
|
||||
@ -381,7 +387,7 @@ static zend_always_inline struct _zend_property_info *zend_get_property_info_qui
|
||||
|
||||
ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zval *member, int silent TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
return zend_get_property_info_quick(ce, Z_STR_P(member), silent, -1 TSRMLS_CC);
|
||||
return zend_get_property_info_quick(ce, Z_STR_P(member), silent, NULL TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -399,7 +405,7 @@ ZEND_API int zend_check_property_access(zend_object *zobj, zend_string *prop_inf
|
||||
} else {
|
||||
member = STR_COPY(prop_info_name);
|
||||
}
|
||||
property_info = zend_get_property_info_quick(zobj->ce, member, 1, -1 TSRMLS_CC);
|
||||
property_info = zend_get_property_info_quick(zobj->ce, member, 1, NULL TSRMLS_CC);
|
||||
STR_RELEASE(member);
|
||||
if (!property_info) {
|
||||
return FAILURE;
|
||||
@ -454,7 +460,7 @@ static long *zend_get_property_guard(zend_object *zobj, zend_property_info *prop
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
zval *zend_std_read_property(zval *object, zval *member, int type, zend_uint cache_slot, zval *rv TSRMLS_DC) /* {{{ */
|
||||
zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_object *zobj;
|
||||
zval tmp_member;
|
||||
@ -470,7 +476,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type, zend_uint cac
|
||||
ZVAL_DUP(&tmp_member, member);
|
||||
convert_to_string(&tmp_member);
|
||||
member = &tmp_member;
|
||||
cache_slot = -1;
|
||||
cache_slot = NULL;
|
||||
}
|
||||
|
||||
#if DEBUG_OBJECT_HANDLERS
|
||||
@ -548,7 +554,7 @@ exit:
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, zend_uint cache_slot TSRMLS_DC) /* {{{ */
|
||||
ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, void **cache_slot TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_object *zobj;
|
||||
zval tmp_member;
|
||||
@ -562,7 +568,7 @@ ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, z
|
||||
ZVAL_DUP(&tmp_member, member);
|
||||
convert_to_string(&tmp_member);
|
||||
member = &tmp_member;
|
||||
cache_slot = -1;
|
||||
cache_slot = NULL;
|
||||
}
|
||||
|
||||
property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), (zobj->ce->__set != NULL), cache_slot TSRMLS_CC);
|
||||
@ -752,7 +758,7 @@ static int zend_std_has_dimension(zval *object, zval *offset, int check_empty TS
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type, zend_uint cache_slot TSRMLS_DC) /* {{{ */
|
||||
static zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_object *zobj;
|
||||
zval tmp_member;
|
||||
@ -767,7 +773,7 @@ static zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type,
|
||||
ZVAL_DUP(&tmp_member, member);
|
||||
convert_to_string(&tmp_member);
|
||||
member = &tmp_member;
|
||||
cache_slot = -1;
|
||||
cache_slot = NULL;
|
||||
}
|
||||
|
||||
#if DEBUG_OBJECT_HANDLERS
|
||||
@ -821,7 +827,7 @@ exit:
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void zend_std_unset_property(zval *object, zval *member, zend_uint cache_slot TSRMLS_DC) /* {{{ */
|
||||
static void zend_std_unset_property(zval *object, zval *member, void **cache_slot TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_object *zobj;
|
||||
zval tmp_member;
|
||||
@ -834,7 +840,7 @@ static void zend_std_unset_property(zval *object, zval *member, zend_uint cache_
|
||||
ZVAL_DUP(&tmp_member, member);
|
||||
convert_to_string(&tmp_member);
|
||||
member = &tmp_member;
|
||||
cache_slot = -1;
|
||||
cache_slot = NULL;
|
||||
}
|
||||
|
||||
property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), (zobj->ce->__unset != NULL), cache_slot TSRMLS_CC);
|
||||
@ -899,7 +905,7 @@ static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC) /* {{
|
||||
|
||||
ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
|
||||
{
|
||||
zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->function_state.function;
|
||||
zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->func;
|
||||
zval method_name, method_args;
|
||||
zval method_result;
|
||||
zend_class_entry *ce = Z_OBJCE_P(getThis());
|
||||
@ -1117,7 +1123,7 @@ static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_str
|
||||
|
||||
ZEND_API void zend_std_callstatic_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
|
||||
{
|
||||
zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->function_state.function;
|
||||
zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->func;
|
||||
zval method_name, method_args;
|
||||
zval method_result;
|
||||
zend_class_entry *ce = EG(scope);
|
||||
@ -1265,12 +1271,12 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *property_name, zend_bool silent, zend_uint cache_slot TSRMLS_DC) /* {{{ */
|
||||
ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *property_name, zend_bool silent, void **cache_slot TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_property_info *property_info;
|
||||
|
||||
if (UNEXPECTED(cache_slot == -1) ||
|
||||
(property_info = CACHED_POLYMORPHIC_PTR_EX(EG(active_op_array), cache_slot, ce)) == NULL) {
|
||||
if (UNEXPECTED(cache_slot == NULL) ||
|
||||
(property_info = CACHED_POLYMORPHIC_PTR_EX(cache_slot, ce)) == NULL) {
|
||||
|
||||
if (UNEXPECTED((property_info = zend_hash_find_ptr(&ce->properties_info, property_name)) == NULL)) {
|
||||
if (!silent) {
|
||||
@ -1295,8 +1301,8 @@ ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *p
|
||||
|
||||
zend_update_class_constants(ce TSRMLS_CC);
|
||||
|
||||
if (EXPECTED(cache_slot != -1)) {
|
||||
CACHE_POLYMORPHIC_PTR_EX(EG(active_op_array), cache_slot, ce, property_info);
|
||||
if (EXPECTED(cache_slot != NULL)) {
|
||||
CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, property_info);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1312,7 +1318,7 @@ ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *p
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, zend_string *property_name, zend_uint cache_slot TSRMLS_DC) /* {{{ */
|
||||
ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, zend_string *property_name, void **cache_slot TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_error_noreturn(E_ERROR, "Attempt to unset static property %s::$%s", ce->name->val, property_name->val);
|
||||
return 0;
|
||||
@ -1417,7 +1423,7 @@ static int zend_std_compare_objects(zval *o1, zval *o2 TSRMLS_DC) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int zend_std_has_property(zval *object, zval *member, int has_set_exists, zend_uint cache_slot TSRMLS_DC) /* {{{ */
|
||||
static int zend_std_has_property(zval *object, zval *member, int has_set_exists, void **cache_slot TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_object *zobj;
|
||||
int result;
|
||||
@ -1432,7 +1438,7 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists,
|
||||
ZVAL_DUP(&tmp_member, member);
|
||||
convert_to_string(&tmp_member);
|
||||
member = &tmp_member;
|
||||
cache_slot = -1;
|
||||
cache_slot = NULL;
|
||||
}
|
||||
|
||||
property_info = zend_get_property_info_quick(zobj->ce, Z_STR_P(member), 1, cache_slot TSRMLS_CC);
|
||||
|
@ -30,7 +30,7 @@ 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, zend_uint cache_slot, zval *rv TSRMLS_DC);
|
||||
typedef zval *(*zend_object_read_property_t)(zval *object, zval *member, int type, void **cache_slot, zval *rv TSRMLS_DC);
|
||||
|
||||
/* Used to fetch dimension from the object, read-only */
|
||||
typedef zval *(*zend_object_read_dimension_t)(zval *object, zval *offset, int type, zval *rv TSRMLS_DC);
|
||||
@ -42,14 +42,14 @@ typedef zval *(*zend_object_read_dimension_t)(zval *object, zval *offset, int ty
|
||||
any changes. You should NOT modify the reference count of the value passed to you.
|
||||
*/
|
||||
/* Used to set property of the object */
|
||||
typedef void (*zend_object_write_property_t)(zval *object, zval *member, zval *value, zend_uint cache_slot TSRMLS_DC);
|
||||
typedef void (*zend_object_write_property_t)(zval *object, zval *member, zval *value, void **cache_slot TSRMLS_DC);
|
||||
|
||||
/* Used to set dimension of the object */
|
||||
typedef void (*zend_object_write_dimension_t)(zval *object, zval *offset, zval *value TSRMLS_DC);
|
||||
|
||||
|
||||
/* 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, zend_uint cache_slot TSRMLS_DC);
|
||||
typedef zval *(*zend_object_get_property_ptr_ptr_t)(zval *object, zval *member, int type, void **cache_slot TSRMLS_DC);
|
||||
|
||||
/* Used to set object value. Can be used to override assignments and scalar
|
||||
write ops (like ++, +=) on the object */
|
||||
@ -66,13 +66,13 @@ typedef zval* (*zend_object_get_t)(zval *object, zval *rv TSRMLS_DC);
|
||||
* 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, zend_uint cache_slot TSRMLS_DC);
|
||||
typedef int (*zend_object_has_property_t)(zval *object, zval *member, int has_set_exists, void **cache_slot TSRMLS_DC);
|
||||
|
||||
/* Used to check if a dimension of the object exists */
|
||||
typedef int (*zend_object_has_dimension_t)(zval *object, zval *member, int check_empty TSRMLS_DC);
|
||||
|
||||
/* Used to remove a property of the object */
|
||||
typedef void (*zend_object_unset_property_t)(zval *object, zval *member, zend_uint cache_slot TSRMLS_DC);
|
||||
typedef void (*zend_object_unset_property_t)(zval *object, zval *member, void **cache_slot TSRMLS_DC);
|
||||
|
||||
/* Used to remove a dimension of the object */
|
||||
typedef void (*zend_object_unset_dimension_t)(zval *object, zval *offset TSRMLS_DC);
|
||||
@ -156,14 +156,14 @@ extern ZEND_API zend_object_handlers std_object_handlers;
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
ZEND_API union _zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_string *function_name_strval, const zval *key TSRMLS_DC);
|
||||
ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *property_name, zend_bool silent, zend_uint cache_slot TSRMLS_DC);
|
||||
ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, zend_string *property_name, zend_uint cache_slot TSRMLS_DC);
|
||||
ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *property_name, zend_bool silent, void **cache_slot TSRMLS_DC);
|
||||
ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, zend_string *property_name, void **cache_slot TSRMLS_DC);
|
||||
ZEND_API union _zend_function *zend_std_get_constructor(zend_object *object TSRMLS_DC);
|
||||
ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zval *member, int silent TSRMLS_DC);
|
||||
ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC);
|
||||
ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC);
|
||||
ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC);
|
||||
ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, zend_uint cache_slot TSRMLS_DC);
|
||||
ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, void **cache_slot TSRMLS_DC);
|
||||
ZEND_API void rebuild_object_properties(zend_object *zobj);
|
||||
|
||||
|
||||
|
@ -77,11 +77,11 @@ ZEND_API void zend_objects_destroy_object(zend_object *object TSRMLS_DC)
|
||||
if (object->ce != EG(scope)) {
|
||||
zend_class_entry *ce = object->ce;
|
||||
|
||||
zend_error(EG(in_execution) ? E_ERROR : E_WARNING,
|
||||
zend_error(EG(current_execute_data) ? E_ERROR : E_WARNING,
|
||||
"Call to private %s::__destruct() from context '%s'%s",
|
||||
ce->name->val,
|
||||
EG(scope) ? EG(scope)->name->val : "",
|
||||
EG(in_execution) ? "" : " during shutdown ignored");
|
||||
EG(current_execute_data) ? "" : " during shutdown ignored");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@ -90,11 +90,11 @@ ZEND_API void zend_objects_destroy_object(zend_object *object TSRMLS_DC)
|
||||
if (!zend_check_protected(zend_get_function_root_class(destructor), EG(scope))) {
|
||||
zend_class_entry *ce = object->ce;
|
||||
|
||||
zend_error(EG(in_execution) ? E_ERROR : E_WARNING,
|
||||
zend_error(EG(current_execute_data) ? E_ERROR : E_WARNING,
|
||||
"Call to protected %s::__destruct() from context '%s'%s",
|
||||
ce->name->val,
|
||||
EG(scope) ? EG(scope)->name->val : "",
|
||||
EG(in_execution) ? "" : " during shutdown ignored");
|
||||
EG(current_execute_data) ? "" : " during shutdown ignored");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ ZEND_API void zend_object_proxy_set(zval *property, zval *value TSRMLS_DC)
|
||||
zend_proxy_object *probj = (zend_proxy_object*)Z_OBJ_P(property);
|
||||
|
||||
if (Z_OBJ_HT(probj->object) && Z_OBJ_HT(probj->object)->write_property) {
|
||||
Z_OBJ_HT(probj->object)->write_property(&probj->object, &probj->property, value, -1 TSRMLS_CC);
|
||||
Z_OBJ_HT(probj->object)->write_property(&probj->object, &probj->property, value, NULL TSRMLS_CC);
|
||||
} else {
|
||||
zend_error(E_WARNING, "Cannot write property of object - no write handler defined");
|
||||
}
|
||||
@ -281,7 +281,7 @@ ZEND_API zval* zend_object_proxy_get(zval *property, zval *rv TSRMLS_DC)
|
||||
zend_proxy_object *probj = (zend_proxy_object*)Z_OBJ_P(property);
|
||||
|
||||
if (Z_OBJ_HT(probj->object) && Z_OBJ_HT(probj->object)->read_property) {
|
||||
return Z_OBJ_HT(probj->object)->read_property(&probj->object, &probj->property, BP_VAR_R, -1, rv TSRMLS_CC);
|
||||
return Z_OBJ_HT(probj->object)->read_property(&probj->object, &probj->property, BP_VAR_R, NULL, rv TSRMLS_CC);
|
||||
} else {
|
||||
zend_error(E_WARNING, "Cannot read property of object - no read handler defined");
|
||||
}
|
||||
|
@ -70,9 +70,6 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
|
||||
|
||||
op_array->T = 0;
|
||||
|
||||
op_array->nested_calls = 0;
|
||||
op_array->used_stack = 0;
|
||||
|
||||
op_array->function_name = NULL;
|
||||
op_array->filename = zend_get_compiled_filename(TSRMLS_C);
|
||||
op_array->doc_comment = NULL;
|
||||
@ -130,7 +127,11 @@ ZEND_API void zend_function_dtor(zval *zv)
|
||||
TSRMLS_FETCH();
|
||||
|
||||
destroy_zend_function(function TSRMLS_CC);
|
||||
pefree(function, function->type == ZEND_INTERNAL_FUNCTION);
|
||||
if (function->type == ZEND_INTERNAL_FUNCTION) {
|
||||
pefree(function, 1);
|
||||
} else if (!function->common.function_name) {
|
||||
efree(function);
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API void zend_cleanup_op_array_data(zend_op_array *op_array)
|
||||
@ -278,7 +279,6 @@ ZEND_API void destroy_zend_class(zval *zv)
|
||||
|
||||
_destroy_zend_class_traits_info(ce);
|
||||
|
||||
efree(ce);
|
||||
break;
|
||||
case ZEND_INTERNAL_CLASS:
|
||||
if (ce->default_properties_table) {
|
||||
@ -329,7 +329,7 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
|
||||
FREE_HASHTABLE(op_array->static_variables);
|
||||
}
|
||||
|
||||
if (op_array->run_time_cache) {
|
||||
if (op_array->run_time_cache && !op_array->function_name) {
|
||||
efree(op_array->run_time_cache);
|
||||
}
|
||||
|
||||
@ -481,6 +481,49 @@ static void zend_check_finally_breakout(zend_op_array *op_array, zend_uint op_nu
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_adjust_fast_call(zend_op_array *op_array, zend_uint fast_call, zend_uint start, zend_uint end TSRMLS_DC)
|
||||
{
|
||||
int i;
|
||||
zend_uint op_num = 0;
|
||||
|
||||
for (i = 0; i < op_array->last_try_catch; i++) {
|
||||
if (op_array->try_catch_array[i].finally_op > start
|
||||
&& op_array->try_catch_array[i].finally_end < end) {
|
||||
op_num = op_array->try_catch_array[i].finally_op;
|
||||
start = op_array->try_catch_array[i].finally_end;
|
||||
}
|
||||
}
|
||||
|
||||
if (op_num) {
|
||||
/* Must be ZEND_FAST_CALL */
|
||||
ZEND_ASSERT(op_array->opcodes[op_num - 2].opcode == ZEND_FAST_CALL);
|
||||
op_array->opcodes[op_num - 2].extended_value = ZEND_FAST_CALL_FROM_FINALLY;
|
||||
op_array->opcodes[op_num - 2].op2.opline_num = fast_call;
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_resolve_fast_call(zend_op_array *op_array, zend_uint fast_call, zend_uint op_num TSRMLS_DC)
|
||||
{
|
||||
int i;
|
||||
zend_uint finally_op_num = 0;
|
||||
|
||||
for (i = 0; i < op_array->last_try_catch; i++) {
|
||||
if (op_num >= op_array->try_catch_array[i].finally_op
|
||||
&& op_num < op_array->try_catch_array[i].finally_end) {
|
||||
finally_op_num = op_array->try_catch_array[i].finally_op;
|
||||
}
|
||||
}
|
||||
|
||||
if (finally_op_num) {
|
||||
/* Must be ZEND_FAST_CALL */
|
||||
ZEND_ASSERT(op_array->opcodes[finally_op_num - 2].opcode == ZEND_FAST_CALL);
|
||||
if (op_array->opcodes[fast_call].extended_value == 0) {
|
||||
op_array->opcodes[fast_call].extended_value = ZEND_FAST_CALL_FROM_FINALLY;
|
||||
op_array->opcodes[fast_call].op2.opline_num = finally_op_num - 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_resolve_finally_call(zend_op_array *op_array, zend_uint op_num, zend_uint dst_num TSRMLS_DC)
|
||||
{
|
||||
zend_uint start_op;
|
||||
@ -508,11 +551,23 @@ static void zend_resolve_finally_call(zend_op_array *op_array, zend_uint op_num,
|
||||
opline->opcode = ZEND_FAST_CALL;
|
||||
SET_UNUSED(opline->op1);
|
||||
SET_UNUSED(opline->op2);
|
||||
opline->op1.opline_num = op_array->try_catch_array[i].finally_op;
|
||||
zend_adjust_fast_call(op_array, start_op,
|
||||
op_array->try_catch_array[i].finally_op,
|
||||
op_array->try_catch_array[i].finally_end TSRMLS_CC);
|
||||
if (op_array->try_catch_array[i].catch_op) {
|
||||
opline->extended_value = 1;
|
||||
opline->extended_value = ZEND_FAST_CALL_FROM_CATCH;
|
||||
opline->op2.opline_num = op_array->try_catch_array[i].catch_op;
|
||||
opline->op1.opline_num = get_next_op_number(op_array);
|
||||
/* generate a FAST_CALL to hole CALL_FROM_FINALLY */
|
||||
opline = get_next_op(op_array TSRMLS_CC);
|
||||
opline->opcode = ZEND_FAST_CALL;
|
||||
SET_UNUSED(opline->op1);
|
||||
SET_UNUSED(opline->op2);
|
||||
zend_resolve_fast_call(op_array, start_op + 1, op_array->try_catch_array[i].finally_op - 2 TSRMLS_CC);
|
||||
} else {
|
||||
zend_resolve_fast_call(op_array, start_op, op_array->try_catch_array[i].finally_op - 2 TSRMLS_CC);
|
||||
}
|
||||
opline->op1.opline_num = op_array->try_catch_array[i].finally_op;
|
||||
|
||||
/* generate a sequence of FAST_CALL to upward finally block */
|
||||
while (i > 0) {
|
||||
@ -577,10 +632,10 @@ static void zend_resolve_finally_ret(zend_op_array *op_array, zend_uint op_num T
|
||||
|
||||
static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC)
|
||||
{
|
||||
zend_uint i;
|
||||
zend_uint i, j;
|
||||
zend_op *opline;
|
||||
|
||||
for (i = 0; i < op_array->last; i++) {
|
||||
for (i = 0, j = op_array->last; i < j; i++) {
|
||||
opline = op_array->opcodes + i;
|
||||
switch (opline->opcode) {
|
||||
case ZEND_RETURN:
|
||||
@ -595,15 +650,16 @@ static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC)
|
||||
zend_brk_cont_element *jmp_to;
|
||||
|
||||
nest_levels = Z_LVAL(op_array->literals[opline->op2.constant]);
|
||||
array_offset = opline->op1.opline_num;
|
||||
do {
|
||||
jmp_to = &op_array->brk_cont_array[array_offset];
|
||||
if (nest_levels > 1) {
|
||||
array_offset = jmp_to->parent;
|
||||
}
|
||||
} while (--nest_levels > 0);
|
||||
zend_resolve_finally_call(op_array, i, opline->opcode == ZEND_BRK ? jmp_to->brk : jmp_to->cont TSRMLS_CC);
|
||||
break;
|
||||
if ((array_offset = opline->op1.opline_num) != -1) {
|
||||
do {
|
||||
jmp_to = &op_array->brk_cont_array[array_offset];
|
||||
if (nest_levels > 1) {
|
||||
array_offset = jmp_to->parent;
|
||||
}
|
||||
} while (--nest_levels > 0);
|
||||
zend_resolve_finally_call(op_array, i, opline->opcode == ZEND_BRK ? jmp_to->brk : jmp_to->cont TSRMLS_CC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case ZEND_GOTO:
|
||||
if (Z_TYPE(op_array->literals[opline->op2.constant]) != IS_LONG) {
|
||||
@ -616,6 +672,9 @@ static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC)
|
||||
case ZEND_JMP:
|
||||
zend_resolve_finally_call(op_array, i, opline->op1.opline_num TSRMLS_CC);
|
||||
break;
|
||||
case ZEND_FAST_CALL:
|
||||
zend_resolve_fast_call(op_array, i, i TSRMLS_CC);
|
||||
break;
|
||||
case ZEND_FAST_RET:
|
||||
zend_resolve_finally_ret(op_array, i TSRMLS_CC);
|
||||
break;
|
||||
@ -629,7 +688,7 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
|
||||
{
|
||||
zend_op *opline, *end;
|
||||
|
||||
if (op_array->type!=ZEND_USER_FUNCTION && op_array->type!=ZEND_EVAL_CODE) {
|
||||
if (!ZEND_USER_CODE(op_array->type)) {
|
||||
return 0;
|
||||
}
|
||||
if (op_array->has_finally_block) {
|
||||
@ -660,20 +719,20 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
opline->op1.zv = &op_array->literals[opline->op1.constant];
|
||||
} else if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
|
||||
opline->op1.var = (zend_uint)EX_VAR_NUM_2(NULL, op_array->last_var + opline->op1.var);
|
||||
opline->op1.var = (zend_uint)(zend_intptr_t)EX_VAR_NUM_2(NULL, op_array->last_var + opline->op1.var);
|
||||
}
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
opline->op2.zv = &op_array->literals[opline->op2.constant];
|
||||
} else if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) {
|
||||
opline->op2.var = (zend_uint)EX_VAR_NUM_2(NULL, op_array->last_var + opline->op2.var);
|
||||
opline->op2.var = (zend_uint)(zend_intptr_t)EX_VAR_NUM_2(NULL, op_array->last_var + opline->op2.var);
|
||||
}
|
||||
if (opline->result_type & (IS_VAR|IS_TMP_VAR)) {
|
||||
opline->result.var = (zend_uint)EX_VAR_NUM_2(NULL, op_array->last_var + opline->result.var);
|
||||
opline->result.var = (zend_uint)(zend_intptr_t)EX_VAR_NUM_2(NULL, op_array->last_var + opline->result.var);
|
||||
}
|
||||
switch (opline->opcode) {
|
||||
case ZEND_DECLARE_INHERITED_CLASS:
|
||||
case ZEND_DECLARE_INHERITED_CLASS_DELAYED:
|
||||
opline->extended_value = (zend_uint)EX_VAR_NUM_2(NULL, op_array->last_var + opline->extended_value);
|
||||
opline->extended_value = (zend_uint)(zend_intptr_t)EX_VAR_NUM_2(NULL, op_array->last_var + opline->extended_value);
|
||||
break;
|
||||
case ZEND_GOTO:
|
||||
if (Z_TYPE_P(opline->op2.zv) != IS_LONG) {
|
||||
@ -694,6 +753,9 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
|
||||
case ZEND_JMPNZ_EX:
|
||||
case ZEND_JMP_SET:
|
||||
case ZEND_JMP_SET_VAR:
|
||||
case ZEND_NEW:
|
||||
case ZEND_FE_RESET:
|
||||
case ZEND_FE_FETCH:
|
||||
opline->op2.jmp_addr = &op_array->opcodes[opline->op2.opline_num];
|
||||
break;
|
||||
case ZEND_RETURN:
|
||||
|
@ -627,12 +627,13 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{{ */
|
||||
TSRMLS_FETCH();
|
||||
|
||||
convert_object_to_type(op, &dst, IS_STRING, convert_to_string);
|
||||
zval_dtor(op);
|
||||
|
||||
if (Z_TYPE(dst) == IS_STRING) {
|
||||
zval_dtor(op);
|
||||
ZVAL_COPY_VALUE(op, &dst);
|
||||
} else {
|
||||
zend_error(E_NOTICE, "Object of class %s to string conversion", Z_OBJCE_P(op)->name->val);
|
||||
zval_dtor(op);
|
||||
ZVAL_NEW_STR(op, STR_INIT("Object", sizeof("Object")-1, 0));
|
||||
}
|
||||
break;
|
||||
@ -1546,14 +1547,15 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{
|
||||
zval op1_copy, op2_copy;
|
||||
int use_copy1 = 0, use_copy2 = 0;
|
||||
|
||||
if (Z_TYPE_P(op1) != IS_STRING || Z_TYPE_P(op2) != IS_STRING) {
|
||||
if (UNEXPECTED(Z_TYPE_P(op1) != IS_STRING) ||
|
||||
UNEXPECTED(Z_TYPE_P(op2) != IS_STRING)) {
|
||||
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_CONCAT);
|
||||
|
||||
if (Z_TYPE_P(op1) != IS_STRING) {
|
||||
zend_make_printable_zval(op1, &op1_copy, &use_copy1);
|
||||
use_copy1 = zend_make_printable_zval(op1, &op1_copy);
|
||||
}
|
||||
if (Z_TYPE_P(op2) != IS_STRING) {
|
||||
zend_make_printable_zval(op2, &op2_copy, &use_copy2);
|
||||
use_copy2 = zend_make_printable_zval(op2, &op2_copy);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1569,6 +1571,7 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{
|
||||
if (use_copy2) {
|
||||
op2 = &op2_copy;
|
||||
}
|
||||
|
||||
if (result==op1 && !IS_INTERNED(Z_STR_P(op1))) { /* special case, perform operations on result */
|
||||
uint op1_len = Z_STRLEN_P(op1);
|
||||
uint op2_len = Z_STRLEN_P(op2);
|
||||
@ -1592,10 +1595,10 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{
|
||||
buf->val[length] = 0;
|
||||
ZVAL_NEW_STR(result, buf);
|
||||
}
|
||||
if (use_copy1) {
|
||||
if (UNEXPECTED(use_copy1)) {
|
||||
zval_dtor(op1);
|
||||
}
|
||||
if (use_copy2) {
|
||||
if (UNEXPECTED(use_copy2)) {
|
||||
zval_dtor(op2);
|
||||
}
|
||||
return SUCCESS;
|
||||
@ -1621,13 +1624,45 @@ ZEND_API int string_compare_function_ex(zval *result, zval *op1, zval *op2, zend
|
||||
|
||||
ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
return string_compare_function_ex(result, op1, op2, 0 TSRMLS_CC);
|
||||
if (EXPECTED(Z_TYPE_P(op1) == IS_STRING) &&
|
||||
EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
|
||||
if (Z_STR_P(op1) == Z_STR_P(op2)) {
|
||||
ZVAL_LONG(result, 0);
|
||||
} else {
|
||||
ZVAL_LONG(result, zend_binary_strcmp(Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2)));
|
||||
}
|
||||
} else {
|
||||
zend_string *str1 = zval_get_string(op1);
|
||||
zend_string *str2 = zval_get_string(op2);
|
||||
|
||||
ZVAL_LONG(result, zend_binary_strcmp(str1->val, str1->len, str2->val, str2->len));
|
||||
|
||||
STR_RELEASE(str1);
|
||||
STR_RELEASE(str2);
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API int string_case_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
return string_compare_function_ex(result, op1, op2, 1 TSRMLS_CC);
|
||||
if (EXPECTED(Z_TYPE_P(op1) == IS_STRING) &&
|
||||
EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
|
||||
if (Z_STR_P(op1) == Z_STR_P(op2)) {
|
||||
ZVAL_LONG(result, 0);
|
||||
} else {
|
||||
ZVAL_LONG(result, zend_binary_strcasecmp_l(Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2)));
|
||||
}
|
||||
} else {
|
||||
zend_string *str1 = zval_get_string(op1);
|
||||
zend_string *str2 = zval_get_string(op2);
|
||||
|
||||
ZVAL_LONG(result, zend_binary_strcasecmp_l(str1->val, str1->len, str2->val, str1->len));
|
||||
|
||||
STR_RELEASE(str1);
|
||||
STR_RELEASE(str2);
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -1648,15 +1683,12 @@ ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 T
|
||||
|
||||
ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval op1_copy, op2_copy;
|
||||
double d1, d2;
|
||||
|
||||
ZVAL_DUP_DEREF(&op1_copy, op1);
|
||||
ZVAL_DUP_DEREF(&op2_copy, op2);
|
||||
d1 = zval_get_double(op1);
|
||||
d2 = zval_get_double(op2);
|
||||
|
||||
convert_to_double(&op1_copy);
|
||||
convert_to_double(&op2_copy);
|
||||
|
||||
ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL(op1_copy)-Z_DVAL(op2_copy)));
|
||||
ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(d1 - d2));
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
@ -1727,15 +1759,19 @@ ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {
|
||||
return SUCCESS;
|
||||
|
||||
case TYPE_PAIR(IS_STRING, IS_STRING):
|
||||
if (Z_STR_P(op1) == Z_STR_P(op2)) {
|
||||
ZVAL_LONG(result, 0);
|
||||
return SUCCESS;
|
||||
}
|
||||
zendi_smart_strcmp(result, op1, op2);
|
||||
return SUCCESS;
|
||||
|
||||
case TYPE_PAIR(IS_NULL, IS_STRING):
|
||||
ZVAL_LONG(result, zend_binary_strcmp("", 0, Z_STRVAL_P(op2), Z_STRLEN_P(op2)));
|
||||
ZVAL_LONG(result, Z_STRLEN_P(op2) == 0 ? 0 : -1);
|
||||
return SUCCESS;
|
||||
|
||||
case TYPE_PAIR(IS_STRING, IS_NULL):
|
||||
ZVAL_LONG(result, zend_binary_strcmp(Z_STRVAL_P(op1), Z_STRLEN_P(op1), "", 0));
|
||||
ZVAL_LONG(result, Z_STRLEN_P(op1) == 0 ? 0 : 1);
|
||||
return SUCCESS;
|
||||
|
||||
case TYPE_PAIR(IS_OBJECT, IS_NULL):
|
||||
@ -2525,6 +2561,10 @@ ZEND_API zend_string *zend_long_to_str(long num) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API zend_uchar is_numeric_str_function(const zend_string *str, long *lval, double *dval) {
|
||||
return is_numeric_string_ex(str->val, str->len, lval, dval, -1, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
|
@ -270,6 +270,8 @@ static inline zend_uchar is_numeric_string(const char *str, int length, long *lv
|
||||
return is_numeric_string_ex(str, length, lval, dval, allow_errors, NULL);
|
||||
}
|
||||
|
||||
ZEND_API zend_uchar is_numeric_str_function(const zend_string *str, long *lval, double *dval);
|
||||
|
||||
static inline const char *
|
||||
zend_memnstr(const char *haystack, const char *needle, int needle_len, char *end)
|
||||
{
|
||||
@ -830,6 +832,21 @@ static zend_always_inline int fast_equal_check_function(zval *result, zval *op1,
|
||||
} else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
|
||||
return Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2));
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
|
||||
if (Z_STR_P(op1) == Z_STR_P(op2)) {
|
||||
return 1;
|
||||
} else if (Z_STRVAL_P(op1)[0] > '9' || Z_STRVAL_P(op2)[0] > '9') {
|
||||
if (Z_STRLEN_P(op1) != Z_STRLEN_P(op2)) {
|
||||
return 0;
|
||||
} else {
|
||||
return memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1)) == 0;
|
||||
}
|
||||
} else {
|
||||
zendi_smart_strcmp(result, op1, op2);
|
||||
return Z_LVAL_P(result) == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
compare_function(result, op1, op2 TSRMLS_CC);
|
||||
return Z_LVAL_P(result) == 0;
|
||||
@ -853,6 +870,25 @@ static zend_always_inline void fast_equal_function(zval *result, zval *op1, zval
|
||||
ZVAL_BOOL(result, Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
|
||||
return;
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
|
||||
if (Z_STR_P(op1) == Z_STR_P(op2)) {
|
||||
ZVAL_TRUE(result);
|
||||
return;
|
||||
} else if (Z_STRVAL_P(op1)[0] > '9' || Z_STRVAL_P(op2)[0] > '9') {
|
||||
if (Z_STRLEN_P(op1) != Z_STRLEN_P(op2)) {
|
||||
ZVAL_FALSE(result);
|
||||
return;
|
||||
} else {
|
||||
ZVAL_BOOL(result, memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1)) == 0);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
zendi_smart_strcmp(result, op1, op2);
|
||||
ZVAL_BOOL(result, Z_LVAL_P(result) == 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
compare_function(result, op1, op2 TSRMLS_CC);
|
||||
ZVAL_BOOL(result, Z_LVAL_P(result) == 0);
|
||||
@ -876,6 +912,25 @@ static zend_always_inline void fast_not_equal_function(zval *result, zval *op1,
|
||||
ZVAL_BOOL(result, Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2)));
|
||||
return;
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
|
||||
if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
|
||||
if (Z_STR_P(op1) == Z_STR_P(op2)) {
|
||||
ZVAL_FALSE(result);
|
||||
return;
|
||||
} else if (Z_STRVAL_P(op1)[0] > '9' || Z_STRVAL_P(op2)[0] > '9') {
|
||||
if (Z_STRLEN_P(op1) != Z_STRLEN_P(op2)) {
|
||||
ZVAL_TRUE(result);
|
||||
return;
|
||||
} else {
|
||||
ZVAL_BOOL(result, memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1)) != 0);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
zendi_smart_strcmp(result, op1, op2);
|
||||
ZVAL_BOOL(result, Z_LVAL_P(result) != 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
compare_function(result, op1, op2 TSRMLS_CC);
|
||||
ZVAL_BOOL(result, Z_LVAL_P(result) != 0);
|
||||
|
@ -60,6 +60,7 @@ void zend_interned_strings_init(TSRMLS_D)
|
||||
#else
|
||||
str = STR_ALLOC(sizeof("")-1, 1);
|
||||
str->val[0] = '\000';
|
||||
STR_HASH_VAL(str);
|
||||
str->gc.u.v.flags |= IS_STR_INTERNED;
|
||||
CG(empty_string) = str;
|
||||
#endif
|
||||
|
@ -57,7 +57,7 @@ END_EXTERN_C()
|
||||
#define _STR_HEADER_SIZE XtOffsetOf(zend_string, val)
|
||||
|
||||
#define STR_ALLOCA_ALLOC(str, _len, use_heap) do { \
|
||||
(str) = do_alloca(_STR_HEADER_SIZE + (_len) + 1, (use_heap)); \
|
||||
(str) = (zend_string *)do_alloca(ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + (_len) + 1), (use_heap)); \
|
||||
GC_REFCOUNT(str) = 1; \
|
||||
(str)->h = 0; \
|
||||
(str)->len = (_len); \
|
||||
@ -109,7 +109,7 @@ static zend_always_inline zend_uint zend_str_delref(zend_string *s)
|
||||
|
||||
static zend_always_inline zend_string *zend_str_alloc(int len, int persistent)
|
||||
{
|
||||
zend_string *ret = pemalloc(_STR_HEADER_SIZE + len + 1, persistent);
|
||||
zend_string *ret = (zend_string *)pemalloc(ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + len + 1), persistent);
|
||||
|
||||
GC_REFCOUNT(ret) = 1;
|
||||
#if 1
|
||||
@ -127,7 +127,7 @@ static zend_always_inline zend_string *zend_str_alloc(int len, int persistent)
|
||||
|
||||
static zend_always_inline zend_string *zend_str_safe_alloc(size_t n, size_t m, size_t l, int persistent)
|
||||
{
|
||||
zend_string *ret = safe_pemalloc(n, m, _STR_HEADER_SIZE + l + 1, persistent);
|
||||
zend_string *ret = (zend_string *)safe_pemalloc(n, m, ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + l + 1), persistent);
|
||||
|
||||
GC_REFCOUNT(ret) = 1;
|
||||
#if 1
|
||||
@ -176,8 +176,8 @@ static zend_always_inline zend_string *zend_str_realloc(zend_string *s, int len,
|
||||
if (IS_INTERNED(s)) {
|
||||
ret = STR_ALLOC(len, persistent);
|
||||
memcpy(ret->val, s->val, (len > s->len ? s->len : len) + 1);
|
||||
} else if (STR_REFCOUNT(s) == 1) {
|
||||
ret = perealloc(s, _STR_HEADER_SIZE + len + 1, persistent);
|
||||
} else if (EXPECTED(STR_REFCOUNT(s) == 1)) {
|
||||
ret = (zend_string *)perealloc(s, ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + len + 1), persistent);
|
||||
ret->len = len;
|
||||
STR_FORGET_HASH_VAL(ret);
|
||||
} else {
|
||||
@ -194,14 +194,14 @@ static zend_always_inline zend_string *zend_str_safe_realloc(zend_string *s, siz
|
||||
|
||||
if (IS_INTERNED(s)) {
|
||||
ret = STR_SAFE_ALLOC(n, m, l, persistent);
|
||||
memcpy(ret->val, s->val, ((n * m) + l > s->len ? s->len : ((n * m) + l)) + 1);
|
||||
memcpy(ret->val, s->val, ((n * m) + l > (size_t)s->len ? (size_t)s->len : ((n * m) + l)) + 1);
|
||||
} else if (STR_REFCOUNT(s) == 1) {
|
||||
ret = safe_perealloc(s, n, m, _STR_HEADER_SIZE + l + 1, persistent);
|
||||
ret = (zend_string *)safe_perealloc(s, n, m, ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + l + 1), persistent);
|
||||
ret->len = (n * m) + l;
|
||||
STR_FORGET_HASH_VAL(ret);
|
||||
} else {
|
||||
ret = STR_SAFE_ALLOC(n, m, l, persistent);
|
||||
memcpy(ret->val, s->val, ((n * m) + l > s->len ? s->len : ((n * m) + l)) + 1);
|
||||
memcpy(ret->val, s->val, ((n * m) + l > (size_t)s->len ? (size_t)s->len : ((n * m) + l)) + 1);
|
||||
STR_DELREF(s);
|
||||
}
|
||||
return ret;
|
||||
|
@ -44,8 +44,8 @@ ZEND_API void _zval_dtor_func(zend_refcounted *p ZEND_FILE_LINE_DC)
|
||||
if (arr != &EG(symbol_table)) {
|
||||
/* break possible cycles */
|
||||
GC_TYPE(arr) = IS_NULL;
|
||||
zend_hash_destroy(&arr->ht);
|
||||
GC_REMOVE_FROM_BUFFER(arr);
|
||||
zend_hash_destroy(&arr->ht);
|
||||
efree(arr);
|
||||
}
|
||||
break;
|
||||
@ -104,8 +104,8 @@ ZEND_API void _zval_dtor_func_for_ptr(zend_refcounted *p ZEND_FILE_LINE_DC)
|
||||
if (arr != &EG(symbol_table)) {
|
||||
/* break possible cycles */
|
||||
GC_TYPE(arr) = IS_NULL;
|
||||
zend_hash_destroy(&arr->ht);
|
||||
GC_REMOVE_FROM_BUFFER(arr);
|
||||
zend_hash_destroy(&arr->ht);
|
||||
efree(arr);
|
||||
}
|
||||
break;
|
||||
@ -210,7 +210,7 @@ ZEND_API void zval_add_ref(zval *p)
|
||||
{
|
||||
if (Z_REFCOUNTED_P(p)) {
|
||||
if (Z_ISREF_P(p) && Z_REFCOUNT_P(p) == 1) {
|
||||
ZVAL_DUP(p, Z_REFVAL_P(p));
|
||||
ZVAL_COPY(p, Z_REFVAL_P(p));
|
||||
} else {
|
||||
Z_ADDREF_P(p);
|
||||
}
|
||||
@ -305,6 +305,7 @@ ZEND_API void _zval_internal_ptr_dtor_wrapper(zval *zval_ptr)
|
||||
|
||||
ZEND_API int zval_copy_static_var(zval *p TSRMLS_DC, int num_args, va_list args, zend_hash_key *key) /* {{{ */
|
||||
{
|
||||
zend_array *symbol_table;
|
||||
HashTable *target = va_arg(args, HashTable*);
|
||||
zend_bool is_ref;
|
||||
zval tmp;
|
||||
@ -312,16 +313,14 @@ ZEND_API int zval_copy_static_var(zval *p TSRMLS_DC, int num_args, va_list args,
|
||||
if (Z_CONST_FLAGS_P(p) & (IS_LEXICAL_VAR|IS_LEXICAL_REF)) {
|
||||
is_ref = Z_CONST_FLAGS_P(p) & IS_LEXICAL_REF;
|
||||
|
||||
if (!EG(active_symbol_table)) {
|
||||
zend_rebuild_symbol_table(TSRMLS_C);
|
||||
}
|
||||
p = zend_hash_find(&EG(active_symbol_table)->ht, key->key);
|
||||
symbol_table = zend_rebuild_symbol_table(TSRMLS_C);
|
||||
p = zend_hash_find(&symbol_table->ht, key->key);
|
||||
if (!p) {
|
||||
p = &tmp;
|
||||
ZVAL_NULL(&tmp);
|
||||
if (is_ref) {
|
||||
ZVAL_NEW_REF(&tmp, &tmp);
|
||||
zend_hash_add_new(&EG(active_symbol_table)->ht, key->key, &tmp);
|
||||
zend_hash_add_new(&symbol_table->ht, key->key, &tmp);
|
||||
Z_ADDREF_P(p);
|
||||
} else {
|
||||
zend_error(E_NOTICE,"Undefined variable: %s", key->key->val);
|
||||
@ -340,7 +339,7 @@ ZEND_API int zval_copy_static_var(zval *p TSRMLS_DC, int num_args, va_list args,
|
||||
}
|
||||
}
|
||||
if (is_ref) {
|
||||
SEPARATE_ZVAL_TO_MAKE_IS_REF(p);
|
||||
ZVAL_MAKE_REF(p);
|
||||
Z_ADDREF_P(p);
|
||||
} else if (Z_ISREF_P(p)) {
|
||||
ZVAL_DUP(&tmp, Z_REFVAL_P(p));
|
||||
|
@ -62,6 +62,28 @@ static zend_always_inline void _zval_opt_copy_ctor(zval *zvalue ZEND_FILE_LINE_D
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline void _zval_copy_ctor_no_imm(zval *zvalue ZEND_FILE_LINE_DC)
|
||||
{
|
||||
if (Z_REFCOUNTED_P(zvalue)) {
|
||||
if (Z_COPYABLE_P(zvalue)) {
|
||||
_zval_copy_ctor_func(zvalue ZEND_FILE_LINE_RELAY_CC);
|
||||
} else {
|
||||
Z_ADDREF_P(zvalue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline void _zval_opt_copy_ctor_no_imm(zval *zvalue ZEND_FILE_LINE_DC)
|
||||
{
|
||||
if (Z_OPT_REFCOUNTED_P(zvalue)) {
|
||||
if (Z_OPT_COPYABLE_P(zvalue)) {
|
||||
_zval_copy_ctor_func(zvalue ZEND_FILE_LINE_RELAY_CC);
|
||||
} else {
|
||||
Z_ADDREF_P(zvalue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API int zval_copy_static_var(zval *p TSRMLS_DC, int num_args, va_list args, zend_hash_key *key);
|
||||
|
||||
ZEND_API int zend_print_variable(zval *var TSRMLS_DC);
|
||||
@ -72,6 +94,8 @@ ZEND_API void _zval_internal_ptr_dtor(zval *zvalue ZEND_FILE_LINE_DC);
|
||||
ZEND_API void _zval_dtor_wrapper(zval *zvalue);
|
||||
#define zval_copy_ctor(zvalue) _zval_copy_ctor((zvalue) ZEND_FILE_LINE_CC)
|
||||
#define zval_opt_copy_ctor(zvalue) _zval_opt_copy_ctor((zvalue) ZEND_FILE_LINE_CC)
|
||||
#define zval_copy_ctor_no_imm(zvalue) _zval_copy_ctor_no_imm((zvalue) ZEND_FILE_LINE_CC)
|
||||
#define zval_opt_copy_ctor_no_imm(zvalue) _zval_opt_copy_ctor_no_imm((zvalue) ZEND_FILE_LINE_CC)
|
||||
#define zval_dtor(zvalue) _zval_dtor((zvalue) ZEND_FILE_LINE_CC)
|
||||
#define zval_ptr_dtor(zval_ptr) _zval_ptr_dtor((zval_ptr) ZEND_FILE_LINE_CC)
|
||||
#define zval_internal_dtor(zvalue) _zval_internal_dtor((zvalue) ZEND_FILE_LINE_CC)
|
||||
|
1994
Zend/zend_vm_def.h
1994
Zend/zend_vm_def.h
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -3,15 +3,11 @@
|
||||
ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *execute_data TSRMLS_DC)
|
||||
{
|
||||
DCL_OPLINE
|
||||
zend_bool original_in_execution;
|
||||
|
||||
{%HELPER_VARS%}
|
||||
|
||||
{%INTERNAL_LABELS%}
|
||||
|
||||
original_in_execution = EG(in_execution);
|
||||
EG(in_execution) = 1;
|
||||
|
||||
LOAD_REGS();
|
||||
LOAD_OPLINE();
|
||||
|
||||
@ -33,10 +29,22 @@ ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *execute_data TSRMLS_DC)
|
||||
|
||||
ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array, zval *return_value TSRMLS_DC)
|
||||
{
|
||||
zend_execute_data *execute_data;
|
||||
|
||||
if (EG(exception) != NULL) {
|
||||
return;
|
||||
}
|
||||
zend_{%EXECUTOR_NAME%}_ex(i_create_execute_data_from_op_array(op_array, return_value, EG(active_symbol_table) ? VM_FRAME_TOP_CODE : VM_FRAME_TOP_FUNCTION TSRMLS_CC) TSRMLS_CC);
|
||||
}
|
||||
|
||||
execute_data = zend_vm_stack_push_call_frame(
|
||||
(zend_function*)op_array, 0, 0, EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL, Z_OBJ(EG(This)), NULL TSRMLS_CC);
|
||||
if (EG(current_execute_data)) {
|
||||
execute_data->symbol_table = zend_rebuild_symbol_table(TSRMLS_C);
|
||||
} else {
|
||||
execute_data->symbol_table = &EG(symbol_table);
|
||||
}
|
||||
EX(prev_execute_data) = EG(current_execute_data);
|
||||
i_init_execute_data(execute_data, op_array, return_value, VM_FRAME_TOP_CODE TSRMLS_CC);
|
||||
zend_{%EXECUTOR_NAME%}_ex(execute_data TSRMLS_CC);
|
||||
}
|
||||
|
||||
{%EXTERNAL_EXECUTOR%}
|
||||
|
@ -914,10 +914,10 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
|
||||
out($f,"#define HANDLE_EXCEPTION() LOAD_OPLINE(); ZEND_VM_CONTINUE()\n");
|
||||
out($f,"#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()\n");
|
||||
out($f,"#define LOAD_REGS()\n");
|
||||
out($f,"#define ZEND_VM_CONTINUE() return 0\n");
|
||||
out($f,"#define ZEND_VM_RETURN() return 1\n");
|
||||
out($f,"#define ZEND_VM_ENTER() return 2\n");
|
||||
out($f,"#define ZEND_VM_LEAVE() return 3\n");
|
||||
out($f,"#define ZEND_VM_CONTINUE() return 0\n");
|
||||
out($f,"#define ZEND_VM_RETURN() return -1\n");
|
||||
out($f,"#define ZEND_VM_ENTER() return 1\n");
|
||||
out($f,"#define ZEND_VM_LEAVE() return 2\n");
|
||||
out($f,"#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n\n");
|
||||
out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n");
|
||||
break;
|
||||
@ -941,7 +941,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
|
||||
out($f,"#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()\n");
|
||||
out($f,"#define LOAD_REGS()\n");
|
||||
out($f,"#define ZEND_VM_CONTINUE() goto zend_vm_continue\n");
|
||||
out($f,"#define ZEND_VM_RETURN() EG(in_execution) = original_in_execution; return\n");
|
||||
out($f,"#define ZEND_VM_RETURN() return\n");
|
||||
out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n");
|
||||
out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n");
|
||||
out($f,"#define ZEND_VM_DISPATCH(opcode, opline) dispatch_handler = zend_vm_get_opcode_handler(opcode, opline); goto zend_vm_dispatch;\n\n");
|
||||
@ -973,7 +973,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
|
||||
}
|
||||
out($f,"#define LOAD_REGS()\n");
|
||||
out($f,"#define ZEND_VM_CONTINUE() goto *(void**)(OPLINE->handler)\n");
|
||||
out($f,"#define ZEND_VM_RETURN() EG(in_execution) = original_in_execution; return\n");
|
||||
out($f,"#define ZEND_VM_RETURN() return\n");
|
||||
out($f,"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n");
|
||||
out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n");
|
||||
out($f,"#define ZEND_VM_DISPATCH(opcode, opline) goto *(void**)(zend_vm_get_opcode_handler(opcode, opline));\n\n");
|
||||
@ -1028,7 +1028,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
|
||||
// Emit code that dispatches to opcode handler
|
||||
switch ($kind) {
|
||||
case ZEND_VM_KIND_CALL:
|
||||
out($f, $m[1]."if ((ret = OPLINE->handler(execute_data TSRMLS_CC)) > 0)".$m[3]."\n");
|
||||
out($f, $m[1]."if (UNEXPECTED((ret = OPLINE->handler(execute_data TSRMLS_CC)) != 0))".$m[3]."\n");
|
||||
break;
|
||||
case ZEND_VM_KIND_SWITCH:
|
||||
out($f, $m[1]."dispatch_handler = OPLINE->handler;\nzend_vm_dispatch:\n".$m[1]."switch ((int)dispatch_handler)".$m[3]."\n");
|
||||
@ -1041,16 +1041,10 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
|
||||
case "INTERNAL_EXECUTOR":
|
||||
if ($kind == ZEND_VM_KIND_CALL) {
|
||||
// Executor is defined as a set of functions
|
||||
out($f, $m[1]."switch (ret) {\n" .
|
||||
$m[1]."\tcase 1:\n" .
|
||||
$m[1]."\t\tEG(in_execution) = original_in_execution;\n".
|
||||
$m[1]."\t\treturn;\n".
|
||||
$m[1]."\tcase 2:\n" .
|
||||
$m[1]."\tcase 3:\n" .
|
||||
$m[1]."\t\texecute_data = EG(current_execute_data);\n".
|
||||
$m[1]."\t\tbreak;\n" .
|
||||
$m[1]."\tdefault:\n".
|
||||
$m[1]."\t\tbreak;\n".
|
||||
out($f, $m[1]."if (EXPECTED(ret > 0)) {\n" .
|
||||
$m[1]."\texecute_data = EG(current_execute_data);\n".
|
||||
$m[1]."} else {\n" .
|
||||
$m[1]."\treturn;\n".
|
||||
$m[1]."}".$m[3]."\n");
|
||||
} else {
|
||||
// Emit executor code
|
||||
@ -1416,10 +1410,10 @@ function gen_vm($def, $skel) {
|
||||
out($f,"#undef ZEND_VM_LEAVE\n");
|
||||
out($f,"#undef ZEND_VM_DISPATCH\n");
|
||||
out($f,"#undef ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL\n\n");
|
||||
out($f,"#define ZEND_VM_CONTINUE() return 0\n");
|
||||
out($f,"#define ZEND_VM_RETURN() return 1\n");
|
||||
out($f,"#define ZEND_VM_ENTER() return 2\n");
|
||||
out($f,"#define ZEND_VM_LEAVE() return 3\n");
|
||||
out($f,"#define ZEND_VM_CONTINUE() return 0\n");
|
||||
out($f,"#define ZEND_VM_RETURN() return -1\n");
|
||||
out($f,"#define ZEND_VM_ENTER() return 1\n");
|
||||
out($f,"#define ZEND_VM_LEAVE() return 2\n");
|
||||
out($f,"#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n\n");
|
||||
out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n\n");
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include <stdio.h>
|
||||
#include <zend.h>
|
||||
|
||||
const char *zend_vm_opcodes_map[168] = {
|
||||
const char *zend_vm_opcodes_map[169] = {
|
||||
"ZEND_NOP",
|
||||
"ZEND_ADD",
|
||||
"ZEND_SUB",
|
||||
@ -83,12 +83,12 @@ const char *zend_vm_opcodes_map[168] = {
|
||||
"ZEND_END_SILENCE",
|
||||
"ZEND_INIT_FCALL_BY_NAME",
|
||||
"ZEND_DO_FCALL",
|
||||
"ZEND_DO_FCALL_BY_NAME",
|
||||
"ZEND_INIT_FCALL",
|
||||
"ZEND_RETURN",
|
||||
"ZEND_RECV",
|
||||
"ZEND_RECV_INIT",
|
||||
"ZEND_SEND_VAL",
|
||||
"ZEND_SEND_VAR",
|
||||
"ZEND_SEND_VAR_EX",
|
||||
"ZEND_SEND_REF",
|
||||
"ZEND_NEW",
|
||||
"ZEND_INIT_NS_FCALL_BY_NAME",
|
||||
@ -138,14 +138,14 @@ const char *zend_vm_opcodes_map[168] = {
|
||||
"ZEND_INIT_STATIC_METHOD_CALL",
|
||||
"ZEND_ISSET_ISEMPTY_VAR",
|
||||
"ZEND_ISSET_ISEMPTY_DIM_OBJ",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
"ZEND_SEND_VAL_EX",
|
||||
"ZEND_SEND_VAR",
|
||||
"ZEND_INIT_USER_CALL",
|
||||
"ZEND_SEND_ARRAY",
|
||||
"ZEND_SEND_USER",
|
||||
"ZEND_STRLEN",
|
||||
"ZEND_DEFINED",
|
||||
"ZEND_TYPE_CHECK",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
@ -190,6 +190,7 @@ const char *zend_vm_opcodes_map[168] = {
|
||||
"ZEND_SEND_UNPACK",
|
||||
"ZEND_POW",
|
||||
"ZEND_ASSIGN_POW",
|
||||
"ZEND_BIND_GLOBAL",
|
||||
};
|
||||
|
||||
ZEND_API const char* zend_get_opcode_name(zend_uchar opcode) {
|
||||
|
@ -84,12 +84,12 @@ ZEND_API const char *zend_get_opcode_name(zend_uchar opcode);
|
||||
#define ZEND_END_SILENCE 58
|
||||
#define ZEND_INIT_FCALL_BY_NAME 59
|
||||
#define ZEND_DO_FCALL 60
|
||||
#define ZEND_DO_FCALL_BY_NAME 61
|
||||
#define ZEND_INIT_FCALL 61
|
||||
#define ZEND_RETURN 62
|
||||
#define ZEND_RECV 63
|
||||
#define ZEND_RECV_INIT 64
|
||||
#define ZEND_SEND_VAL 65
|
||||
#define ZEND_SEND_VAR 66
|
||||
#define ZEND_SEND_VAR_EX 66
|
||||
#define ZEND_SEND_REF 67
|
||||
#define ZEND_NEW 68
|
||||
#define ZEND_INIT_NS_FCALL_BY_NAME 69
|
||||
@ -139,6 +139,14 @@ ZEND_API const char *zend_get_opcode_name(zend_uchar opcode);
|
||||
#define ZEND_INIT_STATIC_METHOD_CALL 113
|
||||
#define ZEND_ISSET_ISEMPTY_VAR 114
|
||||
#define ZEND_ISSET_ISEMPTY_DIM_OBJ 115
|
||||
#define ZEND_SEND_VAL_EX 116
|
||||
#define ZEND_SEND_VAR 117
|
||||
#define ZEND_INIT_USER_CALL 118
|
||||
#define ZEND_SEND_ARRAY 119
|
||||
#define ZEND_SEND_USER 120
|
||||
#define ZEND_STRLEN 121
|
||||
#define ZEND_DEFINED 122
|
||||
#define ZEND_TYPE_CHECK 123
|
||||
#define ZEND_PRE_INC_OBJ 132
|
||||
#define ZEND_PRE_DEC_OBJ 133
|
||||
#define ZEND_POST_INC_OBJ 134
|
||||
@ -173,5 +181,6 @@ ZEND_API const char *zend_get_opcode_name(zend_uchar opcode);
|
||||
#define ZEND_SEND_UNPACK 165
|
||||
#define ZEND_POW 166
|
||||
#define ZEND_ASSIGN_POW 167
|
||||
#define ZEND_BIND_GLOBAL 168
|
||||
|
||||
#endif
|
||||
|
@ -1711,7 +1711,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
FILE *fp;
|
||||
long position;
|
||||
char *filename = "/tmp/phpglibccheck";
|
||||
char *filename = tmpnam(NULL);
|
||||
|
||||
fp = fopen(filename, "w");
|
||||
if (fp == NULL) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
# +----------------------------------------------------------------------+
|
||||
# | PHP Version 5 |
|
||||
# +----------------------------------------------------------------------+
|
||||
# | Copyright (c) 1997-2006 The PHP Group |
|
||||
# | Copyright (c) 1997-2014 The PHP Group |
|
||||
# +----------------------------------------------------------------------+
|
||||
# | This source file is subject to version 3.01 of the PHP license, |
|
||||
# | that is bundled with this package in the file LICENSE, and is |
|
||||
@ -14,8 +14,6 @@
|
||||
# | Author: Sascha Schumann <sascha@schumann.cx> |
|
||||
# +----------------------------------------------------------------------+
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
#
|
||||
# Makefile to generate build tools
|
||||
#
|
||||
@ -61,16 +59,6 @@ snapshot:
|
||||
md5sum $$distname.tar.bz2; \
|
||||
bzip2 -t $$distname.tar.bz2
|
||||
|
||||
cvsclean-work:
|
||||
@for i in `find . -name .cvsignore`; do \
|
||||
(cd `dirname $$i` 2>/dev/null && rm -rf `cat .cvsignore | grep -v config.nice | sed 's/[[:space:]]/ /g'` *.o *.a *.lo *.la *.gcno *.gcda .libs || true); \
|
||||
done
|
||||
|
||||
svnclean-work:
|
||||
@for i in `find . -type d ! -path '*/.svn/*' | grep -v '.svn'`; do \
|
||||
(cd $$i 2>/dev/null && rm -rf `svn propget svn:ignore . | grep -v config.nice` *.o *.a *.lo *.la *.gcno *.gcda .libs || true); \
|
||||
done
|
||||
|
||||
gitclean-work:
|
||||
@if (test ! -f '.git/info/exclude' || grep -s "git-ls-files" .git/info/exclude); then \
|
||||
(echo "Rebuild .git/info/exclude" && echo '*.o' > .git/info/exclude && git svn propget svn:ignore | grep -v config.nice >> .git/info/exclude); \
|
||||
|
8
build/libtool.m4
vendored
8
build/libtool.m4
vendored
@ -1532,10 +1532,6 @@ dgux*)
|
||||
shlibpath_var=LD_LIBRARY_PATH
|
||||
;;
|
||||
|
||||
freebsd1*)
|
||||
dynamic_linker=no
|
||||
;;
|
||||
|
||||
freebsd* | dragonfly*)
|
||||
# DragonFly does not have aout. When/if they implement a new
|
||||
# versioning mechanism, adjust this.
|
||||
@ -5843,10 +5839,6 @@ _LT_EOF
|
||||
_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
|
||||
;;
|
||||
|
||||
freebsd1*)
|
||||
_LT_AC_TAGVAR(ld_shlibs, $1)=no
|
||||
;;
|
||||
|
||||
# FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
|
||||
# support. Future versions do this automatically, but an explicit c++rt0.o
|
||||
# does not break anything, and helps significantly (at the cost of a little
|
||||
|
@ -199,12 +199,11 @@ PHP_FUNCTION(curl_multi_exec)
|
||||
int still_running;
|
||||
int result;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &z_mh, &z_still_running) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz/", &z_mh, &z_still_running) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
ZEND_FETCH_RESOURCE(mh, php_curlm *, z_mh, -1, le_curl_multi_handle_name, le_curl_multi_handle);
|
||||
ZVAL_DEREF(z_still_running);
|
||||
|
||||
{
|
||||
zend_llist_position pos;
|
||||
@ -260,7 +259,7 @@ PHP_FUNCTION(curl_multi_info_read)
|
||||
int queued_msgs;
|
||||
zval *zmsgs_in_queue = NULL;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|z", &z_mh, &zmsgs_in_queue) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|z/", &z_mh, &zmsgs_in_queue) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2013 The PHP Group |
|
||||
| Copyright (c) 1997-2014 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -50,7 +50,11 @@ static inline long long php_date_llabs( long long i ) { return i >= 0 ? i : -i;
|
||||
int st = snprintf(s, len, "%lld", i); \
|
||||
s[st] = '\0'; \
|
||||
} while (0);
|
||||
#ifdef HAVE_ATOLL
|
||||
# define DATE_A64I(i, s) i = atoll(s)
|
||||
#else
|
||||
# define DATE_A64I(i, s) i = strtoll(s, NULL, 10)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* {{{ arginfo */
|
||||
@ -638,10 +642,10 @@ static HashTable *date_object_get_properties_period(zval *object TSRMLS_DC);
|
||||
static HashTable *date_object_get_properties_timezone(zval *object TSRMLS_DC);
|
||||
static HashTable *date_object_get_gc_timezone(zval *object, zval **table, int *n TSRMLS_DC);
|
||||
|
||||
zval *date_interval_read_property(zval *object, zval *member, int type, zend_uint cache_slot, zval *rv TSRMLS_DC);
|
||||
void date_interval_write_property(zval *object, zval *member, zval *value, zend_uint cache_slot TSRMLS_DC);
|
||||
static zval *date_period_read_property(zval *object, zval *member, int type, zend_uint cache_slot, zval *rv TSRMLS_DC);
|
||||
static void date_period_write_property(zval *object, zval *member, zval *value, zend_uint cache_slot TSRMLS_DC);
|
||||
zval *date_interval_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv TSRMLS_DC);
|
||||
void date_interval_write_property(zval *object, zval *member, zval *value, void **cache_slot TSRMLS_DC);
|
||||
static zval *date_period_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv TSRMLS_DC);
|
||||
static void date_period_write_property(zval *object, zval *member, zval *value, void **cache_slot TSRMLS_DC);
|
||||
|
||||
/* {{{ Module struct */
|
||||
zend_module_entry date_module_entry = {
|
||||
@ -2529,6 +2533,8 @@ PHPAPI int php_date_initialize(php_date_obj *dateobj, /*const*/ char *time_str,
|
||||
err->error_messages[0].position, err->error_messages[0].character, err->error_messages[0].message);
|
||||
}
|
||||
if (err && err->error_count) {
|
||||
timelib_time_dtor(dateobj->time);
|
||||
dateobj->time = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2681,7 +2687,7 @@ PHP_METHOD(DateTime, __construct)
|
||||
zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC);
|
||||
if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sO!", &time_str, &time_str_len, &timezone_object, date_ce_timezone)) {
|
||||
if (!php_date_initialize(Z_PHPDATE_P(getThis()), time_str, time_str_len, NULL, timezone_object, 1 TSRMLS_CC)) {
|
||||
//??? ZVAL_NULL(getThis());
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
}
|
||||
}
|
||||
zend_restore_error_handling(&error_handling TSRMLS_CC);
|
||||
@ -3959,7 +3965,7 @@ static int date_interval_initialize(timelib_rel_time **rt, /*const*/ char *forma
|
||||
} /* }}} */
|
||||
|
||||
/* {{{ date_interval_read_property */
|
||||
zval *date_interval_read_property(zval *object, zval *member, int type, zend_uint cache_slot, zval *rv TSRMLS_DC)
|
||||
zval *date_interval_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv TSRMLS_DC)
|
||||
{
|
||||
php_interval_obj *obj;
|
||||
zval *retval;
|
||||
@ -3971,7 +3977,7 @@ zval *date_interval_read_property(zval *object, zval *member, int type, zend_uin
|
||||
zval_copy_ctor(&tmp_member);
|
||||
convert_to_string(&tmp_member);
|
||||
member = &tmp_member;
|
||||
cache_slot = -1;
|
||||
cache_slot = NULL;
|
||||
}
|
||||
|
||||
obj = Z_PHPINTERVAL_P(object);
|
||||
@ -4025,7 +4031,7 @@ zval *date_interval_read_property(zval *object, zval *member, int type, zend_uin
|
||||
/* }}} */
|
||||
|
||||
/* {{{ date_interval_write_property */
|
||||
void date_interval_write_property(zval *object, zval *member, zval *value, zend_uint cache_slot TSRMLS_DC)
|
||||
void date_interval_write_property(zval *object, zval *member, zval *value, void **cache_slot TSRMLS_DC)
|
||||
{
|
||||
php_interval_obj *obj;
|
||||
zval tmp_member;
|
||||
@ -4035,7 +4041,7 @@ void date_interval_write_property(zval *object, zval *member, zval *value, zend_
|
||||
zval_copy_ctor(&tmp_member);
|
||||
convert_to_string(&tmp_member);
|
||||
member = &tmp_member;
|
||||
cache_slot = -1;
|
||||
cache_slot = NULL;
|
||||
}
|
||||
|
||||
obj = Z_PHPINTERVAL_P(object);
|
||||
@ -4942,7 +4948,7 @@ PHP_METHOD(DatePeriod, __wakeup)
|
||||
/* }}} */
|
||||
|
||||
/* {{{ date_period_read_property */
|
||||
static zval *date_period_read_property(zval *object, zval *member, int type, zend_uint cache_slot, zval *rv TSRMLS_DC)
|
||||
static zval *date_period_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv TSRMLS_DC)
|
||||
{
|
||||
zval *zv;
|
||||
if (type != BP_VAR_IS && type != BP_VAR_R) {
|
||||
@ -4962,7 +4968,7 @@ static zval *date_period_read_property(zval *object, zval *member, int type, zen
|
||||
/* }}} */
|
||||
|
||||
/* {{{ date_period_write_property */
|
||||
static void date_period_write_property(zval *object, zval *member, zval *value, zend_uint cache_slot TSRMLS_DC)
|
||||
static void date_period_write_property(zval *object, zval *member, zval *value, void **cache_slot TSRMLS_DC)
|
||||
{
|
||||
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Writing to DatePeriod properties is unsupported");
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ array(12) {
|
||||
bool(false)
|
||||
object(DateTime)#1 (3) {
|
||||
["date"]=>
|
||||
string(20) "-0001-11-30 00:00:00.000000"
|
||||
string(27) "-0001-11-30 00:00:00.000000"
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
|
@ -1,5 +1,5 @@
|
||||
--TEST--
|
||||
Bug #67118 php-cgi crashes regularly on IIS 7
|
||||
Bug #67118 crashes in DateTime when this used after failed __construct
|
||||
--INI--
|
||||
date.timezone=Europe/Berlin
|
||||
--FILE--
|
||||
@ -11,17 +11,16 @@ class mydt extends datetime
|
||||
if (!empty($tz) && !is_object($tz)) {
|
||||
$tz = new DateTimeZone($tz);
|
||||
}
|
||||
|
||||
@parent::__construct($time, $tz);
|
||||
try {
|
||||
@parent::__construct($time, $tz);
|
||||
} catch (Exception $e) {
|
||||
echo "Bad date" . $this->format("Y") . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
new mydt("Funktionsansvarig rådgivning och juridik", "UTC");
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught exception 'Exception' with message 'DateTime::__construct(): Failed to parse time string (Funktionsansvarig rådgivning och juridik) at position 0 (F): The timezone could not be found in the database' in %sbug67118.php:%d
|
||||
Stack trace:
|
||||
#0 %sbug67118.php(%d): DateTime->__construct('Funktionsansvar...', Object(DateTimeZone))
|
||||
#1 %sbug67118.php(%d): mydt->__construct('Funktionsansvar...', 'UTC')
|
||||
#2 {main}
|
||||
thrown in %sbug67118.php on line %d
|
||||
Fatal error: Call to a member function format() on null in %sbug67118.php on line %d
|
||||
|
28
ext/date/tests/bug67118_2.phpt
Normal file
28
ext/date/tests/bug67118_2.phpt
Normal file
@ -0,0 +1,28 @@
|
||||
--TEST--
|
||||
Regression introduce in fix for Bug #67118 - Invalid code
|
||||
--INI--
|
||||
date.timezone=Europe/Paris
|
||||
--FILE--
|
||||
<?php
|
||||
class Foo extends DateTime {
|
||||
public function __construct($time = null) {
|
||||
$tz = new DateTimeZone('UTC');
|
||||
try {
|
||||
echo "First try\n";
|
||||
parent::__construct($time, $tz);
|
||||
return;
|
||||
} catch (Exception $e) {
|
||||
echo "Second try\n";
|
||||
parent::__construct($time.'C', $tz);
|
||||
}
|
||||
}
|
||||
}
|
||||
$date = '12 Sep 2007 15:49:12 UT';
|
||||
var_dump(new Foo($date));
|
||||
?>
|
||||
Done
|
||||
--EXPECTF--
|
||||
First try
|
||||
Second try
|
||||
NULL
|
||||
Done
|
@ -310,7 +310,7 @@ static void dom_register_prop_handler(HashTable *prop_handler, char *name, dom_r
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zval *dom_get_property_ptr_ptr(zval *object, zval *member, int type, zend_uint cache_slot TSRMLS_DC) /* {{{ */
|
||||
static zval *dom_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
dom_object *obj = Z_DOMOBJ_P(object);
|
||||
zend_string *member_str = zval_get_string(member);
|
||||
@ -327,7 +327,7 @@ static zval *dom_get_property_ptr_ptr(zval *object, zval *member, int type, zend
|
||||
/* }}} */
|
||||
|
||||
/* {{{ dom_read_property */
|
||||
zval *dom_read_property(zval *object, zval *member, int type, zend_uint cache_slot, zval *rv TSRMLS_DC)
|
||||
zval *dom_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv TSRMLS_DC)
|
||||
{
|
||||
dom_object *obj = Z_DOMOBJ_P(object);
|
||||
zend_string *member_str = zval_get_string(member);
|
||||
@ -358,7 +358,7 @@ zval *dom_read_property(zval *object, zval *member, int type, zend_uint cache_sl
|
||||
/* }}} */
|
||||
|
||||
/* {{{ dom_write_property */
|
||||
void dom_write_property(zval *object, zval *member, zval *value, zend_uint cache_slot TSRMLS_DC)
|
||||
void dom_write_property(zval *object, zval *member, zval *value, void **cache_slot TSRMLS_DC)
|
||||
{
|
||||
dom_object *obj = Z_DOMOBJ_P(object);
|
||||
zend_string *member_str = zval_get_string(member);
|
||||
@ -379,7 +379,7 @@ void dom_write_property(zval *object, zval *member, zval *value, zend_uint cache
|
||||
/* }}} */
|
||||
|
||||
/* {{{ dom_property_exists */
|
||||
static int dom_property_exists(zval *object, zval *member, int check_empty, zend_uint cache_slot TSRMLS_DC)
|
||||
static int dom_property_exists(zval *object, zval *member, int check_empty, void **cache_slot TSRMLS_DC)
|
||||
{
|
||||
dom_object *obj = Z_DOMOBJ_P(object);
|
||||
zend_string *member_str = zval_get_string(member);
|
||||
|
@ -12,6 +12,7 @@ require_once dirname(__FILE__) .'/skipif.inc';
|
||||
// reusing existing xml: http://cvs.php.net/viewvc.cgi/php-src/ext/dom/tests/dom.xml?view=co&content-type=text%2Fplain
|
||||
// reusing existing dtd: http://cvs.php.net/viewvc.cgi/php-src/ext/dom/tests/dom.ent?view=co&content-type=text%2Fplain
|
||||
$dom = new DOMDocument('1.0');
|
||||
$dom->substituteEntities = true;
|
||||
$dom->load(dirname(__FILE__).'/dom.xml');
|
||||
var_dump($dom->validate());
|
||||
?>
|
||||
|
@ -7,18 +7,22 @@ require_once('skipif.inc');
|
||||
--FILE--
|
||||
<?php
|
||||
$domDocument = new DOMDocument();
|
||||
$domDocument->substituteEntities = true;
|
||||
$domDocument->load(dirname(__FILE__) . DIRECTORY_SEPARATOR . "bug67081_0.xml");
|
||||
var_dump($domDocument->doctype->internalSubset);
|
||||
|
||||
$domDocument = new DOMDocument();
|
||||
$domDocument->substituteEntities = true;
|
||||
$domDocument->load(dirname(__FILE__) . DIRECTORY_SEPARATOR . "bug67081_1.xml");
|
||||
var_dump($domDocument->doctype->internalSubset);
|
||||
|
||||
$domDocument = new DOMDocument();
|
||||
$domDocument->substituteEntities = true;
|
||||
$domDocument->load(dirname(__FILE__) . DIRECTORY_SEPARATOR . "bug67081_2.xml");
|
||||
var_dump($domDocument->doctype->internalSubset);
|
||||
|
||||
$domDocument = new DOMDocument();
|
||||
$domDocument->substituteEntities = true;
|
||||
$domDocument->load(dirname(__FILE__) . DIRECTORY_SEPARATOR . "dom.xml");
|
||||
var_dump($domDocument->doctype->internalSubset);
|
||||
?>
|
||||
|
@ -486,7 +486,7 @@ PHP_FUNCTION(enchant_broker_get_dict_path)
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
RETURN_STRING(value, 1);
|
||||
RETURN_STRING(value);
|
||||
}
|
||||
/* }}} */
|
||||
#else
|
||||
|
@ -305,7 +305,7 @@ static void php_ereg(INTERNAL_FUNCTION_PARAMETERS, int icase)
|
||||
char *string = NULL;
|
||||
int argc = ZEND_NUM_ARGS();
|
||||
|
||||
if (zend_parse_parameters(argc TSRMLS_CC, "zs|z", ®ex, &findin, &findin_len, &array) == FAILURE) {
|
||||
if (zend_parse_parameters(argc TSRMLS_CC, "zs|z/", ®ex, &findin, &findin_len, &array) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -351,10 +351,6 @@ static void php_ereg(INTERNAL_FUNCTION_PARAMETERS, int icase)
|
||||
}
|
||||
match_len = 1;
|
||||
|
||||
if (array) {
|
||||
ZVAL_DEREF(array);
|
||||
}
|
||||
|
||||
if (array && err != REG_NOMATCH) {
|
||||
match_len = (int) (subs[0].rm_eo - subs[0].rm_so);
|
||||
string_len = findin_len + 1;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user