diff options
| author | Remi Collet <remi@php.net> | 2017-06-26 17:22:01 +0200 |
|---|---|---|
| committer | Remi Collet <remi@php.net> | 2017-06-26 17:22:01 +0200 |
| commit | 85c32322acfc07628140bf631e7c52b12e6050b4 (patch) | |
| tree | ae79035283e68957177407123d7d342278e021d9 /Zend/zend_API.c | |
| parent | 4ed8ff509001b35e0cb971a1d6a294345c5d7673 (diff) | |
| parent | caaeb4849aa56cbbdc66ea015c11a58bd47a43ff (diff) | |
| download | php-git-85c32322acfc07628140bf631e7c52b12e6050b4.tar.gz | |
Merge branch 'master' of git.php.net:php-src
* 'master' of git.php.net:php-src: (24 commits)
Removed EG(valid_symbol_table). Used EG(active) instead.
Release temporary string reference
Remove superfluous semicolons
Fix tests on Windows
Produce a better exception message when IntlDateFormatter constructor fails.
Fix format arguments
Remove unused variable op2. It is redeclared later.
Fix typo
Implement object type annotation
Fixed bug #73173
Expose inflate_get_status() and inflate_get_read_len() functions
Add more constants, improve comments, and add tests
Fixed bug #73900
Add OPENSSL_DONT_ZERO_PAD_KEY constant to prevent key padding
Drop soap_hash_str_find_deref()
Only compute callback name in error cases
Extract zend_get_callable_name() API
Move va_copy compatibility code into zend_portability.h
Remove unnecessary string copy
Fix FE_FETCH_* exception check
...
Diffstat (limited to 'Zend/zend_API.c')
| -rw-r--r-- | Zend/zend_API.c | 144 |
1 files changed, 86 insertions, 58 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c index fef56750a2..bf2619e8e2 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -3241,14 +3241,86 @@ get_function_via_handler: } /* }}} */ -ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint32_t check_flags, zend_string **callable_name, zend_fcall_info_cache *fcc, char **error) /* {{{ */ +static zend_string *zend_create_method_string(zend_string *class_name, zend_string *method_name) { + zend_string *callable_name = zend_string_alloc( + ZSTR_LEN(class_name) + ZSTR_LEN(method_name) + sizeof("::") - 1, 0); + char *ptr = ZSTR_VAL(callable_name); + memcpy(ptr, ZSTR_VAL(class_name), ZSTR_LEN(class_name)); + ptr += ZSTR_LEN(class_name); + memcpy(ptr, "::", sizeof("::") - 1); + ptr += sizeof("::") - 1; + memcpy(ptr, ZSTR_VAL(method_name), ZSTR_LEN(method_name) + 1); + return callable_name; +} + +ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *object) /* {{{ */ +{ +try_again: + switch (Z_TYPE_P(callable)) { + case IS_STRING: + if (object) { + return zend_create_method_string(object->ce->name, Z_STR_P(callable)); + } + return zend_string_copy(Z_STR_P(callable)); + + case IS_ARRAY: + { + zval *method = NULL; + zval *obj = NULL; + + if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) { + obj = zend_hash_index_find_deref(Z_ARRVAL_P(callable), 0); + method = zend_hash_index_find_deref(Z_ARRVAL_P(callable), 1); + } + + if (obj == NULL || method == NULL || Z_TYPE_P(method) != IS_STRING) { + return zend_string_init("Array", sizeof("Array")-1, 0); + } + + if (Z_TYPE_P(obj) == IS_STRING) { + return zend_create_method_string(Z_STR_P(obj), Z_STR_P(method)); + } else if (Z_TYPE_P(obj) == IS_OBJECT) { + return zend_create_method_string(Z_OBJCE_P(obj)->name, Z_STR_P(method)); + } else { + return zend_string_init("Array", sizeof("Array")-1, 0); + } + } + case IS_OBJECT: + { + zend_class_entry *calling_scope; + zend_function *fptr; + zend_object *object; + if (Z_OBJ_HANDLER_P(callable, get_closure) + && Z_OBJ_HANDLER_P(callable, get_closure)(callable, &calling_scope, &fptr, &object) == SUCCESS) { + zend_class_entry *ce = Z_OBJCE_P(callable); + zend_string *callable_name = zend_string_alloc( + ZSTR_LEN(ce->name) + sizeof("::__invoke") - 1, 0); + memcpy(ZSTR_VAL(callable_name), ZSTR_VAL(ce->name), ZSTR_LEN(ce->name)); + memcpy(ZSTR_VAL(callable_name) + ZSTR_LEN(ce->name), "::__invoke", sizeof("::__invoke")); + return callable_name; + } + return zval_get_string(callable); + } + case IS_REFERENCE: + callable = Z_REFVAL_P(callable); + goto try_again; + default: + return zval_get_string(callable); + } +} +/* }}} */ + +ZEND_API zend_string *zend_get_callable_name(zval *callable) /* {{{ */ +{ + return zend_get_callable_name_ex(callable, NULL); +} +/* }}} */ + +static zend_bool zend_is_callable_impl(zval *callable, zend_object *object, uint32_t check_flags, zend_fcall_info_cache *fcc, char **error) /* {{{ */ { zend_bool ret; zend_fcall_info_cache fcc_local; - if (callable_name) { - *callable_name = NULL; - } if (fcc == NULL) { fcc = &fcc_local; } @@ -3274,20 +3346,8 @@ again: if (object) { fcc->object = object; fcc->calling_scope = object->ce; - if (callable_name) { - char *ptr; - - *callable_name = zend_string_alloc(ZSTR_LEN(fcc->calling_scope->name) + Z_STRLEN_P(callable) + sizeof("::") - 1, 0); - ptr = ZSTR_VAL(*callable_name); - memcpy(ptr, ZSTR_VAL(fcc->calling_scope->name), ZSTR_LEN(fcc->calling_scope->name)); - ptr += ZSTR_LEN(fcc->calling_scope->name); - memcpy(ptr, "::", sizeof("::") - 1); - ptr += sizeof("::") - 1; - memcpy(ptr, Z_STRVAL_P(callable), Z_STRLEN_P(callable) + 1); - } - } else if (callable_name) { - *callable_name = zend_string_copy(Z_STR_P(callable)); } + if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) { fcc->called_scope = fcc->calling_scope; return 1; @@ -3329,19 +3389,6 @@ again: ZVAL_DEREF(obj); if (Z_TYPE_P(obj) == IS_STRING) { - if (callable_name) { - char *ptr; - - - *callable_name = zend_string_alloc(Z_STRLEN_P(obj) + Z_STRLEN_P(method) + sizeof("::") - 1, 0); - ptr = ZSTR_VAL(*callable_name); - memcpy(ptr, Z_STRVAL_P(obj), Z_STRLEN_P(obj)); - ptr += Z_STRLEN_P(obj); - memcpy(ptr, "::", sizeof("::") - 1); - ptr += sizeof("::") - 1; - memcpy(ptr, Z_STRVAL_P(method), Z_STRLEN_P(method) + 1); - } - if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) { return 1; } @@ -3360,18 +3407,6 @@ again: fcc->object = Z_OBJ_P(obj); - if (callable_name) { - char *ptr; - - *callable_name = zend_string_alloc(ZSTR_LEN(fcc->calling_scope->name) + Z_STRLEN_P(method) + sizeof("::") - 1, 0); - ptr = ZSTR_VAL(*callable_name); - memcpy(ptr, ZSTR_VAL(fcc->calling_scope->name), ZSTR_LEN(fcc->calling_scope->name)); - ptr += ZSTR_LEN(fcc->calling_scope->name); - memcpy(ptr, "::", sizeof("::") - 1); - ptr += sizeof("::") - 1; - memcpy(ptr, Z_STRVAL_P(method), Z_STRLEN_P(method) + 1); - } - if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) { fcc->called_scope = fcc->calling_scope; return 1; @@ -3405,42 +3440,35 @@ again: } else { if (error) zend_spprintf(error, 0, "array must have exactly two members"); } - if (callable_name) { - *callable_name = zend_string_init("Array", sizeof("Array")-1, 0); - } } return 0; case IS_OBJECT: if (Z_OBJ_HANDLER_P(callable, get_closure) && Z_OBJ_HANDLER_P(callable, get_closure)(callable, &fcc->calling_scope, &fcc->function_handler, &fcc->object) == SUCCESS) { fcc->called_scope = fcc->calling_scope; - if (callable_name) { - zend_class_entry *ce = Z_OBJCE_P(callable); /* TBFixed: what if it's overloaded? */ - - *callable_name = zend_string_alloc(ZSTR_LEN(ce->name) + sizeof("::__invoke") - 1, 0); - memcpy(ZSTR_VAL(*callable_name), ZSTR_VAL(ce->name), ZSTR_LEN(ce->name)); - memcpy(ZSTR_VAL(*callable_name) + ZSTR_LEN(ce->name), "::__invoke", sizeof("::__invoke")); - } fcc->initialized = 1; return 1; } - if (callable_name) { - *callable_name = zval_get_string(callable); - } if (error) zend_spprintf(error, 0, "no array or string given"); return 0; case IS_REFERENCE: callable = Z_REFVAL_P(callable); goto again; default: - if (callable_name) { - *callable_name = zval_get_string(callable); - } if (error) zend_spprintf(error, 0, "no array or string given"); return 0; } } /* }}} */ +ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint32_t check_flags, zend_string **callable_name, zend_fcall_info_cache *fcc, char **error) /* {{{ */ +{ + zend_bool ret = zend_is_callable_impl(callable, object, check_flags, fcc, error); + if (callable_name) { + *callable_name = zend_get_callable_name_ex(callable, object); + } + return ret; +} + ZEND_API zend_bool zend_is_callable(zval *callable, uint32_t check_flags, zend_string **callable_name) /* {{{ */ { return zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, NULL); |
