Merge pull request #15219 from rdmarsh2/rdmarsh2/swift/parameterized-cfg-library

Swift: switch to shared, parameterized CFG library
This commit is contained in:
Mathias Vorreiter Pedersen
2024-01-16 21:54:05 +00:00
committed by GitHub
13 changed files with 467 additions and 1225 deletions

View File

@@ -1 +1 @@
import codeql.swift.controlflow.internal.ControlFlowGraphImplShared::Consistency
import codeql.swift.controlflow.internal.ControlFlowGraphImplSpecific::CfgImpl::Consistency

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The control flow graph library (`codeql.swift.controlflow`) has been transitioned to use the shared implementation from the `codeql/controlflow` qlpack. No result changes are expected due to this change.

View File

@@ -2,7 +2,7 @@
private import swift
private import ControlFlowGraph
private import internal.ControlFlowGraphImpl
private import internal.ControlFlowGraphImpl as Impl
private import internal.ControlFlowElements
private import CfgNodes
private import SuccessorTypes
@@ -133,7 +133,9 @@ private module Cached {
private predicate predBB(BasicBlock succ, BasicBlock pred) { succBB(pred, succ) }
/** Holds if `bb` is an exit basic block that represents normal exit. */
private predicate normalExitBB(BasicBlock bb) { bb.getANode().(AnnotatedExitNode).isNormal() }
private predicate normalExitBB(BasicBlock bb) {
bb.getANode().(Impl::AnnotatedExitNode).isNormal()
}
/** Holds if `dom` is an immediate post-dominator of `bb`. */
cached
@@ -167,7 +169,9 @@ private predicate entryBB(BasicBlock bb) { bb.getFirstNode() instanceof EntryNod
class EntryBasicBlock extends BasicBlock {
EntryBasicBlock() { entryBB(this) }
override CfgScope getScope() { this.getFirstNode() = TEntryNode(result) }
override CfgScope getScope() {
this.getFirstNode() = any(EntryNode node | node.getScope() = result)
}
}
/**
@@ -178,7 +182,7 @@ class AnnotatedExitBasicBlock extends BasicBlock {
private boolean normal;
AnnotatedExitBasicBlock() {
exists(AnnotatedExitNode n |
exists(Impl::AnnotatedExitNode n |
n = this.getANode() and
if n.isNormal() then normal = true else normal = false
)

View File

@@ -3,61 +3,10 @@
private import swift
private import BasicBlocks
private import ControlFlowGraph
private import internal.ControlFlowGraphImpl
private import internal.ControlFlowGraphImpl as Impl
private import internal.ControlFlowElements
private import internal.Splitting
/** An entry node for a given scope. */
class EntryNode extends ControlFlowNode, TEntryNode {
private CfgScope scope;
EntryNode() { this = TEntryNode(scope) }
final override EntryBasicBlock getBasicBlock() { result = ControlFlowNode.super.getBasicBlock() }
final override Location getLocation() { result = scope.getLocation() }
final override string toString() { result = "enter " + scope }
}
/** An exit node for a given scope, annotated with the type of exit. */
class AnnotatedExitNode extends ControlFlowNode, TAnnotatedExitNode {
private CfgScope scope;
private boolean normal;
AnnotatedExitNode() { this = TAnnotatedExitNode(scope, normal) }
/** Holds if this node represent a normal exit. */
final predicate isNormal() { normal = true }
final override AnnotatedExitBasicBlock getBasicBlock() {
result = ControlFlowNode.super.getBasicBlock()
}
final override Location getLocation() { result = scope.getLocation() }
final override string toString() {
exists(string s |
normal = true and s = "normal"
or
normal = false and s = "abnormal"
|
result = "exit " + scope + " (" + s + ")"
)
}
}
/** An exit node for a given scope. */
class ExitNode extends ControlFlowNode, TExitNode {
private CfgScope scope;
ExitNode() { this = TExitNode(scope) }
final override Location getLocation() { result = scope.getLocation() }
final override string toString() { result = "exit " + scope }
}
/**
* A node for an AST node.
*
@@ -65,46 +14,28 @@ class ExitNode extends ControlFlowNode, TExitNode {
* (dead) code or not important for control flow, and multiple when there are different
* splits for the AST node.
*/
class CfgNode extends ControlFlowNode, TElementNode {
private Splits splits;
ControlFlowElement n;
CfgNode() { this = TElementNode(_, n, splits) }
final override ControlFlowElement getNode() { result = n }
override Location getLocation() { result = n.getLocation() }
final override string toString() {
exists(string s | s = n.toString() |
result = "[" + this.getSplitsString() + "] " + s
or
not exists(this.getSplitsString()) and result = s
)
}
/** Gets a comma-separated list of strings for each split in this node, if any. */
final string getSplitsString() {
result = splits.toString() and
result != ""
}
class CfgNode extends ControlFlowNode instanceof Impl::AstCfgNode {
final override ControlFlowElement getNode() { result = this.getAstNode() }
/** Gets a split for this control flow node, if any. */
final Split getASplit() { result = splits.getASplit() }
final Split getASplit() { result = super.getASplit() }
/** Gets a comma-separated list of strings for each split in this node, if any. */
final string getSplitsString() { result = super.getSplitsString() }
/** Gets the AST representation of this control flow node, if any. */
Expr getAst() {
result = n.asAstNode()
result = this.getNode().asAstNode()
or
result = n.(PropertyGetterElement).getRef()
result = this.getNode().(PropertyGetterElement).getRef()
or
result = n.(PropertySetterElement).getAssignExpr()
result = this.getNode().(PropertySetterElement).getAssignExpr()
or
result = n.(PropertyObserverElement).getAssignExpr()
result = this.getNode().(PropertyObserverElement).getAssignExpr()
or
result = n.(ClosureElement).getAst()
result = this.getNode().(ClosureElement).getAst()
or
result = n.(KeyPathElement).getAst()
result = this.getNode().(KeyPathElement).getAst()
}
}
@@ -130,7 +61,9 @@ class PatternCfgNode extends CfgNode {
/** A control-flow node that wraps a property getter. */
class PropertyGetterCfgNode extends CfgNode {
override PropertyGetterElement n;
PropertyGetterElement n;
PropertyGetterCfgNode() { n = this.getAstNode() }
Expr getRef() { result = n.getRef() }
@@ -141,7 +74,9 @@ class PropertyGetterCfgNode extends CfgNode {
/** A control-flow node that wraps a property setter. */
class PropertySetterCfgNode extends CfgNode {
override PropertySetterElement n;
PropertySetterElement n;
PropertySetterCfgNode() { n = this.getAstNode() }
AssignExpr getAssignExpr() { result = n.getAssignExpr() }
@@ -153,7 +88,9 @@ class PropertySetterCfgNode extends CfgNode {
}
class PropertyObserverCfgNode extends CfgNode {
override PropertyObserverElement n;
PropertyObserverElement n;
PropertyObserverCfgNode() { n = this.getAstNode() }
AssignExpr getAssignExpr() { result = n.getAssignExpr() }
@@ -201,3 +138,9 @@ class KeyPathApplicationExprCfgNode extends ExprCfgNode {
class KeyPathExprCfgNode extends ExprCfgNode {
override KeyPathExpr e;
}
class EntryNode = Impl::EntryNode;
class ExitNode = Impl::ExitNode;
class AnnotatedExitNode = Impl::AnnotatedExitNode;

View File

@@ -27,16 +27,10 @@ class CfgScope extends Scope instanceof CfgScope::Range_ {
*
* Only nodes that can be reached from an entry point are included in the CFG.
*/
class ControlFlowNode extends TCfgNode {
/** Gets a textual representation of this control flow node. */
string toString() { none() }
class ControlFlowNode extends Node {
/** Gets the AST node that this node corresponds to, if any. */
ControlFlowElement getNode() { none() }
/** Gets the location of this control flow node. */
Location getLocation() { none() }
/** Gets the file of this control flow node. */
final File getFile() { result = this.getLocation().getFile() }
@@ -50,7 +44,7 @@ class ControlFlowNode extends TCfgNode {
BasicBlock getBasicBlock() { result.getANode() = this }
/** Gets a successor node of a given type, if any. */
final ControlFlowNode getASuccessor(SuccessorType t) { result = getASuccessor(this, t) }
final ControlFlowNode getASuccessor(SuccessorType t) { result = super.getASuccessor(t) }
/** Gets an immediate successor, if any. */
final ControlFlowNode getASuccessor() { result = this.getASuccessor(_) }

View File

@@ -1,6 +1,6 @@
private import swift
private import Completion
private import ControlFlowGraphImplShared
private import ControlFlowGraphImplSpecific::CfgImpl
private import ControlFlowElements
abstract class AstControlFlowTree extends ControlFlowTree {

View File

@@ -36,7 +36,7 @@ private import codeql.swift.controlflow.ControlFlowGraph
private import codeql.swift.generated.Synth
private import Completion
private import Scope
import ControlFlowGraphImplShared
import ControlFlowGraphImplSpecific::CfgImpl
private import ControlFlowElements
private import AstControlFlowTrees
@@ -80,10 +80,12 @@ module CfgScope {
final override predicate exit(ControlFlowElement last, Completion c) { last(tree, last, c) }
}
private class KeyPathControlFlowTree extends StandardPostOrderTree, KeyPathElement {
final override ControlFlowElement getChildElement(int i) {
result.asAstNode() = expr.getComponent(i)
private class KeyPathControlFlowTree extends StandardPostOrderTree instanceof KeyPathElement {
override ControlFlowElement getChildNode(int i) {
result.asAstNode() = super.getAst().getComponent(i)
}
KeyPathExpr getAst() { result = super.getAst() }
}
}
@@ -100,7 +102,7 @@ predicate succExit(CfgScope::Range_ scope, ControlFlowElement last, Completion c
private class KeyPathComponentTree extends AstStandardPostOrderTree {
override KeyPathComponent ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
result.asAstNode() = ast.getSubscriptArgument(i).getExpr().getFullyConverted()
}
}
@@ -232,7 +234,7 @@ module Stmts {
private class ReturnStmtTree extends AstStandardPostOrderTree {
override ReturnStmt ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
result.asAstNode() = ast.getResult().getFullyConverted() and i = 0
}
}
@@ -240,7 +242,7 @@ module Stmts {
private class DiscardStmtTree extends AstStandardPostOrderTree {
override DiscardStmt ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
i = 0 and result.asAstNode() = ast.getSubExpr().getFullyUnresolved()
}
}
@@ -248,7 +250,7 @@ module Stmts {
private class YieldStmtTree extends AstStandardPostOrderTree {
override YieldStmt ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
result.asAstNode() = ast.getResult(i).getFullyConverted()
}
}
@@ -822,7 +824,7 @@ module Patterns {
private class TypedTree extends AstStandardPostOrderTree {
override TypedPattern ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
i = 0 and
result.asAstNode() = ast.getSubPattern().getFullyUnresolved()
}
@@ -863,7 +865,7 @@ module Patterns {
private class ParenTree extends AstStandardPreOrderTree {
override ParenPattern ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
i = 0 and
result.asAstNode() = ast.getResolveStep()
}
@@ -884,7 +886,7 @@ module Patterns {
private class IsTree extends AstStandardPostOrderTree {
override IsPattern ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
// Note: `getSubPattern` only has a result if the `is` pattern is of the form `pattern as type`.
i = 0 and
result.asAstNode() = ast.getSubPattern().getFullyUnresolved()
@@ -924,7 +926,7 @@ module Patterns {
private class BindingTree extends AstStandardPostOrderTree {
override BindingPattern ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
i = 0 and
result.asAstNode() = ast.getResolveStep()
}
@@ -933,7 +935,7 @@ module Patterns {
private class ExprTree extends AstStandardPostOrderTree {
override ExprPattern ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
i = 0 and
result.asAstNode() = ast.getSubExpr().getFullyConverted()
}
@@ -973,7 +975,7 @@ module Decls {
private class PatternBindingDeclTree extends AstStandardPostOrderTree {
override PatternBindingDecl ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
exists(int j |
i = 2 * j and
result.asAstNode() = ast.getPattern(j).getFullyUnresolved()
@@ -1033,7 +1035,7 @@ module Decls {
Function getAst() { result = ast }
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
i = -1 and
result.asAstNode() = ast.getSelfParam()
or
@@ -1167,7 +1169,7 @@ module Exprs {
ClosureExpr getAst() { result = expr }
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
result.asAstNode() = expr.getParam(i)
or
result.asAstNode() = expr.getBody() and
@@ -1178,7 +1180,7 @@ module Exprs {
private class BindOptionalTree extends AstStandardPostOrderTree {
override BindOptionalExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 0
}
}
@@ -1186,7 +1188,7 @@ module Exprs {
private class CaptureListTree extends AstStandardPostOrderTree {
override CaptureListExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
result.asAstNode() = ast.getBindingDecl(i).getFullyUnresolved()
or
i = ast.getNumberOfBindingDecls() and
@@ -1255,7 +1257,7 @@ module Exprs {
class KeyPathApplicationTree extends AstStandardPostOrderTree {
override KeyPathApplicationExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
i = 0 and result.asAstNode() = ast.getBase().getFullyConverted()
or
i = 1 and result.asAstNode() = ast.getKeyPath().getFullyConverted()
@@ -1313,7 +1315,7 @@ module Exprs {
private class TupleTree extends AstStandardPostOrderTree {
override TupleExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
result.asAstNode() = ast.getElement(i).getFullyConverted()
}
}
@@ -1321,7 +1323,7 @@ module Exprs {
private class TupleElementTree extends AstStandardPostOrderTree {
override TupleElementExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 0
}
}
@@ -1329,7 +1331,7 @@ module Exprs {
private class RebindSelfInInitializerTree extends AstStandardPostOrderTree {
override RebindSelfInInitializerExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 0
}
}
@@ -1341,7 +1343,7 @@ module Exprs {
private class DotSyntaxBaseIgnoredTree extends AstStandardPostOrderTree {
override DotSyntaxBaseIgnoredExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
result.asAstNode() = ast.getQualifier().getFullyConverted() and i = 0
or
result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 1
@@ -1355,7 +1357,7 @@ module Exprs {
private class DynamicTypeTree extends AstStandardPostOrderTree {
override DynamicTypeExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
result.asAstNode() = ast.getBase().getFullyConverted() and i = 0
}
}
@@ -1363,7 +1365,7 @@ module Exprs {
private class LazyInitializationTree extends AstStandardPostOrderTree {
override LazyInitializationExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 0
}
}
@@ -1371,7 +1373,7 @@ module Exprs {
private class ObjCSelectorTree extends AstStandardPostOrderTree {
override ObjCSelectorExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 0
}
}
@@ -1379,7 +1381,7 @@ module Exprs {
private class OneWayTree extends AstStandardPostOrderTree {
override OneWayExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 0
}
}
@@ -1387,7 +1389,7 @@ module Exprs {
private class OptionalEvaluationTree extends AstStandardPostOrderTree {
override OptionalEvaluationExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 0
}
}
@@ -1404,7 +1406,7 @@ module Exprs {
private class InterpolatedStringLiteralExprTree extends AstStandardPostOrderTree {
override InterpolatedStringLiteralExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
i = 0 and
result.asAstNode() = ast.getAppendingExpr().getFullyConverted()
}
@@ -1414,7 +1416,7 @@ module Exprs {
private class TapExprTree extends AstStandardPostOrderTree {
override TapExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
// We first visit the expression that gives the local variable its initial value.
i = 0 and
result.asAstNode() = ast.getSubExpr().getFullyConverted()
@@ -1429,7 +1431,7 @@ module Exprs {
private class SingleValueStmtExprTree extends AstStandardPostOrderTree {
override SingleValueStmtExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
i = 0 and result.asAstNode() = ast.getStmt()
}
}
@@ -1438,7 +1440,7 @@ module Exprs {
private class PackExpansionExprTree extends AstStandardPostOrderTree {
override PackExpansionExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
i = 0 and result.asAstNode() = ast.getPatternExpr().getFullyConverted()
}
}
@@ -1447,7 +1449,7 @@ module Exprs {
private class PackElementExprTree extends AstStandardPostOrderTree {
override PackElementExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
i = 0 and result.asAstNode() = ast.getSubExpr().getFullyUnresolved()
}
}
@@ -1455,7 +1457,7 @@ module Exprs {
private class MaterializePackExprTree extends AstStandardPostOrderTree {
override MaterializePackExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
i = 0 and result.asAstNode() = ast.getSubExpr().getFullyUnresolved()
}
}
@@ -1464,7 +1466,7 @@ module Exprs {
private class CopyExprTree extends AstStandardPostOrderTree {
override CopyExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
i = 0 and result.asAstNode() = ast.getSubExpr().getFullyUnresolved()
}
}
@@ -1473,7 +1475,7 @@ module Exprs {
private class ConsumeExprTree extends AstStandardPostOrderTree {
override ConsumeExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
i = 0 and result.asAstNode() = ast.getSubExpr().getFullyUnresolved()
}
}
@@ -1535,7 +1537,7 @@ module Exprs {
class MethodLookupExprTree extends AstStandardPreOrderTree {
override MethodLookupExpr ast;
override ControlFlowElement getChildElement(int i) {
override ControlFlowElement getChildNode(int i) {
i = 0 and result.asAstNode() = ast.getBase().getFullyConverted()
}
}
@@ -1642,7 +1644,7 @@ module Exprs {
not ast instanceof NilCoalescingExpr
}
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
i = -1 and
result.asAstNode() = ast.getFunction().getFullyConverted()
or
@@ -1657,13 +1659,15 @@ module Exprs {
private class ForceValueTree extends AstStandardPostOrderTree {
override ForceValueExpr ast;
override ControlFlowElement getChildElement(int i) {
override ControlFlowElement getChildNode(int i) {
i = 0 and
result.asAstNode() = ast.getSubExpr().getFullyConverted()
}
}
private class NilCoalescingTestTree extends LeafTree, NilCoalescingElement { }
private class NilCoalescingTestTree extends LeafTree instanceof NilCoalescingElement {
NilCoalescingExpr getAst() { result = super.getAst() }
}
private class NilCoalescingTree extends AstPostOrderTree {
override NilCoalescingExpr ast;
@@ -1768,7 +1772,7 @@ module Exprs {
private class VarargExpansionTree extends AstStandardPostOrderTree {
override VarargExpansionExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
i = 0 and
result.asAstNode() = ast.getSubExpr().getFullyConverted()
}
@@ -1777,7 +1781,7 @@ module Exprs {
private class ArrayTree extends AstStandardPostOrderTree {
override ArrayExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
result.asAstNode() = ast.getElement(i).getFullyConverted()
}
}
@@ -1785,7 +1789,7 @@ module Exprs {
private class EnumIsCaseTree extends AstStandardPostOrderTree {
override EnumIsCaseExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 0
}
}
@@ -1793,7 +1797,7 @@ module Exprs {
private class IsTree extends AstStandardPostOrderTree {
override IsExpr ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
result.asAstNode() = ast.getSubExpr().getFullyConverted() and i = 0
}
}
@@ -1827,7 +1831,7 @@ module Exprs {
private class AnyTryTree extends AstStandardPostOrderTree {
override AnyTryExpr ast;
override ControlFlowElement getChildElement(int i) {
override ControlFlowElement getChildNode(int i) {
i = 0 and
result.asAstNode() = ast.getSubExpr().getFullyConverted()
}
@@ -1836,7 +1840,7 @@ module Exprs {
private class DictionaryLiteralTree extends AstStandardPostOrderTree {
override DictionaryExpr ast;
override ControlFlowElement getChildElement(int i) {
override ControlFlowElement getChildNode(int i) {
result.asAstNode() = ast.getElement(i).getFullyConverted()
}
}
@@ -1844,7 +1848,7 @@ module Exprs {
private class OpenExistentialTree extends AstStandardPostOrderTree {
override OpenExistentialExpr ast;
override ControlFlowElement getChildElement(int i) {
override ControlFlowElement getChildNode(int i) {
i = 0 and
result.asAstNode() = ast.getExistential().getFullyConverted()
or
@@ -1863,7 +1867,7 @@ module Exprs {
abstract predicate convertsFrom(Expr e);
override ControlFlowElement getChildElement(int i) {
override ControlFlowElement getChildNode(int i) {
i = 0 and
this.convertsFrom(result.asAstNode())
}
@@ -1900,7 +1904,7 @@ module AvailabilityInfo {
private class AvailabilityInfoTree extends AstStandardPostOrderTree {
override AvailabilityInfo ast;
final override ControlFlowElement getChildElement(int i) {
final override ControlFlowElement getChildNode(int i) {
result.asAstNode() = ast.getSpec(i).getFullyUnresolved()
}
}

View File

@@ -1,7 +1,18 @@
/**
* Provides the `CfgImpl` module that is used to construct the basic successor relation on control
* flow elements, and the `CfgInput` module that is used to construct `CgfImpl`.
*
* See `ControlFlowGraphImpl.qll` for the auxiliary classes and predicates that map AST elements to
* control flow elements and sequence their children.
*/
private import swift as S
import codeql.controlflow.Cfg
import codeql.util.Unit
private import Completion as C
private import ControlFlowGraphImpl as Impl
import Completion
private import codeql.swift.controlflow.ControlFlowGraph as CFG
private import codeql.swift.controlflow.ControlFlowGraph as Cfg
private import Splitting as Splitting
private import Scope
import ControlFlowElements
@@ -10,45 +21,71 @@ import AstControlFlowTrees
/** The base class for `ControlFlowTree`. */
class ControlFlowTreeBase = ControlFlowElement;
class CfgScope = CFG::CfgScope;
class CfgScope = Cfg::CfgScope;
predicate getCfgScope = Impl::getCfgScope/1;
/** Holds if `first` is first executed when entering `scope`. */
predicate scopeFirst(CfgScope scope, ControlFlowElement first) {
scope.(Impl::CfgScope::Range_).entry(first)
}
/** Holds if `scope` is exited when `last` finishes with completion `c`. */
predicate scopeLast(CfgScope scope, ControlFlowElement last, Completion c) {
scope.(Impl::CfgScope::Range_).exit(last, c)
}
/** Gets the maximum number of splits allowed for a given node. */
int maxSplits() { result = 5 }
class SplitKindBase = Splitting::TSplitKind;
class Split = Splitting::Split;
class SuccessorType = CFG::SuccessorType;
/** Gets a successor type that matches completion `c`. */
SuccessorType getAMatchingSuccessorType(Completion c) { result = c.getAMatchingSuccessorType() }
/**
* Hold if `c` represents simple (normal) evaluation of a statement or an
* expression.
*/
predicate successorTypeIsSimple(SuccessorType t) {
t instanceof CFG::SuccessorTypes::NormalSuccessor
}
/** Holds if `t` is an abnormal exit type out of a CFG scope. */
predicate isAbnormalExitType(SuccessorType t) {
t instanceof CFG::SuccessorTypes::ExceptionSuccessor
}
class Location = S::Location;
class Node = CFG::ControlFlowNode;
class Node = Cfg::ControlFlowNode;
module CfgInput implements InputSig<Location> {
class AstNode = ControlFlowElement;
class Completion = C::Completion;
predicate completionIsNormal = C::completionIsNormal/1;
predicate completionIsSimple = C::completionIsSimple/1;
predicate completionIsValidFor = C::completionIsValidFor/2;
/** An AST node with an associated control-flow graph. */
class CfgScope extends S::Locatable instanceof Impl::CfgScope::Range_ { }
CfgScope getCfgScope(AstNode n) { result = scopeOfAst(n.asAstNode()) }
class SplitKindBase = Splitting::TSplitKind;
class Split = Splitting::Split;
class SuccessorType = Cfg::SuccessorType;
/** Gets a successor type that matches completion `c`. */
SuccessorType getAMatchingSuccessorType(Completion c) { result = c.getAMatchingSuccessorType() }
/**
* Hold if `c` represents simple (normal) evaluation of a statement or an
* expression.
*/
predicate successorTypeIsSimple(SuccessorType t) {
t instanceof Cfg::SuccessorTypes::NormalSuccessor
}
/** Holds if `t` is an abnormal exit type out of a CFG scope. */
predicate isAbnormalExitType(SuccessorType t) {
t instanceof Cfg::SuccessorTypes::ExceptionSuccessor
}
/** Hold if `t` represents a conditional successor type. */
predicate successorTypeIsCondition(SuccessorType t) {
t instanceof Cfg::SuccessorTypes::BooleanSuccessor or
t instanceof Cfg::SuccessorTypes::BreakSuccessor or
t instanceof Cfg::SuccessorTypes::ContinueSuccessor or
t instanceof Cfg::SuccessorTypes::MatchingSuccessor or
t instanceof Cfg::SuccessorTypes::EmptinessSuccessor
}
/** Holds if `first` is first executed when entering `scope`. */
predicate scopeFirst(CfgScope scope, AstNode first) {
scope.(Impl::CfgScope::Range_).entry(first)
}
/** Holds if `scope` is exited when `last` finishes with completion `c`. */
predicate scopeLast(CfgScope scope, AstNode last, Completion c) {
scope.(Impl::CfgScope::Range_).exit(last, c)
}
}
module CfgImpl = Make<Location, CfgInput>;

View File

@@ -5,9 +5,9 @@
private import swift
private import Completion
private import ControlFlowGraphImpl
private import codeql.swift.controlflow.ControlFlowGraph
private import AstControlFlowTrees
private import ControlFlowElements
private import ControlFlowGraphImplSpecific::CfgInput as CfgInput
cached
private module Cached {
@@ -33,6 +33,8 @@ private module ConditionalCompletionSplitting {
ConditionalCompletionSplit() { this = TConditionalCompletionSplit(completion) }
ConditionalCompletion getCompletion() { result = completion }
override string toString() { result = completion.toString() }
}
@@ -44,49 +46,50 @@ private module ConditionalCompletionSplitting {
override string toString() { result = "ConditionalCompletion" }
}
private class ConditionalCompletionSplitImpl extends SplitImpl, ConditionalCompletionSplit {
private class ConditionalCompletionSplitImpl extends SplitImpl instanceof ConditionalCompletionSplit
{
override ConditionalCompletionSplitKind getKind() { any() }
override predicate hasEntry(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
succ(pred, succ, c) and
last(succ, _, completion) and
last(succ, _, super.getCompletion()) and
(
astLast(succ.asAstNode().(NotExpr).getOperand().getFullyConverted(), pred, c) and
completion.(BooleanCompletion).getDual() = c
super.getCompletion().(BooleanCompletion).getDual() = c
or
astLast(succ.asAstNode().(LogicalAndExpr).getAnOperand().getFullyConverted(), pred, c) and
completion = c
super.getCompletion() = c
or
astLast(succ.asAstNode().(LogicalOrExpr).getAnOperand().getFullyConverted(), pred, c) and
completion = c
super.getCompletion() = c
or
succ.asAstNode() =
any(IfExpr ce |
astLast(ce.getBranch(_).getFullyConverted(), pred, c) and
completion = c
super.getCompletion() = c
)
or
exists(Expr e, Exprs::Conversions::ConversionOrIdentityTree conv |
succ.asAstNode() = conv.getAst() and
conv.convertsFrom(e) and
astLast(e, pred, c) and
completion = c
super.getCompletion() = c
)
)
}
override predicate hasEntryScope(CfgScope scope, ControlFlowElement succ) { none() }
override predicate hasEntryScope(CfgInput::CfgScope scope, ControlFlowElement succ) { none() }
override predicate hasExit(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
this.appliesTo(pred) and
succ(pred, succ, c) and
if c instanceof ConditionalCompletion then completion = c else any()
if c instanceof ConditionalCompletion then super.getCompletion() = c else any()
}
override predicate hasExitScope(CfgScope scope, ControlFlowElement last, Completion c) {
override predicate hasExitScope(CfgInput::CfgScope scope, ControlFlowElement last, Completion c) {
this.appliesTo(last) and
succExit(scope, last, c) and
if c instanceof ConditionalCompletion then completion = c else any()
if c instanceof ConditionalCompletion then super.getCompletion() = c else any()
}
override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) {

View File

@@ -6,6 +6,7 @@ dbscheme: swift.dbscheme
upgrades: upgrades
library: true
dependencies:
codeql/controlflow: ${workspace}
codeql/dataflow: ${workspace}
codeql/regex: ${workspace}
codeql/mad: ${workspace}

View File

@@ -1,3 +1,252 @@
#-----| ... = ...
#-----| -> exit set (normal)
#-----| ... = ...
#-----| -> exit set (normal)
#-----| ... = ...
#-----| -> exit set (normal)
#-----| ... = ...
#-----| -> exit set (normal)
#-----| ... = ...
#-----| -> exit set (normal)
#-----| ... = ...
#-----| -> exit set (normal)
#-----| ... = ...
#-----| -> exit set (normal)
#-----| &...
#-----| -> yield ...
#-----| &...
#-----| -> yield ...
#-----| &...
#-----| -> yield ...
#-----| &...
#-----| -> yield ...
#-----| &...
#-----| -> yield ...
#-----| &...
#-----| -> yield ...
#-----| &...
#-----| -> yield ...
#-----| .b
#-----| -> return ...
#-----| .b
#-----| -> value
#-----| .bs
#-----| -> return ...
#-----| .bs
#-----| -> value
#-----| .c
#-----| -> return ...
#-----| .field
#-----| -> return ...
#-----| .field
#-----| -> value
#-----| .mayB
#-----| -> return ...
#-----| .mayB
#-----| -> value
#-----| .myInt
#-----| -> return ...
#-----| .x
#-----| -> return ...
#-----| .x
#-----| -> value
#-----| .x
#-----| -> return ...
#-----| .x
#-----| -> value
#-----| .x
#-----| -> return ...
#-----| .x
#-----| -> value
#-----| KeyPathComponent
#-----| -> #keyPath(...)
#-----| await ...
#-----| -> for ... in ... { ... }
#-----| getter for .b
#-----| -> &...
#-----| getter for .bs
#-----| -> &...
#-----| getter for .field
#-----| -> &...
#-----| getter for .mayB
#-----| -> &...
#-----| getter for .x
#-----| -> &...
#-----| getter for .x
#-----| -> &...
#-----| getter for .x
#-----| -> &...
#-----| n
#-----| -> _unimplementedInitializer(className:initName:file:line:column:)
#-----| return
#-----| return -> exit Derived.init(n:) (normal)
#-----| return ...
#-----| return -> exit get (normal)
#-----| return ...
#-----| return -> exit get (normal)
#-----| return ...
#-----| return -> exit get (normal)
#-----| return ...
#-----| return -> exit get (normal)
#-----| return ...
#-----| return -> exit get (normal)
#-----| return ...
#-----| return -> exit get (normal)
#-----| return ...
#-----| return -> exit get (normal)
#-----| return ...
#-----| return -> exit get (normal)
#-----| return ...
#-----| return -> exit get (normal)
#-----| self
#-----| -> .myInt
#-----| self
#-----| -> .c
#-----| self
#-----| -> .field
#-----| self
#-----| -> .field
#-----| self
#-----| -> getter for .field
#-----| self
#-----| -> .x
#-----| self
#-----| -> .x
#-----| self
#-----| -> getter for .x
#-----| self
#-----| -> .x
#-----| self
#-----| -> .x
#-----| self
#-----| -> getter for .x
#-----| self
#-----| -> .x
#-----| self
#-----| -> .x
#-----| self
#-----| -> getter for .x
#-----| self
#-----| -> .mayB
#-----| self
#-----| -> .mayB
#-----| self
#-----| -> getter for .mayB
#-----| self
#-----| -> .bs
#-----| self
#-----| -> .bs
#-----| self
#-----| -> getter for .bs
#-----| self
#-----| -> .b
#-----| self
#-----| -> .b
#-----| self
#-----| -> getter for .b
#-----| value
#-----| -> ... = ...
#-----| value
#-----| -> ... = ...
#-----| value
#-----| -> ... = ...
#-----| value
#-----| -> ... = ...
#-----| value
#-----| -> ... = ...
#-----| value
#-----| -> ... = ...
#-----| value
#-----| -> ... = ...
#-----| var ... = ...
#-----| -> .next()
#-----| var ... = ...
#-----| -> .next()
#-----| var ... = ...
#-----| -> .next()
cfg.swift:
# 5| enter returnZero()
#-----| -> returnZero()
@@ -956,6 +1205,7 @@ cfg.swift:
#-----| -> self
# 99| self
#-----| -> self
# 100| self
#-----| -> n
@@ -1456,6 +1706,7 @@ cfg.swift:
#-----| -> ....(_:_:)
# 138| call to makeIterator()
#-----| -> var ... = ...
# 138| ....(_:_:)
#-----| -> Int.Type
@@ -4606,6 +4857,7 @@ cfg.swift:
#-----| -> self
# 353| self
#-----| -> self
# 354| self
#-----| -> arg
@@ -4875,6 +5127,7 @@ cfg.swift:
#-----| -> cfg.Derived
# 377| call to _unimplementedInitializer(className:initName:file:line:column:)
#-----| -> return
# 377| cfg.Derived
#-----| -> #...
@@ -4905,6 +5158,7 @@ cfg.swift:
#-----| -> exit Derived.init(n:)
# 377| self
#-----| -> n
# 378| self
#-----| -> C.init(n:)
@@ -5069,16 +5323,19 @@ cfg.swift:
#-----| -> self
# 394| self
#-----| -> self
# 394| self
#-----| -> value
# 394| self
#-----| -> self
# 394| set
#-----| -> self
# 394| value
#-----| -> self
# 394| yield ...
#-----| -> exit _modify (normal)
@@ -5241,16 +5498,19 @@ cfg.swift:
#-----| -> self
# 410| self
#-----| -> self
# 410| self
#-----| -> value
# 410| self
#-----| -> self
# 410| set
#-----| -> self
# 410| value
#-----| -> self
# 410| yield ...
#-----| -> exit _modify (normal)
@@ -5318,16 +5578,19 @@ cfg.swift:
#-----| -> self
# 417| self
#-----| -> self
# 417| self
#-----| -> value
# 417| self
#-----| -> self
# 417| set
#-----| -> self
# 417| value
#-----| -> self
# 417| yield ...
#-----| -> exit _modify (normal)
@@ -5410,16 +5673,19 @@ cfg.swift:
#-----| -> self
# 446| self
#-----| -> self
# 446| self
#-----| -> value
# 446| self
#-----| -> self
# 446| set
#-----| -> self
# 446| value
#-----| -> self
# 446| yield ...
#-----| -> exit _modify (normal)
@@ -5455,16 +5721,19 @@ cfg.swift:
#-----| -> self
# 450| self
#-----| -> self
# 450| self
#-----| -> value
# 450| self
#-----| -> self
# 450| set
#-----| -> self
# 450| value
#-----| -> self
# 450| yield ...
#-----| -> exit _modify (normal)
@@ -5500,16 +5769,19 @@ cfg.swift:
#-----| -> self
# 451| self
#-----| -> self
# 451| self
#-----| -> value
# 451| self
#-----| -> self
# 451| set
#-----| -> self
# 451| value
#-----| -> self
# 451| yield ...
#-----| -> exit _modify (normal)
@@ -5545,16 +5817,19 @@ cfg.swift:
#-----| -> self
# 452| self
#-----| -> self
# 452| self
#-----| -> value
# 452| self
#-----| -> self
# 452| set
#-----| -> self
# 452| value
#-----| -> self
# 452| yield ...
#-----| -> exit _modify (normal)
@@ -5687,6 +5962,7 @@ cfg.swift:
#-----| -> KeyPathComponent
# 459| KeyPathComponent
#-----| -> KeyPathComponent
# 461| var ... = ...
#-----| -> apply_kpGet_bs_0_x
@@ -6132,6 +6408,7 @@ cfg.swift:
#-----| -> ....(_:_:)
# 526| call to makeIterator()
#-----| -> var ... = ...
# 526| ....(_:_:)
#-----| -> Int.Type
@@ -6173,6 +6450,7 @@ cfg.swift:
#-----| -> $i$generator
# 533| call to next()
#-----| -> await ...
# 533| for ... in ... { ... }
#-----| empty -> exit testAsyncFor() (normal)
@@ -6191,6 +6469,7 @@ cfg.swift:
#-----| -> stream
# 533| call to makeAsyncIterator()
#-----| -> var ... = ...
# 533| stream
#-----| -> (AsyncStream<Int>) ...

View File

@@ -9,7 +9,7 @@ import codeql.swift.controlflow.internal.ControlFlowGraphImpl::TestOutput
class MyRelevantNode extends RelevantNode {
MyRelevantNode() { this.getScope().getLocation().getFile().getName().matches("%swift/ql/test%") }
private AstNode asAstNode() { result = this.getNode().asAstNode() }
private AstNode asAstNode() { result = this.getAstNode().asAstNode() }
override string getOrderDisambiguation() {
result = this.asAstNode().getPrimaryQlClasses()