Rewrite SafeUriHostedModeUtils#isValid without regexp to workaround what looks
like a bug in the Sun/Oracle JVM (error not reproduced with OpenJDK).

http://gwt-code-reviews.appspot.com/1449814/

Author: tbroyer
Review by: xtof, jlabanca


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10324 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/safehtml/shared/SafeUriHostedModeUtils.java b/user/src/com/google/gwt/safehtml/shared/SafeUriHostedModeUtils.java
index 7b3dbe2..0ebb8e3 100644
--- a/user/src/com/google/gwt/safehtml/shared/SafeUriHostedModeUtils.java
+++ b/user/src/com/google/gwt/safehtml/shared/SafeUriHostedModeUtils.java
@@ -22,38 +22,33 @@
 import java.net.URISyntaxException;
 
 /**
- * SafeUri utilities whose implementation differs between Development and
- * Production Mode.
+ * SafeUri utilities whose implementation differs between Development and Production Mode.
  *
  * <p>
- * This class has a super-source peer that provides the Production Mode
- * implementation.
+ * This class has a super-source peer that provides the Production Mode implementation.
  *
  * <p>
- * Do not use this class - it is used for implementation only, and its methods
- * may change in the future.
+ * Do not use this class - it is used for implementation only, and its methods may change in the
+ * future.
  */
 public class SafeUriHostedModeUtils {
 
   /**
-   * All valid Web Addresses, i.e. the href-ucschar production from RFC 3987bis.
+   * All valid Web Addresses discrete characters, i.e. the reserved, iunreserved, href-ucschar, and
+   * href-pct-form productions from RFC 3986 and RFC 3987bis, with the exception of character
+   * ranges.
    *
    * @see <a href="http://tools.ietf.org/html/rfc3986#section-2">RFC 3986</a>
    * @see <a href="http://tools.ietf.org/html/draft-ietf-iri-3987bis-05#section-7.2">RFC 3987bis Web Addresses</a>
    */
-  static final String HREF_UCSCHAR = "("
-    + "["
-    + ":/?#\\[\\]@!$&'()*+,;=" // reserved
-    + "a-zA-Z0-9\\-._~" // iunreserved
-    + " <>\"{}|\\\\^`\u0000-\u001F\u001F-\uD7FF\uE000-\uFFFD" // href-ucschar
-    + "]"
-    + "|"
-    + "[\uD800-\uDBFF][\uDC00-\uDFFF]" // surrogate pairs
-    + ")*";
+  static final String HREF_DISCRETE_UCSCHAR = ":/?#[]@!$&'()*+,;=" // reserved
+      + "-._~" // iunreserved
+      + " <>\"{}|\\^`" // href-ucschar
+      + "%"; // href-pct-form
 
   /**
-   * Name of system property that if set, enables checks in server-side code
-   * (even if assertions are disabled).
+   * Name of system property that if set, enables checks in server-side code (even if assertions are
+   * disabled).
    */
   public static final String FORCE_CHECK_VALID_URI = "com.google.gwt.safehtml.ForceCheckValidUri";
 
@@ -64,6 +59,37 @@
   }
 
   /**
+   * Tests whether all characters in the given URI are valid Web Addresses characters.
+   */
+  // @VisibleForTesting
+  public static boolean isValidUriCharset(String uri) {
+    int len = uri.length();
+    int i = 0;
+    while (i < len) {
+      int codePoint = uri.codePointAt(i);
+      i += Character.charCount(codePoint);
+      if (Character.isSupplementaryCodePoint(codePoint)) {
+        continue;
+      }
+      if (HREF_DISCRETE_UCSCHAR.indexOf(codePoint) >= 0) {
+        continue;
+      }
+      // iunreserved ranges
+      if (('a' <= codePoint && codePoint <= 'z') || ('A' <= codePoint && codePoint <= 'Z')
+          || ('0' <= codePoint && codePoint <= '9')) {
+        continue;
+      }
+      // href-ucschar ranges
+      if ((0 <= codePoint && codePoint <= 0x1F) || (0x7F <= codePoint && codePoint <= 0xD7FF)
+          || (0xE000 <= codePoint && codePoint <= 0xFFFD)) {
+        continue;
+      }
+      return false;
+    }
+    return true;
+  }
+
+  /**
    * Checks if the provided URI is a valid Web Address (per RFC 3987bis).
    *
    * @param uri the URL to check
@@ -77,9 +103,8 @@
   }
 
   /**
-   * Sets a global flag that controls whether or not
-   * {@link #maybeCheckValidUri(String)} should perform its check in a
-   * server-side environment.
+   * Sets a global flag that controls whether or not {@link #maybeCheckValidUri(String)} should
+   * perform its check in a server-side environment.
    *
    * @param check if true, perform server-side checks.
    */
