diff --git a/extensions/cookie/test/unit/test_bug481775.js b/extensions/cookie/test/unit/test_bug481775.js index 86dd1663513..a2a47c3e117 100644 --- a/extensions/cookie/test/unit/test_bug481775.js +++ b/extensions/cookie/test/unit/test_bug481775.js @@ -2,9 +2,7 @@ const Cc = Components.classes; const Ci = Components.interfaces; function run_test() { - var cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService); var cm = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager2); - var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); var pb = null; try { @@ -13,7 +11,7 @@ function run_test() { // accept all cookies and clear the table prefs.setIntPref("network.cookie.lifetimePolicy", 0); - cs.removeAll(); + cm.removeAll(); // saturate the cookie table addCookies(0, 5000); @@ -37,7 +35,7 @@ function run_test() { do_check_eq(getCookieCount(), count); // remove them all - cs.removeAll(); + cm.removeAll(); do_check_eq(getCookieCount(), 0); // leave private browsing mode @@ -55,7 +53,7 @@ function run_test() { do_check_eq(getCookieCount(), count); // remove them all - cs.removeAll(); + cm.removeAll(); do_check_eq(getCookieCount(), 0); } diff --git a/extensions/cookie/test/unit/test_bug526789.js b/extensions/cookie/test/unit/test_bug526789.js new file mode 100644 index 00000000000..4f110c0db9c --- /dev/null +++ b/extensions/cookie/test/unit/test_bug526789.js @@ -0,0 +1,77 @@ +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cr = Components.results; + +function do_check_throws(f, result, stack) +{ + if (!stack) + stack = Components.stack.caller; + + try { + f(); + } catch (exc) { + if (exc.result == result) + return; + do_throw("expected result " + result + ", caught " + exc, stack); + } + do_throw("expected result " + result + ", none thrown", stack); +} + +function run_test() { + var cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService); + var cm = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager2); + var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); + + // test that an empty host results in a no-op + var uri = ios.newURI("http://baz.com/", null, null); + var emptyuri = ios.newURI("http:///", null, null); + var doturi = ios.newURI("http://./", null, null); + do_check_eq(emptyuri.asciiHost, ""); + do_check_eq(doturi.asciiHost, "."); + cs.setCookieString(uri, null, "foo=bar", null); + cs.setCookieString(emptyuri, null, "foo=bar", null); + cs.setCookieString(doturi, null, "foo=bar", null); + + do_check_eq(cs.getCookieString(uri, null), "foo=bar"); + do_check_eq(cs.getCookieString(emptyuri, null), null); + do_check_eq(cs.getCookieString(doturi, null), null); + + // test that an empty host throws + cm.add("test.com", "/", "foo", "bar", false, false, true, 1 << 60); + do_check_throws(function() { + cm.add("", "/", "foo", "bar", false, false, true, 1 << 60); + }, Cr.NS_ERROR_ILLEGAL_VALUE); + do_check_throws(function() { + cm.add(".", "/", "foo", "bar", false, false, true, 1 << 60); + }, Cr.NS_ERROR_ILLEGAL_VALUE); + + cm.remove("test.com", "foo", "/", false); + do_check_throws(function() { + cm.remove("", "foo", "/", false); + }, Cr.NS_ERROR_ILLEGAL_VALUE); + do_check_throws(function() { + cm.remove("", "foo", "/", false); + }, Cr.NS_ERROR_ILLEGAL_VALUE); + + do_check_eq(cm.countCookiesFromHost("baz.com"), 1); + do_check_throws(function() { + cm.countCookiesFromHost(""); + }, Cr.NS_ERROR_ILLEGAL_VALUE); + do_check_throws(function() { + cm.countCookiesFromHost("."); + }, Cr.NS_ERROR_ILLEGAL_VALUE); + + var e = cm.getCookiesFromHost("baz.com"); + do_check_true(e.hasMoreElements()); + do_check_eq(e.getNext().QueryInterface(Ci.nsICookie2).name, "foo"); + do_check_false(e.hasMoreElements()); + do_check_throws(function() { + cm.getCookiesFromHost(""); + }, Cr.NS_ERROR_ILLEGAL_VALUE); + do_check_throws(function() { + cm.getCookiesFromHost("."); + }, Cr.NS_ERROR_ILLEGAL_VALUE); + + cm.removeAll(); +} + diff --git a/netwerk/cookie/public/nsICookieManager.idl b/netwerk/cookie/public/nsICookieManager.idl index c59fc455361..7ba55417134 100644 --- a/netwerk/cookie/public/nsICookieManager.idl +++ b/netwerk/cookie/public/nsICookieManager.idl @@ -66,6 +66,7 @@ interface nsICookieManager : nsISupports * * @param aDomain The host or domain for which the cookie was set * @param aName The name specified in the cookie + * @param aPath The path for which the cookie was set * @param aBlocked Indicates if cookies from this host should be permanently blocked * */ diff --git a/netwerk/cookie/src/nsCookieService.cpp b/netwerk/cookie/src/nsCookieService.cpp index a094929fa39..a8ee42faae3 100644 --- a/netwerk/cookie/src/nsCookieService.cpp +++ b/netwerk/cookie/src/nsCookieService.cpp @@ -920,6 +920,10 @@ nsCookieService::Add(const nsACString &aDomain, PRBool aIsSession, PRInt64 aExpiry) { + NS_ENSURE_TRUE(!aDomain.IsEmpty() && !aDomain.EqualsLiteral("."), + NS_ERROR_INVALID_ARG); + NS_ENSURE_TRUE(!aValue.IsEmpty(), NS_ERROR_INVALID_ARG); + PRInt64 currentTimeInUsec = PR_Now(); nsRefPtr cookie = @@ -944,6 +948,9 @@ nsCookieService::Remove(const nsACString &aHost, const nsACString &aPath, PRBool aBlocked) { + NS_ENSURE_TRUE(!aHost.IsEmpty() && !aHost.EqualsLiteral("."), + NS_ERROR_INVALID_ARG); + nsListIter matchIter; if (FindCookie(PromiseFlatCString(aHost), PromiseFlatCString(aName), @@ -960,7 +967,7 @@ nsCookieService::Remove(const nsACString &aHost, nsCAutoString host(NS_LITERAL_CSTRING("http://")); // strip off the domain dot, if necessary - if (!aHost.IsEmpty() && aHost.First() == '.') + if (aHost.First() == '.') host.Append(Substring(aHost, 1, aHost.Length() - 1)); else host.Append(aHost); @@ -1247,6 +1254,10 @@ nsCookieService::GetCookieInternal(nsIURI *aHostURI, } // trim trailing dots hostFromURI.Trim("."); + if (hostFromURI.IsEmpty()) { + COOKIE_LOGFAILURE(GET_COOKIE, aHostURI, nsnull, "empty host"); + return; + } // insert a leading dot, so we begin the hash lookup with the // equivalent domain cookie host hostFromURI.Insert(NS_LITERAL_CSTRING("."), 0); @@ -1835,6 +1846,8 @@ nsCookieService::IsForeign(nsIURI *aHostURI, // trim trailing dots currentHost.Trim("."); firstHost.Trim("."); + if (currentHost.IsEmpty() || firstHost.IsEmpty()) + return PR_TRUE; // fast path: check if the two hosts are identical. // this also covers two special cases: @@ -1941,6 +1954,8 @@ nsCookieService::CheckDomain(nsCookieAttributes &aCookieAttributes, } // trim trailing dots hostFromURI.Trim("."); + if (hostFromURI.IsEmpty()) + return PR_FALSE; // if a domain is given, check the host has permission if (!aCookieAttributes.host.IsEmpty()) { @@ -2169,8 +2184,9 @@ PRUint32 nsCookieService::CountCookiesFromHostInternal(const nsACString &aHost, nsEnumerationData &aData) { - PRUint32 countFromHost = 0; + NS_ASSERTION(!aHost.IsEmpty() && !aHost.EqualsLiteral("."), "empty host"); + PRUint32 countFromHost = 0; nsCAutoString hostWithDot(NS_LITERAL_CSTRING(".") + aHost); const char *currentDot = hostWithDot.get(); @@ -2205,9 +2221,11 @@ NS_IMETHODIMP nsCookieService::CountCookiesFromHost(const nsACString &aHost, PRUint32 *aCountFromHost) { + NS_ENSURE_TRUE(!aHost.IsEmpty() && !aHost.EqualsLiteral("."), + NS_ERROR_INVALID_ARG); + // we don't care about finding the oldest cookie here, so disable the search nsEnumerationData data(PR_Now() / PR_USEC_PER_SEC, LL_MININT); - *aCountFromHost = CountCookiesFromHostInternal(aHost, data); return NS_OK; } @@ -2218,6 +2236,9 @@ NS_IMETHODIMP nsCookieService::GetCookiesFromHost(const nsACString &aHost, nsISimpleEnumerator **aEnumerator) { + NS_ENSURE_TRUE(!aHost.IsEmpty() && !aHost.EqualsLiteral("."), + NS_ERROR_INVALID_ARG); + nsCOMArray cookieList(mMaxCookiesPerHost); nsCAutoString hostWithDot(NS_LITERAL_CSTRING(".") + aHost); PRInt64 currentTime = PR_Now() / PR_USEC_PER_SEC; @@ -2249,6 +2270,8 @@ nsCookieService::FindCookie(const nsAFlatCString &aHost, nsListIter &aIter, PRInt64 aCurrentTime) { + NS_ASSERTION(!aHost.IsEmpty() && !aHost.EqualsLiteral("."), "empty host"); + nsCookieEntry *entry = mDBState->hostTable.GetEntry(aHost.get()); for (aIter = nsListIter(entry); aIter.current; ++aIter) { if (aIter.current->Expiry() > aCurrentTime &&