Syntax highlight dubious patterns

Network filters with dubious patterns are discarded
by the static network filtering engine.
This commit is contained in:
Raymond Hill 2020-06-08 08:53:29 -04:00
parent 5752ad58b8
commit 58c6baf0ba
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
1 changed files with 37 additions and 24 deletions

View File

@ -324,11 +324,14 @@ const Parser = class {
let patternStartIsRegex = let patternStartIsRegex =
islice < this.optionsAnchorSpan.i && islice < this.optionsAnchorSpan.i &&
hasBits(this.slices[islice], BITSlash); hasBits(this.slices[islice], BITSlash);
let patternIsRegex = patternStartIsRegex;
let patternIsRegex = patternStartIsRegex && ( if ( patternStartIsRegex ) {
this.patternSpan.l === 3 && this.slices[this.patternSpan.i+2] > 2 || const { i, l } = this.patternSpan;
hasBits(this.slices[this.optionsAnchorSpan.i-3], BITSlash) patternIsRegex = (
l === 3 && this.slices[i+2] > 2 ||
l > 3 && hasBits(this.slices[i+l-3], BITSlash)
); );
}
// If the pattern is not a regex, there might be options. // If the pattern is not a regex, there might be options.
if ( patternIsRegex === false ) { if ( patternIsRegex === false ) {
@ -364,12 +367,15 @@ const Parser = class {
this.optionsSpan.i = i; this.optionsSpan.i = i;
this.optionsSpan.l = this.commentSpan.i - i; this.optionsSpan.l = this.commentSpan.i - i;
this.optionsBits = optionsBits; this.optionsBits = optionsBits;
patternIsRegex = patternStartIsRegex && ( if ( patternStartIsRegex ) {
this.patternSpan.l === 3 && this.slices[this.patternSpan.i+2] > 2 || const { i, l } = this.patternSpan;
hasBits(this.slices[this.optionsAnchorSpan.i-3], BITSlash) patternIsRegex = (
l === 3 && this.slices[i+2] > 2 ||
l > 3 && hasBits(this.slices[i+l-3], BITSlash)
); );
} }
} }
}
// If the pattern is a regex, remember this. // If the pattern is a regex, remember this.
if ( patternIsRegex ) { if ( patternIsRegex ) {
@ -557,7 +563,7 @@ const Parser = class {
analyzeNetExtra() { analyzeNetExtra() {
// Validate regex // Validate regex
if ( hasBits(this.flavorBits, BITFlavorNetRegex) ) { if ( this.patternIsRegex() ) {
try { try {
void new RegExp(this.getNetPattern()); void new RegExp(this.getNetPattern());
} }
@ -565,6 +571,8 @@ const Parser = class {
const { i, l } = this.patternSpan; const { i, l } = this.patternSpan;
this.markSlices(i, i + l, BITError); this.markSlices(i, i + l, BITError);
} }
} else if ( this.patternIsDubious() ) {
this.markSpan(this.patternSpan, BITError);
} }
// Validate options // Validate options
for ( const _ of this.options() ) { void _; } for ( const _ of this.options() ) { void _; }
@ -718,6 +726,11 @@ const Parser = class {
} }
} }
markSpan(span, bits) {
const { i, l } = span;
this.markSlices(i, i + l, bits);
}
unmarkSlices(beg, end, bits) { unmarkSlices(beg, end, bits) {
while ( beg < end ) { while ( beg < end ) {
this.slices[beg] &= ~bits; this.slices[beg] &= ~bits;
@ -799,9 +812,10 @@ const Parser = class {
// Examples of dubious filter content: // Examples of dubious filter content:
// - Single character other than `*` wildcard // - Single character other than `*` wildcard
patternIsDubious() { patternIsDubious() {
return this.patternSpan.l === 3 && return this.patternBits !== BITAsterisk &&
this.patternBits !== BITAsterisk && this.optionsSpan.l === 0 &&
this.optionsSpan.l === 0; this.patternSpan.l === 3 &&
this.slices[this.patternSpan.i+2] === 1;
} }
patternIsMatchAll() { patternIsMatchAll() {
@ -1277,9 +1291,9 @@ const NetOptionsIterator = class {
this.parser = parser; this.parser = parser;
this.exception = false; this.exception = false;
this.interactive = false; this.interactive = false;
this.i = 0;
this.optSlices = []; this.optSlices = [];
this.writePtr = 0; this.writePtr = 0;
this.readPtr = 0;
this.item = { this.item = {
id: OPTTokenInvalid, id: OPTTokenInvalid,
val: undefined, val: undefined,
@ -1289,27 +1303,26 @@ const NetOptionsIterator = class {
this.done = true; this.done = true;
} }
[Symbol.iterator]() { [Symbol.iterator]() {
this.writePtr = 0; this.readPtr = this.writePtr = 0;
const optSpan = this.parser.optionsSpan; this.done = this.parser.optionsSpan.l === 0;
this.done = optSpan.l === 0;
if ( this.done ) { if ( this.done ) {
this.value = undefined; this.value = undefined;
return this; return this;
} }
// Prime iterator // Prime iterator
this.value = this.item; this.value = this.item;
this.i = 0;
this.exception = this.parser.isException(); this.exception = this.parser.isException();
this.interactive = this.parser.interactive; this.interactive = this.parser.interactive;
// Each option is encoded as follow: // Each option is encoded as follow:
// //
// desc ~token=value, // desc ~token=value,
// 0 12 34 5 // 0 1| 3| 5
// 2 4
// //
// At index 0 is the option descriptor. // At index 0 is the option descriptor.
// At indices 1-5 is a slice index. // At indices 1-5 is a slice index.
const lopts = optSpan.i; const lopts = this.parser.optionsSpan.i;
const ropts = lopts + optSpan.l; const ropts = lopts + this.parser.optionsSpan.l;
const slices = this.parser.slices; const slices = this.parser.slices;
const optSlices = this.optSlices; const optSlices = this.optSlices;
let writePtr = 0; let writePtr = 0;
@ -1394,12 +1407,12 @@ const NetOptionsIterator = class {
return this; return this;
} }
next() { next() {
if ( this.i === this.writePtr ) { const i = this.readPtr;
if ( i === this.writePtr ) {
this.value = undefined; this.value = undefined;
this.done = true; this.done = true;
return this; return this;
} }
const i = this.i;
const optSlices = this.optSlices; const optSlices = this.optSlices;
const descriptor = optSlices[i+0]; const descriptor = optSlices[i+0];
this.item.id = descriptor & 0xFF; this.item.id = descriptor & 0xFF;
@ -1420,7 +1433,7 @@ const NetOptionsIterator = class {
); );
} }
} }
this.i += 6; this.readPtr = i + 6;
return this; return this;
} }
}; };