Bug 1020041 - Host limit in nsStandardURL. r=jduell, r=valentin, a=lmandel
authorAndrea Marchesini <amarchesini@mozilla.com>
Tue, 10 Jun 2014 12:53:54 +0100
changeset 207115 b110a17ac17b908fedb4f7c007cad77d767d8f68
parent 207114 f9b60c46c1ed454f79dbdd442147b341541109aa
child 207116 d5851385e16ae71738e7c55c6fed362543ff1aff
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjduell, valentin, lmandel
bugs1020041
milestone32.0a2
Bug 1020041 - Host limit in nsStandardURL. r=jduell, r=valentin, a=lmandel
content/base/src/Link.cpp
dom/base/test/mochitest.ini
dom/base/test/test_url_malformedHost.html
netwerk/base/src/nsStandardURL.cpp
netwerk/base/src/nsStandardURL.h
--- a/content/base/src/Link.cpp
+++ b/content/base/src/Link.cpp
@@ -178,17 +178,16 @@ Link::SetHost(const nsAString &aHost)
   nsCOMPtr<nsIURI> uri(GetURIToMutate());
   if (!uri) {
     // Ignore failures to be compatible with NS4.
     return;
   }
 
   (void)uri->SetHostPort(NS_ConvertUTF16toUTF8(aHost));
   SetHrefAttribute(uri);
