diff --git a/core/lib/Drupal/Core/Template/Attribute.php b/core/lib/Drupal/Core/Template/Attribute.php
index e9dee43..ecd1e05 100644
--- a/core/lib/Drupal/Core/Template/Attribute.php
+++ b/core/lib/Drupal/Core/Template/Attribute.php
@@ -123,12 +123,13 @@ protected function createAttributeValue($name, $value) {
$value = new AttributeBoolean($name, $value);
}
// As a development aid, we allow the value to be a safe string object.
- elseif (!is_object($value) || $value instanceof SafeStringInterface) {
+ elseif (SafeMarkup::isSafe($value)) {
// Attributes are not supposed to display HTML markup, so we just convert
// the value to plain text.
- if (SafeMarkup::isSafe($value)) {
- $value = PlainTextOutput::renderFromHtml($value);
- }
+ $value = PlainTextOutput::renderFromHtml($value);
+ $value = new AttributeString($name, $value);
+ }
+ elseif (!is_object($value)) {
$value = new AttributeString($name, $value);
}
return $value;
diff --git a/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php b/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php
index a2a4e25..3b0c5c1 100644
--- a/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php
+++ b/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php
@@ -12,7 +12,6 @@
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Cache\Context\CacheContextsManager;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
-use Drupal\Core\Entity\EntityChangedInterface;
use Drupal\Core\Form\EnforcedResponseException;
use Drupal\Core\Form\FormBuilder;
use Drupal\Core\Form\FormBuilderInterface;
diff --git a/core/tests/Drupal/Tests/Core/Template/AttributeTest.php b/core/tests/Drupal/Tests/Core/Template/AttributeTest.php
index b4a192d..6766525 100644
--- a/core/tests/Drupal/Tests/Core/Template/AttributeTest.php
+++ b/core/tests/Drupal/Tests/Core/Template/AttributeTest.php
@@ -7,6 +7,8 @@
namespace Drupal\Tests\Core\Template;
+use Drupal\Component\Utility\Html;
+use Drupal\Core\Render\SafeString;
use Drupal\Core\Template\Attribute;
use Drupal\Core\Template\AttributeArray;
use Drupal\Core\Template\AttributeString;
@@ -341,6 +343,27 @@ public function testPrint() {
}
/**
+ * @covers ::createAttributeValue
+ * @dataProvider providerTestAttributeValues
+ */
+ public function testAttributeValues(array $attributes, $expected) {
+ $this->assertEquals($expected, (new Attribute($attributes))->__toString());
+ }
+
+ public function providerTestAttributeValues() {
+ $data = [];
+
+ $string = '"> "';
+ $data['safe-object-xss1'] = [['title' => SafeString::create($string)], ' title=""> alert(123)""'];
+ $data['non-safe-object-xss1'] = [['title' => $string], ' title="' . Html::escape($string) . '"'];
+ $string = '">';
+ $data['safe-object-xss2'] = [['title' => SafeString::create($string)], ' title="">alert(123)"'];
+ $data['non-safe-object-xss2'] = [['title' => $string], ' title="' . Html::escape($string) . '"'];
+
+ return $data;
+ }
+
+ /**
* Checks that the given CSS class is present in the given HTML snippet.
*
* @param string $class