Skip to content

Commit 8beef45

Browse files
authored
Merge pull request #9195 from aschackmull/java/perf-local-flow
Java: Performance fixes for local flow relation
2 parents 20af134 + 651d9d0 commit 8beef45

File tree

12 files changed

+105
-50
lines changed

12 files changed

+105
-50
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,7 @@ private module Cached {
769769
or
770770
// Simple flow through library code is included in the exposed local
771771
// step relation, even though flow is technically inter-procedural
772-
FlowSummaryImpl::Private::Steps::summaryThroughStep(nodeFrom, nodeTo, true)
772+
FlowSummaryImpl::Private::Steps::summaryThroughStepValue(nodeFrom, nodeTo)
773773
}
774774

775775
cached

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

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -791,24 +791,37 @@ module Private {
791791
private ParamNode summaryArgParam(ArgNode arg, ReturnNodeExt ret, OutNodeExt out) {
792792
exists(DataFlowCall call, ReturnKindExt rk |
793793
result = summaryArgParam0(call, arg) and
794-
pragma[only_bind_out](ret).getKind() = pragma[only_bind_into](rk) and
794+
ret.getKind() = pragma[only_bind_into](rk) and
795795
out = pragma[only_bind_into](rk).getAnOutNode(call)
796796
)
797797
}
798798

799799
/**
800-
* Holds if `arg` flows to `out` using a simple flow summary, that is, a flow
801-
* summary without reads and stores.
800+
* Holds if `arg` flows to `out` using a simple value-preserving flow
801+
* summary, that is, a flow summary without reads and stores.
802802
*
803803
* NOTE: This step should not be used in global data-flow/taint-tracking, but may
804804
* be useful to include in the exposed local data-flow/taint-tracking relations.
805805
*/
806-
predicate summaryThroughStep(ArgNode arg, Node out, boolean preservesValue) {
807-
exists(ReturnNodeExt ret |
808-
summaryLocalStep(summaryArgParam(arg, ret, out), ret, preservesValue)
806+
predicate summaryThroughStepValue(ArgNode arg, Node out) {
807+
exists(ReturnKind rk, ReturnNode ret, DataFlowCall call |
808+
summaryLocalStep(summaryArgParam0(call, arg), ret, true) and
809+
ret.getKind() = pragma[only_bind_into](rk) and
810+
out = getAnOutNode(call, pragma[only_bind_into](rk))
809811
)
810812
}
811813

814+
/**
815+
* Holds if `arg` flows to `out` using a simple flow summary involving taint
816+
* step, that is, a flow summary without reads and stores.
817+
*
818+
* NOTE: This step should not be used in global data-flow/taint-tracking, but may
819+
* be useful to include in the exposed local data-flow/taint-tracking relations.
820+
*/
821+
predicate summaryThroughStepTaint(ArgNode arg, Node out) {
822+
exists(ReturnNodeExt ret | summaryLocalStep(summaryArgParam(arg, ret, out), ret, false))
823+
}
824+
812825
/**
813826
* Holds if there is a read(+taint) of `c` from `arg` to `out` using a
814827
* flow summary.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ private module Cached {
117117
(
118118
// Simple flow through library code is included in the exposed local
119119
// step relation, even though flow is technically inter-procedural
120-
FlowSummaryImpl::Private::Steps::summaryThroughStep(nodeFrom, nodeTo, false)
120+
FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(nodeFrom, nodeTo)
121121
or
122122
// Taint collection by adding a tainted element
123123
exists(DataFlow::ElementContent c |

csharp/ql/test/library-tests/dataflow/external-models/steps.ql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ class SummaryModelTest extends SummaryModelCsv {
3131
query predicate summaryThroughStep(
3232
DataFlow::Node node1, DataFlow::Node node2, boolean preservesValue
3333
) {
34-
FlowSummaryImpl::Private::Steps::summaryThroughStep(node1, node2, preservesValue)
34+
FlowSummaryImpl::Private::Steps::summaryThroughStepValue(node1, node2) and preservesValue = true
35+
or
36+
FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(node1, node2) and preservesValue = false
3537
}
3638

3739
query predicate summaryGetterStep(DataFlow::Node arg, DataFlow::Node out, Content c) {

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

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,9 @@ private module ThisFlow {
7575
* local (intra-procedural) steps.
7676
*/
7777
pragma[inline]
78-
predicate localFlow(Node node1, Node node2) { localFlowStep*(node1, node2) }
78+
predicate localFlow(Node node1, Node node2) { node1 = node2 or localFlowStepPlus(node1, node2) }
79+
80+
private predicate localFlowStepPlus(Node node1, Node node2) = fastTC(localFlowStep/2)(node1, node2)
7981

8082
/**
8183
* Holds if data can flow from `e1` to `e2` in zero or more
@@ -97,27 +99,43 @@ predicate hasNonlocalValue(FieldRead fr) {
9799
)
98100
}
99101

100-
/**
101-
* Holds if data can flow from `node1` to `node2` in one local step.
102-
*/
103-
predicate localFlowStep(Node node1, Node node2) {
104-
simpleLocalFlowStep(node1, node2)
105-
or
106-
adjacentUseUse(node1.asExpr(), node2.asExpr())
107-
or
108-
// Simple flow through library code is included in the exposed local
109-
// step relation, even though flow is technically inter-procedural
110-
FlowSummaryImpl::Private::Steps::summaryThroughStep(node1, node2, true)
102+
cached
103+
private module Cached {
104+
/**
105+
* Holds if data can flow from `node1` to `node2` in one local step.
106+
*/
107+
cached
108+
predicate localFlowStep(Node node1, Node node2) {
109+
simpleLocalFlowStep0(node1, node2)
110+
or
111+
adjacentUseUse(node1.asExpr(), node2.asExpr())
112+
or
113+
// Simple flow through library code is included in the exposed local
114+
// step relation, even though flow is technically inter-procedural
115+
FlowSummaryImpl::Private::Steps::summaryThroughStepValue(node1, node2)
116+
}
117+
118+
/**
119+
* INTERNAL: do not use.
120+
*
121+
* This is the local flow predicate that's used as a building block in global
122+
* data flow. It may have less flow than the `localFlowStep` predicate.
123+
*/
124+
cached
125+
predicate simpleLocalFlowStep(Node node1, Node node2) {
126+
simpleLocalFlowStep0(node1, node2)
127+
or
128+
any(AdditionalValueStep a).step(node1, node2) and
129+
pragma[only_bind_out](node1.getEnclosingCallable()) =
130+
pragma[only_bind_out](node2.getEnclosingCallable()) and
131+
// prevent recursive call
132+
(any(AdditionalValueStep a).step(_, _) implies any())
133+
}
111134
}
112135

113-
/**
114-
* INTERNAL: do not use.
115-
*
116-
* This is the local flow predicate that's used as a building block in global
117-
* data flow. It may have less flow than the `localFlowStep` predicate.
118-
*/
119-
cached
120-
predicate simpleLocalFlowStep(Node node1, Node node2) {
136+
import Cached
137+
138+
private predicate simpleLocalFlowStep0(Node node1, Node node2) {
121139
TaintTrackingUtil::forceCachingInSameStage() and
122140
// Variable flow steps through adjacent def-use and use-use pairs.
123141
exists(SsaExplicitUpdate upd |
@@ -166,10 +184,6 @@ predicate simpleLocalFlowStep(Node node1, Node node2) {
166184
)
167185
or
168186
FlowSummaryImpl::Private::Steps::summaryLocalStep(node1, node2, true)
169-
or
170-
any(AdditionalValueStep a).step(node1, node2) and
171-
pragma[only_bind_out](node1.getEnclosingCallable()) =
172-
pragma[only_bind_out](node2.getEnclosingCallable())
173187
}
174188

175189
private newtype TContent =

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

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -791,24 +791,37 @@ module Private {
791791
private ParamNode summaryArgParam(ArgNode arg, ReturnNodeExt ret, OutNodeExt out) {
792792
exists(DataFlowCall call, ReturnKindExt rk |
793793
result = summaryArgParam0(call, arg) and
794-
pragma[only_bind_out](ret).getKind() = pragma[only_bind_into](rk) and
794+
ret.getKind() = pragma[only_bind_into](rk) and
795795
out = pragma[only_bind_into](rk).getAnOutNode(call)
796796
)
797797
}
798798

799799
/**
800-
* Holds if `arg` flows to `out` using a simple flow summary, that is, a flow
801-
* summary without reads and stores.
800+
* Holds if `arg` flows to `out` using a simple value-preserving flow
801+
* summary, that is, a flow summary without reads and stores.
802802
*
803803
* NOTE: This step should not be used in global data-flow/taint-tracking, but may
804804
* be useful to include in the exposed local data-flow/taint-tracking relations.
805805
*/
806-
predicate summaryThroughStep(ArgNode arg, Node out, boolean preservesValue) {
807-
exists(ReturnNodeExt ret |
808-
summaryLocalStep(summaryArgParam(arg, ret, out), ret, preservesValue)
806+
predicate summaryThroughStepValue(ArgNode arg, Node out) {
807+
exists(ReturnKind rk, ReturnNode ret, DataFlowCall call |
808+
summaryLocalStep(summaryArgParam0(call, arg), ret, true) and
809+
ret.getKind() = pragma[only_bind_into](rk) and
810+
out = getAnOutNode(call, pragma[only_bind_into](rk))
809811
)
810812
}
811813

814+
/**
815+
* Holds if `arg` flows to `out` using a simple flow summary involving taint
816+
* step, that is, a flow summary without reads and stores.
817+
*
818+
* NOTE: This step should not be used in global data-flow/taint-tracking, but may
819+
* be useful to include in the exposed local data-flow/taint-tracking relations.
820+
*/
821+
predicate summaryThroughStepTaint(ArgNode arg, Node out) {
822+
exists(ReturnNodeExt ret | summaryLocalStep(summaryArgParam(arg, ret, out), ret, false))
823+
}
824+
812825
/**
813826
* Holds if there is a read(+taint) of `c` from `arg` to `out` using a
814827
* flow summary.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ private module Cached {
5151
or
5252
// Simple flow through library code is included in the exposed local
5353
// step relation, even though flow is technically inter-procedural
54-
FlowSummaryImpl::Private::Steps::summaryThroughStep(src, sink, false)
54+
FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(src, sink)
5555
or
5656
// Treat container flow as taint for the local taint flow relation
5757
exists(DataFlow::Content c | containerContent(c) |

java/ql/test/library-tests/dataflow/external-models/steps.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,5 @@ class SummaryModelTest extends SummaryModelCsv {
2222
}
2323

2424
from DataFlow::Node node1, DataFlow::Node node2
25-
where FlowSummaryImpl::Private::Steps::summaryThroughStep(node1, node2, false)
25+
where FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(node1, node2)
2626
select node1, node2

java/ql/test/library-tests/dataflow/local-additional-taint/localAdditionalTaintStep.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ from DataFlow::Node src, DataFlow::Node sink
1616
where
1717
(
1818
localAdditionalTaintStep(src, sink) or
19-
FlowSummaryImpl::Private::Steps::summaryThroughStep(src, sink, false)
19+
FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(src, sink)
2020
) and
2121
not FlowSummaryImpl::Private::Steps::summaryLocalStep(src, sink, false) and
2222
not FlowSummaryImpl::Private::Steps::summaryReadStep(src, _, sink) and

ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ private module Cached {
272272
or
273273
// Simple flow through library code is included in the exposed local
274274
// step relation, even though flow is technically inter-procedural
275-
FlowSummaryImpl::Private::Steps::summaryThroughStep(nodeFrom, nodeTo, true)
275+
FlowSummaryImpl::Private::Steps::summaryThroughStepValue(nodeFrom, nodeTo)
276276
}
277277

278278
/** This is the local flow predicate that is used in type tracking. */

0 commit comments

Comments
 (0)