Skip to content

Commit 1d5e5ac

Browse files
committed
wip
1 parent 29222e6 commit 1d5e5ac

File tree

9 files changed

+2053
-1006
lines changed

9 files changed

+2053
-1006
lines changed

java/ql/lib/semmle/code/java/dataflow/SSA.qll

Lines changed: 1055 additions & 817 deletions
Large diffs are not rendered by default.

java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class BaseSsaSourceVariable extends TBaseSsaSourceVariable {
5555
}
5656

5757
cached
58-
private module SsaImpl {
58+
private module BaseSsaImpl {
5959
/** Gets the destination variable of an update of a tracked variable. */
6060
cached
6161
BaseSsaSourceVariable getDestVar(VariableUpdate upd) {
@@ -436,7 +436,7 @@ private module SsaImpl {
436436
}
437437
}
438438

439-
private import SsaImpl
439+
private import BaseSsaImpl
440440
private import SsaDefReaches
441441
import SsaPublic
442442

java/ql/lib/semmle/code/java/dataflow/internal/DataFlowNodes.qll

Lines changed: 13 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ private import FlowSummaryImpl as FlowSummaryImpl
1010
private import DataFlowImplCommon as DataFlowImplCommon
1111
private import semmle.code.java.controlflow.Guards
1212
private import semmle.code.java.dataflow.RangeUtils
13+
private import SsaImpl as SsaImpl
1314

1415
/** Gets a string for approximating the name of a field. */
1516
string approximateFieldContent(FieldContent fc) { result = fc.getField().getName().prefix(1) }
@@ -22,117 +23,24 @@ private predicate deadcode(Expr e) {
2223
}
2324

2425
module SsaFlow {
25-
import codeql.ssa.Ssa
26+
module Impl = SsaImpl::DataFlowIntegration;
2627

27-
private module SsaInput implements InputSig<Location> {
28-
private import semmle.code.java.controlflow.BasicBlocks as BB
29-
private import semmle.code.java.controlflow.Dominance as Dom
30-
private import semmle.code.java.ControlFlowGraph as Cfg
31-
32-
class BasicBlock = BB::BasicBlock;
33-
34-
class ControlFlowNode = Cfg::ControlFlowNode;
35-
36-
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { Dom::bbIDominates(result, bb) }
37-
38-
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getABBSuccessor() }
39-
40-
class ExitBasicBlock extends BasicBlock {
41-
ExitBasicBlock() { not exists(this.getABBSuccessor()) }
42-
}
43-
44-
class SourceVariable = LocalScopeVariable;
45-
46-
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
47-
bb.getNode(i) =
48-
any(VariableUpdate upd |
49-
v.getAnAccess() = upd.(Assignment).getDest()
50-
or
51-
v = upd.(LocalVariableDeclExpr).getVariable()
52-
or
53-
v.getAnAccess() = upd.(UnaryAssignExpr).getExpr()
54-
) and
55-
certain = true
56-
or
57-
exists(Callable c |
58-
bb = c.getBody() and
59-
i = -1 and
60-
v = c.getAParameter() and
61-
certain = true
62-
)
63-
}
64-
65-
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
66-
bb.getNode(i).(VarRead).getVariable() = v and certain = true
67-
}
68-
}
69-
70-
module SsaImpl = Make<Location, SsaInput>;
71-
72-
module IntegrationInput implements SsaImpl::DataFlowIntegrationInputSig {
73-
private import java as J
74-
75-
class Expr instanceof J::Expr {
76-
string toString() { result = super.toString() }
77-
78-
Location getLocation() { result = super.getLocation() }
79-
80-
predicate hasCfgNode(BasicBlock bb, int i) { this = bb.(J::BasicBlock).getNode(i) }
81-
}
82-
83-
class Parameter = J::Parameter;
84-
85-
predicate ssaDefAssigns(SsaImpl::WriteDefinition def, Expr value) {
86-
exists(BasicBlock bb, int i, VariableUpdate upd |
87-
def.definesAt(_, bb, i) and
88-
bb.getNode(i) = upd
89-
|
90-
value = upd.(VariableAssign).getSource() or
91-
value = upd.(AssignOp) or
92-
value = upd.(RecordBindingVariableExpr)
93-
)
94-
}
95-
96-
predicate ssaDefInitializesParam(SsaImpl::WriteDefinition def, Parameter p) {
97-
def.definesAt(p, _, -1)
98-
}
99-
100-
private import semmle.code.java.controlflow.Guards as Guards
101-
102-
class Guard extends Guards::Guard {
103-
predicate hasCfgNode(SsaInput::BasicBlock bb, int i) { this = bb.getNode(i) }
104-
}
105-
106-
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
107-
predicate guardControlsBlock(Guard guard, SsaInput::BasicBlock bb, boolean branch) {
108-
guard.controls(bb, branch)
109-
}
110-
111-
/** Gets an immediate conditional successor of basic block `bb`, if any. */
112-
SsaInput::BasicBlock getAConditionalBasicBlockSuccessor(SsaInput::BasicBlock bb, boolean branch) {
113-
result = bb.(Guards::ConditionBlock).getTestSuccessor(branch)
114-
}
115-
}
116-
117-
module Integration = SsaImpl::DataFlowIntegration<IntegrationInput>;
118-
119-
Integration::Node asNode(Node n) {
28+
Impl::Node asNode(Node n) {
12029
n = TSsaNode(result)
12130
or
122-
result.(Integration::ExprNode).getExpr() = n.asExpr()
31+
result.(Impl::ExprNode).getExpr() = n.asExpr()
12332
or
124-
result.(Integration::ExprPostUpdateNode).getExpr() =
125-
n.(PostUpdateNode).getPreUpdateNode().asExpr()
33+
result.(Impl::ExprPostUpdateNode).getExpr() = n.(PostUpdateNode).getPreUpdateNode().asExpr()
12634
or
127-
TExplicitParameterNode(result.(Integration::ParameterNode).getParameter()) = n
35+
TExplicitParameterNode(result.(Impl::ParameterNode).getParameter()) = n
12836
}
12937

130-
predicate localFlowStep(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
131-
Integration::localFlowStep(def, asNode(nodeFrom), asNode(nodeTo))
38+
predicate localFlowStep(SsaImpl::Impl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
39+
Impl::localFlowStep(def, asNode(nodeFrom), asNode(nodeTo))
13240
}
13341

134-
predicate localMustFlowStep(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
135-
Integration::localMustFlowStep(def, asNode(nodeFrom), asNode(nodeTo))
42+
predicate localMustFlowStep(SsaImpl::Impl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
43+
Impl::localMustFlowStep(def, asNode(nodeFrom), asNode(nodeTo))
13644
}
13745
}
13846

@@ -146,7 +54,7 @@ private module Cached {
14654
not e.getType() instanceof VoidType and
14755
not e.getParent*() instanceof Annotation
14856
} or
149-
TSsaNode(SsaFlow::Integration::SsaNode node) or
57+
TSsaNode(SsaFlow::Impl::SsaNode node) or
15058
TExplicitParameterNode(Parameter p) { exists(p.getCallable().getBody()) } or
15159
TImplicitVarargsArray(Call c) {
15260
c.getCallee().isVarargs() and
@@ -317,11 +225,11 @@ module Public {
317225
}
318226

319227
class SsaNode extends Node, TSsaNode {
320-
private SsaFlow::Integration::SsaNode node;
228+
private SsaFlow::Impl::SsaNode node;
321229

322230
SsaNode() { this = TSsaNode(node) }
323231

324-
SsaFlow::SsaImpl::DefinitionExt getDefinitionExt() { result = node.getDefinitionExt() }
232+
SsaImpl::Impl::DefinitionExt getDefinitionExt() { result = node.getDefinitionExt() }
325233

326234
override Location getLocation() { result = node.getLocation() }
327235

java/ql/lib/semmle/code/java/dataflow/internal/DataFlowUtil.qll

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ private import semmle.code.java.dataflow.FlowSummary
1212
private import semmle.code.java.dataflow.InstanceAccess
1313
private import FlowSummaryImpl as FlowSummaryImpl
1414
private import TaintTrackingUtil as TaintTrackingUtil
15+
private import SsaImpl as SsaImpl
1516
private import DataFlowNodes
1617
import DataFlowNodes::Public
1718

@@ -99,6 +100,10 @@ predicate hasNonlocalValue(FieldRead fr) {
99100
)
100101
}
101102

103+
private predicate capturedVariableRead(Node n) {
104+
n.asExpr().(VarRead).getVariable() instanceof CapturedVariable
105+
}
106+
102107
cached
103108
private module Cached {
104109
/**
@@ -126,6 +131,10 @@ private module Cached {
126131
simpleLocalFlowStep0(node1, node2, model)
127132
or
128133
SsaFlow::localFlowStep(_, node1, node2) and
134+
not capturedVariableRead(node2) and
135+
not exists(FieldRead fr |
136+
hasNonlocalValue(fr) and fr.getField().isStatic() and fr = node1.asExpr()
137+
) and
129138
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(node1, _) and
130139
model = ""
131140
or
@@ -136,6 +145,11 @@ private module Cached {
136145
// prevent recursive call
137146
(any(AdditionalValueStep a).step(_, _) implies any())
138147
}
148+
149+
cached
150+
Node getABarrierNode(Guard guard, SsaVariable def, boolean branch) {
151+
SsaFlow::asNode(result) = SsaImpl::DataFlowIntegration::getABarrierNode(guard, def, branch)
152+
}
139153
}
140154

141155
/**
@@ -368,23 +382,16 @@ signature predicate guardChecksSig(Guard g, Expr e, boolean branch);
368382
* in data flow and taint tracking.
369383
*/
370384
module BarrierGuard<guardChecksSig/3 guardChecks> {
371-
// pragma[nomagic]
372-
// private predicate guardChecksSsaDef(Guard g, SsaFlow::SsaImpl::Definition def, boolean branch) {
373-
// guardChecks(g, def.get, branch)
374-
// }
385+
pragma[nomagic]
386+
private predicate guardChecksSsaDef(Guard g, SsaVariable v, boolean branch) {
387+
guardChecks(g, v.getAUse(), branch)
388+
}
389+
375390
/** Gets a node that is safely guarded by the given guard check. */
376391
Node getABarrierNode() {
377-
// still needed for fields
378-
exists(Guard g, SsaVariable v, boolean branch, VarRead use |
379-
guardChecks(g, v.getAUse(), branch) and
380-
use = v.getAUse() and
381-
g.controls(use.getBasicBlock(), branch) and
382-
result.asExpr() = use
392+
exists(Guard g, SsaVariable v, boolean branch |
393+
guardChecksSsaDef(g, v, branch) and
394+
result = getABarrierNode(g, v, branch)
383395
)
384-
// or
385-
// exists(Guard g, SsaFlow::SsaImpl::Definition def, boolean branch |
386-
// guardChecksSsaDef(g, def, branch) and
387-
// SsaFlow::asNode(result) = SsaFlow::Integration::getABarrierNode(g, def, branch)
388-
// )
389396
}
390397
}

0 commit comments

Comments
 (0)