C#: Adopt shared CFG construction library from shared `controlflow` pack

This commit is contained in:
Tom Hvitved 2023-06-27 16:59:46 +02:00
Родитель e011480114
Коммит b69188fee9
36 изменённых файлов: 692 добавлений и 1863 удалений

Просмотреть файл

@ -484,10 +484,6 @@
"ruby/ql/lib/codeql/ruby/security/internal/SensitiveDataHeuristics.qll",
"swift/ql/lib/codeql/swift/security/internal/SensitiveDataHeuristics.qll"
],
"CFG": [
"csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImplShared.qll",
"swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImplShared.qll"
],
"TypeTracker": [
"python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll",
"ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll"

Просмотреть файл

@ -2,15 +2,14 @@ import csharp
import semmle.code.csharp.controlflow.internal.Completion
import semmle.code.csharp.controlflow.internal.PreBasicBlocks
import ControlFlow
import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl
import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl::Consistency
import semmle.code.csharp.controlflow.internal.Splitting
import Consistency
private predicate splitBB(ControlFlow::BasicBlock bb) {
exists(ControlFlow::Node first |
first = bb.getFirstNode() and
first.isJoin() and
strictcount(first.getAPredecessor().getElement()) = 1
strictcount(first.getAPredecessor().getAstNode()) = 1
)
}

Просмотреть файл

@ -10,7 +10,7 @@ private class MyConsistencyConfiguration extends ConsistencyConfiguration {
// TODO: Remove once static initializers are folded into the
// static constructors
exists(ControlFlow::Node cfn |
cfn.getElement() = any(FieldOrProperty f | f.isStatic()).getAChild+() and
cfn.getAstNode() = any(FieldOrProperty f | f.isStatic()).getAChild+() and
cfn = n.getControlFlowNode()
)
}
@ -19,7 +19,7 @@ private class MyConsistencyConfiguration extends ConsistencyConfiguration {
// TODO: Remove once static initializers are folded into the
// static constructors
exists(ControlFlow::Node cfn |
cfn.getElement() = any(FieldOrProperty f | f.isStatic()).getAChild+() and
cfn.getAstNode() = any(FieldOrProperty f | f.isStatic()).getAChild+() and
cfn = call.getControlFlowNode()
)
}

Просмотреть файл

@ -6,6 +6,7 @@ extractor: csharp
library: true
upgrades: upgrades
dependencies:
codeql/controlflow: ${workspace}
codeql/dataflow: ${workspace}
codeql/mad: ${workspace}
codeql/ssa: ${workspace}

Просмотреть файл

@ -1,12 +1,9 @@
/** Provides classes for assertions. */
private import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl
private import semmle.code.csharp.frameworks.system.Diagnostics
private import semmle.code.csharp.frameworks.system.diagnostics.Contracts
private import semmle.code.csharp.frameworks.test.VisualStudio
private import semmle.code.csharp.frameworks.System
private import ControlFlow
private import ControlFlow::BasicBlocks
private newtype TAssertionFailure =
TExceptionAssertionFailure(Class c) or

Просмотреть файл

@ -400,13 +400,13 @@ class ExitBasicBlock extends BasicBlock {
private module JoinBlockPredecessors {
private import ControlFlow::Nodes
private import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl
private import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl as Impl
int getId(JoinBlockPredecessor jbp) {
exists(ControlFlowTree::Range_ t | ControlFlowTree::idOf(t, result) |
t = jbp.getFirstNode().getElement()
exists(Impl::AstNode n | result = n.getId() |
n = jbp.getFirstNode().getAstNode()
or
t = jbp.(EntryBasicBlock).getCallable()
n = jbp.(EntryBasicBlock).getCallable()
)
}

Просмотреть файл

@ -7,7 +7,7 @@ private import ControlFlow
private import ControlFlow::BasicBlocks
private import SuccessorTypes
private import semmle.code.csharp.Caching
private import internal.ControlFlowGraphImpl
private import internal.ControlFlowGraphImpl as Impl
/**
* A program element that can possess control flow. That is, either a statement or
@ -39,20 +39,20 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element {
* several `ControlFlow::Node`s, for example to represent the continuation
* flow in a `try/catch/finally` construction.
*/
Nodes::ElementNode getAControlFlowNode() { result.getElement() = this }
Nodes::ElementNode getAControlFlowNode() { result.getAstNode() = this }
/**
* Gets a first control flow node executed within this element.
*/
Nodes::ElementNode getAControlFlowEntryNode() {
result = getAControlFlowEntryNode(this).getAControlFlowNode()
result = Impl::getAControlFlowEntryNode(this).(ControlFlowElement).getAControlFlowNode()
}
/**
* Gets a potential last control flow node executed within this element.
*/
Nodes::ElementNode getAControlFlowExitNode() {
result = getAControlFlowExitNode(this).getAControlFlowNode()
result = Impl::getAControlFlowExitNode(this).(ControlFlowElement).getAControlFlowNode()
}
/**
@ -88,7 +88,7 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element {
) {
// Only calculate dominance by explicit recursion for split nodes;
// all other nodes can use regular CFG dominance
this instanceof SplitControlFlowElement and
this instanceof Impl::SplitAstNode and
cb.getLastNode() = this.getAControlFlowNode() and
succ = cb.getASuccessorByType(s)
}
@ -111,7 +111,7 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element {
succ.dominates(pred)
or
// `pred` might be another split of this element
pred.getLastNode().getElement() = this and
pred.getLastNode().getAstNode() = this and
t = s
)
}

Просмотреть файл

@ -7,7 +7,7 @@ module ControlFlow {
private import semmle.code.csharp.controlflow.BasicBlocks as BBs
import semmle.code.csharp.controlflow.internal.SuccessorType
private import SuccessorTypes
private import internal.ControlFlowGraphImpl
private import internal.ControlFlowGraphImpl as Impl
private import internal.Splitting as Splitting
/**
@ -25,18 +25,16 @@ module ControlFlow {
* Only nodes that can be reached from the callable entry point are included in
* the CFG.
*/
class Node extends TCfgNode {
/** Gets a textual representation of this control flow node. */
string toString() { none() }
class Node extends Impl::Node {
/** Gets the control flow element that this node corresponds to, if any. */
ControlFlowElement getElement() { none() }
final ControlFlowElement getAstNode() { result = super.getAstNode() }
/** Gets the location of this control flow node. */
Location getLocation() { result = this.getElement().getLocation() }
/** Holds if this control flow node has conditional successors. */
predicate isCondition() { exists(this.getASuccessorByType(any(ConditionalSuccessor e))) }
/**
* DEPRECATED: Use `getAstNode` instead.
*
* Gets the control flow element that this node corresponds to, if any.
*/
deprecated ControlFlowElement getElement() { result = this.getAstNode() }
/** Gets the basic block that this control flow node belongs to. */
BasicBlock getBasicBlock() { result.getANode() = this }
@ -183,7 +181,7 @@ module ControlFlow {
}
/** Gets a successor node of a given type, if any. */
Node getASuccessorByType(SuccessorType t) { result = getASuccessor(this, t) }
Node getASuccessorByType(SuccessorType t) { result = this.getASuccessor(t) }
/** Gets an immediate successor, if any. */
Node getASuccessor() { result = this.getASuccessorByType(_) }
@ -234,80 +232,39 @@ module ControlFlow {
result = this.getASuccessorByType(any(BooleanSuccessor t | t.getValue() = false))
}
/** Holds if this node has more than one predecessor. */
predicate isJoin() { strictcount(this.getAPredecessor()) > 1 }
/** Holds if this node has more than one successor. */
predicate isBranch() { strictcount(this.getASuccessor()) > 1 }
/** Gets the enclosing callable of this control flow node. */
final Callable getEnclosingCallable() { result = getNodeCfgScope(this) }
final Callable getEnclosingCallable() { result = Impl::getNodeCfgScope(this) }
}
/** Provides different types of control flow nodes. */
module Nodes {
/** A node for a callable entry point. */
class EntryNode extends Node, TEntryNode {
class EntryNode extends Node instanceof Impl::EntryNode {
/** Gets the callable that this entry applies to. */
Callable getCallable() { this = TEntryNode(result) }
Callable getCallable() { result = this.getScope() }
override BasicBlocks::EntryBlock getBasicBlock() { result = Node.super.getBasicBlock() }
private Assignable getAssignable() { this = TEntryNode(result) }
override Location getLocation() {
result in [this.getCallable().getLocation(), this.getAssignable().getLocation()]
}
override string toString() {
result = "enter " + [this.getCallable().toString(), this.getAssignable().toString()]
}
}
/** A node for a callable exit point, annotated with the type of exit. */
class AnnotatedExitNode extends Node, TAnnotatedExitNode {
private CfgScope scope;
private boolean normal;
AnnotatedExitNode() { this = TAnnotatedExitNode(scope, normal) }
class AnnotatedExitNode extends Node instanceof Impl::AnnotatedExitNode {
/** Holds if this node represent a normal exit. */
final predicate isNormal() { super.isNormal() }
/** Gets the callable that this exit applies to. */
CfgScope getCallable() { result = scope }
/** Holds if this node represents a normal exit. */
predicate isNormal() { normal = true }
Callable getCallable() { result = this.getScope() }
override BasicBlocks::AnnotatedExitBlock getBasicBlock() {
result = Node.super.getBasicBlock()
}
override Location getLocation() { result = scope.getLocation() }
override string toString() {
exists(string s |
normal = true and s = "normal"
or
normal = false and s = "abnormal"
|
result = "exit " + scope + " (" + s + ")"
)
}
}
/** A node for a callable exit point. */
class ExitNode extends Node, TExitNode {
private CfgScope scope;
ExitNode() { this = TExitNode(scope) }
class ExitNode extends Node instanceof Impl::ExitNode {
/** Gets the callable that this exit applies to. */
Callable getCallable() { result = scope }
Callable getCallable() { result = this.getScope() }
override BasicBlocks::ExitBlock getBasicBlock() { result = Node.super.getBasicBlock() }
override Location getLocation() { result = scope.getLocation() }
override string toString() { result = "exit " + scope }
}
/**
@ -317,35 +274,19 @@ module ControlFlow {
* the element is in unreachable (dead) code, and multiple when there are
* different splits for the element.
*/
class ElementNode extends Node, TElementNode {
private Splits splits;
private ControlFlowElement cfe;
ElementNode() { this = TElementNode(_, cfe, splits) }
override ControlFlowElement getElement() { result = cfe }
override string toString() {
result = "[" + this.getSplitsString() + "] " + cfe.toString()
or
not exists(this.getSplitsString()) and result = cfe.toString()
}
class ElementNode extends Node instanceof Impl::AstCfgNode {
/** Gets a comma-separated list of strings for each split in this node, if any. */
string getSplitsString() {
result = splits.toString() and
result != ""
}
final string getSplitsString() { result = super.getSplitsString() }
/** Gets a split for this control flow node, if any. */
Split getASplit() { result = splits.getASplit() }
final Split getASplit() { result = super.getASplit() }
}
/** A control-flow node for an expression. */
class ExprNode extends ElementNode {
Expr e;
ExprNode() { e = unique(Expr e_ | e_ = this.getElement() | e_) }
ExprNode() { e = unique(Expr e_ | e_ = this.getAstNode() | e_) }
/** Gets the expression that this control-flow node belongs to. */
Expr getExpr() { result = e }

Просмотреть файл

@ -1946,7 +1946,7 @@ module Internal {
|
def =
guarded
.getElement()
.getAstNode()
.(AccessOrCallExpr)
.getAnSsaQualifier(guarded.getBasicBlock().getANode()) and
if v.isReferentialProperty()

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,69 +0,0 @@
private import csharp as CS
private import ControlFlowGraphImpl as Impl
private import Completion as Comp
private import Splitting as Splitting
private import SuccessorType as ST
private import semmle.code.csharp.Caching
class ControlFlowTreeBase = Impl::ControlFlowTree::Range;
class ControlFlowElement = CS::ControlFlowElement;
class Completion = Comp::Completion;
/**
* Hold if `c` represents normal evaluation of a statement or an
* expression.
*/
predicate completionIsNormal(Completion c) { c instanceof Comp::NormalCompletion }
/**
* Hold if `c` represents simple (normal) evaluation of a statement or an
* expression.
*/
predicate completionIsSimple(Completion c) { c instanceof Comp::SimpleCompletion }
/** Holds if `c` is a valid completion for `e`. */
predicate completionIsValidFor(Completion c, ControlFlowElement e) { c.isValidFor(e) }
class CfgScope = Impl::CfgScope;
/** Gets the CFG scope for `e`. */
CfgScope getCfgScope(ControlFlowElement e) {
Stages::ControlFlowStage::forceCachingInSameStage() and
result = e.getEnclosingCallable()
}
predicate scopeFirst = Impl::scopeFirst/2;
predicate scopeLast = Impl::scopeLast/3;
/** The maximum number of splits allowed for a given node. */
int maxSplits() { result = 5 }
class SplitKindBase = Splitting::TSplitKind;
class Split = Splitting::Split;
class SuccessorType = ST::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 ST::SuccessorTypes::NormalSuccessor
}
/** Holds if `t` is an abnormal exit type out of a callable. */
predicate isAbnormalExitType(SuccessorType t) {
t instanceof ST::SuccessorTypes::ExceptionSuccessor or
t instanceof ST::SuccessorTypes::ExitSuccessor
}
class Location = CS::Location;
class Node = CS::ControlFlow::Node;

Просмотреть файл

@ -12,7 +12,7 @@
import csharp
private import Completion
private import ControlFlowGraphImpl
private import semmle.code.csharp.controlflow.ControlFlowGraph::ControlFlow
private import semmle.code.csharp.controlflow.ControlFlowGraph::ControlFlow as Cfg
private predicate startsBB(ControlFlowElement cfe) {
not succ(_, cfe, _) and
@ -55,7 +55,7 @@ private predicate bbIDominates(PreBasicBlock dom, PreBasicBlock bb) =
class PreBasicBlock extends ControlFlowElement {
PreBasicBlock() { startsBB(this) }
PreBasicBlock getASuccessorByType(SuccessorType t) {
PreBasicBlock getASuccessorByType(Cfg::SuccessorType t) {
succ(this.getLastElement(), result, any(Completion c | t = c.getAMatchingSuccessorType()))
}
@ -116,7 +116,7 @@ class ConditionBlock extends PreBasicBlock {
}
pragma[nomagic]
predicate controls(PreBasicBlock controlled, SuccessorTypes::ConditionalSuccessor s) {
predicate controls(PreBasicBlock controlled, Cfg::SuccessorTypes::ConditionalSuccessor s) {
exists(PreBasicBlock succ, ConditionalCompletion c | this.immediatelyControls(succ, c) |
succ.dominates(controlled) and
s = c.getAMatchingSuccessorType()

Просмотреть файл

@ -7,8 +7,7 @@
import csharp
private import Completion
private import ControlFlowGraphImpl
private import SuccessorTypes
private import semmle.code.csharp.controlflow.ControlFlowGraph::ControlFlow
private import semmle.code.csharp.controlflow.ControlFlowGraph::ControlFlow as Cfg
private import semmle.code.csharp.controlflow.internal.PreSsa
cached
@ -83,7 +82,7 @@ module InitializerSplitting {
* Gets a control flow element that is a syntactic descendant of the
* initializer expression.
*/
ControlFlowElement getAnInitializerDescendant() {
AstNode getAnInitializerDescendant() {
result = this.getInitializer()
or
result = this.getAnInitializerDescendant().getAChild()
@ -193,49 +192,49 @@ module InitializerSplitting {
private class InitializerSplitKind extends SplitKind, TInitializerSplitKind {
override int getListOrder() { result = 0 }
override predicate isEnabled(ControlFlowElement cfe) { this.appliesTo(cfe) }
override predicate isEnabled(AstNode cfe) { this.appliesTo(cfe) }
override string toString() { result = "Initializer" }
}
int getNextListOrder() { result = 1 }
private class InitializerSplitImpl extends SplitImpl, InitializerSplit {
private class InitializerSplitImpl extends SplitImpl instanceof InitializerSplit {
override InitializerSplitKind getKind() { any() }
override predicate hasEntry(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
override predicate hasEntry(AstNode pred, AstNode succ, Completion c) {
exists(ConstructorInitializer ci |
last(ci, pred, c) and
succ(pred, succ, c) and
succ = any(InitializedInstanceMember m).getAnInitializerDescendant() and
this.getConstructor() = ci.getConstructor()
super.getConstructor() = ci.getConstructor()
)
}
override predicate hasEntryScope(CfgScope scope, ControlFlowElement first) {
override predicate hasEntryScope(CfgScope scope, AstNode first) {
scopeFirst(scope, first) and
scope = this.getConstructor() and
scope = super.getConstructor() and
first = any(InitializedInstanceMember m).getAnInitializerDescendant()
}
override predicate hasExit(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
override predicate hasExit(AstNode pred, AstNode succ, Completion c) {
this.appliesTo(pred) and
succ(pred, succ, c) and
not succ = any(InitializedInstanceMember m).getAnInitializerDescendant() and
succ.getEnclosingCallable() = this.getConstructor()
succ.(ControlFlowElement).getEnclosingCallable() = super.getConstructor()
}
override predicate hasExitScope(CfgScope scope, ControlFlowElement last, Completion c) {
override predicate hasExitScope(CfgScope scope, AstNode last, Completion c) {
this.appliesTo(last) and
scopeLast(scope, last, c) and
scope = this.getConstructor()
scope = super.getConstructor()
}
override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
override predicate hasSuccessor(AstNode pred, AstNode succ, Completion c) {
this.appliesSucc(pred, succ, c) and
succ =
any(InitializedInstanceMember m |
constructorInitializes(this.getConstructor(), m.getInitializer())
constructorInitializes(super.getConstructor(), m.getInitializer())
).getAnInitializerDescendant()
}
}
@ -267,17 +266,22 @@ module ConditionalCompletionSplitting {
private class ConditionalCompletionSplitKind extends SplitKind, TConditionalCompletionSplitKind {
override int getListOrder() { result = InitializerSplitting::getNextListOrder() }
override predicate isEnabled(ControlFlowElement cfe) { this.appliesTo(cfe) }
override predicate isEnabled(AstNode cfe) { this.appliesTo(cfe) }
override string toString() { result = "ConditionalCompletion" }
}
int getNextListOrder() { result = InitializerSplitting::getNextListOrder() + 1 }
private class ConditionalCompletionSplitImpl extends SplitImpl, ConditionalCompletionSplit {
private class ConditionalCompletionSplitImpl extends SplitImpl instanceof ConditionalCompletionSplit
{
ConditionalCompletion completion;
ConditionalCompletionSplitImpl() { this = TConditionalCompletionSplit(completion) }
override ConditionalCompletionSplitKind getKind() { any() }
override predicate hasEntry(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
override predicate hasEntry(AstNode pred, AstNode succ, Completion c) {
succ(pred, succ, c) and
last(succ, _, completion) and
(
@ -334,23 +338,21 @@ module ConditionalCompletionSplitting {
)
}
override predicate hasEntryScope(CfgScope scope, ControlFlowElement first) { none() }
override predicate hasEntryScope(CfgScope scope, AstNode first) { none() }
override predicate hasExit(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
override predicate hasExit(AstNode pred, AstNode succ, Completion c) {
this.appliesTo(pred) and
succ(pred, succ, c) and
if c instanceof ConditionalCompletion then completion = c else any()
}
override predicate hasExitScope(CfgScope scope, ControlFlowElement last, Completion c) {
override predicate hasExitScope(CfgScope scope, AstNode last, Completion c) {
this.appliesTo(last) and
scopeLast(scope, last, c) and
if c instanceof ConditionalCompletion then completion = c else any()
}
override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
none()
}
override predicate hasSuccessor(AstNode pred, AstNode succ, Completion c) { none() }
}
}
@ -358,7 +360,7 @@ module AssertionSplitting {
import semmle.code.csharp.commons.Assertions
private import semmle.code.csharp.ExprOrStmtParent
private ControlFlowElement getAnAssertionDescendant(Assertion a) {
private AstNode getAnAssertionDescendant(Assertion a) {
result = a
or
result = getAnAssertionDescendant(a).getAChild()
@ -401,17 +403,23 @@ module AssertionSplitting {
private class AssertionSplitKind extends SplitKind, TAssertionSplitKind {
override int getListOrder() { result = ConditionalCompletionSplitting::getNextListOrder() }
override predicate isEnabled(ControlFlowElement cfe) { this.appliesTo(cfe) }
override predicate isEnabled(AstNode cfe) { this.appliesTo(cfe) }
override string toString() { result = "Assertion" }
}
int getNextListOrder() { result = ConditionalCompletionSplitting::getNextListOrder() + 1 }
private class AssertionSplitImpl extends SplitImpl, AssertionSplit {
private class AssertionSplitImpl extends SplitImpl instanceof AssertionSplit {
Assertion a;
boolean success;
int i;
AssertionSplitImpl() { this = TAssertionSplit(a, i, success) }
override AssertionSplitKind getKind() { any() }
override predicate hasEntry(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
override predicate hasEntry(AstNode pred, AstNode succ, Completion c) {
exists(AssertMethod m |
last(a.getExpr(i), pred, c) and
succ(pred, succ, c) and
@ -440,9 +448,9 @@ module AssertionSplitting {
)
}
override predicate hasEntryScope(CfgScope scope, ControlFlowElement first) { none() }
override predicate hasEntryScope(CfgScope scope, AstNode first) { none() }
override predicate hasExit(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
override predicate hasExit(AstNode pred, AstNode succ, Completion c) {
this.appliesTo(pred) and
pred = a and
succ(pred, succ, c) and
@ -455,7 +463,7 @@ module AssertionSplitting {
)
}
override predicate hasExitScope(CfgScope scope, ControlFlowElement last, Completion c) {
override predicate hasExitScope(CfgScope scope, AstNode last, Completion c) {
this.appliesTo(last) and
last = a and
scopeLast(scope, last, c) and
@ -468,7 +476,7 @@ module AssertionSplitting {
)
}
override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
override predicate hasSuccessor(AstNode pred, AstNode succ, Completion c) {
this.appliesSucc(pred, succ, c) and
succ = getAnAssertionDescendant(a)
}
@ -484,8 +492,8 @@ module FinallySplitting {
* then the `finally` block must end with a `return` as well (provided that
* the `finally` block exits normally).
*/
class FinallySplitType extends SuccessorType {
FinallySplitType() { not this instanceof ConditionalSuccessor }
class FinallySplitType extends Cfg::SuccessorType {
FinallySplitType() { not this instanceof Cfg::SuccessorTypes::ConditionalSuccessor }
/** Holds if this split type matches entry into a `finally` block with completion `c`. */
predicate isSplitForEntryCompletion(Completion c) {
@ -493,22 +501,22 @@ module FinallySplitting {
then
// If the entry into the `finally` block completes with any normal completion,
// it simply means normal execution after the `finally` block
this instanceof NormalSuccessor
this instanceof Cfg::SuccessorTypes::NormalSuccessor
else this = c.getAMatchingSuccessorType()
}
}
/** A control flow element that belongs to a `finally` block. */
private class FinallyControlFlowElement extends ControlFlowElement {
private class FinallyAstNode extends AstNode {
private Statements::TryStmtTree try;
FinallyControlFlowElement() { this = try.getAFinallyDescendant() }
FinallyAstNode() { this = try.getAFinallyDescendant() }
/** Gets the immediate `try` block that this node belongs to. */
Statements::TryStmtTree getTryStmt() { result = try }
/** Holds if this node is the entry node in the `finally` block it belongs to. */
predicate isEntryNode() { first(try.getFinally(), this) }
predicate isEntryNode() { first(try.(TryStmt).getFinally(), this) }
}
/**
@ -547,7 +555,7 @@ module FinallySplitting {
int getNestLevel() { result = nestLevel }
override string toString() {
if type instanceof NormalSuccessor
if type instanceof Cfg::SuccessorTypes::NormalSuccessor
then result = ""
else
if nestLevel > 0
@ -577,38 +585,34 @@ module FinallySplitting {
override string toString() { result = "Finally (" + nestLevel + ")" }
}
pragma[noinline]
private predicate hasEntry0(
ControlFlowElement pred, FinallyControlFlowElement succ, int nestLevel, Completion c
) {
pragma[nomagic]
private predicate hasEntry0(AstNode pred, FinallyAstNode succ, int nestLevel, Completion c) {
succ.isEntryNode() and
nestLevel = succ.getTryStmt().nestLevel() and
succ(pred, succ, c)
}
private class FinallySplitImpl extends SplitImpl, FinallySplit {
override FinallySplitKind getKind() { result.getNestLevel() = this.getNestLevel() }
private class FinallySplitImpl extends SplitImpl instanceof FinallySplit {
override FinallySplitKind getKind() { result.getNestLevel() = super.getNestLevel() }
override predicate hasEntry(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
hasEntry0(pred, succ, this.getNestLevel(), c) and
this.getType().isSplitForEntryCompletion(c)
override predicate hasEntry(AstNode pred, AstNode succ, Completion c) {
hasEntry0(pred, succ, super.getNestLevel(), c) and
super.getType().isSplitForEntryCompletion(c)
}
override predicate hasEntryScope(CfgScope scope, ControlFlowElement first) { none() }
override predicate hasEntryScope(CfgScope scope, AstNode first) { none() }
/**
* Holds if this split applies to control flow element `pred`, where `pred`
* is a valid predecessor.
*/
private predicate appliesToPredecessor(ControlFlowElement pred) {
private predicate appliesToPredecessor(AstNode pred) {
this.appliesTo(pred) and
(succ(pred, _, _) or scopeLast(_, pred, _))
}
pragma[noinline]
private predicate exit0(
ControlFlowElement pred, Statements::TryStmtTree try, int nestLevel, Completion c
) {
private predicate exit0(AstNode pred, Statements::TryStmtTree try, int nestLevel, Completion c) {
this.appliesToPredecessor(pred) and
nestLevel = try.nestLevel() and
last(try, pred, c)
@ -619,10 +623,10 @@ module FinallySplitting {
* `inherited` indicates whether `c` is an inherited completion from a `try`/
* `catch` block.
*/
private predicate exit(ControlFlowElement pred, Completion c, boolean inherited) {
private predicate exit(AstNode pred, Completion c, boolean inherited) {
exists(TryStmt try, FinallySplitType type |
this.exit0(pred, try, this.getNestLevel(), c) and
type = this.getType()
this.exit0(pred, try, super.getNestLevel(), c) and
type = super.getType()
|
if last(try.getFinally(), pred, c)
then
@ -635,14 +639,14 @@ module FinallySplitting {
or
not c instanceof NormalCompletion
or
type instanceof NormalSuccessor
type instanceof Cfg::SuccessorTypes::NormalSuccessor
)
else (
// Finally block can exit with completion `c` inherited from try/catch
// block: must match this split
inherited = true and
type = c.getAMatchingSuccessorType() and
not type instanceof NormalSuccessor
not type instanceof Cfg::SuccessorTypes::NormalSuccessor
)
)
or
@ -672,15 +676,15 @@ module FinallySplitting {
// is "normal" (corresponding to `b1 = true` and `b2 = false`), then the inner
// split must be able to exit with an `ExceptionA` completion.
this.appliesToPredecessor(pred) and
exists(FinallySplitImpl outer |
outer.getNestLevel() = this.getNestLevel() - 1 and
outer.exit(pred, c, inherited) and
this.getType() instanceof NormalSuccessor and
exists(FinallySplit outer |
outer.getNestLevel() = super.getNestLevel() - 1 and
outer.(FinallySplitImpl).exit(pred, c, inherited) and
super.getType() instanceof Cfg::SuccessorTypes::NormalSuccessor and
inherited = true
)
}
override predicate hasExit(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
override predicate hasExit(AstNode pred, AstNode succ, Completion c) {
succ(pred, succ, c) and
(
this.exit(pred, c, _)
@ -689,7 +693,7 @@ module FinallySplitting {
)
}
override predicate hasExitScope(CfgScope scope, ControlFlowElement last, Completion c) {
override predicate hasExitScope(CfgScope scope, AstNode last, Completion c) {
scopeLast(scope, last, c) and
(
this.exit(last, c, _)
@ -698,17 +702,17 @@ module FinallySplitting {
)
}
override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
override predicate hasSuccessor(AstNode pred, AstNode succ, Completion c) {
this.appliesSucc(pred, succ, c) and
succ =
any(FinallyControlFlowElement fcfe |
any(FinallyAstNode fcfe |
if fcfe.isEntryNode()
then
// entering a nested `finally` block
fcfe.getTryStmt().nestLevel() > this.getNestLevel()
fcfe.getTryStmt().nestLevel() > super.getNestLevel()
else
// staying in the same (possibly nested) `finally` block as `pred`
fcfe.getTryStmt().nestLevel() >= this.getNestLevel()
fcfe.getTryStmt().nestLevel() >= super.getNestLevel()
)
}
}
@ -774,20 +778,20 @@ module ExceptionHandlerSplitting {
int getNextListOrder() { result = FinallySplitting::getNextListOrder() + 1 }
private class ExceptionHandlerSplitImpl extends SplitImpl, ExceptionHandlerSplit {
private class ExceptionHandlerSplitImpl extends SplitImpl instanceof ExceptionHandlerSplit {
override ExceptionHandlerSplitKind getKind() { any() }
override predicate hasEntry(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
override predicate hasEntry(AstNode pred, AstNode succ, Completion c) {
// Entry into first catch clause
exists(Statements::TryStmtTree ts |
this.getExceptionClass() = ts.getAThrownException(pred, c)
super.getExceptionClass() = ts.getAThrownException(pred, c)
|
succ(pred, succ, c) and
succ = ts.getCatchClause(0).(SpecificCatchClause)
succ = ts.(TryStmt).getCatchClause(0).(SpecificCatchClause)
)
}
override predicate hasEntryScope(CfgScope scope, ControlFlowElement first) { none() }
override predicate hasEntryScope(CfgScope scope, AstNode first) { none() }
/**
* Holds if this split applies to catch clause `scc`. The parameter `match`
@ -796,9 +800,9 @@ module ExceptionHandlerSplitting {
*/
private predicate appliesToCatchClause(SpecificCatchClause scc, TMatch match) {
exists(Statements::TryStmtTree ts, ExceptionClass ec |
ec = this.getExceptionClass() and
ec = super.getExceptionClass() and
ec = ts.getAThrownException(_, _) and
scc = ts.getACatchClause()
scc = ts.(TryStmt).getACatchClause()
|
if scc.getCaughtExceptionType() = ec.getABaseType*()
then match = TAlways()
@ -813,7 +817,7 @@ module ExceptionHandlerSplitting {
* Holds if this split applies to control flow element `pred`, where `pred`
* is a valid predecessor with completion `c`.
*/
private predicate appliesToPredecessor(ControlFlowElement pred, Completion c) {
private predicate appliesToPredecessor(AstNode pred, Completion c) {
this.appliesTo(pred) and
(succ(pred, _, c) or scopeLast(_, pred, c)) and
(
@ -843,18 +847,18 @@ module ExceptionHandlerSplitting {
* with throw completion `c`, because it belongs to the last `catch` clause
* in a `try` statement.
*/
private predicate hasLastExit(ControlFlowElement pred, ThrowCompletion c) {
private predicate hasLastExit(AstNode pred, ThrowCompletion c) {
this.appliesToPredecessor(pred, c) and
exists(TryStmt ts, SpecificCatchClause scc, int last |
last(ts.getCatchClause(last), pred, c)
|
ts.getCatchClause(last) = scc and
scc.isLast() and
c.getExceptionClass() = this.getExceptionClass()
c.getExceptionClass() = super.getExceptionClass()
)
}
override predicate hasExit(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
override predicate hasExit(AstNode pred, AstNode succ, Completion c) {
this.appliesToPredecessor(pred, c) and
succ(pred, succ, c) and
(
@ -869,13 +873,13 @@ module ExceptionHandlerSplitting {
)
}
override predicate hasExitScope(CfgScope scope, ControlFlowElement last, Completion c) {
override predicate hasExitScope(CfgScope scope, AstNode last, Completion c) {
// Exit out from last `catch` clause (no catch clauses match)
this.hasLastExit(last, c) and
scopeLast(scope, last, c)
}
override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
override predicate hasSuccessor(AstNode pred, AstNode succ, Completion c) {
this.appliesToPredecessor(pred, c) and
this.appliesSucc(pred, succ, c) and
not first(any(SpecificCatchClause scc).getBlock(), succ) and
@ -916,7 +920,7 @@ module BooleanSplitting {
abstract predicate correlatesConditions(ConditionBlock cb1, ConditionBlock cb2, boolean inverted);
/** Holds if control flow element `cfe` starts a split of this kind. */
predicate startsSplit(ControlFlowElement cfe) {
predicate startsSplit(AstNode cfe) {
this.correlatesConditions(any(ConditionBlock cb | cb.getLastElement() = cfe), _, _)
}
@ -1078,27 +1082,26 @@ module BooleanSplitting {
override string toString() { result = kind.toString() }
}
pragma[noinline]
pragma[nomagic]
private predicate hasEntry0(
ControlFlowElement pred, ControlFlowElement succ, BooleanSplitSubKind kind, boolean b,
Completion c
AstNode pred, AstNode succ, BooleanSplitSubKind kind, boolean b, Completion c
) {
kind.startsSplit(pred) and
succ(pred, succ, c) and
b = c.getInnerCompletion().(BooleanCompletion).getValue()
}
private class BooleanSplitImpl extends SplitImpl, BooleanSplit {
override BooleanSplitKind getKind() { result.getSubKind() = this.getSubKind() }
private class BooleanSplitImpl extends SplitImpl instanceof BooleanSplit {
override BooleanSplitKind getKind() { result.getSubKind() = super.getSubKind() }
override predicate hasEntry(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
hasEntry0(pred, succ, this.getSubKind(), this.getBranch(), c)
override predicate hasEntry(AstNode pred, AstNode succ, Completion c) {
hasEntry0(pred, succ, super.getSubKind(), super.getBranch(), c)
}
override predicate hasEntryScope(CfgScope scope, ControlFlowElement first) { none() }
override predicate hasEntryScope(CfgScope scope, AstNode first) { none() }
private ConditionBlock getACorrelatedCondition(boolean inverted) {
this.getSubKind().correlatesConditions(_, result, inverted)
super.getSubKind().correlatesConditions(_, result, inverted)
}
/**
@ -1107,35 +1110,35 @@ module BooleanSplitting {
*/
private predicate appliesToBlock(PreBasicBlock bb, Completion c) {
this.appliesTo(bb) and
exists(ControlFlowElement last | last = bb.getLastElement() |
exists(AstNode last | last = bb.getLastElement() |
(succ(last, _, c) or scopeLast(_, last, c)) and
// Respect the value recorded in this split for all correlated conditions
forall(boolean inverted | bb = this.getACorrelatedCondition(inverted) |
c.getInnerCompletion() instanceof BooleanCompletion
implies
c.getInnerCompletion().(BooleanCompletion).getValue() =
this.getBranch().booleanXor(inverted)
super.getBranch().booleanXor(inverted)
)
)
}
override predicate hasExit(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
override predicate hasExit(AstNode pred, AstNode succ, Completion c) {
exists(PreBasicBlock bb | this.appliesToBlock(bb, c) |
pred = bb.getLastElement() and
succ(pred, succ, c) and
// Exit this split if we can no longer reach a correlated condition
not this.getSubKind().canReachCorrelatedCondition(succ)
not super.getSubKind().canReachCorrelatedCondition(succ)
)
}
override predicate hasExitScope(CfgScope scope, ControlFlowElement last, Completion c) {
override predicate hasExitScope(CfgScope scope, AstNode last, Completion c) {
exists(PreBasicBlock bb | this.appliesToBlock(bb, c) |
last = bb.getLastElement() and
scopeLast(scope, last, c)
)
}
override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
override predicate hasSuccessor(AstNode pred, AstNode succ, Completion c) {
exists(PreBasicBlock bb, Completion c0 | this.appliesToBlock(bb, c0) |
pred = bb.getAnElement() and
this.appliesSucc(pred, succ, c) and
@ -1144,7 +1147,7 @@ module BooleanSplitting {
implies
(
// We must still be able to reach a correlated condition to stay in this split
this.getSubKind().canReachCorrelatedCondition(succ) and
super.getSubKind().canReachCorrelatedCondition(succ) and
c = c0
)
)
@ -1174,15 +1177,15 @@ module LoopSplitting {
*/
abstract class AnalyzableLoopStmt extends LoopStmt {
/** Holds if the step `pred --c--> succ` should start the split. */
abstract predicate start(ControlFlowElement pred, ControlFlowElement succ, Completion c);
abstract predicate start(AstNode pred, AstNode succ, Completion c);
/** Holds if the step `pred --c--> succ` should stop the split. */
abstract predicate stop(ControlFlowElement pred, ControlFlowElement succ, Completion c);
abstract predicate stop(AstNode pred, AstNode succ, Completion c);
/**
* Holds if any step `pred --c--> _` should be pruned from the control flow graph.
*/
abstract predicate pruneLoopCondition(ControlFlowElement pred, ConditionalCompletion c);
abstract predicate pruneLoopCondition(AstNode pred, ConditionalCompletion c);
/**
* Holds if the body is guaranteed to be executed at least once. If not, the
@ -1219,17 +1222,17 @@ module LoopSplitting {
)
}
override predicate start(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
override predicate start(AstNode pred, AstNode succ, Completion c) {
last(this.getIterableExpr(), pred, c) and
succ = this
}
override predicate stop(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
override predicate stop(AstNode pred, AstNode succ, Completion c) {
pred = this and
succ(pred, succ, c)
}
override predicate pruneLoopCondition(ControlFlowElement pred, ConditionalCompletion c) {
override predicate pruneLoopCondition(AstNode pred, ConditionalCompletion c) {
pred = this and
c = any(EmptinessCompletion ec | if v.isEmpty() then not ec.isEmpty() else ec.isEmpty())
}
@ -1298,36 +1301,40 @@ module LoopSplitting {
override string toString() { result = "Unroll" }
}
private class LoopUnrollingSplitImpl extends SplitImpl, LoopSplit {
private class LoopUnrollingSplitImpl extends SplitImpl instanceof LoopSplit {
AnalyzableLoopStmt loop;
LoopUnrollingSplitImpl() { this = TLoopSplit(loop) }
override LoopSplitKind getKind() { result = TLoopSplitKind(loop) }
override predicate hasEntry(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
override predicate hasEntry(AstNode pred, AstNode succ, Completion c) {
loop.start(pred, succ, c)
}
override predicate hasEntryScope(CfgScope scope, ControlFlowElement first) { none() }
override predicate hasEntryScope(CfgScope scope, AstNode first) { none() }
/**
* Holds if this split applies to control flow element `pred`, where `pred`
* is a valid predecessor.
*/
private predicate appliesToPredecessor(ControlFlowElement pred, Completion c) {
private predicate appliesToPredecessor(AstNode pred, Completion c) {
this.appliesTo(pred) and
(succ(pred, _, c) or scopeLast(_, pred, c)) and
not loop.pruneLoopCondition(pred, c)
}
override predicate hasExit(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
override predicate hasExit(AstNode pred, AstNode succ, Completion c) {
this.appliesToPredecessor(pred, c) and
loop.stop(pred, succ, c)
}
override predicate hasExitScope(CfgScope scope, ControlFlowElement last, Completion c) {
override predicate hasExitScope(CfgScope scope, AstNode last, Completion c) {
this.appliesToPredecessor(last, c) and
scopeLast(scope, last, c)
}
override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
override predicate hasSuccessor(AstNode pred, AstNode succ, Completion c) {
this.appliesToPredecessor(pred, c) and
this.appliesSucc(pred, succ, c) and
not loop.stop(pred, succ, c)

Просмотреть файл

@ -411,7 +411,7 @@ module Ssa {
* This is either an expression, for example `x = 0`, a parameter, or a
* callable. Phi nodes have no associated syntax element.
*/
Element getElement() { result = this.getControlFlowNode().getElement() }
Element getElement() { result = this.getControlFlowNode().getAstNode() }
/** Gets the callable to which this SSA definition belongs. */
final Callable getEnclosingCallable() {

Просмотреть файл

@ -24,11 +24,11 @@ private ControlFlowElement getANonExactScopeChild(ControlFlowScope scope) {
pragma[noinline]
private ControlFlow::BasicBlock getABasicBlockInScope(ControlFlowScope scope, boolean exactScope) {
result.getANode().getElement() = getANonExactScopeChild(scope) and
result.getANode().getAstNode() = getANonExactScopeChild(scope) and
exactScope = false
or
scope.isExact() and
result.getANode().getElement() = scope and
result.getANode().getAstNode() = scope and
exactScope = true
}

Просмотреть файл

@ -104,10 +104,10 @@ private module Cached {
newtype TDataFlowCall =
TNonDelegateCall(ControlFlow::Nodes::ElementNode cfn, DispatchCall dc) {
DataFlowImplCommon::forceCachingInSameStage() and
cfn.getElement() = dc.getCall()
cfn.getAstNode() = dc.getCall()
} or
TExplicitDelegateLikeCall(ControlFlow::Nodes::ElementNode cfn, DelegateLikeCall dc) {
cfn.getElement() = dc
cfn.getAstNode() = dc
} or
TTransitiveCapturedCall(ControlFlow::Nodes::ElementNode cfn, Callable target) {
transitiveCapturedCallTarget(cfn, target)

Просмотреть файл

@ -819,7 +819,7 @@ private module Cached {
cached
newtype TNode =
TExprNode(ControlFlow::Nodes::ElementNode cfn) { cfn.getElement() instanceof Expr } or
TExprNode(ControlFlow::Nodes::ElementNode cfn) { cfn.getAstNode() instanceof Expr } or
TCilExprNode(CIL::Expr e) { e.getImplementation() instanceof CIL::BestImplementation } or
TCilSsaDefinitionExtNode(CilSsaImpl::DefinitionExt def) or
TSsaDefinitionExtNode(SsaImpl::DefinitionExt def) {
@ -835,19 +835,19 @@ private module Cached {
not c.(Modifiable).isStatic()
} or
TYieldReturnNode(ControlFlow::Nodes::ElementNode cfn) {
any(Callable c).canYieldReturn(cfn.getElement())
any(Callable c).canYieldReturn(cfn.getAstNode())
} or
TAsyncReturnNode(ControlFlow::Nodes::ElementNode cfn) {
any(Callable c | c.(Modifiable).isAsync()).canReturn(cfn.getElement())
any(Callable c | c.(Modifiable).isAsync()).canReturn(cfn.getAstNode())
} or
TImplicitCapturedArgumentNode(ControlFlow::Nodes::ElementNode cfn, LocalScopeVariable v) {
exists(Ssa::ExplicitDefinition def | def.isCapturedVariableDefinitionFlowIn(_, cfn, _) |
v = def.getSourceVariable().getAssignable()
)
} or
TMallocNode(ControlFlow::Nodes::ElementNode cfn) { cfn.getElement() instanceof ObjectCreation } or
TMallocNode(ControlFlow::Nodes::ElementNode cfn) { cfn.getAstNode() instanceof ObjectCreation } or
TObjectInitializerNode(ControlFlow::Nodes::ElementNode cfn) {
cfn.getElement().(ObjectCreation).hasInitializer()
cfn.getAstNode().(ObjectCreation).hasInitializer()
} or
TExprPostUpdateNode(ControlFlow::Nodes::ExprNode cfn) {
cfn = LocalFlow::getAPostUpdateNodeForArg(_)
@ -1256,7 +1256,7 @@ private module ArgumentNodes {
result.asCallable() = cfn.getEnclosingCallable()
}
override Type getTypeImpl() { result = cfn.getElement().(Expr).getType() }
override Type getTypeImpl() { result = cfn.getAstNode().(Expr).getType() }
override Location getLocationImpl() { result = cfn.getLocation() }
@ -1397,7 +1397,7 @@ private module ReturnNodes {
private ControlFlow::Nodes::ElementNode cfn;
private Expr expr;
AsyncReturnNode() { this = TAsyncReturnNode(cfn) and expr = cfn.getElement() }
AsyncReturnNode() { this = TAsyncReturnNode(cfn) and expr = cfn.getAstNode() }
Expr getExpr() { result = expr }
@ -2106,7 +2106,7 @@ private module PostUpdateNodes {
result.asCallable() = cfn.getEnclosingCallable()
}
override Type getTypeImpl() { result = cfn.getElement().(Expr).getType() }
override Type getTypeImpl() { result = cfn.getAstNode().(Expr).getType() }
override ControlFlow::Node getControlFlowNodeImpl() { none() }

Просмотреть файл

@ -90,7 +90,7 @@ class ExprNode extends Node, TExprNode_ {
*/
Expr getExprAtNode(ControlFlow::Nodes::ElementNode cfn) {
this = TExprNode(cfn) and
result = cfn.getElement()
result = cfn.getAstNode()
}
}

Просмотреть файл

@ -71,7 +71,7 @@ module ExposedForTestingOnly {
* Holds if the `i`th node of basic block `bb` reads source variable `v`.
*/
private predicate variableReadActual(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v) {
v.getAnAccess().(AssignableRead) = bb.getNode(i).getElement()
v.getAnAccess().(AssignableRead) = bb.getNode(i).getAstNode()
}
private module SourceVariableImpl {
@ -939,7 +939,7 @@ private module CapturedVariableLivenessImpl {
CapturedReadLocalScopeVariable captured, Callable c, boolean libraryDelegateCall
) {
implicitReadCandidate(v, call) and
c = getARuntimeTarget(call.getElement(), libraryDelegateCall) and
c = getARuntimeTarget(call.getAstNode(), libraryDelegateCall) and
captured = v.getAssignable() and
capturerReads(_, captured)
}

Просмотреть файл

@ -24,11 +24,11 @@ private ControlFlowElement getANonExactScopeChild(ControlFlowScope scope) {
pragma[noinline]
private ControlFlow::BasicBlock getABasicBlockInScope(ControlFlowScope scope, boolean exactScope) {
result.getANode().getElement() = getANonExactScopeChild(scope) and
result.getANode().getAstNode() = getANonExactScopeChild(scope) and
exactScope = false
or
scope.isExact() and
result.getANode().getElement() = scope and
result.getANode().getAstNode() = scope and
exactScope = true
}

Просмотреть файл

@ -22,10 +22,10 @@ private class PhiInputEdgeBlock extends BasicBlock {
}
private int getId(PhiInputEdgeBlock bb) {
exists(CfgImpl::ControlFlowTree::Range_ t | CfgImpl::ControlFlowTree::idOf(t, result) |
t = bb.getFirstNode().getElement()
exists(CfgImpl::AstNode n | result = n.getId() |
n = bb.getFirstNode().getAstNode()
or
t = bb.(ControlFlow::BasicBlocks::EntryBlock).getCallable()
n = bb.(ControlFlow::BasicBlocks::EntryBlock).getCallable()
)
}

Просмотреть файл

@ -16,7 +16,7 @@
import csharp
predicate lockedFieldUpdate(LockStmt lock, Field f, AssignableDefinition def) {
lock.getAChild+() = def.getAControlFlowNode().getElement() and
lock.getAChild+() = def.getAControlFlowNode().getAstNode() and
def.getTarget() = f
}

Просмотреть файл

@ -28,7 +28,7 @@ ControlFlow::Node unlockedReachable(Callable a) {
result = a.getEntryPoint()
or
exists(ControlFlow::Node mid | mid = unlockedReachable(a) |
not mid.getElement() instanceof LockingCall and
not mid.getAstNode() instanceof LockingCall and
result = mid.getASuccessor()
)
}

Просмотреть файл

@ -81,20 +81,20 @@ class NestedForLoopSameVariable extends ForStmt {
/** Finds elements inside the outer loop that are no longer guarded by the loop invariant. */
private ControlFlow::Node getAnUnguardedNode() {
hasChild(this.getOuterForStmt().getBody(), result.getElement()) and
hasChild(this.getOuterForStmt().getBody(), result.getAstNode()) and
(
result =
this.getCondition().(ControlFlowElement).getAControlFlowExitNode().getAFalseSuccessor()
or
exists(ControlFlow::Node mid | mid = this.getAnUnguardedNode() |
mid.getASuccessor() = result and
not exists(this.getAComparisonTest(result.getElement()))
not exists(this.getAComparisonTest(result.getAstNode()))
)
)
}
private VariableAccess getAnUnguardedAccess() {
result = this.getAnUnguardedNode().getElement() and
result = this.getAnUnguardedNode().getAstNode() and
result.getTarget() = iteration
}
}

Просмотреть файл

@ -15,9 +15,9 @@ import csharp
// Iterate the control flow until we reach a Stmt
Stmt findSuccessorStmt(ControlFlow::Node n) {
result = n.getElement()
result = n.getAstNode()
or
not n.getElement() instanceof Stmt and result = findSuccessorStmt(n.getASuccessor())
not n.getAstNode() instanceof Stmt and result = findSuccessorStmt(n.getASuccessor())
}
// Return a successor statement to s

Просмотреть файл

@ -19,13 +19,13 @@ private predicate equalsMethodChild(EqualsMethod equals, Element child) {
}
predicate nodeBeforeParameterAccess(ControlFlow::Node node) {
exists(EqualsMethod equals | equals.getBody() = node.getElement())
exists(EqualsMethod equals | equals.getBody() = node.getAstNode())
or
exists(EqualsMethod equals, Parameter param, ControlFlow::Node mid |
equals.getParameter(0) = param and
equalsMethodChild(equals, mid.getElement()) and
equalsMethodChild(equals, mid.getAstNode()) and
nodeBeforeParameterAccess(mid) and
not param.getAnAccess() = mid.getElement() and
not param.getAnAccess() = mid.getAstNode() and
mid.getASuccessor() = node
)
}

Просмотреть файл

@ -58,16 +58,16 @@ predicate sessionUse(MemberAccess ma) {
/** A control flow step that is not sanitised by a call to clear the session. */
predicate controlStep(ControlFlow::Node s1, ControlFlow::Node s2) {
s2 = s1.getASuccessor() and
not sessionEndMethod(s2.getElement().(MethodCall).getTarget())
not sessionEndMethod(s2.getAstNode().(MethodCall).getTarget())
}
from
ControlFlow::Node loginCall, Method loginMethod, ControlFlow::Node sessionUse,
ControlFlow::SuccessorType fromLoginFlow
where
loginMethod = loginCall.getElement().(MethodCall).getTarget() and
loginMethod = loginCall.getAstNode().(MethodCall).getTarget() and
loginMethod(loginMethod, fromLoginFlow) and
sessionUse(sessionUse.getElement()) and
sessionUse(sessionUse.getAstNode()) and
controlStep+(loginCall.getASuccessorByType(fromLoginFlow), sessionUse)
select sessionUse, "This session has not been invalidated following the call to $@.", loginCall,
loginMethod.getName()

Просмотреть файл

@ -2,5 +2,5 @@ import csharp
query predicate deadCode(MethodCall c) {
c.getTarget().getName() = "DeadCode" and
not exists(ControlFlow::Node node | node.getElement() = c)
not exists(ControlFlow::Node node | node.getAstNode() = c)
}

Просмотреть файл

@ -4,6 +4,6 @@
import csharp
import Common
import semmle.code.csharp.controlflow.internal.ControlFlowGraphImplShared::TestOutput
import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl::TestOutput
private class MyRelevantNode extends RelevantNode, SourceControlFlowNode { }

Просмотреть файл

@ -1,7 +1,7 @@
import csharp
import ControlFlow
import Common
import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl
import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl as Impl
import semmle.code.csharp.controlflow.internal.Splitting as Splitting
import Nodes
@ -16,11 +16,11 @@ class MyFinallySplitControlFlowNode extends ElementNode {
)
}
Statements::TryStmtTree getTryStmt() { this.getElement() = result.getAFinallyDescendant() }
Impl::Statements::TryStmtTree getTryStmt() { this.getAstNode() = result.getAFinallyDescendant() }
}
query predicate finallyNode(MyFinallySplitControlFlowNode f, TryStmt try) { try = f.getTryStmt() }
query predicate entryPoint(Callable c, SourceControlFlowElement cfn) {
c.getEntryPoint().getASuccessor().getElement() = cfn
c.getEntryPoint().getASuccessor().getAstNode() = cfn
}

Просмотреть файл

@ -2,7 +2,7 @@ import csharp
query predicate countSplits(ControlFlowElement cfe, int i) {
not cfe.fromLibrary() and
i = strictcount(ControlFlow::Nodes::ElementNode n | n.getElement() = cfe)
i = strictcount(ControlFlow::Nodes::ElementNode n | n.getAstNode() = cfe)
}
query predicate ssaDef(Ssa::Definition def) { any() }

Просмотреть файл

@ -4,7 +4,7 @@ import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl
import semmle.code.csharp.dataflow.internal.SsaImpl as SsaImpl
class CallableWithSplitting extends Callable {
CallableWithSplitting() { this = any(SplitControlFlowElement e).getEnclosingCallable() }
CallableWithSplitting() { this = any(SplitAstNode n).getEnclosingCallable() }
}
query predicate defReadInconsistency(
@ -57,8 +57,8 @@ query predicate readReadInconsistency(
not PreSsa::adjacentReadPairSameVar(read1, read2) and
// Exclude split CFG elements because SSA may be more precise than pre-SSA
// in those cases
not read1 instanceof SplitControlFlowElement and
not read2 instanceof SplitControlFlowElement
not read1 instanceof SplitAstNode and
not read2 instanceof SplitAstNode
)
}
@ -78,7 +78,7 @@ query predicate phiInconsistency(
|
edef.getADefinition() = adef and
phi.definesAt(_, bb, _) and
cfe = bb.getFirstNode().getElement()
cfe = bb.getFirstNode().getAstNode()
)
)
or
@ -89,7 +89,7 @@ query predicate phiInconsistency(
edef = phi.getAnUltimateDefinition() and
edef.getADefinition() = adef and
phi.definesAt(_, bb, _) and
cfe = bb.getFirstNode().getElement() and
cfe = bb.getFirstNode().getAstNode() and
not exists(PreSsa::PhiNode prePhi |
adef = prePhi.getAnInput+().getDefinition() and
cfe = prePhi.getBasicBlock().getFirstElement()

Просмотреть файл

@ -1,7 +1,7 @@
import csharp
query predicate edges(ControlFlow::Node node, ControlFlow::Node successor, string attr, string val) {
not node.getElement().fromLibrary() and
not node.getAstNode().fromLibrary() and
exists(ControlFlow::SuccessorType t | successor = node.getASuccessorByType(t) |
attr = "semmle.label" and
val = t.toString()

Просмотреть файл

@ -12,5 +12,5 @@ class UnknownCall extends Call {
}
query predicate edges(ControlFlow::Node n1, ControlFlow::Node n2) {
not n1.getElement().fromLibrary() and n2 = n1.getASuccessor()
not n1.getAstNode().fromLibrary() and n2 = n1.getASuccessor()
}

Просмотреть файл

@ -937,23 +937,6 @@ module Make<LocationSig Location, InputSig<Location> Input> {
)
}
/**
* Gets the CFG scope of node `n`. Unlike `getCfgScope`, this predicate
* is calculated based on reachability from an entry node, and it may
* yield different results for AST elements that are split into multiple
* scopes.
*/
cached
CfgScope getNodeCfgScope(Node n) {
n = TEntryNode(result)
or
n = TAnnotatedExitNode(result, _)
or
n = TExitNode(result)
or
n = TAstNode(result, _, _)
}
cached
module Public {
/**
@ -974,6 +957,23 @@ module Make<LocationSig Location, InputSig<Location> Input> {
*/
cached
AstNode getAControlFlowExitNode(AstNode n) { last(n, result, _) }
/**
* Gets the CFG scope of node `n`. Unlike `getCfgScope`, this predicate
* is calculated based on reachability from an entry node, and it may
* yield different results for AST elements that are split into multiple
* scopes.
*/
cached
CfgScope getNodeCfgScope(Node n) {
n = TEntryNode(result)
or
n = TAnnotatedExitNode(result, _)
or
n = TExitNode(result)
or
n = TAstNode(result, _, _)
}
}
}