mirror of
https://github.com/gorhill/uBlock.git
synced 2024-09-15 07:22:28 +02:00
Mitigate generic cosmetic filters erroneously targeting html/body
Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/1692 The ids/classes from html/body elements will leave out looking up lowly generic cosmetic filters made of a single identifier. This does not absolutely guarantee that html/body elements will never be targeted, but it should greatly mitigate the probability that this erroneously happens.
This commit is contained in:
parent
925c01dc14
commit
f0b46bde4f
@ -982,14 +982,14 @@ vAPI.DOMFilterer = class {
|
|||||||
accepted: 0,
|
accepted: 0,
|
||||||
iterated: 0,
|
iterated: 0,
|
||||||
stopped: false,
|
stopped: false,
|
||||||
add: function(nodes) {
|
add(nodes) {
|
||||||
if ( nodes.length === 0 || this.accepted >= maxSurveyNodes ) {
|
if ( nodes.length === 0 || this.accepted >= maxSurveyNodes ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.nodeLists.push(nodes);
|
this.nodeLists.push(nodes);
|
||||||
this.accepted += nodes.length;
|
this.accepted += nodes.length;
|
||||||
},
|
},
|
||||||
next: function() {
|
next() {
|
||||||
if ( this.nodeLists.length === 0 || this.stopped ) { return 0; }
|
if ( this.nodeLists.length === 0 || this.stopped ) { return 0; }
|
||||||
const nodeLists = this.nodeLists;
|
const nodeLists = this.nodeLists;
|
||||||
let ib = 0;
|
let ib = 0;
|
||||||
@ -1018,7 +1018,7 @@ vAPI.DOMFilterer = class {
|
|||||||
}
|
}
|
||||||
return ib;
|
return ib;
|
||||||
},
|
},
|
||||||
hasNodes: function() {
|
hasNodes() {
|
||||||
return this.nodeLists.length !== 0;
|
return this.nodeLists.length !== 0;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -1032,46 +1032,46 @@ vAPI.DOMFilterer = class {
|
|||||||
// http://www.w3.org/TR/2014/REC-html5-20141028/infrastructure.html#space-separated-tokens
|
// http://www.w3.org/TR/2014/REC-html5-20141028/infrastructure.html#space-separated-tokens
|
||||||
// http://jsperf.com/enumerate-classes/6
|
// http://jsperf.com/enumerate-classes/6
|
||||||
|
|
||||||
|
const idFromNode = (node, out) => {
|
||||||
|
const raw = node.id;
|
||||||
|
if ( typeof raw !== 'string' || raw.length === 0 ) { return; }
|
||||||
|
const s = raw.trim();
|
||||||
|
if ( queriedIds.has(s) || s.length === 0 ) { return; }
|
||||||
|
out.push(s);
|
||||||
|
queriedIds.add(s);
|
||||||
|
};
|
||||||
|
|
||||||
|
const classesFromNode = (node, out) => {
|
||||||
|
const s = node.className;
|
||||||
|
if ( typeof s !== 'string' || s.length === 0 ) { return; }
|
||||||
|
if ( reWhitespace.test(s) === false ) {
|
||||||
|
if ( queriedClasses.has(s) ) { return; }
|
||||||
|
out.push(s);
|
||||||
|
queriedClasses.add(s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for ( const s of node.classList.values() ) {
|
||||||
|
if ( queriedClasses.has(s) ) { continue; }
|
||||||
|
out.push(s);
|
||||||
|
queriedClasses.add(s);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const surveyPhase1 = function() {
|
const surveyPhase1 = function() {
|
||||||
//console.time('dom surveyor/surveying');
|
//console.time('dom surveyor/surveying');
|
||||||
const t0 = performance.now();
|
const t0 = performance.now();
|
||||||
const rews = reWhitespace;
|
|
||||||
const ids = [];
|
const ids = [];
|
||||||
const classes = [];
|
const classes = [];
|
||||||
const nodes = pendingNodes.buffer;
|
const nodes = pendingNodes.buffer;
|
||||||
const deadline = t0 + maxSurveyTimeSlice;
|
const deadline = t0 + maxSurveyTimeSlice;
|
||||||
let qids = queriedIds;
|
|
||||||
let qcls = queriedClasses;
|
|
||||||
let processed = 0;
|
let processed = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const n = pendingNodes.next();
|
const n = pendingNodes.next();
|
||||||
if ( n === 0 ) { break; }
|
if ( n === 0 ) { break; }
|
||||||
for ( let i = 0; i < n; i++ ) {
|
for ( let i = 0; i < n; i++ ) {
|
||||||
const node = nodes[i]; nodes[i] = null;
|
const node = nodes[i]; nodes[i] = null;
|
||||||
let v = node.id;
|
idFromNode(node, ids);
|
||||||
if ( typeof v === 'string' && v.length !== 0 ) {
|
classesFromNode(node, classes);
|
||||||
v = v.trim();
|
|
||||||
if ( qids.has(v) === false && v.length !== 0 ) {
|
|
||||||
ids.push(v); qids.add(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let vv = node.className;
|
|
||||||
if ( typeof vv === 'string' && vv.length !== 0 ) {
|
|
||||||
if ( rews.test(vv) === false ) {
|
|
||||||
if ( qcls.has(vv) === false ) {
|
|
||||||
classes.push(vv); qcls.add(vv);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
vv = node.classList;
|
|
||||||
let j = vv.length;
|
|
||||||
while ( j-- ) {
|
|
||||||
const v = vv[j];
|
|
||||||
if ( qcls.has(v) === false ) {
|
|
||||||
classes.push(v); qcls.add(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
processed += n;
|
processed += n;
|
||||||
if ( performance.now() >= deadline ) { break; }
|
if ( performance.now() >= deadline ) { break; }
|
||||||
@ -1084,8 +1084,7 @@ vAPI.DOMFilterer = class {
|
|||||||
messaging.send('contentscript', {
|
messaging.send('contentscript', {
|
||||||
what: 'retrieveGenericCosmeticSelectors',
|
what: 'retrieveGenericCosmeticSelectors',
|
||||||
hostname,
|
hostname,
|
||||||
ids,
|
ids, classes,
|
||||||
classes,
|
|
||||||
exceptions: domFilterer.exceptions,
|
exceptions: domFilterer.exceptions,
|
||||||
cost: surveyCost,
|
cost: surveyCost,
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
@ -1164,19 +1163,40 @@ vAPI.DOMFilterer = class {
|
|||||||
}
|
}
|
||||||
//console.time('dom surveyor/dom layout created');
|
//console.time('dom surveyor/dom layout created');
|
||||||
domFilterer = vAPI.domFilterer;
|
domFilterer = vAPI.domFilterer;
|
||||||
pendingNodes.add(document.querySelectorAll('[id],[class]'));
|
pendingNodes.add(document.querySelectorAll(
|
||||||
|
'[id]:not(html):not(body),[class]:not(html):not(body)'
|
||||||
|
));
|
||||||
surveyTimer.start();
|
surveyTimer.start();
|
||||||
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/1692
|
||||||
|
// Look-up safe-only selectors to mitigate probability of
|
||||||
|
// html/body elements of erroneously being targeted.
|
||||||
|
const ids = [], classes = [];
|
||||||
|
idFromNode(document.documentElement, ids);
|
||||||
|
idFromNode(document.body, ids);
|
||||||
|
classesFromNode(document.documentElement, classes);
|
||||||
|
classesFromNode(document.body, classes);
|
||||||
|
if ( ids.length !== 0 || classes.length !== 0 ) {
|
||||||
|
messaging.send('contentscript', {
|
||||||
|
what: 'retrieveGenericCosmeticSelectors',
|
||||||
|
hostname,
|
||||||
|
ids, classes,
|
||||||
|
exceptions: domFilterer.exceptions,
|
||||||
|
safeOnly: true,
|
||||||
|
}).then(response => {
|
||||||
|
surveyPhase3(response);
|
||||||
|
});
|
||||||
|
}
|
||||||
//console.timeEnd('dom surveyor/dom layout created');
|
//console.timeEnd('dom surveyor/dom layout created');
|
||||||
},
|
},
|
||||||
onDOMChanged: function(addedNodes) {
|
onDOMChanged: function(addedNodes) {
|
||||||
if ( addedNodes.length === 0 ) { return; }
|
if ( addedNodes.length === 0 ) { return; }
|
||||||
//console.time('dom surveyor/dom layout changed');
|
//console.time('dom surveyor/dom layout changed');
|
||||||
let i = addedNodes.length;
|
for ( const node of addedNodes ) {
|
||||||
while ( i-- ) {
|
|
||||||
const node = addedNodes[i];
|
|
||||||
pendingNodes.add([ node ]);
|
pendingNodes.add([ node ]);
|
||||||
if ( node.firstElementChild === null ) { continue; }
|
if ( node.firstElementChild === null ) { continue; }
|
||||||
pendingNodes.add(node.querySelectorAll('[id],[class]'));
|
pendingNodes.add(node.querySelectorAll(
|
||||||
|
'[id]:not(html):not(body),[class]:not(html):not(body)'
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if ( pendingNodes.hasNodes() ) {
|
if ( pendingNodes.hasNodes() ) {
|
||||||
surveyTimer.start(1);
|
surveyTimer.start(1);
|
||||||
|
@ -829,6 +829,7 @@ FilterContainer.prototype.retrieveGenericSelectors = function(request) {
|
|||||||
if ( this.acceptedCount === 0 ) { return; }
|
if ( this.acceptedCount === 0 ) { return; }
|
||||||
if ( !request.ids && !request.classes ) { return; }
|
if ( !request.ids && !request.classes ) { return; }
|
||||||
|
|
||||||
|
const { safeOnly = false } = request;
|
||||||
//console.time('cosmeticFilteringEngine.retrieveGenericSelectors');
|
//console.time('cosmeticFilteringEngine.retrieveGenericSelectors');
|
||||||
|
|
||||||
const simpleSelectors = this.$simpleSet;
|
const simpleSelectors = this.$simpleSet;
|
||||||
@ -841,24 +842,24 @@ FilterContainer.prototype.retrieveGenericSelectors = function(request) {
|
|||||||
const entry = this.lowlyGeneric[type];
|
const entry = this.lowlyGeneric[type];
|
||||||
const selectors = request[entry.canonical];
|
const selectors = request[entry.canonical];
|
||||||
if ( Array.isArray(selectors) === false ) { continue; }
|
if ( Array.isArray(selectors) === false ) { continue; }
|
||||||
for ( let selector of selectors ) {
|
for ( const selector of selectors ) {
|
||||||
if ( entry.simple.has(selector) === false ) { continue; }
|
if ( entry.simple.has(selector) === false ) { continue; }
|
||||||
const bucket = entry.complex.get(selector);
|
const bucket = entry.complex.get(selector);
|
||||||
if ( bucket !== undefined ) {
|
if ( bucket === undefined ) {
|
||||||
if ( Array.isArray(bucket) ) {
|
if ( safeOnly ) { continue; }
|
||||||
for ( const selector of bucket ) {
|
const simpleSelector = entry.prefix + selector;
|
||||||
if ( previousHits.has(selector) === false ) {
|
if ( previousHits.has(simpleSelector) ) { continue; }
|
||||||
complexSelectors.add(selector);
|
simpleSelectors.add(simpleSelector);
|
||||||
}
|
continue;
|
||||||
}
|
}
|
||||||
} else if ( previousHits.has(bucket) === false ) {
|
if ( Array.isArray(bucket) === false ) {
|
||||||
complexSelectors.add(bucket);
|
if ( previousHits.has(bucket) ) { continue; }
|
||||||
}
|
complexSelectors.add(bucket);
|
||||||
} else {
|
continue;
|
||||||
selector = entry.prefix + selector;
|
}
|
||||||
if ( previousHits.has(selector) === false ) {
|
for ( const selector of bucket ) {
|
||||||
simpleSelectors.add(selector);
|
if ( previousHits.has(selector) ) { continue; }
|
||||||
}
|
complexSelectors.add(selector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user