Skip to content

Commit a93296e

Browse files
committed
perf
1 parent 92b14b6 commit a93296e

File tree

8 files changed

+268
-233
lines changed

8 files changed

+268
-233
lines changed

csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll

Lines changed: 10 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,9 @@ module VariableCapture {
256256
private predicate closureFlowStep(ControlFlow::Nodes::ExprNode e1, ControlFlow::Nodes::ExprNode e2) {
257257
e1 = LocalFlow::getALastEvalNode(e2)
258258
or
259-
exists(Ssa::Definition def |
260-
SsaFlow::Input::ssaDefAssigns(def.getAnUltimateDefinition(), e1) and
259+
exists(Ssa::Definition def, AssignableDefinition adef |
260+
LocalFlow::defAssigns(adef, _, e1) and
261+
def.getAnUltimateDefinition().(Ssa::ExplicitDefinition).getADefinition() = adef and
261262
exists(def.getAReadAtNode(e2))
262263
)
263264
}
@@ -483,42 +484,7 @@ module VariableCapture {
483484

484485
/** Provides logic related to SSA. */
485486
module SsaFlow {
486-
module Input implements SsaImpl::Impl::DataFlowIntegrationInputSig {
487-
private import csharp as Cs
488-
489-
class Expr extends ControlFlow::Node {
490-
predicate hasCfgNode(ControlFlow::BasicBlock bb, int i) { this = bb.getNode(i) }
491-
}
492-
493-
predicate ssaDefAssigns(SsaImpl::WriteDefinition def, Expr value) {
494-
exists(AssignableDefinition adef, ControlFlow::Node cfnDef |
495-
any(LocalFlow::LocalExprStepConfiguration conf).hasDefPath(_, value, adef, cfnDef) and
496-
def.(Ssa::ExplicitDefinition).getADefinition() = adef and
497-
def.(Ssa::ExplicitDefinition).getControlFlowNode() = cfnDef
498-
)
499-
}
500-
501-
class Parameter = Cs::Parameter;
502-
503-
predicate ssaDefInitializesParam(SsaImpl::WriteDefinition def, Parameter p) {
504-
def.(Ssa::ImplicitParameterDefinition).getParameter() = p
505-
}
506-
507-
/**
508-
* Allows for flow into uncertain defintions that are not call definitions,
509-
* as we, conservatively, consider such definitions to be certain.
510-
*/
511-
predicate allowFlowIntoUncertainDef(SsaImpl::UncertainWriteDefinition def) {
512-
def instanceof Ssa::ExplicitDefinition
513-
or
514-
def =
515-
any(Ssa::ImplicitQualifierDefinition qdef |
516-
allowFlowIntoUncertainDef(qdef.getQualifierDefinition())
517-
)
518-
}
519-
}
520-
521-
module Impl = SsaImpl::Impl::DataFlowIntegration<Input>;
487+
module Impl = SsaImpl::DataFlowIntegration;
522488

523489
Impl::Node asNode(Node n) {
524490
n = TSsaNode(result)
@@ -532,47 +498,12 @@ module SsaFlow {
532498
}
533499

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

541504
predicate localMustFlowStep(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
542505
Impl::localMustFlowStep(def, asNode(nodeFrom), asNode(nodeTo))
543506
}
544-
545-
module BarrierGuardsInput implements Impl::BarrierGuardsInputSig {
546-
private import semmle.code.csharp.controlflow.BasicBlocks
547-
private import semmle.code.csharp.controlflow.Guards as Guards
548-
549-
class Guard extends Guards::Guard {
550-
predicate hasCfgNode(ControlFlow::BasicBlock bb, int i) {
551-
this.getAControlFlowNode() = bb.getNode(i)
552-
}
553-
}
554-
555-
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
556-
predicate guardControlsBlock(Guard guard, ControlFlow::BasicBlock bb, boolean branch) {
557-
exists(ConditionBlock conditionBlock, ControlFlow::SuccessorTypes::ConditionalSuccessor s |
558-
guard.getAControlFlowNode() = conditionBlock.getLastNode() and
559-
s.getValue() = branch and
560-
conditionBlock.controls(bb, s)
561-
)
562-
}
563-
564-
/** Gets an immediate conditional successor of basic block `bb`, if any. */
565-
ControlFlow::BasicBlock getAConditionalBasicBlockSuccessor(
566-
ControlFlow::BasicBlock bb, boolean branch
567-
) {
568-
exists(ControlFlow::SuccessorTypes::ConditionalSuccessor s |
569-
result = bb.getASuccessorByType(s) and
570-
s.getValue() = branch
571-
)
572-
}
573-
}
574-
575-
module BarrierGuardsImpl = Impl::BarrierGuards<BarrierGuardsInput>;
576507
}
577508

578509
/** Provides predicates related to local data flow. */
@@ -1200,6 +1131,11 @@ private module Cached {
12001131
newtype TDataFlowType =
12011132
TGvnDataFlowType(Gvn::GvnType t) or
12021133
TDelegateDataFlowType(Callable lambda) { lambdaCreationExpr(_, lambda) }
1134+
1135+
cached
1136+
Node getABarrierNode(Guard guard, Ssa::Definition def, boolean branch) {
1137+
SsaFlow::asNode(result) = SsaImpl::DataFlowIntegration::getABarrierNode(guard, def, branch)
1138+
}
12031139
}
12041140

12051141
import Cached

csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -171,20 +171,21 @@ signature predicate guardChecksSig(Guard g, Expr e, AbstractValue v);
171171
* in data flow and taint tracking.
172172
*/
173173
module BarrierGuard<guardChecksSig/3 guardChecks> {
174-
private predicate guardChecksAdj(
175-
SsaFlow::BarrierGuardsInput::Guard g, SsaFlow::Input::Expr e, boolean branch
176-
) {
174+
pragma[nomagic]
175+
private predicate guardChecksSsaDef(Guard g, Ssa::Definition def, boolean branch) {
177176
exists(AbstractValues::BooleanValue v |
178-
guardChecks(g, e.getAstNode(), v) and
177+
guardChecks(g, def.getARead(), v) and
179178
branch = v.getValue()
180179
)
181180
}
182181

183182
/** Gets a node that is safely guarded by the given guard check. */
184183
pragma[nomagic]
185184
Node getABarrierNode() {
186-
SsaFlow::asNode(result) =
187-
SsaFlow::BarrierGuardsImpl::BarrierGuard<guardChecksAdj/3>::getABarrierNode()
185+
exists(Guard g, Ssa::Definition def, boolean branch |
186+
result = getABarrierNode(g, def, branch) and
187+
guardChecksSsaDef(g, def, branch)
188+
)
188189
or
189190
exists(Guard g, Expr e, AbstractValue v |
190191
guardChecks(g, e, v) and

csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImpl.qll

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -977,6 +977,15 @@ private module Cached {
977977
outRefExitRead(bb, i, v)
978978
)
979979
}
980+
981+
private import TaintTrackingPrivate as TaintTrackingPrivate
982+
983+
cached
984+
predicate forceCachingInSameStage() {
985+
// needed in order to avoid recomputing SSA predicates in the `Integration` module
986+
TaintTrackingPrivate::forceCachingInSameStage() and
987+
DataFlowIntegration::localFlowStep(_, _, _)
988+
}
980989
}
981990

982991
import Cached
@@ -1034,3 +1043,65 @@ class PhiReadNode extends DefinitionExt, Impl::PhiReadNode {
10341043
result = this.getSourceVariable().getEnclosingCallable()
10351044
}
10361045
}
1046+
1047+
private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInputSig {
1048+
private import csharp as Cs
1049+
private import semmle.code.csharp.controlflow.BasicBlocks
1050+
private import semmle.code.csharp.controlflow.Guards as Guards
1051+
1052+
class Expr extends ControlFlow::Node {
1053+
predicate hasCfgNode(ControlFlow::BasicBlock bb, int i) { this = bb.getNode(i) }
1054+
}
1055+
1056+
predicate ssaDefAssigns(WriteDefinition def, Expr value) {
1057+
// exclude flow directly from RHS to SSA definition, as we instead want to
1058+
// go from RHS to matching assingnable definition, and from there to SSA definition
1059+
none()
1060+
}
1061+
1062+
class Parameter = Cs::Parameter;
1063+
1064+
predicate ssaDefInitializesParam(WriteDefinition def, Parameter p) {
1065+
def.(Ssa::ImplicitParameterDefinition).getParameter() = p
1066+
}
1067+
1068+
/**
1069+
* Allows for flow into uncertain defintions that are not call definitions,
1070+
* as we, conservatively, consider such definitions to be certain.
1071+
*/
1072+
predicate allowFlowIntoUncertainDef(UncertainWriteDefinition def) {
1073+
def instanceof Ssa::ExplicitDefinition
1074+
or
1075+
def =
1076+
any(Ssa::ImplicitQualifierDefinition qdef |
1077+
allowFlowIntoUncertainDef(qdef.getQualifierDefinition())
1078+
)
1079+
}
1080+
1081+
class Guard extends Guards::Guard {
1082+
predicate hasCfgNode(ControlFlow::BasicBlock bb, int i) {
1083+
this.getAControlFlowNode() = bb.getNode(i)
1084+
}
1085+
}
1086+
1087+
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
1088+
predicate guardControlsBlock(Guard guard, ControlFlow::BasicBlock bb, boolean branch) {
1089+
exists(ConditionBlock conditionBlock, ControlFlow::SuccessorTypes::ConditionalSuccessor s |
1090+
guard.getAControlFlowNode() = conditionBlock.getLastNode() and
1091+
s.getValue() = branch and
1092+
conditionBlock.controls(bb, s)
1093+
)
1094+
}
1095+
1096+
/** Gets an immediate conditional successor of basic block `bb`, if any. */
1097+
ControlFlow::BasicBlock getAConditionalBasicBlockSuccessor(
1098+
ControlFlow::BasicBlock bb, boolean branch
1099+
) {
1100+
exists(ControlFlow::SuccessorTypes::ConditionalSuccessor s |
1101+
result = bb.getASuccessorByType(s) and
1102+
s.getValue() = branch
1103+
)
1104+
}
1105+
}
1106+
1107+
module DataFlowIntegration = Impl::DataFlowIntegration<DataFlowIntegrationInput>;

ruby/ql/lib/codeql/ruby/dataflow/SSA.qll

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,15 +202,32 @@ module Ssa {
202202
final VariableWriteAccessCfgNode getWriteAccess() { result = write }
203203

204204
/**
205-
* Holds if this SSA definition represents a direct assignment of `value`
206-
* to the underlying variable.
205+
* Holds if this SSA definition assigns `value` to the underlying variable.
206+
*
207+
* This is either a direct assignment, `x = value`, or an assignment via
208+
* simple pattern matching
209+
*
210+
* ```rb
211+
* case value
212+
* in Foo => x then ...
213+
* in y => then ...
214+
* end
215+
* ```
207216
*/
208217
predicate assigns(CfgNodes::ExprCfgNode value) {
209218
exists(CfgNodes::ExprNodes::AssignExprCfgNode a, BasicBlock bb, int i |
210219
this.definesAt(_, bb, i) and
211220
a = bb.getNode(i) and
212221
value = a.getRhs()
213222
)
223+
or
224+
exists(CfgNodes::ExprNodes::CaseExprCfgNode case, CfgNodes::AstCfgNode pattern |
225+
case.getValue() = value and
226+
pattern = case.getBranch(_).(CfgNodes::ExprNodes::InClauseCfgNode).getPattern()
227+
|
228+
this.getWriteAccess() =
229+
[pattern, pattern.(CfgNodes::ExprNodes::AsPatternCfgNode).getVariableAccess()]
230+
)
214231
}
215232

216233
final override string toString() { result = write.toString() }

0 commit comments

Comments
 (0)