Bug 1020041 - Host limit in nsStandardURL. r=jduell, r=valentin, a=1.3+
authorAndrea Marchesini <amarchesini@mozilla.com>
Tue, 10 Jun 2014 12:53:54 +0100
changeset 171564 8405b3819ac80486800fda5bcec82a32a64f4e4a
parent 171563 ff91d6aebeddfb5f4d0826f3d53ff26655965eea
child 171565 8ef1dadd62781177e7b8a7a4ef9aca66f7fb4874
push id559
push userryanvm@gmail.com
push dateTue, 24 Jun 2014 21:59:29 +0000
reviewersjduell, valentin, 1
bugs1020041
milestone28.0
Bug 1020041 - Host limit in nsStandardURL. r=jduell, r=valentin, a=1.3+
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
@@ -25,25 +25,26 @@ support-files =
 [test_messageChannel.html]
 [test_messageChannel_cloning.html]
 [test_messageChannel_pingpong.html]
 [test_messageChannel_post.html]
 [test_messageChannel_pref.html]
 [test_messageChannel_start.html]
 [test_messageChannel_transferable.html]
 [test_messageChannel_unshipped.html]
+[test_messagemanager_targetchain.html]
 [test_named_frames.html]
 [test_navigator_resolve_identity.html]
 [test_nondomexception.html]
+[test_openDialogChromeOnly.html]
 [test_screen_orientation.html]
 [test_settimeout_extra_arguments.html]
 [test_setting_opener.html]
 [test_url.html]
+[test_url_empty_port.html]
+[test_url_malformedHost.html]
+[test_urlExceptions.html]
 [test_window_constructor.html]
 [test_window_cross_origin_props.html]
 [test_window_enumeration.html]
 [test_window_extensible.html]
 [test_window_indexing.html]
 [test_writable-replaceable.html]
-[test_urlExceptions.html]
-[test_openDialogChromeOnly.html]
-[test_messagemanager_targetchain.html]
-[test_url_empty_port.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,43 +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 = '';
-  is(url.port, 0, 'URL.port is 0');
+  var tests = [
+    { host: '?', expected: '' },
+    { 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: 'abcd#bla:10', expected: 'abcd'}
+  ];
 
-  var link = document.getElementById("link");
-  is(link.port, 8080, 'URL.port is 8080');
-  link.port = '';
-  is(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.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;
 nsICharsetConverterManager *nsStandardURL::gCharsetMgr = 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
 
@@ -1408,30 +1409,44 @@ 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.
 
   // First set the hostname.
   nsACString::const_iterator start, end;
   aValue.BeginReading(start);
   aValue.EndReading(end);
   nsACString::const_iterator iter(start);
+
+  FindHostLimit(iter, end);
   FindCharInReadable(':', iter, end);
 
   nsresult rv = SetHost(Substring(start, iter));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Also set the port if needed.
   if (iter != end) {
     iter++;
@@ -1449,17 +1464,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
@@ -222,16 +222,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;
@@ -266,16 +269,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 nsICharsetConverterManager  *gCharsetMgr;
     static bool                         gInitialized;
     static bool                         gEscapeUTF8;
     static bool                         gAlwaysEncodeInUTF8;
     static bool                         gEncodeQueryInUTF8;
 
 public:
 #ifdef DEBUG_DUMP_URLS_AT_SHUTDOWN