Skip to content

Commit 219c94b

Browse files
committed
modify inside-expr
1 parent bac6d0c commit 219c94b

27 files changed

Lines changed: 452 additions & 153 deletions

docs/RuleSpec.md

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ Only these top-level keys are accepted:
6565
- `patterns` (optional for structural rules): non-empty YAML array
6666
- `patterns-not` (optional for structural rules): non-empty YAML array using
6767
the same object schema as `patterns`
68-
- `inside-expr` (optional for structural rules): YAML string containing one
69-
MoonBit expression snippet used as an outer context
68+
- `inside-expr` (optional for structural rules): YAML mapping using the same
69+
`shape` and optional `guard` schema as `patterns`, used as an outer context
7070
- `taint` (required for taint rules): YAML mapping
7171

7272
Unknown top-level keys are rejected.
@@ -88,7 +88,8 @@ including trailing newlines produced by block scalars.
8888

8989
### Pattern Objects
9090

91-
Structural entries in `patterns` and `patterns-not` use this object schema.
91+
Structural entries in `patterns`, `patterns-not`, and `inside-expr` use this
92+
object schema.
9293

9394
Only these keys are accepted:
9495

@@ -538,12 +539,15 @@ context. It may be used with `patterns`, with `patterns-not`, or with both.
538539
id: wrapped-target
539540
description: |
540541
Match a target call only inside wrapper(...).
541-
inside-expr: wrapper($(prefix:exp), __TARGET__)
542+
inside-expr:
543+
shape: wrapper($(prefix:exp), __TARGET__)
542544
patterns:
543545
- shape: target.call($(prefix:exp))
544546
```
545547

546-
`inside-expr` is a YAML string parsed as one MoonBit expression snippet.
548+
`inside-expr` is a YAML mapping. Its `shape` is parsed as one MoonBit
549+
expression snippet, and its optional `guard` filters `id` and `const` captures
550+
declared by that outer shape.
547551

548552
Additional rules:
549553

@@ -707,11 +711,11 @@ A rule set or rule file is rejected when any of these conditions occurs:
707711
- an unsupported key appears at the top level, inside `taint`, or inside a
708712
pattern object
709713
- a required key is missing
710-
- `id`, `description`, `inside-expr`, or `shape` is not a YAML string
714+
- `id`, `description`, or `shape` is not a YAML string
711715
- `id` is empty or contains `/`
712716
- the rule does not choose structural or taint mode
713717
- `inside-expr` appears on a taint rule
714-
- `inside-expr` is present but is not a string
718+
- `inside-expr` is present but is not a mapping
715719
- `inside-expr` is present without `patterns` or `patterns-not`
716720
- `patterns` is not an array or is empty
717721
- a `patterns` entry is not a mapping
@@ -790,7 +794,8 @@ positions. `start`, `limit`, and `body` are expression captures.
790794
id: unsafe-wrapper
791795
description: |
792796
Match a sink only under an unsafe wrapper.
793-
inside-expr: unsafe(__TARGET__)
797+
inside-expr:
798+
shape: unsafe(__TARGET__)
794799
patterns:
795800
- shape: sink(__)
796801
```
@@ -823,7 +828,8 @@ own `value`; it does not reuse any positive pattern capture.
823828
id: wrapper-without-danger
824829
description: |
825830
Match wrappers whose payload contains no danger call.
826-
inside-expr: wrapper(__TARGET__)
831+
inside-expr:
832+
shape: wrapper(__TARGET__)
827833
patterns-not:
828834
- shape: danger()
829835
```

docs/RuleSpec_CN.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ rules/security/nested/raw.yml with id: unsafe-html -> security/nested/unsafe-htm
5353
- `description`(必需):YAML 字符串
5454
- `patterns`(结构规则可选):非空 YAML 数组
5555
- `patterns-not`(结构规则可选):与 `patterns` 使用相同条目 schema 的非空 YAML 数组
56-
- `inside-expr`(结构规则可选):包含一个 MoonBit 表达式片段的 YAML 字符串,作为外层上下文
56+
- `inside-expr`(结构规则可选):YAML 映射,使用与 `patterns` 相同的
57+
`shape` 和可选 `guard` schema,作为外层上下文
5758
- `taint`(污点规则必需):YAML 映射
5859

5960
未知顶层键会被拒绝。
@@ -70,7 +71,7 @@ rules/security/nested/raw.yml with id: unsafe-html -> security/nested/unsafe-htm
7071

7172
### Pattern Objects
7273

73-
结构规则中的 `patterns``patterns-not` 条目使用以下对象 schema。
74+
结构规则中的 `patterns``patterns-not` 条目以及 `inside-expr` 使用以下对象 schema。
7475

7576
只接受这些键:
7677

@@ -339,7 +340,8 @@ patterns:
339340

340341
## Guard
341342

342-
结构规则的 pattern object 可以包含可选的 `guard` 映射。guard 的键是带
343+
结构规则的 pattern object(包括 `patterns`、`patterns-not` 和
344+
`inside-expr`)可以包含可选的 `guard` 映射。guard 的键是带
343345
`$` 前缀的捕获名,值是正则字符串:
344346

345347
```yaml
@@ -422,12 +424,14 @@ patterns-not:
422424
id: wrapped-target
423425
description: |
424426
Match a target call only inside wrapper(...).
425-
inside-expr: wrapper($(prefix:exp), __TARGET__)
427+
inside-expr:
428+
shape: wrapper($(prefix:exp), __TARGET__)
426429
patterns:
427430
- shape: target.call($(prefix:exp))
428431
```
429432

430-
`inside-expr` 是 YAML 字符串,会作为一个 MoonBit 表达式片段解析。
433+
`inside-expr` 是 YAML 映射。它的 `shape` 会作为一个 MoonBit 表达式片段解析;
434+
可选 `guard` 会过滤这个外层 shape 声明的 `id` 和 `const` 捕获。
431435

432436
额外规则:
433437

@@ -558,11 +562,11 @@ taint 命中报告的 pattern index 是匹配 sink 条目的零基索引。
558562
- 顶层 YAML 文档不是映射
559563
- 顶层、`taint` 内或 pattern object 内出现不支持的键
560564
- 缺少必需键
561-
- `id`、`description`、`inside-expr` 或 `shape` 不是 YAML 字符串
565+
- `id`、`description` 或 `shape` 不是 YAML 字符串
562566
- `id` 为空或包含 `/`
563567
- 规则没有选择结构模式或污点模式
564568
- taint 规则中出现 `inside-expr`
565-
- `inside-expr` 存在但不是字符串
569+
- `inside-expr` 存在但不是映射
566570
- `inside-expr` 存在但没有 `patterns` 或 `patterns-not`
567571
- `patterns` 不是数组或为空
568572
- `patterns` 条目不是映射
@@ -635,7 +639,8 @@ patterns:
635639
id: unsafe-wrapper
636640
description: |
637641
Match a sink only under an unsafe wrapper.
638-
inside-expr: unsafe(__TARGET__)
642+
inside-expr:
643+
shape: unsafe(__TARGET__)
639644
patterns:
640645
- shape: sink(__)
641646
```

