Skip to content

Commit fe07630

Browse files
authored
Merge pull request github#5219 from smowton/smowton/feature/backward-dataflow-for-fluent-methods
Java: Add backward dataflow edges through fluent function invocations.
2 parents 342c7ab + 5d2f342 commit fe07630

35 files changed

+300
-23
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* The data-flow library now recognises more side-effects of method chaining (e.g. `someObject.setX(clean).setY(tainted).setZ...` having a side-effect on `someObject`), as well as other related circumstances where a function input is directly passed to its output. All queries that use data-flow analysis, including most security queries, may return more results accordingly.

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep(
223223
* Holds if data can flow in one local step from `node1` to `node2`.
224224
*/
225225
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
226-
simpleLocalFlowStep(node1, node2) and
226+
(
227+
simpleLocalFlowStep(node1, node2) or
228+
reverseStepThroughInputOutputAlias(node1, node2)
229+
) and
227230
not outBarrier(node1, config) and
228231
not inBarrier(node2, config) and
229232
not fullBarrier(node1, config) and

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep(
223223
* Holds if data can flow in one local step from `node1` to `node2`.
224224
*/
225225
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
226-
simpleLocalFlowStep(node1, node2) and
226+
(
227+
simpleLocalFlowStep(node1, node2) or
228+
reverseStepThroughInputOutputAlias(node1, node2)
229+
) and
227230
not outBarrier(node1, config) and
228231
not inBarrier(node2, config) and
229232
not fullBarrier(node1, config) and

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep(
223223
* Holds if data can flow in one local step from `node1` to `node2`.
224224
*/
225225
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
226-
simpleLocalFlowStep(node1, node2) and
226+
(
227+
simpleLocalFlowStep(node1, node2) or
228+
reverseStepThroughInputOutputAlias(node1, node2)
229+
) and
227230
not outBarrier(node1, config) and
228231
not inBarrier(node2, config) and
229232
not fullBarrier(node1, config) and

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep(
223223
* Holds if data can flow in one local step from `node1` to `node2`.
224224
*/
225225
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
226-
simpleLocalFlowStep(node1, node2) and
226+
(
227+
simpleLocalFlowStep(node1, node2) or
228+
reverseStepThroughInputOutputAlias(node1, node2)
229+
) and
227230
not outBarrier(node1, config) and
228231
not inBarrier(node2, config) and
229232
not fullBarrier(node1, config) and

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,30 @@ private module Cached {
415415
store(node1, tc.getContent(), node2, contentType, tc.getContainerType())
416416
}
417417

418+
/**
419+
* Holds if data can flow from `fromNode` to `toNode` because they are the post-update
420+
* nodes of some function output and input respectively, where the output and input
421+
* are aliases. A typical example is a function returning `this`, implementing a fluent
422+
* interface.
423+
*/
424+
cached
425+
predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) {
426+
exists(Node fromPre, Node toPre |
427+
fromPre = fromNode.getPreUpdateNode() and
428+
toPre = toNode.getPreUpdateNode()
429+
|
430+
exists(DataFlowCall c |
431+
// Does the language-specific simpleLocalFlowStep already model flow
432+
// from function input to output?
433+
fromPre = getAnOutNode(c, _) and
434+
toPre.(ArgumentNode).argumentOf(c, _) and
435+
simpleLocalFlowStep(toPre.(ArgumentNode), fromPre)
436+
)
437+
or
438+
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
439+
)
440+
}
441+
418442
/**
419443
* Holds if the call context `call` either improves virtual dispatch in
420444
* `callable` or if it allows us to prune unreachable nodes in `callable`.

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep(
223223
* Holds if data can flow in one local step from `node1` to `node2`.
224224
*/
225225
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
226-
simpleLocalFlowStep(node1, node2) and
226+
(
227+
simpleLocalFlowStep(node1, node2) or
228+
reverseStepThroughInputOutputAlias(node1, node2)
229+
) and
227230
not outBarrier(node1, config) and
228231
not inBarrier(node2, config) and
229232
not fullBarrier(node1, config) and

cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep(
223223
* Holds if data can flow in one local step from `node1` to `node2`.
224224
*/
225225
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
226-
simpleLocalFlowStep(node1, node2) and
226+
(
227+
simpleLocalFlowStep(node1, node2) or
228+
reverseStepThroughInputOutputAlias(node1, node2)
229+
) and
227230
not outBarrier(node1, config) and
228231
not inBarrier(node2, config) and
229232
not fullBarrier(node1, config) and

cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep(
223223
* Holds if data can flow in one local step from `node1` to `node2`.
224224
*/
225225
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
226-
simpleLocalFlowStep(node1, node2) and
226+
(
227+
simpleLocalFlowStep(node1, node2) or
228+
reverseStepThroughInputOutputAlias(node1, node2)
229+
) and
227230
not outBarrier(node1, config) and
228231
not inBarrier(node2, config) and
229232
not fullBarrier(node1, config) and

cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,10 @@ private predicate isAdditionalFlowStep(
223223
* Holds if data can flow in one local step from `node1` to `node2`.
224224
*/
225225
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
226-
simpleLocalFlowStep(node1, node2) and
226+
(
227+
simpleLocalFlowStep(node1, node2) or
228+
reverseStepThroughInputOutputAlias(node1, node2)
229+
) and
227230
not outBarrier(node1, config) and
228231
not inBarrier(node2, config) and
229232
not fullBarrier(node1, config) and

0 commit comments

Comments
 (0)