mirror of
https://github.com/php/php-src.git
synced 2024-11-23 18:04:36 +08:00
LSB parent/self forwarding
This commit is contained in:
parent
6895773aff
commit
feb8580166
@ -51,4 +51,4 @@ ok
|
||||
__callstatic:
|
||||
string(3) "www"
|
||||
|
||||
Fatal error: Cannot access self:: when no class scope is active in %s on line %d
|
||||
Warning: call_user_func() expects parameter 1 to be a valid callback, cannot access self:: when no class scope is active in %sbug45186.php on line 31
|
||||
|
@ -47,4 +47,4 @@ ok
|
||||
|
||||
Warning: call_user_func() expects parameter 1 to be a valid callback, class 'bar' does not have a method 'www' in %s on line %d
|
||||
|
||||
Fatal error: Cannot access self:: when no class scope is active in %s on line %d
|
||||
Warning: call_user_func() expects parameter 1 to be a valid callback, cannot access self:: when no class scope is active in %sbug45186_2.php on line 27
|
||||
|
@ -86,7 +86,7 @@ A
|
||||
B
|
||||
B
|
||||
B
|
||||
A
|
||||
A
|
||||
B
|
||||
B
|
||||
B
|
||||
==DONE==
|
||||
|
@ -1,5 +1,5 @@
|
||||
--TEST--
|
||||
Test LSB of properties and methods declared as protected and overridden as public.
|
||||
ZE2 Late Static Binding properties and methods declared as protected and overridden as public.
|
||||
--FILE--
|
||||
<?php
|
||||
class TestClass {
|
||||
@ -45,4 +45,4 @@ TestClassFunction
|
||||
ChildClassStatic
|
||||
ChildClassFunction
|
||||
TestClassStatic
|
||||
TestClassFunction
|
||||
TestClassFunction
|
||||
|
@ -1,5 +1,5 @@
|
||||
--TEST--
|
||||
Test LSB of properties and methods declared as public and overridden as public.
|
||||
ZE2 Late Static Binding properties and methods declared as public and overridden as public.
|
||||
--FILE--
|
||||
<?php
|
||||
class TestClass {
|
||||
@ -45,4 +45,4 @@ TestClassFunction
|
||||
ChildClassStatic
|
||||
ChildClassFunction
|
||||
TestClassStatic
|
||||
TestClassFunction
|
||||
TestClassFunction
|
||||
|
50
Zend/tests/lsb_021.phpt
Normal file
50
Zend/tests/lsb_021.phpt
Normal file
@ -0,0 +1,50 @@
|
||||
--TEST--
|
||||
ZE2 Late Static Binding parent::/self:: forwarding while classname doesn't
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
public static function test() {
|
||||
echo get_called_class()."\n";
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
public static function testForward() {
|
||||
parent::test();
|
||||
call_user_func("parent::test");
|
||||
call_user_func(array("parent", "test"));
|
||||
self::test();
|
||||
call_user_func("self::test");
|
||||
call_user_func(array("self", "test"));
|
||||
}
|
||||
public static function testNoForward() {
|
||||
A::test();
|
||||
call_user_func("A::test");
|
||||
call_user_func(array("A", "test"));
|
||||
B::test();
|
||||
call_user_func("B::test");
|
||||
call_user_func(array("B", "test"));
|
||||
}
|
||||
}
|
||||
|
||||
class C extends B {
|
||||
|
||||
}
|
||||
|
||||
C::testForward();
|
||||
C::testNoForward();
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
C
|
||||
C
|
||||
C
|
||||
C
|
||||
C
|
||||
C
|
||||
A
|
||||
A
|
||||
A
|
||||
B
|
||||
B
|
||||
B
|
31
Zend/tests/lsb_022.phpt
Executable file
31
Zend/tests/lsb_022.phpt
Executable file
@ -0,0 +1,31 @@
|
||||
--TEST--
|
||||
ZE2 Late Static Binding parent::/self:: forwarding and __callStatic
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
static function test() {
|
||||
echo "A\n";
|
||||
}
|
||||
static function __callstatic($name, $args) {
|
||||
call_user_func("static::test");
|
||||
}
|
||||
}
|
||||
class B extends A {
|
||||
static function test() {
|
||||
echo "B\n";
|
||||
}
|
||||
static function __callstatic($name, $args) {
|
||||
parent::__callstatic($name, $args);
|
||||
call_user_func_array("parent::__callstatic", array($name, $args));
|
||||
parent::foo();
|
||||
call_user_func_array("parent::foo", $args);
|
||||
call_user_func_array(array("parent","foo"), $args);
|
||||
}
|
||||
}
|
||||
B::foo();
|
||||
--EXPECT--
|
||||
B
|
||||
B
|
||||
B
|
||||
B
|
||||
B
|
@ -30,7 +30,7 @@ object(foo)#%d (0) {
|
||||
Strict Standards: Non-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(bar)#%d (0) {
|
||||
object(foo)#%d (0) {
|
||||
}
|
||||
object(foo)#%d (0) {
|
||||
}
|
||||
@ -40,7 +40,7 @@ Strict Standards: call_user_func() expects parameter 1 to be a valid callback, n
|
||||
Strict Standards: Non-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(bar)#%d (0) {
|
||||
object(foo)#%d (0) {
|
||||
}
|
||||
|
||||
|
||||
|
258
Zend/zend_API.c
258
Zend/zend_API.c
@ -2305,21 +2305,69 @@ ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, zend_class_entry *ce_org, zval *callable, zend_class_entry **ce_ptr, zend_function **fptr_ptr, char **error TSRMLS_DC) /* {{{ */
|
||||
static int zend_is_callable_check_class(char *name, int name_len, zend_fcall_info_cache *fcc, char **error TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
int ret = 0;
|
||||
zend_class_entry **pce;
|
||||
char *lcname = zend_str_tolower_dup(name, name_len);
|
||||
|
||||
if (name_len == sizeof("self") - 1 &&
|
||||
!memcmp(lcname, "self", sizeof("self") - 1)) {
|
||||
if (!EG(scope)) {
|
||||
if (error) *error = estrdup("cannot access self:: when no class scope is active");
|
||||
} else {
|
||||
fcc->called_scope = EG(called_scope);
|
||||
fcc->calling_scope = EG(scope);
|
||||
ret = 1;
|
||||
}
|
||||
} else if (name_len == sizeof("parent") - 1 &&
|
||||
!memcmp(lcname, "parent", sizeof("parent") - 1)) {
|
||||
if (!EG(scope)) {
|
||||
if (error) *error = estrdup("cannot access parent:: when no class scope is active");
|
||||
} 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->calling_scope = EG(scope)->parent;
|
||||
ret = 1;
|
||||
}
|
||||
} else if (name_len == sizeof("static") - 1 &&
|
||||
!memcmp(lcname, "static", sizeof("static") - 1)) {
|
||||
if (!EG(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);
|
||||
ret = 1;
|
||||
}
|
||||
} else if (zend_lookup_class_ex(name, name_len, 1, &pce TSRMLS_CC) == SUCCESS) {
|
||||
fcc->called_scope = fcc->calling_scope = *pce;
|
||||
ret = 1;
|
||||
} else {
|
||||
if (error) zend_spprintf(error, 0, "class '%.*s' not found", name_len, name);
|
||||
}
|
||||
efree(lcname);
|
||||
return ret;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fcall_info_cache *fcc, char **error TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_class_entry *ce_org = fcc->calling_scope;
|
||||
int retval;
|
||||
char *lmname, *colon;
|
||||
int clen, mlen;
|
||||
zend_function *fptr;
|
||||
zend_class_entry *last_scope;
|
||||
HashTable *ftable;
|
||||
int call_via_handler = 0;
|
||||
|
||||
if (error) {
|
||||
*error = NULL;
|
||||
}
|
||||
|
||||
*ce_ptr = NULL;
|
||||
*fptr_ptr = NULL;
|
||||
fcc->calling_scope = NULL;
|
||||
fcc->function_handler = NULL;
|
||||
|
||||
if (!ce_org) {
|
||||
/* Skip leading :: */
|
||||
@ -2334,8 +2382,7 @@ static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, ze
|
||||
}
|
||||
/* Check if function with given name exists.
|
||||
* This may be a compound name that includes namespace name */
|
||||
if (zend_hash_find(EG(function_table), lmname, mlen+1, (void**)&fptr) == SUCCESS) {
|
||||
*fptr_ptr = fptr;
|
||||
if (zend_hash_find(EG(function_table), lmname, mlen+1, (void**)&fcc->function_handler) == SUCCESS) {
|
||||
efree(lmname);
|
||||
return 1;
|
||||
}
|
||||
@ -2363,15 +2410,16 @@ static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, ze
|
||||
if (ce_org) {
|
||||
EG(scope) = ce_org;
|
||||
}
|
||||
*ce_ptr = zend_fetch_class(Z_STRVAL_P(callable), clen, ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_SILENT TSRMLS_CC);
|
||||
EG(scope) = last_scope;
|
||||
if (!*ce_ptr) {
|
||||
if (error) zend_spprintf(error, 0, "class '%.*Z' not found", clen, callable);
|
||||
|
||||
if (!zend_is_callable_check_class(Z_STRVAL_P(callable), clen, fcc, error TSRMLS_CC)) {
|
||||
EG(scope) = last_scope;
|
||||
return 0;
|
||||
}
|
||||
ftable = &(*ce_ptr)->function_table;
|
||||
if (ce_org && !instanceof_function(ce_org, *ce_ptr TSRMLS_CC)) {
|
||||
if (error) zend_spprintf(error, 0, "class '%s' is not a subclass of '%s'", ce_org->name, (*ce_ptr)->name);
|
||||
EG(scope) = last_scope;
|
||||
|
||||
ftable = &fcc->calling_scope->function_table;
|
||||
if (ce_org && !instanceof_function(ce_org, fcc->calling_scope TSRMLS_CC)) {
|
||||
if (error) zend_spprintf(error, 0, "class '%s' is not a subclass of '%s'", ce_org->name, fcc->calling_scope->name);
|
||||
return 0;
|
||||
}
|
||||
lmname = zend_str_tolower_dup(Z_STRVAL_P(callable) + clen + 2, mlen);
|
||||
@ -2380,49 +2428,51 @@ static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, ze
|
||||
mlen = Z_STRLEN_P(callable);
|
||||
lmname = zend_str_tolower_dup(Z_STRVAL_P(callable), Z_STRLEN_P(callable));
|
||||
ftable = &ce_org->function_table;
|
||||
*ce_ptr = ce_org;
|
||||
fcc->calling_scope = ce_org;
|
||||
} else {
|
||||
/* We already checked for plain function before. */
|
||||
if (error) zend_spprintf(error, 0, "function '%s' not found or invalid function name", Z_STRVAL_P(callable));
|
||||
return 0;
|
||||
}
|
||||
|
||||
retval = zend_hash_find(ftable, lmname, mlen+1, (void**)&fptr) == SUCCESS ? 1 : 0;
|
||||
retval = zend_hash_find(ftable, lmname, mlen+1, (void**)&fcc->function_handler) == SUCCESS ? 1 : 0;
|
||||
|
||||
if (!retval) {
|
||||
if (*zobj_ptr_ptr && *ce_ptr && (*ce_ptr)->__call != 0) {
|
||||
retval = (*ce_ptr)->__call != NULL;
|
||||
*fptr_ptr = (*ce_ptr)->__call;
|
||||
if (fcc->object_pp && fcc->calling_scope && fcc->calling_scope->__call != 0) {
|
||||
retval = 1;
|
||||
call_via_handler = 1;
|
||||
fcc->function_handler = fcc->calling_scope->__call;
|
||||
} else {
|
||||
if (!*zobj_ptr_ptr && *ce_ptr && ((*ce_ptr)->__callstatic || (*ce_ptr)->__call)) {
|
||||
if ((*ce_ptr)->__call &&
|
||||
if (!fcc->object_pp && fcc->calling_scope && (fcc->calling_scope->__callstatic || fcc->calling_scope->__call)) {
|
||||
if (fcc->calling_scope->__call &&
|
||||
EG(This) &&
|
||||
Z_OBJ_HT_P(EG(This))->get_class_entry &&
|
||||
instanceof_function(Z_OBJCE_P(EG(This)), *ce_ptr TSRMLS_CC)) {
|
||||
instanceof_function(Z_OBJCE_P(EG(This)), fcc->calling_scope TSRMLS_CC)) {
|
||||
retval = 1;
|
||||
*fptr_ptr = (*ce_ptr)->__call;
|
||||
*zobj_ptr_ptr = &EG(This);
|
||||
} else if ((*ce_ptr)->__callstatic) {
|
||||
call_via_handler = 1;
|
||||
fcc->function_handler = fcc->calling_scope->__call;
|
||||
fcc->object_pp = &EG(This);
|
||||
} else if (fcc->calling_scope->__callstatic) {
|
||||
retval = 1;
|
||||
*fptr_ptr = (*ce_ptr)->__callstatic;
|
||||
call_via_handler = 1;
|
||||
fcc->function_handler = fcc->calling_scope->__callstatic;
|
||||
}
|
||||
}
|
||||
|
||||
if (retval == 0) {
|
||||
if (*ce_ptr) {
|
||||
if (error) zend_spprintf(error, 0, "class '%s' does not have a method '%s'", (*ce_ptr)->name, lmname);
|
||||
if (fcc->calling_scope) {
|
||||
if (error) zend_spprintf(error, 0, "class '%s' does not have a method '%s'", fcc->calling_scope->name, lmname);
|
||||
} else {
|
||||
if (error) zend_spprintf(error, 0, "function '%s' does not exist", lmname);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*fptr_ptr = fptr;
|
||||
if (*ce_ptr) {
|
||||
if (!*zobj_ptr_ptr && !(fptr->common.fn_flags & ZEND_ACC_STATIC)) {
|
||||
if (fcc->calling_scope) {
|
||||
if (!fcc->object_pp && !(fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) {
|
||||
int severity;
|
||||
char *verb;
|
||||
if (fptr->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
||||
if (fcc->function_handler->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
||||
severity = E_STRICT;
|
||||
verb = "should not";
|
||||
} else {
|
||||
@ -2433,39 +2483,39 @@ static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, ze
|
||||
if ((check_flags & IS_CALLABLE_CHECK_IS_STATIC) != 0) {
|
||||
retval = 0;
|
||||
}
|
||||
if (EG(This) && instanceof_function(Z_OBJCE_P(EG(This)), *ce_ptr TSRMLS_CC)) {
|
||||
*zobj_ptr_ptr = &EG(This);
|
||||
if (EG(This) && instanceof_function(Z_OBJCE_P(EG(This)), fcc->calling_scope TSRMLS_CC)) {
|
||||
fcc->object_pp = &EG(This);
|
||||
if (error) {
|
||||
zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically, assuming $this from compatible context %s", (*ce_ptr)->name, fptr->common.function_name, verb, Z_OBJCE_P(EG(This))->name);
|
||||
zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically, assuming $this from compatible context %s", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb, Z_OBJCE_P(EG(This))->name);
|
||||
} else if (retval) {
|
||||
zend_error(severity, "Non-static method %s::%s() %s be called statically, assuming $this from compatible context %s", (*ce_ptr)->name, fptr->common.function_name, verb, Z_OBJCE_P(EG(This))->name);
|
||||
zend_error(severity, "Non-static method %s::%s() %s be called statically, assuming $this from compatible context %s", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb, Z_OBJCE_P(EG(This))->name);
|
||||
}
|
||||
} else {
|
||||
if (error) {
|
||||
zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically", (*ce_ptr)->name, fptr->common.function_name, verb);
|
||||
zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb);
|
||||
} else if (retval) {
|
||||
zend_error(severity, "Non-static method %s::%s() %s be called statically", (*ce_ptr)->name, fptr->common.function_name, verb);
|
||||
zend_error(severity, "Non-static method %s::%s() %s be called statically", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (retval && (check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0) {
|
||||
if (fptr->op_array.fn_flags & ZEND_ACC_PRIVATE) {
|
||||
if (!zend_check_private(fptr, *zobj_ptr_ptr ? Z_OBJCE_PP(*zobj_ptr_ptr) : EG(scope), lmname, mlen TSRMLS_CC)) {
|
||||
if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
|
||||
if (!zend_check_private(fcc->function_handler, fcc->object_pp ? Z_OBJCE_PP(fcc->object_pp) : EG(scope), lmname, mlen TSRMLS_CC)) {
|
||||
if (error) {
|
||||
if (*error) {
|
||||
efree(*error);
|
||||
}
|
||||
zend_spprintf(error, 0, "cannot access private method %s::%s()", (*ce_ptr)->name, fptr->common.function_name);
|
||||
zend_spprintf(error, 0, "cannot access private method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
|
||||
}
|
||||
retval = 0;
|
||||
}
|
||||
} else if ((fptr->common.fn_flags & ZEND_ACC_PROTECTED)) {
|
||||
if (!zend_check_protected(fptr->common.scope, EG(scope))) {
|
||||
} else if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED)) {
|
||||
if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) {
|
||||
if (error) {
|
||||
if (*error) {
|
||||
efree(*error);
|
||||
}
|
||||
zend_spprintf(error, 0, "cannot access protected method %s::%s()", (*ce_ptr)->name, fptr->common.function_name);
|
||||
zend_spprintf(error, 0, "cannot access protected method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
|
||||
}
|
||||
retval = 0;
|
||||
}
|
||||
@ -2473,18 +2523,21 @@ static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, ze
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fcc->object_pp) {
|
||||
fcc->called_scope = Z_OBJCE_PP(fcc->object_pp);
|
||||
}
|
||||
efree(lmname);
|
||||
if (retval && !call_via_handler) {
|
||||
fcc->initialized = 1;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **callable_name, int *callable_name_len, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zval ***zobj_ptr_ptr, char **error TSRMLS_DC) /* {{{ */
|
||||
ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **callable_name, int *callable_name_len, zend_fcall_info_cache *fcc, char **error TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char *lcname;
|
||||
int callable_name_len_local;
|
||||
zend_class_entry *ce_local, **pce;
|
||||
zend_function *fptr_local;
|
||||
zval **zobj_ptr_local;
|
||||
zend_fcall_info_cache fcc_local;
|
||||
|
||||
if (callable_name) {
|
||||
*callable_name = NULL;
|
||||
@ -2492,21 +2545,19 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **
|
||||
if (callable_name_len == NULL) {
|
||||
callable_name_len = &callable_name_len_local;
|
||||
}
|
||||
if (ce_ptr == NULL) {
|
||||
ce_ptr = &ce_local;
|
||||
}
|
||||
if (fptr_ptr == NULL) {
|
||||
fptr_ptr = &fptr_local;
|
||||
}
|
||||
if (zobj_ptr_ptr == NULL) {
|
||||
zobj_ptr_ptr = &zobj_ptr_local;
|
||||
if (fcc == NULL) {
|
||||
fcc = &fcc_local;
|
||||
}
|
||||
if (error) {
|
||||
*error = NULL;
|
||||
}
|
||||
*ce_ptr = NULL;
|
||||
*fptr_ptr = NULL;
|
||||
*zobj_ptr_ptr = NULL;
|
||||
|
||||
fcc->initialized = 0;
|
||||
fcc->calling_scope = NULL;
|
||||
fcc->called_scope = NULL;
|
||||
fcc->function_handler = NULL;
|
||||
fcc->calling_scope = NULL;
|
||||
fcc->object_pp = NULL;
|
||||
|
||||
switch (Z_TYPE_P(callable)) {
|
||||
case IS_STRING:
|
||||
@ -2518,11 +2569,10 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **
|
||||
return 1;
|
||||
}
|
||||
|
||||
return zend_is_callable_check_func(check_flags, zobj_ptr_ptr, NULL, callable, ce_ptr, fptr_ptr, error TSRMLS_CC);
|
||||
return zend_is_callable_check_func(check_flags, callable, fcc, error TSRMLS_CC);
|
||||
|
||||
case IS_ARRAY:
|
||||
{
|
||||
zend_class_entry *ce = NULL;
|
||||
zval **method = NULL;
|
||||
zval **obj = NULL;
|
||||
|
||||
@ -2552,51 +2602,34 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **
|
||||
return 1;
|
||||
}
|
||||
|
||||
lcname = zend_str_tolower_dup(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj));
|
||||
|
||||
if (EG(active_op_array) &&
|
||||
Z_STRLEN_PP(obj) == sizeof("self") - 1 &&
|
||||
!memcmp(lcname, "self", sizeof("self") - 1)) {
|
||||
ce = EG(active_op_array)->scope;
|
||||
} else if (EG(active_op_array) && EG(active_op_array)->scope &&
|
||||
Z_STRLEN_PP(obj) == sizeof("parent") - 1 &&
|
||||
!memcmp(lcname, "parent", sizeof("parent") - 1)) {
|
||||
ce = EG(active_op_array)->scope->parent;
|
||||
} else if (Z_STRLEN_PP(obj) == sizeof("static") - 1 &&
|
||||
!memcmp(lcname, "static", sizeof("static") - 1)) {
|
||||
ce = EG(called_scope);
|
||||
} else if (zend_lookup_class(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), &pce TSRMLS_CC) == SUCCESS) {
|
||||
ce = *pce;
|
||||
if (!zend_is_callable_check_class(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), fcc, error TSRMLS_CC)) {
|
||||
return 0;
|
||||
}
|
||||
efree(lcname);
|
||||
} else {
|
||||
ce = Z_OBJCE_PP(obj); /* TBFixed: what if it's overloaded? */
|
||||
|
||||
*zobj_ptr_ptr = obj;
|
||||
} else {
|
||||
fcc->calling_scope = Z_OBJCE_PP(obj); /* TBFixed: what if it's overloaded? */
|
||||
|
||||
fcc->object_pp = obj;
|
||||
|
||||
if (callable_name) {
|
||||
char *ptr;
|
||||
|
||||
*callable_name_len = ce->name_length + Z_STRLEN_PP(method) + sizeof("::") - 1;
|
||||
*callable_name_len = fcc->calling_scope->name_length + Z_STRLEN_PP(method) + sizeof("::") - 1;
|
||||
ptr = *callable_name = emalloc(*callable_name_len + 1);
|
||||
memcpy(ptr, ce->name, ce->name_length);
|
||||
ptr += ce->name_length;
|
||||
memcpy(ptr, fcc->calling_scope->name, fcc->calling_scope->name_length);
|
||||
ptr += fcc->calling_scope->name_length;
|
||||
memcpy(ptr, "::", sizeof("::") - 1);
|
||||
ptr += sizeof("::") - 1;
|
||||
memcpy(ptr, Z_STRVAL_PP(method), Z_STRLEN_PP(method) + 1);
|
||||
}
|
||||
|
||||
if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
|
||||
*ce_ptr = ce;
|
||||
fcc->called_scope = fcc->calling_scope;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ce) {
|
||||
return zend_is_callable_check_func(check_flags, zobj_ptr_ptr, ce, *method, ce_ptr, fptr_ptr, error TSRMLS_CC);
|
||||
} else {
|
||||
if (error) zend_spprintf(error, 0, "first array member is not a valid %s", Z_TYPE_PP(obj) == IS_STRING ? "class name" : "object");
|
||||
}
|
||||
return zend_is_callable_check_func(check_flags, *method, fcc, error TSRMLS_CC);
|
||||
} else {
|
||||
if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
|
||||
if (!obj || (Z_TYPE_PP(obj) != IS_STRING && Z_TYPE_PP(obj) != IS_OBJECT)) {
|
||||
@ -2612,12 +2645,12 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **
|
||||
*callable_name_len = sizeof("Array") - 1;
|
||||
}
|
||||
}
|
||||
*ce_ptr = ce;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case IS_OBJECT:
|
||||
if (zend_get_closure(callable, ce_ptr, fptr_ptr, NULL, zobj_ptr_ptr TSRMLS_CC) == SUCCESS) {
|
||||
if (zend_get_closure(callable, &fcc->calling_scope, &fcc->function_handler, NULL, &fcc->object_pp TSRMLS_CC) == SUCCESS) {
|
||||
fcc->called_scope = fcc->calling_scope;
|
||||
if (callable_name) {
|
||||
zend_class_entry *ce = Z_OBJCE_P(callable); /* TBFixed: what if it's overloaded? */
|
||||
|
||||
@ -2650,22 +2683,20 @@ ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **cal
|
||||
{
|
||||
TSRMLS_FETCH();
|
||||
|
||||
return zend_is_callable_ex(callable, check_flags, callable_name, NULL, NULL, NULL, NULL, NULL TSRMLS_CC);
|
||||
return zend_is_callable_ex(callable, check_flags, callable_name, NULL, NULL, NULL TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_class_entry *ce;
|
||||
zend_function *fptr;
|
||||
zval **zobj_ptr;
|
||||
zend_fcall_info_cache fcc;
|
||||
|
||||
if (zend_is_callable_ex(callable, IS_CALLABLE_STRICT, callable_name, NULL, &ce, &fptr, &zobj_ptr, NULL TSRMLS_CC)) {
|
||||
if (Z_TYPE_P(callable) == IS_STRING && ce) {
|
||||
if (zend_is_callable_ex(callable, IS_CALLABLE_STRICT, callable_name, NULL, &fcc, NULL TSRMLS_CC)) {
|
||||
if (Z_TYPE_P(callable) == IS_STRING && fcc.calling_scope) {
|
||||
zval_dtor(callable);
|
||||
array_init(callable);
|
||||
add_next_index_string(callable, ce->name, 1);
|
||||
add_next_index_string(callable, fptr->common.function_name, 1);
|
||||
add_next_index_string(callable, fcc.calling_scope->name, 1);
|
||||
add_next_index_string(callable, fcc.function_handler->common.function_name, 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -2675,18 +2706,13 @@ ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRML
|
||||
|
||||
ZEND_API int zend_fcall_info_init(zval *callable, uint check_flags, zend_fcall_info *fci, zend_fcall_info_cache *fcc, char **callable_name, char **error TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
int len;
|
||||
zend_class_entry *ce;
|
||||
zend_function *func;
|
||||
zval **obj;
|
||||
|
||||
if (!zend_is_callable_ex(callable, check_flags, callable_name, NULL, &ce, &func, &obj, error TSRMLS_CC)) {
|
||||
if (!zend_is_callable_ex(callable, check_flags, callable_name, NULL, fcc, error TSRMLS_CC)) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
fci->size = sizeof(*fci);
|
||||
fci->function_table = ce ? &ce->function_table : EG(function_table);
|
||||
fci->object_pp = obj;
|
||||
fci->function_table = fcc->calling_scope ? &fcc->calling_scope->function_table : EG(function_table);
|
||||
fci->object_pp = fcc->object_pp;
|
||||
fci->function_name = callable;
|
||||
fci->retval_ptr_ptr = NULL;
|
||||
fci->param_count = 0;
|
||||
@ -2694,24 +2720,6 @@ ZEND_API int zend_fcall_info_init(zval *callable, uint check_flags, zend_fcall_i
|
||||
fci->no_separation = 1;
|
||||
fci->symbol_table = NULL;
|
||||
|
||||
if (ce) {
|
||||
len = strlen(func->common.function_name);
|
||||
if ((len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && !zend_binary_strcasecmp(func->common.function_name, len, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME) - 1)) ||
|
||||
(len == sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1 && !zend_binary_strcasecmp(func->common.function_name, len, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1))
|
||||
) {
|
||||
fcc->initialized = 0;
|
||||
fcc->function_handler = NULL;
|
||||
fcc->calling_scope = NULL;
|
||||
fcc->object_pp = NULL;
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
fcc->initialized = 1;
|
||||
fcc->function_handler = func;
|
||||
fcc->calling_scope = ce;
|
||||
fcc->object_pp = obj;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -40,6 +40,26 @@ typedef struct _zend_function_entry {
|
||||
zend_uint flags;
|
||||
} zend_function_entry;
|
||||
|
||||
typedef struct _zend_fcall_info {
|
||||
size_t size;
|
||||
HashTable *function_table;
|
||||
zval *function_name;
|
||||
HashTable *symbol_table;
|
||||
zval **retval_ptr_ptr;
|
||||
zend_uint param_count;
|
||||
zval ***params;
|
||||
zval **object_pp;
|
||||
zend_bool no_separation;
|
||||
} zend_fcall_info;
|
||||
|
||||
typedef struct _zend_fcall_info_cache {
|
||||
zend_bool initialized;
|
||||
zend_function *function_handler;
|
||||
zend_class_entry *calling_scope;
|
||||
zend_class_entry *called_scope;
|
||||
zval **object_pp;
|
||||
} zend_fcall_info_cache;
|
||||
|
||||
#define ZEND_NS_NAME(ns, name) ns"::"name
|
||||
|
||||
#define ZEND_FN(name) zif_##name
|
||||
@ -256,7 +276,7 @@ ZEND_API void zend_wrong_param_count(TSRMLS_D);
|
||||
|
||||
#define IS_CALLABLE_STRICT (IS_CALLABLE_CHECK_IS_STATIC)
|
||||
|
||||
ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **callable_name, int *callable_name_len, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zval ***zobj_ptr_ptr, char **error TSRMLS_DC);
|
||||
ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **callable_name, int *callable_name_len, zend_fcall_info_cache *fcc, char **error TSRMLS_DC);
|
||||
ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **callable_name);
|
||||
ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRMLS_DC);
|
||||
ZEND_API const char *zend_get_module_version(const char *module_name);
|
||||
@ -405,28 +425,7 @@ ZEND_API int add_property_zval_ex(zval *arg, char *key, uint key_len, zval *valu
|
||||
|
||||
ZEND_API int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, zend_uint param_count, zval *params[] TSRMLS_DC);
|
||||
ZEND_API int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, zend_uint param_count, zval **params[], int no_separation, HashTable *symbol_table TSRMLS_DC);
|
||||
END_EXTERN_C()
|
||||
|
||||
typedef struct _zend_fcall_info {
|
||||
size_t size;
|
||||
HashTable *function_table;
|
||||
zval *function_name;
|
||||
HashTable *symbol_table;
|
||||
zval **retval_ptr_ptr;
|
||||
zend_uint param_count;
|
||||
zval ***params;
|
||||
zval **object_pp;
|
||||
zend_bool no_separation;
|
||||
} zend_fcall_info;
|
||||
|
||||
typedef struct _zend_fcall_info_cache {
|
||||
zend_bool initialized;
|
||||
zend_function *function_handler;
|
||||
zend_class_entry *calling_scope;
|
||||
zval **object_pp;
|
||||
} zend_fcall_info_cache;
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
ZEND_API extern zend_fcall_info empty_fcall_info;
|
||||
ZEND_API extern zend_fcall_info_cache empty_fcall_info_cache;
|
||||
|
||||
|
@ -41,7 +41,7 @@ ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, int
|
||||
|
||||
/* true globals */
|
||||
ZEND_API zend_fcall_info empty_fcall_info = { 0, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0 };
|
||||
ZEND_API zend_fcall_info_cache empty_fcall_info_cache = { 0, NULL, NULL, NULL };
|
||||
ZEND_API zend_fcall_info_cache empty_fcall_info_cache = { 0, NULL, NULL, NULL, NULL };
|
||||
|
||||
#ifdef ZEND_WIN32
|
||||
#include <process.h>
|
||||
@ -684,6 +684,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
zend_class_entry *current_scope;
|
||||
zend_class_entry *current_called_scope;
|
||||
zend_class_entry *calling_scope = NULL;
|
||||
zend_class_entry *called_scope = NULL;
|
||||
zend_class_entry *check_scope_or_static = NULL;
|
||||
zval *current_this;
|
||||
zend_execute_data execute_data;
|
||||
@ -758,24 +759,26 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
calling_scope = Z_OBJCE_PP(fci->object_pp);
|
||||
calling_scope = called_scope = Z_OBJCE_PP(fci->object_pp);
|
||||
fci->function_table = &calling_scope->function_table;
|
||||
EX(object) = *fci->object_pp;
|
||||
} else if (Z_TYPE_PP(fci->object_pp) == IS_STRING) {
|
||||
zend_class_entry **ce;
|
||||
int found = FAILURE;
|
||||
|
||||
if (EG(active_op_array) && strcmp(Z_STRVAL_PP(fci->object_pp), "self") == 0) {
|
||||
if (!EG(active_op_array)->scope) {
|
||||
if (strcmp(Z_STRVAL_PP(fci->object_pp), "self") == 0) {
|
||||
if (!EG(active_op_array) || !EG(active_op_array)->scope) {
|
||||
zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
|
||||
}
|
||||
ce = &(EG(active_op_array)->scope);
|
||||
found = (*ce != NULL?SUCCESS:FAILURE);
|
||||
fci->object_pp = EG(This)?&EG(This):NULL;
|
||||
EX(object) = EG(This);
|
||||
calling_scope = *ce;
|
||||
called_scope = EG(called_scope) ? EG(called_scope) : calling_scope;
|
||||
} else if (strcmp(Z_STRVAL_PP(fci->object_pp), "parent") == 0 && EG(active_op_array)) {
|
||||
|
||||
if (!EG(active_op_array)->scope) {
|
||||
if (!EG(active_op_array) || !EG(active_op_array)->scope) {
|
||||
zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
|
||||
}
|
||||
if (!EG(active_op_array)->scope->parent) {
|
||||
@ -785,6 +788,8 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
found = (*ce != NULL?SUCCESS:FAILURE);
|
||||
fci->object_pp = EG(This)?&EG(This):NULL;
|
||||
EX(object) = EG(This);
|
||||
calling_scope = *ce;
|
||||
called_scope = EG(called_scope) ? EG(called_scope) : calling_scope;
|
||||
} else if (Z_STRLEN_PP(fci->object_pp) == sizeof("static") - 1 &&
|
||||
!memcmp(Z_STRVAL_PP(fci->object_pp), "static", sizeof("static") - 1)
|
||||
) {
|
||||
@ -792,9 +797,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
zend_error(E_ERROR, "Cannot access static:: when no class scope is active");
|
||||
}
|
||||
ce = &(EG(called_scope));
|
||||
found = (*ce != NULL?SUCCESS:FAILURE);
|
||||
found = (EG(called_scope) != NULL?SUCCESS:FAILURE);
|
||||
fci->object_pp = EG(This)?&EG(This):NULL;
|
||||
EX(object) = EG(This);
|
||||
calling_scope = called_scope = EG(called_scope);
|
||||
} else {
|
||||
zend_class_entry *scope;
|
||||
scope = EG(active_op_array) ? EG(active_op_array)->scope : NULL;
|
||||
@ -811,12 +817,12 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
} else {
|
||||
fci->object_pp = NULL;
|
||||
}
|
||||
calling_scope = called_scope = *ce;
|
||||
}
|
||||
if (found == FAILURE)
|
||||
return FAILURE;
|
||||
|
||||
fci->function_table = &(*ce)->function_table;
|
||||
calling_scope = *ce;
|
||||
} else {
|
||||
zend_error(E_NOTICE, "Non-callable array passed to zend_call_function()");
|
||||
return FAILURE;
|
||||
@ -829,6 +835,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
|
||||
if (Z_TYPE_P(fci->function_name) == IS_OBJECT) {
|
||||
if (zend_get_closure(fci->function_name, &calling_scope, &EX(function_state).function, NULL, &fci->object_pp TSRMLS_CC) == SUCCESS) {
|
||||
called_scope = calling_scope;
|
||||
goto init_fci_cache;
|
||||
}
|
||||
} else if (Z_TYPE_P(fci->function_name) != IS_STRING) {
|
||||
@ -865,20 +872,34 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
|
||||
lcname = zend_str_tolower_dup(cname, clen);
|
||||
/* caution: lcname is not '\0' terminated */
|
||||
if (calling_scope && clen == sizeof("self") - 1 &&
|
||||
if (clen == sizeof("self") - 1 &&
|
||||
memcmp(lcname, "self", sizeof("self") - 1) == 0
|
||||
) {
|
||||
if (!EG(active_op_array) || !EG(active_op_array)->scope) {
|
||||
zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
|
||||
}
|
||||
ce_child = EG(active_op_array) ? EG(active_op_array)->scope : NULL;
|
||||
} else if (calling_scope && clen == sizeof("parent") - 1 &&
|
||||
called_scope = EG(called_scope) ? EG(called_scope) : ce_child;
|
||||
} else if (clen == sizeof("parent") - 1 &&
|
||||
memcmp(lcname, "parent", sizeof("parent") - 1) == 0
|
||||
) {
|
||||
ce_child = EG(active_op_array) && EG(active_op_array)->scope ? EG(scope)->parent : NULL;
|
||||
if (!EG(active_op_array) || !EG(active_op_array)->scope) {
|
||||
zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
|
||||
}
|
||||
if (!EG(active_op_array)->scope->parent) {
|
||||
zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent");
|
||||
}
|
||||
ce_child = EG(active_op_array) && EG(active_op_array)->scope ? EG(active_op_array)->scope->parent : NULL;
|
||||
called_scope = EG(called_scope) ? EG(called_scope) : ce_child;
|
||||
} else if (clen == sizeof("static") - 1 &&
|
||||
memcmp(lcname, "static", sizeof("static") - 1)
|
||||
) {
|
||||
ce_child = EG(called_scope);
|
||||
if (!EG(called_scope)) {
|
||||
zend_error(E_ERROR, "Cannot access static:: when no class scope is active");
|
||||
}
|
||||
called_scope = ce_child = EG(called_scope);
|
||||
} else if (zend_lookup_class(lcname, clen, &pce TSRMLS_CC) == SUCCESS) {
|
||||
ce_child = *pce;
|
||||
called_scope = ce_child = *pce;
|
||||
}
|
||||
efree(lcname);
|
||||
|
||||
@ -949,11 +970,13 @@ init_fci_cache:
|
||||
fci_cache->function_handler = EX(function_state).function;
|
||||
fci_cache->object_pp = fci->object_pp;
|
||||
fci_cache->calling_scope = calling_scope;
|
||||
fci_cache->called_scope = called_scope;
|
||||
fci_cache->initialized = 1;
|
||||
}
|
||||
} else {
|
||||
EX(function_state).function = fci_cache->function_handler;
|
||||
calling_scope = fci_cache->calling_scope;
|
||||
called_scope = fci_cache->called_scope;
|
||||
fci->object_pp = fci_cache->object_pp;
|
||||
EX(object) = fci->object_pp ? *fci->object_pp : NULL;
|
||||
if (fci->object_pp && *fci->object_pp && Z_TYPE_PP(fci->object_pp) == IS_OBJECT
|
||||
@ -1048,8 +1071,8 @@ init_fci_cache:
|
||||
current_this = EG(This);
|
||||
|
||||
current_called_scope = EG(called_scope);
|
||||
if (calling_scope) {
|
||||
EG(called_scope) = calling_scope;
|
||||
if (called_scope) {
|
||||
EG(called_scope) = called_scope;
|
||||
} else if (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION) {
|
||||
EG(called_scope) = NULL;
|
||||
}
|
||||
|
@ -84,6 +84,7 @@ ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend
|
||||
fcic.function_handler = *fn_proxy;
|
||||
}
|
||||
fcic.calling_scope = obj_ce;
|
||||
fcic.called_scope = object_pp ? obj_ce : EG(called_scope);
|
||||
fcic.object_pp = object_pp;
|
||||
result = zend_call_function(&fci, &fcic TSRMLS_CC);
|
||||
}
|
||||
|
@ -1937,8 +1937,15 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
|
||||
if (!ce) {
|
||||
zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
|
||||
}
|
||||
EX(called_scope) = ce;
|
||||
} else {
|
||||
ce = EX_T(opline->op1.u.var).class_entry;
|
||||
|
||||
if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
|
||||
EX(called_scope) = EG(called_scope);
|
||||
} else {
|
||||
EX(called_scope) = ce;
|
||||
}
|
||||
}
|
||||
if(OP2_TYPE != IS_UNUSED) {
|
||||
char *function_name_strval;
|
||||
@ -1980,8 +1987,6 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
|
||||
EX(fbc) = ce->constructor;
|
||||
}
|
||||
|
||||
EX(called_scope) = ce;
|
||||
|
||||
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
|
||||
EX(object) = NULL;
|
||||
} else {
|
||||
|
@ -2606,8 +2606,15 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
|
||||
if (!ce) {
|
||||
zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
|
||||
}
|
||||
EX(called_scope) = ce;
|
||||
} else {
|
||||
ce = EX_T(opline->op1.u.var).class_entry;
|
||||
|
||||
if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
|
||||
EX(called_scope) = EG(called_scope);
|
||||
} else {
|
||||
EX(called_scope) = ce;
|
||||
}
|
||||
}
|
||||
if(IS_CONST != IS_UNUSED) {
|
||||
char *function_name_strval;
|
||||
@ -2649,8 +2656,6 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
|
||||
EX(fbc) = ce->constructor;
|
||||
}
|
||||
|
||||
EX(called_scope) = ce;
|
||||
|
||||
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
|
||||
EX(object) = NULL;
|
||||
} else {
|
||||
@ -3194,8 +3199,15 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE
|
||||
if (!ce) {
|
||||
zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
|
||||
}
|
||||
EX(called_scope) = ce;
|
||||
} else {
|
||||
ce = EX_T(opline->op1.u.var).class_entry;
|
||||
|
||||
if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
|
||||
EX(called_scope) = EG(called_scope);
|
||||
} else {
|
||||
EX(called_scope) = ce;
|
||||
}
|
||||
}
|
||||
if(IS_TMP_VAR != IS_UNUSED) {
|
||||
char *function_name_strval;
|
||||
@ -3237,8 +3249,6 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE
|
||||
EX(fbc) = ce->constructor;
|
||||
}
|
||||
|
||||
EX(called_scope) = ce;
|
||||
|
||||
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
|
||||
EX(object) = NULL;
|
||||
} else {
|
||||
@ -3662,8 +3672,15 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE
|
||||
if (!ce) {
|
||||
zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
|
||||
}
|
||||
EX(called_scope) = ce;
|
||||
} else {
|
||||
ce = EX_T(opline->op1.u.var).class_entry;
|
||||
|
||||
if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
|
||||
EX(called_scope) = EG(called_scope);
|
||||
} else {
|
||||
EX(called_scope) = ce;
|
||||
}
|
||||
}
|
||||
if(IS_VAR != IS_UNUSED) {
|
||||
char *function_name_strval;
|
||||
@ -3705,8 +3722,6 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE
|
||||
EX(fbc) = ce->constructor;
|
||||
}
|
||||
|
||||
EX(called_scope) = ce;
|
||||
|
||||
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
|
||||
EX(object) = NULL;
|
||||
} else {
|
||||
@ -3886,8 +3901,15 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
|
||||
if (!ce) {
|
||||
zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
|
||||
}
|
||||
EX(called_scope) = ce;
|
||||
} else {
|
||||
ce = EX_T(opline->op1.u.var).class_entry;
|
||||
|
||||
if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
|
||||
EX(called_scope) = EG(called_scope);
|
||||
} else {
|
||||
EX(called_scope) = ce;
|
||||
}
|
||||
}
|
||||
if(IS_UNUSED != IS_UNUSED) {
|
||||
char *function_name_strval;
|
||||
@ -3929,8 +3951,6 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
|
||||
EX(fbc) = ce->constructor;
|
||||
}
|
||||
|
||||
EX(called_scope) = ce;
|
||||
|
||||
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
|
||||
EX(object) = NULL;
|
||||
} else {
|
||||
@ -4322,8 +4342,15 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
|
||||
if (!ce) {
|
||||
zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
|
||||
}
|
||||
EX(called_scope) = ce;
|
||||
} else {
|
||||
ce = EX_T(opline->op1.u.var).class_entry;
|
||||
|
||||
if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
|
||||
EX(called_scope) = EG(called_scope);
|
||||
} else {
|
||||
EX(called_scope) = ce;
|
||||
}
|
||||
}
|
||||
if(IS_CV != IS_UNUSED) {
|
||||
char *function_name_strval;
|
||||
@ -4365,8 +4392,6 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
|
||||
EX(fbc) = ce->constructor;
|
||||
}
|
||||
|
||||
EX(called_scope) = ce;
|
||||
|
||||
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
|
||||
EX(object) = NULL;
|
||||
} else {
|
||||
@ -10260,8 +10285,15 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
|
||||
if (!ce) {
|
||||
zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
|
||||
}
|
||||
EX(called_scope) = ce;
|
||||
} else {
|
||||
ce = EX_T(opline->op1.u.var).class_entry;
|
||||
|
||||
if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
|
||||
EX(called_scope) = EG(called_scope);
|
||||
} else {
|
||||
EX(called_scope) = ce;
|
||||
}
|
||||
}
|
||||
if(IS_CONST != IS_UNUSED) {
|
||||
char *function_name_strval;
|
||||
@ -10303,8 +10335,6 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
|
||||
EX(fbc) = ce->constructor;
|
||||
}
|
||||
|
||||
EX(called_scope) = ce;
|
||||
|
||||
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
|
||||
EX(object) = NULL;
|
||||
} else {
|
||||
@ -12092,8 +12122,15 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND
|
||||
if (!ce) {
|
||||
zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
|
||||
}
|
||||
EX(called_scope) = ce;
|
||||
} else {
|
||||
ce = EX_T(opline->op1.u.var).class_entry;
|
||||
|
||||
if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
|
||||
EX(called_scope) = EG(called_scope);
|
||||
} else {
|
||||
EX(called_scope) = ce;
|
||||
}
|
||||
}
|
||||
if(IS_TMP_VAR != IS_UNUSED) {
|
||||
char *function_name_strval;
|
||||
@ -12135,8 +12172,6 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND
|
||||
EX(fbc) = ce->constructor;
|
||||
}
|
||||
|
||||
EX(called_scope) = ce;
|
||||
|
||||
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
|
||||
EX(object) = NULL;
|
||||
} else {
|
||||
@ -13894,8 +13929,15 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND
|
||||
if (!ce) {
|
||||
zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
|
||||
}
|
||||
EX(called_scope) = ce;
|
||||
} else {
|
||||
ce = EX_T(opline->op1.u.var).class_entry;
|
||||
|
||||
if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
|
||||
EX(called_scope) = EG(called_scope);
|
||||
} else {
|
||||
EX(called_scope) = ce;
|
||||
}
|
||||
}
|
||||
if(IS_VAR != IS_UNUSED) {
|
||||
char *function_name_strval;
|
||||
@ -13937,8 +13979,6 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND
|
||||
EX(fbc) = ce->constructor;
|
||||
}
|
||||
|
||||
EX(called_scope) = ce;
|
||||
|
||||
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
|
||||
EX(object) = NULL;
|
||||
} else {
|
||||
@ -14799,8 +14839,15 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
|
||||
if (!ce) {
|
||||
zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
|
||||
}
|
||||
EX(called_scope) = ce;
|
||||
} else {
|
||||
ce = EX_T(opline->op1.u.var).class_entry;
|
||||
|
||||
if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
|
||||
EX(called_scope) = EG(called_scope);
|
||||
} else {
|
||||
EX(called_scope) = ce;
|
||||
}
|
||||
}
|
||||
if(IS_UNUSED != IS_UNUSED) {
|
||||
char *function_name_strval;
|
||||
@ -14842,8 +14889,6 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
|
||||
EX(fbc) = ce->constructor;
|
||||
}
|
||||
|
||||
EX(called_scope) = ce;
|
||||
|
||||
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
|
||||
EX(object) = NULL;
|
||||
} else {
|
||||
@ -16302,8 +16347,15 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
|
||||
if (!ce) {
|
||||
zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
|
||||
}
|
||||
EX(called_scope) = ce;
|
||||
} else {
|
||||
ce = EX_T(opline->op1.u.var).class_entry;
|
||||
|
||||
if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
|
||||
EX(called_scope) = EG(called_scope);
|
||||
} else {
|
||||
EX(called_scope) = ce;
|
||||
}
|
||||
}
|
||||
if(IS_CV != IS_UNUSED) {
|
||||
char *function_name_strval;
|
||||
@ -16345,8 +16397,6 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
|
||||
EX(fbc) = ce->constructor;
|
||||
}
|
||||
|
||||
EX(called_scope) = ce;
|
||||
|
||||
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
|
||||
EX(object) = NULL;
|
||||
} else {
|
||||
|
@ -433,6 +433,7 @@ PHP_FUNCTION(spl_autoload_register)
|
||||
zend_function *spl_func_ptr;
|
||||
autoload_func_info alfi;
|
||||
zval **obj_ptr;
|
||||
zend_fcall_info_cache fcc;
|
||||
|
||||
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "|zbb", &zcallable, &do_throw, &prepend) == FAILURE) {
|
||||
return;
|
||||
@ -450,7 +451,10 @@ PHP_FUNCTION(spl_autoload_register)
|
||||
}
|
||||
}
|
||||
|
||||
if (!zend_is_callable_ex(zcallable, IS_CALLABLE_STRICT, &func_name, &func_name_len, &alfi.ce, &alfi.func_ptr, &obj_ptr, &error TSRMLS_CC)) {
|
||||
if (!zend_is_callable_ex(zcallable, IS_CALLABLE_STRICT, &func_name, &func_name_len, &fcc, &error TSRMLS_CC)) {
|
||||
alfi.ce = fcc.calling_scope;
|
||||
alfi.func_ptr = fcc.function_handler;
|
||||
obj_ptr = fcc.object_pp;
|
||||
if (Z_TYPE_P(zcallable) == IS_ARRAY) {
|
||||
if (!obj_ptr && alfi.func_ptr && !(alfi.func_ptr->common.fn_flags & ZEND_ACC_STATIC)) {
|
||||
if (do_throw) {
|
||||
@ -490,6 +494,9 @@ PHP_FUNCTION(spl_autoload_register)
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
alfi.ce = fcc.calling_scope;
|
||||
alfi.func_ptr = fcc.function_handler;
|
||||
obj_ptr = fcc.object_pp;
|
||||
if (error) {
|
||||
efree(error);
|
||||
}
|
||||
@ -560,12 +567,13 @@ PHP_FUNCTION(spl_autoload_unregister)
|
||||
int success = FAILURE;
|
||||
zend_function *spl_func_ptr;
|
||||
zval **obj_ptr;
|
||||
zend_fcall_info_cache fcc;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zcallable) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!zend_is_callable_ex(zcallable, IS_CALLABLE_CHECK_SYNTAX_ONLY, &func_name, &func_name_len, NULL, NULL, &obj_ptr, &error TSRMLS_CC)) {
|
||||
if (!zend_is_callable_ex(zcallable, IS_CALLABLE_CHECK_SYNTAX_ONLY, &func_name, &func_name_len, &fcc, &error TSRMLS_CC)) {
|
||||
zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "Unable to unregister invalid function (%s)", error);
|
||||
if (error) {
|
||||
efree(error);
|
||||
@ -575,6 +583,7 @@ PHP_FUNCTION(spl_autoload_unregister)
|
||||
}
|
||||
RETURN_FALSE;
|
||||
}
|
||||
obj_ptr = fcc.object_pp;
|
||||
if (error) {
|
||||
efree(error);
|
||||
}
|
||||
|
@ -5204,7 +5204,7 @@ PHP_FUNCTION(forward_static_call)
|
||||
|
||||
if (EG(called_scope) &&
|
||||
instanceof_function(EG(called_scope), fci_cache.calling_scope TSRMLS_CC)) {
|
||||
fci_cache.calling_scope = EG(called_scope);
|
||||
fci_cache.called_scope = EG(called_scope);
|
||||
}
|
||||
|
||||
if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && fci.retval_ptr_ptr && *fci.retval_ptr_ptr) {
|
||||
@ -5234,7 +5234,7 @@ PHP_FUNCTION(forward_static_call_array)
|
||||
|
||||
if (EG(called_scope) &&
|
||||
instanceof_function(EG(called_scope), fci_cache.calling_scope TSRMLS_CC)) {
|
||||
fci_cache.calling_scope = EG(called_scope);
|
||||
fci_cache.called_scope = EG(called_scope);
|
||||
}
|
||||
|
||||
if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && fci.retval_ptr_ptr && *fci.retval_ptr_ptr) {
|
||||
|
@ -37,7 +37,7 @@ echo "Done";
|
||||
*** Testing array_map() : with non-existent class and method ***
|
||||
-- with non-existent class --
|
||||
|
||||
Warning: array_map() expects parameter 1 to be a valid callback, first array member is not a valid class name in %s on line %d
|
||||
Warning: array_map() expects parameter 1 to be a valid callback, class 'non-existent' not found in %s on line %d
|
||||
NULL
|
||||
-- with existent class and non-existent method --
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user