OSDN Git Service

Adjust Uri host parsing to use last instead of first @.
authorAdam Vartanian <flooey@google.com>
Tue, 7 Nov 2017 12:22:23 +0000 (12:22 +0000)
committerNikoli Cartagena <dargeren@google.com>
Tue, 14 Nov 2017 01:29:54 +0000 (17:29 -0800)
Malformed authority segments can currently cause the parser to produce
a hostname that doesn't match the hostname produced by the WHATWG URL
parsing algorithm* used by browsers, which means that a URL could be seen
as having a "safe" host when checked by an Android app but actually visit
a different host when passed to a browser.  The WHATWG URL parsing
algorithm always produces a hostname based on the last @ in the authority
segment, so we do the same.

* https://url.spec.whatwg.org/#authority-state resets the "buffer", which
  is being used to build up the host name, each time an @ is found, so it
  has the effect of using the content between the final @ and the end
  of the authority section as the hostname.

Bug: 68341964
Test: vogar android.net.UriTest (on NYC branch)
Test: cts -m CtsNetTestCases (on NYC branch)
Change-Id: Idca79f35a886de042c94d6ab66787c2e98ac8376
(cherry picked from commit cd6228dd377b2a0caa02a1e6df92f3d9ae702a95)

core/java/android/net/Uri.java
core/tests/coretests/src/android/net/UriTest.java

index 09af05c..a84f74a 100644 (file)
@@ -1065,7 +1065,7 @@ public abstract class Uri implements Parcelable, Comparable<Uri> {
                 return null;
             }
 
-            int end = authority.indexOf('@');
+            int end = authority.lastIndexOf('@');
             return end == NOT_FOUND ? null : authority.substring(0, end);
         }
 
@@ -1089,7 +1089,7 @@ public abstract class Uri implements Parcelable, Comparable<Uri> {
             }
 
             // Parse out user info and then port.
-            int userInfoSeparator = authority.indexOf('@');
+            int userInfoSeparator = authority.lastIndexOf('@');
             int portSeparator = authority.indexOf(':', userInfoSeparator);
 
             String encodedHost = portSeparator == NOT_FOUND
@@ -1115,7 +1115,7 @@ public abstract class Uri implements Parcelable, Comparable<Uri> {
 
             // Make sure we look for the port separtor *after* the user info
             // separator. We have URLs with a ':' in the user info.
-            int userInfoSeparator = authority.indexOf('@');
+            int userInfoSeparator = authority.lastIndexOf('@');
             int portSeparator = authority.indexOf(':', userInfoSeparator);
 
             if (portSeparator == NOT_FOUND) {
index 6fa28b1..27b7f9e 100644 (file)
@@ -187,6 +187,11 @@ public class UriTest extends TestCase {
         uri = Uri.parse("http://localhost");
         assertEquals("localhost", uri.getHost());
         assertEquals(-1, uri.getPort());
+
+        uri = Uri.parse("http://a:a@example.com:a@example2.com/path");
+        assertEquals("a:a@example.com:a@example2.com", uri.getAuthority());
+        assertEquals("example2.com", uri.getHost());
+        assertEquals(-1, uri.getPort());
     }
 
     @SmallTest