From 5fb425fd67f3fd9fd426f8796b1c8eedaf864e75 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 13 Jan 2026 10:24:04 +0100 Subject: [PATCH] Rust: Update extractor and QL code after removing `MacroBlockExpr` --- rust/extractor/src/translate/base.rs | 19 ++++++++++-- .../internal/ControlFlowGraphImpl.qll | 11 +------ .../rust/dataflow/internal/DataFlowImpl.qll | 1 - .../codeql/rust/internal/PathResolution.qll | 31 +++++++++++-------- 4 files changed, 35 insertions(+), 27 deletions(-) diff --git a/rust/extractor/src/translate/base.rs b/rust/extractor/src/translate/base.rs index a3a0b3c9133..94d8545bb15 100644 --- a/rust/extractor/src/translate/base.rs +++ b/rust/extractor/src/translate/base.rs @@ -518,7 +518,7 @@ impl<'a> Translator<'a> { pub(crate) fn emit_macro_stmts( &mut self, node: &ast::MacroStmts, - ) -> Option> { + ) -> Option> { // not generated to work around a bug in rust-analyzer AST generation machinery. // Because an Expr can also be a Stmt (AsmExpr: Expr and AsmExpr: Item: Stmt) // then such an element will be returned by both `expr()` and `statements()` @@ -537,10 +537,23 @@ impl<'a> Translator<'a> { .iter() .filter_map(|x| self.emit_stmt(x)) .collect(); - let label = self.trap.emit(generated::MacroBlockExpr { + let stmt_list = self.trap.emit(generated::StmtList { id: TrapId::Star, - tail_expr, + attrs: vec![], statements, + tail_expr, + }); + let label = self.trap.emit(generated::BlockExpr { + id: TrapId::Star, + label: None, + attrs: vec![], + is_async: false, + is_const: false, + is_gen: false, + is_move: false, + is_try: false, + is_unsafe: false, + stmt_list: Some(stmt_list), }); self.emit_location(label, node); self.emit_tokens(node, label.into(), node.syntax().children_with_tokens()); diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll index 522e5741795..16e14ce84a2 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll @@ -99,7 +99,7 @@ class FormatTemplateVariableAccessTree extends LeafTree, FormatTemplateVariableA class ItemTree extends LeafTree, Item { ItemTree() { not this instanceof MacroCall and - this = [any(StmtList s).getAStatement(), any(MacroBlockExpr s).getAStatement()] + this = any(StmtList s).getAStatement() } } @@ -140,15 +140,6 @@ class MacroCallTree extends StandardPostOrderTree, MacroCall { override AstNode getChildNode(int i) { i = 0 and result = this.getMacroCallExpansion() } } -class MacroBlockExprTree extends StandardPostOrderTree, MacroBlockExpr { - override AstNode getChildNode(int i) { - result = this.getStatement(i) - or - i = this.getNumberOfStatements() and - result = this.getTailExpr() - } -} - class MatchArmTree extends ControlFlowTree, MatchArm { override predicate propagatesAbnormal(AstNode child) { child = this.getExpr() } diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll index c21c053b173..a0026f6757e 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll @@ -149,7 +149,6 @@ private Expr getALastEvalNode(Expr e) { not be.isAsync() and result = be.getTailExpr() ) or - result = e.(MacroBlockExpr).getTailExpr() or result = e.(MatchExpr).getAnArm().getExpr() or result = e.(MacroExpr).getMacroCall().getMacroCallExpansion() or result.(BreakExpr).getTarget() = e or diff --git a/rust/ql/lib/codeql/rust/internal/PathResolution.qll b/rust/ql/lib/codeql/rust/internal/PathResolution.qll index e23efc60ee4..f30625807b4 100644 --- a/rust/ql/lib/codeql/rust/internal/PathResolution.qll +++ b/rust/ql/lib/codeql/rust/internal/PathResolution.qll @@ -110,20 +110,18 @@ pragma[nomagic] private ItemNode getAChildSuccessor(ItemNode item, string name, SuccessorKind kind) { item = result.getImmediateParent() and name = result.getName() and - ( - // type parameters are only available inside the declaring item - if result instanceof TypeParam - then kind.isInternal() + // type parameters are only available inside the declaring item + if result instanceof TypeParam + then kind.isInternal() + else + // associated items must always be qualified, also within the declaring + // item (using `Self`) + if item instanceof ImplOrTraitItemNode and result instanceof AssocItem + then kind.isExternal() else - // associated items must always be qualified, also within the declaring - // item (using `Self`) - if item instanceof ImplOrTraitItemNode and result instanceof AssocItem - then kind.isExternal() - else - if result.isPublic() - then kind.isBoth() - else kind.isInternal() - ) + if result.isPublic() + then kind.isBoth() + else kind.isInternal() } private module UseOption = Option; @@ -372,6 +370,13 @@ abstract class ItemNode extends Locatable { result = this.(TypeAliasItemNodeImpl).resolveAliasCand().getASuccessor(name, kind, useOpt) and kind.isExternalOrBoth() or + // items declared at top-level inside macros are also available at the macro invocation sites + exists(BlockExprItemNode be | + this = be.getImmediateParent() and + be = any(MacroCall mc).getMacroCallExpansion() and + result = be.getASuccessor(name, kind, useOpt) + ) + or name = "super" and useOpt.isNone() and (