diff options
author | Marcus Boerger <helly@php.net> | 2005-12-16 22:15:41 +0000 |
---|---|---|
committer | Marcus Boerger <helly@php.net> | 2005-12-16 22:15:41 +0000 |
commit | 0cd997d79c1601e72047f8faea8614aaeaebc053 (patch) | |
tree | c55a69494db57f2ab9d409418faf4f0bde09a40a /Zend/zend_API.c | |
parent | 418223e2f629ba63392c5b2fff7470cdd3484eac (diff) | |
download | php-git-0cd997d79c1601e72047f8faea8614aaeaebc053.tar.gz |
- Simplify and synch is_callable_ex() with actual execution code
. Allow array($this, 'parent::method') for function 'pointers'
. Spit out E_STRICT in case of erroneous use of function 'pointers'
Diffstat (limited to 'Zend/zend_API.c')
-rw-r--r-- | Zend/zend_API.c | 148 |
1 files changed, 90 insertions, 58 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c index bae16c5492..81921ff574 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1974,15 +1974,94 @@ ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_ return 1; } -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 TSRMLS_DC) +static int zend_is_callable_check_func(int check_flags, zval **zobj_ptr, zend_class_entry *ce_org, zval *callable, zend_class_entry **ce_ptr, zend_function **fptr_ptr TSRMLS_DC) { + int retval; char *lcname, *lmname, *colon; + int clen, mlen; + zend_function *fptr; + zend_class_entry **pce; + HashTable *ftable; + + *ce_ptr = NULL; + *fptr_ptr = NULL; + + if ((colon = strstr(Z_STRVAL_P(callable), "::")) != NULL) { + clen = colon - Z_STRVAL_P(callable); + mlen = Z_STRLEN_P(callable) - clen - 2; + if (zend_lookup_class(Z_STRVAL_P(callable), clen, &pce TSRMLS_CC) == SUCCESS) { + *ce_ptr = *pce; + } else { + lcname = zend_str_tolower_dup(Z_STRVAL_P(callable), clen); + /* caution: lcname is not '\0' terminated */ + if (clen == sizeof("self") - 1 && memcmp(lcname, "self", sizeof("self") - 1) == 0) { + *ce_ptr = EG(scope); + } else if (clen == sizeof("parent") - 1 && memcmp(lcname, "parent", sizeof("parent") - 1) == 0 && EG(active_op_array)->scope) { + *ce_ptr = EG(scope) ? EG(scope)->parent : NULL; + } + efree(lcname); + } + if (!*ce_ptr) { + return 0; + } + ftable = &(*ce_ptr)->function_table; + if (ce_org && !instanceof_function(ce_org, *ce_ptr TSRMLS_CC)) { + return 0; + } + lmname = zend_str_tolower_dup(Z_STRVAL_P(callable) + clen + 2, mlen); + } else { + mlen = Z_STRLEN_P(callable); + lmname = zend_str_tolower_dup(Z_STRVAL_P(callable), mlen); + if (ce_org) { + ftable = &ce_org->function_table; + *ce_ptr = ce_org; + } else { + ftable = EG(function_table); + } + } + + retval = zend_hash_find(ftable, lmname, mlen+1, (void**)&fptr) == SUCCESS ? 1 : 0; + + if (!retval) { + if (zobj_ptr && *ce_ptr && (*ce_ptr)->__call != 0) { + retval = (*ce_ptr)->__call != NULL; + *fptr_ptr = (*ce_ptr)->__call; + } + } else { + *fptr_ptr = fptr; + if (*ce_ptr) { + if (!zobj_ptr && !(fptr->common.fn_flags & ZEND_ACC_STATIC)) { + if ((check_flags & IS_CALLABLE_CHECK_IS_STATIC) != 0) { + retval = 0; + } else { + zend_error(E_STRICT, "Non-static method %s::%s() cannot be called statically", (*ce_ptr)->name, fptr->common.function_name); + } + } + 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 ? Z_OBJCE_PP(zobj_ptr) : EG(scope), lmname, mlen TSRMLS_CC)) { + retval = 0; + } + } else if ((fptr->common.fn_flags & ZEND_ACC_PROTECTED)) { + if (!zend_check_protected(fptr->common.scope, EG(scope))) { + retval = 0; + } + } + } + } + } + efree(lmname); + 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 TSRMLS_DC) +{ + char *lcname; zend_bool retval = 0; - int callable_name_len_local, clen, mlen; + int callable_name_len_local; zend_class_entry *ce_local, **pce; zend_function *fptr_local; zval **zobj_ptr_local; - HashTable *ftable; if (callable_name_len == NULL) { callable_name_len = &callable_name_len_local; @@ -2010,33 +2089,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char ** return 1; } - if ((colon = strstr(Z_STRVAL_P(callable), "::")) != NULL) { - clen = colon - Z_STRVAL_P(callable); - mlen = Z_STRLEN_P(callable) - clen - 2; - lcname = estrndup(Z_STRVAL_P(callable), clen); - lcname[clen] = '\0'; - lmname = zend_str_tolower_dup(Z_STRVAL_P(callable) + clen + 2, mlen); - if (zend_lookup_class(lcname, clen, &pce TSRMLS_CC) == FAILURE) { - efree(lcname); - efree(lmname); - return 0; - } - efree(lcname); - *ce_ptr = *pce; - ftable = &(*ce_ptr)->function_table; - } else { - mlen = Z_STRLEN_P(callable); - lmname = zend_str_tolower_dup(Z_STRVAL_P(callable), mlen); - ftable = EG(function_table); - } - - if (zend_hash_find(ftable, lmname, mlen+1, (void**)fptr_ptr) == SUCCESS) { - retval = 1; - } - if (*ce_ptr && *fptr_ptr && !((*fptr_ptr)->common.fn_flags & ZEND_ACC_STATIC)) { - retval = 0; - } - efree(lmname); + retval = zend_is_callable_check_func(check_flags|IS_CALLABLE_CHECK_IS_STATIC, NULL, NULL, callable, ce_ptr, fptr_ptr TSRMLS_CC); break; case IS_ARRAY: @@ -2065,7 +2118,6 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char ** } if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) { - *ce_ptr = ce; return 1; } @@ -2080,6 +2132,12 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char ** } efree(lcname); } + if (EG(This)) { + if (instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { + *zobj_ptr_ptr = &EG(This); + zend_error(E_STRICT, "Non-static method %s::%s() canot be called statically, assuming $this from compatible context %s", ce->name, Z_STRVAL_PP(method), Z_OBJCE_P(EG(This))->name); + } + } } else { ce = Z_OBJCE_PP(obj); /* TBFixed: what if it's overloaded? */ @@ -2104,38 +2162,12 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char ** } if (ce) { - zend_function *fbc; - - lcname = zend_str_tolower_dup(Z_STRVAL_PP(method), Z_STRLEN_PP(method)); - if (zend_hash_find(&ce->function_table, lcname, Z_STRLEN_PP(method)+1, (void **)&fbc) == SUCCESS) { - retval = 1; - if ((check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0) { - if (fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) { - if (!zend_check_private(fbc, (Z_TYPE_PP(obj) == IS_STRING)?EG(scope):(*obj)->value.obj.handlers->get_class_entry(*obj TSRMLS_CC), lcname, Z_STRLEN_PP(method) TSRMLS_CC)) { - retval = 0; - } - } else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) { - if (!zend_check_protected(fbc->common.scope, EG(scope))) { - retval = 0; - } - } - } - *fptr_ptr = fbc; - } - /* check for __call too */ - if (retval == 0 && *zobj_ptr_ptr && ce->__call != 0) { - retval = 1; - *fptr_ptr = ce->__call; - } - efree(lcname); + retval = zend_is_callable_check_func(check_flags, *zobj_ptr_ptr, ce, *method, ce_ptr, fptr_ptr TSRMLS_CC); } } else if (callable_name) { *callable_name = estrndup("Array", sizeof("Array")-1); *callable_name_len = sizeof("Array") - 1; } - if ((check_flags & IS_CALLABLE_CHECK_IS_STATIC) != 0 && !*zobj_ptr_ptr && (!*fptr_ptr || !((*fptr_ptr)->common.fn_flags & ZEND_ACC_STATIC))) { - retval = 0; - } *ce_ptr = ce; } break; |