@@ -88,9 +113,8 @@
   }
 
   /**
-   * Sets a global flag that controls whether or not
-   * {@link #maybeCheckValidUri(String)} should perform its check in a
-   * server-side environment from the value of the {@value
+   * Sets a global flag that controls whether or not {@link #maybeCheckValidUri(String)} should
+   * perform its check in a server-side environment from the value of the {@value
    * FORCE_CHECK_VALID_URI} property.
    */
   // The following annotation causes javadoc to crash on Mac OS X 10.5.8,
@@ -104,17 +128,12 @@
   }
 
   private static boolean isValidUri(String uri) {
-    // TODO(xtof): The regex appears to cause stack overflows in some cases.
-    // Investigate and re-enable.
-    // if (!uri.matches(HREF_UCSCHAR)) {
-    //   return false;
-    // }
-    /*
-     * pre-process to turn href-ucschars into ucschars, and encode to URI.
-     *
-     * This is done by encoding everything, and decoding back "%25" to "%".
-     */
-    uri = UriUtils.encode(uri).replace("%25", "%");
+    if (!isValidUriCharset(uri)) {
+      return false;
+    }
+
+    // pre-process to turn href-ucschars into ucschars, and encode to URI.
+    uri = UriUtils.encodeAllowEscapes(uri);
     try {
       new URI(uri);
       return true;
diff --git a/user/super/com/google/gwt/safehtml/super/com/google/gwt/safehtml/shared/SafeUriHostedModeUtils.java b/user/super/com/google/gwt/safehtml/super/com/google/gwt/safehtml/shared/SafeUriHostedModeUtils.java
index 849ac5b..2112624 100644
--- a/user/super/com/google/gwt/safehtml/super/com/google/gwt/safehtml/shared/SafeUriHostedModeUtils.java
+++ b/user/super/com/google/gwt/safehtml/super/com/google/gwt/safehtml/shared/SafeUriHostedModeUtils.java
@@ -23,13 +23,14 @@
 
   // Unused in super-source; only defined to avoid compiler warnings
   public static final String FORCE_CHECK_VALID_URI = null;
-  static final String HREF_UCSCHAR = null;
+  static final String HREF_DISCRETE_UCSCHAR = null;
   
   public static void maybeCheckValidUri(String uri) {
     // This check is a noop in web mode.
   }
   
   // Unused in super-source; only defined to avoid compiler warnings
+  public static boolean isValidUriCharset(String uri) { return true; }
   public static void setForceCheckValidUri(boolean check) { }
-  static void setForceCheckValidUriFromProperty() { }
+  public static void setForceCheckValidUriFromProperty() { }
 }
diff --git a/user/test/com/google/gwt/safehtml/SafeHtmlGwtSuite.java b/user/test/com/google/gwt/safehtml/SafeHtmlGwtSuite.java
index e50b5ce..0ed7951 100644
--- a/user/test/com/google/gwt/safehtml/SafeHtmlGwtSuite.java
+++ b/user/test/com/google/gwt/safehtml/SafeHtmlGwtSuite.java
@@ -21,6 +21,8 @@
 import com.google.gwt.safehtml.shared.GwtSafeHtmlHostedModeUtilsTest;
 import com.google.gwt.safehtml.shared.GwtSafeHtmlStringTest;
 import com.google.gwt.safehtml.shared.GwtSafeHtmlUtilsTest;
+import com.google.gwt.safehtml.shared.GwtSafeUriHostedModeUtilsTest;
+import com.google.gwt.safehtml.shared.GwtUriUtilsTest;
 
 import junit.framework.Test;
 
@@ -37,6 +39,8 @@
     suite.addTestSuite(GwtSafeHtmlBuilderTest.class);
     suite.addTestSuite(SafeHtmlTemplatesTest.class);
     suite.addTestSuite(GwtSafeHtmlHostedModeUtilsTest.class);
+    suite.addTestSuite(GwtUriUtilsTest.class);
+    suite.addTestSuite(GwtSafeUriHostedModeUtilsTest.class);
 
     return suite;
   }