-  return;
 }
 
 void
 Link::SetHostname(const nsAString &aHostname)
 {
   nsCOMPtr<nsIURI> uri(GetURIToMutate());
   if (!uri) {
     // Ignore failures to be compatible with NS4.
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -57,16 +57,17 @@ skip-if = (buildapp == 'b2g' && toolkit 
 [test_postMessage_solidus.html]
 [test_screen_orientation.html]
 [test_settimeout_extra_arguments.html]
 [test_settimeout_inner.html]
 [test_setting_opener.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_url.html]
 [test_url_empty_port.html]
+[test_url_malformedHost.html]
 [test_urlExceptions.html]
 [test_urlSearchParams.html]
 [test_urlutils_stringify.html]
 [test_window_constructor.html]
 [test_window_cross_origin_props.html]
 [test_window_enumeration.html]
 [test_window_extensible.html]
 [test_window_indexing.html]
copy from dom/base/test/test_url_empty_port.html
copy to dom/base/test/test_url_malformedHost.html
--- a/dom/base/test/test_url_empty_port.html
+++ b/dom/base/test/test_url_malformedHost.html
@@ -1,53 +1,48 @@
 
 <!DOCTYPE HTML>
 <html>
 <!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=930450
+https://bugzilla.mozilla.org/show_bug.cgi?id=1020041
 -->
 <head>
   <meta charset="utf-8">
-  <title>Test for Bug 930450</title>
+  <title>Test for Bug 1020041</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=930450">Mozilla Bug 930450</a>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1020041">Mozilla Bug 1020041</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   <iframe name="x" id="x"></iframe>
   <iframe name="y" id="y"></iframe>
 </div>
 <pre id="test">
 </pre>
   <a id="link" href="http://www.example.com:8080">foobar</a>
   <area id="area" href="http://www.example.com:8080" />
   <script type="application/javascript">
 
-  var url = new URL('http://www.example.com:8080');
-  is(url.port, 8080, 'URL.port is 8080');
-  url.port = '';
-  ise(url.port, '', 'URL.port is \'\'');
-  url.port = 0;
-  ise(url.port, '0', 'URL.port is 0');
+  var tests = [
+    { host: '?', expected: 'www.example.com' },
+    { host: 'what?' , expected: 'what' },
+    { host: 'so what' , expected: 'www.example.com' },
+    { host: 'aa#bb' , expected: 'aa' },
+    { host: 'a/b' , expected: 'a' },
+    { host: 'a\\b', expected: 'a' },
+    { host: '[2001::1]#bla:10', expected: '[2001::1]'}
+  ];
 
-  var link = document.getElementById("link");
-  is(link.port, 8080, 'URL.port is 8080');
-  link.port = '';
-  is(link.href, 'http://www.example.com/', "link.href matches");
-  ise(link.port, '', 'URL.port is \'\'');
-  link.port = 0;
-  is(link.href, 'http://www.example.com:0/', "link.href matches");
-  ise(link.port, '0', 'URL.port is 0');
+  for (var i = 0; i < tests.length; ++i) {
+    var url = new URL('http://www.example.com');
+    url.host = tests[i].host;
+    is (url.host, tests[i].expected, "URL.host is: " + url.host);
 
-  var area = document.getElementById("area");
-  is(area.port, 8080, 'URL.port is 8080');
-  area.port = '';
-  is(area.href, 'http://www.example.com/', "area.href matches");
-  ise(area.port, '', 'URL.port is \'\'');
-  area.port = 0;
-  is(area.href, 'http://www.example.com:0/', "area.href matches");
-  ise(area.port, '0', 'URL.port is 0');
+    url = new URL('http://www.example.com');
+    url.hostname = tests[i].host;
+    is (url.hostname, tests[i].expected, "URL.hostname is: " + url.host);
+  }
 
   </script>
 </body>
 </html>
--- a/netwerk/base/src/nsStandardURL.cpp
+++ b/netwerk/base/src/nsStandardURL.cpp
@@ -30,16 +30,17 @@ using namespace mozilla::ipc;
 
 static NS_DEFINE_CID(kThisImplCID, NS_THIS_STANDARDURL_IMPL_CID);
 static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
 
 nsIIDNService *nsStandardURL::gIDN = nullptr;
 bool nsStandardURL::gInitialized = false;
 bool nsStandardURL::gEscapeUTF8 = true;
 bool nsStandardURL::gAlwaysEncodeInUTF8 = true;
+char nsStandardURL::gHostLimitDigits[] = { '/', '\\', '?', '#', 0 };
 
 #if defined(PR_LOGGING)
 //
 // setenv NSPR_LOG_MODULES nsStandardURL:5
 //
 static PRLogModuleInfo *gStandardURLLog;
 #endif
 
@@ -1418,31 +1419,45 @@ nsStandardURL::SetPassword(const nsACStr
     if (shift) {
         mPassword.mLen = escPassword.Length();
         mAuthority.mLen += shift;
         ShiftFromHost(shift);
     }
     return NS_OK;
 }
 
+void
+nsStandardURL::FindHostLimit(nsACString::const_iterator& aStart,
+                             nsACString::const_iterator& aEnd)
+{
+  for (int32_t i = 0; gHostLimitDigits[i]; ++i) {
+    nsACString::const_iterator c(aStart);
+    if (FindCharInReadable(gHostLimitDigits[i], c, aEnd)) {
+      aEnd = c;
+    }
+  }
+}
+
 NS_IMETHODIMP
 nsStandardURL::SetHostPort(const nsACString &aValue)
 {
     ENSURE_MUTABLE();
 
     // We cannot simply call nsIURI::SetHost because that would treat the name as
     // an IPv6 address (like http:://[server:443]/).  We also cannot call
     // nsIURI::SetHostPort because that isn't implemented.  Sadfaces.
 
     nsACString::const_iterator start, end;
     aValue.BeginReading(start);
     aValue.EndReading(end);
     nsACString::const_iterator iter(start);
     bool isIPv6 = false;
 
+    FindHostLimit(start, end);
+
     if (*start == '[') { // IPv6 address
         if (!FindCharInReadable(']', iter, end)) {
             // the ] character is missing
             return NS_ERROR_MALFORMED_URI;
         }
         // iter now at the ']' character
         isIPv6 = true;
     } else {
@@ -1491,17 +1506,25 @@ nsStandardURL::SetHostPort(const nsACStr
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStandardURL::SetHost(const nsACString &input)
 {
     ENSURE_MUTABLE();
 
-    const nsPromiseFlatCString &flat = PromiseFlatCString(input);
+    const nsPromiseFlatCString &hostname = PromiseFlatCString(input);
+
+    nsACString::const_iterator start, end;
+    hostname.BeginReading(start);
+    hostname.EndReading(end);
+
+    FindHostLimit(start, end);
+
+    const nsCString flat(Substring(start, end));
     const char *host = flat.get();
 
     LOG(("nsStandardURL::SetHost [host=%s]\n", host));
 
     if (mURLType == URLTYPE_NO_AUTHORITY) {
         if (flat.IsEmpty())
             return NS_OK;
         NS_WARNING("cannot set host on no-auth url");
--- a/netwerk/base/src/nsStandardURL.h
+++ b/netwerk/base/src/nsStandardURL.h
@@ -221,16 +221,19 @@ private:
     void ShiftFromRef(int32_t diff)       { mRef.mPos += diff; }
 
     // fastload helper functions
     nsresult ReadSegment(nsIBinaryInputStream *, URLSegment &);
     nsresult WriteSegment(nsIBinaryOutputStream *, const URLSegment &);
 
     static void PrefsChanged(nsIPrefBranch *prefs, const char *pref);
 
+    void FindHostLimit(nsACString::const_iterator& aStart,
+                       nsACString::const_iterator& aEnd);
+
     // mSpec contains the normalized version of the URL spec (UTF-8 encoded).
     nsCString mSpec;
     int32_t   mDefaultPort;
     int32_t   mPort;
 
     // url parts (relative to mSpec)
     URLSegment mScheme;
     URLSegment mAuthority;
@@ -265,16 +268,17 @@ private:
     uint32_t mSpecEncoding    : 2; // eEncoding_xxx
     uint32_t mURLType         : 2; // nsIStandardURL::URLTYPE_xxx
     uint32_t mMutable         : 1; // nsIStandardURL::mutable
     uint32_t mSupportsFileURL : 1; // QI to nsIFileURL?
 
     // global objects.  don't use COMPtr as its destructor will cause a
     // coredump if we leak it.
     static nsIIDNService               *gIDN;
+    static char                         gHostLimitDigits[];
     static bool                         gInitialized;
     static bool                         gEscapeUTF8;
     static bool                         gAlwaysEncodeInUTF8;
     static bool                         gEncodeQueryInUTF8;
 
 public:
 #ifdef DEBUG_DUMP_URLS_AT_SHUTDOWN
     PRCList mDebugCList;