Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.1128
diff -u -p -r1.1128 common.inc
--- includes/common.inc	12 Mar 2010 14:20:32 -0000	1.1128
+++ includes/common.inc	12 Mar 2010 19:29:27 -0000
@@ -1185,6 +1185,9 @@ function check_file($filename) {
 
 /**
  * Prepare a URL for use in an HTML attribute. Strips harmful protocols.
+ * 
+ * @return
+ *   Cleaned up and HTML-escaped version of $uri.
  */
 function check_url($uri) {
   return filter_xss_bad_protocol($uri, FALSE);
Index: includes/theme.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.inc,v
retrieving revision 1.582
diff -u -p -r1.582 theme.inc
--- includes/theme.inc	4 Mar 2010 09:03:08 -0000	1.582
+++ includes/theme.inc	12 Mar 2010 19:29:27 -0000
@@ -1855,7 +1855,7 @@ function theme_item_list($variables) {
  * Returns code that emits the 'more help'-link.
  */
 function theme_more_help_link($variables) {
-  return '<div class="more-help-link">' . t('<a href="@link">More help</a>', array('@link' => check_url($variables['url']))) . '</div>';
+  return '<div class="more-help-link">' . t('<a href="!link">More help</a>', array('!link' => check_url($variables['url']))) . '</div>';
 }
 
 /**
@@ -1922,7 +1922,7 @@ function theme_html_tag($variables) {
  *   - title: A descriptive verb for the link, like 'Read more'
  */
 function theme_more_link($variables) {
-  return '<div class="more-link">' . t('<a href="@link" title="@title">More</a>', array('@link' => check_url($variables['url']), '@title' => $variables['title'])) . '</div>';
+  return '<div class="more-link">' . t('<a href="!link" title="@title">More</a>', array('!link' => check_url($variables['url']), '@title' => $variables['title'])) . '</div>';
 }
 
 /**
Index: modules/simpletest/tests/theme.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/theme.test,v
retrieving revision 1.12
diff -u -p -r1.12 theme.test
--- modules/simpletest/tests/theme.test	23 Feb 2010 18:32:00 -0000	1.12
+++ modules/simpletest/tests/theme.test	12 Mar 2010 19:29:32 -0000
@@ -124,3 +124,30 @@ class ThemeItemListUnitTest extends Drup
     $this->assertIdentical($expected, $output, 'Nested list is rendered correctly.');
   }
 }
+
+/**
+ * Unit tests for theme_more_link() and theme_more_help_link().
+ */
+class ThemeMoreLinkUnitTest extends DrupalWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Theme more link',
+      'description' => 'Test the theme_more_link() and theme_more_help_link() functions.',
+      'group' => 'Theme',
+    );
+  }
+
+  /**
+   * Test escaping.
+   */
+  function testEscaping() {
+    // Ensure that check_url() is called (bad protocols are stripped) and that
+    // check_plain() is called once and only once: just 1 & to &amp; conversion.
+    $url = 'badprotocol:http://www.google.com/#&q=more';
+    $expected = 'href="http://www.google.com/#&amp;q=more"';
+    $output1 = theme('more_link', array('url' => $url));
+    $output2 = theme('more_help_link', array('url' => $url));
+    $this->assertTrue(strpos($output1, $expected) !== FALSE, t('theme_more_link() correctly escaped the URL.'));
+    $this->assertTrue(strpos($output2, $expected) !== FALSE, t('theme_more_help_link() correctly escaped the URL.'));
+  }
+}
