Merge pull request #140 from hvitved/csharp/cfg/renaming

C#: Rename and restructure control flow graph entities
This commit is contained in:
calumgrant
2018-09-05 17:18:08 +01:00
committed by GitHub
48 changed files with 3379 additions and 3291 deletions

View File

@@ -40,4 +40,22 @@
## Changes to QL libraries
* A new non-member predicate `mayBeDisposed()` can be used to determine if a variable is potentially disposed inside a library. It will analyse the CIL code in the library to determine this.
* A new non-member predicate `mayBeDisposed()` can be used to determine if a variable is potentially disposed inside a library. It will analyse the CIL code in the library to determine this.
* Several control flow graph entities have been renamed (the old names still exist for backwards compatibility):
- `ControlFlowNode` has been renamed to `ControlFlow::Node`.
- `CallableEntryNode` has been renamed to `ControlFlow::Nodes::EntryNode`.
- `CallableExitNode` has been renamed to `ControlFlow::Nodes::ExitNode`.
- `ControlFlowEdgeType` has been renamed to `ControlFlow::SuccessorType`.
- `ControlFlowEdgeSuccessor` has been renamed to `ControlFlow::SuccessorTypes::NormalSuccessor`.
- `ControlFlowEdgeConditional` has been renamed to `ControlFlow::SuccessorTypes::ConditionalSuccessor`.
- `ControlFlowEdgeBoolean` has been renamed to `ControlFlow::SuccessorTypes::BooleanSuccessor`.
- `ControlFlowEdgeNullness` has been renamed to `ControlFlow::SuccessorTypes::NullnessSuccessor`.
- `ControlFlowEdgeMatching` has been renamed to `ControlFlow::SuccessorTypes::MatchingSuccessor`.
- `ControlFlowEdgeEmptiness` has been renamed to `ControlFlow::SuccessorTypes::EmptinessSuccessor`.
- `ControlFlowEdgeReturn` has been renamed to `ControlFlow::SuccessorTypes::ReturnSuccessor`.
- `ControlFlowEdgeBreak` has been renamed to `ControlFlow::SuccessorTypes::BreakSuccessor`.
- `ControlFlowEdgeContinue` has been renamed to `ControlFlow::SuccessorTypes::ContinueSuccessor`.
- `ControlFlowEdgeGotoLabel` has been renamed to `ControlFlow::SuccessorTypes::GotoLabelSuccessor`.
- `ControlFlowEdgeGotoCase` has been renamed to `ControlFlow::SuccessorTypes::GotoCaseSuccessor`.
- `ControlFlowEdgeGotoDefault` has been renamed to `ControlFlow::SuccessorTypes::GotoDefaultSuccessor`.
- `ControlFlowEdgeException` has been renamed to `ControlFlow::SuccessorTypes::ExceptionSuccessor`.

View File

