Fix bug 616264. r=ehsan,sdwilsh, a=beta9+

This commit is contained in:
Dan Witte 2010-12-22 13:50:56 -08:00
parent 6f12d736db
commit 2685d64a45
4 changed files with 80 additions and 54 deletions

View File

@ -59,11 +59,11 @@ ThirdPartyUtil::Init()
// Get the base domain for aHostURI; e.g. for "www.bbc.co.uk", this would be
// "bbc.co.uk". Only properly-formed URI's are tolerated, though a trailing
// dot may be present (and will be stripped). If aHostURI is an IP address,
// an alias such as 'localhost', an eTLD such as 'co.uk', or the empty string,
// aBaseDomain will be the exact host. The result of this function should only
// be used in exact string comparisons, since substring comparisons will not
// be valid for the special cases elided above.
// dot may be present. If aHostURI is an IP address, an alias such as
// 'localhost', an eTLD such as 'co.uk', or the empty string, aBaseDomain will
// be the exact host. The result of this function should only be used in exact
// string comparisons, since substring comparisons will not be valid for the
// special cases elided above.
nsresult
ThirdPartyUtil::GetBaseDomain(nsIURI* aHostURI,
nsCString& aBaseDomain)
@ -80,9 +80,9 @@ ThirdPartyUtil::GetBaseDomain(nsIURI* aHostURI,
}
NS_ENSURE_SUCCESS(rv, rv);
// aHostURI (and thus aBaseDomain) may contain a trailing dot; if so, trim it.
if (!aBaseDomain.IsEmpty() && aBaseDomain.Last() == '.')
aBaseDomain.Truncate(aBaseDomain.Length() - 1);
// aHostURI (and thus aBaseDomain) may be the string '.'. If so, fail.
if (aBaseDomain.Length() == 1 && aBaseDomain.Last() == '.')
return NS_ERROR_INVALID_ARG;
// Reject any URIs without a host that aren't file:// URIs. This makes it the
// only way we can get a base domain consisting of the empty string, which

View File

