Skip to content

Commit

Permalink
Fixed issue #2216: Crash in ZTS builds because of overloaded functions
Browse files Browse the repository at this point in the history
  • Loading branch information
dunglas committed Mar 28, 2024
1 parent 5115378 commit 6cdc594
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 78 deletions.
77 changes: 20 additions & 57 deletions src/base/base.c
Expand Up @@ -50,6 +50,12 @@

ZEND_EXTERN_MODULE_GLOBALS(xdebug)

/* True globals for overloaded functions */
zif_handler orig_error_reporting_func = NULL;
zif_handler orig_set_time_limit_func = NULL;
zif_handler orig_pcntl_exec_func = NULL;
zif_handler orig_pcntl_fork_func = NULL;

#if PHP_VERSION_ID >= 80100
void (*xdebug_old_error_cb)(int type, zend_string *error_filename, const uint32_t error_lineno, zend_string *message);
void (*xdebug_new_error_cb)(int type, zend_string *error_filename, const uint32_t error_lineno, zend_string *message);
Expand Down Expand Up @@ -1071,74 +1077,33 @@ static void xdebug_base_overloaded_functions_setup(void)
zend_function *orig;

/* Override set_time_limit with our own function to prevent timing out while debugging */
orig = zend_hash_str_find_ptr(EG(function_table), "set_time_limit", sizeof("set_time_limit") - 1);
orig = zend_hash_str_find_ptr(CG(function_table), "set_time_limit", sizeof("set_time_limit") - 1);
if (orig) {
XG_BASE(orig_set_time_limit_func) = orig->internal_function.handler;
orig_set_time_limit_func = orig->internal_function.handler;
orig->internal_function.handler = zif_xdebug_set_time_limit;
} else {
XG_BASE(orig_set_time_limit_func) = NULL;
}

/* Override error_reporting with our own function, to be able to give right answer during DBGp's
* 'eval' commands */
orig = zend_hash_str_find_ptr(EG(function_table), "error_reporting", sizeof("error_reporting") - 1);
orig = zend_hash_str_find_ptr(CG(function_table), "error_reporting", sizeof("error_reporting") - 1);
if (orig) {
XG_BASE(orig_error_reporting_func) = orig->internal_function.handler;
orig_error_reporting_func = orig->internal_function.handler;
orig->internal_function.handler = zif_xdebug_error_reporting;
} else {
XG_BASE(orig_error_reporting_func) = NULL;
}

/* Override pcntl_exec with our own function to be able to write profiling summary */
orig = zend_hash_str_find_ptr(EG(function_table), "pcntl_exec", sizeof("pcntl_exec") - 1);
orig = zend_hash_str_find_ptr(CG(function_table), "pcntl_exec", sizeof("pcntl_exec") - 1);
if (orig) {
XG_BASE(orig_pcntl_exec_func) = orig->internal_function.handler;
orig_pcntl_exec_func = orig->internal_function.handler;
orig->internal_function.handler = zif_xdebug_pcntl_exec;
} else {
XG_BASE(orig_pcntl_exec_func) = NULL;
}

/* Override pcntl_fork with our own function to be able
* to start the debugger for the forked process */
orig = zend_hash_str_find_ptr(EG(function_table), "pcntl_fork", sizeof("pcntl_fork") - 1);
orig = zend_hash_str_find_ptr(CG(function_table), "pcntl_fork", sizeof("pcntl_fork") - 1);
if (orig) {
XG_BASE(orig_pcntl_fork_func) = orig->internal_function.handler;
orig_pcntl_fork_func = orig->internal_function.handler;
orig->internal_function.handler = zif_xdebug_pcntl_fork;
} else {
XG_BASE(orig_pcntl_fork_func) = NULL;
}
}

static void xdebug_base_overloaded_functions_restore(void)
{
zend_function *orig;

if (XG_BASE(orig_set_time_limit_func)) {
orig = zend_hash_str_find_ptr(EG(function_table), "set_time_limit", sizeof("set_time_limit") - 1);
if (orig) {
orig->internal_function.handler = XG_BASE(orig_set_time_limit_func);
}
}

if (XG_BASE(orig_error_reporting_func)) {
orig = zend_hash_str_find_ptr(EG(function_table), "error_reporting", sizeof("error_reporting") - 1);
if (orig) {
orig->internal_function.handler = XG_BASE(orig_error_reporting_func);
}
}

if (XG_BASE(orig_pcntl_exec_func)) {
orig = zend_hash_str_find_ptr(EG(function_table), "pcntl_exec", sizeof("pcntl_exec") - 1);
if (orig) {
orig->internal_function.handler = XG_BASE(orig_pcntl_exec_func);
}
}

if (XG_BASE(orig_pcntl_fork_func)) {
orig = zend_hash_str_find_ptr(EG(function_table), "pcntl_fork", sizeof("pcntl_fork") - 1);
if (orig) {
orig->internal_function.handler = XG_BASE(orig_pcntl_fork_func);
}
}
}

Expand Down Expand Up @@ -1359,6 +1324,8 @@ void xdebug_base_minit(INIT_FUNC_ARGS)
XG_BASE(control_socket_fd) = 0;
XG_BASE(control_socket_last_trigger) = 0;
#endif

xdebug_base_overloaded_functions_setup();
}

void xdebug_base_mshutdown()
Expand Down Expand Up @@ -1431,8 +1398,6 @@ void xdebug_base_rinit()
XG_BASE(filters_stack) = xdebug_llist_alloc(xdebug_llist_string_dtor);
XG_BASE(filters_tracing) = xdebug_llist_alloc(xdebug_llist_string_dtor);

