1999-09-20 12:24:39 +00:00
|
|
|
/*
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| Zend Engine |
|
|
|
|
+----------------------------------------------------------------------+
|
2019-01-30 09:23:29 +00:00
|
|
|
| Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
|
1999-09-20 12:24:39 +00:00
|
|
|
+----------------------------------------------------------------------+
|
2001-12-11 15:16:21 +00:00
|
|
|
| This source file is subject to version 2.00 of the Zend license, |
|
1999-09-20 12:24:39 +00:00
|
|
|
| that is bundled with this package in the file LICENSE, and is |
|
2003-06-10 20:04:29 +00:00
|
|
|
| available through the world-wide-web at the following url: |
|
2001-12-11 15:16:21 +00:00
|
|
|
| http://www.zend.com/license/2_00.txt. |
|
1999-09-20 12:24:39 +00: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 15:20:07 +00:00
|
|
|
| Authors: Andi Gutmans <andi@php.net> |
|
|
|
|
| Zeev Suraski <zeev@php.net> |
|
1999-09-20 12:24:39 +00:00
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "zend.h"
|
|
|
|
#include "zend_API.h"
|
2021-10-11 13:49:27 +00:00
|
|
|
#include "zend_attributes.h"
|
2018-06-13 08:10:17 +00:00
|
|
|
#include "zend_gc.h"
|
1999-09-20 12:24:39 +00:00
|
|
|
#include "zend_builtin_functions.h"
|
1999-09-20 21:28:37 +00:00
|
|
|
#include "zend_constants.h"
|
2002-11-19 17:51:30 +00:00
|
|
|
#include "zend_ini.h"
|
2021-12-21 11:21:24 +00:00
|
|
|
#include "zend_interfaces.h"
|
2007-02-24 02:17:47 +00:00
|
|
|
#include "zend_exceptions.h"
|
2007-07-31 22:47:25 +00:00
|
|
|
#include "zend_extensions.h"
|
2010-06-11 23:20:13 +00:00
|
|
|
#include "zend_closures.h"
|
2015-03-06 23:28:12 +00:00
|
|
|
#include "zend_generators.h"
|
2019-06-18 09:33:07 +00:00
|
|
|
#include "zend_builtin_functions_arginfo.h"
|
2021-04-15 09:26:42 +00:00
|
|
|
#include "zend_smart_str.h"
|
2015-02-04 17:21:42 +00:00
|
|
|
|
2016-01-21 06:31:03 +00:00
|
|
|
/* }}} */
|
|
|
|
|
2008-12-31 12:26:33 +00:00
|
|
|
ZEND_MINIT_FUNCTION(core) { /* {{{ */
|
2014-12-13 22:06:14 +00:00
|
|
|
zend_register_default_classes();
|
2008-12-31 13:25:21 +00:00
|
|
|
|
2021-10-11 13:49:27 +00:00
|
|
|
zend_standard_class_def = register_class_stdClass();
|
|
|
|
|
2008-12-31 12:26:33 +00:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2024-05-22 11:11:46 +00:00
|
|
|
static zend_module_entry zend_builtin_module = { /* {{{ */
|
2019-03-18 14:17:29 +00:00
|
|
|
STANDARD_MODULE_HEADER,
|
2008-12-30 20:15:28 +00:00
|
|
|
"Core",
|
2020-04-21 10:23:21 +00:00
|
|
|
ext_functions,
|
2008-12-31 12:26:33 +00:00
|
|
|
ZEND_MINIT(core),
|
2008-12-30 18:17:44 +00:00
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
ZEND_VERSION,
|
|
|
|
STANDARD_MODULE_PROPERTIES
|
|
|
|
};
|
|
|
|
/* }}} */
|
1999-09-20 12:24:39 +00:00
|
|
|
|
2020-08-28 13:41:27 +00:00
|
|
|
zend_result zend_startup_builtin_functions(void) /* {{{ */
|
1999-09-20 12:24:39 +00:00
|
|
|
{
|
2023-09-25 15:36:13 +00:00
|
|
|
zend_module_entry *module;
|
|
|
|
EG(current_module) = module = zend_register_module_ex(&zend_builtin_module, MODULE_PERSISTENT);
|
|
|
|
if (UNEXPECTED(module == NULL)) {
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
ZEND_ASSERT(module->module_number == 0);
|
|
|
|
return SUCCESS;
|
1999-09-20 12:24:39 +00:00
|
|
|
}
|
2008-12-30 18:17:44 +00:00
|
|
|
/* }}} */
|
1999-09-20 12:24:39 +00:00
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Get the version of the Zend Engine */
|
1999-09-20 12:24:39 +00:00
|
|
|
ZEND_FUNCTION(zend_version)
|
|
|
|
{
|
2020-01-03 11:11:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2018-07-12 13:05:56 +00:00
|
|
|
|
2014-02-10 06:04:30 +00:00
|
|
|
RETURN_STRINGL(ZEND_VERSION, sizeof(ZEND_VERSION)-1);
|
1999-09-20 12:24:39 +00:00
|
|
|
}
|
2001-12-04 17:58:32 +00:00
|
|
|
/* }}} */
|
1999-09-20 13:00:35 +00:00
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Reclaims memory used by MM caches.
|
2015-08-04 15:21:05 +00:00
|
|
|
Returns number of freed bytes */
|
|
|
|
ZEND_FUNCTION(gc_mem_caches)
|
|
|
|
{
|
2020-01-03 11:11:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2018-07-12 13:05:56 +00:00
|
|
|
|
2015-08-04 15:21:05 +00:00
|
|
|
RETURN_LONG(zend_mm_gc(zend_mm_get_heap()));
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Forces collection of any existing garbage cycles.
|
2008-01-22 09:27:48 +00:00
|
|
|
Returns number of freed zvals */
|
|
|
|
ZEND_FUNCTION(gc_collect_cycles)
|
|
|
|
{
|
2020-01-03 11:11:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2018-07-12 13:05:56 +00:00
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
RETURN_LONG(gc_collect_cycles());
|
2008-01-22 09:27:48 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Returns status of the circular reference collector */
|
2008-01-22 09:27:48 +00:00
|
|
|
ZEND_FUNCTION(gc_enabled)
|
|
|
|
{
|
2020-01-03 11:11:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2018-07-12 13:05:56 +00:00
|
|
|
|
2018-02-26 09:49:58 +00:00
|
|
|
RETURN_BOOL(gc_enabled());
|
2008-01-22 09:27:48 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Activates the circular reference collector */
|
2008-01-22 09:27:48 +00:00
|
|
|
ZEND_FUNCTION(gc_enable)
|
|
|
|
{
|
2018-07-12 13:05:56 +00:00
|
|
|
zend_string *key;
|
|
|
|
|
2020-01-03 11:11:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2018-07-12 13:05:56 +00:00
|
|
|
|
2023-03-20 15:19:05 +00:00
|
|
|
key = ZSTR_INIT_LITERAL("zend.enable_gc", 0);
|
2014-09-01 16:57:33 +00:00
|
|
|
zend_alter_ini_entry_chars(key, "1", sizeof("1")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(key, 0);
|
2008-01-22 09:27:48 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Deactivates the circular reference collector */
|
2008-01-22 09:27:48 +00:00
|
|
|
ZEND_FUNCTION(gc_disable)
|
|
|
|
{
|
2018-07-12 13:05:56 +00:00
|
|
|
zend_string *key;
|
|
|
|
|
2020-01-03 11:11:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2018-07-12 13:05:56 +00:00
|
|
|
|
2023-03-20 15:19:05 +00:00
|
|
|
key = ZSTR_INIT_LITERAL("zend.enable_gc", 0);
|
2014-09-01 16:57:33 +00:00
|
|
|
zend_alter_ini_entry_chars(key, "0", sizeof("0")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(key, 0);
|
2008-01-22 09:27:48 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
1999-09-20 13:00:35 +00:00
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Returns current GC statistics */
|
2018-06-13 08:10:17 +00:00
|
|
|
ZEND_FUNCTION(gc_status)
|
|
|
|
{
|
|
|
|
zend_gc_status status;
|
|
|
|
|
2020-01-03 11:11:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2018-07-12 13:05:56 +00:00
|
|
|
|
2018-06-13 08:10:17 +00:00
|
|
|
zend_gc_get_status(&status);
|
|
|
|
|
2023-07-16 10:34:28 +00:00
|
|
|
array_init_size(return_value, 16);
|
2018-06-13 08:10:17 +00:00
|
|
|
|
2022-10-04 12:56:02 +00:00
|
|
|
add_assoc_bool_ex(return_value, "running", sizeof("running")-1, status.active);
|
|
|
|
add_assoc_bool_ex(return_value, "protected", sizeof("protected")-1, status.gc_protected);
|
|
|
|
add_assoc_bool_ex(return_value, "full", sizeof("full")-1, status.full);
|
2018-06-13 08:28:24 +00:00
|
|
|
add_assoc_long_ex(return_value, "runs", sizeof("runs")-1, (long)status.runs);
|
2018-06-13 08:10:17 +00:00
|
|
|
add_assoc_long_ex(return_value, "collected", sizeof("collected")-1, (long)status.collected);
|
2018-06-13 08:28:24 +00:00
|
|
|
add_assoc_long_ex(return_value, "threshold", sizeof("threshold")-1, (long)status.threshold);
|
2022-10-04 12:56:02 +00:00
|
|
|
add_assoc_long_ex(return_value, "buffer_size", sizeof("buffer_size")-1, (long)status.buf_size);
|
2018-06-13 08:41:51 +00:00
|
|
|
add_assoc_long_ex(return_value, "roots", sizeof("roots")-1, (long)status.num_roots);
|
2023-07-16 10:34:28 +00:00
|
|
|
|
|
|
|
/* Using double because zend_long may be too small on some platforms */
|
|
|
|
add_assoc_double_ex(return_value, "application_time", sizeof("application_time")-1, (double) status.application_time / ZEND_NANO_IN_SEC);
|
|
|
|
add_assoc_double_ex(return_value, "collector_time", sizeof("collector_time")-1, (double) status.collector_time / ZEND_NANO_IN_SEC);
|
|
|
|
add_assoc_double_ex(return_value, "destructor_time", sizeof("destructor_time")-1, (double) status.dtor_time / ZEND_NANO_IN_SEC);
|
|
|
|
add_assoc_double_ex(return_value, "free_time", sizeof("free_time")-1, (double) status.free_time / ZEND_NANO_IN_SEC);
|
2018-06-13 08:10:17 +00:00
|
|
|
}
|
2018-06-13 08:41:51 +00:00
|
|
|
/* }}} */
|
2018-06-13 08:10:17 +00:00
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Get the number of arguments that were passed to the function */
|
1999-09-21 07:31:24 +00:00
|
|
|
ZEND_FUNCTION(func_num_args)
|
1999-09-20 13:00:35 +00:00
|
|
|
{
|
2014-10-03 15:32:46 +00:00
|
|
|
zend_execute_data *ex = EX(prev_execute_data);
|
1999-09-20 13:00:35 +00:00
|
|
|
|
2020-01-03 11:11:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2018-07-12 13:05:56 +00:00
|
|
|
|
2023-11-30 19:26:24 +00:00
|
|
|
if (ex && (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE)) {
|
2020-07-12 10:40:37 +00:00
|
|
|
zend_throw_error(NULL, "func_num_args() must be called from a function context");
|
|
|
|
RETURN_THROWS();
|
1999-09-20 13:00:35 +00:00
|
|
|
}
|
2016-04-24 21:49:52 +00:00
|
|
|
|
2021-09-01 08:32:05 +00:00
|
|
|
if (zend_forbid_dynamic_call() == FAILURE) {
|
2016-04-24 21:49:52 +00:00
|
|
|
RETURN_LONG(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
RETURN_LONG(ZEND_CALL_NUM_ARGS(ex));
|
1999-09-20 13:00:35 +00:00
|
|
|
}
|
2001-12-04 17:58:32 +00:00
|
|
|
/* }}} */
|
1999-09-20 13:00:35 +00:00
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Get the $arg_num'th argument that was passed to the function */
|
1999-09-21 07:31:24 +00:00
|
|
|
ZEND_FUNCTION(func_get_arg)
|
1999-09-20 13:00:35 +00:00
|
|
|
{
|
2014-09-15 10:08:42 +00:00
|
|
|
uint32_t arg_count, first_extra_arg;
|
1999-09-20 13:00:35 +00:00
|
|
|
zval *arg;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long requested_offset;
|
2014-06-26 19:51:14 +00:00
|
|
|
zend_execute_data *ex;
|
1999-09-20 13:00:35 +00:00
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &requested_offset) == FAILURE) {
|
2019-12-30 16:35:46 +00:00
|
|
|
RETURN_THROWS();
|
1999-09-20 13:00:35 +00:00
|
|
|
}
|
|
|
|
|
2002-05-08 14:10:30 +00:00
|
|
|
if (requested_offset < 0) {
|
2020-03-29 22:40:18 +00:00
|
|
|
zend_argument_value_error(1, "must be greater than or equal to 0");
|
|
|
|
RETURN_THROWS();
|
2002-05-08 14:10:30 +00:00
|
|
|
}
|
|
|
|
|
2014-10-03 15:32:46 +00:00
|
|
|
ex = EX(prev_execute_data);
|
2023-11-30 19:26:24 +00:00
|
|
|
if (ex && (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE)) {
|
2020-03-29 22:40:18 +00:00
|
|
|
zend_throw_error(NULL, "func_get_arg() cannot be called from the global scope");
|
|
|
|
RETURN_THROWS();
|
1999-09-20 13:00:35 +00:00
|
|
|
}
|
|
|
|
|
2021-09-01 08:32:05 +00:00
|
|
|
if (zend_forbid_dynamic_call() == FAILURE) {
|
2020-03-29 22:40:18 +00:00
|
|
|
RETURN_THROWS();
|
2016-04-24 21:49:52 +00:00
|
|
|
}
|
|
|
|
|
2014-11-28 07:28:49 +00:00
|
|
|
arg_count = ZEND_CALL_NUM_ARGS(ex);
|
2008-01-24 09:41:39 +00:00
|
|
|
|
2016-04-29 11:44:56 +00:00
|
|
|
if ((zend_ulong)requested_offset >= arg_count) {
|
2020-07-12 10:40:37 +00:00
|
|
|
zend_argument_value_error(1, "must be less than the number of the arguments passed to the currently executed function");
|
2020-03-29 22:40:18 +00:00
|
|
|
RETURN_THROWS();
|
1999-09-20 13:00:35 +00:00
|
|
|
}
|
|
|
|
|
2014-06-30 10:17:17 +00:00
|
|
|
first_extra_arg = ex->func->op_array.num_args;
|
2016-04-29 11:44:56 +00:00
|
|
|
if ((zend_ulong)requested_offset >= first_extra_arg && (ZEND_CALL_NUM_ARGS(ex) > first_extra_arg)) {
|
2014-11-28 08:11:33 +00: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-26 19:51:14 +00:00
|
|
|
} else {
|
|
|
|
arg = ZEND_CALL_ARG(ex, requested_offset + 1);
|
|
|
|
}
|
2015-09-23 02:00:20 +00:00
|
|
|
if (EXPECTED(!Z_ISUNDEF_P(arg))) {
|
2021-07-22 07:38:05 +00:00
|
|
|
RETURN_COPY_DEREF(arg);
|
2015-09-23 02:00:20 +00:00
|
|
|
}
|
1999-09-20 13:00:35 +00:00
|
|
|
}
|
2001-12-04 17:58:32 +00:00
|
|
|
/* }}} */
|
1999-09-20 13:00:35 +00:00
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Get an array of the arguments that were passed to the function */
|
1999-09-21 07:31:24 +00:00
|
|
|
ZEND_FUNCTION(func_get_args)
|
|
|
|
{
|
2014-12-23 16:08:28 +00:00
|
|
|
zval *p, *q;
|
2014-09-15 10:08:42 +00:00
|
|
|
uint32_t arg_count, first_extra_arg;
|
2017-06-25 13:08:36 +00:00
|
|
|
uint32_t i;
|
2014-10-03 15:32:46 +00:00
|
|
|
zend_execute_data *ex = EX(prev_execute_data);
|
1999-09-21 07:31:24 +00:00
|
|
|
|
2020-05-30 21:33:25 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
|
2023-11-30 19:26:24 +00:00
|
|
|
if (ex && (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE)) {
|
2020-03-29 22:40:18 +00:00
|
|
|
zend_throw_error(NULL, "func_get_args() cannot be called from the global scope");
|
|
|
|
RETURN_THROWS();
|
1999-09-21 07:31:24 +00:00
|
|
|
}
|
|
|
|
|
2021-09-01 08:32:05 +00:00
|
|
|
if (zend_forbid_dynamic_call() == FAILURE) {
|
2020-03-29 22:40:18 +00:00
|
|
|
RETURN_THROWS();
|
2016-04-24 21:49:52 +00:00
|
|
|
}
|
|
|
|
|
2014-11-28 07:28:49 +00:00
|
|
|
arg_count = ZEND_CALL_NUM_ARGS(ex);
|
1999-09-21 07:31:24 +00:00
|
|
|
|
2014-05-26 13:15:52 +00:00
|
|
|
if (arg_count) {
|
2017-10-24 14:27:31 +00:00
|
|
|
array_init_size(return_value, arg_count);
|
2014-06-30 10:17:17 +00:00
|
|
|
first_extra_arg = ex->func->op_array.num_args;
|
2018-03-22 21:13:45 +00:00
|
|
|
zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
|
2014-12-23 16:08:28 +00:00
|
|
|
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
|
|
|
|
i = 0;
|
|
|
|
p = ZEND_CALL_ARG(ex, 1);
|
2015-01-20 05:55:36 +00:00
|
|
|
if (arg_count > first_extra_arg) {
|
2014-12-23 16:08:28 +00:00
|
|
|
while (i < first_extra_arg) {
|
|
|
|
q = p;
|
2015-09-22 05:58:42 +00:00
|
|
|
if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) {
|
|
|
|
ZVAL_DEREF(q);
|
2017-12-31 04:35:25 +00:00
|
|
|
if (Z_OPT_REFCOUNTED_P(q)) {
|
2015-09-22 05:58:42 +00:00
|
|
|
Z_ADDREF_P(q);
|
|
|
|
}
|
2019-05-28 10:35:00 +00:00
|
|
|
ZEND_HASH_FILL_SET(q);
|
2017-06-25 13:08:36 +00:00
|
|
|
} else {
|
2019-05-28 10:35:00 +00:00
|
|
|
ZEND_HASH_FILL_SET_NULL();
|
2015-09-22 05:58:42 +00:00
|
|
|
}
|
2019-05-28 10:35:00 +00:00
|
|
|
ZEND_HASH_FILL_NEXT();
|
2014-12-23 16:08:28 +00: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 05:58:42 +00:00
|
|
|
if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) {
|
|
|
|
ZVAL_DEREF(q);
|
2017-12-31 04:35:25 +00:00
|
|
|
if (Z_OPT_REFCOUNTED_P(q)) {
|
2015-09-22 05:58:42 +00:00
|
|
|
Z_ADDREF_P(q);
|
|
|
|
}
|
2019-05-28 10:35:00 +00:00
|
|
|
ZEND_HASH_FILL_SET(q);
|
2017-06-25 13:08:36 +00:00
|
|
|
} else {
|
2019-05-28 10:35:00 +00:00
|
|
|
ZEND_HASH_FILL_SET_NULL();
|
2015-09-22 05:58:42 +00:00
|
|
|
}
|
2019-05-28 10:35:00 +00:00
|
|
|
ZEND_HASH_FILL_NEXT();
|
2014-06-26 19:51:14 +00:00
|
|
|
p++;
|
|
|
|
i++;
|
|
|
|
}
|
2014-12-23 16:08:28 +00:00
|
|
|
} ZEND_HASH_FILL_END();
|
2017-06-25 13:08:36 +00:00
|
|
|
Z_ARRVAL_P(return_value)->nNumOfElements = arg_count;
|
2017-10-24 14:27:31 +00:00
|
|
|
} else {
|
2019-05-14 12:57:10 +00:00
|
|
|
RETURN_EMPTY_ARRAY();
|
1999-09-21 07:31:24 +00:00
|
|
|
}
|
|
|
|
}
|
2001-12-04 17:58:32 +00:00
|
|
|
/* }}} */
|
1999-09-21 07:31:24 +00:00
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Get string length
|
2014-08-28 19:53:32 +00:00
|
|
|
Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
|
2008-11-17 22:21:55 +00:00
|
|
|
ZEND_FUNCTION(strlen)
|
1999-09-20 16:56:09 +00:00
|
|
|
{
|
2014-05-13 06:05:28 +00:00
|
|
|
zend_string *s;
|
2006-05-09 23:53:23 +00:00
|
|
|
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(s)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2008-06-18 23:38:37 +00:00
|
|
|
|
2015-06-30 10:59:27 +00:00
|
|
|
RETVAL_LONG(ZSTR_LEN(s));
|
1999-09-20 16:56:09 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Binary safe string comparison */
|
1999-09-20 16:56:09 +00:00
|
|
|
ZEND_FUNCTION(strcmp)
|
|
|
|
{
|
2014-08-16 09:16:11 +00:00
|
|
|
zend_string *s1, *s2;
|
2015-01-03 09:22:58 +00:00
|
|
|
|
2017-06-07 20:08:18 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 2)
|
|
|
|
Z_PARAM_STR(s1)
|
|
|
|
Z_PARAM_STR(s2)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2008-06-18 23:38:37 +00:00
|
|
|
|
2015-06-30 10:59:27 +00:00
|
|
|
RETURN_LONG(zend_binary_strcmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2)));
|
1999-09-20 16:56:09 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Binary safe string comparison */
|
2000-02-08 17:19:43 +00:00
|
|
|
ZEND_FUNCTION(strncmp)
|
|
|
|
{
|
2014-08-16 09:16:11 +00:00
|
|
|
zend_string *s1, *s2;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long len;
|
2008-06-18 23:38:37 +00:00
|
|
|
|
2017-06-07 20:08:18 +00: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 11:36:13 +00:00
|
|
|
|
2008-06-18 23:38:37 +00:00
|
|
|
if (len < 0) {
|
2020-03-29 22:40:18 +00:00
|
|
|
zend_argument_value_error(3, "must be greater than or equal to 0");
|
|
|
|
RETURN_THROWS();
|
2006-04-05 11:36:13 +00:00
|
|
|
}
|
2008-06-18 23:38:37 +00:00
|
|
|
|
2015-06-30 10:59:27 +00:00
|
|
|
RETURN_LONG(zend_binary_strncmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2), len));
|
2000-02-08 17:19:43 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Binary safe case-insensitive string comparison */
|
1999-09-20 16:56:09 +00:00
|
|
|
ZEND_FUNCTION(strcasecmp)
|
|
|
|
{
|
2014-08-16 09:16:11 +00:00
|
|
|
zend_string *s1, *s2;
|
2015-01-03 09:22:58 +00:00
|
|
|
|
2017-06-07 20:08:18 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 2)
|
|
|
|
Z_PARAM_STR(s1)
|
|
|
|
Z_PARAM_STR(s2)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2008-06-18 23:38:37 +00:00
|
|
|
|
2015-06-30 10:59:27 +00:00
|
|
|
RETURN_LONG(zend_binary_strcasecmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2)));
|
1999-09-20 16:56:09 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Binary safe string comparison */
|
2000-07-26 11:32:15 +00:00
|
|
|
ZEND_FUNCTION(strncasecmp)
|
|
|
|
{
|
2014-08-16 09:16:11 +00:00
|
|
|
zend_string *s1, *s2;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long len;
|
2008-06-18 23:38:37 +00:00
|
|
|
|
2017-06-07 20:08:18 +00: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 11:36:13 +00:00
|
|
|
|
2008-06-18 23:38:37 +00:00
|
|
|
if (len < 0) {
|
2020-03-29 22:40:18 +00:00
|
|
|
zend_argument_value_error(3, "must be greater than or equal to 0");
|
|
|
|
RETURN_THROWS();
|
2006-04-05 11:36:13 +00:00
|
|
|
}
|
|
|
|
|
2015-06-30 10:59:27 +00:00
|
|
|
RETURN_LONG(zend_binary_strncasecmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2), len));
|
2000-07-26 11:32:15 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Return the current error_reporting level, and if an argument was passed - change to the new level */
|
1999-09-20 16:56:09 +00:00
|
|
|
ZEND_FUNCTION(error_reporting)
|
|
|
|
{
|
2020-07-12 10:40:37 +00:00
|
|
|
zend_long err;
|
2021-01-15 11:30:54 +00:00
|
|
|
bool err_is_null = 1;
|
1999-09-20 16:56:09 +00:00
|
|
|
int old_error_reporting;
|
|
|
|
|
2015-01-12 16:26:12 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(0, 1)
|
|
|
|
Z_PARAM_OPTIONAL
|
2020-07-12 10:40:37 +00:00
|
|
|
Z_PARAM_LONG_OR_NULL(err, err_is_null)
|
2015-01-12 16:26:12 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2008-06-18 23:38:37 +00:00
|
|
|
|
1999-09-20 16:56:09 +00:00
|
|
|
old_error_reporting = EG(error_reporting);
|
2020-07-12 10:40:37 +00:00
|
|
|
|
2021-03-11 11:27:53 +00:00
|
|
|
if (!err_is_null && err != old_error_reporting) {
|
2021-04-23 15:10:24 +00:00
|
|
|
zend_ini_entry *p = EG(error_reporting_ini_entry);
|
2019-02-26 14:32:18 +00:00
|
|
|
|
2021-04-23 15:10:24 +00:00
|
|
|
if (!p) {
|
2021-07-20 23:07:17 +00:00
|
|
|
zval *zv = zend_hash_find_known_hash(EG(ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING));
|
2021-04-23 15:10:24 +00:00
|
|
|
if (!zv) {
|
|
|
|
/* Ini setting does not exist -- can this happen? */
|
|
|
|
RETURN_LONG(old_error_reporting);
|
|
|
|
}
|
2015-01-13 05:30:54 +00:00
|
|
|
|
2021-04-23 15:10:24 +00:00
|
|
|
p = EG(error_reporting_ini_entry) = (zend_ini_entry*)Z_PTR_P(zv);
|
|
|
|
}
|
|
|
|
if (!p->modified) {
|
|
|
|
if (!EG(modified_ini_directives)) {
|
|
|
|
ALLOC_HASHTABLE(EG(modified_ini_directives));
|
|
|
|
zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
|
2015-01-12 20:50:03 +00:00
|
|
|
}
|
2021-04-23 15:10:24 +00:00
|
|
|
if (EXPECTED(zend_hash_add_ptr(EG(modified_ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING), p) != NULL)) {
|
|
|
|
p->orig_value = p->value;
|
|
|
|
p->orig_modifiable = p->modifiable;
|
|
|
|
p->modified = 1;
|
2015-01-12 20:50:03 +00:00
|
|
|
}
|
2021-04-23 15:10:24 +00:00
|
|
|
} else if (p->orig_value != p->value) {
|
|
|
|
zend_string_release_ex(p->value, 0);
|
|
|
|
}
|
2015-01-12 20:50:03 +00:00
|
|
|
|
2021-04-23 15:10:24 +00:00
|
|
|
p->value = zend_long_to_str(err);
|
|
|
|
EG(error_reporting) = err;
|
1999-09-20 16:56:09 +00:00
|
|
|
}
|
2000-06-30 11:45:32 +00:00
|
|
|
|
2021-04-23 15:10:24 +00:00
|
|
|
RETURN_LONG(old_error_reporting);
|
1999-09-20 17:01:38 +00:00
|
|
|
}
|
2001-12-04 17:58:32 +00:00
|
|
|
/* }}} */
|
|
|
|
|
2020-08-28 13:41:27 +00:00
|
|
|
static bool validate_constant_array_argument(HashTable *ht, int argument_number) /* {{{ */
|
2014-12-21 03:03:49 +00:00
|
|
|
{
|
2020-08-28 13:41:27 +00:00
|
|
|
bool ret = 1;
|
2014-12-21 03:03:49 +00:00
|
|
|
zval *val;
|
|
|
|
|
2017-10-05 22:34:50 +00:00
|
|
|
GC_PROTECT_RECURSION(ht);
|
2020-12-03 15:52:32 +00:00
|
|
|
ZEND_HASH_FOREACH_VAL(ht, val) {
|
2014-12-21 03:03:49 +00:00
|
|
|
ZVAL_DEREF(val);
|
2021-06-14 10:23:24 +00:00
|
|
|
if (Z_TYPE_P(val) == IS_ARRAY && Z_REFCOUNTED_P(val)) {
|
|
|
|
if (Z_IS_RECURSIVE_P(val)) {
|
|
|
|
zend_argument_value_error(argument_number, "cannot be a recursive array");
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
} else if (!validate_constant_array_argument(Z_ARRVAL_P(val), argument_number)) {
|
2014-12-21 03:03:49 +00:00
|
|
|
ret = 0;
|
|
|
|
break;
|
2015-01-03 09:22:58 +00:00
|
|
|
}
|
2014-12-21 03:03:49 +00:00
|
|
|
}
|
|
|
|
} ZEND_HASH_FOREACH_END();
|
2017-10-05 22:34:50 +00:00
|
|
|
GC_UNPROTECT_RECURSION(ht);
|
2014-12-21 03:03:49 +00: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)));
|
2020-12-03 15:52:32 +00:00
|
|
|
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(src), idx, key, val) {
|
2014-12-21 03:03:49 +00:00
|
|
|
/* constant arrays can't contain references */
|
2015-01-22 12:49:38 +00:00
|
|
|
ZVAL_DEREF(val);
|
2014-12-21 03:03:49 +00: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 09:22:58 +00:00
|
|
|
}
|
2014-12-21 03:03:49 +00:00
|
|
|
if (Z_TYPE_P(val) == IS_ARRAY) {
|
2016-11-28 19:59:57 +00:00
|
|
|
if (Z_REFCOUNTED_P(val)) {
|
2014-12-21 03:03:49 +00:00
|
|
|
copy_constant_array(new_val, val);
|
|
|
|
}
|
2017-11-02 04:13:35 +00:00
|
|
|
} else {
|
|
|
|
Z_TRY_ADDREF_P(val);
|
2014-12-21 03:03:49 +00:00
|
|
|
}
|
|
|
|
} ZEND_HASH_FOREACH_END();
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Define a new constant */
|
1999-09-20 21:28:37 +00:00
|
|
|
ZEND_FUNCTION(define)
|
|
|
|
{
|
2014-04-21 21:41:09 +00:00
|
|
|
zend_string *name;
|
2014-02-10 06:04:30 +00:00
|
|
|
zval *val, val_free;
|
2021-01-15 11:30:54 +00:00
|
|
|
bool non_cs = 0;
|
1999-09-20 21:28:37 +00:00
|
|
|
zend_constant c;
|
2006-05-09 23:53:23 +00:00
|
|
|
|
2014-07-11 12:32:20 +00: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-18 23:38:37 +00:00
|
|
|
|
2015-06-30 10:59:27 +00:00
|
|
|
if (zend_memnstr(ZSTR_VAL(name), "::", sizeof("::") - 1, ZSTR_VAL(name) + ZSTR_LEN(name))) {
|
2020-07-12 10:40:37 +00:00
|
|
|
zend_argument_value_error(1, "cannot be a class constant");
|
|
|
|
RETURN_THROWS();
|
2009-06-08 01:26:03 +00:00
|
|
|
}
|
|
|
|
|
2019-01-29 12:36:26 +00:00
|
|
|
if (non_cs) {
|
2020-07-12 10:40:37 +00:00
|
|
|
zend_error(E_WARNING, "define(): Argument #3 ($case_insensitive) is ignored since declaration of case-insensitive constants is no longer supported");
|
2021-06-29 08:04:10 +00:00
|
|
|
}
|
2019-01-29 12:36:26 +00:00
|
|
|
|
2014-02-10 06:04:30 +00:00
|
|
|
ZVAL_UNDEF(&val_free);
|
|
|
|
|
2021-06-14 10:23:24 +00:00
|
|
|
if (Z_TYPE_P(val) == IS_ARRAY) {
|
|
|
|
if (Z_REFCOUNTED_P(val)) {
|
|
|
|
if (!validate_constant_array_argument(Z_ARRVAL_P(val), 2)) {
|
|
|
|
RETURN_THROWS();
|
|
|
|
} else {
|
|
|
|
copy_constant_array(&c.value, val);
|
|
|
|
goto register_constant;
|
2006-07-09 22:45:11 +00:00
|
|
|
}
|
2021-06-14 10:23:24 +00:00
|
|
|
}
|
1999-09-20 21:28:37 +00:00
|
|
|
}
|
2015-01-03 09:22:58 +00:00
|
|
|
|
2017-05-23 12:25:21 +00:00
|
|
|
ZVAL_COPY(&c.value, val);
|
2014-02-10 06:04:30 +00:00
|
|
|
zval_ptr_dtor(&val_free);
|
2018-06-23 18:51:49 +00:00
|
|
|
|
2014-12-21 03:03:49 +00:00
|
|
|
register_constant:
|
2018-07-26 09:58:07 +00:00
|
|
|
/* non persistent */
|
2022-11-28 16:12:07 +00:00
|
|
|
ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT);
|
2023-07-06 07:55:11 +00:00
|
|
|
c.name = zend_string_copy(name);
|
|
|
|
if (zend_register_constant(&c) == SUCCESS) {
|
2002-05-13 08:41:55 +00:00
|
|
|
RETURN_TRUE;
|
2000-07-28 09:44:46 +00:00
|
|
|
} else {
|
2002-05-13 08:41:55 +00:00
|
|
|
RETURN_FALSE;
|
2000-07-28 09:44:46 +00:00
|
|
|
}
|
1999-09-20 21:28:37 +00:00
|
|
|
}
|
2001-12-04 17:58:32 +00:00
|
|
|
/* }}} */
|
1999-09-20 21:28:37 +00:00
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Check whether a constant exists
|
2014-08-28 19:53:32 +00:00
|
|
|
Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
|
1999-09-20 21:28:37 +00:00
|
|
|
ZEND_FUNCTION(defined)
|
|
|
|
{
|
2014-04-24 20:56:15 +00:00
|
|
|
zend_string *name;
|
2006-05-09 23:53:23 +00:00
|
|
|
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(name)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2015-01-03 09:22:58 +00:00
|
|
|
|
2019-01-30 16:16:09 +00:00
|
|
|
if (zend_get_constant_ex(name, zend_get_executed_scope(), ZEND_FETCH_CLASS_SILENT)) {
|
2004-03-01 08:07:25 +00:00
|
|
|
RETURN_TRUE;
|
1999-09-20 21:28:37 +00:00
|
|
|
} else {
|
2004-03-01 08:07:25 +00:00
|
|
|
RETURN_FALSE;
|
1999-09-20 21:28:37 +00:00
|
|
|
}
|
|
|
|
}
|
2001-12-04 17:58:32 +00:00
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Retrieves the class name */
|
1999-09-20 21:28:37 +00:00
|
|
|
ZEND_FUNCTION(get_class)
|
|
|
|
{
|
2008-06-18 23:38:37 +00:00
|
|
|
zval *obj = NULL;
|
2006-05-09 23:53:23 +00:00
|
|
|
|
2016-08-11 22:21:04 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|o", &obj) == FAILURE) {
|
2019-12-30 16:35:46 +00:00
|
|
|
RETURN_THROWS();
|
2008-06-18 23:38:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!obj) {
|
2016-04-28 01:13:34 +00:00
|
|
|
zend_class_entry *scope = zend_get_executed_scope();
|
|
|
|
|
|
|
|
if (scope) {
|
2023-07-09 11:17:53 +00:00
|
|
|
zend_error(E_DEPRECATED, "Calling get_class() without arguments is deprecated");
|
|
|
|
if (UNEXPECTED(EG(exception))) {
|
|
|
|
RETURN_THROWS();
|
|
|
|
}
|
2016-04-28 01:13:34 +00:00
|
|
|
RETURN_STR_COPY(scope->name);
|
2004-03-14 22:40:25 +00:00
|
|
|
} else {
|
2020-03-29 22:40:18 +00:00
|
|
|
zend_throw_error(NULL, "get_class() without arguments must be called from within a class");
|
|
|
|
RETURN_THROWS();
|
2004-03-14 22:40:25 +00:00
|
|
|
}
|
|
|
|
}
|
2001-07-28 18:35:22 +00:00
|
|
|
|
2015-03-12 13:53:51 +00:00
|
|
|
RETURN_STR_COPY(Z_OBJCE_P(obj)->name);
|
1999-09-20 21:28:37 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Retrieves the "Late Static Binding" class name */
|
2007-09-29 07:28:34 +00:00
|
|
|
ZEND_FUNCTION(get_called_class)
|
|
|
|
{
|
2015-04-23 09:16:37 +00:00
|
|
|
zend_class_entry *called_scope;
|
|
|
|
|
2020-01-03 11:11:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2008-06-18 23:38:37 +00:00
|
|
|
|
2015-04-23 09:16:37 +00:00
|
|
|
called_scope = zend_get_called_scope(execute_data);
|
2020-03-29 22:40:18 +00:00
|
|
|
if (!called_scope) {
|
|
|
|
zend_throw_error(NULL, "get_called_class() must be called from within a class");
|
|
|
|
RETURN_THROWS();
|
2007-09-29 07:28:34 +00:00
|
|
|
}
|
2020-03-29 22:40:18 +00:00
|
|
|
|
|
|
|
RETURN_STR_COPY(called_scope->name);
|
2007-09-29 07:28:34 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Retrieves the parent class name for object or class or current scope or false if not in a scope. */
|
1999-09-20 21:28:37 +00:00
|
|
|
ZEND_FUNCTION(get_parent_class)
|
|
|
|
{
|
2001-03-26 19:03:06 +00:00
|
|
|
zend_class_entry *ce = NULL;
|
2015-01-03 09:22:58 +00:00
|
|
|
|
2020-06-30 09:14:58 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(0, 1)
|
|
|
|
Z_PARAM_OPTIONAL
|
2020-09-10 22:23:54 +00:00
|
|
|
Z_PARAM_OBJ_OR_CLASS_NAME(ce)
|
2020-06-30 09:14:58 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2008-06-18 23:38:37 +00:00
|
|
|
|
2020-06-30 09:14:58 +00:00
|
|
|
if (!ce) {
|
2023-07-09 11:17:53 +00:00
|
|
|
zend_error(E_DEPRECATED, "Calling get_parent_class() without arguments is deprecated");
|
|
|
|
if (UNEXPECTED(EG(exception))) {
|
|
|
|
RETURN_THROWS();
|
|
|
|
}
|
2016-04-28 01:13:34 +00:00
|
|
|
ce = zend_get_executed_scope();
|
2001-03-26 19:03:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ce && ce->parent) {
|
2015-03-12 13:53:51 +00:00
|
|
|
RETURN_STR_COPY(ce->parent->name);
|
2001-03-26 19:03:06 +00:00
|
|
|
} else {
|
1999-09-20 21:28:37 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
1999-12-15 21:26:43 +00:00
|
|
|
|
2021-01-15 11:30:54 +00:00
|
|
|
static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, bool only_subclass) /* {{{ */
|
1999-12-15 21:26:43 +00:00
|
|
|
{
|
2008-06-18 23:38:37 +00:00
|
|
|
zval *obj;
|
2014-02-10 06:04:30 +00:00
|
|
|
zend_string *class_name;
|
2003-03-05 11:14:44 +00:00
|
|
|
zend_class_entry *instance_ce;
|
2014-02-10 06:04:30 +00:00
|
|
|
zend_class_entry *ce;
|
2021-01-15 11:30:54 +00:00
|
|
|
bool allow_string = only_subclass;
|
|
|
|
bool retval;
|
1999-12-15 21:26:43 +00:00
|
|
|
|
2014-07-11 12:32:20 +00: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 05:27:45 +00:00
|
|
|
/*
|
2015-01-03 09:22:58 +00:00
|
|
|
* allow_string - is_a default is no, is_subclass_of is yes.
|
2011-11-09 05:27:45 +00: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-13 22:06:14 +00:00
|
|
|
instance_ce = zend_lookup_class(Z_STR_P(obj));
|
2014-02-10 06:04:30 +00:00
|
|
|
if (!instance_ce) {
|
2004-10-26 23:25:05 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2014-10-09 11:58:14 +00:00
|
|
|
} else if (Z_TYPE_P(obj) == IS_OBJECT) {
|
2011-07-04 14:55:39 +00:00
|
|
|
instance_ce = Z_OBJCE_P(obj);
|
2004-10-26 23:25:05 +00:00
|
|
|
} else {
|
2002-02-07 14:08:43 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
1999-12-15 21:26:43 +00:00
|
|
|
|
2015-01-19 14:10:01 +00:00
|
|
|
if (!only_subclass && EXPECTED(zend_string_equals(instance_ce->name, class_name))) {
|
|
|
|
retval = 1;
|
2003-03-05 11:14:44 +00:00
|
|
|
} else {
|
2019-05-24 12:41:38 +00:00
|
|
|
ce = zend_lookup_class_ex(class_name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
|
2015-01-19 14:10:01 +00:00
|
|
|
if (!ce) {
|
2003-03-05 11:14:44 +00:00
|
|
|
retval = 0;
|
2015-01-19 14:10:01 +00:00
|
|
|
} else {
|
|
|
|
if (only_subclass && instance_ce == ce) {
|
|
|
|
retval = 0;
|
|
|
|
} else {
|
|
|
|
retval = instanceof_function(instance_ce, ce);
|
|
|
|
}
|
1999-12-15 21:26:43 +00:00
|
|
|
}
|
1999-12-15 22:37:05 +00:00
|
|
|
}
|
2003-03-05 11:14:44 +00:00
|
|
|
|
|
|
|
RETURN_BOOL(retval);
|
1999-12-15 21:26:43 +00:00
|
|
|
}
|
2014-09-20 07:16:09 +00:00
|
|
|
/* }}} */
|
2002-02-01 22:55:02 +00:00
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Returns true if the object has this class as one of its parents */
|
2002-02-01 22:55:02 +00:00
|
|
|
ZEND_FUNCTION(is_subclass_of)
|
|
|
|
{
|
|
|
|
is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00: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-01 22:55:02 +00:00
|
|
|
ZEND_FUNCTION(is_a)
|
|
|
|
{
|
|
|
|
is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
|
|
|
|
}
|
1999-12-15 21:26:43 +00:00
|
|
|
/* }}} */
|
1999-09-20 21:28:37 +00:00
|
|
|
|
2004-10-12 22:19:43 +00:00
|
|
|
/* {{{ add_class_vars */
|
2020-08-28 13:41:27 +00:00
|
|
|
static void add_class_vars(zend_class_entry *scope, zend_class_entry *ce, bool statics, zval *return_value)
|
2004-10-12 22:19:43 +00:00
|
|
|
{
|
2010-05-24 14:11:39 +00:00
|
|
|
zend_property_info *prop_info;
|
2014-02-10 06:04:30 +00:00
|
|
|
zval *prop, prop_copy;
|
|
|
|
zend_string *key;
|
Added Inheritance Cache.
This is a new transparent technology that eliminates overhead of PHP class inheritance.
PHP classes are compiled and cached (by opcahce) separately, however their "linking" was done at run-time - on each request. The process of "linking" may involve a number of compatibility checks and borrowing methods/properties/constants form parent and traits. This takes significant time, but the result is the same on each request.
Inheritance Cache performs "linking" for unique set of all the depending classes (parent, interfaces, traits, property types, method types involved into compatibility checks) once and stores result in opcache shared memory. As a part of the this patch, I removed limitations for immutable classes (unresolved constants, typed properties and covariant type checks). So now all classes stored in opcache are "immutable". They may be lazily loaded into process memory, if necessary, but this usually occurs just once (on first linking).
The patch shows 8% improvement on Symphony "Hello World" app.
2021-02-09 19:53:57 +00:00
|
|
|
zval *default_properties_table = CE_DEFAULT_PROPERTIES_TABLE(ce);
|
2010-05-24 14:11:39 +00:00
|
|
|
|
2021-11-03 12:18:26 +00:00
|
|
|
ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
|
2018-09-11 08:56:45 +00:00
|
|
|
if (((prop_info->flags & ZEND_ACC_PROTECTED) &&
|
2019-03-18 14:17:29 +00:00
|
|
|
!zend_check_protected(prop_info->ce, scope)) ||
|
|
|
|
((prop_info->flags & ZEND_ACC_PRIVATE) &&
|
|
|
|
prop_info->ce != scope)) {
|
2010-05-24 14:11:39 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
prop = NULL;
|
2014-11-06 11:50:03 +00:00
|
|
|
if (statics && (prop_info->flags & ZEND_ACC_STATIC) != 0) {
|
|
|
|
prop = &ce->default_static_members_table[prop_info->offset];
|
2018-06-22 10:58:48 +00:00
|
|
|
ZVAL_DEINDIRECT(prop);
|
2014-11-06 11:50:03 +00:00
|
|
|
} else if (!statics && (prop_info->flags & ZEND_ACC_STATIC) == 0) {
|
Added Inheritance Cache.
This is a new transparent technology that eliminates overhead of PHP class inheritance.
PHP classes are compiled and cached (by opcahce) separately, however their "linking" was done at run-time - on each request. The process of "linking" may involve a number of compatibility checks and borrowing methods/properties/constants form parent and traits. This takes significant time, but the result is the same on each request.
Inheritance Cache performs "linking" for unique set of all the depending classes (parent, interfaces, traits, property types, method types involved into compatibility checks) once and stores result in opcache shared memory. As a part of the this patch, I removed limitations for immutable classes (unresolved constants, typed properties and covariant type checks). So now all classes stored in opcache are "immutable". They may be lazily loaded into process memory, if necessary, but this usually occurs just once (on first linking).
The patch shows 8% improvement on Symphony "Hello World" app.
2021-02-09 19:53:57 +00:00
|
|
|
prop = &default_properties_table[OBJ_PROP_TO_NUM(prop_info->offset)];
|
2010-05-24 14:11:39 +00:00
|
|
|
}
|
2019-07-23 10:41:24 +00:00
|
|
|
if (!prop) {
|
2010-05-24 14:11:39 +00:00
|
|
|
continue;
|
|
|
|
}
|
2004-10-12 22:19:43 +00:00
|
|
|
|
2019-07-23 10:41:24 +00: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-30 20:13:10 +00:00
|
|
|
prop = &prop_copy;
|
2006-05-09 23:53:23 +00:00
|
|
|
|
2010-05-24 14:11:39 +00:00
|
|
|
/* this is necessary to make it able to work with default array
|
|
|
|
* properties, returned to user */
|
2017-10-10 07:11:05 +00:00
|
|
|
if (Z_OPT_TYPE_P(prop) == IS_CONSTANT_AST) {
|
Added Inheritance Cache.
This is a new transparent technology that eliminates overhead of PHP class inheritance.
PHP classes are compiled and cached (by opcahce) separately, however their "linking" was done at run-time - on each request. The process of "linking" may involve a number of compatibility checks and borrowing methods/properties/constants form parent and traits. This takes significant time, but the result is the same on each request.
Inheritance Cache performs "linking" for unique set of all the depending classes (parent, interfaces, traits, property types, method types involved into compatibility checks) once and stores result in opcache shared memory. As a part of the this patch, I removed limitations for immutable classes (unresolved constants, typed properties and covariant type checks). So now all classes stored in opcache are "immutable". They may be lazily loaded into process memory, if necessary, but this usually occurs just once (on first linking).
The patch shows 8% improvement on Symphony "Hello World" app.
2021-02-09 19:53:57 +00:00
|
|
|
if (UNEXPECTED(zval_update_constant_ex(prop, ce) != SUCCESS)) {
|
2015-04-01 23:05:25 +00:00
|
|
|
return;
|
|
|
|
}
|
2004-10-12 22:19:43 +00:00
|
|
|
}
|
2010-05-24 14:11:39 +00:00
|
|
|
|
2014-06-02 20:36:31 +00:00
|
|
|
zend_hash_add_new(Z_ARRVAL_P(return_value), key, prop);
|
2014-04-18 15:18:11 +00:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
2004-10-12 22:19:43 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Returns an array of default properties of the class. */
|
2000-02-26 17:54:00 +00:00
|
|
|
ZEND_FUNCTION(get_class_vars)
|
|
|
|
{
|
2020-09-22 11:05:05 +00:00
|
|
|
zend_class_entry *ce = NULL, *scope;
|
2000-02-26 17:54:00 +00:00
|
|
|
|
2020-09-22 11:05:05 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "C", &ce) == FAILURE) {
|
2019-12-30 16:35:46 +00:00
|
|
|
RETURN_THROWS();
|
2000-02-26 17:54:00 +00:00
|
|
|
}
|
|
|
|
|
2020-09-22 11:05:05 +00: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-01 23:05:25 +00:00
|
|
|
}
|
2000-02-26 17:54:00 +00:00
|
|
|
}
|
2020-09-22 11:05:05 +00:00
|
|
|
|
|
|
|
scope = zend_get_executed_scope();
|
|
|
|
add_class_vars(scope, ce, 0, return_value);
|
|
|
|
add_class_vars(scope, ce, 1, return_value);
|
2000-02-26 17:54:00 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Returns an array of object properties */
|
2000-02-26 17:54:00 +00:00
|
|
|
ZEND_FUNCTION(get_object_vars)
|
|
|
|
{
|
2014-02-10 06:04:30 +00:00
|
|
|
zval *value;
|
2003-11-10 21:03:04 +00:00
|
|
|
HashTable *properties;
|
2014-02-10 06:04:30 +00:00
|
|
|
zend_string *key;
|
2007-07-24 11:39:56 +00:00
|
|
|
zend_object *zobj;
|
2016-11-22 19:49:12 +00:00
|
|
|
zend_ulong num_key;
|
2000-02-26 17:54:00 +00:00
|
|
|
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
2021-01-02 19:07:45 +00:00
|
|
|
Z_PARAM_OBJ(zobj)
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2000-02-26 17:54:00 +00:00
|
|
|
|
2024-07-14 09:55:03 +00:00
|
|
|
zval obj_zv;
|
|
|
|
ZVAL_OBJ(&obj_zv, zobj);
|
|
|
|
properties = zend_get_properties_for(&obj_zv, ZEND_PROP_PURPOSE_GET_OBJECT_VARS);
|
2006-02-07 00:33:13 +00:00
|
|
|
if (properties == NULL) {
|
2019-06-06 07:49:25 +00:00
|
|
|
RETURN_EMPTY_ARRAY();
|
2006-02-07 00:33:13 +00:00
|
|
|
}
|
|
|
|
|
2017-10-05 22:34:50 +00:00
|
|
|
if (!zobj->ce->default_properties_count && properties == zobj->properties && !GC_IS_RECURSIVE(properties)) {
|
2014-12-22 23:49:47 +00:00
|
|
|
/* fast copy */
|
2024-07-14 09:55:03 +00:00
|
|
|
bool always_duplicate = zobj->handlers != &std_object_handlers;
|
|
|
|
RETVAL_ARR(zend_proptable_to_symtable(properties, always_duplicate));
|
2014-12-22 23:49:47 +00:00
|
|
|
} else {
|
|
|
|
array_init_size(return_value, zend_hash_num_elements(properties));
|
|
|
|
|
2023-01-02 14:34:03 +00:00
|
|
|
ZEND_HASH_FOREACH_KEY_VAL(properties, num_key, key, value) {
|
2021-01-15 11:30:54 +00:00
|
|
|
bool is_dynamic = 1;
|
2024-07-14 09:55:03 +00:00
|
|
|
zval tmp;
|
|
|
|
ZVAL_UNDEF(&tmp);
|
2016-11-22 19:49:12 +00:00
|
|
|
if (Z_TYPE_P(value) == IS_INDIRECT) {
|
|
|
|
value = Z_INDIRECT_P(value);
|
|
|
|
if (UNEXPECTED(Z_ISUNDEF_P(value))) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2024-07-14 09:55:03 +00:00
|
|
|
is_dynamic = 0;
|
|
|
|
} else if (Z_TYPE_P(value) == IS_PTR) {
|
2018-10-20 15:11:17 +00:00
|
|
|
is_dynamic = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key && zend_check_property_access(zobj, key, is_dynamic) == FAILURE) {
|
|
|
|
continue;
|
2016-11-22 19:49:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Z_ISREF_P(value) && Z_REFCOUNT_P(value) == 1) {
|
|
|
|
value = Z_REFVAL_P(value);
|
|
|
|
}
|
2024-07-14 09:55:03 +00:00
|
|
|
if (Z_TYPE_P(value) == IS_PTR) {
|
|
|
|
/* value is IS_PTR for properties with hooks. */
|
|
|
|
zend_property_info *prop_info = Z_PTR_P(value);
|
|
|
|
if ((prop_info->flags & ZEND_ACC_VIRTUAL) && !prop_info->hooks[ZEND_PROPERTY_HOOK_GET]) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const char *unmangled_name_cstr = zend_get_unmangled_property_name(prop_info->name);
|
|
|
|
zend_string *unmangled_name = zend_string_init(unmangled_name_cstr, strlen(unmangled_name_cstr), false);
|
|
|
|
zend_read_property_ex(prop_info->ce, zobj, unmangled_name, /* silent */ true, &tmp);
|
|
|
|
zend_string_release_ex(unmangled_name, false);
|
|
|
|
if (EG(exception)) {
|
|
|
|
zend_release_properties(properties);
|
|
|
|
zval_ptr_dtor(return_value);
|
|
|
|
ZVAL_UNDEF(return_value);
|
|
|
|
RETURN_THROWS();
|
|
|
|
}
|
|
|
|
value = &tmp;
|
|
|
|
}
|
2016-11-22 19:49:12 +00:00
|
|
|
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 15:11:17 +00:00
|
|
|
} else if (!is_dynamic && ZSTR_VAL(key)[0] == 0) {
|
2016-11-22 19:49:12 +00: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-07 20:29:57 +00:00
|
|
|
zend_symtable_add_new(Z_ARRVAL_P(return_value), key, value);
|
2004-10-04 08:59:29 +00:00
|
|
|
}
|
2024-07-14 09:55:03 +00:00
|
|
|
zval_ptr_dtor(&tmp);
|
2014-12-22 23:49:47 +00:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
|
|
|
}
|
2024-07-14 09:55:03 +00:00
|
|
|
zend_release_properties(properties);
|
2000-02-26 17:54:00 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Returns an array of mangled object properties. Does not respect property visibility. */
|
2019-05-14 12:27:10 +00:00
|
|
|
ZEND_FUNCTION(get_mangled_object_vars)
|
|
|
|
{
|
2021-01-02 19:07:45 +00:00
|
|
|
zend_object *obj;
|
2019-05-14 12:27:10 +00:00
|
|
|
HashTable *properties;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
2021-01-02 19:07:45 +00:00
|
|
|
Z_PARAM_OBJ(obj)
|
2019-05-14 12:27:10 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
2021-01-02 19:07:45 +00:00
|
|
|
properties = obj->handlers->get_properties(obj);
|
2019-05-14 12:27:10 +00:00
|
|
|
if (!properties) {
|
|
|
|
ZVAL_EMPTY_ARRAY(return_value);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
properties = zend_proptable_to_symtable(properties,
|
2021-01-02 19:07:45 +00:00
|
|
|
(obj->ce->default_properties_count ||
|
|
|
|
obj->handlers != &std_object_handlers ||
|
2019-05-14 12:27:10 +00:00
|
|
|
GC_IS_RECURSIVE(properties)));
|
|
|
|
RETURN_ARR(properties);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Returns an array of method names for class or class instance. */
|
2000-03-23 17:47:28 +00:00
|
|
|
ZEND_FUNCTION(get_class_methods)
|
|
|
|
{
|
2014-02-10 06:04:30 +00:00
|
|
|
zval method_name;
|
|
|
|
zend_class_entry *ce = NULL;
|
2016-04-28 01:13:34 +00:00
|
|
|
zend_class_entry *scope;
|
2003-09-18 16:20:42 +00:00
|
|
|
zend_function *mptr;
|
2000-03-23 17:47:28 +00:00
|
|
|
|
2020-07-01 14:49:57 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
2020-09-10 22:23:54 +00:00
|
|
|
Z_PARAM_OBJ_OR_CLASS_NAME(ce)
|
2020-07-01 14:49:57 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2001-03-26 20:14:21 +00:00
|
|
|
|
|
|
|
array_init(return_value);
|
2016-04-28 01:13:34 +00:00
|
|
|
scope = zend_get_executed_scope();
|
2003-09-18 16:20:42 +00:00
|
|
|
|
2021-11-03 12:18:26 +00:00
|
|
|
ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, mptr) {
|
2015-01-03 09:22:58 +00:00
|
|
|
if ((mptr->common.fn_flags & ZEND_ACC_PUBLIC)
|
2016-04-28 01:13:34 +00:00
|
|
|
|| (scope &&
|
2019-03-18 14:17:29 +00:00
|
|
|
(((mptr->common.fn_flags & ZEND_ACC_PROTECTED) &&
|
|
|
|
zend_check_protected(mptr->common.scope, scope))
|
2005-05-03 08:52:04 +00:00
|
|
|
|| ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) &&
|
2019-03-18 14:17:29 +00:00
|
|
|
scope == mptr->common.scope)))
|
2019-02-14 10:28:13 +00:00
|
|
|
) {
|
2020-03-02 10:07:57 +00: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 11:01:08 +00:00
|
|
|
}
|
2014-04-18 15:18:11 +00:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
2000-03-23 17:47:28 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
2003-11-27 17:06:26 +00:00
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Checks if the class method exists */
|
1999-09-20 21:28:37 +00:00
|
|
|
ZEND_FUNCTION(method_exists)
|
|
|
|
{
|
2015-01-03 09:22:58 +00:00
|
|
|
zval *klass;
|
2014-02-10 06:04:30 +00:00
|
|
|
zend_string *method_name;
|
|
|
|
zend_string *lcname;
|
2019-09-03 11:14:33 +00:00
|
|
|
zend_class_entry *ce;
|
|
|
|
zend_function *func;
|
2006-05-09 23:53:23 +00:00
|
|
|
|
2023-02-25 17:15:52 +00:00
|
|
|
/* We do not use Z_PARAM_OBJ_OR_STR here to be able to exclude int, float, and bool which are bogus class names */
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 2)
|
|
|
|
Z_PARAM_ZVAL(klass)
|
|
|
|
Z_PARAM_STR(method_name)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2017-12-31 04:35:25 +00:00
|
|
|
|
2008-06-18 23:38:37 +00:00
|
|
|
if (Z_TYPE_P(klass) == IS_OBJECT) {
|
|
|
|
ce = Z_OBJCE_P(klass);
|
|
|
|
} else if (Z_TYPE_P(klass) == IS_STRING) {
|
2014-12-13 22:06:14 +00:00
|
|
|
if ((ce = zend_lookup_class(Z_STR_P(klass))) == NULL) {
|
2014-03-03 08:10:15 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2005-02-27 15:03:09 +00:00
|
|
|
} else {
|
2023-01-23 09:52:14 +00:00
|
|
|
zend_argument_type_error(1, "must be of type object|string, %s given", zend_zval_value_name(klass));
|
2020-04-09 08:55:53 +00:00
|
|
|
RETURN_THROWS();
|
2002-02-07 14:08:43 +00:00
|
|
|
}
|
|
|
|
|
2014-12-24 12:04:51 +00:00
|
|
|
lcname = zend_string_tolower(method_name);
|
2019-09-03 11:14:33 +00:00
|
|
|
func = zend_hash_find_ptr(&ce->function_table, lcname);
|
|
|
|
zend_string_release_ex(lcname, 0);
|
|
|
|
|
|
|
|
if (func) {
|
2019-10-04 10:38:18 +00: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 11:14:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Z_TYPE_P(klass) == IS_OBJECT) {
|
2018-09-19 07:37:04 +00:00
|
|
|
zend_object *obj = Z_OBJ_P(klass);
|
2019-09-03 11:14:33 +00:00
|
|
|
func = Z_OBJ_HT_P(klass)->get_method(&obj, method_name, NULL);
|
2018-09-19 07:37:04 +00:00
|
|
|
if (func != NULL) {
|
2015-04-10 20:01:00 +00:00
|
|
|
if (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
|
2021-05-22 09:06:45 +00:00
|
|
|
/* Returns true for the fake Closure's __invoke */
|
2014-08-25 20:40:58 +00:00
|
|
|
RETVAL_BOOL(func->common.scope == zend_ce_closure
|
2021-05-22 09:06:45 +00:00
|
|
|
&& zend_string_equals_literal_ci(method_name, ZEND_INVOKE_FUNC_NAME));
|
2015-01-03 09:22:58 +00:00
|
|
|
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(func->common.function_name, 0);
|
2015-04-10 20:01:00 +00:00
|
|
|
zend_free_trampoline(func);
|
2010-06-11 23:20:13 +00:00
|
|
|
return;
|
2005-04-26 08:47:31 +00:00
|
|
|
}
|
2005-02-28 18:53:33 +00:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
2021-05-22 09:06:45 +00:00
|
|
|
} else {
|
|
|
|
/* Returns true for fake Closure::__invoke */
|
|
|
|
if (ce == zend_ce_closure
|
|
|
|
&& zend_string_equals_literal_ci(method_name, ZEND_INVOKE_FUNC_NAME)) {
|
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
1999-09-20 21:28:37 +00:00
|
|
|
}
|
2005-02-28 18:53:33 +00:00
|
|
|
RETURN_FALSE;
|
1999-09-20 21:28:37 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2024-02-06 16:02:00 +00:00
|
|
|
static void _property_exists(zval *return_value, zval *object, zend_string *property)
|
2005-04-08 13:33:15 +00:00
|
|
|
{
|
2014-02-10 06:04:30 +00:00
|
|
|
zend_class_entry *ce;
|
2005-04-08 13:33:15 +00:00
|
|
|
zend_property_info *property_info;
|
|
|
|
|
2008-08-18 17:44:02 +00:00
|
|
|
if (Z_TYPE_P(object) == IS_STRING) {
|
2014-12-13 22:06:14 +00:00
|
|
|
ce = zend_lookup_class(Z_STR_P(object));
|
2014-02-18 21:12:05 +00:00
|
|
|
if (!ce) {
|
|
|
|
RETURN_FALSE;
|
2015-01-03 09:22:58 +00:00
|
|
|
}
|
2008-08-18 17:44:02 +00:00
|
|
|
} else if (Z_TYPE_P(object) == IS_OBJECT) {
|
|
|
|
ce = Z_OBJCE_P(object);
|
|
|
|
} else {
|
2023-01-23 09:52:14 +00:00
|
|
|
zend_argument_type_error(1, "must be of type object|string, %s given", zend_zval_value_name(object));
|
2020-03-29 22:40:18 +00:00
|
|
|
RETURN_THROWS();
|
2008-08-18 17:44:02 +00:00
|
|
|
}
|
|
|
|
|
2018-09-11 08:56:45 +00: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-18 17:44:02 +00:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
2006-05-09 23:53:23 +00:00
|
|
|
|
2008-08-18 17:44:02 +00:00
|
|
|
if (Z_TYPE_P(object) == IS_OBJECT &&
|
2019-01-31 15:47:58 +00:00
|
|
|
Z_OBJ_HANDLER_P(object, has_property)(Z_OBJ_P(object), property, 2, NULL)) {
|
2008-08-18 17:44:02 +00:00
|
|
|
RETURN_TRUE;
|
2005-04-08 13:33:15 +00:00
|
|
|
}
|
2008-08-18 17:44:02 +00:00
|
|
|
RETURN_FALSE;
|
2005-04-08 13:33:15 +00:00
|
|
|
}
|
2024-02-06 16:02:00 +00:00
|
|
|
|
|
|
|
/* {{{ Checks if the object or class has a property */
|
|
|
|
ZEND_FUNCTION(property_exists)
|
|
|
|
{
|
|
|
|
zval *object;
|
|
|
|
zend_string *property;
|
|
|
|
|
|
|
|
/* We do not use Z_PARAM_OBJ_OR_STR here to be able to exclude int, float, and bool which are bogus class names */
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zS", &object, &property) == FAILURE) {
|
|
|
|
RETURN_THROWS();
|
|
|
|
}
|
|
|
|
|
|
|
|
_property_exists(return_value, object, property);
|
|
|
|
}
|
2005-04-08 13:33:15 +00:00
|
|
|
/* }}} */
|
|
|
|
|
2024-02-06 16:02:00 +00:00
|
|
|
ZEND_FRAMELESS_FUNCTION(property_exists, 2)
|
|
|
|
{
|
|
|
|
zval *object;
|
|
|
|
zval property_tmp;
|
|
|
|
zend_string *property;
|
|
|
|
|
|
|
|
Z_FLF_PARAM_ZVAL(1, object);
|
|
|
|
Z_FLF_PARAM_STR(2, property, property_tmp);
|
|
|
|
|
|
|
|
_property_exists(return_value, object, property);
|
|
|
|
|
|
|
|
flf_clean:;
|
|
|
|
Z_FLF_PARAM_FREE_STR(2, property_tmp)
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void _class_exists_impl(zval *return_value, zend_string *name, bool autoload, int flags, int skip_flags) /* {{{ */
|
1999-12-14 21:15:24 +00:00
|
|
|
{
|
2019-03-18 14:17:29 +00:00
|
|
|
zend_string *lcname;
|
2014-02-10 06:04:30 +00:00
|
|
|
zend_class_entry *ce;
|
2003-04-08 18:22:32 +00:00
|
|
|
|
2021-04-08 20:37:40 +00:00
|
|
|
if (ZSTR_HAS_CE_CACHE(name)) {
|
|
|
|
ce = ZSTR_GET_CE_CACHE(name);
|
|
|
|
if (ce) {
|
|
|
|
RETURN_BOOL(((ce->ce_flags & flags) == flags) && !(ce->ce_flags & skip_flags));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-04-27 18:09:40 +00:00
|
|
|
if (!autoload) {
|
2019-03-18 14:17:29 +00:00
|
|
|
if (ZSTR_VAL(name)[0] == '\\') {
|
2014-02-10 06:04:30 +00:00
|
|
|
/* Ignore leading "\" */
|
2019-03-18 14:17:29 +00: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 06:04:30 +00:00
|
|
|
} else {
|
2019-03-18 14:17:29 +00:00
|
|
|
lcname = zend_string_tolower(name);
|
2008-12-09 19:17:11 +00:00
|
|
|
}
|
2015-02-12 22:19:14 +00:00
|
|
|
|
2019-03-18 14:17:29 +00:00
|
|
|
ce = zend_hash_find_ptr(EG(class_table), lcname);
|
|
|
|
zend_string_release_ex(lcname, 0);
|
2015-02-12 22:31:01 +00:00
|
|
|
} else {
|
2019-03-18 14:17:29 +00:00
|
|
|
ce = zend_lookup_class(name);
|
2004-04-27 18:09:40 +00:00
|
|
|
}
|
2003-11-24 18:13:29 +00:00
|
|
|
|
2021-06-29 08:04:10 +00:00
|
|
|
if (ce) {
|
2019-12-24 06:20:55 +00:00
|
|
|
RETURN_BOOL(((ce->ce_flags & flags) == flags) && !(ce->ce_flags & skip_flags));
|
2004-08-25 00:41:43 +00:00
|
|
|
} else {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
}
|
2019-03-18 14:17:29 +00:00
|
|
|
/* {{{ */
|
|
|
|
|
2024-02-06 16:02:00 +00:00
|
|
|
static inline void class_exists_impl(INTERNAL_FUNCTION_PARAMETERS, int flags, int skip_flags) /* {{{ */
|
|
|
|
{
|
|
|
|
zend_string *name;
|
|
|
|
bool autoload = true;
|
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
|
|
|
Z_PARAM_STR(name)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_BOOL(autoload)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
|
|
|
_class_exists_impl(return_value, name, autoload, flags, skip_flags);
|
|
|
|
}
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Checks if the class exists */
|
2019-03-18 14:17:29 +00:00
|
|
|
ZEND_FUNCTION(class_exists)
|
|
|
|
{
|
2019-12-24 06:04:19 +00:00
|
|
|
class_exists_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED, ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT);
|
2019-03-18 14:17:29 +00:00
|
|
|
}
|
2004-08-25 00:41:43 +00:00
|
|
|
/* }}} */
|
|
|
|
|
2024-02-06 16:02:00 +00:00
|
|
|
ZEND_FRAMELESS_FUNCTION(class_exists, 1)
|
|
|
|
{
|
|
|
|
zval name_tmp;
|
|
|
|
zend_string *name;
|
|
|
|
|
|
|
|
Z_FLF_PARAM_STR(1, name, name_tmp);
|
|
|
|
|
|
|
|
_class_exists_impl(return_value, name, /* autoload */ true, ZEND_ACC_LINKED, ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT);
|
|
|
|
|
|
|
|
flf_clean:
|
|
|
|
Z_FLF_PARAM_FREE_STR(1, name_tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_FRAMELESS_FUNCTION(class_exists, 2)
|
|
|
|
{
|
|
|
|
zval name_tmp;
|
|
|
|
zend_string *name;
|
|
|
|
bool autoload;
|
|
|
|
|
|
|
|
Z_FLF_PARAM_STR(1, name, name_tmp);
|
|
|
|
Z_FLF_PARAM_BOOL(2, autoload);
|
|
|
|
|
|
|
|
_class_exists_impl(return_value, name, autoload, ZEND_ACC_LINKED, ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT);
|
|
|
|
|
|
|
|
flf_clean:
|
|
|
|
Z_FLF_PARAM_FREE_STR(1, name_tmp);
|
|
|
|
}
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Checks if the class exists */
|
2004-08-25 00:41:43 +00:00
|
|
|
ZEND_FUNCTION(interface_exists)
|
|
|
|
{
|
2019-12-24 06:20:55 +00:00
|
|
|
class_exists_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED|ZEND_ACC_INTERFACE, 0);
|
1999-12-14 21:15:24 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Checks if the trait exists */
|
2011-01-09 19:57:41 +00:00
|
|
|
ZEND_FUNCTION(trait_exists)
|
|
|
|
{
|
2019-03-18 14:17:29 +00:00
|
|
|
class_exists_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_TRAIT, 0);
|
2011-01-09 19:57:41 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-06-10 21:10:18 +00:00
|
|
|
ZEND_FUNCTION(enum_exists)
|
|
|
|
{
|
|
|
|
class_exists_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_ENUM, 0);
|
|
|
|
}
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Checks if the function exists */
|
1999-12-14 21:15:24 +00:00
|
|
|
ZEND_FUNCTION(function_exists)
|
|
|
|
{
|
2014-12-24 12:04:51 +00:00
|
|
|
zend_string *name;
|
2021-01-15 11:30:54 +00:00
|
|
|
bool exists;
|
2014-02-10 06:04:30 +00:00
|
|
|
zend_string *lcname;
|
2015-01-03 09:22:58 +00:00
|
|
|
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
2014-12-24 12:04:51 +00:00
|
|
|
Z_PARAM_STR(name)
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
1999-12-22 18:49:23 +00:00
|
|
|
|
2015-06-30 10:59:27 +00:00
|
|
|
if (ZSTR_VAL(name)[0] == '\\') {
|
2014-02-10 06:04:30 +00:00
|
|
|
/* Ignore leading "\" */
|
2015-06-30 10:59:27 +00: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 06:04:30 +00:00
|
|
|
} else {
|
2014-12-24 12:04:51 +00:00
|
|
|
lcname = zend_string_tolower(name);
|
2009-03-08 17:28:39 +00:00
|
|
|
}
|
2015-01-03 09:22:58 +00: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 11:17:37 +00:00
|
|
|
exists = zend_hash_exists(EG(function_table), lcname);
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(lcname, 0);
|
1999-12-22 18:49:23 +00: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 11:17:37 +00:00
|
|
|
RETURN_BOOL(exists);
|
1999-12-14 21:15:24 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Creates an alias for user defined class */
|
2008-05-12 07:11:55 +00:00
|
|
|
ZEND_FUNCTION(class_alias)
|
|
|
|
{
|
2014-02-10 06:04:30 +00:00
|
|
|
zend_string *class_name;
|
2021-02-24 16:13:11 +00:00
|
|
|
zend_string *alias_name;
|
2014-02-10 06:04:30 +00:00
|
|
|
zend_class_entry *ce;
|
2021-01-15 11:30:54 +00:00
|
|
|
bool autoload = 1;
|
2008-05-12 07:11:55 +00:00
|
|
|
|
2021-02-24 16:13:11 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 3)
|
|
|
|
Z_PARAM_STR(class_name)
|
|
|
|
Z_PARAM_STR(alias_name)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_BOOL(autoload)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2008-05-12 07:11:55 +00:00
|
|
|
|
2019-05-24 12:41:38 +00:00
|
|
|
ce = zend_lookup_class_ex(class_name, NULL, !autoload ? ZEND_FETCH_CLASS_NO_AUTOLOAD : 0);
|
2015-01-03 09:22:58 +00:00
|
|
|
|
2014-02-10 06:04:30 +00:00
|
|
|
if (ce) {
|
2023-02-22 10:47:32 +00:00
|
|
|
if (zend_register_class_alias_ex(ZSTR_VAL(alias_name), ZSTR_LEN(alias_name), ce, false) == SUCCESS) {
|
|
|
|
RETURN_TRUE;
|
2008-05-12 07:11:55 +00:00
|
|
|
} else {
|
2024-04-18 21:48:45 +00:00
|
|
|
zend_class_redeclaration_error_ex(E_WARNING, alias_name, ce);
|
2023-02-22 10:47:32 +00:00
|
|
|
RETURN_FALSE;
|
2008-05-12 07:11:55 +00:00
|
|
|
}
|
|
|
|
} else {
|
2020-05-26 12:10:57 +00:00
|
|
|
zend_error(E_WARNING, "Class \"%s\" not found", ZSTR_VAL(class_name));
|
2008-05-12 07:11:55 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Returns an array with the file names that were include_once()'d */
|
2000-03-10 16:36:30 +00:00
|
|
|
ZEND_FUNCTION(get_included_files)
|
1999-12-04 14:26:26 +00:00
|
|
|
{
|
2014-02-10 06:04:30 +00:00
|
|
|
zend_string *entry;
|
2011-09-13 13:29:35 +00:00
|
|
|
|
2020-01-03 11:11:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2000-05-01 16:22:00 +00:00
|
|
|
|
1999-12-04 14:26:26 +00:00
|
|
|
array_init(return_value);
|
2021-11-03 12:18:26 +00:00
|
|
|
ZEND_HASH_MAP_FOREACH_STR_KEY(&EG(included_files), entry) {
|
2014-04-18 15:18:11 +00:00
|
|
|
if (entry) {
|
2014-08-25 17:24:55 +00:00
|
|
|
add_next_index_str(return_value, zend_string_copy(entry));
|
2014-04-18 15:18:11 +00:00
|
|
|
}
|
|
|
|
} ZEND_HASH_FOREACH_END();
|
2001-04-30 13:05:11 +00:00
|
|
|
}
|
2000-04-19 13:15:13 +00:00
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Generates a user-level error/warning/notice message */
|
2000-06-02 12:36:54 +00:00
|
|
|
ZEND_FUNCTION(trigger_error)
|
2000-04-19 13:15:13 +00:00
|
|
|
{
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long error_type = E_USER_NOTICE;
|
2024-01-15 19:21:30 +00:00
|
|
|
zend_string *message;
|
2000-04-19 13:15:13 +00:00
|
|
|
|
2024-01-15 19:21:30 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &message, &error_type) == FAILURE) {
|
2019-12-30 16:35:46 +00:00
|
|
|
RETURN_THROWS();
|
2008-06-18 23:38:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (error_type) {
|
|
|
|
case E_USER_ERROR:
|
|
|
|
case E_USER_WARNING:
|
|
|
|
case E_USER_NOTICE:
|
2008-07-21 09:41:00 +00:00
|
|
|
case E_USER_DEPRECATED:
|
2000-04-19 13:15:13 +00:00
|
|
|
break;
|
2000-09-05 12:08:41 +00:00
|
|
|
default:
|
2020-03-29 22:40:18 +00: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-18 23:38:37 +00:00
|
|
|
break;
|
2000-04-19 13:15:13 +00:00
|
|
|
}
|
2008-06-18 23:38:37 +00:00
|
|
|
|
2024-01-15 19:21:30 +00:00
|
|
|
zend_error_zstr_at(error_type, zend_get_executed_filename_ex(), zend_get_executed_lineno(), message);
|
2020-03-29 22:40:18 +00:00
|
|
|
// TODO Change to void
|
2000-04-19 13:15:13 +00:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
2000-04-19 15:08:06 +00:00
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Sets a user-defined error handler function. Returns the previously defined error handler, or false on error */
|
2000-06-02 12:36:54 +00:00
|
|
|
ZEND_FUNCTION(set_error_handler)
|
2000-04-19 15:08:06 +00:00
|
|
|
{
|
2020-07-08 16:36:46 +00:00
|
|
|
zend_fcall_info fci;
|
|
|
|
zend_fcall_info_cache fcc;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long error_type = E_ALL;
|
2006-05-09 23:53:23 +00:00
|
|
|
|
2021-02-24 16:13:11 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
|
|
|
Z_PARAM_FUNC_OR_NULL(fci, fcc)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_LONG(error_type)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2000-04-19 15:08:06 +00:00
|
|
|
|
2014-02-10 06:04:30 +00:00
|
|
|
if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
|
2015-06-12 09:33:23 +00:00
|
|
|
ZVAL_COPY(return_value, &EG(user_error_handler));
|
2012-09-22 19:41:51 +00:00
|
|
|
}
|
2012-03-24 11:26:02 +00:00
|
|
|
|
2020-02-24 20:32:02 +00: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-08 16:36:46 +00:00
|
|
|
if (!ZEND_FCI_INITIALIZED(fci)) { /* unset user-defined handler */
|
2014-02-10 06:04:30 +00:00
|
|
|
ZVAL_UNDEF(&EG(user_error_handler));
|
2012-03-24 12:10:51 +00:00
|
|
|
return;
|
2012-03-24 11:26:02 +00:00
|
|
|
}
|
2012-09-22 19:41:51 +00:00
|
|
|
|
2020-07-08 16:36:46 +00:00
|
|
|
ZVAL_COPY(&EG(user_error_handler), &(fci.function_name));
|
2012-09-22 19:41:51 +00:00
|
|
|
EG(user_error_handler_error_reporting) = (int)error_type;
|
2000-04-19 15:08:06 +00:00
|
|
|
}
|
2000-06-02 12:36:54 +00:00
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Restores the previously defined error handler function */
|
2000-06-17 18:04:58 +00:00
|
|
|
ZEND_FUNCTION(restore_error_handler)
|
|
|
|
{
|
2020-01-03 11:11:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2015-03-30 15:57:32 +00:00
|
|
|
|
2014-02-10 06:04:30 +00:00
|
|
|
if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
|
|
|
|
zval zeh;
|
2015-01-03 09:22:58 +00:00
|
|
|
|
2014-02-10 06:04:30 +00:00
|
|
|
ZVAL_COPY_VALUE(&zeh, &EG(user_error_handler));
|
|
|
|
ZVAL_UNDEF(&EG(user_error_handler));
|
2004-05-23 20:27:32 +00:00
|
|
|
zval_ptr_dtor(&zeh);
|
2000-06-17 18:04:58 +00:00
|
|
|
}
|
2004-05-23 20:27:32 +00:00
|
|
|
|
2014-02-10 06:04:30 +00:00
|
|
|
if (zend_stack_is_empty(&EG(user_error_handlers))) {
|
|
|
|
ZVAL_UNDEF(&EG(user_error_handler));
|
2000-06-17 18:04:58 +00:00
|
|
|
} else {
|
2014-02-10 06:04:30 +00:00
|
|
|
zval *tmp;
|
2004-01-10 11:43:42 +00: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-04-30 18:48:02 +00:00
|
|
|
tmp = zend_stack_top(&EG(user_error_handlers));
|
2014-02-10 06:04:30 +00:00
|
|
|
ZVAL_COPY_VALUE(&EG(user_error_handler), tmp);
|
|
|
|
zend_stack_del_top(&EG(user_error_handlers));
|
2000-06-17 18:04:58 +00:00
|
|
|
}
|
2020-03-29 22:40:18 +00:00
|
|
|
|
|
|
|
// TODO Change to void
|
2000-06-17 18:04:58 +00:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
2002-07-05 02:34:54 +00:00
|
|
|
/* }}} */
|
2000-06-17 18:04:58 +00:00
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Sets a user-defined exception handler function. Returns the previously defined exception handler, or false on error */
|
2002-08-16 00:41:37 +00:00
|
|
|
ZEND_FUNCTION(set_exception_handler)
|
|
|
|
{
|
2020-07-08 16:36:46 +00:00
|
|
|
zend_fcall_info fci;
|
|
|
|
zend_fcall_info_cache fcc;
|
2002-08-16 00:41:37 +00:00
|
|
|
|
2021-02-24 16:13:11 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_FUNC_OR_NULL(fci, fcc)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2002-08-16 00:41:37 +00:00
|
|
|
|
2014-02-10 06:04:30 +00:00
|
|
|
if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
|
2015-06-12 09:33:23 +00:00
|
|
|
ZVAL_COPY(return_value, &EG(user_exception_handler));
|
2012-09-22 19:41:51 +00:00
|
|
|
}
|
2002-08-16 00:41:37 +00:00
|
|
|
|
2020-02-24 20:32:02 +00:00
|
|
|
zend_stack_push(&EG(user_exception_handlers), &EG(user_exception_handler));
|
|
|
|
|
2020-07-08 16:36:46 +00:00
|
|
|
if (!ZEND_FCI_INITIALIZED(fci)) { /* unset user-defined handler */
|
2014-02-10 06:04:30 +00:00
|
|
|
ZVAL_UNDEF(&EG(user_exception_handler));
|
2012-03-24 12:10:51 +00:00
|
|
|
return;
|
2002-08-16 00:41:37 +00:00
|
|
|
}
|
2012-09-22 19:41:51 +00:00
|
|
|
|
2020-07-08 16:36:46 +00:00
|
|
|
ZVAL_COPY(&EG(user_exception_handler), &(fci.function_name));
|
2002-08-16 00:41:37 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Restores the previously defined exception handler function */
|
2002-08-16 00:41:37 +00:00
|
|
|
ZEND_FUNCTION(restore_exception_handler)
|
|
|
|
{
|
2020-01-03 11:11:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2015-03-30 15:57:32 +00:00
|
|
|
|
2014-02-10 06:04:30 +00:00
|
|
|
if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
|
2002-08-16 00:41:37 +00:00
|
|
|
zval_ptr_dtor(&EG(user_exception_handler));
|
|
|
|
}
|
2014-02-10 06:04:30 +00:00
|
|
|
if (zend_stack_is_empty(&EG(user_exception_handlers))) {
|
|
|
|
ZVAL_UNDEF(&EG(user_exception_handler));
|
2002-08-16 00:41:37 +00:00
|
|
|
} else {
|
2014-04-30 18:48:02 +00:00
|
|
|
zval *tmp = zend_stack_top(&EG(user_exception_handlers));
|
2014-02-10 06:04:30 +00:00
|
|
|
ZVAL_COPY_VALUE(&EG(user_exception_handler), tmp);
|
|
|
|
zend_stack_del_top(&EG(user_exception_handlers));
|
2002-08-16 00:41:37 +00:00
|
|
|
}
|
2020-03-29 22:40:18 +00:00
|
|
|
|
|
|
|
// TODO Change to void
|
2002-08-16 00:41:37 +00:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2021-04-06 13:18:47 +00:00
|
|
|
static inline void get_declared_class_impl(INTERNAL_FUNCTION_PARAMETERS, int flags) /* {{{ */
|
2010-05-06 15:18:20 +00:00
|
|
|
{
|
2018-12-18 23:49:56 +00:00
|
|
|
zend_string *key;
|
2021-04-06 13:18:47 +00:00
|
|
|
zval *zv;
|
2018-12-18 23:49:56 +00:00
|
|
|
zend_class_entry *ce;
|
2010-05-06 15:18:20 +00:00
|
|
|
|
2020-01-03 11:11:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
2010-05-06 15:18:20 +00:00
|
|
|
|
|
|
|
array_init(return_value);
|
2021-04-06 13:18:47 +00:00
|
|
|
zend_hash_real_init_packed(Z_ARRVAL_P(return_value));
|
|
|
|
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
|
2021-11-03 12:18:26 +00:00
|
|
|
ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) {
|
2021-04-06 13:18:47 +00:00
|
|
|
ce = Z_PTR_P(zv);
|
|
|
|
if ((ce->ce_flags & (ZEND_ACC_LINKED|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT)) == flags
|
|
|
|
&& key
|
|
|
|
&& ZSTR_VAL(key)[0] != 0) {
|
|
|
|
ZEND_HASH_FILL_GROW();
|
|
|
|
if (EXPECTED(Z_TYPE_P(zv) == IS_PTR)) {
|
|
|
|
ZEND_HASH_FILL_SET_STR_COPY(ce->name);
|
|
|
|
} else {
|
|
|
|
ZEND_ASSERT(Z_TYPE_P(zv) == IS_ALIAS_PTR);
|
|
|
|
ZEND_HASH_FILL_SET_STR_COPY(key);
|
|
|
|
}
|
|
|
|
ZEND_HASH_FILL_NEXT();
|
2021-02-09 21:00:55 +00:00
|
|
|
}
|
2021-04-06 13:18:47 +00:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
|
|
|
} ZEND_HASH_FILL_END();
|
2010-05-06 15:18:20 +00:00
|
|
|
}
|
2019-03-18 14:17:29 +00:00
|
|
|
/* {{{ */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Returns an array of all declared traits. */
|
2019-03-18 14:17:29 +00:00
|
|
|
ZEND_FUNCTION(get_declared_traits)
|
|
|
|
{
|
2021-04-06 13:18:47 +00:00
|
|
|
get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED | ZEND_ACC_TRAIT);
|
2019-03-18 14:17:29 +00:00
|
|
|
}
|
2010-05-06 15:18:20 +00:00
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Returns an array of all declared classes. */
|
2000-05-01 16:22:00 +00:00
|
|
|
ZEND_FUNCTION(get_declared_classes)
|
|
|
|
{
|
2021-04-06 13:18:47 +00:00
|
|
|
get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED);
|
2003-12-07 18:54:31 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Returns an array of all declared interfaces. */
|
2003-12-07 18:54:31 +00:00
|
|
|
ZEND_FUNCTION(get_declared_interfaces)
|
|
|
|
{
|
2021-04-06 13:18:47 +00:00
|
|
|
get_declared_class_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_LINKED | ZEND_ACC_INTERFACE);
|
2000-10-14 15:52:24 +00:00
|
|
|
}
|
2014-09-20 07:16:09 +00:00
|
|
|
/* }}} */
|
2001-12-04 17:58:32 +00:00
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Returns an array of all defined functions */
|
2000-10-14 15:52:24 +00:00
|
|
|
ZEND_FUNCTION(get_defined_functions)
|
|
|
|
{
|
2014-09-28 19:30:49 +00:00
|
|
|
zval internal, user;
|
2018-12-18 23:49:56 +00:00
|
|
|
zend_string *key;
|
|
|
|
zend_function *func;
|
2021-01-15 11:30:54 +00:00
|
|
|
bool exclude_disabled = 1;
|
2006-05-09 23:53:23 +00:00
|
|
|
|
2015-06-03 00:42:18 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &exclude_disabled) == FAILURE) {
|
2019-12-30 16:35:46 +00:00
|
|
|
RETURN_THROWS();
|
2000-10-14 15:52:24 +00:00
|
|
|
}
|
2006-05-09 23:53:23 +00: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 11:17:37 +00:00
|
|
|
if (exclude_disabled == 0) {
|
|
|
|
zend_error(E_DEPRECATED,
|
|
|
|
"get_defined_functions(): Setting $exclude_disabled to false has no effect");
|
|
|
|
}
|
|
|
|
|
2014-02-10 06:04:30 +00:00
|
|
|
array_init(&internal);
|
|
|
|
array_init(&user);
|
2000-10-14 15:52:24 +00:00
|
|
|
array_init(return_value);
|
2006-05-09 23:53:23 +00:00
|
|
|
|
2021-11-03 12:18:26 +00:00
|
|
|
ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(function_table), key, func) {
|
2018-12-18 23:49:56 +00:00
|
|
|
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 11:17:37 +00:00
|
|
|
add_next_index_str(&internal, zend_string_copy(key));
|
2018-12-18 23:49:56 +00:00
|
|
|
} else if (func->type == ZEND_USER_FUNCTION) {
|
|
|
|
add_next_index_str(&user, zend_string_copy(key));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} ZEND_HASH_FOREACH_END();
|
2006-05-09 23:53:23 +00:00
|
|
|
|
2014-09-24 09:26:09 +00:00
|
|
|
zend_hash_str_add_new(Z_ARRVAL_P(return_value), "internal", sizeof("internal")-1, &internal);
|
2023-06-08 12:03:29 +00:00
|
|
|
zend_hash_add_new(Z_ARRVAL_P(return_value), ZSTR_KNOWN(ZEND_STR_USER), &user);
|
2000-10-14 15:52:24 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Returns an associative array of names and values of all currently defined variable names (variables in the current scope) */
|
2000-10-14 15:52:24 +00:00
|
|
|
ZEND_FUNCTION(get_defined_vars)
|
2006-05-09 23:53:23 +00:00
|
|
|
{
|
2016-04-24 21:49:52 +00:00
|
|
|
zend_array *symbol_table;
|
2019-10-31 09:20:41 +00:00
|
|
|
|
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
|
2021-09-01 08:32:05 +00:00
|
|
|
if (zend_forbid_dynamic_call() == FAILURE) {
|
2016-04-24 21:49:52 +00:00
|
|
|
return;
|
|
|
|
}
|
2008-04-29 08:15:20 +00:00
|
|
|
|
2016-04-24 21:49:52 +00:00
|
|
|
symbol_table = zend_rebuild_symbol_table();
|
2015-12-26 04:31:37 +00:00
|
|
|
if (UNEXPECTED(symbol_table == NULL)) {
|
2019-12-20 10:10:20 +00:00
|
|
|
RETURN_EMPTY_ARRAY();
|
2015-12-26 04:31:37 +00:00
|
|
|
}
|
|
|
|
|
2015-04-08 06:30:47 +00:00
|
|
|
RETURN_ARR(zend_array_dup(symbol_table));
|
2000-10-14 15:52:24 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
2000-06-03 01:49:49 +00:00
|
|
|
|
2017-03-10 23:33:32 +00:00
|
|
|
#if ZEND_DEBUG && defined(ZTS)
|
2002-09-18 14:08:07 +00:00
|
|
|
ZEND_FUNCTION(zend_thread_id)
|
|
|
|
{
|
2019-10-31 09:20:41 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_NONE();
|
|
|
|
|
2014-08-25 17:24:55 +00:00
|
|
|
RETURN_LONG((zend_long)tsrm_thread_id());
|
2002-09-18 14:08:07 +00:00
|
|
|
}
|
2000-08-26 14:45:29 +00:00
|
|
|
#endif
|
2000-07-14 20:00:24 +00:00
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Get the resource type name for a given resource */
|
2000-07-14 20:00:24 +00:00
|
|
|
ZEND_FUNCTION(get_resource_type)
|
|
|
|
{
|
2011-09-13 13:29:35 +00:00
|
|
|
const char *resource_type;
|
2008-06-18 23:38:37 +00:00
|
|
|
zval *z_resource_type;
|
2000-07-14 20:00:24 +00:00
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &z_resource_type) == FAILURE) {
|
2019-12-30 16:35:46 +00:00
|
|
|
RETURN_THROWS();
|
2000-07-14 20:00:24 +00:00
|
|
|
}
|
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
resource_type = zend_rsrc_list_get_rsrc_type(Z_RES_P(z_resource_type));
|
2000-07-14 20:00:24 +00:00
|
|
|
if (resource_type) {
|
2014-02-10 06:04:30 +00:00
|
|
|
RETURN_STRING(resource_type);
|
2000-07-14 20:00:24 +00:00
|
|
|
} else {
|
2014-02-10 06:04:30 +00:00
|
|
|
RETURN_STRING("Unknown");
|
2000-07-14 20:00:24 +00:00
|
|
|
}
|
|
|
|
}
|
2002-03-02 13:48:13 +00:00
|
|
|
/* }}} */
|
2020-04-21 10:31:17 +00:00
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Get the resource ID for a given resource */
|
2020-04-21 10:31:17 +00: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 15:47:52 +00:00
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Get an array with all active resources */
|
2014-08-20 14:29:44 +00:00
|
|
|
ZEND_FUNCTION(get_resources)
|
|
|
|
{
|
|
|
|
zend_string *type = NULL;
|
|
|
|
zend_string *key;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_ulong index;
|
2014-08-20 14:29:44 +00:00
|
|
|
zval *val;
|
|
|
|
|
2020-07-12 10:40:37 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!", &type) == FAILURE) {
|
2019-12-30 16:35:46 +00:00
|
|
|
RETURN_THROWS();
|
2014-08-20 14:29:44 +00: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-25 20:40:58 +00:00
|
|
|
} else if (zend_string_equals_literal(type, "Unknown")) {
|
2014-08-20 14:29:44 +00: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 10:59:27 +00:00
|
|
|
int id = zend_fetch_list_dtor_id(ZSTR_VAL(type));
|
2014-08-20 14:29:44 +00:00
|
|
|
|
|
|
|
if (id <= 0) {
|
2020-07-12 10:40:37 +00:00
|
|
|
zend_argument_value_error(1, "must be a valid resource type");
|
|
|
|
RETURN_THROWS();
|
2014-08-20 14:29:44 +00: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 15:47:52 +00:00
|
|
|
|
2020-04-15 08:59:58 +00:00
|
|
|
static void add_zendext_info(zend_extension *ext, void *arg) /* {{{ */
|
2007-07-31 22:47:25 +00:00
|
|
|
{
|
|
|
|
zval *name_array = (zval *)arg;
|
2014-04-15 11:40:40 +00:00
|
|
|
add_next_index_string(name_array, ext->name);
|
2007-07-31 22:47:25 +00:00
|
|
|
}
|
2014-09-20 07:16:09 +00:00
|
|
|
/* }}} */
|
2007-07-31 22:47:25 +00:00
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Return an array containing names of loaded extensions */
|
2001-05-21 15:47:52 +00:00
|
|
|
ZEND_FUNCTION(get_loaded_extensions)
|
|
|
|
{
|
2021-01-15 11:30:54 +00:00
|
|
|
bool zendext = 0;
|
2007-07-31 22:47:25 +00:00
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &zendext) == FAILURE) {
|
2019-12-30 16:35:46 +00:00
|
|
|
RETURN_THROWS();
|
2001-05-21 15:47:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
array_init(return_value);
|
2007-07-31 22:47:25 +00:00
|
|
|
|
2007-08-02 16:54:44 +00:00
|
|
|
if (zendext) {
|
2020-04-15 08:59:58 +00:00
|
|
|
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) add_zendext_info, return_value);
|
2007-07-31 22:47:25 +00:00
|
|
|
} else {
|
2018-12-18 23:49:56 +00:00
|
|
|
zend_module_entry *module;
|
|
|
|
|
2021-11-03 12:18:26 +00:00
|
|
|
ZEND_HASH_MAP_FOREACH_PTR(&module_registry, module) {
|
2018-12-18 23:49:56 +00:00
|
|
|
add_next_index_string(return_value, module->name);
|
|
|
|
} ZEND_HASH_FOREACH_END();
|
2007-07-31 22:47:25 +00:00
|
|
|
}
|
2001-05-21 15:47:52 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Return an array containing the names and values of all defined constants */
|
2001-05-21 15:47:52 +00:00
|
|
|
ZEND_FUNCTION(get_defined_constants)
|
|
|
|
{
|
2021-01-15 11:30:54 +00:00
|
|
|
bool categorize = 0;
|
2015-01-03 09:22:58 +00:00
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &categorize) == FAILURE) {
|
2019-12-30 16:35:46 +00:00
|
|
|
RETURN_THROWS();
|
2001-05-21 15:47:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
array_init(return_value);
|
2003-02-07 03:04:26 +00:00
|
|
|
|
2009-05-07 12:08:09 +00:00
|
|
|
if (categorize) {
|
2003-02-07 03:04:26 +00:00
|
|
|
zend_constant *val;
|
2003-08-22 02:08:10 +00:00
|
|
|
int module_number;
|
2014-06-02 22:43:31 +00:00
|
|
|
zval *modules, const_val;
|
2008-01-24 18:07:45 +00:00
|
|
|
char **module_names;
|
2003-02-07 03:04:26 +00:00
|
|
|
zend_module_entry *module;
|
|
|
|
int i = 1;
|
2003-08-22 02:08:10 +00:00
|
|
|
|
2014-02-10 06:04:30 +00:00
|
|
|
modules = ecalloc(zend_hash_num_elements(&module_registry) + 2, sizeof(zval));
|
2003-08-22 02:08:10 +00:00
|
|
|
module_names = emalloc((zend_hash_num_elements(&module_registry) + 2) * sizeof(char *));
|
2006-05-09 23:53:23 +00:00
|
|
|
|
2003-08-22 02:08:10 +00:00
|
|
|
module_names[0] = "internal";
|
2021-11-03 12:18:26 +00:00
|
|
|
ZEND_HASH_MAP_FOREACH_PTR(&module_registry, module) {
|
2009-03-03 23:42:51 +00:00
|
|
|
module_names[module->module_number] = (char *)module->name;
|
|
|
|
i++;
|
2014-04-18 15:18:11 +00:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
2003-08-22 02:08:10 +00:00
|
|
|
module_names[i] = "user";
|
2003-02-07 03:04:26 +00:00
|
|
|
|
2023-07-06 07:55:11 +00:00
|
|
|
ZEND_HASH_MAP_FOREACH_PTR(EG(zend_constants), val) {
|
|
|
|
if (!val->name) {
|
|
|
|
/* skip special constants */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-07-26 09:58:07 +00:00
|
|
|
if (ZEND_CONSTANT_MODULE_NUMBER(val) == PHP_USER_CONSTANT) {
|
2003-08-22 02:08:10 +00:00
|
|
|
module_number = i;
|
2018-07-26 09:58:07 +00:00
|
|
|
} else if (ZEND_CONSTANT_MODULE_NUMBER(val) > i) {
|
2003-08-22 02:08:10 +00:00
|
|
|
/* should not happen */
|
2014-04-18 15:18:11 +00:00
|
|
|
continue;
|
2003-08-22 02:08:10 +00:00
|
|
|
} else {
|
2018-07-26 09:58:07 +00:00
|
|
|
module_number = ZEND_CONSTANT_MODULE_NUMBER(val);
|
2003-08-22 02:08:10 +00:00
|
|
|
}
|
2003-02-07 03:04:26 +00:00
|
|
|
|
2014-02-10 06:04:30 +00: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 02:08:10 +00:00
|
|
|
}
|
2003-02-07 03:04:26 +00:00
|
|
|
|
2017-10-30 20:13:10 +00:00
|
|
|
ZVAL_COPY_OR_DUP(&const_val, &val->value);
|
2023-07-06 07:55:11 +00:00
|
|
|
zend_hash_add_new(Z_ARRVAL(modules[module_number]), val->name, &const_val);
|
2014-04-18 15:18:11 +00:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
|
|
|
|
2003-02-07 03:04:26 +00:00
|
|
|
efree(module_names);
|
2003-08-22 02:08:10 +00:00
|
|
|
efree(modules);
|
2003-02-07 03:04:26 +00:00
|
|
|
} else {
|
2018-12-18 23:49:56 +00:00
|
|
|
zend_constant *constant;
|
|
|
|
zval const_val;
|
|
|
|
|
2023-07-06 07:55:11 +00:00
|
|
|
ZEND_HASH_MAP_FOREACH_PTR(EG(zend_constants), constant) {
|
|
|
|
if (!constant->name) {
|
|
|
|
/* skip special constants */
|
|
|
|
continue;
|
|
|
|
}
|
2018-12-18 23:49:56 +00:00
|
|
|
ZVAL_COPY_OR_DUP(&const_val, &constant->value);
|
2023-07-06 07:55:11 +00:00
|
|
|
zend_hash_add_new(Z_ARRVAL_P(return_value), constant->name, &const_val);
|
2018-12-18 23:49:56 +00:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
2003-02-07 03:04:26 +00:00
|
|
|
}
|
2001-05-21 15:47:52 +00:00
|
|
|
}
|
2002-07-05 02:34:54 +00:00
|
|
|
/* }}} */
|
2001-05-21 15:47:52 +00:00
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) /* {{{ */
|
2004-02-25 21:06:59 +00:00
|
|
|
{
|
2014-11-28 07:28:49 +00:00
|
|
|
uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
|
2002-08-23 14:22:25 +00:00
|
|
|
|
2014-06-26 19:51:14 +00:00
|
|
|
if (num_args) {
|
2014-09-15 10:08:42 +00:00
|
|
|
uint32_t i = 0;
|
2014-06-26 19:51:14 +00:00
|
|
|
zval *p = ZEND_CALL_ARG(call, 1);
|
2014-06-23 22:17:16 +00:00
|
|
|
|
2017-10-24 14:27:31 +00:00
|
|
|
array_init_size(arg_array, num_args);
|
2018-03-22 21:13:45 +00:00
|
|
|
zend_hash_real_init_packed(Z_ARRVAL_P(arg_array));
|
2014-12-23 16:08:28 +00:00
|
|
|
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(arg_array)) {
|
|
|
|
if (call->func->type == ZEND_USER_FUNCTION) {
|
2016-09-26 11:14:57 +00:00
|
|
|
uint32_t first_extra_arg = MIN(num_args, call->func->op_array.num_args);
|
2015-01-03 09:22:58 +00:00
|
|
|
|
2016-09-26 13:16:07 +00:00
|
|
|
if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_SYMBOL_TABLE)) {
|
2016-09-26 11:14:57 +00: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 08:16:38 +00:00
|
|
|
zend_string *arg_name = call->func->op_array.vars[i];
|
2021-12-21 11:21:24 +00:00
|
|
|
zval original_arg;
|
2020-07-24 08:16:38 +00:00
|
|
|
zval *arg = zend_hash_find_ex_ind(call->symbol_table, arg_name, 1);
|
2021-12-21 11:21:24 +00:00
|
|
|
zend_attribute *attribute = zend_get_parameter_attribute_str(
|
|
|
|
call->func->common.attributes,
|
|
|
|
"sensitiveparameter",
|
|
|
|
sizeof("sensitiveparameter") - 1,
|
|
|
|
i
|
|
|
|
);
|
|
|
|
|
|
|
|
bool is_sensitive = attribute != NULL;
|
|
|
|
|
2016-09-26 11:14:57 +00:00
|
|
|
if (arg) {
|
2020-07-24 08:16:38 +00:00
|
|
|
ZVAL_DEREF(arg);
|
2021-12-21 11:21:24 +00:00
|
|
|
ZVAL_COPY_VALUE(&original_arg, arg);
|
|
|
|
} else {
|
|
|
|
ZVAL_NULL(&original_arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_sensitive) {
|
|
|
|
zval redacted_arg;
|
|
|
|
object_init_ex(&redacted_arg, zend_ce_sensitive_parameter_value);
|
2024-05-16 21:23:55 +00:00
|
|
|
zend_call_known_function(Z_OBJCE_P(&redacted_arg)->constructor, Z_OBJ_P(&redacted_arg), Z_OBJCE_P(&redacted_arg), NULL, 1, &original_arg, NULL);
|
2021-12-21 11:21:24 +00:00
|
|
|
ZEND_HASH_FILL_SET(&redacted_arg);
|
2016-09-26 11:14:57 +00:00
|
|
|
} else {
|
2021-12-21 11:21:24 +00:00
|
|
|
Z_TRY_ADDREF_P(&original_arg);
|
|
|
|
ZEND_HASH_FILL_SET(&original_arg);
|
2016-09-26 11:14:57 +00:00
|
|
|
}
|
2021-12-21 11:21:24 +00:00
|
|
|
|
2019-05-28 10:35:00 +00:00
|
|
|
ZEND_HASH_FILL_NEXT();
|
2016-09-26 11:14:57 +00:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
} else {
|
2014-12-23 16:08:28 +00:00
|
|
|
while (i < first_extra_arg) {
|
2021-12-21 11:21:24 +00:00
|
|
|
zval original_arg;
|
|
|
|
zend_attribute *attribute = zend_get_parameter_attribute_str(
|
|
|
|
call->func->common.attributes,
|
|
|
|
"sensitiveparameter",
|
|
|
|
sizeof("sensitiveparameter") - 1,
|
|
|
|
i
|
|
|
|
);
|
|
|
|
bool is_sensitive = attribute != NULL;
|
|
|
|
|
2015-09-22 05:58:42 +00:00
|
|
|
if (EXPECTED(Z_TYPE_INFO_P(p) != IS_UNDEF)) {
|
2020-07-24 08:16:38 +00:00
|
|
|
zval *arg = p;
|
|
|
|
ZVAL_DEREF(arg);
|
2021-12-21 11:21:24 +00:00
|
|
|
ZVAL_COPY_VALUE(&original_arg, arg);
|
|
|
|
} else {
|
|
|
|
ZVAL_NULL(&original_arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_sensitive) {
|
|
|
|
zval redacted_arg;
|
|
|
|
object_init_ex(&redacted_arg, zend_ce_sensitive_parameter_value);
|
2024-05-16 21:23:55 +00:00
|
|
|
zend_call_known_function(Z_OBJCE_P(&redacted_arg)->constructor, Z_OBJ_P(&redacted_arg), Z_OBJCE_P(&redacted_arg), NULL, 1, &original_arg, NULL);
|
2021-12-21 11:21:24 +00:00
|
|
|
ZEND_HASH_FILL_SET(&redacted_arg);
|
2017-06-25 13:08:36 +00:00
|
|
|
} else {
|
2021-12-21 11:21:24 +00:00
|
|
|
Z_TRY_ADDREF_P(&original_arg);
|
|
|
|
ZEND_HASH_FILL_SET(&original_arg);
|
2015-09-22 03:59:35 +00:00
|
|
|
}
|
2021-12-21 11:21:24 +00:00
|
|
|
|
2019-05-28 10:35:00 +00:00
|
|
|
ZEND_HASH_FILL_NEXT();
|
2014-12-23 16:08:28 +00:00
|
|
|
p++;
|
|
|
|
i++;
|
|
|
|
}
|
2014-06-30 10:17:17 +00:00
|
|
|
}
|
2016-09-26 11:14:57 +00:00
|
|
|
p = ZEND_CALL_VAR_NUM(call, call->func->op_array.last_var + call->func->op_array.T);
|
2014-06-23 22:17:16 +00:00
|
|
|
}
|
2014-06-26 19:51:14 +00:00
|
|
|
|
2014-12-23 16:08:28 +00:00
|
|
|
while (i < num_args) {
|
2021-12-21 11:21:24 +00:00
|
|
|
zval original_arg;
|
|
|
|
bool is_sensitive = 0;
|
|
|
|
|
|
|
|
if (i < call->func->common.num_args || call->func->common.fn_flags & ZEND_ACC_VARIADIC) {
|
|
|
|
zend_attribute *attribute = zend_get_parameter_attribute_str(
|
|
|
|
call->func->common.attributes,
|
|
|
|
"sensitiveparameter",
|
|
|
|
sizeof("sensitiveparameter") - 1,
|
|
|
|
MIN(i, call->func->common.num_args)
|
|
|
|
);
|
|
|
|
is_sensitive = attribute != NULL;
|
|
|
|
}
|
|
|
|
|
2015-09-22 05:58:42 +00:00
|
|
|
if (EXPECTED(Z_TYPE_INFO_P(p) != IS_UNDEF)) {
|
2020-07-24 08:16:38 +00:00
|
|
|
zval *arg = p;
|
|
|
|
ZVAL_DEREF(arg);
|
2021-12-21 11:21:24 +00:00
|
|
|
ZVAL_COPY_VALUE(&original_arg, arg);
|
2017-06-25 13:08:36 +00:00
|
|
|
} else {
|
2021-12-21 11:21:24 +00:00
|
|
|
ZVAL_NULL(&original_arg);
|
2015-09-22 03:59:35 +00:00
|
|
|
}
|
2021-12-21 11:21:24 +00:00
|
|
|
|
|
|
|
if (is_sensitive) {
|
|
|
|
zval redacted_arg;
|
|
|
|
object_init_ex(&redacted_arg, zend_ce_sensitive_parameter_value);
|
2024-05-16 21:23:55 +00:00
|
|
|
zend_call_known_function(Z_OBJCE_P(&redacted_arg)->constructor, Z_OBJ_P(&redacted_arg), Z_OBJCE_P(&redacted_arg), NULL, 1, &original_arg, NULL);
|
2021-12-21 11:21:24 +00:00
|
|
|
ZEND_HASH_FILL_SET(&redacted_arg);
|
|
|
|
} else {
|
|
|
|
Z_TRY_ADDREF_P(&original_arg);
|
|
|
|
ZEND_HASH_FILL_SET(&original_arg);
|
|
|
|
}
|
|
|
|
|
2019-05-28 10:35:00 +00:00
|
|
|
ZEND_HASH_FILL_NEXT();
|
2014-12-23 16:08:28 +00:00
|
|
|
p++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
} ZEND_HASH_FILL_END();
|
2017-06-25 13:08:36 +00:00
|
|
|
Z_ARRVAL_P(arg_array)->nNumOfElements = num_args;
|
2017-10-24 14:27:31 +00:00
|
|
|
} else {
|
|
|
|
ZVAL_EMPTY_ARRAY(arg_array);
|
2002-08-23 14:22:25 +00:00
|
|
|
}
|
2020-04-06 10:46:52 +00:00
|
|
|
|
|
|
|
if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
|
|
|
|
zend_string *name;
|
|
|
|
zval *arg;
|
|
|
|
SEPARATE_ARRAY(arg_array);
|
2021-11-03 12:18:26 +00:00
|
|
|
ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(call->extra_named_params, name, arg) {
|
2020-04-06 10:46:52 +00:00
|
|
|
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 14:22:25 +00:00
|
|
|
}
|
2014-09-20 07:16:09 +00:00
|
|
|
/* }}} */
|
2002-08-23 14:22:25 +00:00
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ */
|
2002-12-01 19:47:02 +00:00
|
|
|
ZEND_FUNCTION(debug_print_backtrace)
|
|
|
|
{
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long options = 0;
|
|
|
|
zend_long limit = 0;
|
2021-05-18 09:43:37 +00:00
|
|
|
zval backtrace;
|
2002-12-01 19:47:02 +00:00
|
|
|
|
2021-06-08 09:30:37 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &options, &limit) == FAILURE) {
|
2019-12-30 16:35:46 +00:00
|
|
|
RETURN_THROWS();
|
2002-12-01 19:47:02 +00:00
|
|
|
}
|
|
|
|
|
2021-06-08 09:30:37 +00:00
|
|
|
zend_fetch_debug_backtrace(&backtrace, 1, options, limit);
|
2021-04-15 09:26:42 +00:00
|
|
|
ZEND_ASSERT(Z_TYPE(backtrace) == IS_ARRAY);
|
|
|
|
|
2021-05-18 09:43:37 +00:00
|
|
|
zend_string *str = zend_trace_to_string(Z_ARRVAL(backtrace), /* include_main */ false);
|
|
|
|
ZEND_WRITE(ZSTR_VAL(str), ZSTR_LEN(str));
|
|
|
|
zend_string_release(str);
|
|
|
|
zval_ptr_dtor(&backtrace);
|
2002-12-01 19:47:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* }}} */
|
2003-08-28 20:35:54 +00:00
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int options, int limit) /* {{{ */
|
2002-05-02 17:20:48 +00:00
|
|
|
{
|
2024-06-15 12:42:27 +00:00
|
|
|
zend_execute_data *call, *last_call = NULL;
|
2014-07-07 11:50:44 +00:00
|
|
|
zend_object *object;
|
2021-04-15 12:30:10 +00:00
|
|
|
bool fake_frame = 0;
|
2011-04-09 09:52:24 +00:00
|
|
|
int lineno, frameno = 0;
|
2014-06-23 22:17:16 +00:00
|
|
|
zend_function *func;
|
2015-08-14 14:16:27 +00:00
|
|
|
zend_string *filename;
|
|
|
|
zend_string *include_filename = NULL;
|
2021-04-06 15:25:50 +00:00
|
|
|
zval tmp;
|
2024-02-06 16:02:00 +00:00
|
|
|
HashTable *stack_frame, *prev_stack_frame = NULL;
|
2002-09-02 12:20:09 +00:00
|
|
|
|
2015-11-09 09:14:15 +00:00
|
|
|
array_init(return_value);
|
|
|
|
|
2021-04-15 12:30:10 +00:00
|
|
|
call = EG(current_execute_data);
|
|
|
|
if (!call) {
|
2015-11-09 09:14:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-08-04 12:12:45 +00:00
|
|
|
if (EG(filename_override)) {
|
|
|
|
// Add the current execution point to the frame so we don't lose it
|
|
|
|
zend_string *filename_override = EG(filename_override);
|
|
|
|
zend_long lineno_override = EG(lineno_override);
|
|
|
|
EG(filename_override) = NULL;
|
|
|
|
EG(lineno_override) = -1;
|
|
|
|
|
|
|
|
zend_string *filename = zend_get_executed_filename_ex();
|
|
|
|
zend_long lineno = zend_get_executed_lineno();
|
|
|
|
if (filename && (!zend_string_equals(filename, filename_override) || lineno != lineno_override)) {
|
|
|
|
stack_frame = zend_new_array(8);
|
|
|
|
zend_hash_real_init_mixed(stack_frame);
|
|
|
|
ZVAL_STR_COPY(&tmp, filename);
|
|
|
|
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FILE), &tmp, 1);
|
|
|
|
ZVAL_LONG(&tmp, lineno);
|
|
|
|
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_LINE), &tmp, 1);
|
|
|
|
ZVAL_STR_COPY(&tmp, ZSTR_KNOWN(ZEND_STR_CONST_EXPR_PLACEHOLDER));
|
|
|
|
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FUNCTION), &tmp, 1);
|
|
|
|
ZVAL_ARR(&tmp, stack_frame);
|
|
|
|
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
EG(filename_override) = filename_override;
|
|
|
|
EG(lineno_override) = lineno_override;
|
|
|
|
}
|
|
|
|
|
2021-06-08 09:30:37 +00:00
|
|
|
if (skip_last) {
|
|
|
|
/* skip debug_backtrace() */
|
2024-06-15 12:42:27 +00:00
|
|
|
last_call = call;
|
2021-04-15 12:30:10 +00:00
|
|
|
call = call->prev_execute_data;
|
2005-06-22 15:26:05 +00:00
|
|
|
}
|
|
|
|
|
2021-04-15 12:30:10 +00:00
|
|
|
while (call && (limit == 0 || frameno < limit)) {
|
|
|
|
zend_execute_data *prev = call->prev_execute_data;
|
|
|
|
|
|
|
|
if (!prev) {
|
|
|
|
/* add frame for a handler call without {main} code */
|
|
|
|
if (EXPECTED((ZEND_CALL_INFO(call) & ZEND_CALL_TOP_FUNCTION) == 0)) {
|
|
|
|
break;
|
2014-07-02 18:01:25 +00:00
|
|
|
}
|
2021-04-15 12:30:10 +00:00
|
|
|
} else if (UNEXPECTED((ZEND_CALL_INFO(call) & ZEND_CALL_GENERATOR) != 0)) {
|
|
|
|
prev = zend_generator_check_placeholder_frame(prev);
|
2014-07-02 18:01:25 +00:00
|
|
|
}
|
2002-05-10 09:41:50 +00:00
|
|
|
|
2024-02-06 16:02:00 +00:00
|
|
|
/* For frameless calls we add an additional frame for the call itself. */
|
|
|
|
if (ZEND_USER_CODE(call->func->type)) {
|
|
|
|
const zend_op *opline = call->opline;
|
|
|
|
if (!ZEND_OP_IS_FRAMELESS_ICALL(opline->opcode)) {
|
|
|
|
goto not_frameless_call;
|
|
|
|
}
|
|
|
|
int num_args = ZEND_FLF_NUM_ARGS(opline->opcode);
|
|
|
|
/* Check if any args were already freed. Skip the frame in that case. */
|
|
|
|
if (num_args >= 1) {
|
|
|
|
zval *arg = zend_get_zval_ptr(opline, opline->op1_type, &opline->op1, call);
|
|
|
|
if (Z_TYPE_P(arg) == IS_UNDEF) goto not_frameless_call;
|
|
|
|
}
|
|
|
|
if (num_args >= 2) {
|
|
|
|
zval *arg = zend_get_zval_ptr(opline, opline->op2_type, &opline->op2, call);
|
|
|
|
if (Z_TYPE_P(arg) == IS_UNDEF) goto not_frameless_call;
|
|
|
|
}
|
|
|
|
if (num_args >= 3) {
|
|
|
|
const zend_op *op_data = opline + 1;
|
|
|
|
zval *arg = zend_get_zval_ptr(op_data, op_data->op1_type, &op_data->op1, call);
|
|
|
|
if (Z_TYPE_P(arg) == IS_UNDEF) goto not_frameless_call;
|
|
|
|
}
|
2024-06-15 12:42:27 +00:00
|
|
|
zend_function *func = ZEND_FLF_FUNC(opline);
|
|
|
|
/* Assume frameless functions are not recursive with themselves.
|
|
|
|
* This condition may be true when observers are enabled:
|
|
|
|
* Observers will put a call frame on top of the frameless opcode. */
|
|
|
|
if (last_call && last_call->func == func) {
|
|
|
|
goto not_frameless_call;
|
|
|
|
}
|
2024-02-06 16:02:00 +00:00
|
|
|
stack_frame = zend_new_array(8);
|
|
|
|
zend_hash_real_init_mixed(stack_frame);
|
|
|
|
zend_string *name = func->common.function_name;
|
|
|
|
ZVAL_STRINGL(&tmp, ZSTR_VAL(name), ZSTR_LEN(name));
|
|
|
|
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FUNCTION), &tmp, 1);
|
|
|
|
/* Steal file and line from the previous frame. */
|
|
|
|
if (call->func && ZEND_USER_CODE(call->func->common.type)) {
|
|
|
|
filename = call->func->op_array.filename;
|
|
|
|
if (call->opline->opcode == ZEND_HANDLE_EXCEPTION) {
|
|
|
|
if (EG(opline_before_exception)) {
|
|
|
|
lineno = EG(opline_before_exception)->lineno;
|
|
|
|
} else {
|
|
|
|
lineno = call->func->op_array.line_end;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
lineno = call->opline->lineno;
|
|
|
|
}
|
|
|
|
ZVAL_STR_COPY(&tmp, filename);
|
|
|
|
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FILE), &tmp, 1);
|
|
|
|
ZVAL_LONG(&tmp, lineno);
|
|
|
|
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_LINE), &tmp, 1);
|
|
|
|
if (prev_stack_frame) {
|
|
|
|
zend_hash_del(prev_stack_frame, ZSTR_KNOWN(ZEND_STR_FILE));
|
|
|
|
zend_hash_del(prev_stack_frame, ZSTR_KNOWN(ZEND_STR_LINE));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) {
|
|
|
|
HashTable *args = zend_new_array(8);
|
|
|
|
zend_hash_real_init_mixed(args);
|
|
|
|
if (num_args >= 1) {
|
|
|
|
zval *arg = zend_get_zval_ptr(opline, opline->op1_type, &opline->op1, call);
|
|
|
|
Z_TRY_ADDREF_P(arg);
|
|
|
|
zend_hash_next_index_insert_new(args, arg);
|
|
|
|
}
|
|
|
|
if (num_args >= 2) {
|
|
|
|
zval *arg = zend_get_zval_ptr(opline, opline->op2_type, &opline->op2, call);
|
|
|
|
Z_TRY_ADDREF_P(arg);
|
|
|
|
zend_hash_next_index_insert_new(args, arg);
|
|
|
|
}
|
|
|
|
if (num_args >= 3) {
|
|
|
|
const zend_op *op_data = opline + 1;
|
|
|
|
zval *arg = zend_get_zval_ptr(op_data, op_data->op1_type, &op_data->op1, call);
|
|
|
|
Z_TRY_ADDREF_P(arg);
|
|
|
|
zend_hash_next_index_insert_new(args, arg);
|
|
|
|
}
|
|
|
|
ZVAL_ARR(&tmp, args);
|
|
|
|
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_ARGS), &tmp, 1);
|
|
|
|
}
|
|
|
|
ZVAL_ARR(&tmp, stack_frame);
|
|
|
|
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
|
|
|
|
}
|
|
|
|
not_frameless_call:
|
|
|
|
|
2021-04-06 15:25:50 +00:00
|
|
|
/* We use _zend_hash_append*() and the array must be preallocated */
|
|
|
|
stack_frame = zend_new_array(8);
|
|
|
|
zend_hash_real_init_mixed(stack_frame);
|
2002-05-10 09:41:50 +00:00
|
|
|
|
2021-04-15 12:30:10 +00:00
|
|
|
if (prev && prev->func && ZEND_USER_CODE(prev->func->common.type)) {
|
|
|
|
filename = prev->func->op_array.filename;
|
|
|
|
if (prev->opline->opcode == ZEND_HANDLE_EXCEPTION) {
|
2014-07-02 18:01:25 +00:00
|
|
|
if (EG(opline_before_exception)) {
|
|
|
|
lineno = EG(opline_before_exception)->lineno;
|
|
|
|
} else {
|
2021-04-15 12:30:10 +00:00
|
|
|
lineno = prev->func->op_array.line_end;
|
2014-07-02 18:01:25 +00:00
|
|
|
}
|
|
|
|
} else {
|
2021-04-15 12:30:10 +00:00
|
|
|
lineno = prev->opline->lineno;
|
2014-07-02 18:01:25 +00:00
|
|
|
}
|
2016-05-12 10:47:22 +00:00
|
|
|
ZVAL_STR_COPY(&tmp, filename);
|
2021-04-06 15:25:50 +00:00
|
|
|
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FILE), &tmp, 1);
|
2016-05-12 10:47:22 +00:00
|
|
|
ZVAL_LONG(&tmp, lineno);
|
2021-04-06 15:25:50 +00:00
|
|
|
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_LINE), &tmp, 1);
|
2002-08-28 14:49:15 +00:00
|
|
|
|
|
|
|
/* try to fetch args only if an FCALL was just made - elsewise we're in the middle of a function
|
2021-03-31 03:49:41 +00:00
|
|
|
* and debug_backtrace() might have been called by the error_handler. in this case we don't
|
2002-08-28 14:49:15 +00:00
|
|
|
* want to pop anything of the argument-stack */
|
2002-08-26 16:40:34 +00:00
|
|
|
} else {
|
2021-04-15 12:30:10 +00:00
|
|
|
zend_execute_data *prev_call = prev;
|
|
|
|
|
|
|
|
while (prev_call) {
|
|
|
|
zend_execute_data *prev;
|
2006-07-27 08:20:38 +00:00
|
|
|
|
2014-07-07 11:50:44 +00:00
|
|
|
if (prev_call &&
|
2019-03-18 14:17:29 +00:00
|
|
|
prev_call->func &&
|
2014-07-07 11:50:44 +00:00
|
|
|
!ZEND_USER_CODE(prev_call->func->common.type) &&
|
2015-04-10 20:01:00 +00:00
|
|
|
!(prev_call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
|
2006-07-27 08:20:38 +00:00
|
|
|
break;
|
2015-01-03 09:22:58 +00:00
|
|
|
}
|
2021-04-15 12:30:10 +00:00
|
|
|
|
|
|
|
prev = prev_call->prev_execute_data;
|
|
|
|
if (prev && prev->func && ZEND_USER_CODE(prev->func->common.type)) {
|
2016-05-12 10:47:22 +00:00
|
|
|
ZVAL_STR_COPY(&tmp, prev->func->op_array.filename);
|
2021-04-06 15:25:50 +00:00
|
|
|
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FILE), &tmp, 1);
|
2016-05-12 10:47:22 +00:00
|
|
|
ZVAL_LONG(&tmp, prev->opline->lineno);
|
2021-04-06 15:25:50 +00:00
|
|
|
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_LINE), &tmp, 1);
|
2006-07-27 08:20:38 +00:00
|
|
|
break;
|
|
|
|
}
|
2014-07-07 11:50:44 +00:00
|
|
|
prev_call = prev;
|
2006-07-27 08:20:38 +00:00
|
|
|
}
|
2002-08-26 16:40:34 +00:00
|
|
|
filename = NULL;
|
2002-08-23 13:50:42 +00:00
|
|
|
}
|
2002-05-10 09:41:50 +00:00
|
|
|
|
2021-04-15 12:30:10 +00:00
|
|
|
func = call->func;
|
|
|
|
if (!fake_frame && func->common.function_name) {
|
|
|
|
ZVAL_STR_COPY(&tmp, func->common.function_name);
|
2021-04-06 15:25:50 +00:00
|
|
|
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FUNCTION), &tmp, 1);
|
2002-08-23 13:50:42 +00:00
|
|
|
|
2021-04-15 12:30:10 +00:00
|
|
|
if (Z_TYPE(call->This) == IS_OBJECT) {
|
|
|
|
object = Z_OBJ(call->This);
|
|
|
|
/* $this may be passed into regular internal functions */
|
2014-06-23 22:17:16 +00:00
|
|
|
if (func->common.scope) {
|
2016-05-12 10:47:22 +00:00
|
|
|
ZVAL_STR_COPY(&tmp, func->common.scope->name);
|
2018-05-31 08:57:22 +00:00
|
|
|
} else if (object->handlers->get_class_name == zend_std_get_class_name) {
|
2016-05-12 10:47:22 +00:00
|
|
|
ZVAL_STR_COPY(&tmp, object->ce->name);
|
2016-06-22 14:23:04 +00:00
|
|
|
} else {
|
2016-06-22 14:28:59 +00:00
|
|
|
ZVAL_STR(&tmp, object->handlers->get_class_name(object));
|
2005-04-04 17:23:38 +00:00
|
|
|
}
|
2021-04-06 15:25:50 +00:00
|
|
|
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_CLASS), &tmp, 1);
|
2011-01-16 20:39:22 +00:00
|
|
|
if ((options & DEBUG_BACKTRACE_PROVIDE_OBJECT) != 0) {
|
2020-06-17 10:34:04 +00:00
|
|
|
ZVAL_OBJ_COPY(&tmp, object);
|
2021-04-06 15:25:50 +00:00
|
|
|
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_OBJECT), &tmp, 1);
|
2005-11-24 05:07:28 +00:00
|
|
|
}
|
|
|
|
|
2017-03-04 09:39:13 +00:00
|
|
|
ZVAL_INTERNED_STR(&tmp, ZSTR_KNOWN(ZEND_STR_OBJECT_OPERATOR));
|
2021-04-06 15:25:50 +00:00
|
|
|
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_TYPE), &tmp, 1);
|
2014-06-23 22:17:16 +00:00
|
|
|
} else if (func->common.scope) {
|
2016-05-12 10:47:22 +00:00
|
|
|
ZVAL_STR_COPY(&tmp, func->common.scope->name);
|
2021-04-06 15:25:50 +00:00
|
|
|
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_CLASS), &tmp, 1);
|
2017-03-04 09:39:13 +00:00
|
|
|
ZVAL_INTERNED_STR(&tmp, ZSTR_KNOWN(ZEND_STR_PAAMAYIM_NEKUDOTAYIM));
|
2021-04-06 15:25:50 +00:00
|
|
|
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_TYPE), &tmp, 1);
|
2002-08-23 14:44:58 +00:00
|
|
|
}
|
|
|
|
|
2015-01-03 09:22:58 +00:00
|
|
|
if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0 &&
|
2014-06-26 19:51:14 +00:00
|
|
|
func->type != ZEND_EVAL_CODE) {
|
2014-07-07 11:50:44 +00:00
|
|
|
|
2016-05-12 10:47:22 +00:00
|
|
|
debug_backtrace_get_args(call, &tmp);
|
2021-04-06 15:25:50 +00:00
|
|
|
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_ARGS), &tmp, 1);
|
2006-05-09 23:53:23 +00:00
|
|
|
}
|
2002-08-23 14:44:58 +00:00
|
|
|
} else {
|
|
|
|
/* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
|
2021-01-15 11:30:54 +00:00
|
|
|
bool build_filename_arg = 1;
|
2016-05-12 10:47:22 +00:00
|
|
|
zend_string *pseudo_function_name;
|
2020-09-23 15:06:28 +00:00
|
|
|
uint32_t include_kind = 0;
|
2021-04-15 12:30:10 +00:00
|
|
|
if (prev && prev->func && ZEND_USER_CODE(prev->func->common.type) && prev->opline->opcode == ZEND_INCLUDE_OR_EVAL) {
|
|
|
|
include_kind = prev->opline->extended_value;
|
2020-09-23 15:06:28 +00:00
|
|
|
}
|
2002-08-23 14:44:58 +00:00
|
|
|
|
2020-09-23 15:06:28 +00:00
|
|
|
switch (include_kind) {
|
2002-08-24 20:52:52 +00:00
|
|
|
case ZEND_EVAL:
|
2017-03-04 09:39:13 +00:00
|
|
|
pseudo_function_name = ZSTR_KNOWN(ZEND_STR_EVAL);
|
2002-08-26 16:40:34 +00:00
|
|
|
build_filename_arg = 0;
|
2002-08-24 20:52:52 +00:00
|
|
|
break;
|
|
|
|
case ZEND_INCLUDE:
|
2017-03-04 09:39:13 +00:00
|
|
|
pseudo_function_name = ZSTR_KNOWN(ZEND_STR_INCLUDE);
|
2002-08-24 20:52:52 +00:00
|
|
|
break;
|
|
|
|
case ZEND_REQUIRE:
|
2017-03-04 09:39:13 +00:00
|
|
|
pseudo_function_name = ZSTR_KNOWN(ZEND_STR_REQUIRE);
|
2002-08-24 20:52:52 +00:00
|
|
|
break;
|
|
|
|
case ZEND_INCLUDE_ONCE:
|
2017-03-04 09:39:13 +00:00
|
|
|
pseudo_function_name = ZSTR_KNOWN(ZEND_STR_INCLUDE_ONCE);
|
2002-08-24 20:52:52 +00:00
|
|
|
break;
|
|
|
|
case ZEND_REQUIRE_ONCE:
|
2017-03-04 09:39:13 +00:00
|
|
|
pseudo_function_name = ZSTR_KNOWN(ZEND_STR_REQUIRE_ONCE);
|
2002-08-24 20:52:52 +00:00
|
|
|
break;
|
|
|
|
default:
|
2020-09-23 15:06:28 +00:00
|
|
|
/* Skip dummy frame unless it is needed to preserve filename/lineno info. */
|
|
|
|
if (!filename) {
|
2021-04-06 15:25:50 +00:00
|
|
|
zend_array_destroy(stack_frame);
|
2020-09-23 15:06:28 +00:00
|
|
|
goto skip_frame;
|
|
|
|
}
|
|
|
|
|
2017-03-04 09:39:13 +00:00
|
|
|
pseudo_function_name = ZSTR_KNOWN(ZEND_STR_UNKNOWN);
|
2002-08-26 16:40:34 +00:00
|
|
|
build_filename_arg = 0;
|
2002-08-24 20:52:52 +00:00
|
|
|
break;
|
2002-08-24 09:05:44 +00:00
|
|
|
}
|
|
|
|
|
2002-08-26 16:40:34 +00:00
|
|
|
if (build_filename_arg && include_filename) {
|
2014-02-10 06:04:30 +00:00
|
|
|
zval arg_array;
|
2002-08-26 16:40:34 +00:00
|
|
|
|
2014-02-10 06:04:30 +00:00
|
|
|
array_init(&arg_array);
|
2006-05-09 23:53:23 +00:00
|
|
|
|
2013-07-23 23:55:43 +00:00
|
|
|
/* include_filename always points to the last filename of the last last called-function.
|
2002-08-26 16:40:34 +00:00
|
|
|
if we have called include in the frame above - this is the file we have included.
|
2002-08-24 09:05:44 +00:00
|
|
|
*/
|
2002-08-26 16:40:34 +00:00
|
|
|
|
2016-05-12 10:47:22 +00:00
|
|
|
ZVAL_STR_COPY(&tmp, include_filename);
|
|
|
|
zend_hash_next_index_insert_new(Z_ARRVAL(arg_array), &tmp);
|
2021-04-06 15:25:50 +00:00
|
|
|
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_ARGS), &arg_array, 1);
|
2002-08-23 14:44:58 +00:00
|
|
|
}
|
2002-08-23 13:50:42 +00:00
|
|
|
|
2016-05-12 10:47:22 +00:00
|
|
|
ZVAL_INTERNED_STR(&tmp, pseudo_function_name);
|
2021-04-06 15:25:50 +00:00
|
|
|
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FUNCTION), &tmp, 1);
|
2002-08-23 14:44:58 +00:00
|
|
|
}
|
2002-08-23 14:22:25 +00:00
|
|
|
|
2021-04-06 15:25:50 +00:00
|
|
|
ZVAL_ARR(&tmp, stack_frame);
|
|
|
|
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
|
2022-09-29 14:17:17 +00:00
|
|
|
frameno++;
|
2024-02-06 16:02:00 +00:00
|
|
|
prev_stack_frame = stack_frame;
|
2002-07-26 10:38:25 +00:00
|
|
|
|
2020-09-23 15:06:28 +00:00
|
|
|
skip_frame:
|
2021-09-29 14:22:48 +00:00
|
|
|
if (UNEXPECTED(ZEND_CALL_KIND(call) == ZEND_CALL_TOP_FUNCTION)
|
2021-04-15 12:30:10 +00:00
|
|
|
&& !fake_frame
|
|
|
|
&& prev
|
|
|
|
&& prev->func
|
|
|
|
&& ZEND_USER_CODE(prev->func->common.type)
|
|
|
|
&& prev->opline->opcode == ZEND_INCLUDE_OR_EVAL) {
|
|
|
|
fake_frame = 1;
|
|
|
|
} else {
|
|
|
|
fake_frame = 0;
|
|
|
|
include_filename = filename;
|
2024-06-15 12:42:27 +00:00
|
|
|
last_call = call;
|
2021-04-15 12:30:10 +00:00
|
|
|
call = prev;
|
|
|
|
}
|
2002-05-02 17:20:48 +00:00
|
|
|
}
|
|
|
|
}
|
2002-07-05 02:34:54 +00:00
|
|
|
/* }}} */
|
2002-05-02 17:20:48 +00:00
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Return backtrace as array */
|
2003-08-28 20:35:54 +00:00
|
|
|
ZEND_FUNCTION(debug_backtrace)
|
|
|
|
{
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long options = DEBUG_BACKTRACE_PROVIDE_OBJECT;
|
|
|
|
zend_long limit = 0;
|
2015-01-03 09:22:58 +00:00
|
|
|
|
2021-06-08 09:30:37 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &options, &limit) == FAILURE) {
|
2019-12-30 16:35:46 +00:00
|
|
|
RETURN_THROWS();
|
2003-08-28 20:35:54 +00:00
|
|
|
}
|
2006-05-09 23:53:23 +00:00
|
|
|
|
2021-06-08 09:30:37 +00:00
|
|
|
zend_fetch_debug_backtrace(return_value, 1, options, limit);
|
2003-08-28 20:35:54 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Returns true if the named extension is loaded */
|
2001-05-21 15:47:52 +00:00
|
|
|
ZEND_FUNCTION(extension_loaded)
|
|
|
|
{
|
2014-12-24 12:04:51 +00:00
|
|
|
zend_string *extension_name;
|
2014-02-10 06:04:30 +00:00
|
|
|
zend_string *lcname;
|
2001-05-21 15:47:52 +00:00
|
|
|
|
2014-12-24 12:04:51 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &extension_name) == FAILURE) {
|
2019-12-30 16:35:46 +00:00
|
|
|
RETURN_THROWS();
|
2001-05-21 15:47:52 +00:00
|
|
|
}
|
|
|
|
|
2014-12-24 12:04:51 +00:00
|
|
|
lcname = zend_string_tolower(extension_name);
|
2014-02-10 06:04:30 +00:00
|
|
|
if (zend_hash_exists(&module_registry, lcname)) {
|
2004-03-29 18:48:59 +00:00
|
|
|
RETVAL_TRUE;
|
2001-05-21 15:47:52 +00:00
|
|
|
} else {
|
2004-03-29 18:48:59 +00:00
|
|
|
RETVAL_FALSE;
|
2001-05-21 15:47:52 +00:00
|
|
|
}
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(lcname, 0);
|
2001-05-21 15:47:52 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Returns an array with the names of functions belonging to the named extension */
|
2001-05-21 15:47:52 +00:00
|
|
|
ZEND_FUNCTION(get_extension_funcs)
|
|
|
|
{
|
2014-12-24 12:04:51 +00:00
|
|
|
zend_string *extension_name;
|
2014-02-10 06:04:30 +00:00
|
|
|
zend_string *lcname;
|
2020-08-28 13:41:27 +00:00
|
|
|
bool array;
|
2001-05-21 15:47:52 +00:00
|
|
|
zend_module_entry *module;
|
2013-12-10 15:07:16 +00:00
|
|
|
zend_function *zif;
|
2015-01-03 09:22:58 +00:00
|
|
|
|
2014-12-24 12:04:51 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &extension_name) == FAILURE) {
|
2019-12-30 16:35:46 +00:00
|
|
|
RETURN_THROWS();
|
2001-05-21 15:47:52 +00:00
|
|
|
}
|
2015-06-30 10:59:27 +00:00
|
|
|
if (strncasecmp(ZSTR_VAL(extension_name), "zend", sizeof("zend"))) {
|
2014-12-24 12:04:51 +00:00
|
|
|
lcname = zend_string_tolower(extension_name);
|
2015-07-02 04:31:26 +00:00
|
|
|
module = zend_hash_find_ptr(&module_registry, lcname);
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(lcname, 0);
|
2013-12-10 15:07:16 +00:00
|
|
|
} else {
|
2015-07-02 04:31:26 +00:00
|
|
|
module = zend_hash_str_find_ptr(&module_registry, "core", sizeof("core") - 1);
|
2013-12-10 15:07:16 +00:00
|
|
|
}
|
2015-07-02 04:31:26 +00:00
|
|
|
|
2014-02-10 06:04:30 +00:00
|
|
|
if (!module) {
|
2013-12-10 15:07:16 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2006-05-09 23:53:23 +00:00
|
|
|
|
2013-12-10 15:07:16 +00: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-06 20:21:02 +00:00
|
|
|
} else {
|
2013-12-10 15:07:16 +00:00
|
|
|
array = 0;
|
|
|
|
}
|
2014-04-18 15:18:11 +00:00
|
|
|
|
2021-11-03 12:18:26 +00:00
|
|
|
ZEND_HASH_MAP_FOREACH_PTR(CG(function_table), zif) {
|
2014-03-03 09:06:04 +00:00
|
|
|
if (zif->common.type == ZEND_INTERNAL_FUNCTION
|
2013-12-10 15:07:16 +00:00
|
|
|
&& zif->internal_function.module == module) {
|
|
|
|
if (!array) {
|
|
|
|
array_init(return_value);
|
|
|
|
array = 1;
|
|
|
|
}
|
2014-08-25 17:24:55 +00:00
|
|
|
add_next_index_str(return_value, zend_string_copy(zif->common.function_name));
|
2013-12-10 15:07:16 +00:00
|
|
|
}
|
2014-04-18 15:18:11 +00:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
2001-05-21 15:47:52 +00:00
|
|
|
|
2013-12-10 15:07:16 +00:00
|
|
|
if (!array) {
|
|
|
|
RETURN_FALSE;
|
2001-05-21 15:47:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|