Follow-up to #2514044: Do not use SafeMarkup::format in exceptions

Problem/Motivation

We are escaping exception messages when we are creating exceptions. If the exception message is never displayed or used this wastes valuable time escaping and consume static memory in SafeMarkup::set().

Amusingly all exception messages are escaped again in Error::decodeException() so if it is displayed then there is double escaping. (Hence this issue having a bug status).

Proposed resolution

Use sprintf()/concatentation/magic strings to munge strings together when creating exceptions.

// In \Drupal\Component\Utility\UrlHelper
throw new \InvalidArgumentException(SafeMarkup::format('A path was passed when a fully qualified domain was expected.'));
// Should be
throw new \InvalidArgumentException('A path was passed when a fully qualified domain was expected.');
// In \Drupal\Core\Url
throw new \InvalidArgumentException(SafeMarkup::format("The user-entered string @user_input must begin with a '/', '?', or '#'.", ['@user_input' => $user_input]));
// Should be
throw new \InvalidArgumentException("The user-entered string $user_input must begin with a '/', '?', or '#'.");

Remaining tasks

Fix core

User interface changes

None

API changes

None

Data model changes

None

Issue fork drupal-2552163

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

alexpott created an issue. See original summary.

alexpott’s picture

Title: Do not use SafeMarkup::format in exceptions and trigger_error (the second pass) » Do not use SafeMarkup::format in exceptions, trigger_error, and debug (the second pass)
Status: Active » Needs review
StatusFileSize
new11.91 KB

Status: Needs review » Needs work

The last submitted patch, 2: 2552163.2.patch, failed testing.

Status: Needs work » Needs review

alexpott queued 2: 2552163.2.patch for re-testing.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Looks fine for me!

alexpott’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new2.06 KB
new9.85 KB

So trigger_error is not automatically escaped by the error handler unlike exceptions and debug messages. I'm going to separate out those changes. And handle them in yet another issue once #2501319: Remove SafeMarkup::set() in Error::renderExceptionSafe() and _drupal_log_error() and improve backtrace formatting consistency in _drupal_log_error(), Error::renderExceptionSafe(), and DefaultExceptionSubscriber::onHtml () lands.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

sagar ramgade’s picture

The patch attached removes sprintf usages with single and double quotes for exceptions.

Status: Needs review » Needs work

The last submitted patch, 8: drupal-remove_safe_markup_usages-2552163-8-D8.patch, failed testing.

dawehner’s picture

+++ b/core/lib/Drupal/Component/Datetime/DateTimePlus.php
@@ -307,7 +307,7 @@ public function __call($method, $args) {
     if (!method_exists($this->dateTimeObject, $method)) {
-      throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_class($this), $method));
+      throw new \BadMethodCallException('Call to undefined method ' . get_class($this)::$method . '()');
     }
     return call_user_func_array(array($this->dateTimeObject, $method), $args);
   }
@@ -331,7 +331,7 @@ public function diff($datetime2, $absolute = FALSE) {

@@ -331,7 +331,7 @@ public function diff($datetime2, $absolute = FALSE) {
       $datetime2 = $datetime2->dateTimeObject;
     }
     if (!($datetime2 instanceof \DateTime)) {
-      throw new \BadMethodCallException(sprintf('Method %s expects parameter 1 to be a \DateTime or \Drupal\Component\Datetime\DateTimePlus object', __METHOD__));
+      throw new \BadMethodCallException('Method ' . __METHOD__ .  ' expects parameter 1 to be a \DateTime or \Drupal\Component\Datetime\DateTimePlus object');
     }
     return $this->dateTimeObject->diff($datetime2, $absolute);
   }
@@ -343,7 +343,7 @@ public function diff($datetime2, $absolute = FALSE) {

@@ -343,7 +343,7 @@ public function diff($datetime2, $absolute = FALSE) {
    */
   public static function __callStatic($method, $args) {
     if (!method_exists('\DateTime', $method)) {
-      throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_called_class(), $method));
+      throw new \BadMethodCallException('Call to undefined method ' . get_called_class() . '::' . $method . '()');
     }
     return call_user_func_array(array('\DateTime', $method), $args);
   }
diff --git a/core/lib/Drupal/Component/DependencyInjection/Container.php b/core/lib/Drupal/Component/DependencyInjection/Container.php

diff --git a/core/lib/Drupal/Component/DependencyInjection/Container.php b/core/lib/Drupal/Component/DependencyInjection/Container.php
index 733490c..22f7198 100644

index 733490c..22f7198 100644
--- a/core/lib/Drupal/Component/DependencyInjection/Container.php

--- a/core/lib/Drupal/Component/DependencyInjection/Container.php
+++ b/core/lib/Drupal/Component/DependencyInjection/Container.php

+++ b/core/lib/Drupal/Component/DependencyInjection/Container.php
+++ b/core/lib/Drupal/Component/DependencyInjection/Container.php
@@ -225,7 +225,7 @@ public function reset() {

@@ -225,7 +225,7 @@ public function reset() {
    */
   protected function createService(array $definition, $id) {
     if (isset($definition['synthetic']) && $definition['synthetic'] === TRUE) {
-      throw new RuntimeException(sprintf('You have requested a synthetic service ("%s"). The service container does not know how to construct this service. The service will need to be set before it is first used.', $id));
+      throw new RuntimeException('You have requested a synthetic service ("'. $id . '"). The service container does not know how to construct this service. The service will need to be set before it is first used.');
     }
 

Let's just tackle instances which use Safemarkup::format

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

jeroent’s picture

Since SafeMarkup no longer exists, I believe this issue is outdated?

jeroent’s picture

Status: Needs work » Postponed (maintainer needs more info)
Issue tags: +Bug Smash Initiative
alexpott’s picture

Title: Do not use SafeMarkup::format in exceptions, trigger_error, and debug (the second pass) » Do not use FormattableMarkup in exceptions, trigger_error, and debug (the second pass)
Status: Postponed (maintainer needs more info) » Needs work

Well we still use \Drupal\Component\Render\FormattableMarkup in exceptions which was the replacement for SafeMarkup... for example see \Drupal\Core\Config\UnmetDependenciesException::create()

Version: 9.2.x-dev » 9.3.x-dev

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

quietone’s picture

Status: Needs work » Needs review

Just found this one. My searches didn't turn up other possible instances to change.

dcam’s picture

Status: Needs review » Needs work

The current changes look good, but I found several other instances of FormattableMarkup objects being used in exceptions. Can you double-check my findings and verify whether these should be changed by the MR too?

  • core/lib/Drupal/Core/Config/Development/ConfigSchemaChecker.php line 96
  • core/lib/Drupal/Core/Entity/ContentEntityBase.php lines 855, 866, and 877
mondrake’s picture

A maybe a PHPStan rule could be developed to prevent this to happen in the future?

longwave-bot made their first commit to this issue’s fork.

longwave’s picture

Status: Needs work » Needs review

Added a PHPStan rule.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new1.32 KB

The Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

longwave’s picture

Status: Needs work » Needs review

The PHPStan rule found some more cases, which is encouraging.