From ec19e352b18ce8fc0ff5e9aaadd1d651a9ef9cd1 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Wed, 16 Apr 2025 08:19:52 -0400 Subject: [PATCH] [mv3] Mitigate issues when hitting regex-based rules limit When there are too many regex-based rules, uBOL will start to drop some strict-block rules to comply with the framework limit regarding the maximum number of regex-based rules. Related issues: - https://github.com/uBlockOrigin/uBOL-home/issues/317 - https://github.com/w3c/webextensions/issues/744 --- platform/mv3/extension/js/ruleset-manager.js | 38 ++++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/platform/mv3/extension/js/ruleset-manager.js b/platform/mv3/extension/js/ruleset-manager.js index 4dbc7f1e1..add3c5e25 100644 --- a/platform/mv3/extension/js/ruleset-manager.js +++ b/platform/mv3/extension/js/ruleset-manager.js @@ -43,6 +43,9 @@ import { ubolLog } from './debug.js'; const TRUSTED_DIRECTIVE_BASE_RULE_ID = 8000000; const STRICTBLOCK_PRIORITY = 29; +let dynamicRegexCount = 0; +let sessionRegexCount = 0; + /******************************************************************************/ const isStrictBlockRule = rule => { @@ -280,16 +283,15 @@ async function updateDynamicRules() { ]); if ( addRules.length === 0 && removeRuleIds.length === 0 ) { return; } - const maxRegexRuleCount = dnr.MAX_NUMBER_OF_REGEX_RULES; - let regexRuleCount = 0; + dynamicRegexCount = 0; let ruleId = 1; for ( const rule of addRules ) { - if ( rule?.condition.regexFilter ) { regexRuleCount += 1; } + if ( rule?.condition.regexFilter ) { dynamicRegexCount += 1; } if ( (rule.id || 0) >= TRUSTED_DIRECTIVE_BASE_RULE_ID ) { continue; } rule.id = ruleId++; } - if ( regexRuleCount !== 0 ) { - ubolLog(`Using ${regexRuleCount}/${maxRegexRuleCount} dynamic regex-based DNR rules`); + if ( dynamicRegexCount !== 0 ) { + ubolLog(`Using ${dynamicRegexCount}/${dnr.MAX_NUMBER_OF_REGEX_RULES} dynamic regex-based DNR rules`); } return Promise.all([ dnr.updateDynamicRules({ addRules, removeRuleIds }).then(( ) => { @@ -402,20 +404,26 @@ async function setStrictBlockMode(state) { /******************************************************************************/ async function updateSessionRules() { - const addRules = []; + const addRulesUnfiltered = []; const removeRuleIds = []; const currentRules = await dnr.getSessionRules(); - await updateStrictBlockRules(currentRules, addRules, removeRuleIds); - if ( addRules.length === 0 && removeRuleIds.length === 0 ) { return; } - const maxRegexRuleCount = dnr.MAX_NUMBER_OF_REGEX_RULES; - let regexRuleCount = 0; + await updateStrictBlockRules(currentRules, addRulesUnfiltered, removeRuleIds); + if ( addRulesUnfiltered.length === 0 && removeRuleIds.length === 0 ) { return; } + const maxRegexCount = dnr.MAX_NUMBER_OF_REGEX_RULES * 0.95; + let regexCount = dynamicRegexCount; let ruleId = 1; - for ( const rule of addRules ) { - if ( rule?.condition.regexFilter ) { regexRuleCount += 1; } - rule.id = ruleId++; + for ( const rule of addRulesUnfiltered ) { + if ( rule?.condition.regexFilter ) { regexCount += 1; } + rule.id = regexCount < maxRegexCount ? ruleId++ : 0; } - if ( regexRuleCount !== 0 ) { - ubolLog(`Using ${regexRuleCount}/${maxRegexRuleCount} session regex-based DNR rules`); + sessionRegexCount = regexCount - dynamicRegexCount; + const addRules = addRulesUnfiltered.filter(a => a.id !== 0); + const rejectedRuleCount = addRulesUnfiltered.length - addRules.length; + if ( rejectedRuleCount !== 0 ) { + ubolLog(`Too many regex-based filters, ${rejectedRuleCount} session rules dropped`); + } + if ( sessionRegexCount !== 0 ) { + ubolLog(`Using ${sessionRegexCount}/${dnr.MAX_NUMBER_OF_REGEX_RULES} session regex-based DNR rules`); } return dnr.updateSessionRules({ addRules, removeRuleIds }).then(( ) => { if ( removeRuleIds.length !== 0 ) {