Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix regression that discloses file path in some errors #1280

Merged
merged 7 commits into from Feb 6, 2018
14 changes: 12 additions & 2 deletions api/rest/index.php
Expand Up @@ -45,7 +45,9 @@

# Show SLIM detailed errors according to Mantis settings
$t_config = array();
if( ON == config_get_global( 'show_detailed_errors' ) ) {

$t_show_detailed_errors = ON == config_get_global( 'show_detailed_errors' );
if( $t_show_detailed_errors ) {
$t_config['settings'] = array( 'displayErrorDetails' => true );
}

Expand All @@ -70,7 +72,15 @@
return $p_response->withStatus( $p_exception->getCode(), $p_exception->getMessage() )->withJson( $t_data );
}

return $p_response->withStatus( HTTP_STATUS_INTERNAL_SERVER_ERROR, $p_exception->getMessage() )->withJson( $t_data );
$t_stack_as_string = error_stack_trace_as_string( $p_exception );
$t_error_to_log = $p_exception->getMessage() . "\n" . $t_stack_as_string;
error_log( $t_error_to_log );

if( $t_show_detailed_errors ) {
$p_response = $p_response->withJson( $t_data );
}

return $p_response->withStatus( HTTP_STATUS_INTERNAL_SERVER_ERROR );
};
};

