@@ -11,9 +11,6 @@ using @model {
1111///|
1212using @taint_lowering {lower_compiled_taint_rule}
1313
14- ///|
15- using @traverse {type ScopedExpr }
16-
1714///|
1815priv enum RuleTraversalAction {
1916 RuleContinue
@@ -37,38 +34,32 @@ priv struct AstStructuralRuleEntry {
3734}
3835
3936///|
40- /// Applies only structural rules to the supplied parser AST nodes .
37+ /// Applies only structural rules to the supplied untyped AST root .
4138///
42- /// Supported expression subtrees collected by `collect_impl_exprs` and
43- /// `collect_exprs` are visited in source-tree order. For a single expression
44- /// and rule, the first matching pattern wins and determines `pattern_index`.
39+ /// Supported expression subtrees are visited in source-tree order. For a
40+ /// single expression and rule, the first matching pattern wins and determines
41+ /// `pattern_index`.
4542pub fn apply_structural_rules(
4643 file : String ,
47- impls : @list. List [@syntax. Impl ] ,
44+ root_node : @untyped_ast. Node ,
4845 rules : Array [CompiledRule ],
4946) -> Array [RuleFinding ] {
50- let hits : Array [RuleFinding ] = []
51- for node in impls {
52- let node_hits = apply_structural_rules_to_impl(file, node, rules)
53- for hit in node_hits {
54- hits.push(hit)
55- }
56- }
57- hits
47+ apply_structural_rules_to_node(file, root_node, rules)
5848}
5949
6050///|
61- pub fn apply_structural_rules_to_impl (
51+ pub fn apply_structural_rules_to_node (
6252 file : String ,
63- node : @syntax. Impl ,
53+ node : @untyped_ast. Node ,
6454 rules : Array [CompiledRule ],
6555) -> Array [RuleFinding ] {
6656 let hits : Array [RuleFinding ] = []
6757 let entries = ast_structural_rule_entries(rules)
68- @traverse.visit_impl_scoped_expr_roots (node, fn(scoped_expr) {
58+ @untyped_ast.visit_node_scoped_expr_roots (node, fn(scoped_expr) {
6959 apply_ast_structural_rule_entries_to_scoped_expr(
7060 file, entries, scoped_expr, hits,
7161 )
62+ @untyped_ast.NodeVisitAction ::NodeVisitPrune
7263 })
7364 hits
7465}
@@ -108,7 +99,7 @@ fn ast_structural_rule_entries(
10899fn apply_ast_structural_rule_entries_to_scoped_expr(
109100 file : String ,
110101 entries : Array [AstStructuralRuleEntry ],
111- scoped_expr : ScopedExpr ,
102+ scoped_expr : @untyped_ast. ScopedNodeExpr ,
112103 hits : Array [RuleFinding ],
113104) -> Unit {
114105 let child_entries : Array [AstStructuralRuleEntry ] = []
@@ -124,18 +115,22 @@ fn apply_ast_structural_rule_entries_to_scoped_expr(
124115 if child_entries.length() == 0 {
125116 return
126117 }
127- @traverse.visit_scoped_expr_children(scoped_expr, fn(child) {
128- apply_ast_structural_rule_entries_to_scoped_expr(
129- file, child_entries, child, hits,
130- )
131- })
118+ @untyped_ast.visit_node_scoped_expr_children(
119+ scoped_expr.expr,
120+ scoped_expr.shadowed_names,
121+ fn(child) {
122+ apply_ast_structural_rule_entries_to_scoped_expr(
123+ file, child_entries, child, hits,
124+ )
125+ },
126+ )
132127}
133128
134129///|
135130fn apply_ast_structural_rule_entry_to_scoped_expr(
136131 file : String ,
137132 entry : AstStructuralRuleEntry ,
138- scoped_expr : ScopedExpr ,
133+ scoped_expr : @untyped_ast. ScopedNodeExpr ,
139134 hits : Array [RuleFinding ],
140135) -> RuleTraversalAction {
141136 if entry.structural.inside_expr is Some (inside) {
@@ -152,7 +147,7 @@ fn apply_ast_structural_rule_entry_to_scoped_expr(
152147 )
153148 RuleContinue
154149 } else {
155- apply_ast_patterns_at_expr (
150+ apply_ast_patterns_at_node (
156151 file,
157152 entry.rule,
158153 entry.pattern_buckets,
@@ -166,18 +161,26 @@ fn apply_ast_structural_rule_entry_to_scoped_expr(
166161}
167162
168163///|
169- /// Applies only taint rules to function-like parser AST nodes.
164+ /// Applies only taint rules to function-like untyped AST nodes.
170165///
171166/// Unsupported top-level nodes are ignored. Other taint-analysis errors are
172167/// propagated to the caller.
173168pub fn apply_taint_rules(
174169 file : String ,
175- impls : @list. List [@syntax. Impl ] ,
170+ root_node : @untyped_ast. Node ,
176171 rules : Array [CompiledRule ],
177172) -> Array [RuleFinding ] raise {
178173 let hits : Array [RuleFinding ] = []
179- for node in impls {
180- let node_hits = apply_taint_rules_to_impl(file, node, rules)
174+ if root_node.kind == @untyped_ast.NodeKind ::ImplList {
175+ for entry in root_node.children {
176+ let (_, node) = entry
177+ let node_hits = apply_taint_rules_to_node(file, node, rules)
178+ for hit in node_hits {
179+ hits.push(hit)
180+ }
181+ }
182+ } else {
183+ let node_hits = apply_taint_rules_to_node(file, root_node, rules)
181184 for hit in node_hits {
182185 hits.push(hit)
183186 }
@@ -186,25 +189,24 @@ pub fn apply_taint_rules(
186189}
187190
188191///|
189- pub fn apply_taint_rules_to_impl (
192+ pub fn apply_taint_rules_to_node (
190193 file : String ,
191- node : @syntax. Impl ,
194+ node : @untyped_ast. Node ,
192195 rules : Array [CompiledRule ],
193196) -> Array [RuleFinding ] raise {
194197 let hits : Array [RuleFinding ] = []
195- let untyped_node = @untyped_ast.from_impl(node)
196198 for rule in rules {
197199 match rule.definition {
198200 Taint (taint_rule) =>
199- apply_taint_rule_to_impl (file, rule, taint_rule, untyped_node , hits)
201+ apply_taint_rule_to_node (file, rule, taint_rule, node , hits)
200202 _ => ()
201203 }
202204 }
203205 hits
204206}
205207
206208///|
207- fn apply_taint_rule_to_impl (
209+ fn apply_taint_rule_to_node (
208210 file : String ,
209211 rule : CompiledRule ,
210212 taint_rule : CompiledTaintRule ,
@@ -249,13 +251,13 @@ fn apply_inside_expr_ast_bucketed(
249251 inside_root_key : @untyped_ast.NodeKind? ,
250252 pattern_buckets : ExprPatternBuckets ,
251253 negative_pattern_buckets : ExprPatternBuckets ,
252- expr : @syntax. Expr ,
254+ expr : @untyped_ast. Node ,
253255 hits : Array [RuleFinding ],
254256) -> Unit {
255- if !ast_bucket_root_key_matches (inside_root_key, expr) {
257+ if !node_root_key_matches (inside_root_key, expr) {
256258 return
257259 }
258- if match_ast_rule_pattern (inside, expr, None ) is Some (result) {
260+ if match_node_rule_pattern (inside, expr, None ) is Some (result) {
259261 if result.bindings.get("__TARGET__ ") is Some (target) {
260262 if structural.patterns.is_empty() {
261263 let target_exprs : Array [@untyped_ast.ScopedNodeExpr ] = []
@@ -265,7 +267,7 @@ fn apply_inside_expr_ast_bucketed(
265267 rule,
266268 negative_pattern_buckets,
267269 target_exprs,
268- expr.loc() ,
270+ expr.loc,
269271 result.bindings,
270272 inside.compiled.identifier_metavars,
271273 hits,
@@ -279,7 +281,7 @@ fn apply_inside_expr_ast_bucketed(
279281 pattern_buckets,
280282 negative_pattern_buckets,
281283 target,
282- Some (expr.loc() ),
284+ Some (expr.loc),
283285 result.bindings,
284286 inside.compiled.identifier_metavars,
285287 hits,
@@ -291,7 +293,7 @@ fn apply_inside_expr_ast_bucketed(
291293 pattern_buckets,
292294 negative_pattern_buckets,
293295 target,
294- Some (expr.loc() ),
296+ Some (expr.loc),
295297 result.bindings,
296298 inside.compiled.identifier_metavars,
297299 hits,
@@ -492,31 +494,31 @@ fn apply_ast_bucketed_patterns_at_scoped_expr(
492494}
493495
494496///|
495- fn apply_ast_patterns_at_expr (
497+ fn apply_ast_patterns_at_node (
496498 file : String ,
497499 rule : CompiledRule ,
498500 pattern_buckets : ExprPatternBuckets ,
499501 negative_pattern_buckets : ExprPatternBuckets ,
500- expr : @syntax. Expr ,
502+ expr : @untyped_ast. Node ,
501503 outer_loc : @basic.Location? ,
502504 initial_bindings : @hashmap.HashMap [String , @matching.BoundValue ]?,
503505 hits : Array [RuleFinding ],
504506) -> RuleTraversalAction {
505- for indexed in pattern_buckets.patterns_for_expr (expr) {
506- if match_ast_rule_pattern (indexed.pattern, expr, initial_bindings)
507+ for indexed in pattern_buckets.patterns_for_node (expr) {
508+ if match_node_rule_pattern (indexed.pattern, expr, initial_bindings)
507509 is Some (_) {
508510 hits.push({
509511 file,
510512 rule_id: rule.rule_id,
511513 description: rule.description,
512514 pattern_index: indexed.pattern_index,
513- loc: expr.loc() ,
515+ loc: expr.loc,
514516 outer_loc,
515517 })
516518 return RulePrune
517519 }
518520 }
519- if ast_negative_patterns_match_expr (
521+ if ast_negative_patterns_match_node (
520522 negative_pattern_buckets, expr, initial_bindings,
521523 ) {
522524 return RulePrune
@@ -525,13 +527,13 @@ fn apply_ast_patterns_at_expr(
525527}
526528
527529///|
528- fn ast_negative_patterns_match_expr (
530+ fn ast_negative_patterns_match_node (
529531 negative_pattern_buckets : ExprPatternBuckets ,
530- expr : @syntax. Expr ,
532+ expr : @untyped_ast. Node ,
531533 initial_bindings : @hashmap.HashMap [String , @matching.BoundValue ]?,
532534) -> Bool {
533- for indexed in negative_pattern_buckets.patterns_for_expr (expr) {
534- if match_ast_rule_pattern (indexed.pattern, expr, initial_bindings)
535+ for indexed in negative_pattern_buckets.patterns_for_node (expr) {
536+ if match_node_rule_pattern (indexed.pattern, expr, initial_bindings)
535537 is Some (_) {
536538 return true
537539 }
@@ -614,19 +616,6 @@ fn names_contain(names : Array[String], needle : String) -> Bool {
614616 false
615617}
616618
617- ///|
618- fn match_ast_rule_pattern(
619- pattern : CompiledRulePattern ,
620- expr : @syntax.Expr ,
621- initial_bindings : @hashmap.HashMap [String , @matching.BoundValue ]?,
622- ) -> @matching.ExprMatch? {
623- match_node_rule_pattern(
624- pattern,
625- @untyped_ast.from_expr(expr),
626- initial_bindings,
627- )
628- }
629-
630619///|
631620fn match_node_rule_pattern(
632621 pattern : CompiledRulePattern ,
0 commit comments