1999-09-20 20:24:39 +08:00
|
|
|
/*
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| Zend Engine |
|
|
|
|
+----------------------------------------------------------------------+
|
2019-01-30 17:23:29 +08:00
|
|
|
| Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
|
1999-09-20 20:24:39 +08:00
|
|
|
+----------------------------------------------------------------------+
|
2001-12-11 23:16:21 +08:00
|
|
|
| This source file is subject to version 2.00 of the Zend license, |
|
1999-09-20 20:24:39 +08:00
|
|
|
| that is bundled with this package in the file LICENSE, and is |
|
2003-06-11 04:04:29 +08:00
|
|
|
| available through the world-wide-web at the following url: |
|
2001-12-11 23:16:21 +08:00
|
|
|
| http://www.zend.com/license/2_00.txt. |
|
1999-09-20 20:24:39 +08:00
|
|
|
| If you did not receive a copy of the Zend license and are unable to |
|
|
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
|
|
| license@zend.com so we can mail you a copy immediately. |
|
|
|
|
+----------------------------------------------------------------------+
|
2018-11-01 23:20:07 +08:00
|
|
|
| Authors: Andi Gutmans <andi@php.net> |
|
|
|
|
| Zeev Suraski <zeev@php.net> |
|
1999-09-20 20:24:39 +08:00
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "zend.h"
|
|
|
|
#include "zend_API.h"
|
2018-06-13 16:10:17 +08:00
|
|
|
#include "zend_gc.h"
|
1999-09-20 20:24:39 +08:00
|
|
|
#include "zend_builtin_functions.h"
|
1999-09-21 05:28:37 +08:00
|
|
|
#include "zend_constants.h"
|
2002-11-20 01:51:30 +08:00
|
|
|
#include "zend_ini.h"
|
2007-02-24 10:17:47 +08:00
|
|
|
#include "zend_exceptions.h"
|
2007-08-01 06:47:25 +08:00
|
|
|
#include "zend_extensions.h"
|
2010-06-12 07:20:13 +08:00
|
|
|
#include "zend_closures.h"
|
2015-03-07 07:28:12 +08:00
|
|
|
#include "zend_generators.h"
|
2019-06-18 17:33:07 +08:00
|
|
|
#include "zend_builtin_functions_arginfo.h"
|
2015-02-05 01:21:42 +08:00
|
|
|
|
2016-01-21 14:31:03 +08:00
|
|
|
/* }}} */
|
|
|
|
|
2008-12-31 20:26:33 +08:00
|
|
|
ZEND_MINIT_FUNCTION(core) { /* {{{ */
|
|
|
|
zend_class_entry class_entry;
|
|
|
|
|
|
|
|
INIT_CLASS_ENTRY(class_entry, "stdClass", NULL);
|
2014-12-14 06:06:14 +08:00
|
|
|
zend_standard_class_def = zend_register_internal_class(&class_entry);
|
2008-12-31 20:26:33 +08:00
|
|
|
|
2014-12-14 06:06:14 +08:00
|
|
|
zend_register_default_classes();
|
2008-12-31 21:25:21 +08:00
|
|
|
|
2008-12-31 20:26:33 +08:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2008-12-31 02:17:44 +08:00
|
|
|
zend_module_entry zend_builtin_module = { /* {{{ */
|
2019-03-18 22:17:29 +08:00
|
|
|
STANDARD_MODULE_HEADER,
|
2008-12-31 04:15:28 +08:00
|
|
|
"Core",
|
2020-04-21 18:23:21 +08:00
|
|
|
ext_functions,
|
2008-12-31 20:26:33 +08:00
|
|
|
ZEND_MINIT(core),
|
2008-12-31 02:17:44 +08:00
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
ZEND_VERSION,
|
|
|
|
STANDARD_MODULE_PROPERTIES
|
|
|
|
};
|
|
|
|
/* }}} */
|
1999-09-20 20:24:39 +08:00
|
|
|
|
2020-08-28 21:41:27 +08:00
|
|
|
zend_result zend_startup_builtin_functions(void) /* {{{ */
|
1999-09-20 20:24:39 +08:00
|
|
|
{
|
2008-12-31 04:15:28 +08:00
|
|
|
zend_builtin_module.module_number = 0;
|
|
|
|
zend_builtin_module.type = MODULE_PERSISTENT;
|
2014-12-14 06:06:14 +08:00
|
|
|
return (EG(current_module) = zend_register_module_ex(&zend_builtin_module)) == NULL ? FAILURE : SUCCESS;
|
1999-09-20 20:24:39 +08:00
|
|
|
}
|
2008-12-31 02:17:44 +08:00
|
|
|
/* }}} */
|
1999-09-20 20:24:39 +08:00
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Get the version of the Zend Engine */
|
1999-09-20 20:24:39 +08:00
|
|
|
ZEND_FUNCTION(zend_version)
|
|
|
|
{
|
2020-01-03 19:11:45 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2018-07-12 21:05:56 +08:00
|
|
|
|
2014-02-10 14:04:30 +08:00
|
|
|
RETURN_STRINGL(ZEND_VERSION, sizeof(ZEND_VERSION)-1);
|
1999-09-20 20:24:39 +08:00
|
|
|
}
|
2001-12-05 01:58:32 +08:00
|
|
|
/* }}} */
|
1999-09-20 21:00:35 +08:00
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Reclaims memory used by MM caches.
|
2015-08-04 23:21:05 +08:00
|
|
|
Returns number of freed bytes */
|
|
|
|
ZEND_FUNCTION(gc_mem_caches)
|
|
|
|
{
|
2020-01-03 19:11:45 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2018-07-12 21:05:56 +08:00
|
|
|
|
2015-08-04 23:21:05 +08:00
|
|
|
RETURN_LONG(zend_mm_gc(zend_mm_get_heap()));
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Forces collection of any existing garbage cycles.
|
2008-01-22 17:27:48 +08:00
|
|
|
Returns number of freed zvals */
|
|
|
|
ZEND_FUNCTION(gc_collect_cycles)
|
|
|
|
{
|
2020-01-03 19:11:45 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2018-07-12 21:05:56 +08:00
|
|
|
|
2014-12-14 06:06:14 +08:00
|
|
|
RETURN_LONG(gc_collect_cycles());
|
2008-01-22 17:27:48 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Returns status of the circular reference collector */
|
2008-01-22 17:27:48 +08:00
|
|
|
ZEND_FUNCTION(gc_enabled)
|
|
|
|
{
|
2020-01-03 19:11:45 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2018-07-12 21:05:56 +08:00
|
|
|
|
2018-02-26 17:49:58 +08:00
|
|
|
RETURN_BOOL(gc_enabled());
|
2008-01-22 17:27:48 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Activates the circular reference collector */
|
2008-01-22 17:27:48 +08:00
|
|
|
ZEND_FUNCTION(gc_enable)
|
|
|
|
{
|
2018-07-12 21:05:56 +08:00
|
|
|
zend_string *key;
|
|
|
|
|
2020-01-03 19:11:45 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2018-07-12 21:05:56 +08:00
|
|
|
|
|
|
|
key = zend_string_init("zend.enable_gc", sizeof("zend.enable_gc")-1, 0);
|
2014-09-02 00:57:33 +08:00
|
|
|
zend_alter_ini_entry_chars(key, "1", sizeof("1")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
|
2018-05-28 21:27:12 +08:00
|
|
|
zend_string_release_ex(key, 0);
|
2008-01-22 17:27:48 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Deactivates the circular reference collector */
|
2008-01-22 17:27:48 +08:00
|
|
|
ZEND_FUNCTION(gc_disable)
|
|
|
|
{
|
2018-07-12 21:05:56 +08:00
|
|
|
zend_string *key;
|
|
|
|
|
2020-01-03 19:11:45 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2018-07-12 21:05:56 +08:00
|
|
|
|
|
|
|
key = zend_string_init("zend.enable_gc", sizeof("zend.enable_gc")-1, 0);
|
2014-09-02 00:57:33 +08:00
|
|
|
zend_alter_ini_entry_chars(key, "0", sizeof("0")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
|
2018-05-28 21:27:12 +08:00
|
|
|
zend_string_release_ex(key, 0);
|
2008-01-22 17:27:48 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
1999-09-20 21:00:35 +08:00
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Returns current GC statistics */
|
2018-06-13 16:10:17 +08:00
|
|
|
ZEND_FUNCTION(gc_status)
|
|
|
|
{
|
|
|
|
zend_gc_status status;
|
|
|
|
|
2020-01-03 19:11:45 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2018-07-12 21:05:56 +08:00
|
|
|
|
2018-06-13 16:10:17 +08:00
|
|
|
zend_gc_get_status(&status);
|
|
|
|
|
|
|
|
array_init_size(return_value, 3);
|
|
|
|
|
2018-06-13 16:28:24 +08:00
|
|
|
add_assoc_long_ex(return_value, "runs", sizeof("runs")-1, (long)status.runs);
|
2018-06-13 16:10:17 +08:00
|
|
|
add_assoc_long_ex(return_value, "collected", sizeof("collected")-1, (long)status.collected);
|
2018-06-13 16:28:24 +08:00
|
|
|
add_assoc_long_ex(return_value, "threshold", sizeof("threshold")-1, (long)status.threshold);
|
2018-06-13 16:41:51 +08:00
|
|
|
add_assoc_long_ex(return_value, "roots", sizeof("roots")-1, (long)status.num_roots);
|
2018-06-13 16:10:17 +08:00
|
|
|
}
|
2018-06-13 16:41:51 +08:00
|
|
|
/* }}} */
|
2018-06-13 16:10:17 +08:00
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Get the number of arguments that were passed to the function */
|
1999-09-21 15:31:24 +08:00
|
|
|
ZEND_FUNCTION(func_num_args)
|
1999-09-20 21:00:35 +08:00
|
|
|
{
|
2014-10-03 23:32:46 +08:00
|
|
|
zend_execute_data *ex = EX(prev_execute_data);
|
1999-09-20 21:00:35 +08:00
|
|
|
|
2020-01-03 19:11:45 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2018-07-12 21:05:56 +08:00
|
|
|
|
2016-04-25 05:49:52 +08:00
|
|
|
if (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE) {
|
2020-07-12 18:40:37 +08:00
|
|
|
zend_throw_error(NULL, "func_num_args() must be called from a function context");
|
|
|
|
RETURN_THROWS();
|
1999-09-20 21:00:35 +08:00
|
|
|
}
|
2016-04-25 05:49:52 +08:00
|
|
|
|
|
|
|
if (zend_forbid_dynamic_call("func_num_args()") == FAILURE) {
|
|
|
|
RETURN_LONG(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
RETURN_LONG(ZEND_CALL_NUM_ARGS(ex));
|
1999-09-20 21:00:35 +08:00
|
|
|
}
|
2001-12-05 01:58:32 +08:00
|
|
|
/* }}} */
|
1999-09-20 21:00:35 +08:00
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Get the $arg_num'th argument that was passed to the function */
|
1999-09-21 15:31:24 +08:00
|
|
|
ZEND_FUNCTION(func_get_arg)
|
1999-09-20 21:00:35 +08:00
|
|
|
{
|
2014-09-15 18:08:42 +08:00
|
|
|
uint32_t arg_count, first_extra_arg;
|
1999-09-20 21:00:35 +08:00
|
|
|
zval *arg;
|
2014-08-26 01:24:55 +08:00
|
|
|
zend_long requested_offset;
|
2014-06-27 03:51:14 +08:00
|
|
|
zend_execute_data *ex;
|
1999-09-20 21:00:35 +08:00
|
|
|
|
2014-12-14 06:06:14 +08:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &requested_offset) == FAILURE) {
|
2019-12-31 00:35:46 +08:00
|
|
|
RETURN_THROWS();
|
1999-09-20 21:00:35 +08:00
|
|
|
}
|
|
|
|
|
2002-05-08 22:10:30 +08:00
|
|
|
if (requested_offset < 0) {
|
2020-03-30 06:40:18 +08:00
|
|
|
zend_argument_value_error(1, "must be greater than or equal to 0");
|
|
|
|
RETURN_THROWS();
|
2002-05-08 22:10:30 +08:00
|
|
|
}
|
|
|
|
|
2014-10-03 23:32:46 +08:00
|
|
|
ex = EX(prev_execute_data);
|
2014-11-28 15:33:03 +08:00
|
|
|
if (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE) {
|
2020-03-30 06:40:18 +08:00
|
|
|
zend_throw_error(NULL, "func_get_arg() cannot be called from the global scope");
|
|
|
|
RETURN_THROWS();
|
1999-09-20 21:00:35 +08:00
|
|
|
}
|
|
|
|
|
2016-04-25 05:49:52 +08:00
|
|
|
if (zend_forbid_dynamic_call("func_get_arg()") == FAILURE) {
|
2020-03-30 06:40:18 +08:00
|
|
|
RETURN_THROWS();
|
2016-04-25 05:49:52 +08:00
|
|
|
}
|
|
|
|
|
2014-11-28 15:28:49 +08:00
|
|
|
arg_count = ZEND_CALL_NUM_ARGS(ex);
|
2008-01-24 17:41:39 +08:00
|
|
|
|
2016-04-29 19:44:56 +08:00
|
|
|
if ((zend_ulong)requested_offset >= arg_count) {
|
2020-07-12 18:40:37 +08:00
|
|
|
zend_argument_value_error(1, "must be less than the number of the arguments passed to the currently executed function");
|
2020-03-30 06:40:18 +08:00
|
|
|
RETURN_THROWS();
|
1999-09-20 21:00:35 +08:00
|
|
|
}
|
|
|
|
|
2014-06-30 18:17:17 +08:00
|
|
|
first_extra_arg = ex->func->op_array.num_args;
|
2016-04-29 19:44:56 +08:00
|
|
|
if ((zend_ulong)requested_offset >= first_extra_arg && (ZEND_CALL_NUM_ARGS(ex) > first_extra_arg)) {
|
2014-11-28 16:11:33 +08:00
|
|
|
arg = ZEND_CALL_VAR_NUM(ex, ex->func->op_array.last_var + ex->func->op_array.T) + (requested_offset - first_extra_arg);
|
2014-06-27 03:51:14 +08:00
|
|
|
} else {
|
|
|
|
arg = ZEND_CALL_ARG(ex, requested_offset + 1);
|
|
|
|
}
|
2015-09-23 10:00:20 +08:00
|
|
|
if (EXPECTED(!Z_ISUNDEF_P(arg))) {
|
2018-07-09 17:46:46 +08:00
|
|
|
ZVAL_COPY_DEREF(return_value, arg);
|
2015-09-23 10:00:20 +08:00
|
|
|
}
|
1999-09-20 21:00:35 +08:00
|
|
|
}
|
2001-12-05 01:58:32 +08:00
|
|
|
/* }}} */
|
1999-09-20 21:00:35 +08:00
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Get an array of the arguments that were passed to the function */
|
1999-09-21 15:31:24 +08:00
|
|
|
ZEND_FUNCTION(func_get_args)
|
|
|
|
{
|
2014-12-24 00:08:28 +08:00
|
|
|
zval *p, *q;
|
2014-09-15 18:08:42 +08:00
|
|
|
uint32_t arg_count, first_extra_arg;
|
2017-06-25 21:08:36 +08:00
|
|
|
uint32_t i;
|
2014-10-03 23:32:46 +08:00
|
|
|
zend_execute_data *ex = EX(prev_execute_data);
|
1999-09-21 15:31:24 +08:00
|
|
|
|
2020-05-31 05:33:25 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
|
2014-11-28 15:33:03 +08:00
|
|
|
if (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE) {
|
2020-03-30 06:40:18 +08:00
|
|
|
zend_throw_error(NULL, "func_get_args() cannot be called from the global scope");
|
|
|
|
RETURN_THROWS();
|
1999-09-21 15:31:24 +08:00
|
|
|
}
|
|
|
|
|
2016-04-25 05:49:52 +08:00
|
|
|
if (zend_forbid_dynamic_call("func_get_args()") == FAILURE) {
|
2020-03-30 06:40:18 +08:00
|
|
|
RETURN_THROWS();
|
2016-04-25 05:49:52 +08:00
|
|
|
}
|
|
|
|
|
2014-11-28 15:28:49 +08:00
|
|
|
arg_count = ZEND_CALL_NUM_ARGS(ex);
|
1999-09-21 15:31:24 +08:00
|
|
|
|
2014-05-26 21:15:52 +08:00
|
|
|
if (arg_count) {
|
2017-10-24 22:27:31 +08:00
|
|
|
array_init_size(return_value, arg_count);
|
2014-06-30 18:17:17 +08:00
|
|
|
first_extra_arg = ex->func->op_array.num_args;
|
2018-03-23 05:13:45 +08:00
|
|
|
zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
|
2014-12-24 00:08:28 +08:00
|
|
|
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
|
|
|
|
i = 0;
|
|
|
|
p = ZEND_CALL_ARG(ex, 1);
|
2015-01-20 13:55:36 +08:00
|
|
|
if (arg_count > first_extra_arg) {
|
2014-12-24 00:08:28 +08:00
|
|
|
while (i < first_extra_arg) {
|
|
|
|
q = p;
|
2015-09-22 13:58:42 +08:00
|
|
|
if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) {
|
|
|
|
ZVAL_DEREF(q);
|
2017-12-31 12:35:25 +08:00
|
|
|
if (Z_OPT_REFCOUNTED_P(q)) {
|
2015-09-22 13:58:42 +08:00
|
|
|
Z_ADDREF_P(q);
|
|
|
|
}
|
2019-05-28 18:35:00 +08:00
|
|
|
ZEND_HASH_FILL_SET(q);
|
2017-06-25 21:08:36 +08:00
|
|
|
} else {
|
2019-05-28 18:35:00 +08:00
|
|
|
ZEND_HASH_FILL_SET_NULL();
|
2015-09-22 13:58:42 +08:00
|
|
|
}
|
2019-05-28 18:35:00 +08:00
|
|
|
ZEND_HASH_FILL_NEXT();
|
2014-12-24 00:08:28 +08:00
|
|
|
p++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
p = ZEND_CALL_VAR_NUM(ex, ex->func->op_array.last_var + ex->func->op_array.T);
|
|
|
|
}
|
|
|
|
while (i < arg_count) {
|
|
|
|
q = p;
|
2015-09-22 13:58:42 +08:00
|
|
|
if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) {
|
|
|
|
ZVAL_DEREF(q);
|
2017-12-31 12:35:25 +08:00
|
|
|
if (Z_OPT_REFCOUNTED_P(q)) {
|
2015-09-22 13:58:42 +08:00
|
|
|
Z_ADDREF_P(q);
|
|
|
|
}
|
2019-05-28 18:35:00 +08:00
|
|
|
ZEND_HASH_FILL_SET(q);
|
2017-06-25 21:08:36 +08:00
|
|
|
} else {
|
2019-05-28 18:35:00 +08:00
|
|
|
ZEND_HASH_FILL_SET_NULL();
|
2015-09-22 13:58:42 +08:00
|
|
|
}
|
2019-05-28 18:35:00 +08:00
|
|
|
ZEND_HASH_FILL_NEXT();
|
2014-06-27 03:51:14 +08:00
|
|
|
p++;
|
|
|
|
i++;
|
|
|
|
}
|
2014-12-24 00:08:28 +08:00
|
|
|
} ZEND_HASH_FILL_END();
|
2017-06-25 21:08:36 +08:00
|
|
|
Z_ARRVAL_P(return_value)->nNumOfElements = arg_count;
|
2017-10-24 22:27:31 +08:00
|
|
|
} else {
|
2019-05-14 20:57:10 +08:00
|
|
|
RETURN_EMPTY_ARRAY();
|
1999-09-21 15:31:24 +08:00
|
|
|
}
|
|
|
|
}
|
2001-12-05 01:58:32 +08:00
|
|
|
/* }}} */
|
1999-09-21 15:31:24 +08:00
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Get string length
|
2014-08-29 03:53:32 +08:00
|
|
|
Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
|
2008-11-18 06:21:55 +08:00
|
|
|
ZEND_FUNCTION(strlen)
|
1999-09-21 00:56:09 +08:00
|
|
|
{
|
2014-05-13 14:05:28 +08:00
|
|
|
zend_string *s;
|
2006-05-10 07:53:23 +08:00
|
|
|
|
2014-07-11 20:32:20 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(s)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2008-06-19 07:38:37 +08:00
|
|
|
|
2015-06-30 18:59:27 +08:00
|
|
|
RETVAL_LONG(ZSTR_LEN(s));
|
1999-09-21 00:56:09 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Binary safe string comparison */
|
1999-09-21 00:56:09 +08:00
|
|
|
ZEND_FUNCTION(strcmp)
|
|
|
|
{
|
2014-08-16 17:16:11 +08:00
|
|
|
zend_string *s1, *s2;
|
2015-01-03 17:22:58 +08:00
|
|
|
|
2017-06-08 04:08:18 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 2)
|
|
|
|
Z_PARAM_STR(s1)
|
|
|
|
Z_PARAM_STR(s2)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2008-06-19 07:38:37 +08:00
|
|
|
|
2015-06-30 18:59:27 +08:00
|
|
|
RETURN_LONG(zend_binary_strcmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2)));
|
1999-09-21 00:56:09 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Binary safe string comparison */
|
2000-02-09 01:19:43 +08:00
|
|
|
ZEND_FUNCTION(strncmp)
|
|
|
|
{
|
2014-08-16 17:16:11 +08:00
|
|
|
zend_string *s1, *s2;
|
2014-08-26 01:24:55 +08:00
|
|
|
zend_long len;
|
2008-06-19 07:38:37 +08:00
|
|
|
|
2017-06-08 04:08:18 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_START(3, 3)
|
|
|
|
Z_PARAM_STR(s1)
|
|
|
|
Z_PARAM_STR(s2)
|
|
|
|
Z_PARAM_LONG(len)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2006-04-05 19:36:13 +08:00
|
|
|
|
2008-06-19 07:38:37 +08:00
|
|
|
if (len < 0) {
|
2020-03-30 06:40:18 +08:00
|
|
|
zend_argument_value_error(3, "must be greater than or equal to 0");
|
|
|
|
RETURN_THROWS();
|
2006-04-05 19:36:13 +08:00
|
|
|
}
|
2008-06-19 07:38:37 +08:00
|
|
|
|
2015-06-30 18:59:27 +08:00
|
|
|
RETURN_LONG(zend_binary_strncmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2), len));
|
2000-02-09 01:19:43 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Binary safe case-insensitive string comparison */
|
1999-09-21 00:56:09 +08:00
|
|
|
ZEND_FUNCTION(strcasecmp)
|
|
|
|
{
|
2014-08-16 17:16:11 +08:00
|
|
|
zend_string *s1, *s2;
|
2015-01-03 17:22:58 +08:00
|
|
|
|
2017-06-08 04:08:18 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 2)
|
|
|
|
Z_PARAM_STR(s1)
|
|
|
|
Z_PARAM_STR(s2)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2008-06-19 07:38:37 +08:00
|
|
|
|
2015-06-30 18:59:27 +08:00
|
|
|
RETURN_LONG(zend_binary_strcasecmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2)));
|
1999-09-21 00:56:09 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Binary safe string comparison */
|
2000-07-26 19:32:15 +08:00
|
|
|
ZEND_FUNCTION(strncasecmp)
|
|
|
|
{
|
2014-08-16 17:16:11 +08:00
|
|
|
zend_string *s1, *s2;
|
2014-08-26 01:24:55 +08:00
|
|
|
zend_long len;
|
2008-06-19 07:38:37 +08:00
|
|
|
|
2017-06-08 04:08:18 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_START(3, 3)
|
|
|
|
Z_PARAM_STR(s1)
|
|
|
|
Z_PARAM_STR(s2)
|
|
|
|
Z_PARAM_LONG(len)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2006-04-05 19:36:13 +08:00
|
|
|
|
2008-06-19 07:38:37 +08:00
|
|
|
if (len < 0) {
|
2020-03-30 06:40:18 +08:00
|
|
|
zend_argument_value_error(3, "must be greater than or equal to 0");
|
|
|
|
RETURN_THROWS();
|
2006-04-05 19:36:13 +08:00
|
|
|
}
|
|
|
|
|
2015-06-30 18:59:27 +08:00
|
|
|
RETURN_LONG(zend_binary_strncasecmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2), len));
|
2000-07-26 19:32:15 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Return the current error_reporting level, and if an argument was passed - change to the new level */
|
1999-09-21 00:56:09 +08:00
|
|
|
ZEND_FUNCTION(error_reporting)
|
|
|
|
{
|
2020-07-12 18:40:37 +08:00
|
|
|
zend_long err;
|
|
|
|
zend_bool err_is_null = 1;
|
1999-09-21 00:56:09 +08:00
|
|
|
int old_error_reporting;
|
|
|
|
|
2015-01-13 00:26:12 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_START(0, 1)
|
|
|
|
Z_PARAM_OPTIONAL
|
2020-07-12 18:40:37 +08:00
|
|
|
Z_PARAM_LONG_OR_NULL(err, err_is_null)
|
2015-01-13 00:26:12 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2008-06-19 07:38:37 +08:00
|
|
|
|
1999-09-21 00:56:09 +08:00
|
|
|
old_error_reporting = EG(error_reporting);
|
2020-07-12 18:40:37 +08:00
|
|
|
|
|
|
|
if (!err_is_null) {
|
|
|
|
zend_string *new_val = zend_long_to_str(err);
|
2019-06-06 06:47:22 +08:00
|
|
|
if (UNEXPECTED(!new_val)) {
|
2020-03-30 22:27:38 +08:00
|
|
|
RETURN_THROWS();
|
2019-02-26 22:32:18 +08:00
|
|
|
}
|
|
|
|
|
2015-01-13 04:50:03 +08:00
|
|
|
do {
|
2015-01-13 13:30:54 +08:00
|
|
|
zend_ini_entry *p = EG(error_reporting_ini_entry);
|
|
|
|
|
|
|
|
if (!p) {
|
2017-12-04 18:21:35 +08:00
|
|
|
zval *zv = zend_hash_find_ex(EG(ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING), 1);
|
|
|
|
if (zv) {
|
|
|
|
p = EG(error_reporting_ini_entry) = (zend_ini_entry*)Z_PTR_P(zv);
|
2015-01-13 04:50:03 +08:00
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-01-13 13:30:54 +08:00
|
|
|
if (!p->modified) {
|
2015-01-13 04:50:03 +08:00
|
|
|
if (!EG(modified_ini_directives)) {
|
|
|
|
ALLOC_HASHTABLE(EG(modified_ini_directives));
|
|
|
|
zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
|
|
|
|
}
|
2017-03-04 17:39:13 +08:00
|
|
|
if (EXPECTED(zend_hash_add_ptr(EG(modified_ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING), p) != NULL)) {
|
2015-01-13 13:30:54 +08:00
|
|
|
p->orig_value = p->value;
|
|
|
|
p->orig_modifiable = p->modifiable;
|
|
|
|
p->modified = 1;
|
2015-01-13 04:50:03 +08:00
|
|
|
}
|
2015-01-13 16:32:36 +08:00
|
|
|
} else if (p->orig_value != p->value) {
|
2018-05-28 21:27:12 +08:00
|
|
|
zend_string_release_ex(p->value, 0);
|
2015-01-13 04:50:03 +08:00
|
|
|
}
|
|
|
|
|
2016-05-06 10:45:44 +08:00
|
|
|
p->value = new_val;
|
2020-07-12 18:40:37 +08:00
|
|
|
EG(error_reporting) = err;
|
2015-01-13 04:50:03 +08:00
|
|
|
} while (0);
|
1999-09-21 00:56:09 +08:00
|
|
|
}
|
2000-06-30 19:45:32 +08:00
|
|
|
|
2014-08-26 01:24:55 +08:00
|
|
|
RETVAL_LONG(old_error_reporting);
|
1999-09-21 01:01:38 +08:00
|
|
|
}
|
2001-12-05 01:58:32 +08:00
|
|
|
/* }}} */
|
|
|
|
|
2020-08-28 21:41:27 +08:00
|
|
|
static bool validate_constant_array_argument(HashTable *ht, int argument_number) /* {{{ */
|
2014-12-21 11:03:49 +08:00
|
|
|
{
|
2020-08-28 21:41:27 +08:00
|
|
|
bool ret = 1;
|
2014-12-21 11:03:49 +08:00
|
|
|
zval *val;
|
|
|
|
|
2017-10-06 06:34:50 +08:00
|
|
|
GC_PROTECT_RECURSION(ht);
|
2014-12-21 11:03:49 +08:00
|
|
|
ZEND_HASH_FOREACH_VAL_IND(ht, val) {
|
|
|
|
ZVAL_DEREF(val);
|
|
|
|
if (Z_REFCOUNTED_P(val)) {
|
|
|
|
if (Z_TYPE_P(val) == IS_ARRAY) {
|
2016-11-29 03:59:57 +08:00
|
|
|
if (Z_REFCOUNTED_P(val)) {
|
2017-10-06 06:34:50 +08:00
|
|
|
if (Z_IS_RECURSIVE_P(val)) {
|
2020-07-12 18:40:37 +08:00
|
|
|
zend_argument_value_error(argument_number, "cannot be a recursive array");
|
2014-12-21 11:03:49 +08:00
|
|
|
ret = 0;
|
|
|
|
break;
|
2020-07-12 18:40:37 +08:00
|
|
|
} else if (!validate_constant_array_argument(Z_ARRVAL_P(val), argument_number)) {
|
2014-12-21 11:03:49 +08:00
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (Z_TYPE_P(val) != IS_STRING && Z_TYPE_P(val) != IS_RESOURCE) {
|
2020-07-12 18:40:37 +08:00
|
|
|
zend_argument_type_error(argument_number, "cannot be an object, %s given", zend_zval_type_name(val));
|
2014-12-21 11:03:49 +08:00
|
|
|
ret = 0;
|
|
|
|
break;
|
2015-01-03 17:22:58 +08:00
|
|
|
}
|
2014-12-21 11:03:49 +08:00
|
|
|
}
|
|
|
|
} ZEND_HASH_FOREACH_END();
|
2017-10-06 06:34:50 +08:00
|
|
|
GC_UNPROTECT_RECURSION(ht);
|
2014-12-21 11:03:49 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
static void copy_constant_array(zval *dst, zval *src) /* {{{ */
|
|
|
|
{
|
|
|
|
zend_string *key;
|
|
|
|
zend_ulong idx;
|
|
|
|
zval *new_val, *val;
|
|
|
|
|
|
|
|
array_init_size(dst, zend_hash_num_elements(Z_ARRVAL_P(src)));
|
|
|
|
ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(src), idx, key, val) {
|
|
|
|
/* constant arrays can't contain references */
|
2015-01-22 20:49:38 +08:00
|
|
|
ZVAL_DEREF(val);
|
2014-12-21 11:03:49 +08:00
|
|
|
if (key) {
|
|
|
|
new_val = zend_hash_add_new(Z_ARRVAL_P(dst), key, val);
|
|
|
|
} else {
|
|
|
|
new_val = zend_hash_index_add_new(Z_ARRVAL_P(dst), idx, val);
|
2015-01-03 17:22:58 +08:00
|
|
|
}
|
2014-12-21 11:03:49 +08:00
|
|
|
if (Z_TYPE_P(val) == IS_ARRAY) {
|
2016-11-29 03:59:57 +08:00
|
|
|
if (Z_REFCOUNTED_P(val)) {
|
2014-12-21 11:03:49 +08:00
|
|
|
copy_constant_array(new_val, val);
|
|
|
|
}
|
2017-11-02 12:13:35 +08:00
|
|
|
} else {
|
|
|
|
Z_TRY_ADDREF_P(val);
|
2014-12-21 11:03:49 +08:00
|
|
|
}
|
|
|
|
} ZEND_HASH_FOREACH_END();
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Define a new constant */
|
1999-09-21 05:28:37 +08:00
|
|
|
ZEND_FUNCTION(define)
|
|
|
|
{
|
2014-04-22 05:41:09 +08:00
|
|
|
zend_string *name;
|
2014-02-10 14:04:30 +08:00
|
|
|
zval *val, val_free;
|
2008-06-19 07:38:37 +08:00
|
|
|
zend_bool non_cs = 0;
|
1999-09-21 05:28:37 +08:00
|
|
|
zend_constant c;
|
2006-05-10 07:53:23 +08:00
|
|
|
|
2014-07-11 20:32:20 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 3)
|
|
|
|
Z_PARAM_STR(name)
|
|
|
|
Z_PARAM_ZVAL(val)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_BOOL(non_cs)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2008-06-19 07:38:37 +08:00
|
|
|
|
2015-06-30 18:59:27 +08:00
|
|
|
if (zend_memnstr(ZSTR_VAL(name), "::", sizeof("::") - 1, ZSTR_VAL(name) + ZSTR_LEN(name))) {
|
2020-07-12 18:40:37 +08:00
|
|
|
zend_argument_value_error(1, "cannot be a class constant");
|
|
|
|
RETURN_THROWS();
|
2009-06-08 09:26:03 +08:00
|
|
|
}
|
|
|
|
|
2019-01-29 20:36:26 +08:00
|
|
|
if (non_cs) {
|
2020-07-12 18:40:37 +08:00
|
|
|
zend_error(E_WARNING, "define(): Argument #3 ($case_insensitive) is ignored since declaration of case-insensitive constants is no longer supported");
|
|
|
|
}
|
2019-01-29 20:36:26 +08:00
|
|
|
|
2014-02-10 14:04:30 +08:00
|
|
|
ZVAL_UNDEF(&val_free);
|
|
|
|
|
2008-06-19 07:38:37 +08:00
|
|
|
switch (Z_TYPE_P(val)) {
|
2014-08-26 01:24:55 +08:00
|
|
|
case IS_LONG:
|
1999-09-21 05:28:37 +08:00
|
|
|
case IS_DOUBLE:
|
|
|
|
case IS_STRING:
|
2014-04-30 22:32:42 +08:00
|
|
|
case IS_FALSE:
|
|
|
|
case IS_TRUE:
|
2000-01-04 21:22:58 +08:00
|
|
|
case IS_NULL:
|
2015-09-03 13:07:29 +08:00
|
|
|
case IS_RESOURCE:
|
|
|
|
break;
|
2014-12-21 11:03:49 +08:00
|
|
|
case IS_ARRAY:
|
2016-11-29 03:59:57 +08:00
|
|
|
if (Z_REFCOUNTED_P(val)) {
|
2020-07-12 18:40:37 +08:00
|
|
|
if (!validate_constant_array_argument(Z_ARRVAL_P(val), 2)) {
|
|
|
|
RETURN_THROWS();
|
2014-12-21 11:03:49 +08:00
|
|
|
} else {
|
|
|
|
copy_constant_array(&c.value, val);
|
|
|
|
goto register_constant;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2006-07-10 06:45:11 +08:00
|
|
|
case IS_OBJECT:
|
2020-03-31 18:17:32 +08:00
|
|
|
if (Z_OBJ_HT_P(val)->cast_object(Z_OBJ_P(val), &val_free, IS_STRING) == SUCCESS) {
|
|
|
|
val = &val_free;
|
|
|
|
break;
|
2006-07-10 06:45:11 +08:00
|
|
|
}
|
|
|
|
/* no break */
|
1999-09-21 05:28:37 +08:00
|
|
|
default:
|
2014-02-10 14:04:30 +08:00
|
|
|
zval_ptr_dtor(&val_free);
|
2020-07-12 18:40:37 +08:00
|
|
|
zend_argument_type_error(2, "cannot be an object, %s given", zend_zval_type_name(val));
|
|
|
|
RETURN_THROWS();
|
1999-09-21 05:28:37 +08:00
|
|
|
}
|
2015-01-03 17:22:58 +08:00
|
|
|
|
2017-05-23 20:25:21 +08:00
|
|
|
ZVAL_COPY(&c.value, val);
|
2014-02-10 14:04:30 +08:00
|
|
|
zval_ptr_dtor(&val_free);
|
2018-06-24 02:51:49 +08:00
|
|
|
|
2014-12-21 11:03:49 +08:00
|
|
|
register_constant:
|
2018-07-26 17:58:07 +08:00
|
|
|
/* non persistent */
|
2019-01-29 20:36:26 +08:00
|
|
|
ZEND_CONSTANT_SET_FLAGS(&c, CONST_CS, PHP_USER_CONSTANT);
|
2014-08-26 01:24:55 +08:00
|
|
|
c.name = zend_string_copy(name);
|
2014-12-14 06:06:14 +08:00
|
|
|
if (zend_register_constant(&c) == SUCCESS) {
|
2002-05-13 16:41:55 +08:00
|
|
|
RETURN_TRUE;
|
2000-07-28 17:44:46 +08:00
|
|
|
} else {
|
2002-05-13 16:41:55 +08:00
|
|
|
RETURN_FALSE;
|
2000-07-28 17:44:46 +08:00
|
|
|
}
|
1999-09-21 05:28:37 +08:00
|
|
|
}
|
2001-12-05 01:58:32 +08:00
|
|
|
/* }}} */
|
1999-09-21 05:28:37 +08:00
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Check whether a constant exists
|
2014-08-29 03:53:32 +08:00
|
|
|
Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
|
1999-09-21 05:28:37 +08:00
|
|
|
ZEND_FUNCTION(defined)
|
|
|
|
{
|
2014-04-25 04:56:15 +08:00
|
|
|
zend_string *name;
|
2006-05-10 07:53:23 +08:00
|
|
|
|
2014-07-11 20:32:20 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(name)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2015-01-03 17:22:58 +08:00
|
|
|
|
2019-01-31 00:16:09 +08:00
|
|
|
if (zend_get_constant_ex(name, zend_get_executed_scope(), ZEND_FETCH_CLASS_SILENT)) {
|
2004-03-01 16:07:25 +08:00
|
|
|
RETURN_TRUE;
|
1999-09-21 05:28:37 +08:00
|
|
|
} else {
|
2004-03-01 16:07:25 +08:00
|
|
|
RETURN_FALSE;
|
1999-09-21 05:28:37 +08:00
|
|
|
}
|
|
|
|
}
|
2001-12-05 01:58:32 +08:00
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Retrieves the class name */
|
1999-09-21 05:28:37 +08:00
|
|
|
ZEND_FUNCTION(get_class)
|
|
|
|
{
|
2008-06-19 07:38:37 +08:00
|
|
|
zval *obj = NULL;
|
2006-05-10 07:53:23 +08:00
|
|
|
|
2016-08-12 06:21:04 +08:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|o", &obj) == FAILURE) {
|
2019-12-31 00:35:46 +08:00
|
|
|
RETURN_THROWS();
|
2008-06-19 07:38:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!obj) {
|
2016-04-28 09:13:34 +08:00
|
|
|
zend_class_entry *scope = zend_get_executed_scope();
|
|
|
|
|
|
|
|
if (scope) {
|
|
|
|
RETURN_STR_COPY(scope->name);
|
2004-03-15 06:40:25 +08:00
|
|
|
} else {
|
2020-03-30 06:40:18 +08:00
|
|
|
zend_throw_error(NULL, "get_class() without arguments must be called from within a class");
|
|
|
|
RETURN_THROWS();
|
2004-03-15 06:40:25 +08:00
|
|
|
}
|
|
|
|
}
|
2001-07-29 02:35:22 +08:00
|
|
|
|
2015-03-12 21:53:51 +08:00
|
|
|
RETURN_STR_COPY(Z_OBJCE_P(obj)->name);
|
1999-09-21 05:28:37 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Retrieves the "Late Static Binding" class name */
|
2007-09-29 15:28:34 +08:00
|
|
|
ZEND_FUNCTION(get_called_class)
|
|
|
|
{
|
2015-04-23 17:16:37 +08:00
|
|
|
zend_class_entry *called_scope;
|
|
|
|
|
2020-01-03 19:11:45 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2008-06-19 07:38:37 +08:00
|
|
|
|
2015-04-23 17:16:37 +08:00
|
|
|
called_scope = zend_get_called_scope(execute_data);
|
2020-03-30 06:40:18 +08:00
|
|
|
if (!called_scope) {
|
|
|
|
zend_throw_error(NULL, "get_called_class() must be called from within a class");
|
|
|
|
RETURN_THROWS();
|
2007-09-29 15:28:34 +08:00
|
|
|
}
|
2020-03-30 06:40:18 +08:00
|
|
|
|
|
|
|
RETURN_STR_COPY(called_scope->name);
|
2007-09-29 15:28:34 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Retrieves the parent class name for object or class or current scope or false if not in a scope. */
|
1999-09-21 05:28:37 +08:00
|
|
|
ZEND_FUNCTION(get_parent_class)
|
|
|
|
{
|
2001-03-27 03:03:06 +08:00
|
|
|
zend_class_entry *ce = NULL;
|
2015-01-03 17:22:58 +08:00
|
|
|
|
2020-06-30 17:14:58 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_START(0, 1)
|
|
|
|
Z_PARAM_OPTIONAL
|
2020-09-11 06:23:54 +08:00
|
|
|
Z_PARAM_OBJ_OR_CLASS_NAME(ce)
|
2020-06-30 17:14:58 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2008-06-19 07:38:37 +08:00
|
|
|
|
2020-06-30 17:14:58 +08:00
|
|
|
if (!ce) {
|
2016-04-28 09:13:34 +08:00
|
|
|
ce = zend_get_executed_scope();
|
2001-03-27 03:03:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ce && ce->parent) {
|
2015-03-12 21:53:51 +08:00
|
|
|
RETURN_STR_COPY(ce->parent->name);
|
2001-03-27 03:03:06 +08:00
|
|
|
} else {
|
1999-09-21 05:28:37 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
1999-12-16 05:26:43 +08:00
|
|
|
|
2014-09-20 15:16:09 +08:00
|
|
|
static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass) /* {{{ */
|
1999-12-16 05:26:43 +08:00
|
|
|
{
|
2008-06-19 07:38:37 +08:00
|
|
|
zval *obj;
|
2014-02-10 14:04:30 +08:00
|
|
|
zend_string *class_name;
|
2003-03-05 19:14:44 +08:00
|
|
|
zend_class_entry *instance_ce;
|
2014-02-10 14:04:30 +08:00
|
|
|
zend_class_entry *ce;
|
2011-11-09 13:27:45 +08:00
|
|
|
zend_bool allow_string = only_subclass;
|
2003-03-05 19:14:44 +08:00
|
|
|
zend_bool retval;
|
1999-12-16 05:26:43 +08:00
|
|
|
|
2014-07-11 20:32:20 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 3)
|
|
|
|
Z_PARAM_ZVAL(obj)
|
|
|
|
Z_PARAM_STR(class_name)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_BOOL(allow_string)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2011-11-09 13:27:45 +08:00
|
|
|
/*
|
2015-01-03 17:22:58 +08:00
|
|
|
* allow_string - is_a default is no, is_subclass_of is yes.
|
2011-11-09 13:27:45 +08:00
|
|
|
* if it's allowed, then the autoloader will be called if the class does not exist.
|
|
|
|
* default behaviour is different, as 'is_a' used to be used to test mixed return values
|
|
|
|
* and there is no easy way to deprecate this.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (allow_string && Z_TYPE_P(obj) == IS_STRING) {
|
2014-12-14 06:06:14 +08:00
|
|
|
instance_ce = zend_lookup_class(Z_STR_P(obj));
|
2014-02-10 14:04:30 +08:00
|
|
|
if (!instance_ce) {
|
2004-10-27 07:25:05 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2014-10-09 19:58:14 +08:00
|
|
|
} else if (Z_TYPE_P(obj) == IS_OBJECT) {
|
2011-07-04 22:55:39 +08:00
|
|
|
instance_ce = Z_OBJCE_P(obj);
|
2004-10-27 07:25:05 +08:00
|
|
|
} else {
|
2002-02-07 22:08:43 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
1999-12-16 05:26:43 +08:00
|
|
|
|
2015-01-19 22:10:01 +08:00
|
|
|
if (!only_subclass && EXPECTED(zend_string_equals(instance_ce->name, class_name))) {
|
|
|
|
retval = 1;
|
2003-03-05 19:14:44 +08:00
|
|
|
} else {
|
2019-05-24 20:41:38 +08:00
|
|
|
ce = zend_lookup_class_ex(class_name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
|
2015-01-19 22:10:01 +08:00
|
|
|
if (!ce) {
|
2003-03-05 19:14:44 +08:00
|
|
|
retval = 0;
|
2015-01-19 22:10:01 +08:00
|
|
|
} else {
|
|
|
|
if (only_subclass && instance_ce == ce) {
|
|
|
|
retval = 0;
|
|
|
|
} else {
|
|
|
|
retval = instanceof_function(instance_ce, ce);
|
|
|
|
}
|
1999-12-16 05:26:43 +08:00
|
|
|
}
|
1999-12-16 06:37:05 +08:00
|
|
|
}
|
2003-03-05 19:14:44 +08:00
|
|
|
|
|
|
|
RETURN_BOOL(retval);
|
1999-12-16 05:26:43 +08:00
|
|
|
}
|
2014-09-20 15:16:09 +08:00
|
|
|
/* }}} */
|
2002-02-02 06:55:02 +08:00
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Returns true if the object has this class as one of its parents */
|
2002-02-02 06:55:02 +08:00
|
|
|
ZEND_FUNCTION(is_subclass_of)
|
|
|
|
{
|
|
|
|
is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Returns true if the first argument is an object and is this class or has this class as one of its parents, */
|
2002-02-02 06:55:02 +08:00
|
|
|
ZEND_FUNCTION(is_a)
|
|
|
|
{
|
|
|
|
is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
|
|
|
|
}
|
1999-12-16 05:26:43 +08:00
|
|
|
/* }}} */
|
1999-09-21 05:28:37 +08:00
|
|
|
|
2004-10-13 06:19:43 +08:00
|
|
|
/* {{{ add_class_vars */
|
2020-08-28 21:41:27 +08:00
|
|
|
static void add_class_vars(zend_class_entry *scope, zend_class_entry *ce, bool statics, zval *return_value)
|
2004-10-13 06:19:43 +08:00
|
|
|
{
|
2010-05-24 22:11:39 +08:00
|
|
|
zend_property_info *prop_info;
|
2014-02-10 14:04:30 +08:00
|
|
|
zval *prop, prop_copy;
|
|
|
|
zend_string *key;
|
2010-05-24 22:11:39 +08:00
|
|
|
|
2014-04-22 21:46:34 +08:00
|
|
|
ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
|
2018-09-11 16:56:45 +08:00
|
|
|
if (((prop_info->flags & ZEND_ACC_PROTECTED) &&
|
2019-03-18 22:17:29 +08:00
|
|
|
!zend_check_protected(prop_info->ce, scope)) ||
|
|
|
|
((prop_info->flags & ZEND_ACC_PRIVATE) &&
|
|
|
|
prop_info->ce != scope)) {
|
2010-05-24 22:11:39 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
prop = NULL;
|
2014-11-06 19:50:03 +08:00
|
|
|
if (statics && (prop_info->flags & ZEND_ACC_STATIC) != 0) {
|
|
|
|
prop = &ce->default_static_members_table[prop_info->offset];
|
2018-06-22 18:58:48 +08:00
|
|
|
ZVAL_DEINDIRECT(prop);
|
2014-11-06 19:50:03 +08:00
|
|
|
} else if (!statics && (prop_info->flags & ZEND_ACC_STATIC) == 0) {
|
|
|
|
prop = &ce->default_properties_table[OBJ_PROP_TO_NUM(prop_info->offset)];
|
2010-05-24 22:11:39 +08:00
|
|
|
}
|
2019-07-23 18:41:24 +08:00
|
|
|
if (!prop) {
|
2010-05-24 22:11:39 +08:00
|
|
|
continue;
|
|
|
|
}
|
2004-10-13 06:19:43 +08:00
|
|
|
|
2019-07-23 18:41:24 +08:00
|
|
|
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);
|
|
|
|
}
|
2017-10-31 04:13:10 +08:00
|
|
|
prop = &prop_copy;
|
2006-05-10 07:53:23 +08:00
|
|
|
|
2010-05-24 22:11:39 +08:00
|
|
|
/* this is necessary to make it able to work with default array
|
|
|
|
* properties, returned to user */
|
2017-10-10 15:11:05 +08:00
|
|
|
if (Z_OPT_TYPE_P(prop) == IS_CONSTANT_AST) {
|
2016-04-28 09:13:34 +08:00
|
|
|
if (UNEXPECTED(zval_update_constant_ex(prop, NULL) != SUCCESS)) {
|
2015-04-02 07:05:25 +08:00
|
|
|
return;
|
|
|
|
}
|
2004-10-13 06:19:43 +08:00
|
|
|
}
|
2010-05-24 22:11:39 +08:00
|
|
|
|
2014-06-03 04:36:31 +08:00
|
|
|
zend_hash_add_new(Z_ARRVAL_P(return_value), key, prop);
|
2014-04-18 23:18:11 +08:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
2004-10-13 06:19:43 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Returns an array of default properties of the class. */
|
2000-02-27 01:54:00 +08:00
|
|
|
ZEND_FUNCTION(get_class_vars)
|
|
|
|
{
|
2020-09-22 19:05:05 +08:00
|
|
|
zend_class_entry *ce = NULL, *scope;
|
2000-02-27 01:54:00 +08:00
|
|
|
|
2020-09-22 19:05:05 +08:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "C", &ce) == FAILURE) {
|
2019-12-31 00:35:46 +08:00
|
|
|
RETURN_THROWS();
|
2000-02-27 01:54:00 +08:00
|
|
|
}
|
|
|
|
|
2020-09-22 19:05:05 +08:00
|
|
|
array_init(return_value);
|
|
|
|
if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
|
|
|
|
if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
|
|
|
|
return;
|
2015-04-02 07:05:25 +08:00
|
|
|
}
|
2000-02-27 01:54:00 +08:00
|
|
|
}
|
2020-09-22 19:05:05 +08:00
|
|
|
|
|
|
|
scope = zend_get_executed_scope();
|
|
|
|
add_class_vars(scope, ce, 0, return_value);
|
|
|
|
add_class_vars(scope, ce, 1, return_value);
|
2000-02-27 01:54:00 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Returns an array of object properties */
|
2000-02-27 01:54:00 +08:00
|
|
|
ZEND_FUNCTION(get_object_vars)
|
|
|
|
{
|
2008-06-19 07:38:37 +08:00
|
|
|
zval *obj;
|
2014-02-10 14:04:30 +08:00
|
|
|
zval *value;
|
2003-11-11 05:03:04 +08:00
|
|
|
HashTable *properties;
|
2014-02-10 14:04:30 +08:00
|
|
|
zend_string *key;
|
2007-07-24 19:39:56 +08:00
|
|
|
zend_object *zobj;
|
2016-11-23 03:49:12 +08:00
|
|
|
zend_ulong num_key;
|
2000-02-27 01:54:00 +08:00
|
|
|
|
2014-07-11 20:32:20 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_OBJECT(obj)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2000-02-27 01:54:00 +08:00
|
|
|
|
2019-01-31 23:47:58 +08:00
|
|
|
zobj = Z_OBJ_P(obj);
|
|
|
|
properties = zobj->handlers->get_properties(zobj);
|
2006-02-07 08:33:13 +08:00
|
|
|
if (properties == NULL) {
|
2019-06-06 15:49:25 +08:00
|
|
|
RETURN_EMPTY_ARRAY();
|
2006-02-07 08:33:13 +08:00
|
|
|
}
|
|
|
|
|
2017-10-06 06:34:50 +08:00
|
|
|
if (!zobj->ce->default_properties_count && properties == zobj->properties && !GC_IS_RECURSIVE(properties)) {
|
2014-12-23 07:49:47 +08:00
|
|
|
/* fast copy */
|
2015-06-17 17:50:16 +08:00
|
|
|
if (EXPECTED(zobj->handlers == &std_object_handlers)) {
|
2016-11-15 02:20:45 +08:00
|
|
|
RETURN_ARR(zend_proptable_to_symtable(properties, 0));
|
2015-06-17 17:50:16 +08:00
|
|
|
}
|
2016-11-15 02:20:45 +08:00
|
|
|
RETURN_ARR(zend_proptable_to_symtable(properties, 1));
|
2014-12-23 07:49:47 +08:00
|
|
|
} else {
|
|
|
|
array_init_size(return_value, zend_hash_num_elements(properties));
|
|
|
|
|
2016-11-23 03:49:12 +08:00
|
|
|
ZEND_HASH_FOREACH_KEY_VAL(properties, num_key, key, value) {
|
2018-10-20 23:11:17 +08:00
|
|
|
zend_bool is_dynamic = 1;
|
2016-11-23 03:49:12 +08:00
|
|
|
if (Z_TYPE_P(value) == IS_INDIRECT) {
|
|
|
|
value = Z_INDIRECT_P(value);
|
|
|
|
if (UNEXPECTED(Z_ISUNDEF_P(value))) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-10-20 23:11:17 +08:00
|
|
|
is_dynamic = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key && zend_check_property_access(zobj, key, is_dynamic) == FAILURE) {
|
|
|
|
continue;
|
2016-11-23 03:49:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Z_ISREF_P(value) && Z_REFCOUNT_P(value) == 1) {
|
|
|
|
value = Z_REFVAL_P(value);
|
|
|
|
}
|
|
|
|
Z_TRY_ADDREF_P(value);
|
|
|
|
|
|
|
|
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);
|
2018-10-20 23:11:17 +08:00
|
|
|
} else if (!is_dynamic && ZSTR_VAL(key)[0] == 0) {
|
2016-11-23 03:49:12 +08:00
|
|
|
const char *prop_name, *class_name;
|
|
|
|
size_t prop_len;
|
|
|
|
zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_len);
|
|
|
|
/* We assume here that a mangled property name is never
|
|
|
|
* numeric. This is probably a safe assumption, but
|
|
|
|
* theoretically someone might write an extension with
|
|
|
|
* private, numeric properties. Well, too bad.
|
|
|
|
*/
|
|
|
|
zend_hash_str_add_new(Z_ARRVAL_P(return_value), prop_name, prop_len, value);
|
|
|
|
} else {
|
2017-09-08 04:29:57 +08:00
|
|
|
zend_symtable_add_new(Z_ARRVAL_P(return_value), key, value);
|
2004-10-04 16:59:29 +08:00
|
|
|
}
|
2014-12-23 07:49:47 +08:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
|
|
|
}
|
2000-02-27 01:54:00 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Returns an array of mangled object properties. Does not respect property visibility. */
|
2019-05-14 20:27:10 +08:00
|
|
|
ZEND_FUNCTION(get_mangled_object_vars)
|
|
|
|
{
|
|
|
|
zval *obj;
|
|
|
|
HashTable *properties;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_OBJECT(obj)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
2019-06-11 16:29:20 +08:00
|
|
|
properties = Z_OBJ_HT_P(obj)->get_properties(Z_OBJ_P(obj));
|
2019-05-14 20:27:10 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-08-28 21:41:27 +08:00
|
|
|
static bool same_name(zend_string *key, zend_string *name) /* {{{ */
|
2013-03-19 19:45:48 +08:00
|
|
|
{
|
2014-12-24 20:04:51 +08:00
|
|
|
zend_string *lcname;
|
2020-08-28 21:41:27 +08:00
|
|
|
bool ret;
|
2014-12-24 20:04:51 +08:00
|
|
|
|
|
|
|
if (key == name) {
|
|
|
|
return 1;
|
|
|
|
}
|
2015-06-30 18:59:27 +08:00
|
|
|
if (ZSTR_LEN(key) != ZSTR_LEN(name)) {
|
2014-12-24 20:04:51 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2015-01-03 17:22:58 +08:00
|
|
|
lcname = zend_string_tolower(name);
|
2015-06-30 18:59:27 +08:00
|
|
|
ret = memcmp(ZSTR_VAL(lcname), ZSTR_VAL(key), ZSTR_LEN(key)) == 0;
|
2018-05-28 21:27:12 +08:00
|
|
|
zend_string_release_ex(lcname, 0);
|
2013-03-19 19:45:48 +08:00
|
|
|
return ret;
|
|
|
|
}
|
2014-09-20 15:16:09 +08:00
|
|
|
/* }}} */
|
2001-12-05 01:58:32 +08:00
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Returns an array of method names for class or class instance. */
|
2000-03-24 01:47:28 +08:00
|
|
|
ZEND_FUNCTION(get_class_methods)
|
|
|
|
{
|
2014-02-10 14:04:30 +08:00
|
|
|
zval method_name;
|
|
|
|
zend_class_entry *ce = NULL;
|
2016-04-28 09:13:34 +08:00
|
|
|
zend_class_entry *scope;
|
2003-09-19 00:20:42 +08:00
|
|
|
zend_function *mptr;
|
2000-03-24 01:47:28 +08:00
|
|
|
|
2020-07-01 22:49:57 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
2020-09-11 06:23:54 +08:00
|
|
|
Z_PARAM_OBJ_OR_CLASS_NAME(ce)
|
2020-07-01 22:49:57 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2001-03-27 04:14:21 +08:00
|
|
|
|
|
|
|
array_init(return_value);
|
2016-04-28 09:13:34 +08:00
|
|
|
scope = zend_get_executed_scope();
|
2003-09-19 00:20:42 +08:00
|
|
|
|
2020-03-02 18:07:57 +08:00
|
|
|
ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) {
|
2015-01-03 17:22:58 +08:00
|
|
|
if ((mptr->common.fn_flags & ZEND_ACC_PUBLIC)
|
2016-04-28 09:13:34 +08:00
|
|
|
|| (scope &&
|
2019-03-18 22:17:29 +08:00
|
|
|
(((mptr->common.fn_flags & ZEND_ACC_PROTECTED) &&
|
|
|
|
zend_check_protected(mptr->common.scope, scope))
|
2005-05-03 16:52:04 +08:00
|
|
|
|| ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) &&
|
2019-03-18 22:17:29 +08:00
|
|
|
scope == mptr->common.scope)))
|
2019-02-14 18:28:13 +08:00
|
|
|
) {
|
2020-03-02 18:07:57 +08:00
|
|
|
ZVAL_STR_COPY(&method_name, mptr->common.function_name);
|
|
|
|
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
|
2004-10-12 19:01:08 +08:00
|
|
|
}
|
2014-04-18 23:18:11 +08:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
2000-03-24 01:47:28 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
2003-11-28 01:06:26 +08:00
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Checks if the class method exists */
|
1999-09-21 05:28:37 +08:00
|
|
|
ZEND_FUNCTION(method_exists)
|
|
|
|
{
|
2015-01-03 17:22:58 +08:00
|
|
|
zval *klass;
|
2014-02-10 14:04:30 +08:00
|
|
|
zend_string *method_name;
|
|
|
|
zend_string *lcname;
|
2019-09-03 19:14:33 +08:00
|
|
|
zend_class_entry *ce;
|
|
|
|
zend_function *func;
|
2006-05-10 07:53:23 +08:00
|
|
|
|
2014-07-11 20:32:20 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 2)
|
|
|
|
Z_PARAM_ZVAL(klass)
|
|
|
|
Z_PARAM_STR(method_name)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2017-12-31 12:35:25 +08:00
|
|
|
|
2008-06-19 07:38:37 +08:00
|
|
|
if (Z_TYPE_P(klass) == IS_OBJECT) {
|
|
|
|
ce = Z_OBJCE_P(klass);
|
|
|
|
} else if (Z_TYPE_P(klass) == IS_STRING) {
|
2014-12-14 06:06:14 +08:00
|
|
|
if ((ce = zend_lookup_class(Z_STR_P(klass))) == NULL) {
|
2014-03-03 16:10:15 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2005-02-27 23:03:09 +08:00
|
|
|
} else {
|
2020-04-09 16:55:53 +08:00
|
|
|
zend_argument_type_error(1, "must be of type object|string, %s given", zend_zval_type_name(klass));
|
|
|
|
RETURN_THROWS();
|
2002-02-07 22:08:43 +08:00
|
|
|
}
|
|
|
|
|
2014-12-24 20:04:51 +08:00
|
|
|
lcname = zend_string_tolower(method_name);
|
2019-09-03 19:14:33 +08:00
|
|
|
func = zend_hash_find_ptr(&ce->function_table, lcname);
|
|
|
|
zend_string_release_ex(lcname, 0);
|
|
|
|
|
|
|
|
if (func) {
|
2019-10-04 18:38:18 +08:00
|
|
|
/* 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);
|
2019-09-03 19:14:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Z_TYPE_P(klass) == IS_OBJECT) {
|
2018-09-19 15:37:04 +08:00
|
|
|
zend_object *obj = Z_OBJ_P(klass);
|
2019-09-03 19:14:33 +08:00
|
|
|
func = Z_OBJ_HT_P(klass)->get_method(&obj, method_name, NULL);
|
2018-09-19 15:37:04 +08:00
|
|
|
if (func != NULL) {
|
2015-04-11 04:01:00 +08:00
|
|
|
if (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
|
2010-06-12 07:20:13 +08:00
|
|
|
/* Returns true to the fake Closure's __invoke */
|
2014-08-26 04:40:58 +08:00
|
|
|
RETVAL_BOOL(func->common.scope == zend_ce_closure
|
|
|
|
&& zend_string_equals_literal(method_name, ZEND_INVOKE_FUNC_NAME));
|
2015-01-03 17:22:58 +08:00
|
|
|
|
2018-05-28 21:27:12 +08:00
|
|
|
zend_string_release_ex(func->common.function_name, 0);
|
2015-04-11 04:01:00 +08:00
|
|
|
zend_free_trampoline(func);
|
2010-06-12 07:20:13 +08:00
|
|
|
return;
|
2005-04-26 16:47:31 +08:00
|
|
|
}
|
2005-03-01 02:53:33 +08:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
1999-09-21 05:28:37 +08:00
|
|
|
}
|
2005-03-01 02:53:33 +08:00
|
|
|
RETURN_FALSE;
|
1999-09-21 05:28:37 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Checks if the object or class has a property */
|
2005-04-08 21:33:15 +08:00
|
|
|
ZEND_FUNCTION(property_exists)
|
|
|
|
{
|
2008-06-19 07:38:37 +08:00
|
|
|
zval *object;
|
2014-02-10 14:04:30 +08:00
|
|
|
zend_string *property;
|
|
|
|
zend_class_entry *ce;
|
2005-04-08 21:33:15 +08:00
|
|
|
zend_property_info *property_info;
|
|
|
|
|
2014-12-14 06:06:14 +08:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zS", &object, &property) == FAILURE) {
|
2019-12-31 00:35:46 +08:00
|
|
|
RETURN_THROWS();
|
2005-04-08 21:33:15 +08:00
|
|
|
}
|
2008-06-19 07:38:37 +08:00
|
|
|
|
2008-08-19 01:44:02 +08:00
|
|
|
if (Z_TYPE_P(object) == IS_STRING) {
|
2014-12-14 06:06:14 +08:00
|
|
|
ce = zend_lookup_class(Z_STR_P(object));
|
2014-02-19 05:12:05 +08:00
|
|
|
if (!ce) {
|
|
|
|
RETURN_FALSE;
|
2015-01-03 17:22:58 +08:00
|
|
|
}
|
2008-08-19 01:44:02 +08:00
|
|
|
} else if (Z_TYPE_P(object) == IS_OBJECT) {
|
|
|
|
ce = Z_OBJCE_P(object);
|
|
|
|
} else {
|
2020-03-30 06:40:18 +08:00
|
|
|
zend_argument_type_error(1, "must be of type object|string, %s given", zend_zval_type_name(object));
|
|
|
|
RETURN_THROWS();
|
2008-08-19 01:44:02 +08:00
|
|
|
}
|
|
|
|
|
2018-09-11 16:56:45 +08:00
|
|
|
property_info = zend_hash_find_ptr(&ce->properties_info, property);
|
|
|
|
if (property_info != NULL
|
|
|
|
&& (!(property_info->flags & ZEND_ACC_PRIVATE)
|
|
|
|
|| property_info->ce == ce)) {
|
2008-08-19 01:44:02 +08:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
2006-05-10 07:53:23 +08:00
|
|
|
|
2008-08-19 01:44:02 +08:00
|
|
|
if (Z_TYPE_P(object) == IS_OBJECT &&
|
2019-01-31 23:47:58 +08:00
|
|
|
Z_OBJ_HANDLER_P(object, has_property)(Z_OBJ_P(object), property, 2, NULL)) {
|
2008-08-19 01:44:02 +08:00
|
|
|
RETURN_TRUE;
|
2005-04-08 21:33:15 +08:00
|
|
|
}
|
2008-08-19 01:44:02 +08:00
|
|
|
RETURN_FALSE;
|
2005-04-08 21:33:15 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2019-03-18 22:17:29 +08:00
|
|
|
static inline void class_exists_impl(INTERNAL_FUNCTION_PARAMETERS, int flags, int skip_flags) /* {{{ */
|
1999-12-15 05:15:24 +08:00
|
|
|
{
|
2019-03-18 22:17:29 +08:00
|
|
|
zend_string *name;
|
|
|
|
zend_string *lcname;
|
2014-02-10 14:04:30 +08:00
|
|
|
zend_class_entry *ce;
|
2007-11-22 21:27:13 +08:00
|
|
|
zend_bool autoload = 1;
|
1999-12-15 05:15:24 +08:00
|
|
|
|
2014-07-11 20:32:20 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
2019-03-18 22:17:29 +08:00
|
|
|
Z_PARAM_STR(name)
|
2014-07-11 20:32:20 +08:00
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_BOOL(autoload)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2003-04-09 02:22:32 +08:00
|
|
|
|
2004-04-28 02:09:40 +08:00
|
|
|
if (!autoload) {
|
2019-03-18 22:17:29 +08:00
|
|
|
if (ZSTR_VAL(name)[0] == '\\') {
|
2014-02-10 14:04:30 +08:00
|
|
|
/* Ignore leading "\" */
|
2019-03-18 22:17:29 +08:00
|
|
|
lcname = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
|
|
|
|
zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
|
2014-02-10 14:04:30 +08:00
|
|
|
} else {
|
2019-03-18 22:17:29 +08:00
|
|
|
lcname = zend_string_tolower(name);
|
2008-12-10 03:17:11 +08:00
|
|
|
}
|
2015-02-13 06:19:14 +08:00
|
|
|
|
2019-03-18 22:17:29 +08:00
|
|
|
ce = zend_hash_find_ptr(EG(class_table), lcname);
|
|
|
|
zend_string_release_ex(lcname, 0);
|
2015-02-13 06:31:01 +08:00
|
|
|
} else {
|
2019-03-18 22:17:29 +08:00
|
|
|
ce = zend_lookup_class(name);
|
2004-04-28 02:09:40 +08:00
|
|
|
}
|
2003-11-25 02:13:29 +08:00
|
|
|
|
2014-02-10 14:04:30 +08:00
|
|
|
if (ce) {
|
2019-12-24 14:20:55 +08:00
|
|
|
RETURN_BOOL(((ce->ce_flags & flags) == flags) && !(ce->ce_flags & skip_flags));
|
2004-08-25 08:41:43 +08:00
|
|
|
} else {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
}
|
2019-03-18 22:17:29 +08:00
|
|
|
/* {{{ */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Checks if the class exists */
|
2019-03-18 22:17:29 +08:00
|
|
|
ZEND_FUNCTION(class_exists)
|
|
|
|
{
|
2019-12-24 14:04:19 +08:00
|
|
|
class_exists_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED, ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT);
|
2019-03-18 22:17:29 +08:00
|
|
|
}
|
2004-08-25 08:41:43 +08:00
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Checks if the class exists */
|
2004-08-25 08:41:43 +08:00
|
|
|
ZEND_FUNCTION(interface_exists)
|
|
|
|
{
|
2019-12-24 14:20:55 +08:00
|
|
|
class_exists_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED|ZEND_ACC_INTERFACE, 0);
|
1999-12-15 05:15:24 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Checks if the trait exists */
|
2011-01-10 03:57:41 +08:00
|
|
|
ZEND_FUNCTION(trait_exists)
|
|
|
|
{
|
2019-03-18 22:17:29 +08:00
|
|
|
class_exists_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_TRAIT, 0);
|
2011-01-10 03:57:41 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Checks if the function exists */
|
1999-12-15 05:15:24 +08:00
|
|
|
ZEND_FUNCTION(function_exists)
|
|
|
|
{
|
2014-12-24 20:04:51 +08:00
|
|
|
zend_string *name;
|
Completely remove disabled functions from function table
Currently, disabling a function only replaces the internal
function handler with one that throws a warning, and a few
places in the engine special-case such functions, such as
function_exists. This leaves us with a Schrödinger's function,
which both does not exist (function_exists returns false) and
does exist (you cannot define a function with the same name).
In particular, this prevents the implementation of robust
polyfills, as reported in https://bugs.php.net/bug.php?id=79382:
if (!function_exists('getallheaders')) {
function getallheaders(...) { ... }
}
If getallheaders() is a disabled function, this code will break.
This patch changes disable_functions to remove the functions from
the function table completely. For all intents and purposes, it
will look like the function does not exist.
This also renders two bits of PHP functionality obsolete and thus
deprecated:
* ReflectionFunction::isDisabled(), as it will no longer be
possible to construct the ReflectionFunction of a disabled
function in the first place.
* get_defined_functions() with $exclude_disabled=false, as
get_defined_functions() now never returns disabled functions.
Fixed bug #79382.
Closes GH-5473.
2020-04-27 19:17:37 +08:00
|
|
|
zend_bool exists;
|
2014-02-10 14:04:30 +08:00
|
|
|
zend_string *lcname;
|
2015-01-03 17:22:58 +08:00
|
|
|
|
2014-07-11 20:32:20 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
2014-12-24 20:04:51 +08:00
|
|
|
Z_PARAM_STR(name)
|
2014-07-11 20:32:20 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
1999-12-23 02:49:23 +08:00
|
|
|
|
2015-06-30 18:59:27 +08:00
|
|
|
if (ZSTR_VAL(name)[0] == '\\') {
|
2014-02-10 14:04:30 +08:00
|
|
|
/* Ignore leading "\" */
|
2015-06-30 18:59:27 +08:00
|
|
|
lcname = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
|
|
|
|
zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
|
2014-02-10 14:04:30 +08:00
|
|
|
} else {
|
2014-12-24 20:04:51 +08:00
|
|
|
lcname = zend_string_tolower(name);
|
2009-03-09 01:28:39 +08:00
|
|
|
}
|
2015-01-03 17:22:58 +08:00
|
|
|
|
Completely remove disabled functions from function table
Currently, disabling a function only replaces the internal
function handler with one that throws a warning, and a few
places in the engine special-case such functions, such as
function_exists. This leaves us with a Schrödinger's function,
which both does not exist (function_exists returns false) and
does exist (you cannot define a function with the same name).
In particular, this prevents the implementation of robust
polyfills, as reported in https://bugs.php.net/bug.php?id=79382:
if (!function_exists('getallheaders')) {
function getallheaders(...) { ... }
}
If getallheaders() is a disabled function, this code will break.
This patch changes disable_functions to remove the functions from
the function table completely. For all intents and purposes, it
will look like the function does not exist.
This also renders two bits of PHP functionality obsolete and thus
deprecated:
* ReflectionFunction::isDisabled(), as it will no longer be
possible to construct the ReflectionFunction of a disabled
function in the first place.
* get_defined_functions() with $exclude_disabled=false, as
get_defined_functions() now never returns disabled functions.
Fixed bug #79382.
Closes GH-5473.
2020-04-27 19:17:37 +08:00
|
|
|
exists = zend_hash_exists(EG(function_table), lcname);
|
2018-05-28 21:27:12 +08:00
|
|
|
zend_string_release_ex(lcname, 0);
|
1999-12-23 02:49:23 +08:00
|
|
|
|
Completely remove disabled functions from function table
Currently, disabling a function only replaces the internal
function handler with one that throws a warning, and a few
places in the engine special-case such functions, such as
function_exists. This leaves us with a Schrödinger's function,
which both does not exist (function_exists returns false) and
does exist (you cannot define a function with the same name).
In particular, this prevents the implementation of robust
polyfills, as reported in https://bugs.php.net/bug.php?id=79382:
if (!function_exists('getallheaders')) {
function getallheaders(...) { ... }
}
If getallheaders() is a disabled function, this code will break.
This patch changes disable_functions to remove the functions from
the function table completely. For all intents and purposes, it
will look like the function does not exist.
This also renders two bits of PHP functionality obsolete and thus
deprecated:
* ReflectionFunction::isDisabled(), as it will no longer be
possible to construct the ReflectionFunction of a disabled
function in the first place.
* get_defined_functions() with $exclude_disabled=false, as
get_defined_functions() now never returns disabled functions.
Fixed bug #79382.
Closes GH-5473.
2020-04-27 19:17:37 +08:00
|
|
|
RETURN_BOOL(exists);
|
1999-12-15 05:15:24 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Creates an alias for user defined class */
|
2008-05-12 15:11:55 +08:00
|
|
|
ZEND_FUNCTION(class_alias)
|
|
|
|
{
|
2014-02-10 14:04:30 +08:00
|
|
|
zend_string *class_name;
|
|
|
|
char *alias_name;
|
|
|
|
zend_class_entry *ce;
|
2014-08-27 21:31:48 +08:00
|
|
|
size_t alias_name_len;
|
2008-05-12 15:11:55 +08:00
|
|
|
zend_bool autoload = 1;
|
|
|
|
|
2014-12-14 06:06:14 +08:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ss|b", &class_name, &alias_name, &alias_name_len, &autoload) == FAILURE) {
|
2019-12-31 00:35:46 +08:00
|
|
|
RETURN_THROWS();
|
2008-05-12 15:11:55 +08:00
|
|
|
}
|
|
|
|
|
2019-05-24 20:41:38 +08:00
|
|
|
ce = zend_lookup_class_ex(class_name, NULL, !autoload ? ZEND_FETCH_CLASS_NO_AUTOLOAD : 0);
|
2015-01-03 17:22:58 +08:00
|
|
|
|
2014-02-10 14:04:30 +08:00
|
|
|
if (ce) {
|
2015-01-03 17:22:58 +08:00
|
|
|
if (ce->type == ZEND_USER_CLASS) {
|
2017-10-27 19:44:21 +08:00
|
|
|
if (zend_register_class_alias_ex(alias_name, alias_name_len, ce, 0) == SUCCESS) {
|
2008-05-12 15:11:55 +08:00
|
|
|
RETURN_TRUE;
|
|
|
|
} else {
|
2015-03-26 08:44:23 +08:00
|
|
|
zend_error(E_WARNING, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), alias_name);
|
2008-05-12 15:11:55 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
2020-07-12 18:40:37 +08:00
|
|
|
zend_argument_value_error(1, "must be a user-defined class name, internal class name given");
|
|
|
|
RETURN_THROWS();
|
2008-05-12 15:11:55 +08:00
|
|
|
}
|
|
|
|
} else {
|
2020-05-26 20:10:57 +08:00
|
|
|
zend_error(E_WARNING, "Class \"%s\" not found", ZSTR_VAL(class_name));
|
2008-05-12 15:11:55 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Returns an array with the file names that were include_once()'d */
|
2000-03-11 00:36:30 +08:00
|
|
|
ZEND_FUNCTION(get_included_files)
|
1999-12-04 22:26:26 +08:00
|
|
|
{
|
2014-02-10 14:04:30 +08:00
|
|
|
zend_string *entry;
|
2011-09-13 21:29:35 +08:00
|
|
|
|
2020-01-03 19:11:45 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2000-05-02 00:22:00 +08:00
|
|
|
|
1999-12-04 22:26:26 +08:00
|
|
|
array_init(return_value);
|
2014-04-22 21:46:34 +08:00
|
|
|
ZEND_HASH_FOREACH_STR_KEY(&EG(included_files), entry) {
|
2014-04-18 23:18:11 +08:00
|
|
|
if (entry) {
|
2014-08-26 01:24:55 +08:00
|
|
|
add_next_index_str(return_value, zend_string_copy(entry));
|
2014-04-18 23:18:11 +08:00
|
|
|
}
|
|
|
|
} ZEND_HASH_FOREACH_END();
|
2001-04-30 21:05:11 +08:00
|
|
|
}
|
2000-04-19 21:15:13 +08:00
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Generates a user-level error/warning/notice message */
|
2000-06-02 20:36:54 +08:00
|
|
|
ZEND_FUNCTION(trigger_error)
|
2000-04-19 21:15:13 +08:00
|
|
|
{
|
2014-08-26 01:24:55 +08:00
|
|
|
zend_long error_type = E_USER_NOTICE;
|
2008-06-19 07:38:37 +08:00
|
|
|
char *message;
|
2014-08-27 21:31:48 +08:00
|
|
|
size_t message_len;
|
2000-04-19 21:15:13 +08:00
|
|
|
|
2014-12-14 06:06:14 +08:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &message, &message_len, &error_type) == FAILURE) {
|
2019-12-31 00:35:46 +08:00
|
|
|
RETURN_THROWS();
|
2008-06-19 07:38:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (error_type) {
|
|
|
|
case E_USER_ERROR:
|
|
|
|
case E_USER_WARNING:
|
|
|
|
case E_USER_NOTICE:
|
2008-07-21 17:41:00 +08:00
|
|
|
case E_USER_DEPRECATED:
|
2000-04-19 21:15:13 +08:00
|
|
|
break;
|
2000-09-05 20:08:41 +08:00
|
|
|
default:
|
2020-03-30 06:40:18 +08:00
|
|
|
zend_argument_value_error(2, "must be one of E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE,"
|
|
|
|
" or E_USER_DEPRECATED");
|
|
|
|
RETURN_THROWS();
|
2008-06-19 07:38:37 +08:00
|
|
|
break;
|
2000-04-19 21:15:13 +08:00
|
|
|
}
|
2008-06-19 07:38:37 +08:00
|
|
|
|
2008-07-01 15:23:00 +08:00
|
|
|
zend_error((int)error_type, "%s", message);
|
2020-03-30 06:40:18 +08:00
|
|
|
// TODO Change to void
|
2000-04-19 21:15:13 +08:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
2000-04-19 23:08:06 +08:00
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Sets a user-defined error handler function. Returns the previously defined error handler, or false on error */
|
2000-06-02 20:36:54 +08:00
|
|
|
ZEND_FUNCTION(set_error_handler)
|
2000-04-19 23:08:06 +08:00
|
|
|
{
|
2020-07-09 00:36:46 +08:00
|
|
|
zend_fcall_info fci;
|
|
|
|
zend_fcall_info_cache fcc;
|
2014-08-26 01:24:55 +08:00
|
|
|
zend_long error_type = E_ALL;
|
2006-05-10 07:53:23 +08:00
|
|
|
|
2020-07-09 00:36:46 +08:00
|
|
|
/* callable argument corresponds to the error handler */
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "f!|l", &fci, &fcc, &error_type) == FAILURE) {
|
2019-12-31 00:35:46 +08:00
|
|
|
RETURN_THROWS();
|
2000-04-19 23:08:06 +08:00
|
|
|
}
|
|
|
|
|
2014-02-10 14:04:30 +08:00
|
|
|
if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
|
2015-06-12 17:33:23 +08:00
|
|
|
ZVAL_COPY(return_value, &EG(user_error_handler));
|
2012-09-23 03:41:51 +08:00
|
|
|
}
|
2012-03-24 19:26:02 +08:00
|
|
|
|
2020-02-25 04:32:02 +08:00
|
|
|
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));
|
|
|
|
|
2020-07-09 00:36:46 +08:00
|
|
|
if (!ZEND_FCI_INITIALIZED(fci)) { /* unset user-defined handler */
|
2014-02-10 14:04:30 +08:00
|
|
|
ZVAL_UNDEF(&EG(user_error_handler));
|
2012-03-24 20:10:51 +08:00
|
|
|
return;
|
2012-03-24 19:26:02 +08:00
|
|
|
}
|
2012-09-23 03:41:51 +08:00
|
|
|
|
2020-07-09 00:36:46 +08:00
|
|
|
ZVAL_COPY(&EG(user_error_handler), &(fci.function_name));
|
2012-09-23 03:41:51 +08:00
|
|
|
EG(user_error_handler_error_reporting) = (int)error_type;
|
2000-04-19 23:08:06 +08:00
|
|
|
}
|
2000-06-02 20:36:54 +08:00
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Restores the previously defined error handler function */
|
2000-06-18 02:04:58 +08:00
|
|
|
ZEND_FUNCTION(restore_error_handler)
|
|
|
|
{
|
2020-01-03 19:11:45 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2015-03-30 23:57:32 +08:00
|
|
|
|
2014-02-10 14:04:30 +08:00
|
|
|
if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
|
|
|
|
zval zeh;
|
2015-01-03 17:22:58 +08:00
|
|
|
|
2014-02-10 14:04:30 +08:00
|
|
|
ZVAL_COPY_VALUE(&zeh, &EG(user_error_handler));
|
|
|
|
ZVAL_UNDEF(&EG(user_error_handler));
|
2004-05-24 04:27:32 +08:00
|
|
|
zval_ptr_dtor(&zeh);
|
2000-06-18 02:04:58 +08:00
|
|
|
}
|
2004-05-24 04:27:32 +08:00
|
|
|
|
2014-02-10 14:04:30 +08:00
|
|
|
if (zend_stack_is_empty(&EG(user_error_handlers))) {
|
|
|
|
ZVAL_UNDEF(&EG(user_error_handler));
|
2000-06-18 02:04:58 +08:00
|
|
|
} else {
|
2014-02-10 14:04:30 +08:00
|
|
|
zval *tmp;
|
2004-01-10 19:43:42 +08:00
|
|
|
EG(user_error_handler_error_reporting) = zend_stack_int_top(&EG(user_error_handlers_error_reporting));
|
|
|
|
zend_stack_del_top(&EG(user_error_handlers_error_reporting));
|
2014-05-01 02:48:02 +08:00
|
|
|
tmp = zend_stack_top(&EG(user_error_handlers));
|
2014-02-10 14:04:30 +08:00
|
|
|
ZVAL_COPY_VALUE(&EG(user_error_handler), tmp);
|
|
|
|
zend_stack_del_top(&EG(user_error_handlers));
|
2000-06-18 02:04:58 +08:00
|
|
|
}
|
2020-03-30 06:40:18 +08:00
|
|
|
|
|
|
|
// TODO Change to void
|
2000-06-18 02:04:58 +08:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
2002-07-05 10:34:54 +08:00
|
|
|
/* }}} */
|
2000-06-18 02:04:58 +08:00
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Sets a user-defined exception handler function. Returns the previously defined exception handler, or false on error */
|
2002-08-16 08:41:37 +08:00
|
|
|
ZEND_FUNCTION(set_exception_handler)
|
|
|
|
{
|
2020-07-09 00:36:46 +08:00
|
|
|
zend_fcall_info fci;
|
|
|
|
zend_fcall_info_cache fcc;
|
2002-08-16 08:41:37 +08:00
|
|
|
|
2020-07-09 00:36:46 +08:00
|
|
|
/* callable argument corresponds to the exception handler */
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "f!", &fci, &fcc) == FAILURE) {
|
2019-12-31 00:35:46 +08:00
|
|
|
RETURN_THROWS();
|
2002-08-16 08:41:37 +08:00
|
|
|
}
|
|
|
|
|
2014-02-10 14:04:30 +08:00
|
|
|
if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
|
2015-06-12 17:33:23 +08:00
|
|
|
ZVAL_COPY(return_value, &EG(user_exception_handler));
|
2012-09-23 03:41:51 +08:00
|
|
|
}
|
2002-08-16 08:41:37 +08:00
|
|
|
|
2020-02-25 04:32:02 +08:00
|
|
|
zend_stack_push(&EG(user_exception_handlers), &EG(user_exception_handler));
|
|
|
|
|
2020-07-09 00:36:46 +08:00
|
|
|
if (!ZEND_FCI_INITIALIZED(fci)) { /* unset user-defined handler */
|
2014-02-10 14:04:30 +08:00
|
|
|
ZVAL_UNDEF(&EG(user_exception_handler));
|
2012-03-24 20:10:51 +08:00
|
|
|
return;
|
2002-08-16 08:41:37 +08:00
|
|
|
}
|
2012-09-23 03:41:51 +08:00
|
|
|
|
2020-07-09 00:36:46 +08:00
|
|
|
ZVAL_COPY(&EG(user_exception_handler), &(fci.function_name));
|
2002-08-16 08:41:37 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Restores the previously defined exception handler function */
|
2002-08-16 08:41:37 +08:00
|
|
|
ZEND_FUNCTION(restore_exception_handler)
|
|
|
|
{
|
2020-01-03 19:11:45 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2015-03-30 23:57:32 +08:00
|
|
|
|
2014-02-10 14:04:30 +08:00
|
|
|
if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
|
2002-08-16 08:41:37 +08:00
|
|
|
zval_ptr_dtor(&EG(user_exception_handler));
|
|
|
|
}
|
2014-02-10 14:04:30 +08:00
|
|
|
if (zend_stack_is_empty(&EG(user_exception_handlers))) {
|
|
|
|
ZVAL_UNDEF(&EG(user_exception_handler));
|
2002-08-16 08:41:37 +08:00
|
|
|
} else {
|
2014-05-01 02:48:02 +08:00
|
|
|
zval *tmp = zend_stack_top(&EG(user_exception_handlers));
|
2014-02-10 14:04:30 +08:00
|
|
|
ZVAL_COPY_VALUE(&EG(user_exception_handler), tmp);
|
|
|
|
zend_stack_del_top(&EG(user_exception_handlers));
|
2002-08-16 08:41:37 +08:00
|
|
|
}
|
2020-03-30 06:40:18 +08:00
|
|
|
|
|
|
|
// TODO Change to void
|
2002-08-16 08:41:37 +08:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2018-12-19 07:49:56 +08:00
|
|
|
static void copy_class_or_interface_name(zval *array, zend_string *key, zend_class_entry *ce) /* {{{ */
|
2000-05-02 00:22:00 +08:00
|
|
|
{
|
2018-12-19 07:49:56 +08:00
|
|
|
if ((ce->refcount == 1 && !(ce->ce_flags & ZEND_ACC_IMMUTABLE)) ||
|
2019-03-18 22:17:29 +08:00
|
|
|
same_name(key, ce->name)) {
|
2018-12-19 07:49:56 +08:00
|
|
|
key = ce->name;
|
2000-06-09 23:40:37 +08:00
|
|
|
}
|
2018-12-19 07:49:56 +08:00
|
|
|
add_next_index_str(array, zend_string_copy(key));
|
2000-05-02 00:22:00 +08:00
|
|
|
}
|
2014-09-20 15:16:09 +08:00
|
|
|
/* }}} */
|
2000-05-02 00:22:00 +08:00
|
|
|
|
2019-03-18 22:17:29 +08:00
|
|
|
static inline void get_declared_class_impl(INTERNAL_FUNCTION_PARAMETERS, int flags, int skip_flags) /* {{{ */
|
2010-05-06 23:18:20 +08:00
|
|
|
{
|
2018-12-19 07:49:56 +08:00
|
|
|
zend_string *key;
|
|
|
|
zend_class_entry *ce;
|
2010-05-06 23:18:20 +08:00
|
|
|
|
2020-01-03 19:11:45 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2010-05-06 23:18:20 +08:00
|
|
|
|
|
|
|
array_init(return_value);
|
2018-12-19 07:49:56 +08:00
|
|
|
ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) {
|
|
|
|
if (key
|
|
|
|
&& ZSTR_VAL(key)[0] != 0
|
2019-03-18 22:17:29 +08:00
|
|
|
&& (ce->ce_flags & flags)
|
|
|
|
&& !(ce->ce_flags & skip_flags)) {
|
2018-12-19 07:49:56 +08:00
|
|
|
copy_class_or_interface_name(return_value, key, ce);
|
|
|
|
}
|
|
|
|
} ZEND_HASH_FOREACH_END();
|
2010-05-06 23:18:20 +08:00
|
|
|
}
|
2019-03-18 22:17:29 +08:00
|
|
|
/* {{{ */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Returns an array of all declared traits. */
|
2019-03-18 22:17:29 +08:00
|
|
|
ZEND_FUNCTION(get_declared_traits)
|
|
|
|
{
|
|
|
|
get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_TRAIT, 0);
|
|
|
|
}
|
2010-05-06 23:18:20 +08:00
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Returns an array of all declared classes. */
|
2000-05-02 00:22:00 +08:00
|
|
|
ZEND_FUNCTION(get_declared_classes)
|
|
|
|
{
|
2019-03-18 22:17:29 +08:00
|
|
|
get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED, ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT);
|
2003-12-08 02:54:31 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Returns an array of all declared interfaces. */
|
2003-12-08 02:54:31 +08:00
|
|
|
ZEND_FUNCTION(get_declared_interfaces)
|
|
|
|
{
|
2019-03-18 22:17:29 +08:00
|
|
|
get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_INTERFACE, 0);
|
2000-10-14 23:52:24 +08:00
|
|
|
}
|
2014-09-20 15:16:09 +08:00
|
|
|
/* }}} */
|
2001-12-05 01:58:32 +08:00
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Returns an array of all defined functions */
|
2000-10-14 23:52:24 +08:00
|
|
|
ZEND_FUNCTION(get_defined_functions)
|
|
|
|
{
|
2014-09-29 03:30:49 +08:00
|
|
|
zval internal, user;
|
2018-12-19 07:49:56 +08:00
|
|
|
zend_string *key;
|
|
|
|
zend_function *func;
|
Completely remove disabled functions from function table
Currently, disabling a function only replaces the internal
function handler with one that throws a warning, and a few
places in the engine special-case such functions, such as
function_exists. This leaves us with a Schrödinger's function,
which both does not exist (function_exists returns false) and
does exist (you cannot define a function with the same name).
In particular, this prevents the implementation of robust
polyfills, as reported in https://bugs.php.net/bug.php?id=79382:
if (!function_exists('getallheaders')) {
function getallheaders(...) { ... }
}
If getallheaders() is a disabled function, this code will break.
This patch changes disable_functions to remove the functions from
the function table completely. For all intents and purposes, it
will look like the function does not exist.
This also renders two bits of PHP functionality obsolete and thus
deprecated:
* ReflectionFunction::isDisabled(), as it will no longer be
possible to construct the ReflectionFunction of a disabled
function in the first place.
* get_defined_functions() with $exclude_disabled=false, as
get_defined_functions() now never returns disabled functions.
Fixed bug #79382.
Closes GH-5473.
2020-04-27 19:17:37 +08:00
|
|
|
zend_bool exclude_disabled = 1;
|
2006-05-10 07:53:23 +08:00
|
|
|
|
2015-06-03 08:42:18 +08:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &exclude_disabled) == FAILURE) {
|
2019-12-31 00:35:46 +08:00
|
|
|
RETURN_THROWS();
|
2000-10-14 23:52:24 +08:00
|
|
|
}
|
2006-05-10 07:53:23 +08:00
|
|
|
|
Completely remove disabled functions from function table
Currently, disabling a function only replaces the internal
function handler with one that throws a warning, and a few
places in the engine special-case such functions, such as
function_exists. This leaves us with a Schrödinger's function,
which both does not exist (function_exists returns false) and
does exist (you cannot define a function with the same name).
In particular, this prevents the implementation of robust
polyfills, as reported in https://bugs.php.net/bug.php?id=79382:
if (!function_exists('getallheaders')) {
function getallheaders(...) { ... }
}
If getallheaders() is a disabled function, this code will break.
This patch changes disable_functions to remove the functions from
the function table completely. For all intents and purposes, it
will look like the function does not exist.
This also renders two bits of PHP functionality obsolete and thus
deprecated:
* ReflectionFunction::isDisabled(), as it will no longer be
possible to construct the ReflectionFunction of a disabled
function in the first place.
* get_defined_functions() with $exclude_disabled=false, as
get_defined_functions() now never returns disabled functions.
Fixed bug #79382.
Closes GH-5473.
2020-04-27 19:17:37 +08:00
|
|
|
if (exclude_disabled == 0) {
|
|
|
|
zend_error(E_DEPRECATED,
|
|
|
|
"get_defined_functions(): Setting $exclude_disabled to false has no effect");
|
|
|
|
}
|
|
|
|
|
2014-02-10 14:04:30 +08:00
|
|
|
array_init(&internal);
|
|
|
|
array_init(&user);
|
2000-10-14 23:52:24 +08:00
|
|
|
array_init(return_value);
|
2006-05-10 07:53:23 +08:00
|
|
|
|
2018-12-19 07:49:56 +08:00
|
|
|
ZEND_HASH_FOREACH_STR_KEY_PTR(EG(function_table), key, func) {
|
|
|
|
if (key && ZSTR_VAL(key)[0] != 0) {
|
|
|
|
if (func->type == ZEND_INTERNAL_FUNCTION) {
|
Completely remove disabled functions from function table
Currently, disabling a function only replaces the internal
function handler with one that throws a warning, and a few
places in the engine special-case such functions, such as
function_exists. This leaves us with a Schrödinger's function,
which both does not exist (function_exists returns false) and
does exist (you cannot define a function with the same name).
In particular, this prevents the implementation of robust
polyfills, as reported in https://bugs.php.net/bug.php?id=79382:
if (!function_exists('getallheaders')) {
function getallheaders(...) { ... }
}
If getallheaders() is a disabled function, this code will break.
This patch changes disable_functions to remove the functions from
the function table completely. For all intents and purposes, it
will look like the function does not exist.
This also renders two bits of PHP functionality obsolete and thus
deprecated:
* ReflectionFunction::isDisabled(), as it will no longer be
possible to construct the ReflectionFunction of a disabled
function in the first place.
* get_defined_functions() with $exclude_disabled=false, as
get_defined_functions() now never returns disabled functions.
Fixed bug #79382.
Closes GH-5473.
2020-04-27 19:17:37 +08:00
|
|
|
add_next_index_str(&internal, zend_string_copy(key));
|
2018-12-19 07:49:56 +08:00
|
|
|
} else if (func->type == ZEND_USER_FUNCTION) {
|
|
|
|
add_next_index_str(&user, zend_string_copy(key));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} ZEND_HASH_FOREACH_END();
|
2006-05-10 07:53:23 +08:00
|
|
|
|
2014-09-24 17:26:09 +08:00
|
|
|
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);
|
2000-10-14 23:52:24 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Returns an associative array of names and values of all currently defined variable names (variables in the current scope) */
|
2000-10-14 23:52:24 +08:00
|
|
|
ZEND_FUNCTION(get_defined_vars)
|
2006-05-10 07:53:23 +08:00
|
|
|
{
|
2016-04-25 05:49:52 +08:00
|
|
|
zend_array *symbol_table;
|
2019-10-31 17:20:41 +08:00
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
|
2016-04-25 05:49:52 +08:00
|
|
|
if (zend_forbid_dynamic_call("get_defined_vars()") == FAILURE) {
|
|
|
|
return;
|
|
|
|
}
|
2008-04-29 16:15:20 +08:00
|
|
|
|
2016-04-25 05:49:52 +08:00
|
|
|
symbol_table = zend_rebuild_symbol_table();
|
2015-12-26 12:31:37 +08:00
|
|
|
if (UNEXPECTED(symbol_table == NULL)) {
|
2019-12-20 18:10:20 +08:00
|
|
|
RETURN_EMPTY_ARRAY();
|
2015-12-26 12:31:37 +08:00
|
|
|
}
|
|
|
|
|
2015-04-08 14:30:47 +08:00
|
|
|
RETURN_ARR(zend_array_dup(symbol_table));
|
2000-10-14 23:52:24 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
2000-06-03 09:49:49 +08:00
|
|
|
|
2017-03-11 07:33:32 +08:00
|
|
|
#if ZEND_DEBUG && defined(ZTS)
|
2002-09-18 22:08:07 +08:00
|
|
|
ZEND_FUNCTION(zend_thread_id)
|
|
|
|
{
|
2019-10-31 17:20:41 +08:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
|
2014-08-26 01:24:55 +08:00
|
|
|
RETURN_LONG((zend_long)tsrm_thread_id());
|
2002-09-18 22:08:07 +08:00
|
|
|
}
|
2000-08-26 22:45:29 +08:00
|
|
|
#endif
|
2000-07-15 04:00:24 +08:00
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Get the resource type name for a given resource */
|
2000-07-15 04:00:24 +08:00
|
|
|
ZEND_FUNCTION(get_resource_type)
|
|
|
|
{
|
2011-09-13 21:29:35 +08:00
|
|
|
const char *resource_type;
|
2008-06-19 07:38:37 +08:00
|
|
|
zval *z_resource_type;
|
2000-07-15 04:00:24 +08:00
|
|
|
|
2014-12-14 06:06:14 +08:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &z_resource_type) == FAILURE) {
|
2019-12-31 00:35:46 +08:00
|
|
|
RETURN_THROWS();
|
2000-07-15 04:00:24 +08:00
|
|
|
}
|
|
|
|
|
2014-12-14 06:06:14 +08:00
|
|
|
resource_type = zend_rsrc_list_get_rsrc_type(Z_RES_P(z_resource_type));
|
2000-07-15 04:00:24 +08:00
|
|
|
if (resource_type) {
|
2014-02-10 14:04:30 +08:00
|
|
|
RETURN_STRING(resource_type);
|
2000-07-15 04:00:24 +08:00
|
|
|
} else {
|
2014-02-10 14:04:30 +08:00
|
|
|
RETURN_STRING("Unknown");
|
2000-07-15 04:00:24 +08:00
|
|
|
}
|
|
|
|
}
|
2002-03-02 21:48:13 +08:00
|
|
|
/* }}} */
|
2020-04-21 18:31:17 +08:00
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Get the resource ID for a given resource */
|
2020-04-21 18:31:17 +08:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
/* }}} */
|
2001-05-21 23:47:52 +08:00
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Get an array with all active resources */
|
2014-08-20 22:29:44 +08:00
|
|
|
ZEND_FUNCTION(get_resources)
|
|
|
|
{
|
|
|
|
zend_string *type = NULL;
|
|
|
|
zend_string *key;
|
2014-08-26 01:24:55 +08:00
|
|
|
zend_ulong index;
|
2014-08-20 22:29:44 +08:00
|
|
|
zval *val;
|
|
|
|
|
2020-07-12 18:40:37 +08:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!", &type) == FAILURE) {
|
2019-12-31 00:35:46 +08:00
|
|
|
RETURN_THROWS();
|
2014-08-20 22:29:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!type) {
|
|
|
|
array_init(return_value);
|
|
|
|
ZEND_HASH_FOREACH_KEY_VAL(&EG(regular_list), index, key, val) {
|
|
|
|
if (!key) {
|
|
|
|
Z_ADDREF_P(val);
|
|
|
|
zend_hash_index_add_new(Z_ARRVAL_P(return_value), index, val);
|
|
|
|
}
|
|
|
|
} ZEND_HASH_FOREACH_END();
|
2014-08-26 04:40:58 +08:00
|
|
|
} else if (zend_string_equals_literal(type, "Unknown")) {
|
2014-08-20 22:29:44 +08:00
|
|
|
array_init(return_value);
|
|
|
|
ZEND_HASH_FOREACH_KEY_VAL(&EG(regular_list), index, key, val) {
|
|
|
|
if (!key && Z_RES_TYPE_P(val) <= 0) {
|
|
|
|
Z_ADDREF_P(val);
|
|
|
|
zend_hash_index_add_new(Z_ARRVAL_P(return_value), index, val);
|
|
|
|
}
|
|
|
|
} ZEND_HASH_FOREACH_END();
|
|
|
|
} else {
|
2015-06-30 18:59:27 +08:00
|
|
|
int id = zend_fetch_list_dtor_id(ZSTR_VAL(type));
|
2014-08-20 22:29:44 +08:00
|
|
|
|
|
|
|
if (id <= 0) {
|
2020-07-12 18:40:37 +08:00
|
|
|
zend_argument_value_error(1, "must be a valid resource type");
|
|
|
|
RETURN_THROWS();
|
2014-08-20 22:29:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
array_init(return_value);
|
|
|
|
ZEND_HASH_FOREACH_KEY_VAL(&EG(regular_list), index, key, val) {
|
|
|
|
if (!key && Z_RES_TYPE_P(val) == id) {
|
|
|
|
Z_ADDREF_P(val);
|
|
|
|
zend_hash_index_add_new(Z_ARRVAL_P(return_value), index, val);
|
|
|
|
}
|
|
|
|
} ZEND_HASH_FOREACH_END();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
2001-05-21 23:47:52 +08:00
|
|
|
|
2020-04-15 16:59:58 +08:00
|
|
|
static void add_zendext_info(zend_extension *ext, void *arg) /* {{{ */
|
2007-08-01 06:47:25 +08:00
|
|
|
{
|
|
|
|
zval *name_array = (zval *)arg;
|
2014-04-15 19:40:40 +08:00
|
|
|
add_next_index_string(name_array, ext->name);
|
2007-08-01 06:47:25 +08:00
|
|
|
}
|
2014-09-20 15:16:09 +08:00
|
|
|
/* }}} */
|
2007-08-01 06:47:25 +08:00
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Return an array containing names of loaded extensions */
|
2001-05-21 23:47:52 +08:00
|
|
|
ZEND_FUNCTION(get_loaded_extensions)
|
|
|
|
{
|
2007-08-03 04:32:44 +08:00
|
|
|
zend_bool zendext = 0;
|
2007-08-01 06:47:25 +08:00
|
|
|
|
2014-12-14 06:06:14 +08:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &zendext) == FAILURE) {
|
2019-12-31 00:35:46 +08:00
|
|
|
RETURN_THROWS();
|
2001-05-21 23:47:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
array_init(return_value);
|
2007-08-01 06:47:25 +08:00
|
|
|
|
2007-08-03 00:54:44 +08:00
|
|
|
if (zendext) {
|
2020-04-15 16:59:58 +08:00
|
|
|
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) add_zendext_info, return_value);
|
2007-08-01 06:47:25 +08:00
|
|
|
} else {
|
2018-12-19 07:49:56 +08:00
|
|
|
zend_module_entry *module;
|
|
|
|
|
|
|
|
ZEND_HASH_FOREACH_PTR(&module_registry, module) {
|
|
|
|
add_next_index_string(return_value, module->name);
|
|
|
|
} ZEND_HASH_FOREACH_END();
|
2007-08-01 06:47:25 +08:00
|
|
|
}
|
2001-05-21 23:47:52 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Return an array containing the names and values of all defined constants */
|
2001-05-21 23:47:52 +08:00
|
|
|
ZEND_FUNCTION(get_defined_constants)
|
|
|
|
{
|
2009-05-07 20:08:09 +08:00
|
|
|
zend_bool categorize = 0;
|
2015-01-03 17:22:58 +08:00
|
|
|
|
2014-12-14 06:06:14 +08:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &categorize) == FAILURE) {
|
2019-12-31 00:35:46 +08:00
|
|
|
RETURN_THROWS();
|
2001-05-21 23:47:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
array_init(return_value);
|
2003-02-07 11:04:26 +08:00
|
|
|
|
2009-05-07 20:08:09 +08:00
|
|
|
if (categorize) {
|
2003-02-07 11:04:26 +08:00
|
|
|
zend_constant *val;
|
2003-08-22 10:08:10 +08:00
|
|
|
int module_number;
|
2014-06-03 06:43:31 +08:00
|
|
|
zval *modules, const_val;
|
2008-01-25 02:07:45 +08:00
|
|
|
char **module_names;
|
2003-02-07 11:04:26 +08:00
|
|
|
zend_module_entry *module;
|
|
|
|
int i = 1;
|
2003-08-22 10:08:10 +08:00
|
|
|
|
2014-02-10 14:04:30 +08:00
|
|
|
modules = ecalloc(zend_hash_num_elements(&module_registry) + 2, sizeof(zval));
|
2003-08-22 10:08:10 +08:00
|
|
|
module_names = emalloc((zend_hash_num_elements(&module_registry) + 2) * sizeof(char *));
|
2006-05-10 07:53:23 +08:00
|
|
|
|
2003-08-22 10:08:10 +08:00
|
|
|
module_names[0] = "internal";
|
2014-04-18 23:18:11 +08:00
|
|
|
ZEND_HASH_FOREACH_PTR(&module_registry, module) {
|
2009-03-04 07:42:51 +08:00
|
|
|
module_names[module->module_number] = (char *)module->name;
|
|
|
|
i++;
|
2014-04-18 23:18:11 +08:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
2003-08-22 10:08:10 +08:00
|
|
|
module_names[i] = "user";
|
2003-02-07 11:04:26 +08:00
|
|
|
|
2014-04-18 23:18:11 +08:00
|
|
|
ZEND_HASH_FOREACH_PTR(EG(zend_constants), val) {
|
2013-07-20 18:05:13 +08:00
|
|
|
if (!val->name) {
|
|
|
|
/* skip special constants */
|
2014-04-18 23:18:11 +08:00
|
|
|
continue;
|
2013-07-20 18:05:13 +08:00
|
|
|
}
|
|
|
|
|
2018-07-26 17:58:07 +08:00
|
|
|
if (ZEND_CONSTANT_MODULE_NUMBER(val) == PHP_USER_CONSTANT) {
|
2003-08-22 10:08:10 +08:00
|
|
|
module_number = i;
|
2018-07-26 17:58:07 +08:00
|
|
|
} else if (ZEND_CONSTANT_MODULE_NUMBER(val) > i) {
|
2003-08-22 10:08:10 +08:00
|
|
|
/* should not happen */
|
2014-04-18 23:18:11 +08:00
|
|
|
continue;
|
2003-08-22 10:08:10 +08:00
|
|
|
} else {
|
2018-07-26 17:58:07 +08:00
|
|
|
module_number = ZEND_CONSTANT_MODULE_NUMBER(val);
|
2003-08-22 10:08:10 +08:00
|
|
|
}
|
2003-02-07 11:04:26 +08:00
|
|
|
|
2014-02-10 14:04:30 +08:00
|
|
|
if (Z_TYPE(modules[module_number]) == IS_UNDEF) {
|
|
|
|
array_init(&modules[module_number]);
|
|
|
|
add_assoc_zval(return_value, module_names[module_number], &modules[module_number]);
|
2003-08-22 10:08:10 +08:00
|
|
|
}
|
2003-02-07 11:04:26 +08:00
|
|
|
|
2017-10-31 04:13:10 +08:00
|
|
|
ZVAL_COPY_OR_DUP(&const_val, &val->value);
|
2014-06-03 06:43:31 +08:00
|
|
|
zend_hash_add_new(Z_ARRVAL(modules[module_number]), val->name, &const_val);
|
2014-04-18 23:18:11 +08:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
|
|
|
|
2003-02-07 11:04:26 +08:00
|
|
|
efree(module_names);
|
2003-08-22 10:08:10 +08:00
|
|
|
efree(modules);
|
2003-02-07 11:04:26 +08:00
|
|
|
} else {
|
2018-12-19 07:49:56 +08:00
|
|
|
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();
|
2003-02-07 11:04:26 +08:00
|
|
|
}
|
2001-05-21 23:47:52 +08:00
|
|
|
}
|
2002-07-05 10:34:54 +08:00
|
|
|
/* }}} */
|
2001-05-21 23:47:52 +08:00
|
|
|
|
2014-12-14 06:06:14 +08:00
|
|
|
static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) /* {{{ */
|
2004-02-26 05:06:59 +08:00
|
|
|
{
|
2014-11-28 15:28:49 +08:00
|
|
|
uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
|
2002-08-23 22:22:25 +08:00
|
|
|
|
2014-06-27 03:51:14 +08:00
|
|
|
if (num_args) {
|
2014-09-15 18:08:42 +08:00
|
|
|
uint32_t i = 0;
|
2014-06-27 03:51:14 +08:00
|
|
|
zval *p = ZEND_CALL_ARG(call, 1);
|
2014-06-24 06:17:16 +08:00
|
|
|
|
2017-10-24 22:27:31 +08:00
|
|
|
array_init_size(arg_array, num_args);
|
2018-03-23 05:13:45 +08:00
|
|
|
zend_hash_real_init_packed(Z_ARRVAL_P(arg_array));
|
2014-12-24 00:08:28 +08:00
|
|
|
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(arg_array)) {
|
|
|
|
if (call->func->type == ZEND_USER_FUNCTION) {
|
2016-09-26 19:14:57 +08:00
|
|
|
uint32_t first_extra_arg = MIN(num_args, call->func->op_array.num_args);
|
2015-01-03 17:22:58 +08:00
|
|
|
|
2016-09-26 21:16:07 +08:00
|
|
|
if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_SYMBOL_TABLE)) {
|
2016-09-26 19:14:57 +08:00
|
|
|
/* In case of attached symbol_table, values on stack may be invalid
|
|
|
|
* and we have to access them through symbol_table
|
|
|
|
* See: https://bugs.php.net/bug.php?id=73156
|
|
|
|
*/
|
|
|
|
while (i < first_extra_arg) {
|
2020-07-24 16:16:38 +08:00
|
|
|
zend_string *arg_name = call->func->op_array.vars[i];
|
|
|
|
zval *arg = zend_hash_find_ex_ind(call->symbol_table, arg_name, 1);
|
2016-09-26 19:14:57 +08:00
|
|
|
if (arg) {
|
2020-07-24 16:16:38 +08:00
|
|
|
ZVAL_DEREF(arg);
|
|
|
|
Z_TRY_ADDREF_P(arg);
|
2019-05-28 18:35:00 +08:00
|
|
|
ZEND_HASH_FILL_SET(arg);
|
2016-09-26 19:14:57 +08:00
|
|
|
} else {
|
2019-05-28 18:35:00 +08:00
|
|
|
ZEND_HASH_FILL_SET_NULL();
|
2016-09-26 19:14:57 +08:00
|
|
|
}
|
2019-05-28 18:35:00 +08:00
|
|
|
ZEND_HASH_FILL_NEXT();
|
2016-09-26 19:14:57 +08:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
} else {
|
2014-12-24 00:08:28 +08:00
|
|
|
while (i < first_extra_arg) {
|
2015-09-22 13:58:42 +08:00
|
|
|
if (EXPECTED(Z_TYPE_INFO_P(p) != IS_UNDEF)) {
|
2020-07-24 16:16:38 +08:00
|
|
|
zval *arg = p;
|
|
|
|
ZVAL_DEREF(arg);
|
|
|
|
Z_TRY_ADDREF_P(arg);
|
|
|
|
ZEND_HASH_FILL_SET(arg);
|
2017-06-25 21:08:36 +08:00
|
|
|
} else {
|
2019-05-28 18:35:00 +08:00
|
|
|
ZEND_HASH_FILL_SET_NULL();
|
2015-09-22 11:59:35 +08:00
|
|
|
}
|
2019-05-28 18:35:00 +08:00
|
|
|
ZEND_HASH_FILL_NEXT();
|
2014-12-24 00:08:28 +08:00
|
|
|
p++;
|
|
|
|
i++;
|
|
|
|
}
|
2014-06-30 18:17:17 +08:00
|
|
|
}
|
2016-09-26 19:14:57 +08:00
|
|
|
p = ZEND_CALL_VAR_NUM(call, call->func->op_array.last_var + call->func->op_array.T);
|
2014-06-24 06:17:16 +08:00
|
|
|
}
|
2014-06-27 03:51:14 +08:00
|
|
|
|
2014-12-24 00:08:28 +08:00
|
|
|
while (i < num_args) {
|
2015-09-22 13:58:42 +08:00
|
|
|
if (EXPECTED(Z_TYPE_INFO_P(p) != IS_UNDEF)) {
|
2020-07-24 16:16:38 +08:00
|
|
|
zval *arg = p;
|
|
|
|
ZVAL_DEREF(arg);
|
|
|
|
Z_TRY_ADDREF_P(arg);
|
|
|
|
ZEND_HASH_FILL_SET(arg);
|
2017-06-25 21:08:36 +08:00
|
|
|
} else {
|
2019-05-28 18:35:00 +08:00
|
|
|
ZEND_HASH_FILL_SET_NULL();
|
2015-09-22 11:59:35 +08:00
|
|
|
}
|
2019-05-28 18:35:00 +08:00
|
|
|
ZEND_HASH_FILL_NEXT();
|
2014-12-24 00:08:28 +08:00
|
|
|
p++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
} ZEND_HASH_FILL_END();
|
2017-06-25 21:08:36 +08:00
|
|
|
Z_ARRVAL_P(arg_array)->nNumOfElements = num_args;
|
2017-10-24 22:27:31 +08:00
|
|
|
} else {
|
|
|
|
ZVAL_EMPTY_ARRAY(arg_array);
|
2002-08-23 22:22:25 +08:00
|
|
|
}
|
2020-04-06 18:46:52 +08:00
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
2002-08-23 22:22:25 +08:00
|
|
|
}
|
2014-09-20 15:16:09 +08:00
|
|
|
/* }}} */
|
2002-08-23 22:22:25 +08:00
|
|
|
|
2014-12-14 06:06:14 +08:00
|
|
|
void debug_print_backtrace_args(zval *arg_array) /* {{{ */
|
2002-12-02 03:47:02 +08:00
|
|
|
{
|
2020-04-06 18:46:52 +08:00
|
|
|
zend_string *name;
|
2014-02-10 14:04:30 +08:00
|
|
|
zval *tmp;
|
2002-12-02 03:47:02 +08:00
|
|
|
int i = 0;
|
|
|
|
|
2020-04-06 18:46:52 +08:00
|
|
|
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(arg_array), name, tmp) {
|
2002-12-02 03:47:02 +08:00
|
|
|
if (i++) {
|
|
|
|
ZEND_PUTS(", ");
|
|
|
|
}
|
2020-04-06 18:46:52 +08:00
|
|
|
if (name) {
|
|
|
|
ZEND_PUTS(ZSTR_VAL(name));
|
|
|
|
ZEND_PUTS(": ");
|
|
|
|
}
|
2014-12-14 06:06:14 +08:00
|
|
|
zend_print_flat_zval_r(tmp);
|
2014-04-18 23:18:11 +08:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
2002-12-02 03:47:02 +08:00
|
|
|
}
|
2014-09-20 15:16:09 +08:00
|
|
|
/* }}} */
|
2002-12-02 03:47:02 +08:00
|
|
|
|
2019-03-18 22:17:29 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
/* {{{ */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ */
|
2002-12-02 03:47:02 +08:00
|
|
|
ZEND_FUNCTION(debug_print_backtrace)
|
|
|
|
{
|
2014-07-07 19:50:44 +08:00
|
|
|
zend_execute_data *call, *ptr, *skip;
|
2014-04-24 19:53:20 +08:00
|
|
|
zend_object *object;
|
2011-04-09 17:52:24 +08:00
|
|
|
int lineno, frameno = 0;
|
2014-06-24 06:17:16 +08:00
|
|
|
zend_function *func;
|
2011-09-13 21:29:35 +08:00
|
|
|
const char *function_name;
|
|
|
|
const char *filename;
|
2014-02-10 14:04:30 +08:00
|
|
|
zend_string *class_name = NULL;
|
2002-12-02 03:47:02 +08:00
|
|
|
char *call_type;
|
2011-09-13 21:29:35 +08:00
|
|
|
const char *include_filename = NULL;
|
2014-02-10 14:04:30 +08:00
|
|
|
zval arg_array;
|
2003-01-12 20:57:20 +08:00
|
|
|
int indent = 0;
|
2014-08-26 01:24:55 +08:00
|
|
|
zend_long options = 0;
|
|
|
|
zend_long limit = 0;
|
2002-12-02 03:47:02 +08:00
|
|
|
|
2014-12-14 06:06:14 +08:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &options, &limit) == FAILURE) {
|
2019-12-31 00:35:46 +08:00
|
|
|
RETURN_THROWS();
|
2002-12-02 03:47:02 +08:00
|
|
|
}
|
|
|
|
|
2014-02-10 14:04:30 +08:00
|
|
|
ZVAL_UNDEF(&arg_array);
|
2014-10-03 23:32:46 +08:00
|
|
|
ptr = EX(prev_execute_data);
|
2002-12-02 03:47:02 +08:00
|
|
|
|
|
|
|
/* skip debug_backtrace() */
|
2014-07-07 19:50:44 +08:00
|
|
|
call = ptr;
|
2002-12-02 03:47:02 +08:00
|
|
|
ptr = ptr->prev_execute_data;
|
2005-06-23 20:00:13 +08:00
|
|
|
|
2011-04-09 17:52:24 +08:00
|
|
|
while (ptr && (limit == 0 || frameno < limit)) {
|
|
|
|
frameno++;
|
2014-02-10 14:04:30 +08:00
|
|
|
class_name = NULL;
|
2015-01-03 17:22:58 +08:00
|
|
|
call_type = NULL;
|
2014-02-10 14:04:30 +08:00
|
|
|
ZVAL_UNDEF(&arg_array);
|
2005-06-22 23:26:05 +08:00
|
|
|
|
2015-03-07 07:28:12 +08:00
|
|
|
ptr = zend_generator_check_placeholder_frame(ptr);
|
|
|
|
|
2005-06-22 23:26:05 +08:00
|
|
|
skip = ptr;
|
2006-05-10 07:53:23 +08:00
|
|
|
/* skip internal handler */
|
2019-03-18 22:17:29 +08:00
|
|
|
if (skip_internal_handler(skip)) {
|
2008-01-24 17:41:39 +08:00
|
|
|
skip = skip->prev_execute_data;
|
2005-06-22 23:26:05 +08:00
|
|
|
}
|
|
|
|
|
2014-06-27 17:02:49 +08:00
|
|
|
if (skip->func && ZEND_USER_CODE(skip->func->common.type)) {
|
2015-06-30 18:59:27 +08:00
|
|
|
filename = ZSTR_VAL(skip->func->op_array.filename);
|
2014-07-03 02:01:25 +08:00
|
|
|
if (skip->opline->opcode == ZEND_HANDLE_EXCEPTION) {
|
|
|
|
if (EG(opline_before_exception)) {
|
|
|
|
lineno = EG(opline_before_exception)->lineno;
|
|
|
|
} else {
|
|
|
|
lineno = skip->func->op_array.line_end;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
lineno = skip->opline->lineno;
|
|
|
|
}
|
2002-12-02 03:47:02 +08:00
|
|
|
} else {
|
|
|
|
filename = NULL;
|
2003-08-29 00:41:20 +08:00
|
|
|
lineno = 0;
|
2002-12-02 03:47:02 +08:00
|
|
|
}
|
|
|
|
|
2014-04-24 19:53:20 +08:00
|
|
|
/* $this may be passed into regular internal functions */
|
2016-04-01 21:17:49 +08:00
|
|
|
object = (Z_TYPE(call->This) == IS_OBJECT) ? Z_OBJ(call->This) : NULL;
|
2014-04-24 19:53:20 +08:00
|
|
|
|
2014-07-07 19:50:44 +08:00
|
|
|
if (call->func) {
|
2017-01-23 13:33:58 +08:00
|
|
|
func = call->func;
|
2020-03-02 18:07:57 +08:00
|
|
|
if (func->common.function_name) {
|
|
|
|
function_name = ZSTR_VAL(func->common.function_name);
|
2019-03-18 22:17:29 +08:00
|
|
|
} else {
|
|
|
|
function_name = NULL;
|
|
|
|
}
|
2014-06-24 06:17:16 +08:00
|
|
|
} else {
|
2014-07-07 19:50:44 +08:00
|
|
|
func = NULL;
|
|
|
|
function_name = NULL;
|
2014-06-24 06:17:16 +08:00
|
|
|
}
|
2002-12-02 03:47:02 +08:00
|
|
|
|
|
|
|
if (function_name) {
|
2014-04-24 19:53:20 +08:00
|
|
|
if (object) {
|
2014-06-24 06:17:16 +08:00
|
|
|
if (func->common.scope) {
|
|
|
|
class_name = func->common.scope->name;
|
2018-05-31 16:57:22 +08:00
|
|
|
} else if (object->handlers->get_class_name == zend_std_get_class_name) {
|
2014-10-10 01:15:07 +08:00
|
|
|
class_name = object->ce->name;
|
2016-06-22 22:23:04 +08:00
|
|
|
} else {
|
|
|
|
class_name = object->handlers->get_class_name(object);
|
2005-04-05 01:23:38 +08:00
|
|
|
}
|
2005-06-28 02:13:13 +08:00
|
|
|
|
2002-12-02 03:47:02 +08:00
|
|
|
call_type = "->";
|
2014-06-24 06:17:16 +08:00
|
|
|
} else if (func->common.scope) {
|
|
|
|
class_name = func->common.scope->name;
|
2002-12-02 03:47:02 +08:00
|
|
|
call_type = "::";
|
|
|
|
} else {
|
|
|
|
class_name = NULL;
|
|
|
|
call_type = NULL;
|
|
|
|
}
|
2014-06-27 03:51:14 +08:00
|
|
|
if (func->type != ZEND_EVAL_CODE) {
|
2014-06-24 06:17:16 +08:00
|
|
|
if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) {
|
2014-12-14 06:06:14 +08:00
|
|
|
debug_backtrace_get_args(call, &arg_array);
|
2002-12-02 03:47:02 +08:00
|
|
|
}
|
2006-05-10 07:53:23 +08:00
|
|
|
}
|
2002-12-02 03:47:02 +08:00
|
|
|
} 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;
|
2020-09-23 23:06:28 +08:00
|
|
|
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;
|
|
|
|
}
|
2002-12-02 03:47:02 +08:00
|
|
|
|
2020-09-23 23:06:28 +08:00
|
|
|
switch (include_kind) {
|
2002-12-02 03:47:02 +08:00
|
|
|
case ZEND_EVAL:
|
|
|
|
function_name = "eval";
|
|
|
|
build_filename_arg = 0;
|
|
|
|
break;
|
|
|
|
case ZEND_INCLUDE:
|
|
|
|
function_name = "include";
|
|
|
|
break;
|
|
|
|
case ZEND_REQUIRE:
|
|
|
|
function_name = "require";
|
|
|
|
break;
|
|
|
|
case ZEND_INCLUDE_ONCE:
|
|
|
|
function_name = "include_once";
|
|
|
|
break;
|
|
|
|
case ZEND_REQUIRE_ONCE:
|
|
|
|
function_name = "require_once";
|
|
|
|
break;
|
|
|
|
default:
|
2020-09-23 23:06:28 +08:00
|
|
|
/* Skip dummy frame unless it is needed to preserve filename/lineno info. */
|
|
|
|
if (!filename) {
|
|
|
|
goto skip_frame;
|
|
|
|
}
|
|
|
|
|
2015-01-03 17:22:58 +08:00
|
|
|
function_name = "unknown";
|
2002-12-02 03:47:02 +08:00
|
|
|
build_filename_arg = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (build_filename_arg && include_filename) {
|
2014-02-10 14:04:30 +08:00
|
|
|
array_init(&arg_array);
|
2014-04-15 19:40:40 +08:00
|
|
|
add_next_index_string(&arg_array, (char*)include_filename);
|
2002-12-02 03:47:02 +08:00
|
|
|
}
|
2003-08-29 00:41:20 +08:00
|
|
|
call_type = NULL;
|
2002-12-02 03:47:02 +08:00
|
|
|
}
|
|
|
|
zend_printf("#%-2d ", indent);
|
|
|
|
if (class_name) {
|
2015-06-30 18:59:27 +08:00
|
|
|
ZEND_PUTS(ZSTR_VAL(class_name));
|
2002-12-02 03:47:02 +08:00
|
|
|
ZEND_PUTS(call_type);
|
2016-06-22 22:23:04 +08:00
|
|
|
if (object
|
|
|
|
&& !func->common.scope
|
2018-05-31 16:57:22 +08:00
|
|
|
&& object->handlers->get_class_name != zend_std_get_class_name) {
|
2018-05-28 21:27:12 +08:00
|
|
|
zend_string_release_ex(class_name, 0);
|
2016-06-22 22:23:04 +08:00
|
|
|
}
|
2002-12-02 03:47:02 +08:00
|
|
|
}
|
2011-08-07 14:19:43 +08:00
|
|
|
zend_printf("%s(", function_name);
|
2014-02-10 14:04:30 +08:00
|
|
|
if (Z_TYPE(arg_array) != IS_UNDEF) {
|
2014-12-14 06:06:14 +08:00
|
|
|
debug_print_backtrace_args(&arg_array);
|
2003-01-09 00:41:47 +08:00
|
|
|
zval_ptr_dtor(&arg_array);
|
|
|
|
}
|
2006-03-03 18:09:21 +08:00
|
|
|
if (filename) {
|
|
|
|
zend_printf(") called at [%s:%d]\n", filename, lineno);
|
|
|
|
} else {
|
2014-07-07 19:50:44 +08:00
|
|
|
zend_execute_data *prev_call = skip;
|
2006-07-27 16:20:38 +08:00
|
|
|
zend_execute_data *prev = skip->prev_execute_data;
|
|
|
|
|
|
|
|
while (prev) {
|
2014-07-07 19:50:44 +08:00
|
|
|
if (prev_call &&
|
2019-03-18 22:17:29 +08:00
|
|
|
prev_call->func &&
|
2014-07-07 19:50:44 +08:00
|
|
|
!ZEND_USER_CODE(prev_call->func->common.type)) {
|
2006-07-27 16:20:38 +08:00
|
|
|
prev = NULL;
|
|
|
|
break;
|
2015-01-03 17:22:58 +08:00
|
|
|
}
|
2014-06-27 17:02:49 +08:00
|
|
|
if (prev->func && ZEND_USER_CODE(prev->func->common.type)) {
|
2015-06-30 18:59:27 +08:00
|
|
|
zend_printf(") called at [%s:%d]\n", ZSTR_VAL(prev->func->op_array.filename), prev->opline->lineno);
|
2006-07-27 16:20:38 +08:00
|
|
|
break;
|
|
|
|
}
|
2014-07-07 19:50:44 +08:00
|
|
|
prev_call = prev;
|
2006-07-27 16:20:38 +08:00
|
|
|
prev = prev->prev_execute_data;
|
|
|
|
}
|
|
|
|
if (!prev) {
|
|
|
|
ZEND_PUTS(")\n");
|
|
|
|
}
|
2006-03-03 18:09:21 +08:00
|
|
|
}
|
2020-09-23 23:06:28 +08:00
|
|
|
++indent;
|
|
|
|
|
|
|
|
skip_frame:
|
2004-09-10 00:47:22 +08:00
|
|
|
include_filename = filename;
|
2014-07-07 19:50:44 +08:00
|
|
|
call = skip;
|
2005-06-22 23:26:05 +08:00
|
|
|
ptr = skip->prev_execute_data;
|
2002-12-02 03:47:02 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* }}} */
|
2003-08-29 04:35:54 +08:00
|
|
|
|
2014-12-14 06:06:14 +08:00
|
|
|
ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int options, int limit) /* {{{ */
|
2002-05-03 01:20:48 +08:00
|
|
|
{
|
2015-11-09 17:14:15 +08:00
|
|
|
zend_execute_data *ptr, *skip, *call = NULL;
|
2014-07-07 19:50:44 +08:00
|
|
|
zend_object *object;
|
2011-04-09 17:52:24 +08:00
|
|
|
int lineno, frameno = 0;
|
2014-06-24 06:17:16 +08:00
|
|
|
zend_function *func;
|
2015-08-14 22:16:27 +08:00
|
|
|
zend_string *function_name;
|
|
|
|
zend_string *filename;
|
|
|
|
zend_string *include_filename = NULL;
|
2016-05-12 18:47:22 +08:00
|
|
|
zval stack_frame, tmp;
|
2002-09-02 20:20:09 +08:00
|
|
|
|
2015-11-09 17:14:15 +08:00
|
|
|
array_init(return_value);
|
|
|
|
|
|
|
|
if (!(ptr = EG(current_execute_data))) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-07-07 19:50:44 +08:00
|
|
|
if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type)) {
|
|
|
|
call = ptr;
|
2005-06-22 23:26:05 +08:00
|
|
|
ptr = ptr->prev_execute_data;
|
|
|
|
}
|
|
|
|
|
2014-07-03 02:01:25 +08:00
|
|
|
if (ptr) {
|
|
|
|
if (skip_last) {
|
|
|
|
/* skip debug_backtrace() */
|
2014-07-07 19:50:44 +08:00
|
|
|
call = ptr;
|
2014-07-03 02:01:25 +08:00
|
|
|
ptr = ptr->prev_execute_data;
|
|
|
|
} else {
|
|
|
|
/* skip "new Exception()" */
|
2014-07-07 19:50:44 +08:00
|
|
|
if (ptr->func && ZEND_USER_CODE(ptr->func->common.type) && (ptr->opline->opcode == ZEND_NEW)) {
|
|
|
|
call = ptr;
|
2014-07-03 02:01:25 +08:00
|
|
|
ptr = ptr->prev_execute_data;
|
|
|
|
}
|
|
|
|
}
|
2015-11-09 17:14:15 +08:00
|
|
|
if (!call) {
|
|
|
|
call = ptr;
|
|
|
|
ptr = ptr->prev_execute_data;
|
|
|
|
}
|
2003-08-29 08:16:00 +08:00
|
|
|
}
|
2002-05-10 17:41:50 +08:00
|
|
|
|
2011-04-09 17:52:24 +08:00
|
|
|
while (ptr && (limit == 0 || frameno < limit)) {
|
|
|
|
frameno++;
|
2014-02-10 14:04:30 +08:00
|
|
|
array_init(&stack_frame);
|
2002-05-10 17:41:50 +08:00
|
|
|
|
2015-03-07 07:28:12 +08:00
|
|
|
ptr = zend_generator_check_placeholder_frame(ptr);
|
|
|
|
|
2005-06-22 23:26:05 +08:00
|
|
|
skip = ptr;
|
|
|
|
/* skip internal handler */
|
2019-03-18 22:17:29 +08:00
|
|
|
if (skip_internal_handler(skip)) {
|
2006-07-27 16:20:38 +08:00
|
|
|
skip = skip->prev_execute_data;
|
2005-06-22 23:26:05 +08:00
|
|
|
}
|
|
|
|
|
2014-06-27 17:02:49 +08:00
|
|
|
if (skip->func && ZEND_USER_CODE(skip->func->common.type)) {
|
2015-08-14 22:16:27 +08:00
|
|
|
filename = skip->func->op_array.filename;
|
2014-07-03 02:01:25 +08:00
|
|
|
if (skip->opline->opcode == ZEND_HANDLE_EXCEPTION) {
|
|
|
|
if (EG(opline_before_exception)) {
|
|
|
|
lineno = EG(opline_before_exception)->lineno;
|
|
|
|
} else {
|
|
|
|
lineno = skip->func->op_array.line_end;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
lineno = skip->opline->lineno;
|
|
|
|
}
|
2016-05-12 18:47:22 +08:00
|
|
|
ZVAL_STR_COPY(&tmp, filename);
|
2017-03-04 17:39:13 +08:00
|
|
|
zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_FILE), &tmp);
|
2016-05-12 18:47:22 +08:00
|
|
|
ZVAL_LONG(&tmp, lineno);
|
2017-03-04 17:39:13 +08:00
|
|
|
zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_LINE), &tmp);
|
2002-08-28 22:49:15 +08:00
|
|
|
|
|
|
|
/* try to fetch args only if an FCALL was just made - elsewise we're in the middle of a function
|
2015-01-03 17:22:58 +08:00
|
|
|
* and debug_baktrace() might have been called by the error_handler. in this case we don't
|
2002-08-28 22:49:15 +08:00
|
|
|
* want to pop anything of the argument-stack */
|
2002-08-27 00:40:34 +08:00
|
|
|
} else {
|
2014-07-07 19:50:44 +08:00
|
|
|
zend_execute_data *prev_call = skip;
|
2006-07-27 16:20:38 +08:00
|
|
|
zend_execute_data *prev = skip->prev_execute_data;
|
|
|
|
|
|
|
|
while (prev) {
|
2014-07-07 19:50:44 +08:00
|
|
|
if (prev_call &&
|
2019-03-18 22:17:29 +08:00
|
|
|
prev_call->func &&
|
2014-07-07 19:50:44 +08:00
|
|
|
!ZEND_USER_CODE(prev_call->func->common.type) &&
|
2015-04-11 04:01:00 +08:00
|
|
|
!(prev_call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
|
2006-07-27 16:20:38 +08:00
|
|
|
break;
|
2015-01-03 17:22:58 +08:00
|
|
|
}
|
2014-06-27 17:02:49 +08:00
|
|
|
if (prev->func && ZEND_USER_CODE(prev->func->common.type)) {
|
2016-05-12 18:47:22 +08:00
|
|
|
ZVAL_STR_COPY(&tmp, prev->func->op_array.filename);
|
2017-03-04 17:39:13 +08:00
|
|
|
zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_FILE), &tmp);
|
2016-05-12 18:47:22 +08:00
|
|
|
ZVAL_LONG(&tmp, prev->opline->lineno);
|
2017-03-04 17:39:13 +08:00
|
|
|
zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_LINE), &tmp);
|
2006-07-27 16:20:38 +08:00
|
|
|
break;
|
|
|
|
}
|
2014-07-07 19:50:44 +08:00
|
|
|
prev_call = prev;
|
2006-07-27 16:20:38 +08:00
|
|
|
prev = prev->prev_execute_data;
|
|
|
|
}
|
2002-08-27 00:40:34 +08:00
|
|
|
filename = NULL;
|
2002-08-23 21:50:42 +08:00
|
|
|
}
|
2002-05-10 17:41:50 +08:00
|
|
|
|
2014-04-24 19:53:20 +08:00
|
|
|
/* $this may be passed into regular internal functions */
|
2016-04-01 21:17:49 +08:00
|
|
|
object = (call && (Z_TYPE(call->This) == IS_OBJECT)) ? Z_OBJ(call->This) : NULL;
|
2014-04-24 19:53:20 +08:00
|
|
|
|
2014-07-07 19:50:44 +08:00
|
|
|
if (call && call->func) {
|
|
|
|
func = call->func;
|
2020-03-02 18:07:57 +08:00
|
|
|
function_name = func->common.function_name;
|
2014-06-24 06:17:16 +08:00
|
|
|
} else {
|
2014-07-07 19:50:44 +08:00
|
|
|
func = NULL;
|
|
|
|
function_name = NULL;
|
2014-06-24 06:17:16 +08:00
|
|
|
}
|
2002-08-23 22:44:58 +08:00
|
|
|
|
2002-07-26 18:38:25 +08:00
|
|
|
if (function_name) {
|
2016-05-12 18:47:22 +08:00
|
|
|
ZVAL_STR_COPY(&tmp, function_name);
|
2017-03-04 17:39:13 +08:00
|
|
|
zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_FUNCTION), &tmp);
|
2002-08-23 21:50:42 +08:00
|
|
|
|
2014-04-24 19:53:20 +08:00
|
|
|
if (object) {
|
2014-06-24 06:17:16 +08:00
|
|
|
if (func->common.scope) {
|
2016-05-12 18:47:22 +08:00
|
|
|
ZVAL_STR_COPY(&tmp, func->common.scope->name);
|
2018-05-31 16:57:22 +08:00
|
|
|
} else if (object->handlers->get_class_name == zend_std_get_class_name) {
|
2016-05-12 18:47:22 +08:00
|
|
|
ZVAL_STR_COPY(&tmp, object->ce->name);
|
2016-06-22 22:23:04 +08:00
|
|
|
} else {
|
2016-06-22 22:28:59 +08:00
|
|
|
ZVAL_STR(&tmp, object->handlers->get_class_name(object));
|
2005-04-05 01:23:38 +08:00
|
|
|
}
|
2017-03-04 17:39:13 +08:00
|
|
|
zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_CLASS), &tmp);
|
2011-01-17 04:39:22 +08:00
|
|
|
if ((options & DEBUG_BACKTRACE_PROVIDE_OBJECT) != 0) {
|
2020-06-17 18:34:04 +08:00
|
|
|
ZVAL_OBJ_COPY(&tmp, object);
|
2017-03-04 17:39:13 +08:00
|
|
|
zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_OBJECT), &tmp);
|
2005-11-24 13:07:28 +08:00
|
|
|
}
|
|
|
|
|
2017-03-04 17:39:13 +08:00
|
|
|
ZVAL_INTERNED_STR(&tmp, ZSTR_KNOWN(ZEND_STR_OBJECT_OPERATOR));
|
|
|
|
zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_TYPE), &tmp);
|
2014-06-24 06:17:16 +08:00
|
|
|
} else if (func->common.scope) {
|
2016-05-12 18:47:22 +08:00
|
|
|
ZVAL_STR_COPY(&tmp, func->common.scope->name);
|
2017-03-04 17:39:13 +08:00
|
|
|
zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_CLASS), &tmp);
|
|
|
|
ZVAL_INTERNED_STR(&tmp, ZSTR_KNOWN(ZEND_STR_PAAMAYIM_NEKUDOTAYIM));
|
|
|
|
zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_TYPE), &tmp);
|
2002-08-23 22:44:58 +08:00
|
|
|
}
|
|
|
|
|
2015-01-03 17:22:58 +08:00
|
|
|
if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0 &&
|
2014-06-27 03:51:14 +08:00
|
|
|
func->type != ZEND_EVAL_CODE) {
|
2014-07-07 19:50:44 +08:00
|
|
|
|
2016-05-12 18:47:22 +08:00
|
|
|
debug_backtrace_get_args(call, &tmp);
|
2017-03-04 17:39:13 +08:00
|
|
|
zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_ARGS), &tmp);
|
2006-05-10 07:53:23 +08:00
|
|
|
}
|
2002-08-23 22:44:58 +08:00
|
|
|
} else {
|
|
|
|
/* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
|
2002-08-27 00:40:34 +08:00
|
|
|
zend_bool build_filename_arg = 1;
|
2016-05-12 18:47:22 +08:00
|
|
|
zend_string *pseudo_function_name;
|
2020-09-23 23:06:28 +08:00
|
|
|
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;
|
|
|
|
}
|
2002-08-23 22:44:58 +08:00
|
|
|
|
2020-09-23 23:06:28 +08:00
|
|
|
switch (include_kind) {
|
2002-08-25 04:52:52 +08:00
|
|
|
case ZEND_EVAL:
|
2017-03-04 17:39:13 +08:00
|
|
|
pseudo_function_name = ZSTR_KNOWN(ZEND_STR_EVAL);
|
2002-08-27 00:40:34 +08:00
|
|
|
build_filename_arg = 0;
|
2002-08-25 04:52:52 +08:00
|
|
|
break;
|
|
|
|
case ZEND_INCLUDE:
|
2017-03-04 17:39:13 +08:00
|
|
|
pseudo_function_name = ZSTR_KNOWN(ZEND_STR_INCLUDE);
|
2002-08-25 04:52:52 +08:00
|
|
|
break;
|
|
|
|
case ZEND_REQUIRE:
|
2017-03-04 17:39:13 +08:00
|
|
|
pseudo_function_name = ZSTR_KNOWN(ZEND_STR_REQUIRE);
|
2002-08-25 04:52:52 +08:00
|
|
|
break;
|
|
|
|
case ZEND_INCLUDE_ONCE:
|
2017-03-04 17:39:13 +08:00
|
|
|
pseudo_function_name = ZSTR_KNOWN(ZEND_STR_INCLUDE_ONCE);
|
2002-08-25 04:52:52 +08:00
|
|
|
break;
|
|
|
|
case ZEND_REQUIRE_ONCE:
|
2017-03-04 17:39:13 +08:00
|
|
|
pseudo_function_name = ZSTR_KNOWN(ZEND_STR_REQUIRE_ONCE);
|
2002-08-25 04:52:52 +08:00
|
|
|
break;
|
|
|
|
default:
|
2020-09-23 23:06:28 +08:00
|
|
|
/* Skip dummy frame unless it is needed to preserve filename/lineno info. */
|
|
|
|
if (!filename) {
|
|
|
|
zval_ptr_dtor(&stack_frame);
|
|
|
|
goto skip_frame;
|
|
|
|
}
|
|
|
|
|
2017-03-04 17:39:13 +08:00
|
|
|
pseudo_function_name = ZSTR_KNOWN(ZEND_STR_UNKNOWN);
|
2002-08-27 00:40:34 +08:00
|
|
|
build_filename_arg = 0;
|
2002-08-25 04:52:52 +08:00
|
|
|
break;
|
2002-08-24 17:05:44 +08:00
|
|
|
}
|
|
|
|
|
2002-08-27 00:40:34 +08:00
|
|
|
if (build_filename_arg && include_filename) {
|
2014-02-10 14:04:30 +08:00
|
|
|
zval arg_array;
|
2002-08-27 00:40:34 +08:00
|
|
|
|
2014-02-10 14:04:30 +08:00
|
|
|
array_init(&arg_array);
|
2006-05-10 07:53:23 +08:00
|
|
|
|
2013-07-24 07:55:43 +08:00
|
|
|
/* include_filename always points to the last filename of the last last called-function.
|
2002-08-27 00:40:34 +08:00
|
|
|
if we have called include in the frame above - this is the file we have included.
|
2002-08-24 17:05:44 +08:00
|
|
|
*/
|
2002-08-27 00:40:34 +08:00
|
|
|
|
2016-05-12 18:47:22 +08:00
|
|
|
ZVAL_STR_COPY(&tmp, include_filename);
|
|
|
|
zend_hash_next_index_insert_new(Z_ARRVAL(arg_array), &tmp);
|
2017-03-04 17:39:13 +08:00
|
|
|
zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_ARGS), &arg_array);
|
2002-08-23 22:44:58 +08:00
|
|
|
}
|
2002-08-23 21:50:42 +08:00
|
|
|
|
2016-05-12 18:47:22 +08:00
|
|
|
ZVAL_INTERNED_STR(&tmp, pseudo_function_name);
|
2017-03-04 17:39:13 +08:00
|
|
|
zend_hash_add_new(Z_ARRVAL(stack_frame), ZSTR_KNOWN(ZEND_STR_FUNCTION), &tmp);
|
2002-08-23 22:44:58 +08:00
|
|
|
}
|
2002-08-23 22:22:25 +08:00
|
|
|
|
2014-06-27 03:51:14 +08:00
|
|
|
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &stack_frame);
|
2002-07-26 18:38:25 +08:00
|
|
|
|
2020-09-23 23:06:28 +08:00
|
|
|
skip_frame:
|
2015-01-03 17:22:58 +08:00
|
|
|
include_filename = filename;
|
2014-07-07 19:50:44 +08:00
|
|
|
call = skip;
|
2005-06-22 23:26:05 +08:00
|
|
|
ptr = skip->prev_execute_data;
|
2002-05-03 01:20:48 +08:00
|
|
|
}
|
|
|
|
}
|
2002-07-05 10:34:54 +08:00
|
|
|
/* }}} */
|
2002-05-03 01:20:48 +08:00
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Return backtrace as array */
|
2003-08-29 04:35:54 +08:00
|
|
|
ZEND_FUNCTION(debug_backtrace)
|
|
|
|
{
|
2014-08-26 01:24:55 +08:00
|
|
|
zend_long options = DEBUG_BACKTRACE_PROVIDE_OBJECT;
|
|
|
|
zend_long limit = 0;
|
2015-01-03 17:22:58 +08:00
|
|
|
|
2014-12-14 06:06:14 +08:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &options, &limit) == FAILURE) {
|
2019-12-31 00:35:46 +08:00
|
|
|
RETURN_THROWS();
|
2003-08-29 04:35:54 +08:00
|
|
|
}
|
2006-05-10 07:53:23 +08:00
|
|
|
|
2014-12-14 06:06:14 +08:00
|
|
|
zend_fetch_debug_backtrace(return_value, 1, options, limit);
|
2003-08-29 04:35:54 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Returns true if the named extension is loaded */
|
2001-05-21 23:47:52 +08:00
|
|
|
ZEND_FUNCTION(extension_loaded)
|
|
|
|
{
|
2014-12-24 20:04:51 +08:00
|
|
|
zend_string *extension_name;
|
2014-02-10 14:04:30 +08:00
|
|
|
zend_string *lcname;
|
2001-05-21 23:47:52 +08:00
|
|
|
|
2014-12-24 20:04:51 +08:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &extension_name) == FAILURE) {
|
2019-12-31 00:35:46 +08:00
|
|
|
RETURN_THROWS();
|
2001-05-21 23:47:52 +08:00
|
|
|
}
|
|
|
|
|
2014-12-24 20:04:51 +08:00
|
|
|
lcname = zend_string_tolower(extension_name);
|
2014-02-10 14:04:30 +08:00
|
|
|
if (zend_hash_exists(&module_registry, lcname)) {
|
2004-03-30 02:48:59 +08:00
|
|
|
RETVAL_TRUE;
|
2001-05-21 23:47:52 +08:00
|
|
|
} else {
|
2004-03-30 02:48:59 +08:00
|
|
|
RETVAL_FALSE;
|
2001-05-21 23:47:52 +08:00
|
|
|
}
|
2018-05-28 21:27:12 +08:00
|
|
|
zend_string_release_ex(lcname, 0);
|
2001-05-21 23:47:52 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 21:32:55 +08:00
|
|
|
/* {{{ Returns an array with the names of functions belonging to the named extension */
|
2001-05-21 23:47:52 +08:00
|
|
|
ZEND_FUNCTION(get_extension_funcs)
|
|
|
|
{
|
2014-12-24 20:04:51 +08:00
|
|
|
zend_string *extension_name;
|
2014-02-10 14:04:30 +08:00
|
|
|
zend_string *lcname;
|
2020-08-28 21:41:27 +08:00
|
|
|
bool array;
|
2001-05-21 23:47:52 +08:00
|
|
|
zend_module_entry *module;
|
2013-12-10 23:07:16 +08:00
|
|
|
zend_function *zif;
|
2015-01-03 17:22:58 +08:00
|
|
|
|
2014-12-24 20:04:51 +08:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &extension_name) == FAILURE) {
|
2019-12-31 00:35:46 +08:00
|
|
|
RETURN_THROWS();
|
2001-05-21 23:47:52 +08:00
|
|
|
}
|
2015-06-30 18:59:27 +08:00
|
|
|
if (strncasecmp(ZSTR_VAL(extension_name), "zend", sizeof("zend"))) {
|
2014-12-24 20:04:51 +08:00
|
|
|
lcname = zend_string_tolower(extension_name);
|
2015-07-02 12:31:26 +08:00
|
|
|
module = zend_hash_find_ptr(&module_registry, lcname);
|
2018-05-28 21:27:12 +08:00
|
|
|
zend_string_release_ex(lcname, 0);
|
2013-12-10 23:07:16 +08:00
|
|
|
} else {
|
2015-07-02 12:31:26 +08:00
|
|
|
module = zend_hash_str_find_ptr(&module_registry, "core", sizeof("core") - 1);
|
2013-12-10 23:07:16 +08:00
|
|
|
}
|
2015-07-02 12:31:26 +08:00
|
|
|
|
2014-02-10 14:04:30 +08:00
|
|
|
if (!module) {
|
2013-12-10 23:07:16 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2006-05-10 07:53:23 +08:00
|
|
|
|
2013-12-10 23:07:16 +08:00
|
|
|
if (module->functions) {
|
|
|
|
/* avoid BC break, if functions list is empty, will return an empty array */
|
|
|
|
array_init(return_value);
|
|
|
|
array = 1;
|
2003-02-07 04:21:02 +08:00
|
|
|
} else {
|
2013-12-10 23:07:16 +08:00
|
|
|
array = 0;
|
|
|
|
}
|
2014-04-18 23:18:11 +08:00
|
|
|
|
|
|
|
ZEND_HASH_FOREACH_PTR(CG(function_table), zif) {
|
2014-03-03 17:06:04 +08:00
|
|
|
if (zif->common.type == ZEND_INTERNAL_FUNCTION
|
2013-12-10 23:07:16 +08:00
|
|
|
&& zif->internal_function.module == module) {
|
|
|
|
if (!array) {
|
|
|
|
array_init(return_value);
|
|
|
|
array = 1;
|
|
|
|
}
|
2014-08-26 01:24:55 +08:00
|
|
|
add_next_index_str(return_value, zend_string_copy(zif->common.function_name));
|
2013-12-10 23:07:16 +08:00
|
|
|
}
|
2014-04-18 23:18:11 +08:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
2001-05-21 23:47:52 +08:00
|
|
|
|
2013-12-10 23:07:16 +08:00
|
|
|
if (!array) {
|
|
|
|
RETURN_FALSE;
|
2001-05-21 23:47:52 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|