@@ -5,7 +5,7 @@ private import semmle.code.csharp.frameworks.system.web.UI
class DisposableType extends RefType {
DisposableType() {
this.getABaseType+() = getSystemIDisposableInterface()
this.getABaseType+() instanceof SystemIDisposableInterface
}
}
@@ -17,13 +17,13 @@ class DisposableField extends Field {
class WebControl extends RefType {
WebControl() {
this.getBaseClass*() = getSystemWebUIControlClass()
this.getBaseClass*() instanceof SystemWebUIControlClass
}
}
class WebPage extends RefType {
WebPage() {
this.getBaseClass*() = getSystemWebUIPageClass()
this.getBaseClass*() instanceof SystemWebUIPageClass
}
}

View File

@@ -14,7 +14,6 @@
import csharp
import semmle.code.csharp.commons.Assertions
import semmle.code.csharp.commons.Constants
import ControlFlowGraph
/** A constant condition. */
abstract class ConstantCondition extends Expr {
@@ -76,13 +75,13 @@ class ConstantNullnessCondition extends ConstantCondition {
boolean b;
ConstantNullnessCondition() {
forex(ControlFlowNode cfn |
forex(ControlFlow::Node cfn |
cfn = this.getAControlFlowNode() |
exists(ControlFlowEdgeNullness t |
exists(ControlFlow::SuccessorTypes::NullnessSuccessor t |
exists(cfn.getASuccessorByType(t)) |
if t.isNull() then b = true else b = false
) and
strictcount(ControlFlowEdgeType t | exists(cfn.getASuccessorByType(t))) = 1
strictcount(ControlFlow::SuccessorType t | exists(cfn.getASuccessorByType(t))) = 1
)
}
@@ -99,13 +98,13 @@ class ConstantMatchingCondition extends ConstantCondition {
boolean b;
ConstantMatchingCondition() {
forex(ControlFlowNode cfn |
forex(ControlFlow::Node cfn |
cfn = this.getAControlFlowNode() |
exists(ControlFlowEdgeMatching t |
exists(ControlFlow::SuccessorTypes::MatchingSuccessor t |
exists(cfn.getASuccessorByType(t)) |
if t.isMatch() then b = true else b = false
) and
strictcount(ControlFlowEdgeType t | exists(cfn.getASuccessorByType(t))) = 1
strictcount(ControlFlow::SuccessorType t | exists(cfn.getASuccessorByType(t))) = 1
)
}

View File

@@ -35,5 +35,5 @@ class StringComparison extends Expr {
from StringComparison sc, PropertyAccess pa
where sc.getAnOperand() instanceof StringLiteral
and sc.getAnOperand() = pa
and pa.getTarget() = getSystemTypeClass().getFullNameProperty()
and pa.getTarget() = any(SystemTypeClass c).getFullNameProperty()
select sc, "Erroneous class compare."

View File

@@ -102,17 +102,17 @@ class LockStmtBlock extends LockedBlock
exists( LockStmt s | this=s.getBlock() )
}
predicate isLockThis()
override predicate isLockThis()
{
exists( LockStmt s | this=s.getBlock() and s.isLockThis() )
}
Variable getLockVariable()
override Variable getLockVariable()
{
exists( LockStmt s | this=s.getBlock() and result=s.getLockVariable() )
}
Type getLockTypeObject()
override Type getLockTypeObject()
{
exists( LockStmt s | this=s.getBlock() and result=s.getLockTypeObject() )
}
@@ -138,17 +138,17 @@ class SynchronizedMethodBlock extends LockedBlock
{
exists( SynchronizedMethod m | this=m.getStatementBody() )
}
predicate isLockThis()
override predicate isLockThis()
{
exists( SynchronizedMethod m | this=m.getStatementBody() and m.isLockThis() )
}
Variable getLockVariable()
override Variable getLockVariable()
{
none()
}
Type getLockTypeObject()
override Type getLockTypeObject()
{
exists( SynchronizedMethod m | this=m.getStatementBody() and result=m.getLockTypeObject() )
}

View File

@@ -13,7 +13,6 @@
import csharp
import DataMembers
import ThreadCreation
import ControlFlowGraph
predicate correctlySynchronized(CollectionMember c, Expr access) {
access = c.getAReadOrWrite() and
@@ -24,9 +23,9 @@ predicate correctlySynchronized(CollectionMember c, Expr access) {
)
}
ControlFlowNode unlockedReachable(Callable a) {
ControlFlow::Node unlockedReachable(Callable a) {
result = a.getEntryPoint() or
exists(ControlFlowNode mid | mid = unlockedReachable(a) |
exists(ControlFlow::Node mid | mid = unlockedReachable(a) |
not mid.getElement() instanceof LockingCall and
result = mid.getASuccessor()
)

View File

@@ -13,7 +13,6 @@
import csharp
import semmle.code.csharp.commons.ComparisonTest
import semmle.code.csharp.controlflow.ControlFlowGraph::ControlFlowGraph
import semmle.code.csharp.commons.StructuralComparison as SC
/** A structural comparison configuration for comparing the conditions of nested `for` loops. */
@@ -87,13 +86,13 @@ class NestedForLoopSameVariable extends ForStmt {
}
/** Finds elements inside the outer loop that are no longer guarded by the loop invariant. */
private ControlFlowNode getAnUnguardedNode()
private ControlFlow::Node getAnUnguardedNode()
{
result.getElement().getParent+() = getOuterForStmt().getBody() and
(
result = this.getCondition().(ControlFlowElement).getAControlFlowExitNode().getAFalseSuccessor()
or
exists(ControlFlowNode mid | mid = getAnUnguardedNode() |
exists(ControlFlow::Node mid | mid = getAnUnguardedNode() |
mid.getASuccessor() = result and
not exists(getAComparisonTest(result.getElement()))
)

View File

@@ -14,7 +14,7 @@
import csharp
// Iterate the control flow until we reach a Stmt
Stmt findSuccessorStmt(ControlFlowGraph::ControlFlowNode n)
Stmt findSuccessorStmt(ControlFlow::Node n)
{
result=n.getElement() or
not n.getElement() instanceof Stmt and result=findSuccessorStmt(n.getASuccessor())

View File

@@ -12,11 +12,11 @@
import csharp
import semmle.code.csharp.frameworks.System
predicate nodeBeforeParameterAccess(ControlFlowGraph::ControlFlowNode node)
predicate nodeBeforeParameterAccess(ControlFlow::Node node)
{
exists(EqualsMethod equals | equals.getBody() = node.getElement())
or
exists(EqualsMethod equals, Parameter param, ControlFlowGraph::ControlFlowNode mid |
exists(EqualsMethod equals, Parameter param, ControlFlow::Node mid |
equals.getParameter(0) = param and
equals.getAChild*() = mid.getElement() and
nodeBeforeParameterAccess(mid) and

View File

@@ -11,7 +11,7 @@
import csharp
import semmle.code.csharp.frameworks.system.Text
from ObjectCreation creation, LoopStmt loop, ControlFlowGraph::ControlFlowNode loopEntryNode
from ObjectCreation creation, LoopStmt loop, ControlFlow::Node loopEntryNode
where creation.getType() instanceof SystemTextStringBuilderClass
and loopEntryNode = loop.getBody().getAControlFlowEntryNode()
and loop.getBody().getAChild*() = creation

View File

@@ -12,10 +12,9 @@
*/
import csharp
import ControlFlowGraph
import semmle.code.csharp.frameworks.system.web.Security
predicate loginMethod(Method m, ControlFlowEdgeType flowFrom)
predicate loginMethod(Method m, ControlFlow::SuccessorType flowFrom)
{
(
m = any(SystemWebSecurityMembershipClass c).getValidateUserMethod()
@@ -23,11 +22,11 @@ predicate loginMethod(Method m, ControlFlowEdgeType flowFrom)
m = any(SystemWebSecurityFormsAuthenticationClass c).getAuthenticateMethod()
)
and
flowFrom.(ControlFlowEdgeBoolean).getValue()=true
flowFrom.(ControlFlow::SuccessorTypes::BooleanSuccessor).getValue()=true
or
m = any(SystemWebSecurityFormsAuthenticationClass c).getSignOutMethod()
and
flowFrom instanceof ControlFlowEdgeSuccessor
flowFrom instanceof ControlFlow::SuccessorTypes::NormalSuccessor
}
/** The `System.Web.SessionState.HttpSessionState` class. */
@@ -62,14 +61,14 @@ predicate sessionUse(MemberAccess ma)
}
/** A control flow step that is not sanitised by a call to clear the session. */
predicate controlStep(ControlFlowNode s1, ControlFlowNode s2)
predicate controlStep(ControlFlow::Node s1, ControlFlow::Node s2)
{
s2 = s1.getASuccessor()
and
not sessionEndMethod(s2.getElement().(MethodCall).getTarget())
}
from ControlFlowNode loginCall, Method loginMethod, ControlFlowNode sessionUse, ControlFlowEdgeType fromLoginFlow
from ControlFlow::Node loginCall, Method loginMethod, ControlFlow::Node sessionUse, ControlFlow::SuccessorType fromLoginFlow
where loginMethod = loginCall.getElement().(MethodCall).getTarget()
and loginMethod(loginMethod, fromLoginFlow)
and sessionUse(sessionUse.getElement())

View File

@@ -29,11 +29,18 @@ import semmle.code.csharp.exprs.Dynamic
import semmle.code.csharp.exprs.Expr
import semmle.code.csharp.exprs.Literal
import semmle.code.csharp.exprs.LogicalOperation
import semmle.code.csharp.controlflow.ControlFlowGraph as ControlFlowGraph
import semmle.code.csharp.controlflow.ControlFlowGraph
import semmle.code.csharp.dataflow.DataFlow
import semmle.code.csharp.dataflow.TaintTracking
import semmle.code.csharp.dataflow.SSA
/** DEPRECATED: Use `ControlFlow` instead. */
deprecated
module ControlFlowGraph {
import semmle.code.csharp.controlflow.ControlFlowGraph
import ControlFlow
}
/** Whether the source was extracted without a build command. */
predicate extractionIsStandalone() {
exists(SourceFile f | f.extractedStandalone())

View File

@@ -9,7 +9,7 @@ class ExternalDefect extends @externalDefect, Element {
float getSeverity() { externalDefects(this, _, _, _, result) }
Location getLocation() { externalDefects(this,_,result,_,_) }
override Location getLocation() { externalDefects(this,_,result,_,_) }
override string toString() {
result = getQueryPath() + ": " + getLocation() + " - " + getMessage()
@@ -22,7 +22,7 @@ class ExternalMetric extends @externalMetric, Element {
float getValue() { externalMetrics(this, _, _, result) }
Location getLocation() { externalMetrics(this,_,result,_) }
override Location getLocation() { externalMetrics(this,_,result,_) }
override string toString() {
result = getQueryPath() + ": " + getLocation() + " - " + getValue()

View File

@@ -3,7 +3,6 @@
*/
import csharp
private import ControlFlowGraph
/**
* An assignable, that is, an element that can be assigned to. Either a
@@ -348,7 +347,7 @@ private cached module AssignableDefinitionImpl {
cached predicate isUncertainRefCall(Call c, AssignableAccess aa) {
isRelevantRefCall(c, aa)
and
exists(ControlFlowGraph::BasicBlock bb, Parameter p |
exists(ControlFlow::BasicBlock bb, Parameter p |
isAnalyzableRefCall(c, aa, p) |
parameterReachesWithoutDef(p, bb) and
bb.getLastNode() = p.getCallable().getExitPoint()
@@ -360,14 +359,14 @@ private cached module AssignableDefinitionImpl {
* entry point of `p`'s callable to basic block `bb` without passing through
* any assignments to `p`.
*/
private predicate parameterReachesWithoutDef(Parameter p, BasicBlock bb) {
private predicate parameterReachesWithoutDef(Parameter p, ControlFlow::BasicBlock bb) {
not basicBlockRefParamDef(bb, p)
and
(
isAnalyzableRefCall(_, _, p) and
p.getCallable().getEntryPoint() = bb.getFirstNode()
or
exists(BasicBlock mid |
exists(ControlFlow::BasicBlock mid |
parameterReachesWithoutDef(p, mid) |
bb = mid.getASuccessor()
)
@@ -375,7 +374,7 @@ private cached module AssignableDefinitionImpl {
}
/** Holds if a node in basic block `bb` assigns to `ref` parameter `p`. */
private predicate basicBlockRefParamDef(BasicBlock bb, Parameter p) {
private predicate basicBlockRefParamDef(ControlFlow::BasicBlock bb, Parameter p) {
bb.getANode() = getAnAnalyzableRefDef(_, _, p).getAControlFlowNode()
}
@@ -447,11 +446,11 @@ class AssignableDefinition extends TAssignableDefinition {
* the definitions of `x` and `y` in `M(out x, out y)` and `(x, y) = (0, 1)`
* relate to the same call to `M` and assignment node, respectively.
*/
ControlFlowNode getAControlFlowNode() { none() }
ControlFlow::Node getAControlFlowNode() { none() }
/** DEPRECATED: Use `getAControlFlowNode()` instead. */
deprecated
ControlFlowNode getControlFlowNode() { result = this.getAControlFlowNode() }
ControlFlow::Node getControlFlowNode() { result = this.getAControlFlowNode() }
/** Gets the enclosing callable of this definition. */
Callable getEnclosingCallable() {
@@ -603,7 +602,7 @@ module AssignableDefinitions {
result = a
}
override ControlFlowNode getAControlFlowNode() {
override ControlFlow::Node getAControlFlowNode() {
result = a.getAControlFlowNode()
}
@@ -644,7 +643,7 @@ module AssignableDefinitions {
* orders of the definitions of `x`, `y`, and `z` are 0, 1, and 2, respectively.
*/
int getEvaluationOrder() {
exists(BasicBlock bb, int i |
exists(ControlFlow::BasicBlock bb, int i |
bb.getNode(i).getElement() = leaf |
i = rank[result + 1](int j, TupleAssignmentDefinition def |
bb.getNode(j).getElement() = def.getLeaf() and
@@ -655,7 +654,7 @@ module AssignableDefinitions {
)
}
override ControlFlowNode getAControlFlowNode() {
override ControlFlow::Node getAControlFlowNode() {
result = ae.getAControlFlowNode()
}
@@ -690,7 +689,7 @@ module AssignableDefinitions {
* the definitions of `x` and `y` are 0 and 1, respectively.
*/
int getIndex() {
exists(BasicBlock bb, int i |
exists(ControlFlow::BasicBlock bb, int i |
bb.getNode(i).getElement() = aa |
i = rank[result + 1](int j, OutRefDefinition def |
bb.getNode(j).getElement() = def.getTargetAccess() and
@@ -701,7 +700,7 @@ module AssignableDefinitions {
)
}
override ControlFlowNode getAControlFlowNode() {
override ControlFlow::Node getAControlFlowNode() {
result = this.getCall().getAControlFlowNode()
}
@@ -733,7 +732,7 @@ module AssignableDefinitions {
result = mo
}
override ControlFlowNode getAControlFlowNode() {
override ControlFlow::Node getAControlFlowNode() {
result = mo.getAControlFlowNode()
}
@@ -757,7 +756,7 @@ module AssignableDefinitions {
result = lvde
}
override ControlFlowNode getAControlFlowNode() {
override ControlFlow::Node getAControlFlowNode() {
result = lvde.getAControlFlowNode()
}
@@ -782,7 +781,7 @@ module AssignableDefinitions {
result = p
}
override ControlFlowNode getAControlFlowNode() {
override ControlFlow::Node getAControlFlowNode() {
result = p.getCallable().getEntryPoint()
}
@@ -810,7 +809,7 @@ module AssignableDefinitions {
result = aoe
}
override ControlFlowNode getAControlFlowNode() {
override ControlFlow::Node getAControlFlowNode() {
result = aoe.getAControlFlowNode()
}
@@ -834,7 +833,7 @@ module AssignableDefinitions {
result = ipe.getVariableDeclExpr()
}
override ControlFlowNode getAControlFlowNode() {
override ControlFlow::Node getAControlFlowNode() {
result = this.getDeclaration().getAControlFlowNode()
}
@@ -871,7 +870,7 @@ module AssignableDefinitions {
result = tc.getVariableDeclExpr()
}
override ControlFlowNode getAControlFlowNode() {
override ControlFlow::Node getAControlFlowNode() {
result = this.getDeclaration().getAControlFlowNode()
}
@@ -907,7 +906,7 @@ module AssignableDefinitions {
result = a
}
override ControlFlowNode getAControlFlowNode() {
override ControlFlow::Node getAControlFlowNode() {
none() // initializers are currently not part of the CFG
}

View File

@@ -167,12 +167,12 @@ class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @cal
final predicate hasExpressionBody() { exists(getExpressionBody()) }
/** Gets the entry point in the control graph for this callable. */
ControlFlowGraph::CallableEntryNode getEntryPoint() {
ControlFlow::Nodes::EntryNode getEntryPoint() {
result.getCallable() = this
}
/** Gets the exit point in the control graph for this callable. */
ControlFlowGraph::CallableExitNode getExitPoint() {
ControlFlow::Nodes::ExitNode getExitPoint() {
result.getCallable() = this
}

View File

@@ -92,8 +92,7 @@ class EventAccessor extends Accessor, @event_accessor {
result instanceof VoidType
}
/** Gets the assembly name of this event accessor. */
string getAssemblyName() { event_accessors(this,_,result,_,_) }
override string getAssemblyName() { event_accessors(this,_,result,_,_) }
override EventAccessor getSourceDeclaration() { event_accessors(this,_,_,_,result) }

View File

@@ -29,7 +29,7 @@ abstract class AssertNonNullMethod extends AssertMethod {
*/
class SystemDiagnosticsDebugAssertTrueMethod extends AssertTrueMethod {
SystemDiagnosticsDebugAssertTrueMethod() {
this = getSystemDiagnosticsDebugClass().getAssertMethod()
this = any(SystemDiagnosticsDebugClass c).getAssertMethod()
}
override int getAssertionIndex() { result = 0 }
@@ -38,7 +38,7 @@ class SystemDiagnosticsDebugAssertTrueMethod extends AssertTrueMethod {
/** A Visual Studio assertion method. */
class VSTestAssertTrueMethod extends AssertTrueMethod {
VSTestAssertTrueMethod() {
this = getVSTestAssertClass().getIsTrueMethod()
this = any(VSTestAssertClass c).getIsTrueMethod()
}
override int getAssertionIndex() { result = 0 }
@@ -47,7 +47,7 @@ class VSTestAssertTrueMethod extends AssertTrueMethod {
/** A Visual Studio negated assertion method. */
class VSTestAssertFalseMethod extends AssertFalseMethod {
VSTestAssertFalseMethod() {
this = getVSTestAssertClass().getIsFalseMethod()
this = any(VSTestAssertClass c).getIsFalseMethod()
}
override int getAssertionIndex() { result = 0 }
@@ -56,7 +56,7 @@ class VSTestAssertFalseMethod extends AssertFalseMethod {
/** A Visual Studio `null` assertion method. */
class VSTestAssertNullMethod extends AssertNullMethod {
VSTestAssertNullMethod() {
this = getVSTestAssertClass().getIsNullMethod()
this = any(VSTestAssertClass c).getIsNullMethod()
}
override int getAssertionIndex() { result = 0 }
@@ -65,7 +65,7 @@ class VSTestAssertNullMethod extends AssertNullMethod {
/** A Visual Studio non-`null` assertion method. */
class VSTestAssertNonNullMethod extends AssertNonNullMethod {
VSTestAssertNonNullMethod() {
this = getVSTestAssertClass().getIsNotNullMethod()
this = any(VSTestAssertClass c).getIsNotNullMethod()
}
override int getAssertionIndex() { result = 0 }

View File

@@ -40,7 +40,7 @@ module SsaChecks {
import Ssa
predicate nonUniqueSsaDef(AssignableRead read, string m) {
exists(ControlFlowNode cfn |
exists(ControlFlow::Node cfn |
strictcount(Definition def | def.getAReadAtNode(cfn) = read) > 1
)
and
@@ -48,7 +48,7 @@ module SsaChecks {
}
predicate notDominatedByDef(AssignableRead read, string m) {
exists(Definition def, BasicBlock bb, ControlFlowNode rnode, ControlFlowNode dnode, int i |
exists(Definition def, BasicBlock bb, ControlFlow::Node rnode, ControlFlow::Node dnode, int i |
def.getAReadAtNode(rnode) = read |
def.definesAt(bb, i) and
dnode = bb.getNode(max(int j | j = i or j = 0)) and
@@ -82,12 +82,10 @@ module SsaChecks {
}
module CfgChecks {
import ControlFlowGraph
predicate multipleSuccessors(ControlFlowElement cfe, string m) {
exists(ControlFlowNode cfn |
exists(ControlFlow::Node cfn |
cfn = cfe.getAControlFlowNode() |
strictcount(cfn.getASuccessorByType(any(ControlFlowEdgeSuccessor e))) > 1 and
strictcount(cfn.getASuccessorByType(any(ControlFlow::SuccessorTypes::NormalSuccessor e))) > 1 and
m = "Multiple (non-conditional/exceptional) successors"
)
}

View File

@@ -1,6 +1,5 @@
/** Provides logic for determining constant expressions. */
import csharp
private import ControlFlowGraph
private import semmle.code.csharp.commons.ComparisonTest
private import semmle.code.csharp.commons.StructuralComparison as StructuralComparison
@@ -8,10 +7,10 @@ private import semmle.code.csharp.commons.StructuralComparison as StructuralComp
* Holds if `e` is a condition that always evaluates to Boolean value `b`.
*/
predicate isConstantCondition(Expr e, boolean b) {
forex(ControlFlowNode cfn |
forex(ControlFlow::Node cfn |
cfn = e.getAControlFlowNode() |
exists(cfn.getASuccessorByType(any(ControlFlowEdgeBoolean t | t.getValue() = b))) and
strictcount(ControlFlowEdgeType t | exists(cfn.getASuccessorByType(t))) = 1
exists(cfn.getASuccessorByType(any(ControlFlow::SuccessorTypes::BooleanSuccessor t | t.getValue() = b))) and
strictcount(ControlFlow::SuccessorType t | exists(cfn.getASuccessorByType(t))) = 1
)
}

View File

@@ -99,20 +99,20 @@ class BasicBlock extends TBasicBlockStart {
}
/** Gets the control flow node at a specific (zero-indexed) position in this basic block. */
ControlFlowGraph::ControlFlowNode getNode(int pos) { bbIndex(getFirstNode(), result, pos) }
ControlFlow::Node getNode(int pos) { bbIndex(getFirstNode(), result, pos) }
/** Gets a control flow node in this basic block. */
ControlFlowGraph::ControlFlowNode getANode() {
ControlFlow::Node getANode() {
result = getNode(_)
}
/** Gets the first control flow node in this basic block. */
ControlFlowGraph::ControlFlowNode getFirstNode() {
ControlFlow::Node getFirstNode() {
this = TBasicBlockStart(result)
}
/** Gets the last control flow node in this basic block. */
ControlFlowGraph::ControlFlowNode getLastNode() {
ControlFlow::Node getLastNode() {
result = getNode(length() - 1)
}
@@ -326,22 +326,22 @@ class BasicBlock extends TBasicBlockStart {
private cached module Internal {
/** Internal representation of basic blocks. */
cached newtype TBasicBlock =
TBasicBlockStart(ControlFlowGraph::ControlFlowNode cfn) { startsBB(cfn) }
TBasicBlockStart(ControlFlow::Node cfn) { startsBB(cfn) }
/** Holds if `cfn` starts a new basic block. */
private predicate startsBB(ControlFlowGraph::ControlFlowNode cfn) {
private predicate startsBB(ControlFlow::Node cfn) {
not exists(cfn.getAPredecessor()) and exists(cfn.getASuccessor())
or
cfn.isJoin()
or
exists(ControlFlowGraph::ControlFlowNode pred | pred = cfn.getAPredecessor() | strictcount(pred.getASuccessor()) > 1)
exists(ControlFlow::Node pred | pred = cfn.getAPredecessor() | strictcount(pred.getASuccessor()) > 1)
}
/**
* Holds if `succ` is a control flow successor of `pred` within
* the same basic block.
*/
private predicate intraBBSucc(ControlFlowGraph::ControlFlowNode pred, ControlFlowGraph::ControlFlowNode succ) {
private predicate intraBBSucc(ControlFlow::Node pred, ControlFlow::Node succ) {
succ = pred.getASuccessor() and
not startsBB(succ)
}
@@ -353,7 +353,7 @@ private cached module Internal {
* that starts a basic block to `cfn` along the `intraBBSucc` relation.
*/
cached
predicate bbIndex(ControlFlowGraph::ControlFlowNode bbStart, ControlFlowGraph::ControlFlowNode cfn, int i) =
predicate bbIndex(ControlFlow::Node bbStart, ControlFlow::Node cfn, int i) =
shortestDistances(startsBB/1, intraBBSucc/2)(bbStart, cfn, i)
/**
@@ -395,7 +395,7 @@ class EntryBasicBlock extends BasicBlock {
/** Holds if `bb` is an entry basic block. */
private predicate entryBB(BasicBlock bb) {
bb.getFirstNode() instanceof ControlFlowGraph::CallableEntryNode
bb.getFirstNode() instanceof ControlFlow::Nodes::EntryNode
}
/**
@@ -408,7 +408,7 @@ class ExitBasicBlock extends BasicBlock {
/** Holds if `bb` is an exit basic block. */
private predicate exitBB(BasicBlock bb) {
bb.getLastNode() instanceof ControlFlowGraph::CallableExitNode
bb.getLastNode() instanceof ControlFlow::Nodes::ExitNode
}
/**

View File

@@ -7,12 +7,10 @@ private import semmle.code.csharp.ExprOrStmtParent
* A program element that can possess control flow. That is, either a statement or
* an expression.
*
* A control flow element can be mapped to a control flow node (`ControlFlowNode`)
* A control flow element can be mapped to a control flow node (`ControlFlow::Node`)
* via `getAControlFlowNode()`. There is a one-to-many relationship between
* `ControlFlowElement`s and `ControlFlowNode`s. This allows control flow
* control flow elements and control flow nodes. This allows control flow
* splitting, for example modeling the control flow through `finally` blocks.
*
* `ControlFlowNode`s are nodes in the control flow graph.
*/
class ControlFlowElement extends ExprOrStmtParent, @control_flow_element {
/** Gets the enclosing callable of this element, if any. */
@@ -22,26 +20,26 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element {
* Gets a control flow node for this element. That is, a node in the
* control flow graph that corresponds to this element.
*
* Typically, there is exactly one `ControlFlowNode` associated with a
* Typically, there is exactly one `ControlFlow::Node` associated with a
* `ControlFlowElement`, but a `ControlFlowElement` may be split into
* several `ControlFlowNode`s, for example to represent the continuation
* several `ControlFlow::Node`s, for example to represent the continuation
* flow in a `try/catch/finally` construction.
*/
ControlFlowGraph::ControlFlowNode getAControlFlowNode() {
ControlFlow::Node getAControlFlowNode() {
result.getElement() = this
}
/**
* Gets a first control flow node executed within this element.
*/
ControlFlowGraph::ControlFlowNode getAControlFlowEntryNode() {
ControlFlow::Node getAControlFlowEntryNode() {
result = ControlFlowGraph::Internal::getAControlFlowEntryNode(this).getAControlFlowNode()
}
/**
* Gets a potential last control flow node executed within this element.
*/
ControlFlowGraph::ControlFlowNode getAControlFlowExitNode() {
ControlFlow::Node getAControlFlowExitNode() {
result = ControlFlowGraph::Internal::getAControlFlowExitNode(this).getAControlFlowNode()
}
@@ -61,7 +59,7 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element {
/** Gets an element that is reachable from this element. */
ControlFlowElement getAReachableElement() {
// Reachable in same basic block
exists(ControlFlowGraph::BasicBlock bb, int i, int j |
exists(ControlFlow::BasicBlock bb, int i, int j |
bb.getNode(i) = getAControlFlowNode() and
bb.getNode(j) = result.getAControlFlowNode() and
i < j

View File

@@ -184,7 +184,7 @@ class NullGuardedExpr extends AccessOrCallExpr {
// Call to `string.IsNullOrEmpty()`
exists(MethodCall mc |
mc = cond and
mc.getTarget() = getSystemStringClass().getIsNullOrEmptyMethod() and
mc.getTarget() = any(SystemStringClass c).getIsNullOrEmptyMethod() and
mc.getArgument(0) = sub and
b = false
)

View File

@@ -18,12 +18,10 @@
*/
import csharp
private import ControlFlowGraph
private import semmle.code.csharp.commons.Assertions
private import semmle.code.csharp.commons.ComparisonTest
private import semmle.code.csharp.controlflow.Guards
private import semmle.code.csharp.dataflow.SSA
private import semmle.code.csharp.controlflow.ControlFlowGraph
private import semmle.code.csharp.frameworks.System
/** An expression that may be `null`. */
@@ -412,7 +410,7 @@ private Expr failureIsNonNullTest(LocalScopeVariable var) {
* Gets an immediate successor node of the conditional node `cfgnode` where
* the condition implies that the variable `var` is `null`.
*/
private ControlFlowNode nullBranchKill(LocalScopeVariable var, ControlFlowNode cfgnode) {
private ControlFlow::Node nullBranchKill(LocalScopeVariable var, ControlFlow::Node cfgnode) {
(cfgnode.getElement() = nullTest(var) and result = cfgnode.getATrueSuccessor())
or
(cfgnode.getElement() = failureIsNullTest(var) and result = cfgnode.getAFalseSuccessor())
@@ -422,17 +420,17 @@ private ControlFlowNode nullBranchKill(LocalScopeVariable var, ControlFlowNode c
* Gets an immediate successor node of the conditional node `cfgnode` where
* the condition implies that the variable `var` is non-`null`.
*/
private ControlFlowNode nonNullBranchKill(LocalScopeVariable var, ControlFlowNode cfgnode) {
private ControlFlow::Node nonNullBranchKill(LocalScopeVariable var, ControlFlow::Node cfgnode) {
(cfgnode.getElement() = nonNullTest(var) and result = cfgnode.getATrueSuccessor())
or
(cfgnode.getElement() = failureIsNonNullTest(var) and result = cfgnode.getAFalseSuccessor())
}
/** Gets a node where the variable `var` may be `null`. */
ControlFlowNode maybeNullNode(LocalScopeVariable var) {
ControlFlow::Node maybeNullNode(LocalScopeVariable var) {
result = nullDef(var).getAControlFlowNode().getASuccessor()
or
exists(ControlFlowNode mid |
exists(ControlFlow::Node mid |
mid = maybeNullNode(var) and
not mid.getElement() = nonNullDef(var) and
mid.getASuccessor() = result and
@@ -441,10 +439,10 @@ ControlFlowNode maybeNullNode(LocalScopeVariable var) {
}
/** Gets a node where the variable `var` may be non-`null`. */
ControlFlowNode maybeNonNullNode(LocalScopeVariable var) {
ControlFlow::Node maybeNonNullNode(LocalScopeVariable var) {
result = nonNullDef(var).getAControlFlowNode().getASuccessor()
or
exists(ControlFlowNode mid |
exists(ControlFlow::Node mid |
mid = maybeNonNullNode(var) and
not mid.getElement() = nullDef(var) and
mid.getASuccessor() = result and

View File

@@ -5,8 +5,7 @@
import csharp
module Ssa {
class BasicBlock = ControlFlowGraph::BasicBlock;
class ControlFlowNode = ControlFlowGraph::ControlFlowNode;
class BasicBlock = ControlFlow::BasicBlock;
private module SourceVariableImpl {
private import AssignableDefinitions
@@ -207,7 +206,7 @@ module Ssa {
* Holds if the `i`th node `node` of basic block `bb` reads source variable `v`.
* The read at `node` is of kind `rk`.
*/
predicate variableRead(BasicBlock bb, int i, SourceVariable v, ControlFlowNode node, ReadKind rk) {
predicate variableRead(BasicBlock bb, int i, SourceVariable v, ControlFlow::Node node, ReadKind rk) {
v.getAnAccess().(AssignableRead) = node.getElement() and
node = bb.getNode(i) and
rk = ActualRead()
@@ -222,7 +221,7 @@ module Ssa {
rk = RefReadBeforeWrite()
}
private predicate outRefExitRead(ControlFlowGraph::ExitBasicBlock ebb, int i, LocalScopeSourceVariable v, ControlFlowGraph::CallableExitNode node) {
private predicate outRefExitRead(ControlFlow::BasicBlocks::ExitBlock ebb, int i, LocalScopeSourceVariable v, ControlFlow::Nodes::ExitNode node) {
exists(LocalScopeVariable lsv |
lsv = v.getAssignable() and
ebb.getNode(i) = node and
@@ -231,7 +230,7 @@ module Ssa {
)
}
private predicate capturedVarExitRead(ControlFlowGraph::ExitBasicBlock ebb, int i, LocalScopeSourceVariable v, ControlFlowGraph::CallableExitNode node) {
private predicate capturedVarExitRead(ControlFlow::BasicBlocks::ExitBlock ebb, int i, LocalScopeSourceVariable v, ControlFlow::Nodes::ExitNode node) {
exists(BasicBlock bb |
variableDefinition(bb, _, v, _) |
ebb.getNode(i) = node and
@@ -240,7 +239,7 @@ module Ssa {
)
}
private predicate refReadBeforeWrite(BasicBlock bb, int i, LocalScopeSourceVariable v, ControlFlowNode node) {
private predicate refReadBeforeWrite(BasicBlock bb, int i, LocalScopeSourceVariable v, ControlFlow::Node node) {
exists(AssignableDefinitions::AssignmentDefinition def, LocalVariable lv |
def.getTarget() = lv and
lv.isRef() and
@@ -692,7 +691,7 @@ module Ssa {
* same basic block without crossing another SSA definition of `v`.
* The read at `node` is of kind `rk`.
*/
private predicate ssaDefReachesReadWithinBlock(TrackedVar v, TrackedDefinition def, ControlFlowNode read, ReadKind rk) {
private predicate ssaDefReachesReadWithinBlock(TrackedVar v, TrackedDefinition def, ControlFlow::Node read, ReadKind rk) {
exists(BasicBlock bb, int rankix, int i |
ssaDefReachesRank(bb, def, rankix, v) and
rankix = ssaRefRank(bb, i, v, SsaRead()) and
@@ -873,7 +872,7 @@ module Ssa {
* The read at `node` is of kind `rk`.
*/
cached
predicate ssaDefReachesRead(TrackedVar v, TrackedDefinition def, ControlFlowNode read, ReadKind rk) {
predicate ssaDefReachesRead(TrackedVar v, TrackedDefinition def, ControlFlow::Node read, ReadKind rk) {
ssaDefReachesReadWithinBlock(v, def, read, rk)
or
exists(BasicBlock bb |
@@ -1615,7 +1614,7 @@ module Ssa {
* `c` may read the value of the captured variable.
*/
private predicate capturerReads(Callable c, LocalScopeVariable v) {
exists(ControlFlowGraph::EntryBasicBlock ebb, LocalScopeSourceVariable lssv |
exists(ControlFlow::BasicBlocks::EntryBlock ebb, LocalScopeSourceVariable lssv |
liveAtEntry(ebb, lssv, _) |
v = lssv.getAssignable() and
c = ebb.getCallable() and
@@ -1873,7 +1872,7 @@ module Ssa {
)
}
or
TSsaImplicitEntryDef(TrackedVar v, ControlFlowGraph::EntryBasicBlock ebb) {
TSsaImplicitEntryDef(TrackedVar v, ControlFlow::BasicBlocks::EntryBlock ebb) {
liveAtEntry(ebb, v, _)
and
exists(Callable c |
@@ -1921,7 +1920,7 @@ module Ssa {
bb.getNode(i + 1) = v.getAnAccess().(AssignableRead).getAControlFlowNode()
}
or
TPhiNode(TrackedVar v, ControlFlowGraph::JoinBlock bb) {
TPhiNode(TrackedVar v, ControlFlow::BasicBlocks::JoinBlock bb) {
liveAtEntry(bb, v, _)
and
exists(BasicBlock bb1, Definition def |
@@ -2067,7 +2066,7 @@ module Ssa {
* - The reads of `this.Field` on lines 10 and 11 can be reached from the phi
* node between lines 9 and 10.
*/
AssignableRead getAReadAtNode(ControlFlowNode cfn) {
AssignableRead getAReadAtNode(ControlFlow::Node cfn) {
ssaDefReachesRead(_, this, cfn, _) and
result.getAControlFlowNode() = cfn
}
@@ -2250,7 +2249,7 @@ module Ssa {
* parameter may remain unchanged throughout the rest of the enclosing callable.
*/
predicate isLiveOutRefParameterDefinition(Parameter p) {
exists(Definition def, ControlFlowNode read, SourceVariable v |
exists(Definition def, ControlFlow::Node read, SourceVariable v |
this = def.getAnUltimateDefinition() |
ssaDefReachesRead(v, def, read, OutRefExitRead()) and
v.getAssignable() = p
@@ -2371,7 +2370,7 @@ module Ssa {
class ImplicitEntryDefinition extends ImplicitDefinition, TSsaImplicitEntryDef {
/** Gets the callable that this entry definition belongs to. */
Callable getCallable() {
exists(ControlFlowGraph::EntryBasicBlock ebb |
exists(ControlFlow::BasicBlocks::EntryBlock ebb |
this = TSsaImplicitEntryDef(_, ebb) and
result = ebb.getCallable()
)
@@ -2533,7 +2532,7 @@ module Ssa {
* does not exist in the source program.
*/
override Location getLocation() {
exists(ControlFlowGraph::JoinBlock bb |
exists(ControlFlow::BasicBlocks::JoinBlock bb |
this = TPhiNode(_, bb) and
result = bb.getFirstNode().getLocation()
)

View File

@@ -6,7 +6,7 @@ import csharp
* Provides a simple SSA implementation for local scope variables.
*/
module BaseSsa {
private import ControlFlowGraph
private import ControlFlow
private import AssignableDefinitions
private class SimpleLocalScopeVariable extends LocalScopeVariable {

View File

@@ -11,7 +11,7 @@ import Expr
* (`BinaryArithmeticOperation`).
*/
class ArithmeticOperation extends Operation, @arith_op_expr {
string getOperator() { none() }
override string getOperator() { none() }
}
/**

View File

@@ -38,10 +38,9 @@ class Call extends DotNet::Call, Expr, @call {
* Use `getARuntimeTarget()` instead to get a potential run-time target (will
* include `B.M` in the example above).
*/
Callable getTarget() { none() }
override Callable getTarget() { none() }
/** Gets the `i`th argument of this call. */
Expr getArgument(int i) {
override Expr getArgument(int i) {
result = this.getChild(i) and i >= 0
}
@@ -49,8 +48,7 @@ class Call extends DotNet::Call, Expr, @call {
result = this.getArgument(i)
}
/** Gets an argument of this call. */
Expr getAnArgument() {
override Expr getAnArgument() {
result = getArgument(_)
}
@@ -189,7 +187,7 @@ class Call extends DotNet::Call, Expr, @call {
* - Line 16: There is no static target (delegate call) but the delegate `i => { }` (line
* 20) is a run-time target.
*/
Callable getARuntimeTarget() {
override Callable getARuntimeTarget() {
exists(DispatchCall dc | dc.getCall() = this | result = dc.getADynamicTarget())
}

View File

@@ -189,11 +189,11 @@ private module FormatFlow {
private class FormatConfiguration extends DataFlow::Configuration {
FormatConfiguration() { this = "format" }
predicate isSource(DataFlow::Node n) {
override predicate isSource(DataFlow::Node n) {
n.asExpr() instanceof StringLiteral
}
predicate isSink(DataFlow::Node n) {
override predicate isSink(DataFlow::Node n) {
exists(FormatCall c | n.asExpr() = c.getFormatExpr())
}
}

View File

@@ -77,7 +77,7 @@ class SystemWebHttpRequestClass extends SystemWebClass {
and
result.hasName("Url")
and
result.getType() = getSystemUriClass()
result.getType() instanceof SystemUriClass
}
}

View File

@@ -6,7 +6,7 @@ private import semmle.code.csharp.frameworks.system.Runtime
/** The `System.Runtime.InteropServices` namespace. */
class SystemRuntimeInteropServicesNamespace extends Namespace {
SystemRuntimeInteropServicesNamespace() {
this.getParentNamespace() = getSystemRuntimeNamespace() and
this.getParentNamespace() instanceof SystemRuntimeNamespace and
this.hasName("InteropServices")
}
}

View File

@@ -72,7 +72,7 @@ module MissingXMLValidation {
this.getExpr() = createCall.getArgumentForName("input")
}
string getReason() {
override string getReason() {
// No settings = no Schema validation
result = "there is no 'XmlReaderSettings' instance specifying schema validation." and not exists(createCall.getSettings()) or
/*

View File

@@ -50,7 +50,7 @@ module XMLEntityInjection {
).getAnArgument()
}
string getReason() {
override string getReason() {
exists(InsecureXML::InsecureXmlProcessing r | r.isUnsafe(result) | this.getExpr() = r.getAnArgument())
}
}

View File

@@ -451,7 +451,7 @@ module XSS {
this.getExpr() = aspWrittenValue(inline)
}
string explanation() {
override string explanation() {
result = "member is [[\"accessed inline\"|\"" +makeUrl(inline.getLocation())+ "\"]] in an ASPX page"
}
}

View File

@@ -1,6 +1,5 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
from ConditionBlock cb, BasicBlock controlled, boolean testIsTrue
from ControlFlow::BasicBlocks::ConditionBlock cb, ControlFlow::BasicBlock controlled, boolean testIsTrue
where cb.controls(controlled, testIsTrue)
select cb.getLastNode(), controlled.getFirstNode(), testIsTrue

View File

@@ -1,12 +1,11 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
ControlFlowNode successor(ControlFlowNode node, boolean kind) {
ControlFlow::Node successor(ControlFlow::Node node, boolean kind) {
(kind = true and result = node.getATrueSuccessor()) or
(kind = false and result = node.getAFalseSuccessor())
}
from ControlFlowNode node, ControlFlowNode successor, Location nl, Location sl, boolean kind
from ControlFlow::Node node, ControlFlow::Node successor, Location nl, Location sl, boolean kind
where successor = successor(node, kind)
and nl = node.getLocation()
and sl = successor.getLocation()

View File

@@ -1,7 +1,6 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
from ControlFlowNode dom, ControlFlowNode node, string s
from ControlFlow::Node dom, ControlFlow::Node node, string s
where
dom.strictlyDominates(node) and dom.getASuccessor() = node and s = "pre"
or

View File

@@ -1,8 +1,7 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
query predicate edges(ControlFlowElement node, ControlFlowElement successor, string attr, string val) {
exists(ControlFlowEdgeType t |
exists(ControlFlow::SuccessorType t |
successor = node.getAControlFlowNode().getASuccessorByType(t).getElement() |
attr = "semmle.label" and
val = t.toString()

View File

@@ -1,5 +1,5 @@
import csharp
import ControlFlowGraph::Internal
import ControlFlow::Internal
from ControlFlowElement cfe
select cfe, first(cfe)

View File

@@ -1,5 +1,5 @@
import csharp
import ControlFlowGraph::Internal
import ControlFlow::Internal
private import semmle.code.csharp.controlflow.Completion
from ControlFlowElement cfe, Completion c

View File

@@ -1,12 +1,13 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
import ControlFlow
import Internal
import Nodes
class MyFinallySplitControlFlowNode extends ControlFlowElementNode {
class MyFinallySplitControlFlowNode extends ElementNode {
MyFinallySplitControlFlowNode() {
exists(FinallySplitting::FinallySplitType type |
type = this.getASplit().(FinallySplit).getType() |
not type instanceof ControlFlowEdgeSuccessor
not type instanceof SuccessorTypes::NormalSuccessor
)
}

View File

@@ -1,8 +1,7 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
query predicate edges(ControlFlowNode node, ControlFlowNode successor, string attr, string val) {
exists(ControlFlowEdgeType t |
query predicate edges(ControlFlow::Node node, ControlFlow::Node successor, string attr, string val) {
exists(ControlFlow::SuccessorType t |
successor = node.getASuccessorByType(t) |
attr = "semmle.label" and
val = t.toString()

View File

@@ -1,8 +1,7 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
query predicate edges(ControlFlowNode n1, ControlFlowNode n2, string attr, string val) {
exists(SwitchStmt switch, ControlFlowEdgeType t |
query predicate edges(ControlFlow::Node n1, ControlFlow::Node n2, string attr, string val) {
exists(SwitchStmt switch, ControlFlow::SuccessorType t |
switch.getAControlFlowNode().getASuccessor*()=n1 |
n2 = n1.getASuccessorByType(t) and
attr = "semmle.label" and

View File

@@ -1,11 +1,10 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
/** "Naive" def-use implementation. */
predicate defReaches(AssignableDefinition def, LocalScopeVariable v, ControlFlowNode cfn) {
predicate defReaches(AssignableDefinition def, LocalScopeVariable v, ControlFlow::Node cfn) {
def.getTarget() = v and cfn = def.getAControlFlowNode().getASuccessor()
or
exists(ControlFlowNode mid |
exists(ControlFlow::Node mid |
defReaches(def, v, mid) |
not mid = any(AssignableDefinition ad | ad.getTarget() = v and ad.isCertain()).getAControlFlowNode() and
cfn = mid.getASuccessor()

View File

@@ -1,11 +1,10 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
/** "Naive" parameter-use implementation. */
predicate parameterReaches(Parameter p, ControlFlowNode cfn) {
predicate parameterReaches(Parameter p, ControlFlow::Node cfn) {
cfn = p.getCallable().getEntryPoint().getASuccessor()
or
exists(ControlFlowNode mid |
exists(ControlFlow::Node mid |
parameterReaches(p, mid) |
not mid = any(AssignableDefinition ad | ad.getTarget() = p and ad.isCertain()).getAControlFlowNode() and
cfn = mid.getASuccessor()

View File

@@ -1,11 +1,10 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
/** "Naive" use-use implementation. */
predicate useReaches(LocalScopeVariableRead read, LocalScopeVariable v, ControlFlowNode cfn) {
predicate useReaches(LocalScopeVariableRead read, LocalScopeVariable v, ControlFlow::Node cfn) {
read.getTarget() = v and cfn = read.getAControlFlowNode().getASuccessor()
or
exists(ControlFlowNode mid |
exists(ControlFlow::Node mid |
useReaches(read, v, mid) |
not mid = any(AssignableDefinition ad | ad.getTarget() = v and ad.isCertain()).getAControlFlowNode() and
cfn = mid.getASuccessor()
@@ -29,7 +28,7 @@ private TLocalScopeVariableReadOrSsaDef getANextReadOrDef(TLocalScopeVariableRea
result = TLocalScopeVariableRead(read.getANextRead())
or
not exists(read.getANextRead()) and
exists(Ssa::Definition ssaDef, Ssa::PseudoDefinition pseudoDef, ControlFlowNode cfn, BasicBlock bb, int i |
exists(Ssa::Definition ssaDef, Ssa::PseudoDefinition pseudoDef, ControlFlow::Node cfn, ControlFlow::BasicBlock bb, int i |
ssaDef.getARead() = read |
pseudoDef.getAnInput() = ssaDef and
pseudoDef.definesAt(bb, i) and

View File

@@ -3,5 +3,5 @@ import csharp
from int uses, int live
where
uses = strictcount(Ssa::ExplicitDefinition ssa, AssignableRead read | read = ssa.getARead()) and
live = strictcount(Ssa::ExplicitDefinition ssa, ControlFlowGraph::BasicBlock bb | ssa.isLiveAtEndOfBlock(bb))
live = strictcount(Ssa::ExplicitDefinition ssa, ControlFlow::BasicBlock bb | ssa.isLiveAtEndOfBlock(bb))
select uses, live

View File

@@ -1,8 +1,7 @@
import csharp
import semmle.code.csharp.controlflow.ControlFlowGraph
query predicate edges(ControlFlowNode node, ControlFlowNode successor, string attr, string val) {
exists(ControlFlowEdgeType t |
query predicate edges(ControlFlow::Node node, ControlFlow::Node successor, string attr, string val) {
exists(ControlFlow::SuccessorType t |
successor = node.getASuccessorByType(t) |
attr = "semmle.label" and
val = t.toString()