mirror of https://github.com/gorhill/uBlock.git
hardening against bad regexes
This commit is contained in:
parent
ba20843e07
commit
72201527d3
|
@ -39,6 +39,16 @@ var µb = µBlock;
|
||||||
var encode = JSON.stringify;
|
var encode = JSON.stringify;
|
||||||
var decode = JSON.parse;
|
var decode = JSON.parse;
|
||||||
|
|
||||||
|
var isBadRegex = function(s) {
|
||||||
|
try {
|
||||||
|
void new RegExp(s);
|
||||||
|
} catch (ex) {
|
||||||
|
isBadRegex.message = ex.toString();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/*
|
/*
|
||||||
var histogram = function(label, buckets) {
|
var histogram = function(label, buckets) {
|
||||||
|
@ -252,11 +262,11 @@ FilterParser.prototype.reset = function() {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
FilterParser.prototype.parse = function(s) {
|
FilterParser.prototype.parse = function(raw) {
|
||||||
// important!
|
// important!
|
||||||
this.reset();
|
this.reset();
|
||||||
|
|
||||||
var matches = this.reParser.exec(s);
|
var matches = this.reParser.exec(raw);
|
||||||
if ( matches === null || matches.length !== 4 ) {
|
if ( matches === null || matches.length !== 4 ) {
|
||||||
this.cosmetic = false;
|
this.cosmetic = false;
|
||||||
return this;
|
return this;
|
||||||
|
@ -301,20 +311,43 @@ FilterParser.prototype.parse = function(s) {
|
||||||
// Examples:
|
// Examples:
|
||||||
// focus.de##script:contains(/uabInject/)
|
// focus.de##script:contains(/uabInject/)
|
||||||
// focus.de##script:contains(uabInject)
|
// focus.de##script:contains(uabInject)
|
||||||
if ( this.suffix.charAt(0) === 's' && this.reScriptContains.test(this.suffix) ) {
|
|
||||||
// Currently supported only as non-generic selector. Also, exception
|
// Inline script tag filter?
|
||||||
// script tag filter makes no sense, ignore.
|
if (
|
||||||
if ( this.hostnames.length === 0 || this.unhide === 1 ) {
|
this.suffix.charAt(0) !== 's' ||
|
||||||
this.invalid = true;
|
this.reScriptContains.test(this.suffix) === false )
|
||||||
return this;
|
{
|
||||||
}
|
return this;
|
||||||
var suffix = this.suffix;
|
}
|
||||||
this.suffix = 'script//:';
|
|
||||||
if ( suffix.charAt(16) !== '/' || suffix.slice(-2) !== '/)' ) {
|
// Currently supported only as non-generic selector. Also, exception
|
||||||
this.suffix += suffix.slice(16, -1).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
// script tag filter makes no sense, ignore.
|
||||||
} else {
|
if ( this.hostnames.length === 0 || this.unhide === 1 ) {
|
||||||
this.suffix += suffix.slice(17, -2).replace(/\\/g, '\\');
|
this.invalid = true;
|
||||||
}
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
var suffix = this.suffix;
|
||||||
|
this.suffix = 'script//:';
|
||||||
|
|
||||||
|
// Plain string-based?
|
||||||
|
if ( suffix.charAt(16) !== '/' || suffix.slice(-2) !== '/)' ) {
|
||||||
|
this.suffix += suffix.slice(16, -1).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regex-based
|
||||||
|
this.suffix += suffix.slice(17, -2).replace(/\\/g, '\\');
|
||||||
|
|
||||||
|
// Valid regex?
|
||||||
|
if ( isBadRegex(this.suffix) ) {
|
||||||
|
console.error(
|
||||||
|
"uBlock Origin> discarding bad regular expression-based cosmetic filter '%s': '%s'",
|
||||||
|
raw,
|
||||||
|
isBadRegex.message
|
||||||
|
);
|
||||||
|
this.invalid = true;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -176,6 +176,16 @@ var isFirstParty = function(firstPartyDomain, hostname) {
|
||||||
return c === '.' || c === '';
|
return c === '.' || c === '';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var isBadRegex = function(s) {
|
||||||
|
try {
|
||||||
|
void new RegExp(s);
|
||||||
|
} catch (ex) {
|
||||||
|
isBadRegex.message = ex.toString();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
var alwaysTruePseudoRegex = {
|
var alwaysTruePseudoRegex = {
|
||||||
match: { '0': '', index: 0 },
|
match: { '0': '', index: 0 },
|
||||||
exec: function(s) {
|
exec: function(s) {
|
||||||
|
@ -1539,6 +1549,14 @@ FilterParser.prototype.parse = function(raw) {
|
||||||
if ( s.charAt(0) === '/' && s.slice(-1) === '/' && s.length > 2 ) {
|
if ( s.charAt(0) === '/' && s.slice(-1) === '/' && s.length > 2 ) {
|
||||||
this.isRegex = true;
|
this.isRegex = true;
|
||||||
this.f = s.slice(1, -1);
|
this.f = s.slice(1, -1);
|
||||||
|
if ( isBadRegex(this.f) ) {
|
||||||
|
console.error(
|
||||||
|
"uBlock Origin> discarding bad regular expression-based network filter '%s': '%s'",
|
||||||
|
raw,
|
||||||
|
isBadRegex.message
|
||||||
|
);
|
||||||
|
this.unsupported = true;
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue