Skip to content

Commit a9ac642

Browse files
committed
AG-24716: fixed checking for unsupported options
Merge in ADGUARD-FILTERS/tsurlfilter from fix/AG-24716 to master Squashed commit of the following: commit dda7cd6 Author: Dmitriy Seregin <[email protected]> Date: Fri Aug 11 17:28:06 2023 +0400 fix comment commit e607edc Author: Dmitriy Seregin <[email protected]> Date: Fri Aug 11 17:16:53 2023 +0400 cleaned diff commit 0969a36 Merge: fe3edfe 98a99db Author: Dmitriy Seregin <[email protected]> Date: Fri Aug 11 17:16:11 2023 +0400 Merge branch 'master' into fix/AG-24716 commit fe3edfe Author: Dmitriy Seregin <[email protected]> Date: Wed Aug 9 18:31:07 2023 +0400 AG-24716: fixed checking for unsupported options
1 parent 98a99db commit a9ac642

File tree

5 files changed

+99
-51
lines changed

5 files changed

+99
-51
lines changed

packages/tsurlfilter/src/rules/declarative-converter/README.md

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ into `$elemhide,content,urlblock,jsinject` of which:
8888
- `$jsinject` - not implemented yet,
8989
- `$urlblock` - not implemented yet.
9090

91-
So we still convert rules with `$document`, but not 100% correctly.
91+
So we still convert rules with `$document`, but only part with `$elemhide`
92+
will be applied.
9293

9394
<a name="mv3_specific_limitations__$removeparam__$removeheader__$csp"></a>
9495
## $removeparam, $removeheader, $csp
@@ -2426,20 +2427,7 @@ example 10
24262427
↓↓↓↓ converted to ↓↓↓↓
24272428

24282429
```json
2429-
[
2430-
{
2431-
"id": 1,
2432-
"action": {
2433-
"type": "block"
2434-
},
2435-
"condition": {
2436-
"urlFilter": "||facebook.com^",
2437-
"domainType": "thirdParty",
2438-
"isUrlFilterCaseSensitive": false
2439-
},
2440-
"priority": 2
2441-
}
2442-
]
2430+
[]
24432431

24442432
```
24452433
<a name="advanced_capabilities__$csp"></a>

packages/tsurlfilter/src/rules/declarative-converter/grouped-rules-converters/abstract-rule-converter.ts

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -664,8 +664,8 @@ export abstract class DeclarativeRuleConverter {
664664
const checkRemoveParamModifierFn = (r: NetworkRule, name: string): UnsupportedModifierError | null => {
665665
const removeParam = r.getAdvancedModifier() as RemoveParamModifier;
666666
if (!removeParam.getMV3Validity()) {
667-
const msg = 'Network rule with $removeparam modifier with '
668-
+ `negation or regexp is not supported: "${r.getText()}"`;
667+
// eslint-disable-next-line max-len
668+
const msg = `Network rule with $removeparam modifier with negation or regexp is not supported: "${r.getText()}"`;
669669

670670
return new UnsupportedModifierError(msg, r);
671671
}
@@ -750,7 +750,6 @@ export abstract class DeclarativeRuleConverter {
750750
|| restrictedMethods?.some((method) => method === HTTPMethod.TRACE)
751751
) {
752752
return new UnsupportedModifierError(
753-
// eslint-disable-next-line max-len
754753
`Network rule with $method modifier containing 'trace' method is not supported: "${r.getText()}"`,
755754
r,
756755
);
@@ -759,15 +758,55 @@ export abstract class DeclarativeRuleConverter {
759758
return null;
760759
};
761760

761+
/**
762+
* Checks if rule is a "document"-allowlist and contains all these
763+
* `$elemhide,content,urlblock,jsinject` modifiers at the same time.
764+
* If it is - we allow partially convert this rule, because `$content`
765+
* is not supported in the MV3 at all and `$jsinject` and `$urlblock`
766+
* are not implemented yet, but we can support at least allowlist-rule
767+
* with `$elemhide` modifier (not in the DNR, but with tsurlfilter engine).
768+
*
769+
* TODO: Change the description when `$jsinject` and `$urlblock`
770+
* are implemented.
771+
*
772+
* @param r Network rule.
773+
* @param name Modifier's name.
774+
*
775+
* @returns Error {@link UnsupportedModifierError} or null if rule is supported.
776+
*/
777+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
778+
const checkDocumentAllowlistFn = (r: NetworkRule, name: string): UnsupportedModifierError | null => {
779+
if (rule.isFilteringDisabled()) {
780+
return null;
781+
}
782+
783+
return new UnsupportedModifierError(
784+
`Network rule with "${name}" modifier is not supported: "${r.getText()}"`,
785+
r,
786+
);
787+
};
788+
762789
const unsupportedOptions = [
763790
/* Specific exceptions */
764791
{ option: NetworkRuleOption.Elemhide, name: '$elemhide', skipConversion: true },
765792
{ option: NetworkRuleOption.Generichide, name: '$generichide', skipConversion: true },
766793
{ option: NetworkRuleOption.Specifichide, name: '$specifichide', skipConversion: true },
767794
{ option: NetworkRuleOption.Genericblock, name: '$genericblock' },
768-
{ option: NetworkRuleOption.Jsinject, name: '$jsinject' },
769-
{ option: NetworkRuleOption.Urlblock, name: '$urlblock' },
770-
{ option: NetworkRuleOption.Content, name: '$content' },
795+
{
796+
option: NetworkRuleOption.Jsinject,
797+
name: '$jsinject',
798+
customChecks: [checkDocumentAllowlistFn],
799+
},
800+
{
801+
option: NetworkRuleOption.Urlblock,
802+
name: '$urlblock',
803+
customChecks: [checkDocumentAllowlistFn],
804+
},
805+
{
806+
option: NetworkRuleOption.Content,
807+
name: '$content',
808+
customChecks: [checkDocumentAllowlistFn],
809+
},
771810
{ option: NetworkRuleOption.Extension, name: '$extension' },
772811
{ option: NetworkRuleOption.Stealth, name: '$stealth' },
773812
/* Specific exceptions */
@@ -815,12 +854,15 @@ export abstract class DeclarativeRuleConverter {
815854
skipConversion,
816855
} = unsupportedOptions[i];
817856

818-
if (!rule.isSingleOptionEnabled(option)) {
857+
if (!rule.isOptionEnabled(option)) {
819858
continue;
820859
}
821860

822861
if (skipConversion) {
823-
return false;
862+
if (rule.isSingleOptionEnabled(option)) {
863+
return false;
864+
}
865+
continue;
824866
}
825867

826868
if (customChecks) {

packages/tsurlfilter/src/rules/declarative-converter/readme.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
! - `$jsinject` - not implemented yet,
2424
! - `$urlblock` - not implemented yet.
2525
!
26-
! So we still convert rules with `$document`, but not 100% correctly.
26+
! So we still convert rules with `$document`, but only part with `$elemhide`
27+
! will be applied.
2728
!
2829
! ## $removeparam, $removeheader, $csp
2930
! Rules with `$removeparam` or `$removeheader` or `$csp` which contains the same

packages/tsurlfilter/test/rules/declarative-converter/declarative-converter.test.ts

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -485,8 +485,8 @@ describe('DeclarativeConverter', () => {
485485

486486
// eslint-disable-next-line max-len
487487
const err = new Error('"Unknown modifier: webrtc" in the rule: "@@$webrtc,domain=example.com"');
488-
expect(declarativeRules.length).toBe(0);
489-
expect(errors.length).toBe(1);
488+
expect(declarativeRules).toHaveLength(0);
489+
expect(errors).toHaveLength(1);
490490
expect(errors[0]).toStrictEqual(err);
491491
});
492492

@@ -507,8 +507,8 @@ describe('DeclarativeConverter', () => {
507507
networkRule,
508508
);
509509

510-
expect(declarativeRules.length).toBe(0);
511-
expect(errors.length).toBe(1);
510+
expect(declarativeRules).toHaveLength(0);
511+
expect(errors).toHaveLength(1);
512512
expect(errors[0]).toStrictEqual(err);
513513
});
514514

@@ -523,24 +523,41 @@ describe('DeclarativeConverter', () => {
523523
// eslint-disable-next-line max-len
524524
const err = new Error('"modifier $to is not compatible with $denyallow modifier" in the rule: "/ads$to=good.org,denyallow=good.com"');
525525

526-
expect(declarativeRules.length).toBe(0);
527-
expect(errors.length).toBe(1);
526+
expect(declarativeRules).toHaveLength(0);
527+
expect(errors).toHaveLength(1);
528528

529-
console.log('errors: ', errors);
530529
expect(errors[0]).toStrictEqual(err);
531530
});
532531
});
533532

534-
it('use only main_frame or sub_frame for allowAllRequests rules', async () => {
535-
const rule = '@@||example.com/*/search?*&method=HEAD$xmlhttprequest,document';
536-
const filter = createFilter([rule]);
537-
const { ruleSets: [ruleSet] } = await converter.convert(
538-
[filter],
539-
);
533+
describe('test some edge cases', () => {
534+
it('use only main_frame or sub_frame for allowAllRequests rules', async () => {
535+
const rule = '@@||example.com/*/search?*&method=HEAD$xmlhttprequest,document';
536+
const filter = createFilter([rule]);
537+
const { ruleSets: [ruleSet] } = await converter.convert(
538+
[filter],
539+
);
540540

541-
const { declarativeRules } = await ruleSet.serialize();
541+
const { declarativeRules } = await ruleSet.serialize();
542542

543-
expect(declarativeRules).toHaveLength(1);
544-
expect(declarativeRules[0].action.type).not.toContain(RuleActionType.ALLOW_ALL_REQUESTS);
543+
expect(declarativeRules).toHaveLength(1);
544+
expect(declarativeRules[0].action.type).not.toContain(RuleActionType.ALLOW_ALL_REQUESTS);
545+
});
546+
547+
it('test allowlist rule with $document, $csp and $domain', async () => {
548+
const filter = createFilter([
549+
'@@*$document,csp=worker-src \'none\',domain=new.lewd.ninja',
550+
]);
551+
const {
552+
ruleSets: [ruleSet],
553+
errors,
554+
} = await converter.convert(
555+
[filter],
556+
);
557+
const { declarativeRules } = await ruleSet.serialize();
558+
559+
expect(errors).toHaveLength(1);
560+
expect(declarativeRules).toHaveLength(0);
561+
});
545562
});
546563
});

packages/tsurlfilter/test/rules/declarative-converter/declarative-rule-converter.test.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,7 +1227,7 @@ describe('DeclarativeRuleConverter', () => {
12271227
} = DeclarativeRulesConverter.convert(
12281228
[[filterId, rules]],
12291229
);
1230-
expect(declarativeRules.length).toBe(1);
1230+
expect(declarativeRules).toHaveLength(1);
12311231
expect(declarativeRules[0]).toEqual({
12321232
id: 1,
12331233
priority: 1,
@@ -1262,7 +1262,7 @@ describe('DeclarativeRuleConverter', () => {
12621262
const { declarativeRules } = DeclarativeRulesConverter.convert(
12631263
[[filterId, rules]],
12641264
);
1265-
expect(declarativeRules.length).toBe(3);
1265+
expect(declarativeRules).toHaveLength(3);
12661266
expect(declarativeRules[0]).toStrictEqual({
12671267
id: 1,
12681268
priority: 1,
@@ -1350,7 +1350,7 @@ describe('DeclarativeRuleConverter', () => {
13501350
} = DeclarativeRulesConverter.convert(
13511351
[[filterId, rules]],
13521352
);
1353-
expect(declarativeRules.length).toBe(1);
1353+
expect(declarativeRules).toHaveLength(1);
13541354
expect(declarativeRules[0]).toEqual({
13551355
id: 1,
13561356
priority: 2,
@@ -1381,7 +1381,7 @@ describe('DeclarativeRuleConverter', () => {
13811381
} = DeclarativeRulesConverter.convert(
13821382
[[filterId, rules]],
13831383
);
1384-
expect(declarativeRules.length).toBe(1);
1384+
expect(declarativeRules).toHaveLength(1);
13851385
expect(declarativeRules[0]).toEqual({
13861386
id: 1,
13871387
priority: 2,
@@ -1410,7 +1410,7 @@ describe('DeclarativeRuleConverter', () => {
14101410
} = DeclarativeRulesConverter.convert(
14111411
[[filterId, rules]],
14121412
);
1413-
expect(declarativeRules.length).toBe(1);
1413+
expect(declarativeRules).toHaveLength(1);
14141414
expect(declarativeRules[0]).toEqual({
14151415
id: 1,
14161416
priority: 2,
@@ -1443,7 +1443,7 @@ describe('DeclarativeRuleConverter', () => {
14431443
} = DeclarativeRulesConverter.convert(
14441444
[[filterId, rules]],
14451445
);
1446-
expect(declarativeRules.length).toBe(1);
1446+
expect(declarativeRules).toHaveLength(1);
14471447
expect(declarativeRules[0]).toEqual({
14481448
id: 1,
14491449
priority: 76,
@@ -1471,7 +1471,7 @@ describe('DeclarativeRuleConverter', () => {
14711471
} = DeclarativeRulesConverter.convert(
14721472
[[filterId, rules]],
14731473
);
1474-
expect(declarativeRules.length).toBe(1);
1474+
expect(declarativeRules).toHaveLength(1);
14751475
expect(declarativeRules[0]).toEqual({
14761476
id: 1,
14771477
priority: 2,
@@ -1499,7 +1499,7 @@ describe('DeclarativeRuleConverter', () => {
14991499
} = DeclarativeRulesConverter.convert(
15001500
[[filterId, rules]],
15011501
);
1502-
expect(declarativeRules.length).toBe(1);
1502+
expect(declarativeRules).toHaveLength(1);
15031503
expect(declarativeRules[0]).toEqual({
15041504
id: 1,
15051505
priority: 100101,
@@ -1527,7 +1527,7 @@ describe('DeclarativeRuleConverter', () => {
15271527
} = DeclarativeRulesConverter.convert(
15281528
[[filterId, rules]],
15291529
);
1530-
expect(declarativeRules.length).toBe(1);
1530+
expect(declarativeRules).toHaveLength(1);
15311531
expect(declarativeRules[0]).toEqual({
15321532
id: 1,
15331533
priority: 100002,
@@ -1554,8 +1554,8 @@ describe('DeclarativeRuleConverter', () => {
15541554
} = DeclarativeRulesConverter.convert(
15551555
[[filterId, rules]],
15561556
);
1557-
expect(declarativeRules.length).toBe(0);
1558-
expect(errors.length).toBe(1);
1557+
expect(declarativeRules).toHaveLength(0);
1558+
expect(errors).toHaveLength(1);
15591559

15601560
const networkRule = new NetworkRule(ruleText, filterId);
15611561

0 commit comments

Comments
 (0)