Backed out changeset 9ad299b5161b (bug 1495313) for failing mochitest dom/security/test/cors/test_CrossSiteXHR.html on a CLOSED TREE
authorAndreea Pavel <apavel@mozilla.com>
Wed, 14 Nov 2018 20:55:00 +0200
changeset 446227 1f476b3ce845b4a6385c284734c60fa78b91027c
parent 446226 ca67f7683dfde881cc4ba3551cedd042e7676981
child 446228 b750cfc5a0fc392225d6e0c3892d6dceaa97b0d8
push id35038
push userrmaries@mozilla.com
push dateWed, 14 Nov 2018 22:12:17 +0000
treeherdermozilla-central@4e1b2b7e0c37 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1495313
milestone65.0a1
backs out9ad299b5161b0cedf852d56365310de499f94043
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset 9ad299b5161b (bug 1495313) for failing mochitest dom/security/test/cors/test_CrossSiteXHR.html on a CLOSED TREE
netwerk/base/nsStandardURL.cpp
netwerk/base/nsStandardURL.h
netwerk/base/nsURLParsers.cpp
netwerk/test/unit/test_standardurl.js
testing/web-platform/meta/cors/redirect-userinfo.htm.ini
testing/web-platform/meta/url/a-element-origin-xhtml.xhtml.ini
testing/web-platform/meta/url/a-element-origin.html.ini
testing/web-platform/meta/url/a-element-xhtml.xhtml.ini
testing/web-platform/meta/url/a-element.html.ini
testing/web-platform/meta/url/url-constructor.html.ini
testing/web-platform/meta/url/url-origin.html.ini
testing/web-platform/meta/url/url-setters.html.ini
testing/web-platform/meta/xhr/send-authentication-competing-names-passwords.htm.ini
--- a/netwerk/base/nsStandardURL.cpp
+++ b/netwerk/base/nsStandardURL.cpp
@@ -709,23 +709,22 @@ nsStandardURL::BuildNormalizedSpec(const
         approxLen += mScheme.mLen + 3; // includes room for "://", which we insert always
 
     // encode URL segments; convert UTF-8 to origin charset and possibly escape.
     // results written to encXXX variables only if |spec| is not already in the
     // appropriate encoding.
     {
         nsSegmentEncoder encoder;
         nsSegmentEncoder queryEncoder(encoding);
+        // Items using an extraLen of 1 don't add anything unless mLen > 0
         // Username@
-        approxLen += encoder.EncodeSegmentCount(spec, mUsername, esc_Username, encUsername, useEncUsername, 0);
-        approxLen += 1; // reserve length for @
+        approxLen += encoder.EncodeSegmentCount(spec, mUsername,  esc_Username,      encUsername,  useEncUsername, 1);
         // :password - we insert the ':' even if there's no actual password if "user:@" was in the spec
-        if (mPassword.mLen > 0) {
+        if (mPassword.mLen >= 0)
             approxLen += 1 + encoder.EncodeSegmentCount(spec, mPassword,  esc_Password,      encPassword,  useEncPassword);
-        }
         // mHost is handled differently below due to encoding differences
         MOZ_ASSERT(mPort >= -1, "Invalid negative mPort");
         if (mPort != -1 && mPort != mDefaultPort)
         {
             // :port
             portbuf.AppendInt(mPort);
             approxLen += portbuf.Length() + 1;
         }
@@ -827,36 +826,29 @@ nsStandardURL::BuildNormalizedSpec(const
         net_ToLowerCase(buf + mScheme.mPos, mScheme.mLen);
         i = AppendToBuf(buf, i, "://", 3);
     }
 
     // record authority starting position
     mAuthority.mPos = i;
 
     // append authority
-    if (mUsername.mLen > 0 || mPassword.mLen > 0) {
-        if (mUsername.mLen > 0) {
-            i = AppendSegmentToBuf(buf, i, spec, username, mUsername,
-                                   &encUsername, useEncUsername, &diff);
-            ShiftFromPassword(diff);
-        } else {
-            mUsername.mLen = -1;
-        }
+    if (mUsername.mLen > 0) {
+        i = AppendSegmentToBuf(buf, i, spec, username, mUsername,
+                               &encUsername, useEncUsername, &diff);
+        ShiftFromPassword(diff);
         if (password.mLen > 0) {
             buf[i++] = ':';
             i = AppendSegmentToBuf(buf, i, spec, password, mPassword,
                                    &encPassword, useEncPassword, &diff);
             ShiftFromHost(diff);
         } else {
             mPassword.mLen = -1;
         }
         buf[i++] = '@';
-    } else {
-        mUsername.mLen = -1;
-        mPassword.mLen = -1;
     }
     if (host.mLen > 0) {
         i = AppendSegmentToBuf(buf, i, spec, host, mHost, &encHost, useEncHost,
                                &diff);
         ShiftFromPath(diff);
 
         net_ToLowerCase(buf + mHost.mPos, mHost.mLen);
         MOZ_ASSERT(mPort >= -1, "Invalid negative mPort");
@@ -966,17 +958,16 @@ nsStandardURL::BuildNormalizedSpec(const
         }
         CoalescePath(coalesceFlag, buf + mDirectory.mPos);
     }
     mSpec.Truncate(strlen(buf));
     NS_ASSERTION(mSpec.Length() <= approxLen, "We've overflowed the mSpec buffer!");
     MOZ_ASSERT(mSpec.Length() <= (uint32_t) net_GetURLMaxLength(),
                "The spec should never be this long, we missed a check.");
 
-    MOZ_ASSERT(mUsername.mLen != 0 && mPassword.mLen != 0);
     return NS_OK;
 }
 
 bool
 nsStandardURL::SegmentIs(const URLSegment &seg, const char *val, bool ignoreCase)
 {
     // one or both may be null
     if (!val || mSpec.IsEmpty())
@@ -1267,17 +1258,17 @@ nsStandardURL::GetSpec(nsACString &resul
 // result may contain unescaped UTF-8 characters
 NS_IMETHODIMP
 nsStandardURL::GetSensitiveInfoHiddenSpec(nsACString &result)
 {
     nsresult rv = GetSpec(result);
     if (NS_FAILED(rv)) {
         return rv;
     }
-    if (mPassword.mLen > 0) {
+    if (mPassword.mLen >= 0) {
       result.ReplaceLiteral(mPassword.mPos, mPassword.mLen, "****");
     }
     return NS_OK;
 }
 
 // result may contain unescaped UTF-8 characters
 NS_IMETHODIMP
 nsStandardURL::GetSpecIgnoringRef(nsACString &result)
@@ -1673,30 +1664,46 @@ nsStandardURL::SetUserPass(const nsACStr
     }
 
     if (mSpec.Length() + input.Length() - Userpass(true).Length() > (uint32_t) net_GetURLMaxLength()) {
         return NS_ERROR_MALFORMED_URI;
     }
 
     InvalidateCache();
 
+    if (userpass.IsEmpty()) {
+        // remove user:pass
+        if (mUsername.mLen > 0) {
+            if (mPassword.mLen > 0)
+                mUsername.mLen += (mPassword.mLen + 1);
+            mUsername.mLen++;
+            mSpec.Cut(mUsername.mPos, mUsername.mLen);
+            mAuthority.mLen -= mUsername.mLen;
+            ShiftFromHost(-mUsername.mLen);
+            mUsername.mLen = -1;
+            mPassword.mLen = -1;
+        }
+
+        return NS_OK;
+    }
+
     NS_ASSERTION(mHost.mLen >= 0, "uninitialized");
 
     nsresult rv;
     uint32_t usernamePos, passwordPos;
     int32_t usernameLen, passwordLen;
 
     rv = mParser->ParseUserInfo(userpass.get(), userpass.Length(),
                                 &usernamePos, &usernameLen,
                                 &passwordPos, &passwordLen);
     if (NS_FAILED(rv)) return rv;
 
     // build new user:pass in |buf|
     nsAutoCString buf;
-    if (usernameLen > 0 || passwordLen > 0) {
+    if (usernameLen > 0) {
         nsSegmentEncoder encoder;
         bool ignoredOut;
         usernameLen = encoder.EncodeSegmentCount(userpass.get(),
                                                  URLSegment(usernamePos,
                                                             usernameLen),
                                                  esc_Username | esc_AlwaysCopy,
                                                  buf, ignoredOut);
         if (passwordLen > 0) {
@@ -1705,65 +1712,49 @@ nsStandardURL::SetUserPass(const nsACStr
                                                      URLSegment(passwordPos,
                                                                 passwordLen),
                                                      esc_Password |
                                                      esc_AlwaysCopy, buf,
                                                      ignoredOut);
         } else {
             passwordLen = -1;
         }
-        if (mUsername.mLen < 0 && mPassword.mLen < 0) {
+        if (mUsername.mLen < 0)
             buf.Append('@');
-        }
     }
 
-    int32_t shift = 0;
-
-    if (mUsername.mLen < 0 && mPassword.mLen < 0) {
+    uint32_t shift = 0;
+
+    if (mUsername.mLen < 0) {
         // no existing user:pass
         if (!buf.IsEmpty()) {
             mSpec.Insert(buf, mHost.mPos);
             mUsername.mPos = mHost.mPos;
             shift = buf.Length();
         }
     }
     else {
         // replace existing user:pass
-        uint32_t userpassLen = 0;
-        if (mUsername.mLen > 0) {
-            userpassLen += mUsername.mLen;
-        }
-        if (mPassword.mLen > 0) {
+        uint32_t userpassLen = mUsername.mLen;
+        if (mPassword.mLen >= 0)
             userpassLen += (mPassword.mLen + 1);
-        }
-        if (buf.IsEmpty()) {
-            // remove `@` character too
-            userpassLen++;
-        }
-        mSpec.Replace(mAuthority.mPos, userpassLen, buf);
+        mSpec.Replace(mUsername.mPos, userpassLen, buf);
         shift = buf.Length() - userpassLen;
     }
     if (shift) {
         ShiftFromHost(shift);
-        MOZ_DIAGNOSTIC_ASSERT(mAuthority.mLen >= -shift);
         mAuthority.mLen += shift;
     }
     // update positions and lengths
-    mUsername.mLen = usernameLen > 0 ? usernameLen : -1;
-    mUsername.mPos = mAuthority.mPos;
-    mPassword.mLen = passwordLen > 0 ? passwordLen : -1;
+    mUsername.mLen = usernameLen;
+    mPassword.mLen = passwordLen;
     if (passwordLen > 0) {
-        if (mUsername.mLen > 0) {
-            mPassword.mPos = mUsername.mPos + mUsername.mLen + 1;
-        } else {
-            mPassword.mPos = mAuthority.mPos + 1;
-        }
+        mPassword.mPos = mUsername.mPos + mUsername.mLen + 1;
     }
 
-    MOZ_ASSERT(mUsername.mLen != 0 && mPassword.mLen != 0);
     return NS_OK;
 }
 
 nsresult
 nsStandardURL::SetUsername(const nsACString &input)
 {
     const nsPromiseFlatCString &username = PromiseFlatCString(input);
 
@@ -1771,58 +1762,47 @@ nsStandardURL::SetUsername(const nsACStr
 
     if (mURLType == URLTYPE_NO_AUTHORITY) {
         if (username.IsEmpty())
             return NS_OK;
         NS_WARNING("cannot set username on no-auth url");
         return NS_ERROR_UNEXPECTED;
     }
 
+    if (username.IsEmpty())
+        return SetUserPass(username);
+
     if (mSpec.Length() + input.Length() - Username().Length() > (uint32_t) net_GetURLMaxLength()) {
         return NS_ERROR_MALFORMED_URI;
     }
 
     InvalidateCache();
 
     // escape username if necessary
     nsAutoCString buf;
     nsSegmentEncoder encoder;
     const nsACString &escUsername =
         encoder.EncodeSegment(username, esc_Username, buf);
 
-    int32_t shift = 0;
-
-    if (mUsername.mLen < 0 && escUsername.IsEmpty()) {
-        return NS_OK;
-    }
-
-    if (mUsername.mLen < 0 && mPassword.mLen < 0) {
-        MOZ_ASSERT(!escUsername.IsEmpty(), "Should not be empty at this point");
+    int32_t shift;
+
+    if (mUsername.mLen < 0) {
         mUsername.mPos = mAuthority.mPos;
         mSpec.Insert(escUsername + NS_LITERAL_CSTRING("@"), mUsername.mPos);
         shift = escUsername.Length() + 1;
-        mUsername.mLen = escUsername.Length() > 0 ? escUsername.Length() : -1;
     }
-    else {
-        uint32_t pos = mUsername.mLen < 0 ? mAuthority.mPos : mUsername.mPos;
-        int32_t len = mUsername.mLen < 0 ? 0 : mUsername.mLen;
-
-        if (mPassword.mLen < 0 && escUsername.IsEmpty()) {
-            len++; // remove the @ character too
-        }
-        shift = ReplaceSegment(pos, len, escUsername);
-        mUsername.mLen = escUsername.Length() > 0 ? escUsername.Length() : -1;
-    }
+    else
+        shift = ReplaceSegment(mUsername.mPos, mUsername.mLen, escUsername);
 
     if (shift) {
+        mUsername.mLen = escUsername.Length();
         mAuthority.mLen += shift;
         ShiftFromPassword(shift);
     }
 
-    MOZ_ASSERT(mUsername.mLen != 0 && mPassword.mLen != 0);
     return NS_OK;
 }
 
 nsresult
 nsStandardURL::SetPassword(const nsACString &input)
 {
     const nsPromiseFlatCString &password = PromiseFlatCString(input);
 
@@ -1838,69 +1818,63 @@ nsStandardURL::SetPassword(const nsACStr
     LOG(("nsStandardURL::SetPassword [password=%s]\n", password.get()));
 
     if (mURLType == URLTYPE_NO_AUTHORITY) {
         if (password.IsEmpty())
             return NS_OK;
         NS_WARNING("cannot set password on no-auth url");
         return NS_ERROR_UNEXPECTED;
     }
+    if (mUsername.mLen <= 0) {
+        if (password.IsEmpty()) {
+            MOZ_DIAGNOSTIC_ASSERT(Password().IsEmpty());
+            return NS_OK;
+        }
+        NS_WARNING("cannot set password without existing username");
+        return NS_ERROR_FAILURE;
+    }
 
     if (mSpec.Length() + input.Length() - Password().Length() > (uint32_t) net_GetURLMaxLength()) {
         return NS_ERROR_MALFORMED_URI;
     }
 
     InvalidateCache();
 
     if (password.IsEmpty()) {
-        if (mPassword.mLen > 0) {
+        if (mPassword.mLen >= 0) {
             // cut(":password")
-            int32_t len = mPassword.mLen;
-            if (mUsername.mLen < 0) {
-                len++; // also cut the @ character
-            }
-            len++; // for the : character
-            mSpec.Cut(mPassword.mPos - 1, len);
-            ShiftFromHost(-len);
-            mAuthority.mLen -= len;
+            mSpec.Cut(mPassword.mPos - 1, mPassword.mLen + 1);
+            ShiftFromHost(-(mPassword.mLen + 1));
+            mAuthority.mLen -= (mPassword.mLen + 1);
             mPassword.mLen = -1;
         }
-        MOZ_ASSERT(mUsername.mLen != 0 && mPassword.mLen != 0);
         return NS_OK;
     }
 
     // escape password if necessary
     nsAutoCString buf;
     nsSegmentEncoder encoder;
     const nsACString &escPassword =
         encoder.EncodeSegment(password, esc_Password, buf);
 
     int32_t shift;
 
     if (mPassword.mLen < 0) {
-        if (mUsername.mLen > 0) {
-            mPassword.mPos = mUsername.mPos + mUsername.mLen + 1;
-            mSpec.Insert(NS_LITERAL_CSTRING(":") + escPassword, mPassword.mPos - 1);
-            shift = escPassword.Length() + 1;
-        } else {
-            mPassword.mPos = mAuthority.mPos + 1;
-            mSpec.Insert(NS_LITERAL_CSTRING(":") + escPassword + NS_LITERAL_CSTRING("@"), mPassword.mPos - 1);
-            shift = escPassword.Length() + 2;
-        }
+        mPassword.mPos = mUsername.mPos + mUsername.mLen + 1;
+        mSpec.Insert(NS_LITERAL_CSTRING(":") + escPassword, mPassword.mPos - 1);
+        shift = escPassword.Length() + 1;
     }
     else
         shift = ReplaceSegment(mPassword.mPos, mPassword.mLen, escPassword);
 
     if (shift) {
         mPassword.mLen = escPassword.Length();
         mAuthority.mLen += shift;
         ShiftFromHost(shift);
     }
-
-    MOZ_ASSERT(mUsername.mLen != 0 && mPassword.mLen != 0);
     return NS_OK;
 }
 
 void
 nsStandardURL::FindHostLimit(nsACString::const_iterator& aStart,
                              nsACString::const_iterator& aEnd)
 {
   for (int32_t i = 0; gHostLimitDigits[i]; ++i) {
--- a/netwerk/base/nsStandardURL.h
+++ b/netwerk/base/nsStandardURL.h
@@ -529,28 +529,22 @@ nsStandardURL::Prepath()
         len = mAuthority.mPos + mAuthority.mLen;
     return Substring(mSpec, 0, len);
 }
 
 inline const nsDependentCSubstring
 nsStandardURL::Userpass(bool includeDelim)
 {
     uint32_t pos=0, len=0;
-    if (mUsername.mLen > 0 || mPassword.mLen > 0) {
-        if (mUsername.mLen > 0) {
-            pos = mUsername.mPos;
-            len = mUsername.mLen;
-            if (mPassword.mLen >= 0) {
-                len += (mPassword.mLen + 1);
-            }
-        } else {
-            pos = mPassword.mPos - 1;
-            len = mPassword.mLen + 1;
-        }
-
+    // if there is no username, then there can be no password
+    if (mUsername.mLen > 0) {
+        pos = mUsername.mPos;
+        len = mUsername.mLen;
+        if (mPassword.mLen >= 0)
+            len += (mPassword.mLen + 1);
         if (includeDelim)
             len++;
     }
     return Substring(mSpec, pos, len);
 }
 
 inline const nsDependentCSubstring
 nsStandardURL::Hostport()
--- a/netwerk/base/nsURLParsers.cpp
+++ b/netwerk/base/nsURLParsers.cpp
@@ -530,16 +530,20 @@ nsAuthURLParser::ParseUserInfo(const cha
         SET_RESULT(username, 0, -1);
         SET_RESULT(password, 0, -1);
         return NS_OK;
     }
 
     const char *p = (const char *) memchr(userinfo, ':', userinfoLen);
     if (p) {
         // userinfo = <username:password>
+        if (p == userinfo) {
+            // must have a username!
+            return NS_ERROR_MALFORMED_URI;
+        }
         SET_RESULT(username, 0, p - userinfo);
         SET_RESULT(password, p - userinfo + 1, userinfoLen - (p - userinfo + 1));
     }
     else {
         // userinfo = <username>
         SET_RESULT(username, 0, userinfoLen);
         SET_RESULT(password, 0, -1);
     }
--- a/netwerk/test/unit/test_standardurl.js
+++ b/netwerk/test/unit/test_standardurl.js
@@ -539,100 +539,24 @@ add_test(function test_emptyPassword() {
   Assert.equal(url.spec, "http://xxx:zzzz@example.com/");
   url = url.mutate().setUserPass("xxxxx:yyyyyy").finalize();
   Assert.equal(url.spec, "http://xxxxx:yyyyyy@example.com/");
   url = url.mutate().setUserPass("z:").finalize();
   Assert.equal(url.spec, "http://z@example.com/");
   url = url.mutate().setPassword("ppppppppppp").finalize();
   Assert.equal(url.spec, "http://z:ppppppppppp@example.com/");
 
-  url = stringToURL("http://example.com");
+  url = url.mutate().setUsername("").finalize(); // Should clear password too
+  Assert.equal(url.spec, "http://example.com/");
   url = url.mutate().setPassword("").finalize(); // Still empty. Should work.
   Assert.equal(url.spec, "http://example.com/");
 
   run_next_test();
 });
 
-add_test(function test_emptyUser() {
-  let url = stringToURL("http://:a@example.com/path/to/something?query#hash");
-  Assert.equal(url.spec, "http://:a@example.com/path/to/something?query#hash");
-  url = stringToURL("http://:@example.com/path/to/something?query#hash");
-  Assert.equal(url.spec, "http://example.com/path/to/something?query#hash");
-
-  const kurl = stringToURL("http://user:pass@example.com:8888/path/to/something?query#hash");
-  url = kurl.mutate().setUsername("").finalize();
-  Assert.equal(url.spec, "http://:pass@example.com:8888/path/to/something?query#hash");
-  Assert.equal(url.host, "example.com");
-  Assert.equal(url.hostPort, "example.com:8888");
-  Assert.equal(url.filePath, "/path/to/something");
-  Assert.equal(url.query, "query");
-  Assert.equal(url.ref, "hash");
-  url = kurl.mutate().setUserPass(":pass1").finalize();
-  Assert.equal(url.spec, "http://:pass1@example.com:8888/path/to/something?query#hash");
-  Assert.equal(url.host, "example.com");
-  Assert.equal(url.hostPort, "example.com:8888");
-  Assert.equal(url.filePath, "/path/to/something");
-  Assert.equal(url.query, "query");
-  Assert.equal(url.ref, "hash");
-  url = url.mutate().setUsername("user2").finalize();
-  Assert.equal(url.spec, "http://user2:pass1@example.com:8888/path/to/something?query#hash");
-  Assert.equal(url.host, "example.com");
-  url = url.mutate().setUserPass(":pass234").finalize();
-  Assert.equal(url.spec, "http://:pass234@example.com:8888/path/to/something?query#hash");
-  Assert.equal(url.host, "example.com");
-  url = url.mutate().setUserPass("").finalize();
-  Assert.equal(url.spec, "http://example.com:8888/path/to/something?query#hash");
-  Assert.equal(url.host, "example.com");
-  url = url.mutate().setPassword("pa").finalize();
-  Assert.equal(url.spec, "http://:pa@example.com:8888/path/to/something?query#hash");
-  Assert.equal(url.host, "example.com");
-  url = url.mutate().setUserPass("user:pass").finalize();
-  symmetricEquality(true, url.QueryInterface(Ci.nsIURL), kurl);
-
-  url = stringToURL("http://example.com:8888/path/to/something?query#hash");
-  url = url.mutate().setPassword("pass").finalize();
-  Assert.equal(url.spec, "http://:pass@example.com:8888/path/to/something?query#hash");
-  url = url.mutate().setUsername("").finalize();
-  Assert.equal(url.spec, "http://:pass@example.com:8888/path/to/something?query#hash");
-
-  url = stringToURL("http://example.com:8888");
-  url = url.mutate().setUsername("user").finalize();
-  url = url.mutate().setUsername("").finalize();
-  Assert.equal(url.spec, "http://example.com:8888/");
-
-  url = stringToURL("http://:pass@example.com");
-  Assert.equal(url.spec, "http://:pass@example.com/");
-  url = url.mutate().setPassword("").finalize();
-  Assert.equal(url.spec, "http://example.com/");
-  url = url.mutate().setUserPass("user:pass").finalize();
-  Assert.equal(url.spec, "http://user:pass@example.com/");
-  Assert.equal(url.host, "example.com");
-  url = url.mutate().setUserPass("u:p").finalize();
-  Assert.equal(url.spec, "http://u:p@example.com/");
-  Assert.equal(url.host, "example.com");
-  url = url.mutate().setUserPass("u1:p23").finalize();
-  Assert.equal(url.spec, "http://u1:p23@example.com/");
-  Assert.equal(url.host, "example.com");
-  url = url.mutate().setUsername("u").finalize();
-  Assert.equal(url.spec, "http://u:p23@example.com/");
-  Assert.equal(url.host, "example.com");
-  url = url.mutate().setPassword("p").finalize();
-  Assert.equal(url.spec, "http://u:p@example.com/");
-  Assert.equal(url.host, "example.com");
-
-  url = url.mutate().setUserPass("u2:p2").finalize();
-  Assert.equal(url.spec, "http://u2:p2@example.com/");
-  Assert.equal(url.host, "example.com");
-  url = url.mutate().setUserPass("u23:p23").finalize();
-  Assert.equal(url.spec, "http://u23:p23@example.com/");
-  Assert.equal(url.host, "example.com");
-
-  run_next_test();
-});
-
 registerCleanupFunction(function () {
   gPrefs.clearUserPref("network.standard-url.punycode-host");
 });
 
 add_test(function test_idna_host() {
   // See bug 945240 - this test makes sure that URLs return a punycode hostname
   // when the pref is set, or unicode otherwise.
 
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/cors/redirect-userinfo.htm.ini
@@ -0,0 +1,4 @@
+[redirect-userinfo.htm]
+  [Allow redirect without userinfo (:@ is trimmed during URL parsing)]
+    expected: FAIL
+
--- a/testing/web-platform/meta/url/a-element-origin-xhtml.xhtml.ini
+++ b/testing/web-platform/meta/url/a-element-origin-xhtml.xhtml.ini
@@ -1,9 +1,15 @@
 [a-element-origin-xhtml.xhtml]
+  [Parsing origin: <https://:@test> against <about:blank>]
+    expected: FAIL
+
+  [Parsing origin: <http://::@c@d:2> against <http://example.org/foo/bar>]
+    expected: FAIL
+
   [Parsing origin: <gopher:/example.com/> against <http://example.org/foo/bar>]
     expected: FAIL
 
   [Parsing origin: <data:/example.com/> against <http://example.org/foo/bar>]
     expected: FAIL
 
   [Parsing origin: <gopher:example.com/> against <http://example.org/foo/bar>]
     expected: FAIL
@@ -30,16 +36,25 @@
     expected: FAIL
 
   [Parsing origin: <data:example.com/> against <about:blank>]
     expected: FAIL
 
   [Parsing origin: <http::b@www.example.com> against <about:blank>]
     expected: FAIL
 
+  [Parsing origin: <http:/:b@www.example.com> against <about:blank>]
+    expected: FAIL
+
+  [Parsing origin: <http://:b@www.example.com> against <about:blank>]
+    expected: FAIL
+
+  [Parsing origin: <http://:@www.example.com> against <about:blank>]
+    expected: FAIL
+
   [Parsing origin: <i> against <sc:/pa/pa>]
     expected: FAIL
 
   [Parsing origin: <i> against <sc://ho/pa>]
     expected: FAIL
 
   [Parsing origin: <i> against <sc:///pa/pa>]
     expected: FAIL
--- a/testing/web-platform/meta/url/a-element-origin.html.ini
+++ b/testing/web-platform/meta/url/a-element-origin.html.ini
@@ -1,9 +1,15 @@
 [a-element-origin.html]
+  [Parsing origin: <https://:@test> against <about:blank>]
+    expected: FAIL
+
+  [Parsing origin: <http://::@c@d:2> against <http://example.org/foo/bar>]
+    expected: FAIL
+
   [Parsing origin: <gopher:/example.com/> against <http://example.org/foo/bar>]
     expected: FAIL
 
   [Parsing origin: <data:/example.com/> against <http://example.org/foo/bar>]
     expected: FAIL
 
   [Parsing origin: <gopher:example.com/> against <http://example.org/foo/bar>]
     expected: FAIL
@@ -30,16 +36,25 @@
     expected: FAIL
 
   [Parsing origin: <data:example.com/> against <about:blank>]
     expected: FAIL
 
   [Parsing origin: <http::b@www.example.com> against <about:blank>]
     expected: FAIL
 
+  [Parsing origin: <http:/:b@www.example.com> against <about:blank>]
+    expected: FAIL
+
+  [Parsing origin: <http://:b@www.example.com> against <about:blank>]
+    expected: FAIL
+
+  [Parsing origin: <http://:@www.example.com> against <about:blank>]
+    expected: FAIL
+
   [Parsing origin: <i> against <sc:/pa/pa>]
     expected: FAIL
 
   [Parsing origin: <i> against <sc://ho/pa>]
     expected: FAIL
 
   [Parsing origin: <i> against <sc:///pa/pa>]
     expected: FAIL
--- a/testing/web-platform/meta/url/a-element-xhtml.xhtml.ini
+++ b/testing/web-platform/meta/url/a-element-xhtml.xhtml.ini
@@ -12,16 +12,19 @@
     expected: FAIL
 
   [Parsing: <http://f: 21 / b ? d # e > against <http://example.org/foo/bar>]
     expected: FAIL
 
   [Parsing: <http::@c:29> against <http://example.org/foo/bar>]
     expected: FAIL
 
+  [Parsing: <http://::@c@d:2> against <http://example.org/foo/bar>]
+    expected: FAIL
+
   [Parsing: <http://foo.com:b@d/> against <http://example.org/foo/bar>]
     expected: FAIL
 
   [Parsing: <foo:/> against <http://example.org/foo/bar>]
     expected: FAIL
 
   [Parsing: <foo:/bar.com/> against <http://example.org/foo/bar>]
     expected: FAIL
@@ -168,16 +171,22 @@
     expected: FAIL
 
   [Parsing: <mailto:example.com/> against <about:blank>]
     expected: FAIL
 
   [Parsing: <http::b@www.example.com> against <about:blank>]
     expected: FAIL
 
+  [Parsing: <http:/:b@www.example.com> against <about:blank>]
+    expected: FAIL
+
+  [Parsing: <http://:b@www.example.com> against <about:blank>]
+    expected: FAIL
+
   [Parsing: <http:/:@/www.example.com> against <about:blank>]
     expected: FAIL
 
   [Parsing: <http://user@/www.example.com> against <about:blank>]
     expected: FAIL
 
   [Parsing: <http:@/www.example.com> against <about:blank>]
     expected: FAIL
@@ -210,16 +219,19 @@
     expected: FAIL
 
   [Parsing: <http:/@:www.example.com> against <about:blank>]
     expected: FAIL
 
   [Parsing: <http://@:www.example.com> against <about:blank>]
     expected: FAIL
 
+  [Parsing: <http://:@www.example.com> against <about:blank>]
+    expected: FAIL
+
   [Parsing: <file:..> against <http://www.example.com/test>]
     expected: FAIL
 
   [Parsing: <http://example example.com> against <http://other.com/>]
     expected: FAIL
 
   [Parsing: <http://Goo%20 goo%7C|.com> against <http://other.com/>]
     expected: FAIL
@@ -387,16 +399,19 @@
     expected: FAIL
 
   [Parsing: <http:> against <https://example.org/foo/bar>]
     expected: FAIL
 
   [Parsing: <tel:1234567890> against <http://example.org/foo/bar>]
     expected: FAIL
 
+  [Parsing: <https://:@test> against <about:blank>]
+    expected: FAIL
+
   [Parsing: <non-special://test:@test/x> against <about:blank>]
     expected: FAIL
 
   [Parsing: <non-special://:@test/x> against <about:blank>]
     expected: FAIL
 
   [Parsing: <http://10000000000> against <http://other.com/>]
     expected: FAIL
--- a/testing/web-platform/meta/url/a-element.html.ini
+++ b/testing/web-platform/meta/url/a-element.html.ini
@@ -12,16 +12,19 @@
     expected: FAIL
 
   [Parsing: <http://f: 21 / b ? d # e > against <http://example.org/foo/bar>]
     expected: FAIL
 
   [Parsing: <http::@c:29> against <http://example.org/foo/bar>]
     expected: FAIL
 
+  [Parsing: <http://::@c@d:2> against <http://example.org/foo/bar>]
+    expected: FAIL
+
   [Parsing: <http://foo.com:b@d/> against <http://example.org/foo/bar>]
     expected: FAIL
 
   [Parsing: <foo:/> against <http://example.org/foo/bar>]
     expected: FAIL
 
   [Parsing: <foo:/bar.com/> against <http://example.org/foo/bar>]
     expected: FAIL
@@ -168,16 +171,22 @@
     expected: FAIL
 
   [Parsing: <mailto:example.com/> against <about:blank>]
     expected: FAIL
 
   [Parsing: <http::b@www.example.com> against <about:blank>]
     expected: FAIL
 
+  [Parsing: <http:/:b@www.example.com> against <about:blank>]
+    expected: FAIL
+
+  [Parsing: <http://:b@www.example.com> against <about:blank>]
+    expected: FAIL
+
   [Parsing: <http:/:@/www.example.com> against <about:blank>]
     expected: FAIL
 
   [Parsing: <http://user@/www.example.com> against <about:blank>]
     expected: FAIL
 
   [Parsing: <http:@/www.example.com> against <about:blank>]
     expected: FAIL
@@ -210,16 +219,19 @@
     expected: FAIL
 
   [Parsing: <http:/@:www.example.com> against <about:blank>]
     expected: FAIL
 
   [Parsing: <http://@:www.example.com> against <about:blank>]
     expected: FAIL
 
+  [Parsing: <http://:@www.example.com> against <about:blank>]
+    expected: FAIL
+
   [Parsing: <http://example example.com> against <http://other.com/>]
     expected: FAIL
 
   [Parsing: <http://Goo%20 goo%7C|.com> against <http://other.com/>]
     expected: FAIL
 
   [Parsing: <http://GOO  goo.com> against <http://other.com/>]
     expected: FAIL
@@ -396,16 +408,19 @@
     expected: FAIL
 
   [Parsing: <http:> against <https://example.org/foo/bar>]
     expected: FAIL
 
   [Parsing: <tel:1234567890> against <http://example.org/foo/bar>]
     expected: FAIL
 
+  [Parsing: <https://:@test> against <about:blank>]
+    expected: FAIL
+
   [Parsing: <non-special://test:@test/x> against <about:blank>]
     expected: FAIL
 
   [Parsing: <non-special://:@test/x> against <about:blank>]
     expected: FAIL
 
   [Parsing: <http://10000000000> against <http://other.com/>]
     expected: FAIL
--- a/testing/web-platform/meta/url/url-constructor.html.ini
+++ b/testing/web-platform/meta/url/url-constructor.html.ini
@@ -1,15 +1,18 @@
 [url-constructor.html]
   [Parsing: <foo://> against <http://example.org/foo/bar>]
     expected: FAIL
 
   [Parsing: <http::@c:29> against <http://example.org/foo/bar>]
     expected: FAIL
 
+  [Parsing: <http://::@c@d:2> against <http://example.org/foo/bar>]
+    expected: FAIL
+
   [Parsing: <http://foo.com:b@d/> against <http://example.org/foo/bar>]
     expected: FAIL
 
   [Parsing: <foo://///////> against <http://example.org/foo/bar>]
     expected: FAIL
 
   [Parsing: <foo://///////bar.com/> against <http://example.org/foo/bar>]
     expected: FAIL
@@ -75,19 +78,28 @@
     expected: FAIL
 
   [Parsing: <data:example.com/> against <about:blank>]
     expected: FAIL
 
   [Parsing: <http::b@www.example.com> against <about:blank>]
     expected: FAIL
 
+  [Parsing: <http:/:b@www.example.com> against <about:blank>]
+    expected: FAIL
+
+  [Parsing: <http://:b@www.example.com> against <about:blank>]
+    expected: FAIL
+
   [Parsing: <http://www.@pple.com> against <about:blank>]
     expected: FAIL
 
+  [Parsing: <http://:@www.example.com> against <about:blank>]
+    expected: FAIL
+
   [Parsing: <http://﷐zyx.com> against <http://other.com/>]
     expected: FAIL
 
   [Parsing: <http://%ef%b7%90zyx.com> against <http://other.com/>]
     expected: FAIL
 
   [Parsing: <http://%41.com> against <http://other.com/>]
     expected: FAIL
@@ -171,16 +183,19 @@
     expected: FAIL
 
   [Parsing: <sc://ñ.test/> against <about:blank>]
     expected: FAIL
 
   [Parsing: <file:..> against <http://www.example.com/test>]
     expected: FAIL
 
+  [Parsing: <https://:@test> against <about:blank>]
+    expected: FAIL
+
   [Parsing: <non-special://test:@test/x> against <about:blank>]
     expected: FAIL
 
   [Parsing: <non-special://:@test/x> against <about:blank>]
     expected: FAIL
 
   [Parsing: <http://10000000000> against <http://other.com/>]
     expected: FAIL
--- a/testing/web-platform/meta/url/url-origin.html.ini
+++ b/testing/web-platform/meta/url/url-origin.html.ini
@@ -1,9 +1,15 @@
 [url-origin.html]
+  [Origin parsing: <https://:@test> against <about:blank>]
+    expected: FAIL
+
+  [Origin parsing: <http://::@c@d:2> against <http://example.org/foo/bar>]
+    expected: FAIL
+
   [Origin parsing: <gopher:/example.com/> against <http://example.org/foo/bar>]
     expected: FAIL
 
   [Origin parsing: <data:/example.com/> against <http://example.org/foo/bar>]
     expected: FAIL
 
   [Origin parsing: <gopher:example.com/> against <http://example.org/foo/bar>]
     expected: FAIL
@@ -30,16 +36,25 @@
     expected: FAIL
 
   [Origin parsing: <data:example.com/> against <about:blank>]
     expected: FAIL
 
   [Origin parsing: <http::b@www.example.com> against <about:blank>]
     expected: FAIL
 
+  [Origin parsing: <http:/:b@www.example.com> against <about:blank>]
+    expected: FAIL
+
+  [Origin parsing: <http://:b@www.example.com> against <about:blank>]
+    expected: FAIL
+
+  [Origin parsing: <http://:@www.example.com> against <about:blank>]
+    expected: FAIL
+
   [Origin parsing: <i> against <sc:/pa/pa>]
     expected: FAIL
 
   [Origin parsing: <i> against <sc://ho/pa>]
     expected: FAIL
 
   [Origin parsing: <i> against <sc:///pa/pa>]
     expected: FAIL
--- a/testing/web-platform/meta/url/url-setters.html.ini
+++ b/testing/web-platform/meta/url/url-setters.html.ini
@@ -30,22 +30,37 @@
     expected: FAIL
 
   [Setting <mailto:me@example.net>.protocol = 'http' Cannot-be-a-base URL doesn’t have a host, but URL in a special scheme must.]
     expected: FAIL
 
   [Setting <ssh://me@example.net>.protocol = 'http' Can’t switch from non-special scheme to special. Note: this may change, see https://github.com/whatwg/url/issues/104]
     expected: FAIL
 
+  [Setting <http://:secret@example.net>.username = 'me']
+    expected: FAIL
+
+  [Setting <http://me:secret@example.net>.username = '']
+    expected: FAIL
+
   [Setting <http://example.net>.username = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' UTF-8 percent encoding with the userinfo encode set.]
     expected: FAIL
 
+  [Setting <http://example.net>.password = 'secret']
+    expected: FAIL
+
+  [Setting <http://:secret@example.net>.password = '']
+    expected: FAIL
+
   [Setting <http://example.net>.password = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' UTF-8 percent encoding with the userinfo encode set.]
     expected: FAIL
 
+  [Setting <http://example.net>.password = '%c3%89té' Bytes already percent-encoded are left as-is.]
+    expected: FAIL
+
   [Setting <view-source+http://example.net/foo>.host = '' The empty host is OK for non-special schemes]
     expected: FAIL
 
   [Setting <a:/foo>.host = 'example.net' Path-only URLs can gain a host]
     expected: FAIL
 
   [Setting <http://example.net>.host = '[::0:01\]:2' IPv6 address syntax is normalized]
     expected: FAIL
@@ -126,34 +141,79 @@
     expected: FAIL
 
   [<a>: Setting <ssh://me@example.net>.protocol = 'http' Can’t switch from non-special scheme to special. Note: this may change, see https://github.com/whatwg/url/issues/104]
     expected: FAIL
 
   [<area>: Setting <ssh://me@example.net>.protocol = 'http' Can’t switch from non-special scheme to special. Note: this may change, see https://github.com/whatwg/url/issues/104]
     expected: FAIL
 
+  [URL: Setting <http://:secret@example.net>.username = 'me']
+    expected: FAIL
+
+  [<a>: Setting <http://:secret@example.net>.username = 'me']
+    expected: FAIL
+
+  [<area>: Setting <http://:secret@example.net>.username = 'me']
+    expected: FAIL
+
+  [URL: Setting <http://me:secret@example.net>.username = '']
+    expected: FAIL
+
+  [<a>: Setting <http://me:secret@example.net>.username = '']
+    expected: FAIL
+
+  [<area>: Setting <http://me:secret@example.net>.username = '']
+    expected: FAIL
+
   [URL: Setting <http://example.net>.username = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' UTF-8 percent encoding with the userinfo encode set.]
     expected: FAIL
 
   [<a>: Setting <http://example.net>.username = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' UTF-8 percent encoding with the userinfo encode set.]
     expected: FAIL
 
   [<area>: Setting <http://example.net>.username = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' UTF-8 percent encoding with the userinfo encode set.]
     expected: FAIL
 
+  [URL: Setting <http://example.net>.password = 'secret']
+    expected: FAIL
+
+  [<a>: Setting <http://example.net>.password = 'secret']
+    expected: FAIL
+
+  [<area>: Setting <http://example.net>.password = 'secret']
+    expected: FAIL
+
+  [URL: Setting <http://:secret@example.net>.password = '']
+    expected: FAIL
+
+  [<a>: Setting <http://:secret@example.net>.password = '']
+    expected: FAIL
+
+  [<area>: Setting <http://:secret@example.net>.password = '']
+    expected: FAIL
+
   [URL: Setting <http://example.net>.password = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' UTF-8 percent encoding with the userinfo encode set.]
     expected: FAIL
 
   [<a>: Setting <http://example.net>.password = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' UTF-8 percent encoding with the userinfo encode set.]
     expected: FAIL
 
   [<area>: Setting <http://example.net>.password = '\x00\x01\t\n\r\x1f !"#$%&'()*+,-./09:;<=>?@AZ[\\\]^_`az{|}~€Éé' UTF-8 percent encoding with the userinfo encode set.]
     expected: FAIL
 
+  [URL: Setting <http://example.net>.password = '%c3%89té' Bytes already percent-encoded are left as-is.]
+    expected: FAIL
+
+  [<a>: Setting <http://example.net>.password = '%c3%89té' Bytes already percent-encoded are left as-is.]
+    expected: FAIL
+
+  [<area>: Setting <http://example.net>.password = '%c3%89té' Bytes already percent-encoded are left as-is.]
+    expected: FAIL
+
   [URL: Setting <view-source+http://example.net/foo>.host = '' The empty host is OK for non-special schemes]
     expected: FAIL
 
   [<a>: Setting <view-source+http://example.net/foo>.host = '' The empty host is OK for non-special schemes]
     expected: FAIL
 
   [<area>: Setting <view-source+http://example.net/foo>.host = '' The empty host is OK for non-special schemes]
     expected: FAIL
--- a/testing/web-platform/meta/xhr/send-authentication-competing-names-passwords.htm.ini
+++ b/testing/web-platform/meta/xhr/send-authentication-competing-names-passwords.htm.ini
@@ -1,6 +1,13 @@
 [send-authentication-competing-names-passwords.htm]
   [XMLHttpRequest: send() - "Basic" authenticated requests with competing user name/password options user name in URL userinfo, password in open() call: user name wins and password is thrown away]
     expected: FAIL
 
   [XMLHttpRequest: send() - "Basic" authenticated requests with competing user name/password options user name and password in URL userinfo, only user name in open() call: user name in open() wins]
     expected: FAIL
+
+  [XMLHttpRequest user/pass options: pass in URL, user in open()]
+    expected: FAIL
+
+  [XMLHttpRequest user/pass options: pass in URL, user/pass in open()]
+    expected: FAIL
+