summaryrefslogtreecommitdiff
path: root/Zend/zend_builtin_functions.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_builtin_functions.c')
-rw-r--r--Zend/zend_builtin_functions.c488
1 files changed, 211 insertions, 277 deletions
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index 468a7c3446..33dfea0ea7 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2018 Zend Technologies Ltd. (http://www.zend.com) |
+ | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -56,6 +56,7 @@ static ZEND_FUNCTION(is_subclass_of);
static ZEND_FUNCTION(is_a);
static ZEND_FUNCTION(get_class_vars);
static ZEND_FUNCTION(get_object_vars);
+static ZEND_FUNCTION(get_mangled_object_vars);
static ZEND_FUNCTION(get_class_methods);
static ZEND_FUNCTION(trigger_error);
static ZEND_FUNCTION(set_error_handler);
@@ -145,6 +146,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_get_object_vars, 0, 0, 1)
ZEND_ARG_INFO(0, obj)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_get_mangled_object_vars, 0, 0, 1)
+ ZEND_ARG_INFO(0, obj)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class_methods, 0, 0, 1)
ZEND_ARG_INFO(0, class)
ZEND_END_ARG_INFO()
@@ -264,6 +269,7 @@ static const zend_function_entry builtin_functions[] = { /* {{{ */
ZEND_FE(is_a, arginfo_is_subclass_of)
ZEND_FE(get_class_vars, arginfo_get_class_vars)
ZEND_FE(get_object_vars, arginfo_get_object_vars)
+ ZEND_FE(get_mangled_object_vars, arginfo_get_mangled_object_vars)
ZEND_FE(get_class_methods, arginfo_get_class_methods)
ZEND_FE(trigger_error, arginfo_trigger_error)
ZEND_FALIAS(user_error, trigger_error, arginfo_trigger_error)
@@ -311,7 +317,7 @@ ZEND_MINIT_FUNCTION(core) { /* {{{ */
/* }}} */
zend_module_entry zend_builtin_module = { /* {{{ */
- STANDARD_MODULE_HEADER,
+ STANDARD_MODULE_HEADER,
"Core",
builtin_functions,
ZEND_MINIT(core),
@@ -540,10 +546,11 @@ ZEND_FUNCTION(func_get_args)
if (Z_OPT_REFCOUNTED_P(q)) {
Z_ADDREF_P(q);
}
+ ZEND_HASH_FILL_SET(q);
} else {
- q = &EG(uninitialized_zval);
+ ZEND_HASH_FILL_SET_NULL();
}
- ZEND_HASH_FILL_ADD(q);
+ ZEND_HASH_FILL_NEXT();
p++;
i++;
}
@@ -556,17 +563,18 @@ ZEND_FUNCTION(func_get_args)
if (Z_OPT_REFCOUNTED_P(q)) {
Z_ADDREF_P(q);
}
+ ZEND_HASH_FILL_SET(q);
} else {
- q = &EG(uninitialized_zval);
+ ZEND_HASH_FILL_SET_NULL();
}
- ZEND_HASH_FILL_ADD(q);
+ ZEND_HASH_FILL_NEXT();
p++;
i++;
}
} ZEND_HASH_FILL_END();
Z_ARRVAL_P(return_value)->nNumOfElements = arg_count;
} else {
- ZVAL_EMPTY_ARRAY(return_value);
+ RETURN_EMPTY_ARRAY();
}
}
/* }}} */
@@ -734,7 +742,12 @@ ZEND_FUNCTION(error_reporting)
old_error_reporting = EG(error_reporting);
if (ZEND_NUM_ARGS() != 0) {
- zend_string *new_val = zval_get_string(err);
+ zend_string *new_val = zval_try_get_string(err);
+
+ if (UNEXPECTED(!new_val)) {
+ return;
+ }
+
do {
zend_ini_entry *p = EG(error_reporting_ini_entry);
@@ -1008,7 +1021,7 @@ ZEND_FUNCTION(get_parent_class)
if (Z_TYPE_P(arg) == IS_OBJECT) {
ce = Z_OBJ_P(arg)->ce;
} else if (Z_TYPE_P(arg) == IS_STRING) {
- ce = zend_lookup_class(Z_STR_P(arg));
+ ce = zend_lookup_class(Z_STR_P(arg));
}
if (ce && ce->parent) {
@@ -1055,7 +1068,7 @@ static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass) /*
if (!only_subclass && EXPECTED(zend_string_equals(instance_ce->name, class_name))) {
retval = 1;
} else {
- ce = zend_lookup_class_ex(class_name, NULL, 0);
+ ce = zend_lookup_class_ex(class_name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
if (!ce) {
retval = 0;
} else {
@@ -1095,12 +1108,9 @@ static void add_class_vars(zend_class_entry *scope, zend_class_entry *ce, int st
zend_string *key;
ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
- if (((prop_info->flags & ZEND_ACC_SHADOW) &&
- prop_info->ce != scope) ||
- ((prop_info->flags & ZEND_ACC_PROTECTED) &&
- !zend_check_protected(prop_info->ce, scope)) ||
- ((prop_info->flags & ZEND_ACC_PRIVATE) &&
- ce != scope &&
+ if (((prop_info->flags & ZEND_ACC_PROTECTED) &&
+ !zend_check_protected(prop_info->ce, scope)) ||
+ ((prop_info->flags & ZEND_ACC_PRIVATE) &&
prop_info->ce != scope)) {
continue;
}
@@ -1111,13 +1121,17 @@ static void add_class_vars(zend_class_entry *scope, zend_class_entry *ce, int st
} else if (!statics && (prop_info->flags & ZEND_ACC_STATIC) == 0) {
prop = &ce->default_properties_table[OBJ_PROP_TO_NUM(prop_info->offset)];
}
- if (!prop || Z_TYPE_P(prop) == IS_UNDEF) {
+ if (!prop) {
continue;
}
- /* copy: enforce read only access */
- ZVAL_DEREF(prop);
- ZVAL_COPY_OR_DUP(&prop_copy, prop);
+ if (Z_ISUNDEF_P(prop)) {
+ /* Return uninitialized typed properties as a null value */
+ ZVAL_NULL(&prop_copy);
+ } else {
+ /* copy: enforce read only access */
+ ZVAL_COPY_OR_DUP(&prop_copy, prop);
+ }
prop = &prop_copy;
/* this is necessary to make it able to work with default array
@@ -1176,12 +1190,7 @@ ZEND_FUNCTION(get_object_vars)
Z_PARAM_OBJECT(obj)
ZEND_PARSE_PARAMETERS_END();
- if (Z_OBJ_HT_P(obj)->get_properties == NULL) {
- RETURN_FALSE;
- }
-
properties = Z_OBJ_HT_P(obj)->get_properties(obj);
-
if (properties == NULL) {
RETURN_FALSE;
}
@@ -1198,18 +1207,18 @@ ZEND_FUNCTION(get_object_vars)
array_init_size(return_value, zend_hash_num_elements(properties));
ZEND_HASH_FOREACH_KEY_VAL(properties, num_key, key, value) {
- zend_bool unmangle = 0;
+ zend_bool is_dynamic = 1;
if (Z_TYPE_P(value) == IS_INDIRECT) {
value = Z_INDIRECT_P(value);
if (UNEXPECTED(Z_ISUNDEF_P(value))) {
continue;
}
- ZEND_ASSERT(key);
- if (zend_check_property_access(zobj, key) == FAILURE) {
- continue;
- }
- unmangle = 1;
+ is_dynamic = 0;
+ }
+
+ if (key && zend_check_property_access(zobj, key, is_dynamic) == FAILURE) {
+ continue;
}
if (Z_ISREF_P(value) && Z_REFCOUNT_P(value) == 1) {
@@ -1220,7 +1229,7 @@ ZEND_FUNCTION(get_object_vars)
if (UNEXPECTED(!key)) {
/* This case is only possible due to loopholes, e.g. ArrayObject */
zend_hash_index_add(Z_ARRVAL_P(return_value), num_key, value);
- } else if (unmangle && ZSTR_VAL(key)[0] == 0) {
+ } else if (!is_dynamic && ZSTR_VAL(key)[0] == 0) {
const char *prop_name, *class_name;
size_t prop_len;
zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_len);
@@ -1238,6 +1247,31 @@ ZEND_FUNCTION(get_object_vars)
}
/* }}} */
+/* {{{ proto array get_mangled_object_vars(object obj)
+ Returns an array of mangled object properties. Does not respect property visibility. */
+ZEND_FUNCTION(get_mangled_object_vars)
+{
+ zval *obj;
+ HashTable *properties;
+
+ ZEND_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_OBJECT(obj)
+ ZEND_PARSE_PARAMETERS_END();
+
+ properties = Z_OBJ_HT_P(obj)->get_properties(obj);
+ if (!properties) {
+ ZVAL_EMPTY_ARRAY(return_value);
+ return;
+ }
+
+ properties = zend_proptable_to_symtable(properties,
+ (Z_OBJCE_P(obj)->default_properties_count ||
+ Z_OBJ_P(obj)->handlers != &std_object_handlers ||
+ GC_IS_RECURSIVE(properties)));
+ RETURN_ARR(properties);
+}
+/* }}} */
+
static int same_name(zend_string *key, zend_string *name) /* {{{ */
{
zend_string *lcname;
@@ -1274,7 +1308,7 @@ ZEND_FUNCTION(get_class_methods)
if (Z_TYPE_P(klass) == IS_OBJECT) {
ce = Z_OBJCE_P(klass);
} else if (Z_TYPE_P(klass) == IS_STRING) {
- ce = zend_lookup_class(Z_STR_P(klass));
+ ce = zend_lookup_class(Z_STR_P(klass));
}
if (!ce) {
@@ -1288,29 +1322,19 @@ ZEND_FUNCTION(get_class_methods)
if ((mptr->common.fn_flags & ZEND_ACC_PUBLIC)
|| (scope &&
- (((mptr->common.fn_flags & ZEND_ACC_PROTECTED) &&
- zend_check_protected(mptr->common.scope, scope))
+ (((mptr->common.fn_flags & ZEND_ACC_PROTECTED) &&
+ zend_check_protected(mptr->common.scope, scope))
|| ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) &&
- scope == mptr->common.scope)))) {
- size_t len = ZSTR_LEN(mptr->common.function_name);
-
- /* Do not display old-style inherited constructors */
- if (!key) {
+ scope == mptr->common.scope)))
+ ) {
+ if (mptr->type == ZEND_USER_FUNCTION &&
+ (!mptr->op_array.refcount || *mptr->op_array.refcount > 1) &&
+ key && !same_name(key, mptr->common.function_name)) {
+ ZVAL_STR_COPY(&method_name, zend_find_alias_name(mptr->common.scope, key));
+ zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
+ } else {
ZVAL_STR_COPY(&method_name, mptr->common.function_name);
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
- } else if ((mptr->common.fn_flags & ZEND_ACC_CTOR) == 0 ||
- mptr->common.scope == ce ||
- zend_binary_strcasecmp(ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(mptr->common.function_name), len) == 0) {
-
- if (mptr->type == ZEND_USER_FUNCTION &&
- (!mptr->op_array.refcount || *mptr->op_array.refcount > 1) &&
- !same_name(key, mptr->common.function_name)) {
- ZVAL_STR_COPY(&method_name, zend_find_alias_name(mptr->common.scope, key));
- zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
- } else {
- ZVAL_STR_COPY(&method_name, mptr->common.function_name);
- zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
- }
}
}
} ZEND_HASH_FOREACH_END();
@@ -1324,7 +1348,8 @@ ZEND_FUNCTION(method_exists)
zval *klass;
zend_string *method_name;
zend_string *lcname;
- zend_class_entry * ce;
+ zend_class_entry *ce;
+ zend_function *func;
ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_ZVAL(klass)
@@ -1342,28 +1367,33 @@ ZEND_FUNCTION(method_exists)
}
lcname = zend_string_tolower(method_name);
- if (zend_hash_exists(&ce->function_table, lcname)) {
- zend_string_release_ex(lcname, 0);
- RETURN_TRUE;
- } else if (Z_TYPE_P(klass) == IS_OBJECT && Z_OBJ_HT_P(klass)->get_method != NULL) {
+ func = zend_hash_find_ptr(&ce->function_table, lcname);
+ zend_string_release_ex(lcname, 0);
+
+ if (func) {
+ /* Exclude shadow properties when checking a method on a specific class. Include
+ * them when checking an object, as method_exists() generally ignores visibility.
+ * TODO: Should we use EG(scope) for the object case instead? */
+ RETURN_BOOL(Z_TYPE_P(klass) == IS_OBJECT
+ || !(func->common.fn_flags & ZEND_ACC_PRIVATE) || func->common.scope == ce);
+ }
+
+ if (Z_TYPE_P(klass) == IS_OBJECT) {
zend_object *obj = Z_OBJ_P(klass);
- zend_function *func = Z_OBJ_HT_P(klass)->get_method(&obj, method_name, NULL);
+ func = Z_OBJ_HT_P(klass)->get_method(&obj, method_name, NULL);
if (func != NULL) {
if (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
/* Returns true to the fake Closure's __invoke */
RETVAL_BOOL(func->common.scope == zend_ce_closure
&& zend_string_equals_literal(method_name, ZEND_INVOKE_FUNC_NAME));
- zend_string_release_ex(lcname, 0);
zend_string_release_ex(func->common.function_name, 0);
zend_free_trampoline(func);
return;
}
- zend_string_release_ex(lcname, 0);
RETURN_TRUE;
}
}
- zend_string_release_ex(lcname, 0);
RETURN_FALSE;
}
/* }}} */
@@ -1398,15 +1428,16 @@ ZEND_FUNCTION(property_exists)
RETURN_NULL();
}
- if ((property_info = zend_hash_find_ptr(&ce->properties_info, property)) != NULL
- && (property_info->flags & ZEND_ACC_SHADOW) == 0) {
+ property_info = zend_hash_find_ptr(&ce->properties_info, property);
+ if (property_info != NULL
+ && (!(property_info->flags & ZEND_ACC_PRIVATE)
+ || property_info->ce == ce)) {
RETURN_TRUE;
}
ZVAL_STR(&property_z, property);
if (Z_TYPE_P(object) == IS_OBJECT &&
- Z_OBJ_HANDLER_P(object, has_property) &&
Z_OBJ_HANDLER_P(object, has_property)(object, &property_z, 2, NULL)) {
RETURN_TRUE;
}
@@ -1414,77 +1445,55 @@ ZEND_FUNCTION(property_exists)
}
/* }}} */
-/* {{{ proto bool class_exists(string classname [, bool autoload])
- Checks if the class exists */
-ZEND_FUNCTION(class_exists)
+static inline void class_exists_impl(INTERNAL_FUNCTION_PARAMETERS, int flags, int skip_flags) /* {{{ */
{
- zend_string *class_name;
- zend_string *lc_name;
+ zend_string *name;
+ zend_string *lcname;
zend_class_entry *ce;
zend_bool autoload = 1;
ZEND_PARSE_PARAMETERS_START(1, 2)
- Z_PARAM_STR(class_name)
+ Z_PARAM_STR(name)
Z_PARAM_OPTIONAL
Z_PARAM_BOOL(autoload)
ZEND_PARSE_PARAMETERS_END();
if (!autoload) {
- if (ZSTR_VAL(class_name)[0] == '\\') {
+ if (ZSTR_VAL(name)[0] == '\\') {
/* Ignore leading "\" */
- lc_name = zend_string_alloc(ZSTR_LEN(class_name) - 1, 0);
- zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(class_name) + 1, ZSTR_LEN(class_name) - 1);
+ lcname = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
+ zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
} else {
- lc_name = zend_string_tolower(class_name);
+ lcname = zend_string_tolower(name);
}
- ce = zend_hash_find_ptr(EG(class_table), lc_name);
- zend_string_release_ex(lc_name, 0);
+ ce = zend_hash_find_ptr(EG(class_table), lcname);
+ zend_string_release_ex(lcname, 0);
} else {
- ce = zend_lookup_class(class_name);
+ ce = zend_lookup_class(name);
}
if (ce) {
- RETURN_BOOL((ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT)) == 0);
+ RETURN_BOOL(((ce->ce_flags & flags) == flags) && !(ce->ce_flags & skip_flags));
} else {
RETURN_FALSE;
}
}
+/* {{{ */
+
+/* {{{ proto bool class_exists(string classname [, bool autoload])
+ Checks if the class exists */
+ZEND_FUNCTION(class_exists)
+{
+ class_exists_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED, ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT);
+}
/* }}} */
/* {{{ proto bool interface_exists(string classname [, bool autoload])
Checks if the class exists */
ZEND_FUNCTION(interface_exists)
{
- zend_string *iface_name, *lc_name;
- zend_class_entry *ce;
- zend_bool autoload = 1;
-
- ZEND_PARSE_PARAMETERS_START(1, 2)
- Z_PARAM_STR(iface_name)
- Z_PARAM_OPTIONAL
- Z_PARAM_BOOL(autoload)
- ZEND_PARSE_PARAMETERS_END();
-
- if (!autoload) {
- if (ZSTR_VAL(iface_name)[0] == '\\') {
- /* Ignore leading "\" */
- lc_name = zend_string_alloc(ZSTR_LEN(iface_name) - 1, 0);
- zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(iface_name) + 1, ZSTR_LEN(iface_name) - 1);
- } else {
- lc_name = zend_string_tolower(iface_name);
- }
- ce = zend_hash_find_ptr(EG(class_table), lc_name);
- zend_string_release_ex(lc_name, 0);
- RETURN_BOOL(ce && ce->ce_flags & ZEND_ACC_INTERFACE);
- }
-
- ce = zend_lookup_class(iface_name);
- if (ce) {
- RETURN_BOOL((ce->ce_flags & ZEND_ACC_INTERFACE) > 0);
- } else {
- RETURN_FALSE;
- }
+ class_exists_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED|ZEND_ACC_INTERFACE, 0);
}
/* }}} */
@@ -1492,36 +1501,7 @@ ZEND_FUNCTION(interface_exists)
Checks if the trait exists */
ZEND_FUNCTION(trait_exists)
{
- zend_string *trait_name, *lc_name;
- zend_class_entry *ce;
- zend_bool autoload = 1;
-
- ZEND_PARSE_PARAMETERS_START(1, 2)
- Z_PARAM_STR(trait_name)
- Z_PARAM_OPTIONAL
- Z_PARAM_BOOL(autoload)
- ZEND_PARSE_PARAMETERS_END();
-
- if (!autoload) {
- if (ZSTR_VAL(trait_name)[0] == '\\') {
- /* Ignore leading "\" */
- lc_name = zend_string_alloc(ZSTR_LEN(trait_name) - 1, 0);
- zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(trait_name) + 1, ZSTR_LEN(trait_name) - 1);
- } else {
- lc_name = zend_string_tolower(trait_name);
- }
-
- ce = zend_hash_find_ptr(EG(class_table), lc_name);
- zend_string_release_ex(lc_name, 0);
- } else {
- ce = zend_lookup_class(trait_name);
- }
-
- if (ce) {
- RETURN_BOOL((ce->ce_flags & ZEND_ACC_TRAIT) != 0);
- } else {
- RETURN_FALSE;
- }
+ class_exists_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_TRAIT, 0);
}
/* }}} */
@@ -1571,7 +1551,7 @@ ZEND_FUNCTION(class_alias)
return;
}
- ce = zend_lookup_class_ex(class_name, NULL, autoload);
+ ce = zend_lookup_class_ex(class_name, NULL, !autoload ? ZEND_FETCH_CLASS_NO_AUTOLOAD : 0);
if (ce) {
if (ce->type == ZEND_USER_CLASS) {
@@ -1765,40 +1745,42 @@ ZEND_FUNCTION(restore_exception_handler)
}
/* }}} */
-static int copy_class_or_interface_name(zval *el, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
+static void copy_class_or_interface_name(zval *array, zend_string *key, zend_class_entry *ce) /* {{{ */
{
- zend_class_entry *ce = (zend_class_entry *)Z_PTR_P(el);
- zval *array = va_arg(args, zval *);
- uint32_t mask = va_arg(args, uint32_t);
- uint32_t comply = va_arg(args, uint32_t);
- uint32_t comply_mask = (comply)? mask:0;
-
- if ((hash_key->key && ZSTR_VAL(hash_key->key)[0] != 0)
- && (comply_mask == (ce->ce_flags & mask))) {
- if (ce->refcount > 1 &&
- !same_name(hash_key->key, ce->name)) {
- add_next_index_str(array, zend_string_copy(hash_key->key));
- } else {
- add_next_index_str(array, zend_string_copy(ce->name));
- }
+ if ((ce->refcount == 1 && !(ce->ce_flags & ZEND_ACC_IMMUTABLE)) ||
+ same_name(key, ce->name)) {
+ key = ce->name;
}
- return ZEND_HASH_APPLY_KEEP;
+ add_next_index_str(array, zend_string_copy(key));
}
/* }}} */
-/* {{{ proto array get_declared_traits()
- Returns an array of all declared traits. */
-ZEND_FUNCTION(get_declared_traits)
+static inline void get_declared_class_impl(INTERNAL_FUNCTION_PARAMETERS, int flags, int skip_flags) /* {{{ */
{
- uint32_t mask = ZEND_ACC_TRAIT;
- uint32_t comply = 1;
+ zend_string *key;
+ zend_class_entry *ce;
if (zend_parse_parameters_none() == FAILURE) {
return;
}
array_init(return_value);
- zend_hash_apply_with_arguments(EG(class_table), copy_class_or_interface_name, 3, return_value, mask, comply);
+ ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) {
+ if (key
+ && ZSTR_VAL(key)[0] != 0
+ && (ce->ce_flags & flags)
+ && !(ce->ce_flags & skip_flags)) {
+ copy_class_or_interface_name(return_value, key, ce);
+ }
+ } ZEND_HASH_FOREACH_END();
+}
+/* {{{ */
+
+/* {{{ proto array get_declared_traits()
+ Returns an array of all declared traits. */
+ZEND_FUNCTION(get_declared_traits)
+{
+ get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_TRAIT, 0);
}
/* }}} */
@@ -1806,15 +1788,7 @@ ZEND_FUNCTION(get_declared_traits)
Returns an array of all declared classes. */
ZEND_FUNCTION(get_declared_classes)
{
- uint32_t mask = ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT;
- uint32_t comply = 0;
-
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
-
- array_init(return_value);
- zend_hash_apply_with_arguments(EG(class_table), copy_class_or_interface_name, 3, return_value, mask, comply);
+ get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED, ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT);
}
/* }}} */
@@ -1822,37 +1796,7 @@ ZEND_FUNCTION(get_declared_classes)
Returns an array of all declared interfaces. */
ZEND_FUNCTION(get_declared_interfaces)
{
- uint32_t mask = ZEND_ACC_INTERFACE;
- uint32_t comply = 1;
-
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
-
- array_init(return_value);
- zend_hash_apply_with_arguments(EG(class_table), copy_class_or_interface_name, 3, return_value, mask, comply);
-}
-/* }}} */
-
-static int copy_function_name(zval *zv, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
-{
- zend_function *func = Z_PTR_P(zv);
- zval *internal_ar = va_arg(args, zval *),
- *user_ar = va_arg(args, zval *);
- zend_bool *exclude_disabled = va_arg(args, zend_bool *);
-
- if (hash_key->key == NULL || ZSTR_VAL(hash_key->key)[0] == 0) {
- return 0;
- }
-
- if (func->type == ZEND_INTERNAL_FUNCTION
- && (!*exclude_disabled || func->internal_function.handler != ZEND_FN(display_disabled_function))) {
- add_next_index_str(internal_ar, zend_string_copy(hash_key->key));
- } else if (func->type == ZEND_USER_FUNCTION) {
- add_next_index_str(user_ar, zend_string_copy(hash_key->key));
- }
-
- return 0;
+ get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_INTERFACE, 0);
}
/* }}} */
@@ -1861,6 +1805,8 @@ static int copy_function_name(zval *zv, int num_args, va_list args, zend_hash_ke
ZEND_FUNCTION(get_defined_functions)
{
zval internal, user;
+ zend_string *key;
+ zend_function *func;
zend_bool exclude_disabled = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &exclude_disabled) == FAILURE) {
@@ -1871,7 +1817,16 @@ ZEND_FUNCTION(get_defined_functions)
array_init(&user);
array_init(return_value);
- zend_hash_apply_with_arguments(EG(function_table), copy_function_name, 3, &internal, &user, &exclude_disabled);
+ ZEND_HASH_FOREACH_STR_KEY_PTR(EG(function_table), key, func) {
+ if (key && ZSTR_VAL(key)[0] != 0) {
+ if (func->type == ZEND_INTERNAL_FUNCTION
+ && (!exclude_disabled || func->internal_function.handler != ZEND_FN(display_disabled_function))) {
+ add_next_index_str(&internal, zend_string_copy(key));
+ } else if (func->type == ZEND_USER_FUNCTION) {
+ add_next_index_str(&user, zend_string_copy(key));
+ }
+ }
+ } ZEND_HASH_FOREACH_END();
zend_hash_str_add_new(Z_ARRVAL_P(return_value), "internal", sizeof("internal")-1, &internal);
zend_hash_str_add_new(Z_ARRVAL_P(return_value), "user", sizeof("user")-1, &user);
@@ -2043,15 +1998,6 @@ ZEND_FUNCTION(get_resources)
}
/* }}} */
-static int add_extension_info(zval *item, void *arg) /* {{{ */
-{
- zval *name_array = (zval *)arg;
- zend_module_entry *module = (zend_module_entry*)Z_PTR_P(item);
- add_next_index_string(name_array, module->name);
- return 0;
-}
-/* }}} */
-
static int add_zendext_info(zend_extension *ext, void *arg) /* {{{ */
{
zval *name_array = (zval *)arg;
@@ -2060,23 +2006,6 @@ static int add_zendext_info(zend_extension *ext, void *arg) /* {{{ */
}
/* }}} */
-static int add_constant_info(zval *item, void *arg) /* {{{ */
-{
- zval *name_array = (zval *)arg;
- zend_constant *constant = (zend_constant*)Z_PTR_P(item);
- zval const_val;
-
- if (!constant->name) {
- /* skip special constants */
- return 0;
- }
-
- ZVAL_COPY_OR_DUP(&const_val, &constant->value);
- zend_hash_add_new(Z_ARRVAL_P(name_array), constant->name, &const_val);
- return 0;
-}
-/* }}} */
-
/* {{{ proto array get_loaded_extensions([bool zend_extensions])
Return an array containing names of loaded extensions */
ZEND_FUNCTION(get_loaded_extensions)
@@ -2092,7 +2021,11 @@ ZEND_FUNCTION(get_loaded_extensions)
if (zendext) {
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t)add_zendext_info, return_value);
} else {
- zend_hash_apply_with_argument(&module_registry, add_extension_info, return_value);
+ zend_module_entry *module;
+
+ ZEND_HASH_FOREACH_PTR(&module_registry, module) {
+ add_next_index_string(return_value, module->name);
+ } ZEND_HASH_FOREACH_END();
}
}
/* }}} */
@@ -2154,7 +2087,17 @@ ZEND_FUNCTION(get_defined_constants)
efree(module_names);
efree(modules);
} else {
- zend_hash_apply_with_argument(EG(zend_constants), add_constant_info, return_value);
+ zend_constant *constant;
+ zval const_val;
+
+ ZEND_HASH_FOREACH_PTR(EG(zend_constants), constant) {
+ if (!constant->name) {
+ /* skip special constants */
+ continue;
+ }
+ ZVAL_COPY_OR_DUP(&const_val, &constant->value);
+ zend_hash_add_new(Z_ARRVAL_P(return_value), constant->name, &const_val);
+ } ZEND_HASH_FOREACH_END();
}
}
/* }}} */
@@ -2188,10 +2131,11 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) /
if (Z_OPT_REFCOUNTED_P(arg)) {
Z_ADDREF_P(arg);
}
- ZEND_HASH_FILL_ADD(arg);
+ ZEND_HASH_FILL_SET(arg);
} else {
- ZEND_HASH_FILL_ADD(&EG(uninitialized_zval));
+ ZEND_HASH_FILL_SET_NULL();
}
+ ZEND_HASH_FILL_NEXT();
i++;
}
} else {
@@ -2200,10 +2144,11 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) /
if (Z_OPT_REFCOUNTED_P(p)) {
Z_ADDREF_P(p);
}
- ZEND_HASH_FILL_ADD(p);
+ ZEND_HASH_FILL_SET(p);
} else {
- ZEND_HASH_FILL_ADD(&EG(uninitialized_zval));
+ ZEND_HASH_FILL_SET_NULL();
}
+ ZEND_HASH_FILL_NEXT();
p++;
i++;
}
@@ -2216,10 +2161,11 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) /
if (Z_OPT_REFCOUNTED_P(p)) {
Z_ADDREF_P(p);
}
- ZEND_HASH_FILL_ADD(p);
+ ZEND_HASH_FILL_SET(p);
} else {
- ZEND_HASH_FILL_ADD(&EG(uninitialized_zval));
+ ZEND_HASH_FILL_SET_NULL();
}
+ ZEND_HASH_FILL_NEXT();
p++;
i++;
}
@@ -2245,6 +2191,20 @@ void debug_print_backtrace_args(zval *arg_array) /* {{{ */
}
/* }}} */
+static inline zend_bool skip_internal_handler(zend_execute_data *skip) /* {{{ */
+{
+ return !(skip->func && ZEND_USER_CODE(skip->func->common.type))
+ && skip->prev_execute_data
+ && skip->prev_execute_data->func
+ && ZEND_USER_CODE(skip->prev_execute_data->func->common.type)
+ && skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL
+ && skip->prev_execute_data->opline->opcode != ZEND_DO_ICALL
+ && skip->prev_execute_data->opline->opcode != ZEND_DO_UCALL
+ && skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME
+ && skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL;
+}
+/* {{{ */
+
/* {{{ proto void debug_print_backtrace([int options[, int limit]]) */
ZEND_FUNCTION(debug_print_backtrace)
{
@@ -2283,15 +2243,7 @@ ZEND_FUNCTION(debug_print_backtrace)
skip = ptr;
/* skip internal handler */
- if ((!skip->func || !ZEND_USER_CODE(skip->func->common.type)) &&
- skip->prev_execute_data &&
- skip->prev_execute_data->func &&
- ZEND_USER_CODE(skip->prev_execute_data->func->common.type) &&
- skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
- skip->prev_execute_data->opline->opcode != ZEND_DO_ICALL &&
- skip->prev_execute_data->opline->opcode != ZEND_DO_UCALL &&
- skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
- skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
+ if (skip_internal_handler(skip)) {
skip = skip->prev_execute_data;
}
@@ -2318,16 +2270,16 @@ ZEND_FUNCTION(debug_print_backtrace)
zend_string *zend_function_name;
func = call->func;
- if (func->common.scope && func->common.scope->trait_aliases) {
- zend_function_name = zend_resolve_method_name(object ? object->ce : func->common.scope, func);
- } else {
- zend_function_name = func->common.function_name;
- }
- if (zend_function_name != NULL) {
- function_name = ZSTR_VAL(zend_function_name);
- } else {
- function_name = NULL;
- }
+ if (func->common.scope && func->common.scope->trait_aliases) {
+ zend_function_name = zend_resolve_method_name(object ? object->ce : func->common.scope, func);
+ } else {
+ zend_function_name = func->common.function_name;
+ }
+ if (zend_function_name != NULL) {
+ function_name = ZSTR_VAL(zend_function_name);
+ } else {
+ function_name = NULL;
+ }
} else {
func = NULL;
function_name = NULL;
@@ -2419,7 +2371,7 @@ ZEND_FUNCTION(debug_print_backtrace)
while (prev) {
if (prev_call &&
- prev_call->func &&
+ prev_call->func &&
!ZEND_USER_CODE(prev_call->func->common.type)) {
prev = NULL;
break;
@@ -2492,15 +2444,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
skip = ptr;
/* skip internal handler */
- if ((!skip->func || !ZEND_USER_CODE(skip->func->common.type)) &&
- skip->prev_execute_data &&
- skip->prev_execute_data->func &&
- ZEND_USER_CODE(skip->prev_execute_data->func->common.type) &&
- skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
- skip->prev_execute_data->opline->opcode != ZEND_DO_ICALL &&
- skip->prev_execute_data->opline->opcode != ZEND_DO_UCALL &&
- skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
- skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
+ if (skip_internal_handler(skip)) {
skip = skip->prev_execute_data;
}
@@ -2529,7 +2473,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
while (prev) {
if (prev_call &&
- prev_call->func &&
+ prev_call->func &&
!ZEND_USER_CODE(prev_call->func->common.type) &&
!(prev_call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
break;
@@ -2553,7 +2497,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
if (call && call->func) {
func = call->func;
function_name = (func->common.scope &&
- func->common.scope->trait_aliases) ?
+ func->common.scope->trait_aliases) ?
zend_resolve_method_name(
(object ? object->ce : func->common.scope), func) :
func->common.function_name;
@@ -2744,13 +2688,3 @@ ZEND_FUNCTION(get_extension_funcs)
}
}
/* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * indent-tabs-mode: t
- * End:
- * vim600: sw=4 ts=4 fdm=marker
- * vim<600: sw=4 ts=4
- */