diff options
Diffstat (limited to 'Zend/zend_builtin_functions.c')
-rw-r--r-- | Zend/zend_builtin_functions.c | 1105 |
1 files changed, 287 insertions, 818 deletions
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 33dfea0ea7..5ec365c920 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -27,281 +27,8 @@ #include "zend_extensions.h" #include "zend_closures.h" #include "zend_generators.h" +#include "zend_builtin_functions_arginfo.h" -static ZEND_FUNCTION(zend_version); -static ZEND_FUNCTION(func_num_args); -static ZEND_FUNCTION(func_get_arg); -static ZEND_FUNCTION(func_get_args); -static ZEND_FUNCTION(strlen); -static ZEND_FUNCTION(strcmp); -static ZEND_FUNCTION(strncmp); -static ZEND_FUNCTION(strcasecmp); -static ZEND_FUNCTION(strncasecmp); -static ZEND_FUNCTION(each); -static ZEND_FUNCTION(error_reporting); -static ZEND_FUNCTION(define); -static ZEND_FUNCTION(defined); -static ZEND_FUNCTION(get_class); -static ZEND_FUNCTION(get_called_class); -static ZEND_FUNCTION(get_parent_class); -static ZEND_FUNCTION(method_exists); -static ZEND_FUNCTION(property_exists); -static ZEND_FUNCTION(class_exists); -static ZEND_FUNCTION(interface_exists); -static ZEND_FUNCTION(trait_exists); -static ZEND_FUNCTION(function_exists); -static ZEND_FUNCTION(class_alias); -static ZEND_FUNCTION(get_included_files); -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); -static ZEND_FUNCTION(restore_error_handler); -static ZEND_FUNCTION(set_exception_handler); -static ZEND_FUNCTION(restore_exception_handler); -static ZEND_FUNCTION(get_declared_classes); -static ZEND_FUNCTION(get_declared_traits); -static ZEND_FUNCTION(get_declared_interfaces); -static ZEND_FUNCTION(get_defined_functions); -static ZEND_FUNCTION(get_defined_vars); -static ZEND_FUNCTION(create_function); -static ZEND_FUNCTION(get_resource_type); -static ZEND_FUNCTION(get_resources); -static ZEND_FUNCTION(get_loaded_extensions); -static ZEND_FUNCTION(extension_loaded); -static ZEND_FUNCTION(get_extension_funcs); -static ZEND_FUNCTION(get_defined_constants); -static ZEND_FUNCTION(debug_backtrace); -static ZEND_FUNCTION(debug_print_backtrace); -#if ZEND_DEBUG && defined(ZTS) -static ZEND_FUNCTION(zend_thread_id); -#endif -static ZEND_FUNCTION(gc_mem_caches); -static ZEND_FUNCTION(gc_collect_cycles); -static ZEND_FUNCTION(gc_enabled); -static ZEND_FUNCTION(gc_enable); -static ZEND_FUNCTION(gc_disable); -static ZEND_FUNCTION(gc_status); - -/* {{{ arginfo */ -ZEND_BEGIN_ARG_INFO(arginfo_zend__void, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_func_get_arg, 0, 0, 1) - ZEND_ARG_INFO(0, arg_num) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_strlen, 0, 0, 1) - ZEND_ARG_INFO(0, str) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_strcmp, 0, 0, 2) - ZEND_ARG_INFO(0, str1) - ZEND_ARG_INFO(0, str2) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_strncmp, 0, 0, 3) - ZEND_ARG_INFO(0, str1) - ZEND_ARG_INFO(0, str2) - ZEND_ARG_INFO(0, len) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_each, 0, 0, 1) - ZEND_ARG_INFO(1, arr) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_error_reporting, 0, 0, 0) - ZEND_ARG_INFO(0, new_error_level) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_define, 0, 0, 2) - ZEND_ARG_INFO(0, constant_name) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, case_insensitive) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_defined, 0, 0, 1) - ZEND_ARG_INFO(0, constant_name) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class, 0, 0, 0) - ZEND_ARG_INFO(0, object) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_is_subclass_of, 0, 0, 2) - ZEND_ARG_INFO(0, object) - ZEND_ARG_INFO(0, class_name) - ZEND_ARG_INFO(0, allow_string) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class_vars, 0, 0, 1) - ZEND_ARG_INFO(0, class_name) -ZEND_END_ARG_INFO() - -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() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_method_exists, 0, 0, 2) - ZEND_ARG_INFO(0, object) - ZEND_ARG_INFO(0, method) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_property_exists, 0, 0, 2) - ZEND_ARG_INFO(0, object_or_class) - ZEND_ARG_INFO(0, property_name) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_class_exists, 0, 0, 1) - ZEND_ARG_INFO(0, classname) - ZEND_ARG_INFO(0, autoload) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_trait_exists, 0, 0, 1) - ZEND_ARG_INFO(0, traitname) - ZEND_ARG_INFO(0, autoload) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_function_exists, 0, 0, 1) - ZEND_ARG_INFO(0, function_name) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_class_alias, 0, 0, 2) - ZEND_ARG_INFO(0, user_class_name) - ZEND_ARG_INFO(0, alias_name) - ZEND_ARG_INFO(0, autoload) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_trigger_error, 0, 0, 1) - ZEND_ARG_INFO(0, message) - ZEND_ARG_INFO(0, error_type) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_set_error_handler, 0, 0, 1) - ZEND_ARG_INFO(0, error_handler) - ZEND_ARG_INFO(0, error_types) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_set_exception_handler, 0, 0, 1) - ZEND_ARG_INFO(0, exception_handler) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_get_defined_functions, 0, 0, 0) - ZEND_ARG_INFO(0, exclude_disabled) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_create_function, 0, 0, 2) - ZEND_ARG_INFO(0, args) - ZEND_ARG_INFO(0, code) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_get_resource_type, 0, 0, 1) - ZEND_ARG_INFO(0, res) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_get_resources, 0, 0, 0) - ZEND_ARG_INFO(0, type) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_get_loaded_extensions, 0, 0, 0) - ZEND_ARG_INFO(0, zend_extensions) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_get_defined_constants, 0, 0, 0) - ZEND_ARG_INFO(0, categorize) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_debug_backtrace, 0, 0, 0) - ZEND_ARG_INFO(0, options) - ZEND_ARG_INFO(0, limit) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_debug_print_backtrace, 0, 0, 0) - ZEND_ARG_INFO(0, options) - ZEND_ARG_INFO(0, limit) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_extension_loaded, 0, 0, 1) - ZEND_ARG_INFO(0, extension_name) -ZEND_END_ARG_INFO() - -/* }}} */ - -static const zend_function_entry builtin_functions[] = { /* {{{ */ - ZEND_FE(zend_version, arginfo_zend__void) - ZEND_FE(func_num_args, arginfo_zend__void) - ZEND_FE(func_get_arg, arginfo_func_get_arg) - ZEND_FE(func_get_args, arginfo_zend__void) - ZEND_FE(strlen, arginfo_strlen) - ZEND_FE(strcmp, arginfo_strcmp) - ZEND_FE(strncmp, arginfo_strncmp) - ZEND_FE(strcasecmp, arginfo_strcmp) - ZEND_FE(strncasecmp, arginfo_strncmp) - ZEND_FE(each, arginfo_each) - ZEND_FE(error_reporting, arginfo_error_reporting) - ZEND_FE(define, arginfo_define) - ZEND_FE(defined, arginfo_defined) - ZEND_FE(get_class, arginfo_get_class) - ZEND_FE(get_called_class, arginfo_zend__void) - ZEND_FE(get_parent_class, arginfo_get_class) - ZEND_FE(method_exists, arginfo_method_exists) - ZEND_FE(property_exists, arginfo_property_exists) - ZEND_FE(class_exists, arginfo_class_exists) - ZEND_FE(interface_exists, arginfo_class_exists) - ZEND_FE(trait_exists, arginfo_trait_exists) - ZEND_FE(function_exists, arginfo_function_exists) - ZEND_FE(class_alias, arginfo_class_alias) - ZEND_FE(get_included_files, arginfo_zend__void) - ZEND_FALIAS(get_required_files, get_included_files, arginfo_zend__void) - ZEND_FE(is_subclass_of, arginfo_is_subclass_of) - 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) - ZEND_FE(set_error_handler, arginfo_set_error_handler) - ZEND_FE(restore_error_handler, arginfo_zend__void) - ZEND_FE(set_exception_handler, arginfo_set_exception_handler) - ZEND_FE(restore_exception_handler, arginfo_zend__void) - ZEND_FE(get_declared_classes, arginfo_zend__void) - ZEND_FE(get_declared_traits, arginfo_zend__void) - ZEND_FE(get_declared_interfaces, arginfo_zend__void) - ZEND_FE(get_defined_functions, arginfo_get_defined_functions) - ZEND_FE(get_defined_vars, arginfo_zend__void) - ZEND_DEP_FE(create_function, arginfo_create_function) - ZEND_FE(get_resource_type, arginfo_get_resource_type) - ZEND_FE(get_resources, arginfo_get_resources) - ZEND_FE(get_loaded_extensions, arginfo_get_loaded_extensions) - ZEND_FE(extension_loaded, arginfo_extension_loaded) - ZEND_FE(get_extension_funcs, arginfo_extension_loaded) - ZEND_FE(get_defined_constants, arginfo_get_defined_constants) - ZEND_FE(debug_backtrace, arginfo_debug_backtrace) - ZEND_FE(debug_print_backtrace, arginfo_debug_print_backtrace) -#if ZEND_DEBUG && defined(ZTS) - ZEND_FE(zend_thread_id, NULL) -#endif - ZEND_FE(gc_mem_caches, arginfo_zend__void) - ZEND_FE(gc_collect_cycles, arginfo_zend__void) - ZEND_FE(gc_enabled, arginfo_zend__void) - ZEND_FE(gc_enable, arginfo_zend__void) - ZEND_FE(gc_disable, arginfo_zend__void) - ZEND_FE(gc_status, arginfo_zend__void) - ZEND_FE_END -}; /* }}} */ ZEND_MINIT_FUNCTION(core) { /* {{{ */ @@ -319,7 +46,7 @@ ZEND_MINIT_FUNCTION(core) { /* {{{ */ zend_module_entry zend_builtin_module = { /* {{{ */ STANDARD_MODULE_HEADER, "Core", - builtin_functions, + ext_functions, ZEND_MINIT(core), NULL, NULL, @@ -330,7 +57,7 @@ zend_module_entry zend_builtin_module = { /* {{{ */ }; /* }}} */ -int zend_startup_builtin_functions(void) /* {{{ */ +zend_result zend_startup_builtin_functions(void) /* {{{ */ { zend_builtin_module.module_number = 0; zend_builtin_module.type = MODULE_PERSISTENT; @@ -338,65 +65,50 @@ int zend_startup_builtin_functions(void) /* {{{ */ } /* }}} */ -/* {{{ proto string zend_version(void) - Get the version of the Zend Engine */ +/* {{{ Get the version of the Zend Engine */ ZEND_FUNCTION(zend_version) { - if (zend_parse_parameters_none() == FAILURE) { - return; - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_STRINGL(ZEND_VERSION, sizeof(ZEND_VERSION)-1); } /* }}} */ -/* {{{ proto int gc_mem_caches(void) - Reclaims memory used by MM caches. +/* {{{ Reclaims memory used by MM caches. Returns number of freed bytes */ ZEND_FUNCTION(gc_mem_caches) { - if (zend_parse_parameters_none() == FAILURE) { - return; - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_LONG(zend_mm_gc(zend_mm_get_heap())); } /* }}} */ -/* {{{ proto int gc_collect_cycles(void) - Forces collection of any existing garbage cycles. +/* {{{ Forces collection of any existing garbage cycles. Returns number of freed zvals */ ZEND_FUNCTION(gc_collect_cycles) { - if (zend_parse_parameters_none() == FAILURE) { - return; - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_LONG(gc_collect_cycles()); } /* }}} */ -/* {{{ proto void gc_enabled(void) - Returns status of the circular reference collector */ +/* {{{ Returns status of the circular reference collector */ ZEND_FUNCTION(gc_enabled) { - if (zend_parse_parameters_none() == FAILURE) { - return; - } + ZEND_PARSE_PARAMETERS_NONE(); RETURN_BOOL(gc_enabled()); } /* }}} */ -/* {{{ proto void gc_enable(void) - Activates the circular reference collector */ +/* {{{ Activates the circular reference collector */ ZEND_FUNCTION(gc_enable) { zend_string *key; - if (zend_parse_parameters_none() == FAILURE) { - return; - } + ZEND_PARSE_PARAMETERS_NONE(); key = zend_string_init("zend.enable_gc", sizeof("zend.enable_gc")-1, 0); zend_alter_ini_entry_chars(key, "1", sizeof("1")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME); @@ -404,15 +116,12 @@ ZEND_FUNCTION(gc_enable) } /* }}} */ -/* {{{ proto void gc_disable(void) - Deactivates the circular reference collector */ +/* {{{ Deactivates the circular reference collector */ ZEND_FUNCTION(gc_disable) { zend_string *key; - if (zend_parse_parameters_none() == FAILURE) { - return; - } + ZEND_PARSE_PARAMETERS_NONE(); key = zend_string_init("zend.enable_gc", sizeof("zend.enable_gc")-1, 0); zend_alter_ini_entry_chars(key, "0", sizeof("0")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME); @@ -420,15 +129,12 @@ ZEND_FUNCTION(gc_disable) } /* }}} */ -/* {{{ proto array gc_status(void) - Returns current GC statistics */ +/* {{{ Returns current GC statistics */ ZEND_FUNCTION(gc_status) { zend_gc_status status; - if (zend_parse_parameters_none() == FAILURE) { - return; - } + ZEND_PARSE_PARAMETERS_NONE(); zend_gc_get_status(&status); @@ -441,19 +147,16 @@ ZEND_FUNCTION(gc_status) } /* }}} */ -/* {{{ proto int func_num_args(void) - Get the number of arguments that were passed to the function */ +/* {{{ Get the number of arguments that were passed to the function */ ZEND_FUNCTION(func_num_args) { zend_execute_data *ex = EX(prev_execute_data); - if (zend_parse_parameters_none() == FAILURE) { - return; - } + ZEND_PARSE_PARAMETERS_NONE(); if (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE) { - zend_error(E_WARNING, "func_num_args(): Called from the global scope - no function context"); - RETURN_LONG(-1); + zend_throw_error(NULL, "func_num_args() must be called from a function context"); + RETURN_THROWS(); } if (zend_forbid_dynamic_call("func_num_args()") == FAILURE) { @@ -464,8 +167,7 @@ ZEND_FUNCTION(func_num_args) } /* }}} */ -/* {{{ proto mixed func_get_arg(int arg_num) - Get the $arg_num'th argument that was passed to the function */ +/* {{{ Get the $arg_num'th argument that was passed to the function */ ZEND_FUNCTION(func_get_arg) { uint32_t arg_count, first_extra_arg; @@ -474,29 +176,29 @@ ZEND_FUNCTION(func_get_arg) zend_execute_data *ex; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &requested_offset) == FAILURE) { - return; + RETURN_THROWS(); } if (requested_offset < 0) { - zend_error(E_WARNING, "func_get_arg(): The argument number should be >= 0"); - RETURN_FALSE; + zend_argument_value_error(1, "must be greater than or equal to 0"); + RETURN_THROWS(); } ex = EX(prev_execute_data); if (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE) { - zend_error(E_WARNING, "func_get_arg(): Called from the global scope - no function context"); - RETURN_FALSE; + zend_throw_error(NULL, "func_get_arg() cannot be called from the global scope"); + RETURN_THROWS(); } if (zend_forbid_dynamic_call("func_get_arg()") == FAILURE) { - RETURN_FALSE; + RETURN_THROWS(); } arg_count = ZEND_CALL_NUM_ARGS(ex); if ((zend_ulong)requested_offset >= arg_count) { - zend_error(E_WARNING, "func_get_arg(): Argument " ZEND_LONG_FMT " not passed to function", requested_offset); - RETURN_FALSE; + zend_argument_value_error(1, "must be less than the number of the arguments passed to the currently executed function"); + RETURN_THROWS(); } first_extra_arg = ex->func->op_array.num_args; @@ -511,8 +213,7 @@ ZEND_FUNCTION(func_get_arg) } /* }}} */ -/* {{{ proto array func_get_args() - Get an array of the arguments that were passed to the function */ +/* {{{ Get an array of the arguments that were passed to the function */ ZEND_FUNCTION(func_get_args) { zval *p, *q; @@ -520,13 +221,15 @@ ZEND_FUNCTION(func_get_args) uint32_t i; zend_execute_data *ex = EX(prev_execute_data); + ZEND_PARSE_PARAMETERS_NONE(); + if (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE) { - zend_error(E_WARNING, "func_get_args(): Called from the global scope - no function context"); - RETURN_FALSE; + zend_throw_error(NULL, "func_get_args() cannot be called from the global scope"); + RETURN_THROWS(); } if (zend_forbid_dynamic_call("func_get_args()") == FAILURE) { - RETURN_FALSE; + RETURN_THROWS(); } arg_count = ZEND_CALL_NUM_ARGS(ex); @@ -579,8 +282,7 @@ ZEND_FUNCTION(func_get_args) } /* }}} */ -/* {{{ proto int strlen(string str) - Get string length +/* {{{ Get string length Warning: This function is special-cased by zend_compile.c and so is usually bypassed */ ZEND_FUNCTION(strlen) { @@ -594,8 +296,7 @@ ZEND_FUNCTION(strlen) } /* }}} */ -/* {{{ proto int strcmp(string str1, string str2) - Binary safe string comparison */ +/* {{{ Binary safe string comparison */ ZEND_FUNCTION(strcmp) { zend_string *s1, *s2; @@ -609,8 +310,7 @@ ZEND_FUNCTION(strcmp) } /* }}} */ -/* {{{ proto int strncmp(string str1, string str2, int len) - Binary safe string comparison */ +/* {{{ Binary safe string comparison */ ZEND_FUNCTION(strncmp) { zend_string *s1, *s2; @@ -623,16 +323,15 @@ ZEND_FUNCTION(strncmp) ZEND_PARSE_PARAMETERS_END(); if (len < 0) { - zend_error(E_WARNING, "Length must be greater than or equal to 0"); - RETURN_FALSE; + zend_argument_value_error(3, "must be greater than or equal to 0"); + RETURN_THROWS(); } RETURN_LONG(zend_binary_strncmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2), len)); } /* }}} */ -/* {{{ proto int strcasecmp(string str1, string str2) - Binary safe case-insensitive string comparison */ +/* {{{ Binary safe case-insensitive string comparison */ ZEND_FUNCTION(strcasecmp) { zend_string *s1, *s2; @@ -646,8 +345,7 @@ ZEND_FUNCTION(strcasecmp) } /* }}} */ -/* {{{ proto int strncasecmp(string str1, string str2, int len) - Binary safe string comparison */ +/* {{{ Binary safe string comparison */ ZEND_FUNCTION(strncasecmp) { zend_string *s1, *s2; @@ -660,92 +358,32 @@ ZEND_FUNCTION(strncasecmp) ZEND_PARSE_PARAMETERS_END(); if (len < 0) { - zend_error(E_WARNING, "Length must be greater than or equal to 0"); - RETURN_FALSE; + zend_argument_value_error(3, "must be greater than or equal to 0"); + RETURN_THROWS(); } RETURN_LONG(zend_binary_strncasecmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2), len)); } /* }}} */ -/* {{{ proto mixed each(array &arr) - Return the currently pointed key..value pair in the passed array, and advance the pointer to the next element, or false if there is no element at this place */ -ZEND_FUNCTION(each) -{ - zval *array, *entry, tmp; - zend_ulong num_key; - HashTable *target_hash; - zend_string *key; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "z/", &array) == FAILURE) { - return; - } - - if (!EG(each_deprecation_thrown)) { - zend_error(E_DEPRECATED, "The each() function is deprecated. This message will be suppressed on further calls"); - EG(each_deprecation_thrown) = 1; - } - - target_hash = HASH_OF(array); - if (!target_hash) { - zend_error(E_WARNING,"Variable passed to each() is not an array or object"); - return; - } - while (1) { - entry = zend_hash_get_current_data(target_hash); - if (!entry) { - RETURN_FALSE; - } else if (Z_TYPE_P(entry) == IS_INDIRECT) { - entry = Z_INDIRECT_P(entry); - if (Z_TYPE_P(entry) == IS_UNDEF) { - zend_hash_move_forward(target_hash); - continue; - } - } - break; - } - array_init_size(return_value, 4); - zend_hash_real_init_mixed(Z_ARRVAL_P(return_value)); - - /* add value elements */ - ZVAL_DEREF(entry); - if (Z_REFCOUNTED_P(entry)) { - GC_ADDREF_EX(Z_COUNTED_P(entry), 2); - } - zend_hash_index_add_new(Z_ARRVAL_P(return_value), 1, entry); - zend_hash_add_new(Z_ARRVAL_P(return_value), ZSTR_KNOWN(ZEND_STR_VALUE), entry); - - /* add the key elements */ - if (zend_hash_get_current_key(target_hash, &key, &num_key) == HASH_KEY_IS_STRING) { - ZVAL_STR_COPY(&tmp, key); - Z_TRY_ADDREF(tmp); - } else { - ZVAL_LONG(&tmp, num_key); - } - zend_hash_index_add_new(Z_ARRVAL_P(return_value), 0, &tmp); - zend_hash_add_new(Z_ARRVAL_P(return_value), ZSTR_KNOWN(ZEND_STR_KEY), &tmp); - zend_hash_move_forward(target_hash); -} -/* }}} */ - -/* {{{ proto int error_reporting([int new_error_level]) - Return the current error_reporting level, and if an argument was passed - change to the new level */ +/* {{{ Return the current error_reporting level, and if an argument was passed - change to the new level */ ZEND_FUNCTION(error_reporting) { - zval *err = NULL; + zend_long err; + zend_bool err_is_null = 1; int old_error_reporting; ZEND_PARSE_PARAMETERS_START(0, 1) Z_PARAM_OPTIONAL - Z_PARAM_ZVAL(err) + Z_PARAM_LONG_OR_NULL(err, err_is_null) ZEND_PARSE_PARAMETERS_END(); old_error_reporting = EG(error_reporting); - if (ZEND_NUM_ARGS() != 0) { - zend_string *new_val = zval_try_get_string(err); + if (!err_is_null) { + zend_string *new_val = zend_long_to_str(err); if (UNEXPECTED(!new_val)) { - return; + RETURN_THROWS(); } do { @@ -774,11 +412,7 @@ ZEND_FUNCTION(error_reporting) } p->value = new_val; - if (Z_TYPE_P(err) == IS_LONG) { - EG(error_reporting) = Z_LVAL_P(err); - } else { - EG(error_reporting) = atoi(ZSTR_VAL(p->value)); - } + EG(error_reporting) = err; } while (0); } @@ -786,9 +420,9 @@ ZEND_FUNCTION(error_reporting) } /* }}} */ -static int validate_constant_array(HashTable *ht) /* {{{ */ +static bool validate_constant_array_argument(HashTable *ht, int argument_number) /* {{{ */ { - int ret = 1; + bool ret = 1; zval *val; GC_PROTECT_RECURSION(ht); @@ -798,16 +432,16 @@ static int validate_constant_array(HashTable *ht) /* {{{ */ if (Z_TYPE_P(val) == IS_ARRAY) { if (Z_REFCOUNTED_P(val)) { if (Z_IS_RECURSIVE_P(val)) { - zend_error(E_WARNING, "Constants cannot be recursive arrays"); + zend_argument_value_error(argument_number, "cannot be a recursive array"); ret = 0; break; - } else if (!validate_constant_array(Z_ARRVAL_P(val))) { + } else if (!validate_constant_array_argument(Z_ARRVAL_P(val), argument_number)) { ret = 0; break; } } } else if (Z_TYPE_P(val) != IS_STRING && Z_TYPE_P(val) != IS_RESOURCE) { - zend_error(E_WARNING, "Constants may only evaluate to scalar values, arrays or resources"); + zend_argument_type_error(argument_number, "cannot be an object, %s given", zend_zval_type_name(val)); ret = 0; break; } @@ -844,14 +478,12 @@ static void copy_constant_array(zval *dst, zval *src) /* {{{ */ } /* }}} */ -/* {{{ proto bool define(string constant_name, mixed value[, bool case_insensitive]) - Define a new constant */ +/* {{{ Define a new constant */ ZEND_FUNCTION(define) { zend_string *name; zval *val, val_free; zend_bool non_cs = 0; - int case_sensitive = CONST_CS; zend_constant c; ZEND_PARSE_PARAMETERS_START(2, 3) @@ -861,18 +493,17 @@ ZEND_FUNCTION(define) Z_PARAM_BOOL(non_cs) ZEND_PARSE_PARAMETERS_END(); - if (non_cs) { - case_sensitive = 0; - } - if (zend_memnstr(ZSTR_VAL(name), "::", sizeof("::") - 1, ZSTR_VAL(name) + ZSTR_LEN(name))) { - zend_error(E_WARNING, "Class constants cannot be defined or redefined"); - RETURN_FALSE; + zend_argument_value_error(1, "cannot be a class constant"); + RETURN_THROWS(); } + if (non_cs) { + zend_error(E_WARNING, "define(): Argument #3 ($case_insensitive) is ignored since declaration of case-insensitive constants is no longer supported"); + } + ZVAL_UNDEF(&val_free); -repeat: switch (Z_TYPE_P(val)) { case IS_LONG: case IS_DOUBLE: @@ -884,8 +515,8 @@ repeat: break; case IS_ARRAY: if (Z_REFCOUNTED_P(val)) { - if (!validate_constant_array(Z_ARRVAL_P(val))) { - RETURN_FALSE; + if (!validate_constant_array_argument(Z_ARRVAL_P(val), 2)) { + RETURN_THROWS(); } else { copy_constant_array(&c.value, val); goto register_constant; @@ -893,35 +524,23 @@ repeat: } break; case IS_OBJECT: - if (Z_TYPE(val_free) == IS_UNDEF) { - if (Z_OBJ_HT_P(val)->get) { - val = Z_OBJ_HT_P(val)->get(val, &val_free); - goto repeat; - } else if (Z_OBJ_HT_P(val)->cast_object) { - if (Z_OBJ_HT_P(val)->cast_object(val, &val_free, IS_STRING) == SUCCESS) { - val = &val_free; - break; - } - } + if (Z_OBJ_HT_P(val)->cast_object(Z_OBJ_P(val), &val_free, IS_STRING) == SUCCESS) { + val = &val_free; + break; } /* no break */ default: - zend_error(E_WARNING, "Constants may only evaluate to scalar values, arrays or resources"); zval_ptr_dtor(&val_free); - RETURN_FALSE; + zend_argument_type_error(2, "cannot be an object, %s given", zend_zval_type_name(val)); + RETURN_THROWS(); } ZVAL_COPY(&c.value, val); zval_ptr_dtor(&val_free); register_constant: - if (non_cs) { - zend_error(E_DEPRECATED, - "define(): Declaration of case-insensitive constants is deprecated"); - } - /* non persistent */ - ZEND_CONSTANT_SET_FLAGS(&c, case_sensitive, PHP_USER_CONSTANT); + ZEND_CONSTANT_SET_FLAGS(&c, CONST_CS, PHP_USER_CONSTANT); c.name = zend_string_copy(name); if (zend_register_constant(&c) == SUCCESS) { RETURN_TRUE; @@ -931,8 +550,7 @@ register_constant: } /* }}} */ -/* {{{ proto bool defined(string constant_name) - Check whether a constant exists +/* {{{ Check whether a constant exists Warning: This function is special-cased by zend_compile.c and so is usually bypassed */ ZEND_FUNCTION(defined) { @@ -942,7 +560,7 @@ ZEND_FUNCTION(defined) Z_PARAM_STR(name) ZEND_PARSE_PARAMETERS_END(); - if (zend_get_constant_ex(name, zend_get_executed_scope(), ZEND_FETCH_CLASS_SILENT | ZEND_GET_CONSTANT_NO_DEPRECATION_CHECK)) { + if (zend_get_constant_ex(name, zend_get_executed_scope(), ZEND_FETCH_CLASS_SILENT)) { RETURN_TRUE; } else { RETURN_FALSE; @@ -950,14 +568,13 @@ ZEND_FUNCTION(defined) } /* }}} */ -/* {{{ proto string get_class([object object]) - Retrieves the class name */ +/* {{{ Retrieves the class name */ ZEND_FUNCTION(get_class) { zval *obj = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|o", &obj) == FAILURE) { - RETURN_FALSE; + RETURN_THROWS(); } if (!obj) { @@ -966,8 +583,8 @@ ZEND_FUNCTION(get_class) if (scope) { RETURN_STR_COPY(scope->name); } else { - zend_error(E_WARNING, "get_class() called without object from outside a class"); - RETURN_FALSE; + zend_throw_error(NULL, "get_class() without arguments must be called from within a class"); + RETURN_THROWS(); } } @@ -975,53 +592,35 @@ ZEND_FUNCTION(get_class) } /* }}} */ -/* {{{ proto string get_called_class() - Retrieves the "Late Static Binding" class name */ +/* {{{ Retrieves the "Late Static Binding" class name */ ZEND_FUNCTION(get_called_class) { zend_class_entry *called_scope; - if (zend_parse_parameters_none() == FAILURE) { - return; - } + ZEND_PARSE_PARAMETERS_NONE(); called_scope = zend_get_called_scope(execute_data); - if (called_scope) { - RETURN_STR_COPY(called_scope->name); - } else { - zend_class_entry *scope = zend_get_executed_scope(); - if (!scope) { - zend_error(E_WARNING, "get_called_class() called from outside a class"); - } + if (!called_scope) { + zend_throw_error(NULL, "get_called_class() must be called from within a class"); + RETURN_THROWS(); } - RETURN_FALSE; + + RETURN_STR_COPY(called_scope->name); } /* }}} */ -/* {{{ proto mixed get_parent_class([mixed object]) - Retrieves the parent class name for object or class or current scope or false if not in a scope. */ +/* {{{ Retrieves the parent class name for object or class or current scope or false if not in a scope. */ ZEND_FUNCTION(get_parent_class) { - zval *arg; zend_class_entry *ce = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|z", &arg) == FAILURE) { - return; - } + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_OBJ_OR_CLASS_NAME(ce) + ZEND_PARSE_PARAMETERS_END(); - if (!ZEND_NUM_ARGS()) { + if (!ce) { ce = zend_get_executed_scope(); - if (ce && ce->parent) { - RETURN_STR_COPY(ce->parent->name); - } else { - RETURN_FALSE; - } - } - - 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)); } if (ce && ce->parent) { @@ -1084,16 +683,14 @@ static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass) /* } /* }}} */ -/* {{{ proto bool is_subclass_of(mixed object_or_string, string class_name [, bool allow_string]) - Returns true if the object has this class as one of its parents */ +/* {{{ Returns true if the object has this class as one of its parents */ ZEND_FUNCTION(is_subclass_of) { is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } /* }}} */ -/* {{{ proto bool is_a(mixed object_or_string, string class_name [, bool allow_string]) - Returns true if the first argument is an object and is this class or has this class as one of its parents, */ +/* {{{ Returns true if the first argument is an object and is this class or has this class as one of its parents, */ ZEND_FUNCTION(is_a) { is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); @@ -1101,7 +698,7 @@ ZEND_FUNCTION(is_a) /* }}} */ /* {{{ add_class_vars */ -static void add_class_vars(zend_class_entry *scope, zend_class_entry *ce, int statics, zval *return_value) +static void add_class_vars(zend_class_entry *scope, zend_class_entry *ce, bool statics, zval *return_value) { zend_property_info *prop_info; zval *prop, prop_copy; @@ -1147,36 +744,29 @@ static void add_class_vars(zend_class_entry *scope, zend_class_entry *ce, int st } /* }}} */ -/* {{{ proto array get_class_vars(string class_name) - Returns an array of default properties of the class. */ +/* {{{ Returns an array of default properties of the class. */ ZEND_FUNCTION(get_class_vars) { - zend_string *class_name; - zend_class_entry *ce, *scope; + zend_class_entry *ce = NULL, *scope; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &class_name) == FAILURE) { - return; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "C", &ce) == FAILURE) { + RETURN_THROWS(); } - ce = zend_lookup_class(class_name); - if (!ce) { - RETURN_FALSE; - } else { - array_init(return_value); - if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) { - if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) { - return; - } + array_init(return_value); + if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) { + if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) { + return; } - scope = zend_get_executed_scope(); - add_class_vars(scope, ce, 0, return_value); - add_class_vars(scope, ce, 1, return_value); } + + scope = zend_get_executed_scope(); + add_class_vars(scope, ce, 0, return_value); + add_class_vars(scope, ce, 1, return_value); } /* }}} */ -/* {{{ proto array get_object_vars(object obj) - Returns an array of object properties */ +/* {{{ Returns an array of object properties */ ZEND_FUNCTION(get_object_vars) { zval *obj; @@ -1190,13 +780,12 @@ ZEND_FUNCTION(get_object_vars) Z_PARAM_OBJECT(obj) ZEND_PARSE_PARAMETERS_END(); - properties = Z_OBJ_HT_P(obj)->get_properties(obj); + zobj = Z_OBJ_P(obj); + properties = zobj->handlers->get_properties(zobj); if (properties == NULL) { - RETURN_FALSE; + RETURN_EMPTY_ARRAY(); } - zobj = Z_OBJ_P(obj); - if (!zobj->ce->default_properties_count && properties == zobj->properties && !GC_IS_RECURSIVE(properties)) { /* fast copy */ if (EXPECTED(zobj->handlers == &std_object_handlers)) { @@ -1247,8 +836,7 @@ 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. */ +/* {{{ Returns an array of mangled object properties. Does not respect property visibility. */ ZEND_FUNCTION(get_mangled_object_vars) { zval *obj; @@ -1258,7 +846,7 @@ ZEND_FUNCTION(get_mangled_object_vars) Z_PARAM_OBJECT(obj) ZEND_PARSE_PARAMETERS_END(); - properties = Z_OBJ_HT_P(obj)->get_properties(obj); + properties = Z_OBJ_HT_P(obj)->get_properties(Z_OBJ_P(obj)); if (!properties) { ZVAL_EMPTY_ARRAY(return_value); return; @@ -1272,10 +860,10 @@ ZEND_FUNCTION(get_mangled_object_vars) } /* }}} */ -static int same_name(zend_string *key, zend_string *name) /* {{{ */ +static bool same_name(zend_string *key, zend_string *name) /* {{{ */ { zend_string *lcname; - int ret; + bool ret; if (key == name) { return 1; @@ -1290,36 +878,22 @@ static int same_name(zend_string *key, zend_string *name) /* {{{ */ } /* }}} */ -/* {{{ proto array get_class_methods(mixed class) - Returns an array of method names for class or class instance. */ +/* {{{ Returns an array of method names for class or class instance. */ ZEND_FUNCTION(get_class_methods) { - zval *klass; zval method_name; zend_class_entry *ce = NULL; zend_class_entry *scope; zend_function *mptr; - zend_string *key; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &klass) == FAILURE) { - return; - } - - 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)); - } - - if (!ce) { - RETURN_NULL(); - } + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_OBJ_OR_CLASS_NAME(ce) + ZEND_PARSE_PARAMETERS_END(); array_init(return_value); scope = zend_get_executed_scope(); - ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, key, mptr) { - + ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) { if ((mptr->common.fn_flags & ZEND_ACC_PUBLIC) || (scope && (((mptr->common.fn_flags & ZEND_ACC_PROTECTED) && @@ -1327,22 +901,14 @@ ZEND_FUNCTION(get_class_methods) || ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) && 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); - } + 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(); } /* }}} */ -/* {{{ proto bool method_exists(object object, string method) - Checks if the class method exists */ +/* {{{ Checks if the class method exists */ ZEND_FUNCTION(method_exists) { zval *klass; @@ -1363,7 +929,8 @@ ZEND_FUNCTION(method_exists) RETURN_FALSE; } } else { - RETURN_FALSE; + zend_argument_type_error(1, "must be of type object|string, %s given", zend_zval_type_name(klass)); + RETURN_THROWS(); } lcname = zend_string_tolower(method_name); @@ -1398,22 +965,16 @@ ZEND_FUNCTION(method_exists) } /* }}} */ -/* {{{ proto bool property_exists(mixed object_or_class, string property_name) - Checks if the object or class has a property */ +/* {{{ Checks if the object or class has a property */ ZEND_FUNCTION(property_exists) { zval *object; zend_string *property; zend_class_entry *ce; zend_property_info *property_info; - zval property_z; if (zend_parse_parameters(ZEND_NUM_ARGS(), "zS", &object, &property) == FAILURE) { - return; - } - - if (property == NULL) { - RETURN_FALSE; + RETURN_THROWS(); } if (Z_TYPE_P(object) == IS_STRING) { @@ -1424,8 +985,8 @@ ZEND_FUNCTION(property_exists) } else if (Z_TYPE_P(object) == IS_OBJECT) { ce = Z_OBJCE_P(object); } else { - zend_error(E_WARNING, "First parameter must either be an object or the name of an existing class"); - RETURN_NULL(); + zend_argument_type_error(1, "must be of type object|string, %s given", zend_zval_type_name(object)); + RETURN_THROWS(); } property_info = zend_hash_find_ptr(&ce->properties_info, property); @@ -1435,10 +996,8 @@ ZEND_FUNCTION(property_exists) RETURN_TRUE; } - ZVAL_STR(&property_z, property); - if (Z_TYPE_P(object) == IS_OBJECT && - Z_OBJ_HANDLER_P(object, has_property)(object, &property_z, 2, NULL)) { + Z_OBJ_HANDLER_P(object, has_property)(Z_OBJ_P(object), property, 2, NULL)) { RETURN_TRUE; } RETURN_FALSE; @@ -1481,36 +1040,32 @@ static inline void class_exists_impl(INTERNAL_FUNCTION_PARAMETERS, int flags, in } /* {{{ */ -/* {{{ proto bool class_exists(string classname [, bool autoload]) - Checks if the class exists */ +/* {{{ 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 */ +/* {{{ Checks if the class exists */ ZEND_FUNCTION(interface_exists) { class_exists_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED|ZEND_ACC_INTERFACE, 0); } /* }}} */ -/* {{{ proto bool trait_exists(string traitname [, bool autoload]) - Checks if the trait exists */ +/* {{{ Checks if the trait exists */ ZEND_FUNCTION(trait_exists) { class_exists_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_TRAIT, 0); } /* }}} */ -/* {{{ proto bool function_exists(string function_name) - Checks if the function exists */ +/* {{{ Checks if the function exists */ ZEND_FUNCTION(function_exists) { zend_string *name; - zend_function *func; + zend_bool exists; zend_string *lcname; ZEND_PARSE_PARAMETERS_START(1, 1) @@ -1525,20 +1080,14 @@ ZEND_FUNCTION(function_exists) lcname = zend_string_tolower(name); } - func = zend_hash_find_ptr(EG(function_table), lcname); + exists = zend_hash_exists(EG(function_table), lcname); zend_string_release_ex(lcname, 0); - /* - * A bit of a hack, but not a bad one: we see if the handler of the function - * is actually one that displays "function is disabled" message. - */ - RETURN_BOOL(func && (func->type != ZEND_INTERNAL_FUNCTION || - func->internal_function.handler != zif_display_disabled_function)); + RETURN_BOOL(exists); } /* }}} */ -/* {{{ proto bool class_alias(string user_class_name , string alias_name [, bool autoload]) - Creates an alias for user defined class */ +/* {{{ Creates an alias for user defined class */ ZEND_FUNCTION(class_alias) { zend_string *class_name; @@ -1548,7 +1097,7 @@ ZEND_FUNCTION(class_alias) zend_bool autoload = 1; if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ss|b", &class_name, &alias_name, &alias_name_len, &autoload) == FAILURE) { - return; + RETURN_THROWS(); } ce = zend_lookup_class_ex(class_name, NULL, !autoload ? ZEND_FETCH_CLASS_NO_AUTOLOAD : 0); @@ -1562,25 +1111,22 @@ ZEND_FUNCTION(class_alias) RETURN_FALSE; } } else { - zend_error(E_WARNING, "First argument of class_alias() must be a name of user defined class"); - RETURN_FALSE; + zend_argument_value_error(1, "must be a user-defined class name, internal class name given"); + RETURN_THROWS(); } } else { - zend_error(E_WARNING, "Class '%s' not found", ZSTR_VAL(class_name)); + zend_error(E_WARNING, "Class \"%s\" not found", ZSTR_VAL(class_name)); RETURN_FALSE; } } /* }}} */ -/* {{{ proto array get_included_files(void) - Returns an array with the file names that were include_once()'d */ +/* {{{ Returns an array with the file names that were include_once()'d */ ZEND_FUNCTION(get_included_files) { zend_string *entry; - if (zend_parse_parameters_none() == FAILURE) { - return; - } + ZEND_PARSE_PARAMETERS_NONE(); array_init(return_value); ZEND_HASH_FOREACH_STR_KEY(&EG(included_files), entry) { @@ -1591,8 +1137,7 @@ ZEND_FUNCTION(get_included_files) } /* }}} */ -/* {{{ proto void trigger_error(string message [, int error_type]) - Generates a user-level error/warning/notice message */ +/* {{{ Generates a user-level error/warning/notice message */ ZEND_FUNCTION(trigger_error) { zend_long error_type = E_USER_NOTICE; @@ -1600,7 +1145,7 @@ ZEND_FUNCTION(trigger_error) size_t message_len; if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &message, &message_len, &error_type) == FAILURE) { - return; + RETURN_THROWS(); } switch (error_type) { @@ -1610,35 +1155,28 @@ ZEND_FUNCTION(trigger_error) case E_USER_DEPRECATED: break; default: - zend_error(E_WARNING, "Invalid error type specified"); - RETURN_FALSE; + zend_argument_value_error(2, "must be one of E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE," + " or E_USER_DEPRECATED"); + RETURN_THROWS(); break; } zend_error((int)error_type, "%s", message); + // TODO Change to void RETURN_TRUE; } /* }}} */ -/* {{{ proto string set_error_handler(callable error_handler [, int error_types]) - Sets a user-defined error handler function. Returns the previously defined error handler, or false on error */ +/* {{{ Sets a user-defined error handler function. Returns the previously defined error handler, or false on error */ ZEND_FUNCTION(set_error_handler) { - zval *error_handler; + zend_fcall_info fci; + zend_fcall_info_cache fcc; zend_long error_type = E_ALL; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &error_handler, &error_type) == FAILURE) { - return; - } - - if (Z_TYPE_P(error_handler) != IS_NULL) { /* NULL == unset */ - if (!zend_is_callable(error_handler, 0, NULL)) { - zend_string *error_handler_name = zend_get_callable_name(error_handler); - zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback", - get_active_function_name(), error_handler_name?ZSTR_VAL(error_handler_name):"unknown"); - zend_string_release_ex(error_handler_name, 0); - return; - } + /* callable argument corresponds to the error handler */ + if (zend_parse_parameters(ZEND_NUM_ARGS(), "f!|l", &fci, &fcc, &error_type) == FAILURE) { + RETURN_THROWS(); } if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) { @@ -1648,23 +1186,20 @@ ZEND_FUNCTION(set_error_handler) zend_stack_push(&EG(user_error_handlers_error_reporting), &EG(user_error_handler_error_reporting)); zend_stack_push(&EG(user_error_handlers), &EG(user_error_handler)); - if (Z_TYPE_P(error_handler) == IS_NULL) { /* unset user-defined handler */ + if (!ZEND_FCI_INITIALIZED(fci)) { /* unset user-defined handler */ ZVAL_UNDEF(&EG(user_error_handler)); return; } - ZVAL_COPY(&EG(user_error_handler), error_handler); + ZVAL_COPY(&EG(user_error_handler), &(fci.function_name)); EG(user_error_handler_error_reporting) = (int)error_type; } /* }}} */ -/* {{{ proto void restore_error_handler(void) - Restores the previously defined error handler function */ +/* {{{ Restores the previously defined error handler function */ ZEND_FUNCTION(restore_error_handler) { - if (zend_parse_parameters_none() == FAILURE) { - return; - } + ZEND_PARSE_PARAMETERS_NONE(); if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) { zval zeh; @@ -1684,28 +1219,21 @@ ZEND_FUNCTION(restore_error_handler) ZVAL_COPY_VALUE(&EG(user_error_handler), tmp); zend_stack_del_top(&EG(user_error_handlers)); } + + // TODO Change to void RETURN_TRUE; } /* }}} */ -/* {{{ proto mixed set_exception_handler(callable exception_handler) - Sets a user-defined exception handler function. Returns the previously defined exception handler, or false on error */ +/* {{{ Sets a user-defined exception handler function. Returns the previously defined exception handler, or false on error */ ZEND_FUNCTION(set_exception_handler) { - zval *exception_handler; + zend_fcall_info fci; + zend_fcall_info_cache fcc; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &exception_handler) == FAILURE) { - return; - } - - if (Z_TYPE_P(exception_handler) != IS_NULL) { /* NULL == unset */ - if (!zend_is_callable(exception_handler, 0, NULL)) { - zend_string *exception_handler_name = zend_get_callable_name(exception_handler); - zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback", - get_active_function_name(), exception_handler_name?ZSTR_VAL(exception_handler_name):"unknown"); - zend_string_release_ex(exception_handler_name, 0); - return; - } + /* callable argument corresponds to the exception handler */ + if (zend_parse_parameters(ZEND_NUM_ARGS(), "f!", &fci, &fcc) == FAILURE) { + RETURN_THROWS(); } if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) { @@ -1714,22 +1242,19 @@ ZEND_FUNCTION(set_exception_handler) zend_stack_push(&EG(user_exception_handlers), &EG(user_exception_handler)); - if (Z_TYPE_P(exception_handler) == IS_NULL) { /* unset user-defined handler */ + if (!ZEND_FCI_INITIALIZED(fci)) { /* unset user-defined handler */ ZVAL_UNDEF(&EG(user_exception_handler)); return; } - ZVAL_COPY(&EG(user_exception_handler), exception_handler); + ZVAL_COPY(&EG(user_exception_handler), &(fci.function_name)); } /* }}} */ -/* {{{ proto void restore_exception_handler(void) - Restores the previously defined exception handler function */ +/* {{{ Restores the previously defined exception handler function */ ZEND_FUNCTION(restore_exception_handler) { - if (zend_parse_parameters_none() == FAILURE) { - return; - } + ZEND_PARSE_PARAMETERS_NONE(); if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) { zval_ptr_dtor(&EG(user_exception_handler)); @@ -1741,6 +1266,8 @@ ZEND_FUNCTION(restore_exception_handler) ZVAL_COPY_VALUE(&EG(user_exception_handler), tmp); zend_stack_del_top(&EG(user_exception_handlers)); } + + // TODO Change to void RETURN_TRUE; } /* }}} */ @@ -1760,9 +1287,7 @@ static inline void get_declared_class_impl(INTERNAL_FUNCTION_PARAMETERS, int fla zend_string *key; zend_class_entry *ce; - if (zend_parse_parameters_none() == FAILURE) { - return; - } + ZEND_PARSE_PARAMETERS_NONE(); array_init(return_value); ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) { @@ -1776,41 +1301,42 @@ static inline void get_declared_class_impl(INTERNAL_FUNCTION_PARAMETERS, int fla } /* {{{ */ -/* {{{ proto array get_declared_traits() - Returns an array of all 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); } /* }}} */ -/* {{{ proto array get_declared_classes() - Returns an array of all declared classes. */ +/* {{{ Returns an array of all declared classes. */ ZEND_FUNCTION(get_declared_classes) { get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED, ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT); } /* }}} */ -/* {{{ proto array get_declared_interfaces() - Returns an array of all declared interfaces. */ +/* {{{ Returns an array of all declared interfaces. */ ZEND_FUNCTION(get_declared_interfaces) { get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_INTERFACE, 0); } /* }}} */ -/* {{{ proto array get_defined_functions(void) - Returns an array of all defined functions */ +/* {{{ Returns an array of all defined functions */ ZEND_FUNCTION(get_defined_functions) { zval internal, user; zend_string *key; zend_function *func; - zend_bool exclude_disabled = 0; + zend_bool exclude_disabled = 1; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &exclude_disabled) == FAILURE) { - return; + RETURN_THROWS(); + } + + if (exclude_disabled == 0) { + zend_error(E_DEPRECATED, + "get_defined_functions(): Setting $exclude_disabled to false has no effect"); } array_init(&internal); @@ -1819,8 +1345,7 @@ ZEND_FUNCTION(get_defined_functions) 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))) { + if (func->type == ZEND_INTERNAL_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)); @@ -1833,112 +1358,43 @@ ZEND_FUNCTION(get_defined_functions) } /* }}} */ -/* {{{ proto array get_defined_vars(void) - Returns an associative array of names and values of all currently defined variable names (variables in the current scope) */ +/* {{{ Returns an associative array of names and values of all currently defined variable names (variables in the current scope) */ ZEND_FUNCTION(get_defined_vars) { zend_array *symbol_table; + + ZEND_PARSE_PARAMETERS_NONE(); + if (zend_forbid_dynamic_call("get_defined_vars()") == FAILURE) { return; } symbol_table = zend_rebuild_symbol_table(); if (UNEXPECTED(symbol_table == NULL)) { - return; + RETURN_EMPTY_ARRAY(); } RETURN_ARR(zend_array_dup(symbol_table)); } /* }}} */ -#define LAMBDA_TEMP_FUNCNAME "__lambda_func" -/* {{{ proto string create_function(string args, string code) - Creates an anonymous function, and returns its name (funny, eh?) */ -ZEND_FUNCTION(create_function) -{ - zend_string *function_name; - char *eval_code, *function_args, *function_code; - size_t eval_code_length, function_args_len, function_code_len; - int retval; - char *eval_name; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &function_args, &function_args_len, &function_code, &function_code_len) == FAILURE) { - return; - } - - eval_code = (char *) emalloc(sizeof("function " LAMBDA_TEMP_FUNCNAME) - +function_args_len - +2 /* for the args parentheses */ - +2 /* for the curly braces */ - +function_code_len); - - eval_code_length = sizeof("function " LAMBDA_TEMP_FUNCNAME "(") - 1; - memcpy(eval_code, "function " LAMBDA_TEMP_FUNCNAME "(", eval_code_length); - - memcpy(eval_code + eval_code_length, function_args, function_args_len); - eval_code_length += function_args_len; - - eval_code[eval_code_length++] = ')'; - eval_code[eval_code_length++] = '{'; - - memcpy(eval_code + eval_code_length, function_code, function_code_len); - eval_code_length += function_code_len; - - eval_code[eval_code_length++] = '}'; - eval_code[eval_code_length] = '\0'; - - eval_name = zend_make_compiled_string_description("runtime-created function"); - retval = zend_eval_stringl(eval_code, eval_code_length, NULL, eval_name); - efree(eval_code); - efree(eval_name); - - if (retval==SUCCESS) { - zend_op_array *func; - HashTable *static_variables; - - func = zend_hash_str_find_ptr(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1); - if (!func) { - zend_error_noreturn(E_CORE_ERROR, "Unexpected inconsistency in create_function()"); - RETURN_FALSE; - } - if (func->refcount) { - (*func->refcount)++; - } - static_variables = func->static_variables; - func->static_variables = NULL; - zend_hash_str_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1); - func->static_variables = static_variables; - - function_name = zend_string_alloc(sizeof("0lambda_")+MAX_LENGTH_OF_LONG, 0); - ZSTR_VAL(function_name)[0] = '\0'; - - do { - ZSTR_LEN(function_name) = snprintf(ZSTR_VAL(function_name) + 1, sizeof("lambda_")+MAX_LENGTH_OF_LONG, "lambda_%d", ++EG(lambda_count)) + 1; - } while (zend_hash_add_ptr(EG(function_table), function_name, func) == NULL); - RETURN_NEW_STR(function_name); - } else { - zend_hash_str_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1); - RETURN_FALSE; - } -} -/* }}} */ - #if ZEND_DEBUG && defined(ZTS) ZEND_FUNCTION(zend_thread_id) { + ZEND_PARSE_PARAMETERS_NONE(); + RETURN_LONG((zend_long)tsrm_thread_id()); } #endif -/* {{{ proto string get_resource_type(resource res) - Get the resource type name for a given resource */ +/* {{{ Get the resource type name for a given resource */ ZEND_FUNCTION(get_resource_type) { const char *resource_type; zval *z_resource_type; if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &z_resource_type) == FAILURE) { - return; + RETURN_THROWS(); } resource_type = zend_rsrc_list_get_rsrc_type(Z_RES_P(z_resource_type)); @@ -1950,8 +1406,20 @@ ZEND_FUNCTION(get_resource_type) } /* }}} */ -/* {{{ proto array get_resources([string resouce_type]) - Get an array with all active resources */ +/* {{{ Get the resource ID for a given resource */ +ZEND_FUNCTION(get_resource_id) +{ + zval *resource; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_RESOURCE(resource) + ZEND_PARSE_PARAMETERS_END(); + + RETURN_LONG(Z_RES_HANDLE_P(resource)); +} +/* }}} */ + +/* {{{ Get an array with all active resources */ ZEND_FUNCTION(get_resources) { zend_string *type = NULL; @@ -1959,8 +1427,8 @@ ZEND_FUNCTION(get_resources) zend_ulong index; zval *val; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S", &type) == FAILURE) { - return; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!", &type) == FAILURE) { + RETURN_THROWS(); } if (!type) { @@ -1983,8 +1451,8 @@ ZEND_FUNCTION(get_resources) int id = zend_fetch_list_dtor_id(ZSTR_VAL(type)); if (id <= 0) { - zend_error(E_WARNING, "get_resources(): Unknown resource type '%s'", ZSTR_VAL(type)); - RETURN_FALSE; + zend_argument_value_error(1, "must be a valid resource type"); + RETURN_THROWS(); } array_init(return_value); @@ -1998,28 +1466,26 @@ ZEND_FUNCTION(get_resources) } /* }}} */ -static int add_zendext_info(zend_extension *ext, void *arg) /* {{{ */ +static void add_zendext_info(zend_extension *ext, void *arg) /* {{{ */ { zval *name_array = (zval *)arg; add_next_index_string(name_array, ext->name); - return 0; } /* }}} */ -/* {{{ proto array get_loaded_extensions([bool zend_extensions]) - Return an array containing names of loaded extensions */ +/* {{{ Return an array containing names of loaded extensions */ ZEND_FUNCTION(get_loaded_extensions) { zend_bool zendext = 0; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &zendext) == FAILURE) { - return; + RETURN_THROWS(); } array_init(return_value); if (zendext) { - zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t)add_zendext_info, return_value); + zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) add_zendext_info, return_value); } else { zend_module_entry *module; @@ -2030,14 +1496,13 @@ ZEND_FUNCTION(get_loaded_extensions) } /* }}} */ -/* {{{ proto array get_defined_constants([bool categorize]) - Return an array containing the names and values of all defined constants */ +/* {{{ Return an array containing the names and values of all defined constants */ ZEND_FUNCTION(get_defined_constants) { zend_bool categorize = 0; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &categorize) == FAILURE) { - return; + RETURN_THROWS(); } array_init(return_value); @@ -2121,16 +1586,12 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) / * and we have to access them through symbol_table * See: https://bugs.php.net/bug.php?id=73156 */ - zend_string *arg_name; - zval *arg; - while (i < first_extra_arg) { - arg_name = call->func->op_array.vars[i]; - arg = zend_hash_find_ex_ind(call->symbol_table, arg_name, 1); + zend_string *arg_name = call->func->op_array.vars[i]; + zval *arg = zend_hash_find_ex_ind(call->symbol_table, arg_name, 1); if (arg) { - if (Z_OPT_REFCOUNTED_P(arg)) { - Z_ADDREF_P(arg); - } + ZVAL_DEREF(arg); + Z_TRY_ADDREF_P(arg); ZEND_HASH_FILL_SET(arg); } else { ZEND_HASH_FILL_SET_NULL(); @@ -2141,10 +1602,10 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) / } else { while (i < first_extra_arg) { if (EXPECTED(Z_TYPE_INFO_P(p) != IS_UNDEF)) { - if (Z_OPT_REFCOUNTED_P(p)) { - Z_ADDREF_P(p); - } - ZEND_HASH_FILL_SET(p); + zval *arg = p; + ZVAL_DEREF(arg); + Z_TRY_ADDREF_P(arg); + ZEND_HASH_FILL_SET(arg); } else { ZEND_HASH_FILL_SET_NULL(); } @@ -2158,10 +1619,10 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) / while (i < num_args) { if (EXPECTED(Z_TYPE_INFO_P(p) != IS_UNDEF)) { - if (Z_OPT_REFCOUNTED_P(p)) { - Z_ADDREF_P(p); - } - ZEND_HASH_FILL_SET(p); + zval *arg = p; + ZVAL_DEREF(arg); + Z_TRY_ADDREF_P(arg); + ZEND_HASH_FILL_SET(arg); } else { ZEND_HASH_FILL_SET_NULL(); } @@ -2174,18 +1635,34 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) / } else { ZVAL_EMPTY_ARRAY(arg_array); } + + if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { + zend_string *name; + zval *arg; + SEPARATE_ARRAY(arg_array); + ZEND_HASH_FOREACH_STR_KEY_VAL(call->extra_named_params, name, arg) { + ZVAL_DEREF(arg); + Z_TRY_ADDREF_P(arg); + zend_hash_add_new(Z_ARRVAL_P(arg_array), name, arg); + } ZEND_HASH_FOREACH_END(); + } } /* }}} */ void debug_print_backtrace_args(zval *arg_array) /* {{{ */ { + zend_string *name; zval *tmp; int i = 0; - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arg_array), tmp) { + ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(arg_array), name, tmp) { if (i++) { ZEND_PUTS(", "); } + if (name) { + ZEND_PUTS(ZSTR_VAL(name)); + ZEND_PUTS(": "); + } zend_print_flat_zval_r(tmp); } ZEND_HASH_FOREACH_END(); } @@ -2205,7 +1682,7 @@ static inline zend_bool skip_internal_handler(zend_execute_data *skip) /* {{{ */ } /* {{{ */ -/* {{{ proto void debug_print_backtrace([int options[, int limit]]) */ +/* {{{ */ ZEND_FUNCTION(debug_print_backtrace) { zend_execute_data *call, *ptr, *skip; @@ -2223,7 +1700,7 @@ ZEND_FUNCTION(debug_print_backtrace) zend_long limit = 0; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &options, &limit) == FAILURE) { - return; + RETURN_THROWS(); } ZVAL_UNDEF(&arg_array); @@ -2267,16 +1744,9 @@ ZEND_FUNCTION(debug_print_backtrace) object = (Z_TYPE(call->This) == IS_OBJECT) ? Z_OBJ(call->This) : NULL; if (call->func) { - 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); + if (func->common.function_name) { + function_name = ZSTR_VAL(func->common.function_name); } else { function_name = NULL; } @@ -2311,13 +1781,12 @@ ZEND_FUNCTION(debug_print_backtrace) } else { /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */ zend_bool build_filename_arg = 1; + uint32_t include_kind = 0; + if (ptr->func && ZEND_USER_CODE(ptr->func->common.type) && ptr->opline->opcode == ZEND_INCLUDE_OR_EVAL) { + include_kind = ptr->opline->extended_value; + } - if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type) || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) { - /* can happen when calling eval from a custom sapi */ - function_name = "unknown"; - build_filename_arg = 0; - } else - switch (ptr->opline->extended_value) { + switch (include_kind) { case ZEND_EVAL: function_name = "eval"; build_filename_arg = 0; @@ -2335,8 +1804,11 @@ ZEND_FUNCTION(debug_print_backtrace) function_name = "require_once"; break; default: - /* this can actually happen if you use debug_backtrace() in your error_handler and - * you're in the top-scope */ + /* Skip dummy frame unless it is needed to preserve filename/lineno info. */ + if (!filename) { + goto skip_frame; + } + function_name = "unknown"; build_filename_arg = 0; break; @@ -2387,10 +1859,12 @@ ZEND_FUNCTION(debug_print_backtrace) ZEND_PUTS(")\n"); } } + ++indent; + +skip_frame: include_filename = filename; call = skip; ptr = skip->prev_execute_data; - ++indent; } } @@ -2496,11 +1970,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) ? - zend_resolve_method_name( - (object ? object->ce : func->common.scope), func) : - func->common.function_name; + function_name = func->common.function_name; } else { func = NULL; function_name = NULL; @@ -2520,9 +1990,8 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int } zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_CLASS), &tmp); if ((options & DEBUG_BACKTRACE_PROVIDE_OBJECT) != 0) { - ZVAL_OBJ(&tmp, object); + ZVAL_OBJ_COPY(&tmp, object); zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_OBJECT), &tmp); - Z_ADDREF(tmp); } ZVAL_INTERNED_STR(&tmp, ZSTR_KNOWN(ZEND_STR_OBJECT_OPERATOR)); @@ -2544,13 +2013,12 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */ zend_bool build_filename_arg = 1; zend_string *pseudo_function_name; + uint32_t include_kind = 0; + if (ptr->func && ZEND_USER_CODE(ptr->func->common.type) && ptr->opline->opcode == ZEND_INCLUDE_OR_EVAL) { + include_kind = ptr->opline->extended_value; + } - if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type) || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) { - /* can happen when calling eval from a custom sapi */ - pseudo_function_name = ZSTR_KNOWN(ZEND_STR_UNKNOWN); - build_filename_arg = 0; - } else - switch (ptr->opline->extended_value) { + switch (include_kind) { case ZEND_EVAL: pseudo_function_name = ZSTR_KNOWN(ZEND_STR_EVAL); build_filename_arg = 0; @@ -2568,8 +2036,12 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int pseudo_function_name = ZSTR_KNOWN(ZEND_STR_REQUIRE_ONCE); break; default: - /* this can actually happen if you use debug_backtrace() in your error_handler and - * you're in the top-scope */ + /* Skip dummy frame unless it is needed to preserve filename/lineno info. */ + if (!filename) { + zval_ptr_dtor(&stack_frame); + goto skip_frame; + } + pseudo_function_name = ZSTR_KNOWN(ZEND_STR_UNKNOWN); build_filename_arg = 0; break; @@ -2595,38 +2067,36 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &stack_frame); +skip_frame: include_filename = filename; - call = skip; ptr = skip->prev_execute_data; } } /* }}} */ -/* {{{ proto array debug_backtrace([int options[, int limit]]) - Return backtrace as array */ +/* {{{ Return backtrace as array */ ZEND_FUNCTION(debug_backtrace) { zend_long options = DEBUG_BACKTRACE_PROVIDE_OBJECT; zend_long limit = 0; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &options, &limit) == FAILURE) { - return; + RETURN_THROWS(); } zend_fetch_debug_backtrace(return_value, 1, options, limit); } /* }}} */ -/* {{{ proto bool extension_loaded(string extension_name) - Returns true if the named extension is loaded */ +/* {{{ Returns true if the named extension is loaded */ ZEND_FUNCTION(extension_loaded) { zend_string *extension_name; zend_string *lcname; if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &extension_name) == FAILURE) { - return; + RETURN_THROWS(); } lcname = zend_string_tolower(extension_name); @@ -2639,18 +2109,17 @@ ZEND_FUNCTION(extension_loaded) } /* }}} */ -/* {{{ proto array get_extension_funcs(string extension_name) - Returns an array with the names of functions belonging to the named extension */ +/* {{{ Returns an array with the names of functions belonging to the named extension */ ZEND_FUNCTION(get_extension_funcs) { zend_string *extension_name; zend_string *lcname; - int array; + bool array; zend_module_entry *module; zend_function *zif; if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &extension_name) == FAILURE) { - return; + RETURN_THROWS(); } if (strncasecmp(ZSTR_VAL(extension_name), "zend", sizeof("zend"))) { lcname = zend_string_tolower(extension_name); |