diff --git a/core/lib/Drupal/Core/Utility/LinkGenerator.php b/core/lib/Drupal/Core/Utility/LinkGenerator.php
index ab2d232..9bc00d3 100644
--- a/core/lib/Drupal/Core/Utility/LinkGenerator.php
+++ b/core/lib/Drupal/Core/Utility/LinkGenerator.php
@@ -130,21 +130,20 @@ public function generate($text, Url $url, $collect_cacheability_metadata = FALSE
     unset($variables['options']['attributes']);
     $url->setOptions($variables['options']);
 
-    // The result of the url generator is a plain-text URL. Because we are using
-    // it here in an HTML argument context, we need to encode it properly.
+    // The result of the url generator is a plain-text URL.
+    // We encode it below with SafeMarkup::format because we are using it here
+    // in an HTML argument context.
     if (!$collect_cacheability_metadata) {
-      $url = SafeMarkup::checkPlain($url->toString($collect_cacheability_metadata));
+      $url = $url->toString($collect_cacheability_metadata);
     }
     else {
       $generated_url = $url->toString($collect_cacheability_metadata);
-      $url = SafeMarkup::checkPlain($generated_url->getGeneratedUrl());
+      $url = $generated_url->getGeneratedUrl();
       $generated_link = GeneratedLink::createFromObject($generated_url);
     }
 
-    // Make sure the link text is sanitized.
-    $safe_text = SafeMarkup::escape($variables['text']);
+    $result = SafeMarkup::format('<a href="@url"@attributes>@text</a>', ['@url' => $url, '@attributes' => $attributes, '@text' => $variables['text']]);
 
-    $result = SafeMarkup::set('<a href="' . $url . '"' . $attributes . '>' . $safe_text . '</a>');
     return $collect_cacheability_metadata ? $generated_link->setGeneratedLink($result) : $result;
   }
 
diff --git a/core/tests/Drupal/Tests/Core/Utility/LinkGeneratorTest.php b/core/tests/Drupal/Tests/Core/Utility/LinkGeneratorTest.php
index 5bf2b94..76126ba 100644
--- a/core/tests/Drupal/Tests/Core/Utility/LinkGeneratorTest.php
+++ b/core/tests/Drupal/Tests/Core/Utility/LinkGeneratorTest.php
@@ -14,6 +14,7 @@
 use Drupal\Core\Url;
 use Drupal\Core\Utility\LinkGenerator;
 use Drupal\Tests\UnitTestCase;
+use Drupal\Core\DependencyInjection\ContainerBuilder;
 
 /**
  * @coversDefaultClass \Drupal\Core\Utility\LinkGenerator
@@ -181,6 +182,40 @@ public function testGenerateExternal() {
   }
 
   /**
+   * Tests the generate() method with a url containing double quotes.
+   * This tests that quotes are url encoded by the urlAssembler and therefore
+   * the final url string is not broken by being marked as safe.
+   *
+   * @covers ::generate
+   */
+  public function testGenerateUrlWithQuotes() {
+    $this->urlAssembler->expects($this->once())
+      ->method('assemble')
+      ->with('base:example', array('query' => array('foo' => '"bar"')) + $this->defaultOptions)
+      ->will($this->returnValue('/example?foo=%22bar%22'));
+
+    $path_validator = $this->getMock('Drupal\Core\Path\PathValidatorInterface');
+    $container_builder = new ContainerBuilder();
+    $container_builder->set('path.validator', $path_validator);
+    \Drupal::setContainer($container_builder);
+
+    $path = '/example?foo="bar"';
+    SafeMarkup::set($path);
+    $url = Url::fromUserInput($path);
+    $url->setUrlGenerator($this->urlGenerator);
+    $url->setUnroutedUrlAssembler($this->urlAssembler);
+
+    $result = $this->linkGenerator->generate('Drupal', $url);
+
+    $this->assertLink(array(
+      'attributes' => array(
+        'href' => '/example?foo=%22bar%22',
+      ),
+      'content' => 'Drupal',
+    ), $result, 1);
+  }
+
+  /**
    * Tests the link method with additional attributes.
    *
    * @see \Drupal\Core\Utility\LinkGenerator::generate()
diff --git a/core/tests/Drupal/Tests/Core/Utility/UnroutedUrlAssemblerTest.php b/core/tests/Drupal/Tests/Core/Utility/UnroutedUrlAssemblerTest.php
index 0433561..ede25fe 100644
--- a/core/tests/Drupal/Tests/Core/Utility/UnroutedUrlAssemblerTest.php
+++ b/core/tests/Drupal/Tests/Core/Utility/UnroutedUrlAssemblerTest.php
@@ -125,6 +125,7 @@ public function providerTestAssembleWithLocalUri() {
     return [
       ['base:example', [], FALSE, '/example'],
       ['base:example', ['query' => ['foo' => 'bar']], FALSE, '/example?foo=bar'],
+      ['base:example', ['query' => ['foo' => '"bar"']], FALSE, '/example?foo=%22bar%22'],
       ['base:example', ['fragment' => 'example', ], FALSE, '/example#example'],
       ['base:example', [], TRUE, '/subdir/example'],
       ['base:example', ['query' => ['foo' => 'bar']], TRUE, '/subdir/example?foo=bar'],
