Rust: Add a few control flow tree classes

This commit is contained in:
Simon Friis Vindum
2024-09-10 10:03:01 +02:00
parent 91d5171d90
commit 6d972bea2c
4 changed files with 64 additions and 6 deletions

View File

@@ -1,11 +1,12 @@
private import rust
private import codeql.util.Boolean
private import codeql.rust.controlflow.ControlFlowGraph
private import rust
private import SuccessorType
private import SuccessorTypes
private newtype TCompletion =
TSimpleCompletion() or
TBooleanCompletion(boolean b) { b in [false, true] } or
TBooleanCompletion(Boolean b) or
TReturnCompletion()
/** A completion of a statement or an expression. */
@@ -82,3 +83,12 @@ class ReturnCompletion extends TReturnCompletion, Completion {
override string toString() { result = "return" }
}
/** Hold if `c` represents normal evaluation of a statement or an expression. */
predicate completionIsNormal(Completion c) { c instanceof NormalCompletion }
/** Hold if `c` represents simple and normal evaluation of a statement or an expression. */
predicate completionIsSimple(Completion c) { c instanceof SimpleCompletion }
/** Holds if `c` is a valid completion for `n`. */
predicate completionIsValidFor(Completion c, AstNode n) { c.isValidFor(n) }

View File

@@ -1 +1,47 @@
private import rust
import ControlFlowGraphImplSpecific::CfgImpl
import Completion
class CallTree extends StandardPostOrderTree instanceof Call {
override ControlFlowTree getChildNode(int i) { result = super.getArg(i) }
}
class BinaryOpTree extends StandardPostOrderTree instanceof BinaryOp {
override ControlFlowTree getChildNode(int i) {
i = 0 and result = super.getLhs()
or
i = 1 and result = super.getRhs()
}
}
class IfTree extends PostOrderTree instanceof If {
override predicate first(AstNode node) { first(super.getCondition(), node) }
override predicate propagatesAbnormal(AstNode child) { none() }
override predicate succ(AstNode pred, AstNode succ, Completion c) {
// Edges from the condition to each branch
last(super.getCondition(), pred, c) and
(
first(super.getThen(), succ) and c.(BooleanCompletion).getValue() = true
or
first(super.getElse(), succ) and c.(BooleanCompletion).getValue() = false
)
or
// An edge from the then branch to the last node
last(super.getThen(), pred, c) and
succ = this and
completionIsSimple(c)
or
// An edge from the else branch to the last node
last(super.getElse(), pred, c) and
succ = this and
completionIsSimple(c)
}
}
class LetTree extends StandardPostOrderTree instanceof Let {
override ControlFlowTree getChildNode(int i) { i = 0 and result = super.getExpr() }
}
class LiteralTree extends LeafTree instanceof Literal { }

View File

@@ -11,11 +11,11 @@ module CfgInput implements InputSig<Rust::Location> {
class Completion = C::Completion;
predicate completionIsNormal(Completion c) { c instanceof C::NormalCompletion }
predicate completionIsNormal = C::completionIsNormal/1;
predicate completionIsSimple(Completion c) { c instanceof C::SimpleCompletion }
predicate completionIsSimple = C::completionIsSimple/1;
predicate completionIsValidFor(Completion c, AstNode e) { c.isValidFor(e) }
predicate completionIsValidFor = C::completionIsValidFor/2;
/** An AST node with an associated control-flow graph. */
class CfgScope = Scope::CfgScope;

View File

@@ -1,7 +1,9 @@
private import codeql.util.Boolean
cached
newtype TSuccessorType =
TSuccessorSuccessor() or
TBooleanSuccessor(boolean b) { b in [false, true] } or
TBooleanSuccessor(Boolean b) or
TReturnSuccessor()
/** The type of a control flow successor. */