xdebug_base_overloaded_functions_setup();

if (XG_BASE(private_tmp)) {
xdebug_log_ex(XLOG_CHAN_CONFIG, XLOG_INFO, "PRIVTMP", "Systemd Private Temp Directory is enabled (%s)", XG_BASE(private_tmp));
}
Expand Down Expand Up @@ -1466,8 +1431,6 @@ void xdebug_base_post_deactivate()
XG_BASE(filters_tracing) = NULL;
XG_BASE(filters_code_coverage) = NULL;

xdebug_base_overloaded_functions_restore();

#ifdef __linux__
/* Close Down Control Socket */
xdebug_control_socket_teardown();
Expand Down Expand Up @@ -1599,7 +1562,7 @@ void xdebug_base_use_xdebug_throw_exception_hook(void)
PHP_FUNCTION(xdebug_set_time_limit)
{
if (!xdebug_is_debug_connection_active()) {
XG_BASE(orig_set_time_limit_func)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
orig_set_time_limit_func(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}

RETURN_FALSE;
Expand All @@ -1613,7 +1576,7 @@ PHP_FUNCTION(xdebug_error_reporting)
if (ZEND_NUM_ARGS() == 0 && XG_BASE(error_reporting_overridden) && xdebug_is_debug_connection_active()) {
RETURN_LONG(XG_BASE(error_reporting_override));
}
XG_BASE(orig_error_reporting_func)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
orig_error_reporting_func(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */

Expand All @@ -1624,15 +1587,15 @@ PHP_FUNCTION(xdebug_pcntl_exec)
/* We need to stop the profiler and trace files here */
xdebug_profiler_pcntl_exec_handler();

XG_BASE(orig_pcntl_exec_func)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
orig_pcntl_exec_func(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */

/* {{{ proto int xdebug_pcntl_fork(void)
Dummy function to set a new connection when forking a process */
PHP_FUNCTION(xdebug_pcntl_fork)
{
XG_BASE(orig_pcntl_fork_func)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
orig_pcntl_fork_func(INTERNAL_FUNCTION_PARAM_PASSTHRU);

xdebug_debugger_restart_if_pid_changed();
}
Expand Down
4 changes: 0 additions & 4 deletions src/base/base_globals.h
Expand Up @@ -49,10 +49,6 @@ typedef struct _xdebug_base_globals_t {
xdebug_nanotime_context nanotime_context;
uint64_t start_nanotime;
unsigned int prev_memory;
zif_handler orig_set_time_limit_func;
zif_handler orig_error_reporting_func;
zif_handler orig_pcntl_exec_func;
zif_handler orig_pcntl_fork_func;
int output_is_tty;
zend_bool in_debug_info;
zend_long error_reporting_override;
Expand Down
21 changes: 7 additions & 14 deletions src/develop/develop.c
Expand Up @@ -23,26 +23,21 @@

ZEND_EXTERN_MODULE_GLOBALS(xdebug)

/* True global for overloaded var_dump */
zif_handler orig_var_dump_func;

static int xdebug_silence_handler(XDEBUG_OPCODE_HANDLER_ARGS);

static void xdebug_develop_overloaded_functions_setup(void)
{
zend_function *orig;

/* Override var_dump with our own function */
orig = zend_hash_str_find_ptr(EG(function_table), "var_dump", sizeof("var_dump") - 1);
XG_DEV(orig_var_dump_func) = orig->internal_function.handler;
orig = zend_hash_str_find_ptr(CG(function_table), "var_dump", sizeof("var_dump") - 1);
orig_var_dump_func = orig->internal_function.handler;
orig->internal_function.handler = zif_xdebug_var_dump;
}

static void xdebug_develop_overloaded_functions_restore(void)
{
zend_function *orig;

orig = zend_hash_str_find_ptr(EG(function_table), "var_dump", sizeof("var_dump") - 1);
orig->internal_function.handler = XG_DEV(orig_var_dump_func);
}


void xdebug_init_develop_globals(xdebug_develop_globals_t *xg)
{
Expand Down Expand Up @@ -79,6 +74,8 @@ void xdebug_develop_minit(INIT_FUNC_ARGS)
xdebug_set_opcode_handler(ZEND_END_SILENCE, xdebug_silence_handler);

REGISTER_LONG_CONSTANT("XDEBUG_STACK_NO_DESC", XDEBUG_STACK_NO_DESC, CONST_CS | CONST_PERSISTENT);

xdebug_develop_overloaded_functions_setup();
}

void xdebug_develop_mshutdown()
Expand All @@ -102,8 +99,6 @@ void xdebug_develop_rinit()
XG_DEV(last_exception_trace).obj_ptr[i] = NULL;
ZVAL_UNDEF(&XG_DEV(last_exception_trace).stack_trace[i]);
}

xdebug_develop_overloaded_functions_setup();
}

void xdebug_develop_rshutdown()
Expand Down Expand Up @@ -132,8 +127,6 @@ void xdebug_develop_post_deactivate()
xdebug_hash_destroy(XG_DEV(functions_to_monitor));
XG_DEV(functions_to_monitor) = NULL;
}

xdebug_develop_overloaded_functions_restore();
}


Expand Down
3 changes: 0 additions & 3 deletions src/develop/develop.h
Expand Up @@ -41,9 +41,6 @@ typedef struct _xdebug_develop_globals_t {
/* scream */
zend_bool in_at;

/* overloaded var_dump */
zif_handler orig_var_dump_func;

/* last exception stack trace */
struct {
int next_slot;
Expand Down

0 comments on commit 6cdc594

Please sign in to comment.