From d861851e3d470b9edc895e516c29d8d1e44f9948 Mon Sep 17 00:00:00 2001 From: Alex Pott <alex.a.pott@googlemail.com> Date: Wed, 12 Feb 2014 15:58:00 +0000 Subject: [PATCH] Issue #2188523 by sun: ExceptionController does not respect configured system.logging:error_level (verbose backtrace). --- .../Core/Controller/ExceptionController.php | 31 ++++++++++- core/lib/Drupal/Core/Utility/Error.php | 52 +++++++++++++++++++ 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/core/lib/Drupal/Core/Controller/ExceptionController.php b/core/lib/Drupal/Core/Controller/ExceptionController.php index c8da4bc38fd2..d79567c3ba93 100644 --- a/core/lib/Drupal/Core/Controller/ExceptionController.php +++ b/core/lib/Drupal/Core/Controller/ExceptionController.php @@ -317,13 +317,40 @@ public function on500Html(FlattenException $exception, Request $request) { $class = 'error'; // If error type is 'User notice' then treat it as debug information - // instead of an error message, see dd(). + // instead of an error message. + // @see debug() if ($error['%type'] == 'User notice') { $error['%type'] = 'Debug'; $class = 'status'; } - drupal_set_message(t('%type: !message in %function (line %line of %file).', $error), $class); + // Attempt to reduce verbosity by removing DRUPAL_ROOT from the file path + // in the message. This does not happen for (false) security. + $root_length = strlen(DRUPAL_ROOT); + if (substr($error['%file'], 0, $root_length) == DRUPAL_ROOT) { + $error['%file'] = substr($error['%file'], $root_length + 1); + } + // Should not translate the string to avoid errors producing more errors. + $message = String::format('%type: !message in %function (line %line of %file).', $error); + + // Check if verbose error reporting is on. + $error_level = $this->container->get('config.factory')->get('system.logging')->get('error_level'); + + if ($error_level == ERROR_REPORTING_DISPLAY_VERBOSE) { + $backtrace_exception = $exception; + while ($backtrace_exception->getPrevious()) { + $backtrace_exception = $backtrace_exception->getPrevious(); + } + $backtrace = $backtrace_exception->getTrace(); + // First trace is the error itself, already contained in the message. + // While the second trace is the error source and also contained in the + // message, the message doesn't contain argument values, so we output it + // once more in the backtrace. + array_shift($backtrace); + // Generate a backtrace containing only scalar argument values. + $message .= '<pre class="backtrace">' . Error::formatFlattenedBacktrace($backtrace) . '</pre>'; + } + drupal_set_message($message, $class, TRUE); } $page_content = array( diff --git a/core/lib/Drupal/Core/Utility/Error.php b/core/lib/Drupal/Core/Utility/Error.php index 669cca03a89d..e3b084f15f8e 100644 --- a/core/lib/Drupal/Core/Utility/Error.php +++ b/core/lib/Drupal/Core/Utility/Error.php @@ -185,4 +185,56 @@ public static function formatBacktrace(array $backtrace) { return $return; } + /** + * Formats a flattened backtrace into a plain-text string. + * + * The calls show values for scalar arguments and type names for complex ones. + * + * @param array $backtrace + * The backtrace of a Symfony\Component\Debug\Exception\FlattenException. + * + * @return string + * A plain-text line-wrapped string ready to be put inside <pre>. + */ + public static function formatFlattenedBacktrace(array $backtrace) { + $return = ''; + + foreach ($backtrace as $trace) { + $call = array('function' => '', 'args' => array()); + + if (isset($trace['class'])) { + $call['function'] = $trace['class'] . $trace['type'] . $trace['function']; + } + elseif (isset($trace['function'])) { + $call['function'] = $trace['function']; + } + else { + $call['function'] = 'main'; + } + + if (isset($trace['args'])) { + foreach ($trace['args'] as $arg) { + $type = $arg[0]; + $value = $arg[1]; + if ($type == 'array') { + $call['args'][] = '[' . ucfirst($type) . ']'; + } + elseif ($type == 'null') { + $call['args'][] = strtoupper($type); + } + elseif ($type == 'boolean') { + $call['args'][] = $value ? 'TRUE' : 'FALSE'; + } + else { + $call['args'][] = $value; + } + } + } + + $return .= $call['function'] . '(' . implode(', ', $call['args']) . ")\n"; + } + + return $return; + } + } -- GitLab