docs/WritingRules.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -306,16 +306,18 @@ captures.
306306
id: wrapped-target
307307
description: |
308308
Match a call only when it appears inside a specific wrapper.
309-
inside-expr: |
310-
wrapper($(prefix:exp), __TARGET__)
309+
inside-expr:
310+
shape: |
311+
wrapper($(prefix:exp), __TARGET__)
311312
patterns:
312313
- shape: |
313314
target.call($(prefix:exp))
314315
```
315316

316317
Rules for `inside-expr`:
317318

318-
- it uses the same metavar syntax as one structural pattern
319+
- it uses the same `shape` and optional `guard` schema as one structural
320+
pattern
319321
- it must place exactly one supported `__TARGET__`; place it where a whole
320322
expression is expected so runtime traversal can search that subtree
321323
- `__TARGET__` is reserved and must not be used as an metavar name
@@ -357,7 +359,8 @@ reported only when the captured target subtree contains no forbidden shape:
357359
id: wrapper-without-danger
358360
description: |
359361
Wrapper payload contains no danger call.
360-
inside-expr: wrapper(__TARGET__)
362+
inside-expr:
363+
shape: wrapper(__TARGET__)
361364
patterns-not:
362365
- shape: danger()
363366
```
@@ -370,7 +373,8 @@ matches cover their whole matched subtrees. Any negative match outside those
370373
covered positive subtrees rejects the outer context.
371374

