Skip to content

Commit

Permalink
perf
Browse files Browse the repository at this point in the history
  • Loading branch information
hvitved committed Jul 4, 2024
1 parent bd303e8 commit 0e357f7
Show file tree
Hide file tree
Showing 8 changed files with 355 additions and 351 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,9 @@ module VariableCapture {
private predicate closureFlowStep(ControlFlow::Nodes::ExprNode e1, ControlFlow::Nodes::ExprNode e2) {
e1 = LocalFlow::getALastEvalNode(e2)
or
exists(Ssa::Definition def |
SsaFlow::Input::ssaDefAssigns(def.getAnUltimateDefinition(), e1) and
exists(Ssa::Definition def, AssignableDefinition adef |
LocalFlow::defAssigns(adef, _, e1) and
def.getAnUltimateDefinition().(Ssa::ExplicitDefinition).getADefinition() = adef and
exists(def.getAReadAtNode(e2))
)
}
Expand Down Expand Up @@ -483,42 +484,7 @@ module VariableCapture {

/** Provides logic related to SSA. */
module SsaFlow {
module Input implements SsaImpl::Impl::DataFlowIntegrationInputSig {
private import csharp as Cs

class Expr extends ControlFlow::Node {
predicate hasCfgNode(ControlFlow::BasicBlock bb, int i) { this = bb.getNode(i) }
}

predicate ssaDefAssigns(SsaImpl::WriteDefinition def, Expr value) {
exists(AssignableDefinition adef, ControlFlow::Node cfnDef |
any(LocalFlow::LocalExprStepConfiguration conf).hasDefPath(_, value, adef, cfnDef) and
def.(Ssa::ExplicitDefinition).getADefinition() = adef and
def.(Ssa::ExplicitDefinition).getControlFlowNode() = cfnDef
)
}

class Parameter = Cs::Parameter;

predicate ssaDefInitializesParam(SsaImpl::WriteDefinition def, Parameter p) {
def.(Ssa::ImplicitParameterDefinition).getParameter() = p
}

/**
* Allows for flow into uncertain defintions that are not call definitions,
* as we, conservatively, consider such definitions to be certain.
*/
predicate allowFlowIntoUncertainDef(SsaImpl::UncertainWriteDefinition def) {
def instanceof Ssa::ExplicitDefinition
or
def =
any(Ssa::ImplicitQualifierDefinition qdef |
allowFlowIntoUncertainDef(qdef.getQualifierDefinition())
)
}
}

module Impl = SsaImpl::Impl::DataFlowIntegration<Input>;
module Impl = SsaImpl::Integration;

Impl::Node asNode(Node n) {
n = TSsaNode(result)
Expand All @@ -532,47 +498,12 @@ module SsaFlow {
}

predicate localFlowStep(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
Impl::localFlowStep(def, asNode(nodeFrom), asNode(nodeTo)) and
// exclude flow directly from RHS to SSA definition, as we instead want to
// go from RHS to matching assingnable definition, and from there to SSA definition
not Input::ssaDefAssigns(def, nodeFrom.(ExprNode).getControlFlowNode())
Impl::localFlowStep(def, asNode(nodeFrom), asNode(nodeTo))
}

predicate localMustFlowStep(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
Impl::localMustFlowStep(def, asNode(nodeFrom), asNode(nodeTo))
}

module BarrierGuardsInput implements Impl::BarrierGuardsInputSig {
private import semmle.code.csharp.controlflow.BasicBlocks
private import semmle.code.csharp.controlflow.Guards as Guards

class Guard extends Guards::Guard {
predicate hasCfgNode(ControlFlow::BasicBlock bb, int i) {
this.getAControlFlowNode() = bb.getNode(i)
}
}

/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
predicate guardControlsBlock(Guard guard, ControlFlow::BasicBlock bb, boolean branch) {
exists(ConditionBlock conditionBlock, ControlFlow::SuccessorTypes::ConditionalSuccessor s |
guard.getAControlFlowNode() = conditionBlock.getLastNode() and
s.getValue() = branch and
conditionBlock.controls(bb, s)
)
}

/** Gets an immediate conditional successor of basic block `bb`, if any. */
ControlFlow::BasicBlock getAConditionalBasicBlockSuccessor(
ControlFlow::BasicBlock bb, boolean branch
) {
exists(ControlFlow::SuccessorTypes::ConditionalSuccessor s |
result = bb.getASuccessorByType(s) and
s.getValue() = branch
)
}
}

module BarrierGuardsImpl = Impl::BarrierGuards<BarrierGuardsInput>;
}

/** Provides predicates related to local data flow. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ private import DataFlowDispatch
private import DataFlowPrivate
private import semmle.code.csharp.controlflow.Guards
private import semmle.code.csharp.Unification
private import SsaImpl as SsaImpl

/**
* An element, viewed as a node in a data flow graph. Either an expression
Expand Down Expand Up @@ -172,7 +173,7 @@ signature predicate guardChecksSig(Guard g, Expr e, AbstractValue v);
*/
module BarrierGuard<guardChecksSig/3 guardChecks> {
private predicate guardChecksAdj(
SsaFlow::BarrierGuardsInput::Guard g, SsaFlow::Input::Expr e, boolean branch
SsaImpl::IntegrationInput::Guard g, SsaImpl::IntegrationInput::Expr e, boolean branch
) {
exists(AbstractValues::BooleanValue v |
guardChecks(g, e.getAstNode(), v) and
Expand All @@ -184,7 +185,7 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
pragma[nomagic]
Node getABarrierNode() {
SsaFlow::asNode(result) =
SsaFlow::BarrierGuardsImpl::BarrierGuard<guardChecksAdj/3>::getABarrierNode()
SsaImpl::Integration::BarrierGuard<guardChecksAdj/3>::getABarrierNode()
or
exists(Guard g, Expr e, AbstractValue v |
guardChecks(g, e, v) and
Expand Down
65 changes: 65 additions & 0 deletions csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImpl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,9 @@ private module Cached {
outRefExitRead(bb, i, v)
)
}

cached
predicate forceCachingInSameStage() { Integration::localFlowStep(_, _, _) }
}

import Cached
Expand Down Expand Up @@ -1034,3 +1037,65 @@ class PhiReadNode extends DefinitionExt, Impl::PhiReadNode {
result = this.getSourceVariable().getEnclosingCallable()
}
}

module IntegrationInput implements Impl::DataFlowIntegrationInputSig {
private import csharp as Cs

Check warning

Code scanning / CodeQL

Names only differing by case Warning

Cs is only different by casing from CS that is used elsewhere for modules.
private import semmle.code.csharp.controlflow.BasicBlocks
private import semmle.code.csharp.controlflow.Guards as Guards

class Expr extends ControlFlow::Node {
predicate hasCfgNode(ControlFlow::BasicBlock bb, int i) { this = bb.getNode(i) }
}

predicate ssaDefAssigns(WriteDefinition def, Expr value) {
// exclude flow directly from RHS to SSA definition, as we instead want to
// go from RHS to matching assingnable definition, and from there to SSA definition
none()
}

class Parameter = Cs::Parameter;

predicate ssaDefInitializesParam(WriteDefinition def, Parameter p) {
def.(Ssa::ImplicitParameterDefinition).getParameter() = p
}

/**
* Allows for flow into uncertain defintions that are not call definitions,
* as we, conservatively, consider such definitions to be certain.
*/
predicate allowFlowIntoUncertainDef(UncertainWriteDefinition def) {
def instanceof Ssa::ExplicitDefinition
or
def =
any(Ssa::ImplicitQualifierDefinition qdef |
allowFlowIntoUncertainDef(qdef.getQualifierDefinition())
)
}

class Guard extends Guards::Guard {
predicate hasCfgNode(ControlFlow::BasicBlock bb, int i) {
this.getAControlFlowNode() = bb.getNode(i)
}
}

/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
predicate guardControlsBlock(Guard guard, ControlFlow::BasicBlock bb, boolean branch) {
exists(ConditionBlock conditionBlock, ControlFlow::SuccessorTypes::ConditionalSuccessor s |
guard.getAControlFlowNode() = conditionBlock.getLastNode() and
s.getValue() = branch and
conditionBlock.controls(bb, s)
)
}

/** Gets an immediate conditional successor of basic block `bb`, if any. */
ControlFlow::BasicBlock getAConditionalBasicBlockSuccessor(
ControlFlow::BasicBlock bb, boolean branch
) {
exists(ControlFlow::SuccessorTypes::ConditionalSuccessor s |
result = bb.getASuccessorByType(s) and
s.getValue() = branch
)
}
}

module Integration = Impl::DataFlowIntegration<IntegrationInput>;
Loading

0 comments on commit 0e357f7

Please sign in to comment.