зеркало из https://github.com/mozilla/gecko-dev.git
Bug 971341: Fix infinite tab loading due to missing characters in CSP's path regexes r=sstamm
This commit is contained in:
Родитель
fdf116730e
Коммит
8b3c6564e3
|
@ -63,22 +63,21 @@ const R_HOST = new RegExp ("\\*|(((\\*\\.)?" + R_HOSTCHAR.source +
|
|||
// port = ":" ( 1*DIGIT / "*" )
|
||||
const R_PORT = new RegExp ("(\\:([0-9]+|\\*))", 'i');
|
||||
|
||||
// path
|
||||
const R_PATH = new RegExp("(\\/(([a-zA-Z0-9\\-\\_]+)\\/?)*)", 'i');
|
||||
|
||||
// file
|
||||
const R_FILE = new RegExp("(\\/([a-zA-Z0-9\\-\\_]+)\\.([a-zA-Z]+))", 'i');
|
||||
|
||||
// host-source = [ scheme "://" ] host [ port path file ]
|
||||
const R_HOSTSRC = new RegExp ("^((((" + R_SCHEME.source + "\\:\\/\\/)?("
|
||||
const R_HOSTSRC = new RegExp ("^((" + R_SCHEME.source + "\\:\\/\\/)?("
|
||||
+ R_HOST.source + ")"
|
||||
+ R_PORT.source + "?)"
|
||||
+ R_PATH.source + "?)"
|
||||
+ R_FILE.source + "?)$", 'i');
|
||||
+ R_PORT.source + "?)$", 'i');
|
||||
|
||||
function STRIP_INPUTDELIM(re) {
|
||||
return re.replace(/(^\^)|(\$$)/g, "");
|
||||
}
|
||||
|
||||
// ext-host-source = host-source "/" *( <VCHAR except ";" and ","> )
|
||||
// ; ext-host-source is reserved for future use.
|
||||
const R_EXTHOSTSRC = new RegExp ("^" + R_HOSTSRC.source + "\\/[:print:]+$", 'i');
|
||||
const R_VCHAR_EXCEPT = new RegExp("[!-+--:<-~]"); // ranges exclude , and ;
|
||||
const R_EXTHOSTSRC = new RegExp ("^" + STRIP_INPUTDELIM(R_HOSTSRC.source)
|
||||
+ "\\/"
|
||||
+ R_VCHAR_EXCEPT.source + "*$", 'i');
|
||||
|
||||
// keyword-source = "'self'" / "'unsafe-inline'" / "'unsafe-eval'"
|
||||
const R_KEYWORDSRC = new RegExp ("^('self'|'unsafe-inline'|'unsafe-eval')$", 'i');
|
||||
|
@ -99,6 +98,7 @@ const R_HASHSRC = new RegExp ("^'" + R_HASH_ALGOS.source + "-" + R_BASE64.sou
|
|||
// source-exp = scheme-source / host-source / keyword-source
|
||||
const R_SOURCEEXP = new RegExp (R_SCHEMESRC.source + "|" +
|
||||
R_HOSTSRC.source + "|" +
|
||||
R_EXTHOSTSRC.source + "|" +
|
||||
R_KEYWORDSRC.source + "|" +
|
||||
R_NONCESRC.source + "|" +
|
||||
R_HASHSRC.source, 'i');
|
||||
|
@ -1392,7 +1392,13 @@ CSPSource.fromString = function(aStr, aCSPRep, self, enforceSelfChecks) {
|
|||
sObj._scheme = schemeMatch[0];
|
||||
}
|
||||
|
||||
// get array of matches to the R_HOST regular expression
|
||||
// Bug 916054: in CSP 1.0, source-expressions that are paths should have
|
||||
// the path after the origin ignored and only the origin enforced.
|
||||
if (R_EXTHOSTSRC.test(aStr)) {
|
||||
var extHostMatch = R_EXTHOSTSRC.exec(aStr);
|
||||
aStr = extHostMatch[1];
|
||||
}
|
||||
|
||||
var hostMatch = R_HOSTSRC.exec(aStr);
|
||||
if (!hostMatch) {
|
||||
cspError(aCSPRep, CSPLocalizer.getFormatStr("couldntParseInvalidSource",
|
||||
|
@ -1400,24 +1406,20 @@ CSPSource.fromString = function(aStr, aCSPRep, self, enforceSelfChecks) {
|
|||
return null;
|
||||
}
|
||||
// Host regex gets scheme, so remove scheme from aStr. Add 3 for '://'
|
||||
if (schemeMatch)
|
||||
if (schemeMatch) {
|
||||
hostMatch = R_HOSTSRC.exec(aStr.substring(schemeMatch[0].length + 3));
|
||||
|
||||
// Bug 916054: in CSP 1.0, source-expressions that are paths should have
|
||||
// the path after the origin ignored and only the origin enforced.
|
||||
hostMatch[0] = hostMatch[0].replace(R_FILE, "");
|
||||
hostMatch[0] = hostMatch[0].replace(R_PATH, "");
|
||||
}
|
||||
|
||||
var portMatch = R_PORT.exec(hostMatch);
|
||||
|
||||
// Host regex also gets port, so remove the port here.
|
||||
if (portMatch)
|
||||
if (portMatch) {
|
||||
hostMatch = R_HOSTSRC.exec(hostMatch[0].substring(0, hostMatch[0].length - portMatch[0].length));
|
||||
}
|
||||
|
||||
sObj._host = CSPHost.fromString(hostMatch[0]);
|
||||
if (!portMatch) {
|
||||
// gets the default port for the given scheme
|
||||
defPort = Services.io.getProtocolHandler(sObj._scheme).defaultPort;
|
||||
var defPort = Services.io.getProtocolHandler(sObj._scheme).defaultPort;
|
||||
if (!defPort) {
|
||||
cspError(aCSPRep,
|
||||
CSPLocalizer.getFormatStr("couldntParseInvalidSource",
|
||||
|
@ -1440,12 +1442,14 @@ CSPSource.fromString = function(aStr, aCSPRep, self, enforceSelfChecks) {
|
|||
}
|
||||
|
||||
// check for a nonce-source match
|
||||
if (R_NONCESRC.test(aStr))
|
||||
if (R_NONCESRC.test(aStr)) {
|
||||
return CSPNonceSource.fromString(aStr, aCSPRep);
|
||||
}
|
||||
|
||||
// check for a hash-source match
|
||||
if (R_HASHSRC.test(aStr))
|
||||
if (R_HASHSRC.test(aStr)) {
|
||||
return CSPHashSource.fromString(aStr, aCSPRep);
|
||||
}
|
||||
|
||||
// check for 'self' (case insensitive)
|
||||
if (aStr.toLowerCase() === "'self'") {
|
||||
|
|
|
@ -27,6 +27,7 @@ var policies = [
|
|||
["allowed", "test1.example.com/path-1/path_2/file_1.js"],
|
||||
["allowed", "test1.example.com/path-1/path_2/file-2.js"],
|
||||
["allowed", "test1.example.com/path-1/path_2/f.js"],
|
||||
["allowed", "test1.example.com/path-1/path_2/f.oo.js"],
|
||||
["allowed", "*.example.com"],
|
||||
["allowed", "*.example.com/"],
|
||||
["allowed", "*.example.com/path-1"],
|
||||
|
@ -36,6 +37,7 @@ var policies = [
|
|||
["allowed", "*.example.com/path-1/path_2/file_1.js"],
|
||||
["allowed", "*.example.com/path-1/path_2/file-2.js"],
|
||||
["allowed", "*.example.com/path-1/path_2/f.js"],
|
||||
["allowed", "*.example.com/path-1/path_2/f.oo.js"],
|
||||
["allowed", "test1.example.com:80"],
|
||||
["allowed", "test1.example.com:80/"],
|
||||
["allowed", "test1.example.com:80/path-1"],
|
||||
|
@ -43,6 +45,7 @@ var policies = [
|
|||
["allowed", "test1.example.com:80/path-1/path_2"],
|
||||
["allowed", "test1.example.com:80/path-1/path_2/"],
|
||||
["allowed", "test1.example.com:80/path-1/path_2/file.js"],
|
||||
["allowed", "test1.example.com:80/path-1/path_2/f.ile.js"],
|
||||
["allowed", "test1.example.com:*"],
|
||||
["allowed", "test1.example.com:*/"],
|
||||
["allowed", "test1.example.com:*/path-1"],
|
||||
|
@ -50,13 +53,9 @@ var policies = [
|
|||
["allowed", "test1.example.com:*/path-1/path_2"],
|
||||
["allowed", "test1.example.com:*/path-1/path_2/"],
|
||||
["allowed", "test1.example.com:*/path-1/path_2/file.js"],
|
||||
["allowed", "test1.example.com:*/path-1/path_2/f.ile.js"],
|
||||
// the following tests should fail
|
||||
["blocked", "test1.example.com/path-1//path_2"],
|
||||
["blocked", "test1.example.com/path-1/file.js.cpp"],
|
||||
["blocked", "test1.example.com:88path-1/"],
|
||||
["blocked", "test1.example.com:80//"],
|
||||
["blocked", "test1.example.com:80//path-1"],
|
||||
["blocked", "test1.example.com:80/.js"],
|
||||
["blocked", "test1.example.com:80.js"],
|
||||
["blocked", "test1.example.com:*.js"],
|
||||
["blocked", "test1.example.com:*."]
|
||||
|
|
|
@ -12,6 +12,32 @@ var ioService = Cc["@mozilla.org/network/io-service;1"]
|
|||
.getService(Ci.nsIIOService);
|
||||
var self = ioService.newURI("http://test1.example.com:80", null, null);
|
||||
|
||||
function testValidSRCsHostSourceWithSchemeAndPath() {
|
||||
var csps = [
|
||||
"http://test1.example.com",
|
||||
"http://test1.example.com/",
|
||||
"http://test1.example.com/path-1",
|
||||
"http://test1.example.com/path-1/",
|
||||
"http://test1.example.com/path-1/path_2/",
|
||||
"http://test1.example.com/path-1/path_2/file.js",
|
||||
"http://test1.example.com/path-1/path_2/file_1.js",
|
||||
"http://test1.example.com/path-1/path_2/file-2.js",
|
||||
"http://test1.example.com/path-1/path_2/f.js",
|
||||
"http://test1.example.com/path-1/path_2/f.oo.js"
|
||||
]
|
||||
|
||||
var obj;
|
||||
var expected = "http://test1.example.com:80";
|
||||
for (let i in csps) {
|
||||
var src = csps[i];
|
||||
obj = CSPSourceList.fromString(src, undefined, self);
|
||||
dump("expected: " + expected + "\n");
|
||||
dump("got: " + obj._sources[0] + "\n");
|
||||
do_check_eq(1, obj._sources.length);
|
||||
do_check_eq(obj._sources[0], expected);
|
||||
}
|
||||
}
|
||||
|
||||
function testValidSRCsRegularHost() {
|
||||
var csps = [
|
||||
"test1.example.com",
|
||||
|
@ -22,7 +48,8 @@ function testValidSRCsRegularHost() {
|
|||
"test1.example.com/path-1/path_2/file.js",
|
||||
"test1.example.com/path-1/path_2/file_1.js",
|
||||
"test1.example.com/path-1/path_2/file-2.js",
|
||||
"test1.example.com/path-1/path_2/f.js"
|
||||
"test1.example.com/path-1/path_2/f.js",
|
||||
"test1.example.com/path-1/path_2/f.oo.js"
|
||||
]
|
||||
|
||||
var obj;
|
||||
|
@ -46,6 +73,7 @@ function testValidSRCsWildCardHost() {
|
|||
"*.example.com/path-1/path_2/file_1.js",
|
||||
"*.example.com/path-1/path_2/file-2.js",
|
||||
"*.example.com/path-1/path_2/f.js",
|
||||
"*.example.com/path-1/path_2/f.oo.js"
|
||||
]
|
||||
|
||||
var obj;
|
||||
|
@ -66,7 +94,8 @@ function testValidSRCsRegularPort() {
|
|||
"test1.example.com:80/path-1/",
|
||||
"test1.example.com:80/path-1/path_2",
|
||||
"test1.example.com:80/path-1/path_2/",
|
||||
"test1.example.com:80/path-1/path_2/file.js"
|
||||
"test1.example.com:80/path-1/path_2/file.js",
|
||||
"test1.example.com:80/path-1/path_2/f.ile.js"
|
||||
]
|
||||
|
||||
var obj;
|
||||
|
@ -87,7 +116,8 @@ function testValidSRCsWildCardPort() {
|
|||
"test1.example.com:*/path-1/",
|
||||
"test1.example.com:*/path-1/path_2",
|
||||
"test1.example.com:*/path-1/path_2/",
|
||||
"test1.example.com:*/path-1/path_2/file.js"
|
||||
"test1.example.com:*/path-1/path_2/file.js",
|
||||
"test1.example.com:*/path-1/path_2/f.ile.js"
|
||||
]
|
||||
|
||||
var obj;
|
||||
|
@ -103,12 +133,7 @@ function testValidSRCsWildCardPort() {
|
|||
|
||||
function testInvalidSRCs() {
|
||||
var csps = [
|
||||
"test1.example.com/path-1//path_2",
|
||||
"test1.example.com/path-1/file.js.cpp",
|
||||
"test1.example.com:88path-1/",
|
||||
"test1.example.com:80//",
|
||||
"test1.example.com:80//path-1",
|
||||
"test1.example.com:80/.js",
|
||||
"test1.example.com:80.js",
|
||||
"test1.example.com:*.js",
|
||||
"test1.example.com:*."
|
||||
|
@ -124,6 +149,7 @@ function testInvalidSRCs() {
|
|||
}
|
||||
|
||||
function run_test() {
|
||||
testValidSRCsHostSourceWithSchemeAndPath();
|
||||
testValidSRCsRegularHost();
|
||||
testValidSRCsWildCardHost();
|
||||
testValidSRCsRegularPort();
|
||||
|
|
Загрузка…
Ссылка в новой задаче