372375
```yaml
373-
inside-expr: wrapper($(counter:id), __TARGET__)
376+
inside-expr:
377+
shape: wrapper($(counter:id), __TARGET__)
374378
patterns:
375379
- shape: arr[$(counter:id)]
376380
patterns-not:
@@ -520,9 +524,10 @@ exact supported normalization cases in [RuleSpec.md](RuleSpec.md).
520524

521525
### A rule with `guard` fails to load
522526

523-
Check that `guard` is under a structural `patterns` or `patterns-not` entry,
524-
that it is a mapping, and that every key names an `id` or `const` capture
525-
visible to that pattern. `guard` is still rejected in taint clauses.
527+
Check that `guard` is under a structural `patterns`, `patterns-not`, or
528+
`inside-expr` pattern object, that it is a mapping, and that every key names an
529+
`id` or `const` capture visible to that pattern. `guard` is still rejected in
530+
taint clauses.
526531

527532
## Testing Workflow
528533

docs/WritingRules_CN.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -210,16 +210,17 @@ patterns:
210210
id: wrapped-target
211211
description: |
212212
Match a call only when it appears inside a specific wrapper.
213-
inside-expr: |
214-
wrapper($(prefix:exp), __TARGET__)
213+
inside-expr:
214+
shape: |
215+
wrapper($(prefix:exp), __TARGET__)
215216
patterns:
216217
- shape: |
217218
target.call($(prefix:exp))
218219
```
219220

220221
`inside-expr` 的规则:
221222

222-
- 它使用与一个结构 pattern 相同的内联元变量语法
223+
- 它使用与一个结构 pattern 相同的 `shape` 和可选 `guard` schema
223224
- 它必须放置且只放置一个支持的 `__TARGET__`;请将其放在期望完整表达式的位置,使运行时遍历可以搜索该子树
224225
- `__TARGET__` 是保留名称,不能用作内联元变量名
225226
- 内部 `patterns` 和 `patterns-not` 不能包含 `__TARGET__`;target placeholder 选择要搜索的子树,但不是内部 shape 可用的绑定
@@ -249,7 +250,8 @@ patterns-not:
249250
id: wrapper-without-danger
250251
description: |
251252
Wrapper payload contains no danger call.
252-
inside-expr: wrapper(__TARGET__)
253+
inside-expr:
254+
shape: wrapper(__TARGET__)
253255
patterns-not:
254256
- shape: danger()
255257
```
@@ -260,7 +262,8 @@ patterns-not:
260262
当 `inside-expr` 同时使用 `patterns` 和 `patterns-not` 时,正向命中的整个子树会覆盖负向匹配;任何出现在这些正向覆盖子树之外的负向命中都会拒绝外层上下文。
261263

262264
```yaml
263-
inside-expr: wrapper($(counter:id), __TARGET__)
265+
inside-expr:
266+
shape: wrapper($(counter:id), __TARGET__)
264267
patterns:
265268
- shape: arr[$(counter:id)]
266269
patterns-not:
@@ -395,9 +398,9 @@ patterns:
395398

396399
### 带 `guard` 的规则加载失败
397400

398-
请检查 `guard` 是否位于结构规则的 `patterns``patterns-not` 条目下,是否是映射,并且每个键
399-
都引用了该 pattern 可见的 `id` 或 `const` 捕获。taint 子句中仍然会拒绝
400-
`guard`
401+
请检查 `guard` 是否位于结构规则的 `patterns``patterns-not` 或 `inside-expr`
402+
pattern object 下,是否是映射,并且每个键都引用了该 pattern 可见的 `id` 或
403+
`const` 捕获。taint 子句中仍然会拒绝 `guard`。
401404

402405
## 测试工作流
403406

