Fix reverse lookup of ##^responseheader(...) filters

Related issue:
https://github.com/uBlockOrigin/uBlock-issues/issues/3544
This commit is contained in:
Raymond Hill 2025-02-20 15:11:36 -05:00
parent 9bb1a2baaf
commit 5921e50e03
No known key found for this signature in database
GPG key ID: 25E1490B761470C2
4 changed files with 23 additions and 9 deletions

View file

@ -19,7 +19,6 @@
Home: https://github.com/gorhill/uBlock
*/
import * as sfp from './static-filtering-parser.js';
import { StaticExtFilteringHostnameDB } from './static-ext-filtering-db.js';
import { entityFromDomain } from './uri-utils.js';
import logger from './logger.js';
@ -83,8 +82,7 @@ httpheaderFilteringEngine.compile = function(parser, writer) {
writer.select('HTTPHEADER_FILTERS');
const isException = parser.isException();
const root = parser.getBranchFromType(sfp.NODE_TYPE_EXT_PATTERN_RESPONSEHEADER);
const headerName = parser.getNodeString(root);
const headerName = parser.getResponseheaderName();
// Tokenless is meaningful only for exception filters.
if ( headerName === '' && isException === false ) { return; }

View file

@ -120,7 +120,7 @@ const fromExtendedFilter = function(details) {
// The longer the needle, the lower the number of false positives.
// https://github.com/uBlockOrigin/uBlock-issues/issues/1139
// Mind that there is no guarantee a selector has `\w` characters.
const needle = selector.match(/\w+|\*/g).reduce(function(a, b) {
const needle = (details.needle || selector).match(/\w+|\*/g).reduce(function(a, b) {
return a.length > b.length ? a : b;
});
@ -213,6 +213,12 @@ const fromExtendedFilter = function(details) {
/* fallthrough */
case 64: {
if ( exception !== ((fargs[2] & 0b001) !== 0) ) { break; }
if ( /^responseheader\(.+\)$/.test(selector) ) {
if ( fargs[3] !== needle ) { break; }
if ( hostnameMatches(fargs[1]) === false ) { break; }
found = fargs[1] + prefix + selector;
break;
}
const isProcedural = (fargs[2] & 0b010) !== 0;
if (
isProcedural === false && fargs[3] !== selector ||
@ -236,11 +242,13 @@ const fromExtendedFilter = function(details) {
// Scriptlet injection
case 32:
if ( exception !== ((fargs[2] & 0b001) !== 0) ) { break; }
if ( fargs[3] !== details.compiled ) { break; }
if ( fargs[3] !== details.needle ) { break; }
if ( hostnameMatches(fargs[1]) ) {
found = fargs[1] + prefix + selector;
}
break;
default:
break;
}
if ( found !== undefined ) {
if ( response[found] === undefined ) {

View file

@ -93,7 +93,7 @@ const initWorker = function() {
};
for ( const listKey in µb.availableFilterLists ) {
if ( µb.availableFilterLists.hasOwnProperty(listKey) === false ) {
if ( Object.prototype.hasOwnProperty.call(µb.availableFilterLists, listKey) === false ) {
continue;
}
const entry = µb.availableFilterLists[listKey];
@ -167,9 +167,11 @@ const fromExtendedFilter = async function(details) {
nativeCssHas: vAPI.webextFlavor.env.includes('native_css_has'),
});
parser.parse(details.rawFilter);
let compiled;
let needle;
if ( parser.isScriptletFilter() ) {
compiled = JSON.stringify(parser.getScriptletArgs());
needle = JSON.stringify(parser.getScriptletArgs());
} else if ( parser.isResponseheaderFilter() ) {
needle = parser.getResponseheaderName();
}
worker.postMessage({
@ -188,7 +190,7 @@ const fromExtendedFilter = async function(details) {
details.url
) === 2,
rawFilter: details.rawFilter,
compiled,
needle,
});
return new Promise(resolve => {

View file

@ -2494,6 +2494,12 @@ export class AstFilterParser {
return head;
}
getResponseheaderName() {
if ( this.isResponseheaderFilter() === false ) { return ''; }
const root = this.getBranchFromType(NODE_TYPE_EXT_PATTERN_RESPONSEHEADER);
return this.getNodeString(root);
}
parseExtPatternHtml(parent) {
const beg = this.nodes[parent+NODE_BEG_INDEX];
const end = this.nodes[parent+NODE_END_INDEX];