Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 40b0f68

Browse files
committed
Add backward dataflow edges through modelled function invocations.
Also add convenience abstract classes for easily modelling new functions as fluent or value-preserving.
1 parent fe07630 commit 40b0f68

3 files changed

Lines changed: 74 additions & 0 deletions

File tree

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,36 @@ predicate hasNonlocalValue(FieldRead fr) {
368368
*/
369369
predicate localFlowStep(Node node1, Node node2) { simpleLocalFlowStep(node1, node2) }
370370

371+
/**
372+
* A method or constructor that returns the exact value of one of its parameters or the qualifier.
373+
*
374+
* Extend this class and override `returnsValue` to add additional value-preserving steps through a
375+
* method that should be added to the basic local flow step relation.
376+
*
377+
* These steps will be visible for all global data-flow purposes, as well as via
378+
* `DataFlow::Node.getASuccessor` and other related functions exposing intraprocedural dataflow.
379+
*/
380+
abstract class ValuePreservingCallable extends Callable {
381+
/**
382+
* Holds if this callable returns precisely the value passed into argument `arg`.
383+
* `arg` is a parameter index, or is -1 to indicate the qualifier.
384+
*/
385+
abstract predicate returnsValue(int arg);
386+
}
387+
388+
/**
389+
* A method or constructor that returns the exact value of its qualifier (e.g., `return this;`)
390+
*
391+
* Extend this class and override `returnsValue` to add additional value-preserving steps through a
392+
* method that should be added to the basic local flow step relation.
393+
*
394+
* These steps will be visible for all global data-flow purposes, as well as via
395+
* `DataFlow::Node.getASuccessor` and other related functions exposing intraprocedural dataflow.
396+
*/
397+
abstract class FluentMethod extends ValuePreservingCallable {
398+
override predicate returnsValue(int arg) { arg = -1 }
399+
}
400+
371401
/**
372402
* INTERNAL: do not use.
373403
*
@@ -408,6 +438,17 @@ predicate simpleLocalFlowStep(Node node1, Node node2) {
408438
or
409439
summaryStep(node1, node2, "value")
410440
or
441+
exists(MethodAccess ma, ValuePreservingCallable c, int argNo |
442+
ma.getCallee() = c and c.returnsValue(argNo)
443+
|
444+
node2.asExpr() = ma and
445+
(
446+
node1.asExpr() = ma.getArgument(argNo)
447+
or
448+
argNo = -1 and node1.asExpr() = ma.getQualifier()
449+
)
450+
)
451+
or
411452
exists(MethodAccess ma, Method m |
412453
ma = node2.asExpr() and
413454
m = ma.getMethod() and

java/ql/test/library-tests/dataflow/fluent-methods/Test.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ public Test fluentNoop() {
66
return this;
77
}
88

9+
public Test modelledFluentMethod() {
10+
// A model in the accompanying .ql file will indicate that the qualifier flows to the return value.
11+
return null;
12+
}
13+
14+
public static Test modelledIdentity(Test t) {
15+
// A model in the accompanying .ql file will indicate that the argument flows to the return value.
16+
return null;
17+
}
18+
919
public Test indirectlyFluentNoop() {
1020
return this.fluentNoop();
1121
}
@@ -47,4 +57,16 @@ public static void test3() {
4757
sink(t.get()); // $hasTaintFlow=y
4858
}
4959

60+
public static void testModel1() {
61+
Test t = new Test();
62+
t.indirectlyFluentNoop().modelledFluentMethod().fluentSet(source()).fluentNoop();
63+
sink(t.get()); // $hasTaintFlow=y
64+
}
65+
66+
public static void testModel2() {
67+
Test t = new Test();
68+
Test.modelledIdentity(t).indirectlyFluentNoop().modelledFluentMethod().fluentSet(source()).fluentNoop();
69+
sink(t.get()); // $hasTaintFlow=y
70+
}
71+
5072
}

java/ql/test/library-tests/dataflow/fluent-methods/flow.ql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import java
22
import semmle.code.java.dataflow.DataFlow
3+
import semmle.code.java.dataflow.FlowSteps
34
import TestUtilities.InlineExpectationsTest
45

56
class Conf extends DataFlow::Configuration {
@@ -14,6 +15,16 @@ class Conf extends DataFlow::Configuration {
1415
}
1516
}
1617

18+
class Model extends DataFlow::FluentMethod {
19+
Model() { this.getName() = "modelledFluentMethod" }
20+
}
21+
22+
class IdentityModel extends DataFlow::ValuePreservingCallable {
23+
IdentityModel() { this.getName() = "modelledIdentity" }
24+
25+
override predicate returnsValue(int arg) { arg = 0 }
26+
}
27+
1728
class HasFlowTest extends InlineExpectationsTest {
1829
HasFlowTest() { this = "HasFlowTest" }
1930

0 commit comments

Comments
 (0)