Bug 494092 - Make default uri fixup more permissive, taking into account ipv4, ipv6, asciihost and improve test base. r=smaug

This commit is contained in:
Alex Bardas 2014-09-10 12:42:00 -04:00
parent cd8f63c5f9
commit 4f213e3b06
2 changed files with 276 additions and 38 deletions

View File

@ -951,57 +951,128 @@ void nsDefaultURIFixup::KeywordURIFixup(const nsACString & aURIString,
// in practice. So if we cast all locations to uint32_t, then a <
// b guarantees that either b is kNotFound and a is found, or both
// are found and a found before b.
uint32_t dotLoc = uint32_t(aURIString.FindChar('.'));
nsAutoCString tmpURIString(aURIString);
uint32_t lastDotLoc = uint32_t(tmpURIString.RFindChar('.'));
uint32_t colonLoc = uint32_t(aURIString.FindChar(':'));
uint32_t spaceLoc = uint32_t(aURIString.FindChar(' '));
if (spaceLoc == 0) {
// Treat this as not found
spaceLoc = uint32_t(kNotFound);
uint32_t firstDotLoc = uint32_t(kNotFound);
uint32_t firstColonLoc = uint32_t(kNotFound);
uint32_t firstQuoteLoc = uint32_t(kNotFound);
uint32_t firstSpaceLoc = uint32_t(kNotFound);
uint32_t firstQMarkLoc = uint32_t(kNotFound);
uint32_t lastLSBracketLoc = uint32_t(kNotFound);
uint32_t pos = 0;
uint32_t foundDots = 0;
uint32_t foundColons = 0;
uint32_t foundDigits = 0;
uint32_t foundRSBrackets = 0;
bool looksLikeIpv6 = true;
bool hasAsciiAlpha = false;
nsACString::const_iterator iterBegin;
nsACString::const_iterator iterEnd;
aURIString.BeginReading(iterBegin);
aURIString.EndReading(iterEnd);
nsACString::const_iterator iter = iterBegin;
while (iter != iterEnd) {
if (pos >= 1 && foundRSBrackets == 0) {
if (!(lastLSBracketLoc == 0 &&
(*iter == ':' ||
*iter == '.' ||
*iter == ']' ||
(*iter >= 'a' && *iter <= 'f') ||
(*iter >= 'A' && *iter <= 'F') ||
nsCRT::IsAsciiDigit(*iter)))) {
looksLikeIpv6 = false;
}
}
if (*iter == '.') {
++foundDots;
if (firstDotLoc == uint32_t(kNotFound)) {
firstDotLoc = pos;
}
} else if (*iter == ':') {
++foundColons;
if (firstColonLoc == uint32_t(kNotFound)) {
firstColonLoc = pos;
}
} else if (*iter == ' ' && firstSpaceLoc == uint32_t(kNotFound)) {
firstSpaceLoc = pos;
} else if (*iter == '?' && firstQMarkLoc == uint32_t(kNotFound)) {
firstQMarkLoc = pos;
} else if ((*iter == '\'' || *iter == '"') && firstQuoteLoc == uint32_t(kNotFound)) {
firstQuoteLoc = pos;
} else if (*iter == '[') {
lastLSBracketLoc = pos;
} else if (*iter == ']') {
foundRSBrackets++;
} else if (nsCRT::IsAsciiAlpha(*iter)) {
hasAsciiAlpha = true;
} else if (nsCRT::IsAsciiDigit(*iter)) {
++foundDigits;
}
pos++;
iter++;
}
if (lastLSBracketLoc > 0 || foundRSBrackets != 1) {
looksLikeIpv6 = false;
}
uint32_t qMarkLoc = uint32_t(aURIString.FindChar('?'));
uint32_t quoteLoc = std::min(uint32_t(aURIString.FindChar('"')),
uint32_t(aURIString.FindChar('\'')));
nsresult rv;
nsAutoCString asciiHost;
nsAutoCString host;
bool isValidAsciiHost = aFixupInfo->mFixedURI &&
NS_SUCCEEDED(aFixupInfo->mFixedURI->GetAsciiHost(asciiHost)) &&
!asciiHost.IsEmpty();
bool isValidHost = aFixupInfo->mFixedURI &&
NS_SUCCEEDED(aFixupInfo->mFixedURI->GetHost(host)) &&
!host.IsEmpty();
// If there are 3 dots and only numbers between them, then don't do a
// keyword lookup (ipv4)
if (foundDots == 3 && (foundDots + foundDigits == pos)) {
return;
}
// If there are only colons and only hexadecimal characters ([a-z][0-9])
// enclosed in [], then don't do a keyword lookup
if (looksLikeIpv6) {
return;
}
// We do keyword lookups if a space or quote preceded the dot, colon
// or question mark (or if the latter were not found):
if (((spaceLoc < dotLoc || quoteLoc < dotLoc) &&
(spaceLoc < colonLoc || quoteLoc < colonLoc) &&
(spaceLoc < qMarkLoc || quoteLoc < qMarkLoc)) ||
qMarkLoc == 0)
{
// or question mark (or if the latter were not found)
// or when the host is the same as asciiHost and there are no
// characters from [a-z][A-Z]
if (((firstSpaceLoc < firstDotLoc || firstQuoteLoc < firstDotLoc) &&
(firstSpaceLoc < firstColonLoc || firstQuoteLoc < firstColonLoc) &&
(firstSpaceLoc < firstQMarkLoc || firstQuoteLoc < firstQMarkLoc)) || firstQMarkLoc == 0 ||
(isValidAsciiHost && isValidHost && !hasAsciiAlpha &&
host.EqualsIgnoreCase(asciiHost.get()))) {
rv = KeywordToURI(aFixupInfo->mOriginalInput, aPostData,
getter_AddRefs(aFixupInfo->mPreferredURI));
if (NS_SUCCEEDED(rv) && aFixupInfo->mPreferredURI)
{
if (NS_SUCCEEDED(rv) && aFixupInfo->mPreferredURI) {
aFixupInfo->mFixupUsedKeyword = true;
}
}
// ... or if there is no question mark or colon, and there is either no
// dot, or exactly 1 and it is the first or last character of the input:
else if ((dotLoc == uint32_t(kNotFound) ||
(dotLoc == lastDotLoc && (dotLoc == 0 || dotLoc == aURIString.Length() - 1))) &&
colonLoc == uint32_t(kNotFound) && qMarkLoc == uint32_t(kNotFound))
{
else if ((firstDotLoc == uint32_t(kNotFound) ||
(foundDots == 1 && (firstDotLoc == 0 || firstDotLoc == aURIString.Length() - 1))) &&
firstColonLoc == uint32_t(kNotFound) && firstQMarkLoc == uint32_t(kNotFound)) {
nsAutoCString asciiHost;
if (aFixupInfo->mFixedURI &&
NS_SUCCEEDED(aFixupInfo->mFixedURI->GetAsciiHost(asciiHost)) &&
!asciiHost.IsEmpty()) {
if (IsDomainWhitelisted(asciiHost, dotLoc)) {
return;
}
if (isValidAsciiHost && IsDomainWhitelisted(asciiHost, firstDotLoc)) {
return;
}
// If we get here, we don't have a valid URI, or we did but the
// host is not whitelisted, so we do a keyword search *anyway*:
rv = KeywordToURI(aFixupInfo->mOriginalInput, aPostData,
getter_AddRefs(aFixupInfo->mPreferredURI));
if (NS_SUCCEEDED(rv) && aFixupInfo->mPreferredURI)
{
if (NS_SUCCEEDED(rv) && aFixupInfo->mPreferredURI) {
aFixupInfo->mFixupUsedKeyword = true;
}
}

View File

@ -87,6 +87,45 @@ let testcases = [ {
input: "127.0.0.1",
fixedURI: "http://127.0.0.1/",
protocolChange: true,
}, {
input: "192.168.10.110",
fixedURI: "http://192.168.10.110/",
protocolChange: true,
}, {
input: "[::1]",
fixedURI: "http://[::1]/",
alternateURI: "http://[::1]/",
protocolChange: true,
affectedByWhitelist: true
}, {
input: "[fe80:cd00:0:cde:1257:0:211e:729c]",
fixedURI: "http://[fe80:cd00:0:cde:1257:0:211e:729c]/",
alternateURI: "http://[fe80:cd00:0:cde:1257:0:211e:729c]/",
protocolChange: true,
affectedByWhitelist: true
}, {
input: "[64:ff9b::8.8.8.8]",
fixedURI: "http://[64:ff9b::8.8.8.8]/",
protocolChange: true
}, {
input: "[64:ff9b::8.8.8.8]/~moz",
fixedURI: "http://[64:ff9b::8.8.8.8]/~moz",
protocolChange: true
}, {
input: "[::1][::1]",
keywordLookup: true,
protocolChange: true
}, {
input: "[::1][100",
fixedURI: "http://[::1][100/",
alternateURI: "http://[::1][100/",
keywordLookup: true,
protocolChange: true,
affectedByWhitelist: true
}, {
input: "[::1]]",
keywordLookup: true,
protocolChange: true
}, {
input: "1234",
fixedURI: "http://1234/",
@ -124,6 +163,22 @@ let testcases = [ {
input: "mozilla is amazing",
keywordLookup: true,
protocolChange: true,
}, {
input: "search ?mozilla",
keywordLookup: true,
protocolChange: true,
}, {
input: "mozilla .com",
keywordLookup: true,
protocolChange: true,
}, {
input: "what if firefox?",
keywordLookup: true,
protocolChange: true,
}, {
input: "london's map",
keywordLookup: true,
protocolChange: true,
}, {
input: "mozilla ",
fixedURI: "http://mozilla/",
@ -190,6 +245,112 @@ let testcases = [ {
alternateURI: "http://www.whitelisted.com/",
affectedByWhitelist: true,
inWhitelist: true,
}, {
input: "café.local",
fixedURI: "http://café.local/",
alternateURI: "http://www.café.local/",
protocolChange: true
}, {
input: "47.6182,-122.830",
fixedURI: "http://47.6182,-122.830/",
keywordLookup: true,
protocolChange: true
}, {
input: "-47.6182,-23.51",
fixedURI: "http://-47.6182,-23.51/",
keywordLookup: true,
protocolChange: true
}, {
input: "-22.14,23.51-",
fixedURI: "http://-22.14,23.51-/",
keywordLookup: true,
protocolChange: true
}, {
input: "32.7",
fixedURI: "http://32.7/",
alternateURI: "http://www.32.7/",
keywordLookup: true,
protocolChange: true
}, {
input: "5+2",
fixedURI: "http://5+2/",
alternateURI: "http://www.5+2.com/",
keywordLookup: true,
protocolChange: true,
affectedByWhitelist: true
}, {
input: "moz ?.::%27",
keywordLookup: true,
protocolChange: true
}, {
input: "mozilla.com/?q=search",
fixedURI: "http://mozilla.com/?q=search",
alternateURI: "http://www.mozilla.com/?q=search",
protocolChange: true
}, {
input: "mozilla.com?q=search",
fixedURI: "http://mozilla.com/?q=search",
alternateURI: "http://www.mozilla.com/?q=search",
protocolChange: true
}, {
input: "mozilla.com ?q=search",
keywordLookup: true,
protocolChange: true
}, {
input: "mozilla.com.?q=search",
fixedURI: "http://mozilla.com./?q=search",
protocolChange: true
}, {
input: "mozilla.com'?q=search",
fixedURI: "http://mozilla.com'/?q=search",
alternateURI: "http://www.mozilla.com'/?q=search",
protocolChange: true
}, {
input: "mozilla.com':search",
keywordLookup: true,
protocolChange: true
}, {
input: "[mozilla]",
keywordLookup: true,
protocolChange: true
}, {
input: "':?",
fixedURI: "http://'/?",
alternateURI: "http://www.'.com/?",
keywordLookup: true,
protocolChange: true,
affectedByWhitelist: true
}, {
input: "a?.com",
fixedURI: "http://a/?.com",
alternateURI: "http://www.a.com/?.com",
protocolChange: true,
affectedByWhitelist: true
}, {
input: "?'.com",
fixedURI: "http:///?%27.com",
alternateURI: "http://www..com/?%27.com",
keywordLookup: true,
protocolChange: true,
affectedByWhitelist: true
}, {
input: "' ?.com",
keywordLookup: true,
protocolChange: true
}, {
input: "?mozilla",
fixedURI: "http:///?mozilla",
alternateURI: "http://www..com/?mozilla",
keywordLookup: true,
protocolChange: true,
affectedByWhitelist: true
}, {
input: "??mozilla",
fixedURI: "http:///??mozilla",
alternateURI: "http://www..com/??mozilla",
keywordLookup: true,
protocolChange: true,
affectedByWhitelist: true
}];
if (Services.appinfo.OS.toLowerCase().startsWith("win")) {
@ -297,14 +458,20 @@ function run_test() {
do_check_eq(info.fixupCreatedAlternateURI, makeAlternativeURI && alternativeURI != null);
// Check the preferred URI
let requiresWhitelistedDomain = flags & urifixup.FIXUP_FLAG_REQUIRE_WHITELISTED_HOST
let requiresWhitelistedDomain = flags & urifixup.FIXUP_FLAG_REQUIRE_WHITELISTED_HOST;
if (couldDoKeywordLookup) {
if (expectKeywordLookup) {
if (!affectedByWhitelist || (affectedByWhitelist && !inWhitelist)) {
let urlparamInput = encodeURIComponent(sanitize(testInput)).replace("%20", "+", "g");
let searchURL = kSearchEngineURL.replace("{searchTerms}", urlparamInput);
do_check_eq(info.preferredURI.spec, searchURL);
} else {
let urlparamInput = encodeURIComponent(sanitize(testInput)).replace("%20", "+", "g");
// If the input starts with `?`, then info.preferredURI.spec will omit it
// In order to test this behaviour, remove `?` only if it is the first character
if (urlparamInput.startsWith("%3F")) {
urlparamInput = urlparamInput.replace("%3F", "");
}
let searchURL = kSearchEngineURL.replace("{searchTerms}", urlparamInput);
let spec = info.preferredURI.spec.replace("%27", "'", "g");
do_check_eq(spec, searchURL);
} else {
do_check_eq(info.preferredURI, null);
}
} else {