Skip to content

Commit c8094d3

Browse files
committed
Dataflow: Add type-based call-edge pruning.
1 parent 3004255 commit c8094d3

File tree

5 files changed

+663
-95
lines changed

5 files changed

+663
-95
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,13 +326,18 @@ string ppReprType(DataFlowType t) {
326326
else result = t.toString()
327327
}
328328

329+
pragma[nomagic]
330+
private predicate compatibleTypes0(DataFlowType t1, DataFlowType t2) {
331+
erasedHaveIntersection(t1, t2)
332+
}
333+
329334
/**
330335
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
331336
* a node of type `t1` to a node of type `t2`.
332337
*/
333338
bindingset[t1, t2]
334339
pragma[inline_late]
335-
predicate compatibleTypes(DataFlowType t1, DataFlowType t2) { erasedHaveIntersection(t1, t2) }
340+
predicate compatibleTypes(DataFlowType t1, DataFlowType t2) { compatibleTypes0(t1, t2) }
336341

337342
/** A node that performs a type cast. */
338343
class CastNode extends ExprNode {

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,39 @@ private module Cached {
133133
}
134134
}
135135

136+
/**
137+
* Holds if the value of `node2` is given by `node1`.
138+
*/
139+
predicate localMustFlowStep(Node node1, Node node2) {
140+
exists(Callable c | node1.(InstanceParameterNode).getCallable() = c |
141+
exists(InstanceAccess ia |
142+
ia = node2.asExpr() and ia.getEnclosingCallable() = c and ia.isOwnInstanceAccess()
143+
)
144+
or
145+
c =
146+
node2.(ImplicitInstanceAccess).getInstanceAccess().(OwnInstanceAccess).getEnclosingCallable()
147+
)
148+
or
149+
exists(SsaImplicitInit init |
150+
init.isParameterDefinition(node1.asParameter()) and init.getAUse() = node2.asExpr()
151+
)
152+
or
153+
exists(SsaExplicitUpdate upd |
154+
upd.getDefiningExpr().(VariableAssign).getSource() = node1.asExpr() and
155+
upd.getAUse() = node2.asExpr()
156+
)
157+
or
158+
node2.asExpr().(CastingExpr).getExpr() = node1.asExpr()
159+
or
160+
node2.asExpr().(AssignExpr).getSource() = node1.asExpr()
161+
or
162+
node1 =
163+
unique(FlowSummaryNode n1 |
164+
FlowSummaryImpl::Private::Steps::summaryLocalStep(n1.getSummaryNode(),
165+
node2.(FlowSummaryNode).getSummaryNode(), true)
166+
)
167+
}
168+
136169
import Cached
137170

138171
private predicate capturedVariableRead(Node n) {

shared/dataflow/codeql/dataflow/DataFlow.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,11 @@ signature module InputSig {
197197
*/
198198
predicate allowParameterReturnInSelf(ParameterNode p);
199199

200+
/**
201+
* Holds if the value of `node2` is given by `node1`.
202+
*/
203+
predicate localMustFlowStep(Node node1, Node node2);
204+
200205
class LambdaCallKind;
201206

202207
/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */

0 commit comments

Comments
 (0)