@ -14,8 +14,8 @@ function run_test() {
do_check_eq(cm.countCookiesFromHost("baz.com"), 1);
do_check_eq(cm.countCookiesFromHost("BAZ.com"), 1);
do_check_eq(cm.countCookiesFromHost(".baz.com"), 1);
do_check_eq(cm.countCookiesFromHost("baz.com."), 1);
do_check_eq(cm.countCookiesFromHost(".baz.com."), 1);
do_check_eq(cm.countCookiesFromHost("baz.com."), 0);
do_check_eq(cm.countCookiesFromHost(".baz.com."), 0);
do_check_throws(function() {
cm.countCookiesFromHost("baz.com..");
}, Cr.NS_ERROR_ILLEGAL_VALUE);
@ -26,13 +26,27 @@ function run_test() {
cm.countCookiesFromHost("..baz.com");
}, Cr.NS_ERROR_ILLEGAL_VALUE);
cm.remove("BAZ.com.", "foo", "/", false);
do_check_eq(cm.countCookiesFromHost("baz.com"), 1);
cm.remove("baz.com", "foo", "/", false);
do_check_eq(cm.countCookiesFromHost("baz.com"), 0);
// Test that 'baz.com' and 'baz.com.' are treated differently
cm.add("baz.com.", "/", "foo", "bar", false, false, true, expiry);
do_check_eq(cm.countCookiesFromHost("baz.com"), 0);
do_check_eq(cm.countCookiesFromHost("BAZ.com"), 0);
do_check_eq(cm.countCookiesFromHost(".baz.com"), 0);
do_check_eq(cm.countCookiesFromHost("baz.com."), 1);
do_check_eq(cm.countCookiesFromHost(".baz.com."), 1);
cm.remove("baz.com", "foo", "/", false);
do_check_eq(cm.countCookiesFromHost("baz.com."), 1);
cm.remove("baz.com.", "foo", "/", false);
do_check_eq(cm.countCookiesFromHost("baz.com."), 0);
// test that domain cookies are illegal for IP addresses, aliases such as
// 'localhost', and eTLD's such as 'co.uk'
cm.add("192.168.0.1", "/", "foo", "bar", false, false, true, expiry);
do_check_eq(cm.countCookiesFromHost("192.168.0.1"), 1);
do_check_eq(cm.countCookiesFromHost("192.168.0.1."), 1);
do_check_eq(cm.countCookiesFromHost("192.168.0.1."), 0);
do_check_throws(function() {
cm.countCookiesFromHost(".192.168.0.1");
}, Cr.NS_ERROR_ILLEGAL_VALUE);
@ -42,7 +56,7 @@ function run_test() {
cm.add("localhost", "/", "foo", "bar", false, false, true, expiry);
do_check_eq(cm.countCookiesFromHost("localhost"), 1);
do_check_eq(cm.countCookiesFromHost("localhost."), 1);
do_check_eq(cm.countCookiesFromHost("localhost."), 0);
do_check_throws(function() {
cm.countCookiesFromHost(".localhost");
}, Cr.NS_ERROR_ILLEGAL_VALUE);
@ -52,7 +66,7 @@ function run_test() {
cm.add("co.uk", "/", "foo", "bar", false, false, true, expiry);
do_check_eq(cm.countCookiesFromHost("co.uk"), 1);
do_check_eq(cm.countCookiesFromHost("co.uk."), 1);
do_check_eq(cm.countCookiesFromHost("co.uk."), 0);
do_check_throws(function() {
cm.countCookiesFromHost(".co.uk");
}, Cr.NS_ERROR_ILLEGAL_VALUE);
@ -122,14 +136,14 @@ function run_test() {
cs.setCookieString(emptyuri, null, "foo3=bar; domain=", null);
do_check_eq(getCookieCount(), 2);
cs.setCookieString(emptyuri, null, "foo4=bar; domain=.", null);
do_check_eq(getCookieCount(), 3);
do_check_eq(getCookieCount(), 2);
cs.setCookieString(emptyuri, null, "foo5=bar; domain=bar.com", null);
do_check_eq(getCookieCount(), 3);
do_check_eq(getCookieCount(), 2);
do_check_eq(cs.getCookieString(emptyuri, null), "foo2=bar; foo3=bar; foo4=bar");
do_check_eq(cs.getCookieString(emptyuri, null), "foo2=bar; foo3=bar");
do_check_eq(cm.countCookiesFromHost("baz.com"), 0);
do_check_eq(cm.countCookiesFromHost(""), 3);
do_check_eq(cm.countCookiesFromHost(""), 2);
do_check_throws(function() {
cm.countCookiesFromHost(".");
}, Cr.NS_ERROR_ILLEGAL_VALUE);
@ -141,8 +155,6 @@ function run_test() {
e.getNext();
do_check_true(e.hasMoreElements());
e.getNext();
do_check_true(e.hasMoreElements());
e.getNext();
do_check_false(e.hasMoreElements());
do_check_throws(function() {
cm.getCookiesFromHost(".");
@ -166,12 +178,17 @@ function run_test() {
}, Cr.NS_ERROR_ILLEGAL_VALUE);
// test that the 'domain' attribute accepts a leading dot for IP addresses,
// aliases such as 'localhost', eTLD's such as 'co.uk', and the empty host;
// but that the resulting cookie is for the exact host only.
// aliases such as 'localhost', and eTLD's such as 'co.uk'; but that the
// resulting cookie is for the exact host only.
testDomainCookie("http://192.168.0.1/", "192.168.0.1");
testDomainCookie("http://localhost/", "localhost");
testDomainCookie("http://co.uk/", "co.uk");
testDomainCookie("file:///", "");
// Test that trailing dots are treated differently for purposes of the
// 'domain' attribute when using setCookieString.
testTrailingDotCookie("http://192.168.0.1", "192.168.0.1");
testTrailingDotCookie("http://localhost", "localhost");
testTrailingDotCookie("http://foo.com", "foo.com");
cm.removeAll();
}
@ -208,3 +225,22 @@ function testDomainCookie(uriString, domain) {
cm.removeAll();
}
function testTrailingDotCookie(uriString, domain) {
var cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService);
var cm = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager2);
cm.removeAll();
var uri = NetUtil.newURI(uriString);
cs.setCookieString(uri, null, "foo=bar; domain=" + domain + ".", null);
do_check_eq(cm.countCookiesFromHost(domain), 0);
do_check_eq(cm.countCookiesFromHost(domain + "."), 0);
cm.removeAll();
uri = NetUtil.newURI(uriString + ".");
cs.setCookieString(uri, null, "foo=bar; domain=" + domain, null);
do_check_eq(cm.countCookiesFromHost(domain), 0);
do_check_eq(cm.countCookiesFromHost(domain + "."), 0);
cm.removeAll();
}

View File

@ -1512,7 +1512,7 @@ nsCookieService::SetCookieStringInternal(nsIURI *aHostURI,
// e.g. for "www.bbc.co.uk", this would be "bbc.co.uk".
// file:// URI's (i.e. with an empty host) are allowed, but any other
// scheme must have a non-empty host. A trailing dot in the host
// is acceptable, and will be stripped.
// is acceptable.
PRBool requireHostMatch;
nsCAutoString baseDomain;
nsresult rv = GetBaseDomain(aHostURI, baseDomain, requireHostMatch);
@ -2344,7 +2344,7 @@ nsCookieService::GetCookieStringInternal(nsIURI *aHostURI,
// e.g. for "www.bbc.co.uk", the base domain would be "bbc.co.uk".
// file:// URI's (i.e. with an empty host) are allowed, but any other
// scheme must have a non-empty host. A trailing dot in the host
// is acceptable, and will be stripped.
// is acceptable.
PRBool requireHostMatch;
nsCAutoString baseDomain, hostFromURI, pathFromURI;
nsresult rv = GetBaseDomain(aHostURI, baseDomain, requireHostMatch);
@ -2352,9 +2352,6 @@ nsCookieService::GetCookieStringInternal(nsIURI *aHostURI,
rv = aHostURI->GetAsciiHost(hostFromURI);
if (NS_SUCCEEDED(rv))
rv = aHostURI->GetPath(pathFromURI);
// trim any trailing dot
if (!hostFromURI.IsEmpty() && hostFromURI.Last() == '.')
hostFromURI.Truncate(hostFromURI.Length() - 1);
if (NS_FAILED(rv)) {
COOKIE_LOGFAILURE(GET_COOKIE, aHostURI, nsnull, "invalid host/path from URI");
return;
@ -2973,10 +2970,10 @@ nsCookieService::ParseAttributes(nsDependentCString &aCookieHeader,
// Get the base domain for aHostURI; e.g. for "www.bbc.co.uk", this would be
// "bbc.co.uk". Only properly-formed URI's are tolerated, though a trailing
// dot may be present (and will be stripped). If aHostURI is an IP address,
// an alias such as 'localhost', an eTLD such as 'co.uk', or the empty string,
// aBaseDomain will be the exact host, and aRequireHostMatch will be true to
// indicate that substring matches should not be performed.
// dot may be present. If aHostURI is an IP address, an alias such as
// 'localhost', an eTLD such as 'co.uk', or the empty string, aBaseDomain will
// be the exact host, and aRequireHostMatch will be true to indicate that
// substring matches should not be performed.
nsresult
nsCookieService::GetBaseDomain(nsIURI *aHostURI,
nsCString &aBaseDomain,
@ -2995,9 +2992,9 @@ nsCookieService::GetBaseDomain(nsIURI *aHostURI,
}
NS_ENSURE_SUCCESS(rv, rv);
// aHost (and thus aBaseDomain) may contain a trailing dot; if so, trim it.
if (!aBaseDomain.IsEmpty() && aBaseDomain.Last() == '.')
aBaseDomain.Truncate(aBaseDomain.Length() - 1);
// aHost (and thus aBaseDomain) may be the string '.'. If so, fail.
if (aBaseDomain.Length() == 1 && aBaseDomain.Last() == '.')
return NS_ERROR_INVALID_ARG;
// block any URIs without a host that aren't file:// URIs.
if (aBaseDomain.IsEmpty()) {
@ -3013,7 +3010,7 @@ nsCookieService::GetBaseDomain(nsIURI *aHostURI,
// Get the base domain for aHost; e.g. for "www.bbc.co.uk", this would be
// "bbc.co.uk". This is done differently than GetBaseDomain(): it is assumed
// that aHost is already normalized, and it may contain a leading dot
// (indicating that it represents a domain). A trailing dot must not be present.
// (indicating that it represents a domain). A trailing dot may be present.
// If aHost is an IP address, an alias such as 'localhost', an eTLD such as
// 'co.uk', or the empty string, aBaseDomain will be the exact host, and a
// leading dot will be treated as an error.
@ -3021,8 +3018,8 @@ nsresult
nsCookieService::GetBaseDomainFromHost(const nsACString &aHost,
nsCString &aBaseDomain)
{
// aHost must not contain a trailing dot, or be the string '.'.
if (!aHost.IsEmpty() && aHost.Last() == '.')
// aHost must not be the string '.'.
if (aHost.Length() == 1 && aHost.Last() == '.')
return NS_ERROR_INVALID_ARG;
// aHost may contain a leading dot; if so, strip it now.
@ -3051,7 +3048,7 @@ nsCookieService::GetBaseDomainFromHost(const nsACString &aHost,
// Normalizes the given hostname, component by component. ASCII/ACE
// components are lower-cased, and UTF-8 components are normalized per
// RFC 3454 and converted to ACE. Any trailing dot is stripped.
// RFC 3454 and converted to ACE.
nsresult
nsCookieService::NormalizeHost(nsCString &aHost)
{
@ -3064,17 +3061,12 @@ nsCookieService::NormalizeHost(nsCString &aHost)
aHost = host;
}
// Only strip the trailing dot if it wouldn't result in the empty string;
// in that case, treat it like a leading dot.
if (aHost.Length() > 1 && aHost.Last() == '.')
aHost.Truncate(aHost.Length() - 1);
ToLowerCase(aHost);
return NS_OK;
}
// returns PR_TRUE if 'a' is equal to or a subdomain of 'b',
// assuming no leading or trailing dots are present.
// assuming no leading dots are present.
static inline PRBool IsSubdomainOf(const nsCString &a, const nsCString &b)
{
if (a == b)
@ -3158,15 +3150,13 @@ nsCookieService::CheckDomain(nsCookieAttributes &aCookieAttributes,
nsCAutoString hostFromURI;
aHostURI->GetAsciiHost(hostFromURI);
// trim any trailing dot
if (!hostFromURI.IsEmpty() && hostFromURI.Last() == '.')
hostFromURI.Truncate(hostFromURI.Length() - 1);
// if a domain is given, check the host has permission
if (!aCookieAttributes.host.IsEmpty()) {
// Tolerate leading '.' characters.
if (aCookieAttributes.host.First() == '.')
// Tolerate leading '.' characters, but not if it's otherwise an empty host.
if (aCookieAttributes.host.Length() > 1 &&
aCookieAttributes.host.First() == '.') {
aCookieAttributes.host.Cut(0, 1);
}
// switch to lowercase now, to avoid case-insensitive compares everywhere
ToLowerCase(aCookieAttributes.host);

View File

@ -309,11 +309,11 @@ main(PRInt32 argc, char *argv[])
GetACookie(cookieService, "http://www.basic.com/testPath/testfile.txt", nsnull, getter_Copies(cookie));
rv[1] = CheckResult(cookie.get(), MUST_EQUAL, "test=basic");
GetACookie(cookieService, "http://www.basic.com./", nsnull, getter_Copies(cookie));
rv[2] = CheckResult(cookie.get(), MUST_EQUAL, "test=basic");
rv[2] = CheckResult(cookie.get(), MUST_BE_NULL);
GetACookie(cookieService, "http://www.basic.com.", nsnull, getter_Copies(cookie));
rv[3] = CheckResult(cookie.get(), MUST_EQUAL, "test=basic");
rv[3] = CheckResult(cookie.get(), MUST_BE_NULL);
GetACookie(cookieService, "http://www.basic.com./testPath/testfile.txt", nsnull, getter_Copies(cookie));
rv[4] = CheckResult(cookie.get(), MUST_EQUAL, "test=basic");
rv[4] = CheckResult(cookie.get(), MUST_BE_NULL);
GetACookie(cookieService, "http://www.basic2.com/", nsnull, getter_Copies(cookie));
rv[5] = CheckResult(cookie.get(), MUST_BE_NULL);
SetACookie(cookieService, "http://www.basic.com", nsnull, "test=basic; max-age=-1", nsnull);
@ -332,7 +332,7 @@ main(PRInt32 argc, char *argv[])
GetACookie(cookieService, "http://domain.com", nsnull, getter_Copies(cookie));
rv[0] = CheckResult(cookie.get(), MUST_EQUAL, "test=domain");
GetACookie(cookieService, "http://domain.com.", nsnull, getter_Copies(cookie));
rv[1] = CheckResult(cookie.get(), MUST_EQUAL, "test=domain");
rv[1] = CheckResult(cookie.get(), MUST_BE_NULL);
GetACookie(cookieService, "http://www.domain.com", nsnull, getter_Copies(cookie));
rv[2] = CheckResult(cookie.get(), MUST_EQUAL, "test=domain");
GetACookie(cookieService, "http://foo.domain.com", nsnull, getter_Copies(cookie));