Expand Down
16 changes: 15 additions & 1 deletion api/soap/mc_api.php
Expand Up @@ -1057,11 +1057,25 @@ function mci_get_time_tracking_from_note( $p_issue_id, array $p_note ) {
function mc_error_exception_handler( $p_exception ) {
if( is_a( $p_exception, 'Mantis\Exceptions\ClientException' ) ) {
$t_cause = 'Client';
$t_message = $p_exception->getMessage();
$t_log = false;
} else if( is_a( $p_exception, 'Mantis\Exceptions\MantisException' ) ) {
$t_cause = 'Server';
$t_message = $p_exception->getMessage();
$t_log = true;
} else {
$t_cause = 'Server';
$t_message = 'Internal Service Error';
$t_log = true;
}

if( $t_log ) {
$t_stack_as_string = error_stack_trace_as_string( $p_exception );
$t_error_to_log = $p_exception->getMessage() . "\n" . $t_stack_as_string;
error_log( $t_error_to_log );
}

$t_fault = htmlentities( $p_exception->getMessage() );
$t_fault = htmlentities( $t_message );

echo <<<EOL
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
Expand Down
89 changes: 60 additions & 29 deletions core/error_api.php
Expand Up @@ -86,25 +86,29 @@ function error_exception_handler( $p_exception ) {
}

# trigger a generic error
# TODO: we may want to log such errors
trigger_error( ERROR_PHP, ERROR );
}

/**
* Get error stack based on last exception
*
* @param Exception|null $p_exception The exception to print stack trace for. Null will check last seen exception.
* @return array The stack trace as an array
*/
function error_stack_trace() {
global $g_exception;
function error_stack_trace( $p_exception = null ) {
if( $p_exception === null ) {
global $g_exception;
$p_exception = $g_exception;
}

if ( $g_exception === null ) {
if ( $p_exception === null ) {
$t_stack = debug_backtrace();

# remove this function and its caller from the stack trace.
array_shift( $t_stack );
array_shift( $t_stack );
} else {
$t_stack = $g_exception->getTrace();
$t_stack = $p_exception->getTrace();
}

return $t_stack;
Expand Down Expand Up @@ -171,6 +175,8 @@ function error_handler( $p_type, $p_error, $p_file, $p_line, array $p_context )
}
}

$t_show_detailed_errors = config_get_global( 'show_detailed_errors' ) == ON;

# Force errors to use HALT method.
if( $p_type == E_USER_ERROR || $p_type == E_ERROR || $p_type == E_RECOVERABLE_ERROR ) {
$t_method = DISPLAY_ERROR_HALT;
Expand Down Expand Up @@ -198,9 +204,18 @@ function error_handler( $p_type, $p_error, $p_file, $p_line, array $p_context )
break;
case E_USER_ERROR:
if( $p_error == ERROR_PHP ) {
$t_error_type = 'INTERNAL APPLICATION ERROR';

global $g_exception;
$t_error_type = 'APPLICATION ERROR';
$t_error_description = $g_exception->getMessage();
$t_error_to_log = $t_error_description . "\n" . error_stack_trace_as_string();
error_log( $t_error_to_log );

# If show detailed errors is OFF hide PHP exceptions since they sometimes
# include file path.
if( !$t_show_detailed_errors ) {
$t_error_description = '';
}
} else {
$t_error_type = 'APPLICATION ERROR #' . $p_error;
$t_error_description = error_string( $p_error );
Expand Down Expand Up @@ -251,7 +266,7 @@ function error_handler( $p_type, $p_error, $p_file, $p_line, array $p_context )
if( DISPLAY_ERROR_NONE != $t_method ) {
echo $t_error_type . ': ' . $t_error_description . "\n";

if( ON == config_get_global( 'show_detailed_errors' ) ) {
if( $t_show_detailed_errors ) {
echo "\n";
error_print_stack_trace();
}
Expand Down Expand Up @@ -334,7 +349,7 @@ function error_handler( $p_type, $p_error, $p_file, $p_line, array $p_context )
}
echo '</div>';

if( ON == config_get_global( 'show_detailed_errors' ) ) {
if( $t_show_detailed_errors ) {
echo '<p>';
error_print_details( $p_file, $p_line, $p_context );
echo '</p>';
Expand Down Expand Up @@ -480,38 +495,53 @@ function error_print_context( array $p_context ) {
}

/**
* Print out a stack trace
* Get the stack trace as a string that can be logged or echoed to CLI output.
*
* @param Exception|null $p_exception The exception to print stack trace for. Null will check last seen exception.
* @return string multi-line printout of stack trace.
*/
function error_print_stack_trace() {
$t_stack = error_stack_trace();
function error_stack_trace_as_string( $p_exception = null ) {
$t_stack = error_stack_trace( $p_exception );
$t_output = '';

if( php_sapi_name() == 'cli' ) {
foreach( $t_stack as $t_frame ) {
echo ( isset( $t_frame['file'] ) ? $t_frame['file'] : '-' ), ': ' ,
( isset( $t_frame['line'] ) ? $t_frame['line'] : '-' ), ': ',
( isset( $t_frame['class'] ) ? $t_frame['class'] : '-' ), ' - ',
( isset( $t_frame['type'] ) ? $t_frame['type'] : '-' ), ' - ',
( isset( $t_frame['function'] ) ? $t_frame['function'] : '-' );

$t_args = array();
if( isset( $t_frame['args'] ) && !empty( $t_frame['args'] ) ) {
foreach( $t_frame['args'] as $t_value ) {
$t_args[] = error_build_parameter_string( $t_value );
}
echo '(', implode( $t_args, ', ' ), ' )', "\n";
} else {
echo "()\n";
foreach( $t_stack as $t_frame ) {
$t_output .= ( isset( $t_frame['file'] ) ? $t_frame['file'] : '-' ) . ': ' .
( isset( $t_frame['line'] ) ? $t_frame['line'] : '-' ) . ': ' .
( isset( $t_frame['class'] ) ? $t_frame['class'] : '-' ) . ' - ' .
( isset( $t_frame['type'] ) ? $t_frame['type'] : '-' ) . ' - ' .
( isset( $t_frame['function'] ) ? $t_frame['function'] : '-' );

$t_args = array();
if( isset( $t_frame['args'] ) && !empty( $t_frame['args'] ) ) {
foreach( $t_frame['args'] as $t_value ) {
$t_args[] = error_build_parameter_string( $t_value );
}

$t_output .= '( ' . implode( $t_args, ', ' ) . " )\n";
} else {
$t_output .= "()\n";
}

}

return $t_output;
}

/**
* Print out a stack trace
*
* @param Exception|null $p_exception The exception to print stack trace for. Null will check last seen exception.
*/
function error_print_stack_trace( $p_exception = null ) {
if( php_sapi_name() == 'cli' ) {
echo error_stack_trace_as_string( $p_exception );
return;
}

echo '<div class="table-responsive">';
echo '<table class="table table-bordered table-striped table-condensed">';
echo '<tr><th>Filename</th><th>Line</th><th></th><th></th><th>Function</th><th>Args</th></tr>';

# remove the call to the error handler from the stack trace
$t_stack = error_stack_trace( $p_exception );

foreach( $t_stack as $t_frame ) {
echo '<tr>';
Expand All @@ -527,6 +557,7 @@ function error_print_stack_trace() {
echo '<td>-</td></tr>';
}
}

echo '</table>';
}

Expand Down