summaryrefslogtreecommitdiff
path: root/Zend/zend_execute.c
diff options
context:
space:
mode:
authorJakub Zelenka <bukka@php.net>2015-02-08 14:08:31 +0000
committerJakub Zelenka <bukka@php.net>2015-02-08 14:08:31 +0000
commitf2825042b4dd9aa941a080c027f15f41c1b9e4bc (patch)
tree2e7d97c1dfd4aeabb506ffdd206a612b82adea8d /Zend/zend_execute.c
parent0a81f9a0bd36deac8707949acbcf92f612b60e8e (diff)
parentce9f52adcdfb19f70dc4274f3587e58ac07995bd (diff)
downloadphp-git-f2825042b4dd9aa941a080c027f15f41c1b9e4bc.tar.gz
Merge branch 'master' into jsond
Conflicts: ext/json/json.c
Diffstat (limited to 'Zend/zend_execute.c')
-rw-r--r--Zend/zend_execute.c54
1 files changed, 49 insertions, 5 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 7a79defb05..62064dcd5f 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -437,12 +437,13 @@ static zend_always_inline zval *_get_zval_ptr_ptr_var(uint32_t var, const zend_e
if (EXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
*should_free = NULL;
ret = Z_INDIRECT_P(ret);
- } else {
+ } else if (!Z_REFCOUNTED_P(ret)) {
+ *should_free = ret; /* immutable array may be converted to regular */
+ } else if (Z_REFCOUNT_P(ret) == 1) {
*should_free = ret;
- if (Z_REFCOUNTED_P(ret) && Z_REFCOUNT_P(ret) > 1) {
- *should_free = NULL;
- Z_DELREF_P(ret);
- }
+ } else {
+ *should_free = NULL;
+ Z_DELREF_P(ret);
}
return ret;
}
@@ -770,6 +771,49 @@ ZEND_API void zend_verify_return_error(int error_type, const zend_function *zf,
fclass, fsep, fname, need_msg, need_kind, returned_msg, returned_kind);
}
+#if ZEND_DEBUG
+static int zend_verify_internal_return_type(zend_function *zf, zval *ret)
+{
+ zend_arg_info *ret_info = zf->common.arg_info - 1;
+ char *need_msg;
+ zend_class_entry *ce;
+
+ if (ret_info->class_name) {
+ char *class_name;
+
+ if (Z_TYPE_P(ret) == IS_OBJECT) {
+ need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info *)ret_info, &class_name, &ce);
+ if (!ce || !instanceof_function(Z_OBJCE_P(ret), ce)) {
+ zend_verify_return_error(E_CORE_ERROR, zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val);
+ return 0;
+ }
+ } else if (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null) {
+ need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info *)ret_info, &class_name, &ce);
+ zend_verify_return_error(E_CORE_ERROR, zf, need_msg, class_name, zend_zval_type_name(ret), "");
+ return 0;
+ }
+ } else if (ret_info->type_hint) {
+ if (ret_info->type_hint == IS_ARRAY) {
+ if (Z_TYPE_P(ret) != IS_ARRAY && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) {
+ zend_verify_return_error(E_CORE_ERROR, zf, "be of the type array", "", zend_zval_type_name(ret), "");
+ return 0;
+ }
+ } else if (ret_info->type_hint == IS_CALLABLE) {
+ if (!zend_is_callable(ret, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) {
+ zend_verify_return_error(E_CORE_ERROR, zf, "be callable", "", zend_zval_type_name(ret), "");
+ return 0;
+ }
+#if ZEND_DEBUG
+ } else {
+ zend_error(E_CORE_ERROR, "Unknown typehint");
+ return 0;
+#endif
+ }
+ }
+ return 1;
+}
+#endif
+
static void zend_verify_return_type(zend_function *zf, zval *ret)
{
zend_arg_info *ret_info = zf->common.arg_info - 1;