diff options
author | Chalard Jean <jchalard@google.com> | 2018-10-18 17:19:56 +0900 |
---|---|---|
committer | Chalard Jean <jchalard@google.com> | 2018-10-19 11:25:27 +0900 |
commit | 1a1d52ebb4041d3029d4790c1b3f4adc1fa08856 (patch) | |
tree | 461d048117a9a1445bc62f0226aa9b08ebe8538a | |
parent | 9b20115264b8f22e001c68d69db57dd25f91b2e3 (diff) | |
download | base-1a1d52ebb4041d3029d4790c1b3f4adc1fa08856.tar.gz |
Fix a bug where Uri can't parse IPv6 literal addresses.
Bug: 25540738
Test: added CTS in aosp change #793137 and ran them
Change-Id: Ibf870b7e87799090fae9ed456286c11990b01461
-rw-r--r-- | core/java/android/net/Uri.java | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java index 40465ceafcb8..d09f33bcb755 100644 --- a/core/java/android/net/Uri.java +++ b/core/java/android/net/Uri.java @@ -1102,19 +1102,18 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { public String getHost() { @SuppressWarnings("StringEquality") boolean cached = (host != NOT_CACHED); - return cached ? host - : (host = parseHost()); + return cached ? host : (host = parseHost()); } private String parseHost() { - String authority = getEncodedAuthority(); + final String authority = getEncodedAuthority(); if (authority == null) { return null; } // Parse out user info and then port. int userInfoSeparator = authority.lastIndexOf('@'); - int portSeparator = authority.indexOf(':', userInfoSeparator); + int portSeparator = findPortSeparator(authority); String encodedHost = portSeparator == NOT_FOUND ? authority.substring(userInfoSeparator + 1) @@ -1132,16 +1131,8 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { } private int parsePort() { - String authority = getEncodedAuthority(); - if (authority == null) { - return -1; - } - - // 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.lastIndexOf('@'); - int portSeparator = authority.indexOf(':', userInfoSeparator); - + final String authority = getEncodedAuthority(); + int portSeparator = findPortSeparator(authority); if (portSeparator == NOT_FOUND) { return -1; } @@ -1154,6 +1145,24 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { return -1; } } + + private int findPortSeparator(String authority) { + if (authority == null) { + return NOT_FOUND; + } + + // Reverse search for the ':' character that breaks as soon as a char that is neither + // a colon nor an ascii digit is encountered. Thanks to the goodness of UTF-16 encoding, + // it's not possible that a surrogate matches one of these, so this loop can just + // look for characters rather than care about code points. + for (int i = authority.length() - 1; i >= 0; --i) { + final int character = authority.charAt(i); + if (':' == character) return i; + // Character.isDigit would include non-ascii digits + if (character < '0' || character > '9') return NOT_FOUND; + } + return NOT_FOUND; + } } /** |