Loading core/modules/dblog/src/Controller/DbLogController.php +14 −0 Original line number Diff line number Diff line Loading @@ -291,6 +291,12 @@ public function eventDetails($event_id) { ['data' => ['#markup' => $dblog->link]], ], ]; if (isset($dblog->backtrace)) { $rows[] = [ ['data' => $this->t('Backtrace'), 'header' => TRUE], $dblog->backtrace, ]; } $build['dblog_table'] = [ '#type' => 'table', '#rows' => $rows, Loading Loading @@ -350,6 +356,10 @@ protected function buildFilterQuery(Request $request) { * The record from the watchdog table. The object properties are: wid, uid, * severity, type, timestamp, message, variables, link, name. * * If the variables contain a @backtrace_string placeholder which is not * used in the message, the formatted backtrace will be assigned to a new * backtrace property on the row object which can be displayed separately. * * @return string|\Drupal\Core\StringTranslation\TranslatableMarkup|false * The formatted log message or FALSE if the message or variables properties * are not set. Loading @@ -372,6 +382,10 @@ public function formatMessage($row) { $variables['@backtrace_string'] = new FormattableMarkup( '<pre class="backtrace">@backtrace_string</pre>', $variables ); // Save a reference so the backtrace can be displayed separately. if (!str_contains($row->message, '@backtrace_string')) { $row->backtrace = $variables['@backtrace_string']; } } $message = $this->t(Xss::filterAdmin($row->message), $variables); } Loading core/modules/dblog/tests/src/Functional/DbLogTest.php +30 −0 Original line number Diff line number Diff line Loading @@ -142,6 +142,36 @@ public function testLogEventPage() { $this->assertSession()->pageTextContains('Notice'); } /** * Tests that the details page displays the backtrace for a logged \Throwable. */ public function testOnError(): void { // Log in as the admin user. $this->drupalLogin($this->adminUser); // Load a page that throws an exception in the controller, and includes its // function arguments in the exception backtrace. $this->drupalGet('error-test/trigger-exception'); // Load the details page for the most recent event logged by the "php" // logger. $query = Database::getConnection()->select('watchdog') ->condition('type', 'php'); $query->addExpression('MAX([wid])'); $wid = $query->execute()->fetchField(); $this->drupalGet('admin/reports/dblog/event/' . $wid); // Verify the page displays a dblog-event table with a "Type" header. $table = $this->assertSession()->elementExists('xpath', "//table[@class='dblog-event']"); $type = "//tr/th[contains(text(), 'Type')]/../td"; $this->assertSession()->elementsCount('xpath', $type, 1, $table); // Verify that the backtrace row exists and is HTML-encoded. $backtrace = "//tr//pre[contains(@class, 'backtrace')]"; $this->assertCount(1, $table->findAll('xpath', $backtrace)); $this->assertSession()->responseContains('<script>alert('xss')</script>'); } /** * Tests that a 403 event is logged with the exception triggering it. */ Loading core/modules/system/tests/modules/error_test/src/Controller/ErrorTestController.php +9 −1 Original line number Diff line number Diff line Loading @@ -68,9 +68,17 @@ public function generateFatals() { /** * Trigger an exception to test the exception handler. * * @param string $argument * A function argument which will be included in the exception backtrace. * * @throws \Exception */ public function triggerException() { public function triggerException(string $argument = "<script>alert('xss')</script>"): void { define('SIMPLETEST_COLLECT_ERRORS', FALSE); // Add function arguments to the exception backtrace. ini_set('zend.exception_ignore_args', FALSE); ini_set('zend.exception_string_param_max_len', 1024); throw new \Exception("Drupal & awesome"); } Loading Loading
core/modules/dblog/src/Controller/DbLogController.php +14 −0 Original line number Diff line number Diff line Loading @@ -291,6 +291,12 @@ public function eventDetails($event_id) { ['data' => ['#markup' => $dblog->link]], ], ]; if (isset($dblog->backtrace)) { $rows[] = [ ['data' => $this->t('Backtrace'), 'header' => TRUE], $dblog->backtrace, ]; } $build['dblog_table'] = [ '#type' => 'table', '#rows' => $rows, Loading Loading @@ -350,6 +356,10 @@ protected function buildFilterQuery(Request $request) { * The record from the watchdog table. The object properties are: wid, uid, * severity, type, timestamp, message, variables, link, name. * * If the variables contain a @backtrace_string placeholder which is not * used in the message, the formatted backtrace will be assigned to a new * backtrace property on the row object which can be displayed separately. * * @return string|\Drupal\Core\StringTranslation\TranslatableMarkup|false * The formatted log message or FALSE if the message or variables properties * are not set. Loading @@ -372,6 +382,10 @@ public function formatMessage($row) { $variables['@backtrace_string'] = new FormattableMarkup( '<pre class="backtrace">@backtrace_string</pre>', $variables ); // Save a reference so the backtrace can be displayed separately. if (!str_contains($row->message, '@backtrace_string')) { $row->backtrace = $variables['@backtrace_string']; } } $message = $this->t(Xss::filterAdmin($row->message), $variables); } Loading
core/modules/dblog/tests/src/Functional/DbLogTest.php +30 −0 Original line number Diff line number Diff line Loading @@ -142,6 +142,36 @@ public function testLogEventPage() { $this->assertSession()->pageTextContains('Notice'); } /** * Tests that the details page displays the backtrace for a logged \Throwable. */ public function testOnError(): void { // Log in as the admin user. $this->drupalLogin($this->adminUser); // Load a page that throws an exception in the controller, and includes its // function arguments in the exception backtrace. $this->drupalGet('error-test/trigger-exception'); // Load the details page for the most recent event logged by the "php" // logger. $query = Database::getConnection()->select('watchdog') ->condition('type', 'php'); $query->addExpression('MAX([wid])'); $wid = $query->execute()->fetchField(); $this->drupalGet('admin/reports/dblog/event/' . $wid); // Verify the page displays a dblog-event table with a "Type" header. $table = $this->assertSession()->elementExists('xpath', "//table[@class='dblog-event']"); $type = "//tr/th[contains(text(), 'Type')]/../td"; $this->assertSession()->elementsCount('xpath', $type, 1, $table); // Verify that the backtrace row exists and is HTML-encoded. $backtrace = "//tr//pre[contains(@class, 'backtrace')]"; $this->assertCount(1, $table->findAll('xpath', $backtrace)); $this->assertSession()->responseContains('<script>alert('xss')</script>'); } /** * Tests that a 403 event is logged with the exception triggering it. */ Loading
core/modules/system/tests/modules/error_test/src/Controller/ErrorTestController.php +9 −1 Original line number Diff line number Diff line Loading @@ -68,9 +68,17 @@ public function generateFatals() { /** * Trigger an exception to test the exception handler. * * @param string $argument * A function argument which will be included in the exception backtrace. * * @throws \Exception */ public function triggerException() { public function triggerException(string $argument = "<script>alert('xss')</script>"): void { define('SIMPLETEST_COLLECT_ERRORS', FALSE); // Add function arguments to the exception backtrace. ini_set('zend.exception_ignore_args', FALSE); ini_set('zend.exception_string_param_max_len', 1024); throw new \Exception("Drupal & awesome"); } Loading