Detect invalid usage of combinators in :not() pseudoclass

Related feedback:
- https://www.reddit.com/r/uBlockOrigin/comments/z2ttcx/
This commit is contained in:
Raymond Hill 2022-11-25 10:21:58 -05:00
parent 96fdae726a
commit 62601639f6
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
1 changed files with 31 additions and 16 deletions

View File

@ -1547,8 +1547,9 @@ Parser.prototype.SelectorCompiler = class {
}
if ( data.type !== 'PseudoClassSelector' ) { return; }
// Post-analysis
// Mind https://w3c.github.io/csswg-drafts/selectors-4/#has-pseudo
// Post-analysis, mind:
// - https://w3c.github.io/csswg-drafts/selectors-4/#has-pseudo
// - https://w3c.github.io/csswg-drafts/selectors-4/#negation
data.name = this.normalizedOperators.get(data.name) || data.name;
if ( this.proceduralOperatorNames.has(data.name) ) {
data.type = 'ProceduralSelector';
@ -1558,20 +1559,30 @@ Parser.prototype.SelectorCompiler = class {
data.type = 'Error';
return;
}
if ( this.maybeProceduralOperatorNames.has(data.name) ) {
if ( this.astHasType(args, 'ProceduralSelector') ) {
if ( this.maybeProceduralOperatorNames.has(data.name) === false ) {
return;
}
if ( this.astHasType(args, 'ProceduralSelector') ) {
data.type = 'ProceduralSelector';
return;
}
switch ( data.name ) {
case 'has':
if (
this.asProcedural ||
this.nativeCssHas !== true ||
this.astHasName(args, 'has')
) {
data.type = 'ProceduralSelector';
} else if ( data.name === 'has' ) {
if (
this.asProcedural ||
this.nativeCssHas !== true ||
this.astHasName(args, 'has')
) {
data.type = 'ProceduralSelector';
} else if ( this.astHasType(args, 'PseudoElementSelector') ) {
data.type = 'Error';
}
} else if ( this.astHasType(args, 'PseudoElementSelector') ) {
data.type = 'Error';
}
break;
case 'not':
if ( this.astHasType(args, 'Combinator', 0) ) {
data.type = 'Error';
}
break;
}
}
@ -1768,11 +1779,15 @@ Parser.prototype.SelectorCompiler = class {
return out;
}
astHasType(parts, type) {
astHasType(parts, type, depth = 0x7FFFFFFF) {
if ( Array.isArray(parts) === false ) { return false; }
for ( const part of parts ) {
if ( part.data.type === type ) { return true; }
if ( Array.isArray(part.args) && this.astHasType(part.args, type) ) {
if (
Array.isArray(part.args) &&
depth !== 0 &&
this.astHasType(part.args, type, depth-1)
) {
return true;
}
}