зеркало из https://github.com/github/codeql.git
C#: Adopt shared CFG construction library from shared `controlflow` pack
This commit is contained in:
Родитель
e011480114
Коммит
b69188fee9
|
@ -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, _, _)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче