Skip to content

Commit

Permalink
[mv3] Ensure no generic cosmetic filters end up in specific realm
Browse files Browse the repository at this point in the history
Related issue:
uBlockOrigin/uBOL-home#254

Cosmetic filters with only negated hostnames would end up being
classified as specific, while in reality the filter is generic, with
specific exceptions.

This commit fixes the improper classification. Enforcing specific
exception filters in the generic realm is still an issue to
address.
  • Loading branch information
gorhill committed Dec 8, 2024
1 parent ec5a1b3 commit 56ba937
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 55 deletions.
13 changes: 2 additions & 11 deletions platform/mv3/make-rulesets.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,6 @@ const uidint32 = (s) => {
return parseInt(h,16) & 0x7FFFFFFF;
};

const hnSort = (a, b) =>
a.split('.').reverse().join('.').localeCompare(
b.split('.').reverse().join('.')
);

/******************************************************************************/

const stdOutput = [];
Expand Down Expand Up @@ -681,14 +676,10 @@ function groupHostnamesBySelectors(arrayin) {
const out = Array.from(contentMap).map(a => [
a[0], {
a: a[1].a,
y: a[1].y ? Array.from(a[1].y).sort(hnSort) : '*',
y: a[1].y ? Array.from(a[1].y) : undefined,
n: a[1].n ? Array.from(a[1].n) : undefined,
}
]).sort((a, b) => {
const ha = Array.isArray(a[1].y) ? a[1].y[0] : '*';
const hb = Array.isArray(b[1].y) ? b[1].y[0] : '*';
return hnSort(ha, hb);
});
]);
return out;
}

Expand Down
97 changes: 53 additions & 44 deletions src/js/static-dnr-filtering.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,39 @@ const keyFromSelector = selector => {

/******************************************************************************/

function addGenericCosmeticFilter(context, selector, isException) {
if ( selector === undefined ) { return; }
if ( selector.length <= 1 ) { return; }
if ( isException ) {
if ( context.genericCosmeticExceptions === undefined ) {
context.genericCosmeticExceptions = new Set();
}
context.genericCosmeticExceptions.add(selector);
return;
}
if ( selector.charCodeAt(0) === 0x7B /* '{' */ ) { return; }
const key = keyFromSelector(selector);
if ( key === undefined ) {
if ( context.genericHighCosmeticFilters === undefined ) {
context.genericHighCosmeticFilters = new Set();
}
context.genericHighCosmeticFilters.add(selector);
return;
}
const type = key.charCodeAt(0);
const hash = hashFromStr(type, key.slice(1));
if ( context.genericCosmeticFilters === undefined ) {
context.genericCosmeticFilters = new Map();
}
let bucket = context.genericCosmeticFilters.get(hash);
if ( bucket === undefined ) {
context.genericCosmeticFilters.set(hash, bucket = []);
}
bucket.push(selector);
}

/******************************************************************************/

function addExtendedToDNR(context, parser) {
if ( parser.isExtendedFilter() === false ) { return false; }

Expand Down Expand Up @@ -195,35 +228,8 @@ function addExtendedToDNR(context, parser) {

// Generic cosmetic filtering
if ( parser.hasOptions() === false ) {
const { compiled } = parser.result;
if ( compiled === undefined ) { return; }
if ( compiled.length <= 1 ) { return; }
if ( parser.isException() ) {
if ( context.genericCosmeticExceptions === undefined ) {
context.genericCosmeticExceptions = new Set();
}
context.genericCosmeticExceptions.add(compiled);
return;
}
if ( compiled.charCodeAt(0) === 0x7B /* '{' */ ) { return; }
const key = keyFromSelector(compiled);
if ( key === undefined ) {
if ( context.genericHighCosmeticFilters === undefined ) {
context.genericHighCosmeticFilters = new Set();
}
context.genericHighCosmeticFilters.add(compiled);
return;
}
const type = key.charCodeAt(0);
const hash = hashFromStr(type, key.slice(1));
if ( context.genericCosmeticFilters === undefined ) {
context.genericCosmeticFilters = new Map();
}
let bucket = context.genericCosmeticFilters.get(hash);
if ( bucket === undefined ) {
context.genericCosmeticFilters.set(hash, bucket = []);
}
bucket.push(compiled);
const { compiled, exception } = parser.result;
addGenericCosmeticFilter(context, compiled, exception);
return;
}

Expand All @@ -234,26 +240,22 @@ function addExtendedToDNR(context, parser) {
if ( context.specificCosmeticFilters === undefined ) {
context.specificCosmeticFilters = new Map();
}
const { compiled, exception, raw } = parser.result;
if ( compiled === undefined ) {
context.specificCosmeticFilters.set(`Invalid filter: ...##${raw}`, {
rejected: true
});
return;
}
let details = context.specificCosmeticFilters.get(compiled);
for ( const { hn, not, bad } of parser.getExtFilterDomainIterator() ) {
if ( bad ) { continue; }
if ( not && exception ) { continue; }
if ( isRegex(hn) ) { continue; }
let { compiled, exception, raw } = parser.result;
if ( exception ) { continue; }
let rejected;
if ( compiled === undefined ) {
rejected = `Invalid filter: ${hn}##${raw}`;
}
if ( rejected ) {
compiled = rejected;
}
let details = context.specificCosmeticFilters.get(compiled);
if ( details === undefined ) {
details = {};
if ( rejected ) { details.rejected = true; }
context.specificCosmeticFilters.set(compiled, details);
context.specificCosmeticFilters.set(compiled, details = {});
}
if ( rejected ) { continue; }
if ( not ) {
if ( exception ) {
if ( details.excludeMatches === undefined ) {
details.excludeMatches = [];
}
Expand All @@ -270,6 +272,13 @@ function addExtendedToDNR(context, parser) {
}
details.matches.push(hn);
}
if ( details === undefined ) { return; }
if ( exception ) { return; }
if ( compiled.startsWith('{') ) { return; }
if ( details.matches === undefined || details.matches.includes('*') ) {
addGenericCosmeticFilter(context, compiled, false);
details.matches = undefined;
}
}

/******************************************************************************/
Expand Down

0 comments on commit 56ba937

Please sign in to comment.