diff --git a/user/test/com/google/gwt/safehtml/SafeHtmlJreSuite.java b/user/test/com/google/gwt/safehtml/SafeHtmlJreSuite.java
index aeea6a7..66aedf5 100644
--- a/user/test/com/google/gwt/safehtml/SafeHtmlJreSuite.java
+++ b/user/test/com/google/gwt/safehtml/SafeHtmlJreSuite.java
@@ -18,6 +18,7 @@
 import com.google.gwt.safehtml.rebind.HtmlTemplateParserTest;
 import com.google.gwt.safehtml.rebind.ParsedHtmlTemplateTest;
 import com.google.gwt.safehtml.server.SafeHtmlHostedModeUtilsTest;
+import com.google.gwt.safehtml.server.SafeUriHostedModeUtilsTest;
 import com.google.gwt.safehtml.server.UriUtilsTest;
 import com.google.gwt.safehtml.shared.SafeHtmlBuilderTest;
 import com.google.gwt.safehtml.shared.SafeHtmlStringTest;
@@ -43,6 +44,8 @@
     suite.addTestSuite(HtmlTemplateParserTest.class);
     suite.addTestSuite(ParsedHtmlTemplateTest.class);
     suite.addTestSuite(SafeHtmlHostedModeUtilsTest.class);
+    suite.addTestSuite(SafeUriHostedModeUtilsTest.class);
+    suite.addTestSuite(com.google.gwt.safehtml.shared.UriUtilsTest.class);
 
     return suite;
   }
diff --git a/user/test/com/google/gwt/safehtml/server/SafeUriHostedModeUtilsTest.java b/user/test/com/google/gwt/safehtml/server/SafeUriHostedModeUtilsTest.java
new file mode 100644
index 0000000..dd640d8
--- /dev/null
+++ b/user/test/com/google/gwt/safehtml/server/SafeUriHostedModeUtilsTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.safehtml.server;
+
+import com.google.gwt.safehtml.shared.GwtSafeUriHostedModeUtilsTest;
+import com.google.gwt.safehtml.shared.SafeUriHostedModeUtils;
+
+/**
+ * JUnit tests for {@link SafeUriHostedModeUtils}.
+ */
+public class SafeUriHostedModeUtilsTest extends GwtSafeUriHostedModeUtilsTest {
+
+  // This forces a GWTTestCase to run as a vanilla JUnit TestCase.
+  @Override
+  public String getModuleName() {
+    return null;
+  }
+
+  @Override
+  protected void gwtSetUp() throws Exception {
+    super.gwtSetUp();
+    // Since we can't assume assertions are enabled, force
+    // SafeUriHostedModeUtils#maybeCheckValidUri to perform its check when running in JRE.
+    SafeUriHostedModeUtils.setForceCheckValidUri(true);
+  }
+}
diff --git a/user/test/com/google/gwt/safehtml/shared/GwtSafeHtmlHostedModeUtilsTest.java b/user/test/com/google/gwt/safehtml/shared/GwtSafeHtmlHostedModeUtilsTest.java
index 9e7fd1c..fcd5f26 100644
--- a/user/test/com/google/gwt/safehtml/shared/GwtSafeHtmlHostedModeUtilsTest.java
+++ b/user/test/com/google/gwt/safehtml/shared/GwtSafeHtmlHostedModeUtilsTest.java
@@ -30,8 +30,7 @@
 
   public void testMaybeCheckCompleteHtml() {
     if (GWT.isProdMode()) {
-      // SafeHtmlHostedModeUtils#isCompleteHtml always returns true in
-      // prod mode
+      // SafeHtmlHostedModeUtils#isCompleteHtml always returns true in prod mode
       SafeHtmlHostedModeUtils.maybeCheckCompleteHtml("<foo>blah");
       SafeHtmlHostedModeUtils.maybeCheckCompleteHtml("baz<em>foo</em> <x");
     } else {
@@ -48,27 +47,26 @@
       assertCheckCompleteHtmlFails("baz<em>foo</em> <x a=\"b\"");
       assertCheckCompleteHtmlFails("baz<em>foo</em> <x a=\"b\" ");
 
-      SafeHtmlHostedModeUtils.maybeCheckCompleteHtml(
-          "baz<em>foo</em> <x a=\"b\"> ");
-      SafeHtmlHostedModeUtils.maybeCheckCompleteHtml(
-          "baz<em>foo</em> <x a=\"b\">sadf");
-      SafeHtmlHostedModeUtils.maybeCheckCompleteHtml(
-          "baz<em>foo</em> <x a=\"b\">");
-      SafeHtmlHostedModeUtils.maybeCheckCompleteHtml(
-          "baz<em>foo</em> <x a=\"b\"/>");
-      SafeHtmlHostedModeUtils.maybeCheckCompleteHtml(
-          "baz<em>foo</em> <x a=\"b\"/>bbb");
+      SafeHtmlHostedModeUtils.maybeCheckCompleteHtml("baz<em>foo</em> <x a=\"b\"> ");
+      SafeHtmlHostedModeUtils.maybeCheckCompleteHtml("baz<em>foo</em> <x a=\"b\">sadf");
+      SafeHtmlHostedModeUtils.maybeCheckCompleteHtml("baz<em>foo</em> <x a=\"b\">");
+      SafeHtmlHostedModeUtils.maybeCheckCompleteHtml("baz<em>foo</em> <x a=\"b\"/>");
+      SafeHtmlHostedModeUtils.maybeCheckCompleteHtml("baz<em>foo</em> <x a=\"b\"/>bbb");
     }
   }
 
   private void assertCheckCompleteHtmlFails(String html) {
     try {
       SafeHtmlHostedModeUtils.maybeCheckCompleteHtml(html);
-      fail("maybeCheckCompleteHtml failed to throw exception for: " + html);
     } catch (IllegalArgumentException e) {
       // expected
+      return;
     } catch (AssertionError e) {
       // expected
+      return;
     }
+    // This must be outside the try/catch, as it throws an AssertionFailedError which, in some
+    // versions of JUnit, extends AssertionError
+    fail("maybeCheckCompleteHtml failed to throw exception for: " + html);
   }
 }
