diff options
| author | Dmitry Stogov <dmitry@zend.com> | 2014-12-03 16:56:09 +0300 |
|---|---|---|
| committer | Dmitry Stogov <dmitry@zend.com> | 2014-12-03 16:56:09 +0300 |
| commit | 5dd427eac2cdc97c2da03b7a97c59f5c2195832e (patch) | |
| tree | 476f6b6a7b827296f96c4d8058bfdffb3cff1f89 /Zend/zend_execute.c | |
| parent | e938064110e86a6b744fdff8137682edeb24f8c6 (diff) | |
| download | php-git-5dd427eac2cdc97c2da03b7a97c59f5c2195832e.tar.gz | |
Use zend_string* for op_array->arg_info[]->name and op_array->arg_info[]->class_name. For internal functions we still use char*.
Diffstat (limited to 'Zend/zend_execute.c')
| -rw-r--r-- | Zend/zend_execute.c | 65 |
1 files changed, 63 insertions, 2 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index e848e59dec..a9fadd10da 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -525,12 +525,12 @@ static inline zval* make_real_object(zval *object_ptr TSRMLS_DC) return object; } -ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce TSRMLS_DC) +ZEND_API char * zend_verify_internal_arg_class_kind(const zend_internal_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce TSRMLS_DC) { zend_string *key; ALLOCA_FLAG(use_heap); - STR_ALLOCA_INIT(key, cur_arg_info->class_name, cur_arg_info->class_name_len, use_heap); + STR_ALLOCA_INIT(key, cur_arg_info->class_name, strlen(cur_arg_info->class_name), use_heap); *pce = zend_fetch_class(key, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD) TSRMLS_CC); STR_ALLOCA_FREE(key, use_heap); @@ -542,6 +542,18 @@ ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ch } } +ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce TSRMLS_DC) +{ + *pce = zend_fetch_class(cur_arg_info->class_name, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD) TSRMLS_CC); + + *class_name = (*pce) ? (*pce)->name->val : cur_arg_info->class_name->val; + if (*pce && (*pce)->ce_flags & ZEND_ACC_INTERFACE) { + return "implement interface "; + } else { + return "be an instance of "; + } +} + ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, uint32_t arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC) { zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data; @@ -593,6 +605,55 @@ static int is_null_constant(zval *default_value TSRMLS_DC) return 0; } +static void zend_verify_internal_arg_type(zend_function *zf, uint32_t arg_num, zval *arg TSRMLS_DC) +{ + zend_internal_arg_info *cur_arg_info; + char *need_msg; + zend_class_entry *ce; + + if (UNEXPECTED(!zf->internal_function.arg_info)) { + return; + } + + if (EXPECTED(arg_num <= zf->internal_function.num_args)) { + cur_arg_info = &zf->internal_function.arg_info[arg_num-1]; + } else if (zf->internal_function.fn_flags & ZEND_ACC_VARIADIC) { + cur_arg_info = &zf->internal_function.arg_info[zf->internal_function.num_args-1]; + } else { + return; + } + + if (cur_arg_info->class_name) { + char *class_name; + + ZVAL_DEREF(arg); + if (Z_TYPE_P(arg) == IS_OBJECT) { + need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce TSRMLS_CC); + if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) { + zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg TSRMLS_CC); + } + } else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) { + need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce TSRMLS_CC); + zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg TSRMLS_CC); + } + } else if (cur_arg_info->type_hint) { + if (cur_arg_info->type_hint == IS_ARRAY) { + ZVAL_DEREF(arg); + if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) { + zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg TSRMLS_CC); + } + } else if (cur_arg_info->type_hint == IS_CALLABLE) { + if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL TSRMLS_CC) && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) { + zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg TSRMLS_CC); + } +#if ZEND_DEBUG + } else { + zend_error(E_ERROR, "Unknown typehint"); +#endif + } + } +} + static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value TSRMLS_DC) { zend_arg_info *cur_arg_info; |