docs/rule_spec.mbt

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ let _embed_rulespec_md : String =
6969
#|- `patterns` (optional for structural rules): non-empty YAML array
7070
#|- `patterns-not` (optional for structural rules): non-empty YAML array using
7171
#| the same object schema as `patterns`
72-
#|- `inside-expr` (optional for structural rules): YAML string containing one
73-
#| MoonBit expression snippet used as an outer context
72+
#|- `inside-expr` (optional for structural rules): YAML mapping using the same
73+
#| `shape` and optional `guard` schema as `patterns`, used as an outer context
7474
#|- `taint` (required for taint rules): YAML mapping
7575
#|
7676
#|Unknown top-level keys are rejected.
@@ -92,7 +92,8 @@ let _embed_rulespec_md : String =
9292
#|
9393
#|### Pattern Objects
9494
#|
95-
#|Structural entries in `patterns` and `patterns-not` use this object schema.
95+
#|Structural entries in `patterns`, `patterns-not`, and `inside-expr` use this
96+
#|object schema.
9697
#|
9798
#|Only these keys are accepted:
9899
#|
@@ -542,12 +543,15 @@ let _embed_rulespec_md : String =
542543
#|id: wrapped-target
543544
#|description: |
544545
#| Match a target call only inside wrapper(...).
545-
#|inside-expr: wrapper($(prefix:exp), __TARGET__)
546+
#|inside-expr:
547+
#| shape: wrapper($(prefix:exp), __TARGET__)
546548
#|patterns:
547549
#| - shape: target.call($(prefix:exp))
548550
#|```
549551
#|
550-
#|`inside-expr` is a YAML string parsed as one MoonBit expression snippet.
552+
#|`inside-expr` is a YAML mapping. Its `shape` is parsed as one MoonBit
553+
#|expression snippet, and its optional `guard` filters `id` and `const` captures
554+
#|declared by that outer shape.
551555
#|
552556
#|Additional rules:
553557
#|
@@ -711,11 +715,11 @@ let _embed_rulespec_md : String =
711715
#|- an unsupported key appears at the top level, inside `taint`, or inside a
712716
#| pattern object
713717
#|- a required key is missing
714-
#|- `id`, `description`, `inside-expr`, or `shape` is not a YAML string
718+
#|- `id`, `description`, or `shape` is not a YAML string
715719
#|- `id` is empty or contains `/`
716720
#|- the rule does not choose structural or taint mode
717721
#|- `inside-expr` appears on a taint rule
718-
#|- `inside-expr` is present but is not a string
722+
#|- `inside-expr` is present but is not a mapping
719723
#|- `inside-expr` is present without `patterns` or `patterns-not`
720724
#|- `patterns` is not an array or is empty
721725
#|- a `patterns` entry is not a mapping
@@ -794,7 +798,8 @@ let _embed_rulespec_md : String =
794798
#|id: unsafe-wrapper
795799
#|description: |
796800
#| Match a sink only under an unsafe wrapper.
797-
#|inside-expr: unsafe(__TARGET__)
801+
#|inside-expr:
802+
#| shape: unsafe(__TARGET__)
798803
#|patterns:
799804
#| - shape: sink(__)
800805
#|```
@@ -827,7 +832,8 @@ let _embed_rulespec_md : String =
827832
#|id: wrapper-without-danger
828833
#|description: |
829834
#| Match wrappers whose payload contains no danger call.
830-
#|inside-expr: wrapper(__TARGET__)
835+
#|inside-expr:
836+
#| shape: wrapper(__TARGET__)
831837
#|patterns-not:
832838
#| - shape: danger()
833839
#|```

docs/writing_rules.mbt

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -310,16 +310,18 @@ let _embed_writingrules_md : String =
310310
#|id: wrapped-target
311311
#|description: |
312312
#| Match a call only when it appears inside a specific wrapper.
313-
#|inside-expr: |
314-
#| wrapper($(prefix:exp), __TARGET__)
313+
#|inside-expr:
314+
#| shape: |
315+
#| wrapper($(prefix:exp), __TARGET__)
315316
#|patterns:
316317
#| - shape: |
317318
#| target.call($(prefix:exp))
318319
#|```
319320
#|
320321
#|Rules for `inside-expr`:
321322
#|
322-
#|- it uses the same metavar syntax as one structural pattern
323+
#|- it uses the same `shape` and optional `guard` schema as one structural
324+
#| pattern
323325
#|- it must place exactly one supported `__TARGET__`; place it where a whole
324326
#| expression is expected so runtime traversal can search that subtree
325327
#|- `__TARGET__` is reserved and must not be used as an metavar name
@@ -361,7 +363,8 @@ let _embed_writingrules_md : String =
361363
#|id: wrapper-without-danger
362364
#|description: |
363365
#| Wrapper payload contains no danger call.
364-
#|inside-expr: wrapper(__TARGET__)
366+
#|inside-expr:
367+
#| shape: wrapper(__TARGET__)
365368
#|patterns-not:
366369
#| - shape: danger()
367370
#|```
@@ -374,7 +377,8 @@ let _embed_writingrules_md : String =
374377
#|covered positive subtrees rejects the outer context.
375378
#|
376379
#|```yaml
377-
#|inside-expr: wrapper($(counter:id), __TARGET__)
380+
#|inside-expr:
381+
#| shape: wrapper($(counter:id), __TARGET__)
378382
#|patterns:
379383
#| - shape: arr[$(counter:id)]
380384
#|patterns-not:
@@ -524,9 +528,10 @@ let _embed_writingrules_md : String =
524528
#|
525529
#|### A rule with `guard` fails to load
526530
#|
527-
#|Check that `guard` is under a structural `patterns` or `patterns-not` entry,
528-
#|that it is a mapping, and that every key names an `id` or `const` capture
529-
#|visible to that pattern. `guard` is still rejected in taint clauses.
531+
#|Check that `guard` is under a structural `patterns`, `patterns-not`, or
532+
#|`inside-expr` pattern object, that it is a mapping, and that every key names an
533+
#|`id` or `const` capture visible to that pattern. `guard` is still rejected in
534+
#|taint clauses.
530535
#|
531536
#|## Testing Workflow
532537
#|

0 commit comments

Comments
 (0)