⚝
One Hat Cyber Team
⚝
Your IP:
216.73.216.23
Server IP:
178.33.27.10
Server:
Linux cpanel.dev-unit.com 3.10.0-1160.108.1.el7.x86_64 #1 SMP Thu Jan 25 16:17:31 UTC 2024 x86_64
Server Software:
Apache/2.4.57 (Unix) OpenSSL/1.0.2k-fips
PHP Version:
8.2.11
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
usr
/
local
/
src
/
xdebug-3.1.4
/
src
/
develop
/
View File Name :
stack.c
/* +----------------------------------------------------------------------+ | Xdebug | +----------------------------------------------------------------------+ | Copyright (c) 2002-2021 Derick Rethans | +----------------------------------------------------------------------+ | This source file is subject to version 1.01 of the Xdebug license, | | that is bundled with this package in the file LICENSE, and is | | available at through the world-wide-web at | | https://xdebug.org/license.php | | If you did not receive a copy of the Xdebug license and are unable | | to obtain it through the world-wide-web, please send a note to | | derick@xdebug.org so we can mail you a copy immediately. | +----------------------------------------------------------------------+ */ #include "php_xdebug.h" #include "main/php_ini.h" #include "ext/standard/html.h" #include "ext/standard/php_smart_string.h" #include "zend_exceptions.h" #include "zend_generators.h" #include "monitor.h" #include "stack.h" #include "superglobals.h" #include "base/filter.h" #include "coverage/code_coverage.h" #include "lib/compat.h" #include "lib/lib_private.h" #include "lib/str.h" #include "lib/var_export_html.h" #include "lib/var_export_line.h" #include "profiler/profiler.h" ZEND_EXTERN_MODULE_GLOBALS(xdebug) static const char* text_formats[11] = { "\n", "%s: %s in %s on line %d\n", "\nCall Stack:\n", "%10.4F %10ld %3d. %s(", "'%s'", ") %s:%d\n", "\n\nVariables in local scope (#%d):\n", "\n", " $%s = %s\n", " $%s = *uninitialized*\n", "SCREAM: Error suppression ignored for\n" }; static const char* ansi_formats[11] = { "\n", "[1m[31m%s[0m: %s[22m in [31m%s[0m on line [32m%d[0m[22m\n", "\n[1mCall Stack:[22m\n", "%10.4F %10ld %3d. %s(", "'%s'", ") %s:%d\n", "\n\nVariables in local scope (#%d):\n", "\n", " $%s = %s\n", " $%s = *uninitialized*\n", "[1m[31mSCREAM[0m: Error suppression ignored for\n" }; static const char* html_formats[13] = { "<br />\n<font size='1'><table class='xdebug-error xe-%s%s' dir='ltr' border='1' cellspacing='0' cellpadding='1'>\n", "<tr><th align='left' bgcolor='#f57900' colspan=\"5\"><span style='background-color: #cc0000; color: #fce94f; font-size: x-large;'>( ! )</span> %s: %s in %s on line <i>%d</i></th></tr>\n", "<tr><th align='left' bgcolor='#e9b96e' colspan='5'>Call Stack</th></tr>\n<tr><th align='center' bgcolor='#eeeeec'>#</th><th align='left' bgcolor='#eeeeec'>Time</th><th align='left' bgcolor='#eeeeec'>Memory</th><th align='left' bgcolor='#eeeeec'>Function</th><th align='left' bgcolor='#eeeeec'>Location</th></tr>\n", "<tr><td bgcolor='#eeeeec' align='center'>%d</td><td bgcolor='#eeeeec' align='center'>%.4F</td><td bgcolor='#eeeeec' align='right'>%ld</td><td bgcolor='#eeeeec'>%s( ", "<font color='#00bb00'>'%s'</font>", " )</td><td title='%s' bgcolor='#eeeeec'>%s<b>:</b>%d</td></tr>\n", "<tr><th align='left' colspan='5' bgcolor='#e9b96e'>Variables in local scope (#%d)</th></tr>\n", "</table></font>\n", "<tr><td colspan='2' align='right' bgcolor='#eeeeec' valign='top'><pre>$%s =</pre></td><td colspan='3' bgcolor='#eeeeec'>%s</td></tr>\n", "<tr><td colspan='2' align='right' bgcolor='#eeeeec' valign='top'><pre>$%s =</pre></td><td colspan='3' bgcolor='#eeeeec' valign='top'><i>Undefined</i></td></tr>\n", " )</td><td title='%s' bgcolor='#eeeeec'><a style='color: black' href='%s'>%s<b>:</b>%d</a></td></tr>\n", "<tr><th align='left' bgcolor='#f57900' colspan=\"5\"><span style='background-color: #cc0000; color: #fce94f; font-size: x-large;'>( ! )</span> %s: %s in <a style='color: black' href='%s'>%s</a> on line <i>%d</i></th></tr>\n", "<tr><th align='left' bgcolor='#f57900' colspan=\"5\"><span style='background-color: #cc0000; color: #fce94f; font-size: x-large;'>( ! )</span> SCREAM: Error suppression ignored for</th></tr>\n" }; static const char** select_formats(int html) { if (html) { return html_formats; } else if ((XINI_DEV(cli_color) == 1 && xdebug_is_output_tty()) || (XINI_DEV(cli_color) == 2)) { return ansi_formats; } else { return text_formats; } } void xdebug_log_stack(const char *error_type_str, char *buffer, const char *error_filename, const int error_lineno) { char *tmp_log_message; int i; function_stack_entry *fse; tmp_log_message = xdebug_sprintf( "PHP %s: %s in %s on line %d", error_type_str, buffer, error_filename, error_lineno); php_log_err(tmp_log_message); xdfree(tmp_log_message); if (!XG_BASE(stack) || XDEBUG_VECTOR_COUNT(XG_BASE(stack)) < 1) { return; } fse = XDEBUG_VECTOR_HEAD(XG_BASE(stack)); php_log_err((char*) "PHP Stack trace:"); for (i = 0; i < XDEBUG_VECTOR_COUNT(XG_BASE(stack)); i++, fse++) { int c = 0; /* Comma flag */ unsigned int j = 0; /* Counter */ char *tmp_name; xdebug_str log_buffer = XDEBUG_STR_INITIALIZER; int variadic_opened = 0; int sent_variables = fse->varc; if (sent_variables > 0 && fse->var[sent_variables-1].is_variadic && Z_ISUNDEF(fse->var[sent_variables-1].data)) { sent_variables--; } tmp_name = xdebug_show_fname(fse->function, XDEBUG_SHOW_FNAME_DEFAULT); xdebug_str_add_fmt(&log_buffer, "PHP %3d. %s(", fse->level, tmp_name); xdfree(tmp_name); /* Printing vars */ for (j = 0; j < sent_variables; j++) { xdebug_str *tmp_value; if (c) { xdebug_str_add_literal(&log_buffer, ", "); } else { c = 1; } if (fse->var[j].is_variadic) { xdebug_str_add_literal(&log_buffer, "..."); variadic_opened = 1; } if (fse->var[j].name) { xdebug_str_add_fmt(&log_buffer, "$%s = ", ZSTR_VAL(fse->var[j].name)); } if (fse->var[j].is_variadic) { xdebug_str_add_literal(&log_buffer, "variadic("); c = 0; continue; } if (!Z_ISUNDEF(fse->var[j].data)) { tmp_value = xdebug_get_zval_value_line(&fse->var[j].data, 0, NULL); xdebug_str_add_str(&log_buffer, tmp_value); xdebug_str_free(tmp_value); } else { xdebug_str_add_literal(&log_buffer, "*uninitialized*"); } } if (variadic_opened) { xdebug_str_add_literal(&log_buffer, ")"); } xdebug_str_add_fmt(&log_buffer, ") %s:%d", ZSTR_VAL(fse->filename), fse->lineno); php_log_err(log_buffer.d); xdebug_str_destroy(&log_buffer); } } void xdebug_append_error_head(xdebug_str *str, int html, const char *error_type_str) { const char **formats = select_formats(html); if (html) { xdebug_str_add_fmt(str, formats[0], error_type_str, XG_DEV(in_at) ? " xe-scream" : ""); if (XG_DEV(in_at)) { xdebug_str_add_const(str, formats[12]); } } else { xdebug_str_add_const(str, formats[0]); if (XG_DEV(in_at)) { xdebug_str_add_const(str, formats[10]); } } } void xdebug_append_error_description(xdebug_str *str, int html, const char *error_type_str, const char *buffer, const char *error_filename, const int error_lineno) { const char **formats = select_formats(html); char *escaped; if (!html) { escaped = estrdup(buffer); } else { zend_string *tmp; char *first_closing = strchr(buffer, ']'); /* We do need to escape HTML entities here, as HTML chars could be in * the error message. However, PHP in some circumstances also adds an * HTML link to a manual page. That bit, we don't need to escape. So * this bit of code finds the portion that doesn't need escaping, adds * it to a tmp string, and then adds an HTML escaped string for the * rest of the original buffer. */ if (first_closing && strstr(buffer, "() [<a href=") != NULL) { smart_string special_escaped = { 0, 0, 0 }; *first_closing = '\0'; first_closing++; smart_string_appends(&special_escaped, buffer); tmp = php_escape_html_entities((unsigned char *) first_closing, strlen(first_closing), 0, 0, NULL); smart_string_appends(&special_escaped, tmp->val); zend_string_free(tmp); smart_string_0(&special_escaped); escaped = estrdup(special_escaped.c); smart_string_free(&special_escaped); } else if (strncmp(buffer, "assert()", 8) == 0) { /* Also don't escape if we're in an assert, as things are already * escaped. It's all nice and consistent ey? */ escaped = estrdup(buffer); } else { tmp = php_escape_html_entities((unsigned char *) buffer, strlen(buffer), 0, 0, NULL); escaped = estrdup(tmp->val); zend_string_free(tmp); } } if (strlen(XINI_LIB(file_link_format)) > 0 && html && strcmp(error_filename, "Unknown") != 0) { char *file_link; xdebug_format_file_link(&file_link, error_filename, error_lineno); xdebug_str_add_fmt(str, formats[11], error_type_str, escaped, file_link, error_filename, error_lineno); xdfree(file_link); } else { xdebug_str_add_fmt(str, formats[1], error_type_str, escaped, error_filename, error_lineno); } efree(escaped); } static void add_single_value(xdebug_str *str, zval *zv, int html) { xdebug_str *tmp_value = NULL; char *tmp_html_value = NULL; size_t newlen; if (html) { tmp_value = xdebug_get_zval_value_line(zv, 0, NULL); tmp_html_value = xdebug_xmlize(tmp_value->d, tmp_value->l, &newlen); xdebug_str_add_literal(str, "<span>"); xdebug_str_add(str, tmp_html_value, 0); xdebug_str_add_literal(str, "</span>"); xdebug_str_free(tmp_value); efree(tmp_html_value); } else { tmp_value = xdebug_get_zval_value_line(zv, 0, NULL); if (tmp_value) { xdebug_str_add_str(str, tmp_value); xdebug_str_free(tmp_value); } else { xdebug_str_add_literal(str, "???"); } } } #define XDEBUG_VAR_FORMAT_INITIALISED 0 #define XDEBUG_VAR_FORMAT_UNINITIALISED 1 static const char* text_var_formats[2] = { " $%s = %s\n", " $%s = *uninitialized*\n", }; static const char* ansi_var_formats[2] = { " $%s = %s\n", " $%s = *uninitialized*\n", }; static const char* html_var_formats[2] = { "<tr><td colspan='2' align='right' bgcolor='#eeeeec' valign='top'><pre>$%s =</pre></td><td colspan='3' bgcolor='#eeeeec'>%s</td></tr>\n", "<tr><td colspan='2' align='right' bgcolor='#eeeeec' valign='top'><pre>$%s =</pre></td><td colspan='3' bgcolor='#eeeeec' valign='top'><i>Undefined</i></td></tr>\n", }; static const char** get_var_format_string(int html) { if (html) { return html_var_formats; } else if ((XINI_DEV(cli_color) == 1 && xdebug_is_output_tty()) || (XINI_DEV(cli_color) == 2)) { return ansi_var_formats; } else { return text_var_formats; } } static void xdebug_dump_used_var_with_contents(void *htmlq, xdebug_hash_element* he, void *argument) { int html = *(int*) htmlq; zval zvar; xdebug_str *contents; xdebug_str *name = (xdebug_str*) he->ptr; HashTable *tmp_ht; const char **formats; xdebug_str *str = (xdebug_str *) argument; if (!he->ptr) { return; } /* Bail out on $this and $GLOBALS */ if (strcmp(name->d, "this") == 0 || strcmp(name->d, "GLOBALS") == 0) { return; } if (EG(current_execute_data) && !(ZEND_CALL_INFO(EG(current_execute_data)) & ZEND_CALL_HAS_SYMBOL_TABLE)) { zend_rebuild_symbol_table(); } tmp_ht = xdebug_lib_get_active_symbol_table(); { zend_execute_data *ex = EG(current_execute_data); while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) { ex = ex->prev_execute_data; } if (ex) { xdebug_lib_set_active_data(ex); xdebug_lib_set_active_symbol_table(ex->symbol_table); } } xdebug_get_php_symbol(&zvar, name); xdebug_lib_set_active_symbol_table(tmp_ht); formats = get_var_format_string(PG(html_errors)); if (Z_TYPE(zvar) == IS_UNDEF) { xdebug_str_add_fmt(str, formats[XDEBUG_VAR_FORMAT_UNINITIALISED], name->d); return; } if (html) { contents = xdebug_get_zval_value_html(NULL, &zvar, 0, NULL); } else { contents = xdebug_get_zval_value_line(&zvar, 0, NULL); } if (contents) { xdebug_str_add_fmt(str, formats[XDEBUG_VAR_FORMAT_INITIALISED], name->d, contents->d); } else { xdebug_str_add_fmt(str, formats[XDEBUG_VAR_FORMAT_UNINITIALISED], name->d); } if (contents) { xdebug_str_free(contents); } zval_ptr_dtor_nogc(&zvar); } void xdebug_append_printable_stack(xdebug_str *str, int html) { int printed_frames = 0; const char **formats = select_formats(html); int i; function_stack_entry *fse; if (!XG_BASE(stack) || XDEBUG_VECTOR_COUNT(XG_BASE(stack)) < 1) { return; } fse = XDEBUG_VECTOR_HEAD(XG_BASE(stack)); xdebug_str_add_const(str, formats[2]); for (i = 0; i < XDEBUG_VECTOR_COUNT(XG_BASE(stack)); i++, fse++) { int c = 0; /* Comma flag */ unsigned int j = 0; /* Counter */ char *tmp_name; int variadic_opened = 0; int sent_variables = fse->varc; if (sent_variables > 0 && fse->var[sent_variables-1].is_variadic && Z_ISUNDEF(fse->var[sent_variables-1].data)) { sent_variables--; } if (xdebug_is_stack_frame_filtered(XDEBUG_FILTER_STACK, fse)) { continue; } tmp_name = xdebug_show_fname(fse->function, html ? XDEBUG_SHOW_FNAME_ALLOW_HTML : XDEBUG_SHOW_FNAME_DEFAULT); if (html) { xdebug_str_add_fmt(str, formats[3], fse->level, XDEBUG_SECONDS_SINCE_START(fse->nanotime), fse->memory, tmp_name); } else { xdebug_str_add_fmt(str, formats[3], XDEBUG_SECONDS_SINCE_START(fse->nanotime), fse->memory, fse->level, tmp_name); } xdfree(tmp_name); /* Printing vars */ for (j = 0; j < sent_variables; j++) { if (c) { xdebug_str_add_literal(str, ", "); } else { c = 1; } if ( (fse->var[j].is_variadic && Z_ISUNDEF(fse->var[j].data)) ) { xdebug_str_add_literal(str, "..."); } if (fse->var[j].name) { if (html) { xdebug_str_add_literal(str, "<span>$"); xdebug_str_add_zstr(str, fse->var[j].name); xdebug_str_add_literal(str, " = </span>"); } else { xdebug_str_add_literal(str, "$"); xdebug_str_add_zstr(str, fse->var[j].name); xdebug_str_add_literal(str, " = "); } } if (!variadic_opened && fse->var[j].is_variadic && Z_ISUNDEF(fse->var[j].data)) { if (html) { xdebug_str_add_literal(str, "<i>variadic</i>("); } else { xdebug_str_add_literal(str, "variadic("); } c = 0; variadic_opened = 1; continue; } if (!Z_ISUNDEF(fse->var[j].data)) { add_single_value(str, &fse->var[j].data, html); } else { xdebug_str_add_literal(str, "???"); } } if (variadic_opened) { xdebug_str_add_literal(str, ")"); } if (fse->include_filename) { if (html) { xdebug_str_add_literal(str, "<font color='#00bb00'>'"); xdebug_str_add_zstr(str, fse->include_filename); xdebug_str_add_literal(str, "</font>"); } else { xdebug_str_addc(str, '\''); xdebug_str_add_zstr(str, fse->include_filename); xdebug_str_addc(str, '\''); } } if (html) { char *formatted_filename; xdebug_format_filename(&formatted_filename, "...%s%n", fse->filename); if (strlen(XINI_LIB(file_link_format)) > 0 && strcmp(ZSTR_VAL(fse->filename), "Unknown") != 0) { char *file_link; xdebug_format_file_link(&file_link, ZSTR_VAL(fse->filename), fse->lineno); xdebug_str_add_fmt(str, formats[10], ZSTR_VAL(fse->filename), file_link, formatted_filename, fse->lineno); xdfree(file_link); } else { xdebug_str_add_fmt(str, formats[5], ZSTR_VAL(fse->filename), formatted_filename, fse->lineno); } xdfree(formatted_filename); } else { xdebug_str_add_fmt(str, formats[5], ZSTR_VAL(fse->filename), fse->lineno); } printed_frames++; if (XINI_DEV(max_stack_frames) > 0 && printed_frames >= XINI_DEV(max_stack_frames)) { break; } } if (XINI_DEV(dump_globals) && !(XINI_DEV(dump_once) && XG_LIB(dumped))) { char *tmp = xdebug_get_printable_superglobals(html); if (tmp) { xdebug_str_add(str, tmp, 1); } XG_LIB(dumped) = 1; } if (XINI_DEV(show_local_vars) && XG_BASE(stack) && XDEBUG_VECTOR_TAIL(XG_BASE(stack))) { int scope_nr = XDEBUG_VECTOR_COUNT(XG_BASE(stack)); fse = XDEBUG_VECTOR_TAIL(XG_BASE(stack)); if (fse->user_defined == XDEBUG_BUILT_IN && xdebug_vector_element_is_valid(XG_BASE(stack), fse -1)) { fse = fse - 1; scope_nr--; } if (fse->declared_vars && fse->declared_vars->size) { xdebug_hash *tmp_hash; xdebug_str_add_fmt(str, formats[6], scope_nr); tmp_hash = xdebug_declared_var_hash_from_llist(fse->declared_vars); xdebug_hash_apply_with_argument(tmp_hash, (void*) &html, xdebug_dump_used_var_with_contents, (void *) str); xdebug_hash_destroy(tmp_hash); } } } void xdebug_append_error_footer(xdebug_str *str, int html) { const char **formats = select_formats(html); xdebug_str_add_const(str, formats[7]); } char *xdebug_get_printable_stack(int html, int error_type, const char *buffer, const char *error_filename, const int error_lineno, int include_decription) { char *prepend_string; char *append_string; char *error_type_str = xdebug_error_type(error_type); char *error_type_str_simple = xdebug_error_type_simple(error_type); xdebug_str str = XDEBUG_STR_INITIALIZER; prepend_string = INI_STR((char*) "error_prepend_string"); append_string = INI_STR((char*) "error_append_string"); if (prepend_string) { xdebug_str_add(&str, prepend_string, 0); } xdebug_append_error_head(&str, html, error_type_str_simple); if (include_decription) { xdebug_append_error_description(&str, html, error_type_str, buffer, error_filename, error_lineno); } xdebug_append_printable_stack(&str, html); xdebug_append_error_footer(&str, html); if (append_string) { xdebug_str_add(&str, append_string, 0); } xdfree(error_type_str); xdfree(error_type_str_simple); return str.d; } static void php_output_error(const char *error) { #ifdef PHP_DISPLAY_ERRORS_STDERR if (PG(display_errors) == PHP_DISPLAY_ERRORS_STDERR) { fputs(error, stderr); fflush(stderr); return; } #endif php_printf("%s", error); } char *xdebug_strip_php_stack_trace(char *buffer) { char *tmp_buf, *p; if (strncmp(buffer, "Uncaught ", 9) != 0) { return NULL; } /* find first new line */ p = strchr(buffer, '\n'); if (!p) { p = buffer + strlen(buffer); } else { /* find the last " in ", which isn't great and might not work... but in most cases it will */ p = xdebug_strrstr(buffer, " in "); if (!p) { p = buffer + strlen(buffer); } } /* Create new buffer */ tmp_buf = calloc(p - buffer + 1, 1); strncpy(tmp_buf, buffer, p - buffer); return tmp_buf; } static char *xdebug_handle_stack_trace(int type, char *error_type_str, const char *error_filename, const unsigned int error_lineno, char *buffer) { char *printable_stack; char *tmp_buf; /* We need to see if we have an uncaught exception fatal error now */ if (type == E_ERROR && ((tmp_buf = xdebug_strip_php_stack_trace(buffer)) != NULL)) { xdebug_str str = XDEBUG_STR_INITIALIZER; /* Append error */ xdebug_append_error_head(&str, PG(html_errors), "uncaught-exception"); xdebug_append_error_description(&str, PG(html_errors), error_type_str, tmp_buf, error_filename, error_lineno); xdebug_append_printable_stack(&str, PG(html_errors)); if (XG_BASE(last_exception_trace)) { xdebug_str_add(&str, XG_BASE(last_exception_trace), 0); } xdebug_append_error_footer(&str, PG(html_errors)); free(tmp_buf); printable_stack = str.d; } else { printable_stack = xdebug_get_printable_stack(PG(html_errors), type, buffer, error_filename, error_lineno, 1); } return printable_stack; } #if PHP_VERSION_ID >= 80000 static void clear_last_error() { if (PG(last_error_message)) { zend_string_release(PG(last_error_message)); PG(last_error_message) = NULL; } if (PG(last_error_file)) { # if PHP_VERSION_ID >= 80100 zend_string_release(PG(last_error_file)); # else free(PG(last_error_file)); # endif PG(last_error_file) = NULL; } } #else static void clear_last_error() { if (PG(last_error_message)) { char *s = PG(last_error_message); PG(last_error_message) = NULL; free(s); } if (PG(last_error_file)) { char *s = PG(last_error_file); PG(last_error_file) = NULL; free(s); } } #endif /* Error callback for formatting stack traces */ #if PHP_VERSION_ID >= 80100 void xdebug_develop_error_cb(int orig_type, zend_string *error_filename, const unsigned int error_lineno, zend_string *message) { #elif PHP_VERSION_ID >= 80000 void xdebug_develop_error_cb(int orig_type, const char *error_filename, const unsigned int error_lineno, zend_string *message) { #else void xdebug_develop_error_cb(int orig_type, const char *error_filename, const unsigned int error_lineno, const char *format, va_list args) { char *buffer; int buffer_len; #endif char *error_type_str; int display; int type = orig_type & E_ALL; error_handling_t error_handling; zend_class_entry *exception_class; #if PHP_VERSION_ID < 80000 buffer_len = vspprintf(&buffer, PG(log_errors_max_len), format, args); #endif error_type_str = xdebug_error_type(type); /* check for repeated errors to be ignored */ if (PG(ignore_repeated_errors) && PG(last_error_message)) { /* no check for PG(last_error_file) is needed since it cannot * be NULL if PG(last_error_message) is not NULL */ #if PHP_VERSION_ID >= 80000 if (!zend_string_equals(PG(last_error_message), message) #else if (strcmp(PG(last_error_message), buffer) != 0 #endif || (!PG(ignore_repeated_source) && ( (PG(last_error_lineno) != (int)error_lineno) || #if PHP_VERSION_ID >= 80100 !zend_string_equals(PG(last_error_file), error_filename) #else strcmp(PG(last_error_file), error_filename) != 0 #endif )) ) { display = 1; } else { display = 0; } } else { display = 1; } #if PHP_VERSION_ID < 70300 /* Store last error message for error_get_last() */ if (display) { clear_last_error(); if (!error_filename) { error_filename = "Unknown"; } PG(last_error_type) = type; PG(last_error_message) = strdup(buffer); PG(last_error_file) = strdup(error_filename); PG(last_error_lineno) = error_lineno; } #endif error_handling = EG(error_handling); exception_class = EG(exception_class); #if PHP_VERSION_ID >= 70300 /* according to error handling mode, throw exception or show it */ if (error_handling == EH_THROW) { #else /* according to error handling mode, suppress error, throw exception or show it */ if (error_handling != EH_NORMAL) { #endif switch (type) { case E_ERROR: case E_CORE_ERROR: case E_COMPILE_ERROR: case E_USER_ERROR: case E_PARSE: /* fatal errors are real errors and cannot be made exceptions */ break; case E_STRICT: case E_DEPRECATED: case E_USER_DEPRECATED: /* for the sake of BC to old damaged code */ break; case E_NOTICE: case E_USER_NOTICE: /* notices are no errors and are not treated as such like E_WARNINGS */ break; default: /* throw an exception if we are in EH_THROW mode * but DO NOT overwrite a pending exception */ #if PHP_VERSION_ID >= 70300 if (!EG(exception)) { #else if (error_handling == EH_THROW && !EG(exception)) { #endif #if PHP_VERSION_ID >= 80000 zend_throw_error_exception(exception_class, message, 0, type); #else zend_throw_error_exception(exception_class, buffer, 0, type); #endif } #if PHP_VERSION_ID < 80000 efree(buffer); #endif xdfree(error_type_str); return; } } #if PHP_VERSION_ID >= 70300 /* Store last error message for error_get_last() */ if (display) { clear_last_error(); if (!error_filename) { # if PHP_VERSION_ID >= 80100 error_filename = zend_string_init(ZEND_STRL("Unknown"), 0); # else error_filename = "Unknown"; # endif } PG(last_error_type) = type; # if PHP_VERSION_ID >= 80000 PG(last_error_message) = zend_string_copy(message); # else PG(last_error_message) = strdup(buffer); # endif # if PHP_VERSION_ID >= 80100 PG(last_error_file) = zend_string_copy(error_filename); # else PG(last_error_file) = strdup(error_filename); # endif PG(last_error_lineno) = error_lineno; } #endif if ((EG(error_reporting) | XINI_DEV(force_error_reporting)) & type) { /* Log to logger */ if (PG(log_errors)) { #ifdef PHP_WIN32 if (type==E_CORE_ERROR || type==E_CORE_WARNING) { #if PHP_VERSION_ID >= 80000 php_syslog(LOG_ALERT, "PHP %s: %s (%s)", error_type_str, ZSTR_VAL(message), GetCommandLine()); #else MessageBox(NULL, buffer, error_type_str, MB_OK); #endif } #endif #if PHP_VERSION_ID >= 80100 xdebug_log_stack(error_type_str, ZSTR_VAL(message), ZSTR_VAL(error_filename), error_lineno); #elif PHP_VERSION_ID >= 80000 xdebug_log_stack(error_type_str, ZSTR_VAL(message), error_filename, error_lineno); #else xdebug_log_stack(error_type_str, buffer, error_filename, error_lineno); #endif if (XINI_DEV(dump_globals) && !(XINI_DEV(dump_once) && XG_LIB(dumped))) { char *printable_stack = xdebug_get_printable_superglobals(0); if (printable_stack) { int pc; xdebug_arg *parts = xdebug_arg_ctor(); xdebug_explode("\n", printable_stack, parts, -1); for (pc = 0; pc < parts->c; pc++) { char *tmp_line = xdebug_sprintf("PHP %s", parts->args[pc]); php_log_err(tmp_line); xdfree(tmp_line); } xdebug_arg_dtor(parts); xdfree(printable_stack); php_log_err((char*) "PHP "); } } } /* Display errors */ if ((PG(display_errors) || XINI_DEV(force_display_errors)) && !PG(during_request_startup)) { char *printable_stack; #if PHP_VERSION_ID >= 80100 printable_stack = xdebug_handle_stack_trace(type, error_type_str, ZSTR_VAL(error_filename), error_lineno, ZSTR_VAL(message)); #elif PHP_VERSION_ID >= 80000 printable_stack = xdebug_handle_stack_trace(type, error_type_str, error_filename, error_lineno, ZSTR_VAL(message)); #else printable_stack = xdebug_handle_stack_trace(type, error_type_str, error_filename, error_lineno, buffer); #endif if (XG_LIB(do_collect_errors) && (type != E_ERROR) && (type != E_COMPILE_ERROR) && (type != E_USER_ERROR)) { xdebug_llist_insert_next(XG_DEV(collected_errors), XDEBUG_LLIST_TAIL(XG_DEV(collected_errors)), printable_stack); } else { php_output_error(printable_stack); xdfree(printable_stack); } } else if (XG_LIB(do_collect_errors)) { char *printable_stack; #if PHP_VERSION_ID >= 80100 printable_stack = xdebug_get_printable_stack(PG(html_errors), type, ZSTR_VAL(message), ZSTR_VAL(error_filename), error_lineno, 1); #elif PHP_VERSION_ID >= 80000 printable_stack = xdebug_get_printable_stack(PG(html_errors), type, ZSTR_VAL(message), error_filename, error_lineno, 1); #else printable_stack = xdebug_get_printable_stack(PG(html_errors), type, buffer, error_filename, error_lineno, 1); #endif xdebug_llist_insert_next(XG_DEV(collected_errors), XDEBUG_LLIST_TAIL(XG_DEV(collected_errors)), printable_stack); } } { #if PHP_VERSION_ID >= 80100 zend_string *tmp_error_filename = zend_string_copy(error_filename); #else zend_string *tmp_error_filename = zend_string_init(error_filename, strlen(error_filename), 0); #endif #if PHP_VERSION_ID >= 80000 xdebug_debugger_error_cb(tmp_error_filename, error_lineno, type, error_type_str, ZSTR_VAL(message)); #else xdebug_debugger_error_cb(tmp_error_filename, error_lineno, type, error_type_str, buffer); #endif zend_string_release(tmp_error_filename); } xdfree(error_type_str); if (type & XINI_DEV(halt_level) & XDEBUG_ALLOWED_HALT_LEVELS) { type = E_USER_ERROR; } /* Bail out if we can't recover */ switch (type) { case E_CORE_ERROR: if (!php_get_module_initialized()) { /* bad error in module startup - no way we can live with this */ exit(-2); } XDEBUG_BREAK_INTENTIONALLY_MISSING case E_ERROR: case E_RECOVERABLE_ERROR: case E_PARSE: case E_COMPILE_ERROR: case E_USER_ERROR: EG(exit_status) = 255; if (php_get_module_initialized()) { if (!PG(display_errors) && !SG(headers_sent) && SG(sapi_headers).http_response_code == 200 ) { sapi_header_line ctr = { 0, 0, 0 }; ctr.line = (char*) "HTTP/1.0 500 Internal Server Error"; ctr.line_len = sizeof("HTTP/1.0 500 Internal Server Error") - 1; sapi_header_op(SAPI_HEADER_REPLACE, &ctr); } /* the parser would return 1 (failure), we can bail out nicely */ #if PHP_VERSION_ID >= 80000 if (!(orig_type & E_DONT_BAIL)) { #else if (type != E_PARSE) { #endif /* restore memory limit */ zend_set_memory_limit(PG(memory_limit)); #if PHP_VERSION_ID < 80000 efree(buffer); #endif zend_objects_store_mark_destructed(&EG(objects_store)); _zend_bailout((char*) __FILE__, __LINE__); return; } } break; } #if PHP_VERSION_ID < 70400 /* Log if necessary */ if (!display) { efree(buffer); return; } if (PG(track_errors) && EG(active)) { zval tmp; ZVAL_STRINGL(&tmp, buffer, buffer_len); if (EG(current_execute_data)) { if (zend_set_local_var_str("php_errormsg", sizeof("php_errormsg")-1, &tmp, 0) == FAILURE) { zval_ptr_dtor(&tmp); } } else { zend_hash_str_update(&EG(symbol_table), "php_errormsg", sizeof("php_errormsg"), &tmp); } } #endif #if PHP_VERSION_ID < 80000 efree(buffer); #endif } #if PHP_VERSION_ID >= 80000 void xdebug_develop_throw_exception_hook(zend_object *exception, zval *file, zval *line, zval *code, char *code_str, zval *message) { zend_class_entry *exception_ce = exception->ce; #else void xdebug_develop_throw_exception_hook(zval *exception, zval *file, zval *line, zval *code, char *code_str, zval *message) { zend_class_entry *exception_ce = Z_OBJCE_P(exception); #endif zval *xdebug_message_trace, *previous_exception; char *exception_trace; xdebug_str tmp_str = XDEBUG_STR_INITIALIZER; zval dummy; previous_exception = zend_read_property(exception_ce, exception, "previous", sizeof("previous")-1, 1, &dummy); if (previous_exception && Z_TYPE_P(previous_exception) == IS_OBJECT) { #if PHP_VERSION_ID >= 80000 xdebug_message_trace = zend_read_property(exception_ce, Z_OBJ_P(previous_exception), "xdebug_message", sizeof("xdebug_message")-1, 1, &dummy); #else xdebug_message_trace = zend_read_property(exception_ce, previous_exception, "xdebug_message", sizeof("xdebug_message")-1, 1, &dummy); #endif if (xdebug_message_trace && Z_TYPE_P(xdebug_message_trace) != IS_NULL) { xdebug_str_add(&tmp_str, Z_STRVAL_P(xdebug_message_trace), 0); } } if (!PG(html_errors)) { xdebug_str_addc(&tmp_str, '\n'); } xdebug_append_error_description(&tmp_str, PG(html_errors), STR_NAME_VAL(exception_ce->name), message ? Z_STRVAL_P(message) : "", Z_STRVAL_P(file), Z_LVAL_P(line)); xdebug_append_printable_stack(&tmp_str, PG(html_errors)); exception_trace = tmp_str.d; zend_update_property_string(exception_ce, exception, "xdebug_message", sizeof("xdebug_message")-1, exception_trace); if (XG_BASE(last_exception_trace)) { xdfree(XG_BASE(last_exception_trace)); } XG_BASE(last_exception_trace) = exception_trace; if (XINI_DEV(show_ex_trace) || (instanceof_function(exception_ce, zend_ce_error) && XINI_DEV(show_error_trace))) { if (PG(log_errors)) { xdebug_log_stack(STR_NAME_VAL(exception_ce->name), Z_STRVAL_P(message), Z_STRVAL_P(file), Z_LVAL_P(line)); } if (PG(display_errors)) { xdebug_str displ_tmp_str = XDEBUG_STR_INITIALIZER; xdebug_append_error_head(&displ_tmp_str, PG(html_errors), "exception"); xdebug_str_add(&displ_tmp_str, exception_trace, 0); xdebug_append_error_footer(&displ_tmp_str, PG(html_errors)); php_printf("%s", displ_tmp_str.d); xdebug_str_dtor(displ_tmp_str); } } } /* {{{ proto int xdebug_get_stack_depth() Returns the stack depth */ PHP_FUNCTION(xdebug_get_stack_depth) { /* We substract one so that the function call to xdebug_get_stack_depth() * is not part of the returned depth. */ RETURN_LONG(XDEBUG_VECTOR_COUNT(XG_BASE(stack)) - 1); } /* {{{ proto array xdebug_get_function_stack() Returns an array representing the current stack */ PHP_FUNCTION(xdebug_get_function_stack) { function_stack_entry *fse; unsigned int i; unsigned int j; zval *frame; zval *params; int variadic_opened = 0; if (!XDEBUG_MODE_IS(XDEBUG_MODE_DEVELOP)) { php_error(E_WARNING, "Function must be enabled in php.ini by setting 'xdebug.mode' to 'develop'"); array_init(return_value); return; } array_init(return_value); fse = XDEBUG_VECTOR_HEAD(XG_BASE(stack)); for (i = 0; i < XDEBUG_VECTOR_COUNT(XG_BASE(stack)) - 1; i++, fse++) { int sent_variables = fse->varc; if (fse->function.function) { if (strcmp(fse->function.function, "xdebug_get_function_stack") == 0) { return; } } if (sent_variables > 0 && fse->var[sent_variables-1].is_variadic && Z_ISUNDEF(fse->var[sent_variables-1].data)) { sent_variables--; } /* Initialize frame array */ XDEBUG_MAKE_STD_ZVAL(frame); array_init(frame); /* Add data */ if (fse->function.function) { add_assoc_string_ex(frame, "function", HASH_KEY_SIZEOF("function"), fse->function.function); } if (fse->function.object_class) { add_assoc_string_ex(frame, "type", HASH_KEY_SIZEOF("type"), (char*) (fse->function.type == XFUNC_STATIC_MEMBER ? "static" : "dynamic")); add_assoc_str_ex(frame, "class", HASH_KEY_SIZEOF("class"), zend_string_copy(fse->function.object_class)); } add_assoc_str_ex(frame, "file", HASH_KEY_SIZEOF("file"), zend_string_copy(fse->filename)); add_assoc_long_ex(frame, "line", HASH_KEY_SIZEOF("line"), fse->lineno); /* Add parameters */ XDEBUG_MAKE_STD_ZVAL(params); array_init(params); add_assoc_zval_ex(frame, "params", HASH_KEY_SIZEOF("params"), params); for (j = 0; j < sent_variables; j++) { xdebug_str *argument = NULL; if (fse->var[j].is_variadic) { zval *vparams; XDEBUG_MAKE_STD_ZVAL(vparams); array_init(vparams); if (fse->var[j].name) { add_assoc_zval_ex(params, ZSTR_VAL(fse->var[j].name), ZSTR_LEN(fse->var[j].name), vparams); } else { add_index_zval(params, j, vparams); } efree(params); params = vparams; variadic_opened = 1; continue; } if (!Z_ISUNDEF(fse->var[j].data)) { argument = xdebug_get_zval_value_line(&fse->var[j].data, 0, NULL); } else { argument = xdebug_str_create_from_char((char*) "???"); } if (fse->var[j].name && !variadic_opened && argument) { add_assoc_stringl_ex(params, ZSTR_VAL(fse->var[j].name), ZSTR_LEN(fse->var[j].name), argument->d, argument->l); } else { add_index_stringl(params, j - variadic_opened, argument->d, argument->l); } if (argument) { xdebug_str_free(argument); argument = NULL; } } if (fse->include_filename) { add_assoc_str_ex(frame, "include_filename", HASH_KEY_SIZEOF("include_filename"), zend_string_copy(fse->include_filename)); } add_next_index_zval(return_value, frame); efree(params); efree(frame); } } /* }}} */