From f72af4f1f315cbce7e470002f90bf8aebe3cc13a Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 21 Oct 2024 14:04:50 +0200 Subject: [PATCH] Rust: Use `Callable` to define `CfgScope` --- .../internal/ControlFlowGraphImpl.qll | 26 +++---------- .../rust/controlflow/internal/Scope.qll | 38 ++++++++----------- 2 files changed, 20 insertions(+), 44 deletions(-) diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll index 688f0d1e96a9..54e61d531b3a 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll @@ -40,10 +40,12 @@ private module CfgInput implements InputSig { predicate successorTypeIsCondition(SuccessorType t) { t instanceof Cfg::BooleanSuccessor } /** Holds if `first` is first executed when entering `scope`. */ - predicate scopeFirst(CfgScope scope, AstNode first) { scope.scopeFirst(first) } + predicate scopeFirst(CfgScope scope, AstNode first) { + first(scope.(CfgScopeTree).getFirstChildNode(), first) + } /** Holds if `scope` is exited when `last` finishes with completion `c`. */ - predicate scopeLast(CfgScope scope, AstNode last, Completion c) { scope.scopeLast(last, c) } + predicate scopeLast(CfgScope scope, AstNode last, Completion c) { last(scope.getBody(), last, c) } } private module CfgSplittingInput implements SplittingInputSig { @@ -65,7 +67,7 @@ private module CfgImpl = import CfgImpl -class FunctionTree extends StandardTree, Function { +class CfgScopeTree extends StandardTree, Scope::CfgScope { override predicate first(AstNode first) { first = this } override predicate last(AstNode last, Completion c) { @@ -319,24 +321,6 @@ module ExprTrees { override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() } } - class ClosureExprTree extends StandardTree, ClosureExpr { - override predicate first(AstNode first) { first = this } - - override predicate last(AstNode last, Completion c) { - last = this and - completionIsValidFor(c, this) - } - - override predicate propagatesAbnormal(AstNode child) { none() } - - override AstNode getChildNode(int i) { - result = this.getParamList().getParam(i) - or - i = this.getParamList().getNumberOfParams() and - result = this.getBody() - } - } - class ContinueExprTree extends LeafTree, ContinueExpr { override predicate last(AstNode last, Completion c) { none() } diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/Scope.qll b/rust/ql/lib/codeql/rust/controlflow/internal/Scope.qll index 8a49ab975632..24148eaaf771 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/Scope.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/Scope.qll @@ -3,34 +3,26 @@ private import Completion private import ControlFlowGraphImpl private import codeql.rust.elements.internal.generated.ParentChild -abstract class CfgScope extends AstNode { - /** Holds if `first` is executed first when entering scope. */ - abstract predicate scopeFirst(AstNode first); - - /** Holds if scope is exited when `last` finishes with completion `c`. */ - abstract predicate scopeLast(AstNode last, Completion c); -} - -final class FunctionScope extends CfgScope, Function { - FunctionScope() { +/** + * A control-flow graph (CFG) scope. + * + * A CFG scope is a callable with a body. + */ +class CfgScope extends Callable { + CfgScope() { // A function without a body corresponds to a trait method signature and // should not have a CFG scope. - this.hasBody() + this.(Function).hasBody() + or + this instanceof ClosureExpr } - override predicate scopeFirst(AstNode node) { - first(this.(FunctionTree).getFirstChildNode(), node) + /** Gets the body of this callable. */ + AstNode getBody() { + result = this.(Function).getBody() + or + result = this.(ClosureExpr).getBody() } - - override predicate scopeLast(AstNode node, Completion c) { last(this.getBody(), node, c) } -} - -final class ClosureScope extends CfgScope, ClosureExpr { - override predicate scopeFirst(AstNode node) { - first(this.(ExprTrees::ClosureExprTree).getFirstChildNode(), node) - } - - override predicate scopeLast(AstNode node, Completion c) { last(this.getBody(), node, c) } } /**