diff --git a/user/test/com/google/gwt/safehtml/shared/GwtSafeUriHostedModeUtilsTest.java b/user/test/com/google/gwt/safehtml/shared/GwtSafeUriHostedModeUtilsTest.java
new file mode 100644
index 0000000..ae95e0e
--- /dev/null
+++ b/user/test/com/google/gwt/safehtml/shared/GwtSafeUriHostedModeUtilsTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.safehtml.shared;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.junit.client.GWTTestCase;
+
+/**
+ * GWT Unit tests for {@link SafeUriHostedModeUtils}.
+ */
+public class GwtSafeUriHostedModeUtilsTest extends GWTTestCase {
+
+  @Override
+  public String getModuleName() {
+    return "com.google.gwt.safehtml.SafeHtmlTestsModule";
+  }
+
+  public void testIsValidUriCharset() {
+    if (GWT.isProdMode()) {
+      // isValidUriCharset always returns true in prod mode.
+      // Hence we short-circuit this test in prod mode.
+      return;
+    }
+    assertTrue(SafeUriHostedModeUtils.isValidUriCharset(""));
+    assertTrue(SafeUriHostedModeUtils.isValidUriCharset("blah"));
+    assertTrue(SafeUriHostedModeUtils.isValidUriCharset("blah<>foo"));
+    assertTrue(SafeUriHostedModeUtils.isValidUriCharset("blah%foo"));
+    assertTrue(SafeUriHostedModeUtils.isValidUriCharset("blah%25foo"));
+    assertTrue(SafeUriHostedModeUtils.isValidUriCharset(GwtUriUtilsTest.CONSTANT_URL));
+    assertTrue(SafeUriHostedModeUtils.isValidUriCharset(GwtUriUtilsTest.MAILTO_URL));
+    assertTrue(SafeUriHostedModeUtils.isValidUriCharset(GwtUriUtilsTest.EMPTY_GIF_DATA_URL));
+    assertTrue(SafeUriHostedModeUtils.isValidUriCharset(GwtUriUtilsTest.LONG_DATA_URL));
+    assertTrue(SafeUriHostedModeUtils.isValidUriCharset(GwtUriUtilsTest.JAVASCRIPT_URL));
+
+    assertFalse(SafeUriHostedModeUtils
+        .isValidUriCharset(GwtUriUtilsTest.INVALID_URL_UNPAIRED_SURROGATE));
+  }
+
+  public void testMaybeCheckValidUri() {
+    if (GWT.isProdMode()) {
+      // SafeUriHostedModeUtils#maybeCheckValidUri is a no-op in prod mode
+      SafeUriHostedModeUtils.maybeCheckValidUri(GwtUriUtilsTest.INVALID_URL_UNPAIRED_SURROGATE);
+    } else {
+      SafeUriHostedModeUtils.maybeCheckValidUri("");
+      SafeUriHostedModeUtils.maybeCheckValidUri("blah");
+      SafeUriHostedModeUtils.maybeCheckValidUri("blah<>foo");
+      SafeUriHostedModeUtils.maybeCheckValidUri("blah%foo");
+      SafeUriHostedModeUtils.maybeCheckValidUri("blah%25foo");
+      SafeUriHostedModeUtils.maybeCheckValidUri(GwtUriUtilsTest.CONSTANT_URL);
+      SafeUriHostedModeUtils.maybeCheckValidUri(GwtUriUtilsTest.MAILTO_URL);
+      SafeUriHostedModeUtils.maybeCheckValidUri(GwtUriUtilsTest.EMPTY_GIF_DATA_URL);
+      SafeUriHostedModeUtils.maybeCheckValidUri(GwtUriUtilsTest.LONG_DATA_URL);
+      SafeUriHostedModeUtils.maybeCheckValidUri(GwtUriUtilsTest.JAVASCRIPT_URL);
+
+      assertCheckValidUriFails(GwtUriUtilsTest.INVALID_URL_UNPAIRED_SURROGATE);
+      assertCheckValidUriFails("http://");
+
+      if (GWT.isClient()) {
+        SafeUriHostedModeUtils.maybeCheckValidUri(GWT.getModuleBaseURL());
+        SafeUriHostedModeUtils.maybeCheckValidUri(GWT.getHostPageBaseURL());
+      }
+    }
+  }
+
+  private void assertCheckValidUriFails(String uri) {
+    try {
+      SafeUriHostedModeUtils.maybeCheckValidUri(uri);
+    } catch (IllegalArgumentException e) {
+      // expected
+      return;
+    } catch (AssertionError e) {
+      // expected
+      return;
+    }
+    // This must be outside the try/catch, as it throws an AssertionFailedError which, in some
+    // versions of JUnit, extends AssertionError
+    fail("maybeCheckValidUri failed to throw exception for: " + uri);
+  }
+}
diff --git a/user/test/com/google/gwt/safehtml/shared/GwtUriUtilsTest.java b/user/test/com/google/gwt/safehtml/shared/GwtUriUtilsTest.java
index f76c66f..150cc6b 100644
--- a/user/test/com/google/gwt/safehtml/shared/GwtUriUtilsTest.java
+++ b/user/test/com/google/gwt/safehtml/shared/GwtUriUtilsTest.java
@@ -23,12 +23,29 @@
  */
 public class GwtUriUtilsTest extends GWTTestCase {
 
-  private static final String JAVASCRIPT_URL = "javascript:alert('BOOM!');";
-  private static final String MAILTO_URL = "mailto:foo@example.com";
-  private static final String CONSTANT_URL =
-    "http://gwt.google.com/samples/Showcase/Showcase.html?locale=fr#!CwCheckBox";
-  private static final String EMPTY_GIF_DATA_URL =
-    "data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==";
+  static final String INVALID_URL_UNPAIRED_SURROGATE = "a\uD800b";
+  static final String JAVASCRIPT_URL = "javascript:alert('BOOM!');";
+  static final String MAILTO_URL = "mailto:foo@example.com?subject=Hello%20world!";
+  static final String CONSTANT_URL =
+      "http://gwt.google.com/samples/Showcase/Showcase.html?locale=fr#!CwCheckBox";
+  static final String EMPTY_GIF_DATA_URL =
+      "data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==";
+  static final String LONG_DATA_URL =
+      "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAAGXRFWHRTb2Z0d2FyZQ"
+          + "BBZG9iZSBJbWFnZVJlYWR5ccllPAAAAwBQTFRFZmZm////AgICAwMDBAQEBQUFBgYGBwcHCAgICQkJCgoKCwsL"
+          + "DAwMDQ0NDg4ODw8PEBAQEREREhISExMTFBQUFRUVFhYWFxcXGBgYGRkZGhoaGxsbHBwcHR0dHh4eHx8fICAgIS"
+          + "EhIiIiIyMjJCQkJSUlJiYmJycnKCgoKSkpKioqKysrLCwsLS0tLi4uLy8vMDAwMTExMjIyMzMzNDQ0NTU1NjY2"
+          + "Nzc3ODg4OTk5Ojo6Ozs7PDw8PT09Pj4+Pz8/QEBAQUFBQkJCQ0NDRERERUVFRkZGR0dHSEhISUlJSkpKS0tLTE"
+          + "xMTU1NTk5OT09PUFBQUVFRUlJSU1NTVFRUVVVVVlZWV1dXWFhYWVlZWlpaW1tbXFxcXV1dXl5eX19fYGBgYWFh"
+          + "YmJiY2NjZGRkZWVlZmZmZ2dnaGhoaWlpampqa2trbGxsbW1tbm5ub29vcHBwcXFxcnJyc3NzdHR0dXV1dnZ2d3"
+          + "d3eHh4eXl5enp6e3t7fHx8fX19fn5+f39/gICAgYGBgoKCg4ODhISEhYWFhoaGh4eHiIiIiYmJioqKi4uLjIyM"
+          + "jY2Njo6Oj4+PkJCQkZGRkpKSk5OTlJSUlZWVlpaWl5eXmJiYmZmZmpqam5ubnJycnZ2dnp6en5+foKCgoaGhoq"
+          + "Kio6OjpKSkpaWlpqamp6enqKioqampqqqqq6urrKysra2trq6ur6+vsLCwsbGxsrKys7OztLS0tbW1tra2t7e3"
+          + "uLi4ubm5urq6u7u7vLy8vb29vr6+v7+/wMDAwcHBwsLCw8PDxMTExcXFxsbGx8fHyMjIycnJysrKy8vLzMzMzc"
+          + "3Nzs7Oz8/P0NDQ0dHR0tLS09PT1NTU1dXV1tbW19fX2NjY2dnZ2tra29vb3Nzc3d3d3t7e39/f4ODg4eHh4uLi"
+          + "4+Pj5OTk5eXl5ubm5+fn6Ojo6enp6urq6+vr7Ozs7e3t7u7u7+/v8PDw8fHx8vLy8/Pz9PT09fX19vb29/f3+P"
+          + "j4+fn5+vr6+/v7/Pz8/f39/v7+////AADF2QAAAAJ0Uk5T/wDltzBKAAAAH0lEQVR42mJghAAGGJ0GAQyMYAok"
+          + "DqLA8mlI6gACDAC8pAaCn/ezogAAAABJRU5ErkJggg==";
 
   public void testEncode_noEscape() {
     StringBuilder sb = new StringBuilder(UriUtils.DONT_NEED_ENCODING);
@@ -80,6 +97,7 @@
     assertEquals(CONSTANT_URL, UriUtils.fromTrustedString(CONSTANT_URL).asString());
     assertEquals(MAILTO_URL, UriUtils.fromTrustedString(MAILTO_URL).asString());
     assertEquals(EMPTY_GIF_DATA_URL, UriUtils.fromTrustedString(EMPTY_GIF_DATA_URL).asString());
+    assertEquals(LONG_DATA_URL, UriUtils.fromTrustedString(LONG_DATA_URL).asString());
     assertEquals(JAVASCRIPT_URL, UriUtils.fromTrustedString(JAVASCRIPT_URL).asString());
     if (GWT.isClient()) {
       assertEquals(GWT.getModuleBaseURL(),
@@ -96,7 +114,7 @@
       return;
     }
     try {
-      SafeUri u = UriUtils.fromTrustedString("a\uD800b");
+      SafeUri u = UriUtils.fromTrustedString(INVALID_URL_UNPAIRED_SURROGATE);
       fail("Should have thrown IllegalArgumentException");
     } catch (IllegalArgumentException e) {
       // expected
@@ -110,7 +128,8 @@
     assertEquals(EMPTY_GIF_DATA_URL, UriUtils.unsafeCastFromUntrustedString(EMPTY_GIF_DATA_URL)
         .asString());
     assertEquals(JAVASCRIPT_URL, UriUtils.unsafeCastFromUntrustedString(JAVASCRIPT_URL).asString());
-    assertEquals("a\uD800b", UriUtils.unsafeCastFromUntrustedString("a\uD800b").asString());
+    assertEquals(INVALID_URL_UNPAIRED_SURROGATE,
+        UriUtils.unsafeCastFromUntrustedString(INVALID_URL_UNPAIRED_SURROGATE).asString());
     if (GWT.isClient()) {
       assertEquals(GWT.getModuleBaseURL(), UriUtils.unsafeCastFromUntrustedString(
           GWT.getModuleBaseURL()).asString());