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

Skip to content

Commit dbd393b

Browse files
author
Benjamin Muskalla
committed
Support flow into field of referenced objects
1 parent 974c7b0 commit dbd393b

6 files changed

Lines changed: 116 additions & 35 deletions

File tree

java/ql/src/utils/model-generator/CaptureSinkModels.ql

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ class PropagateToSinkConfiguration extends TaintTracking::Configuration {
2727
}
2828

2929
override predicate isSink(DataFlow::Node sink) { sinkNode(sink, _) }
30+
31+
override DataFlow::FlowFeature getAFeature() {
32+
result instanceof DataFlow::FeatureHasSourceCallContext
33+
}
3034
}
3135

3236
string asInputArgument(DataFlow::Node source) {
@@ -50,6 +54,4 @@ string captureSink(Callable api) {
5054

5155
from TargetAPI api, string sink
5256
where sink = captureSink(api)
53-
// and
54-
// api.hasName("openStream")
5557
select sink order by sink

java/ql/src/utils/model-generator/CaptureSourceModels.ql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ class FromSourceConfiguration extends TaintTracking::Configuration {
3030
or
3131
exists(MethodAccess c | sink.asExpr() = c.getAnArgument())
3232
}
33+
34+
override DataFlow::FlowFeature getAFeature() {
35+
result instanceof DataFlow::FeatureHasSourceCallContext
36+
}
3337
}
3438

3539
string asOutput(DataFlow::Node node) {

java/ql/src/utils/model-generator/CaptureSummaryModels.ql

Lines changed: 62 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import ModelGeneratorUtils
99
import semmle.code.java.dataflow.TaintTracking
1010
import semmle.code.java.dataflow.internal.DataFlowImplCommon
1111
import semmle.code.java.dataflow.internal.DataFlowNodes
12+
import semmle.code.java.dataflow.internal.DataFlowPrivate
13+
import semmle.code.java.dataflow.InstanceAccess
1214
import ModelGeneratorUtils
1315

1416
string captureFlow(Callable api) {
@@ -39,6 +41,36 @@ string captureQualifierFlow(Callable api) {
3941
result = asValueModel(api, "Argument[-1]", "ReturnValue")
4042
}
4143

44+
class FieldToReturnConfig extends TaintTracking::Configuration {
45+
FieldToReturnConfig() { this = "FieldToReturnConfig" }
46+
47+
override predicate isSource(DataFlow::Node source) {
48+
source instanceof DataFlow::InstanceParameterNode
49+
}
50+
51+
override predicate isSink(DataFlow::Node sink) { sink instanceof ReturnNodeExt }
52+
53+
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
54+
exists(DataFlow::Content f |
55+
readStep(node1, f, node2) and
56+
if f instanceof DataFlow::FieldContent
57+
then isRelevantType(f.(DataFlow::FieldContent).getField().getType())
58+
else any()
59+
)
60+
or
61+
exists(DataFlow::Content f | storeStep(node1, f, node2) |
62+
f instanceof DataFlow::ArrayContent or
63+
f instanceof DataFlow::CollectionContent or
64+
f instanceof DataFlow::MapKeyContent or
65+
f instanceof DataFlow::MapValueContent
66+
)
67+
}
68+
69+
override DataFlow::FlowFeature getAFeature() {
70+
result instanceof DataFlow::FeatureEqualSourceSinkCallContext
71+
}
72+
}
73+
4274
/**
4375
* Capture APIs that return tainted instance data.
4476
* Example of an API that returns tainted instance data:
@@ -62,15 +94,17 @@ string captureQualifierFlow(Callable api) {
6294
* ```
6395
*/
6496
string captureFieldFlow(Callable api) {
65-
exists(FieldAccess fa, ReturnNodeExt returnNode |
66-
not (fa.getField().isStatic() and fa.getField().isFinal()) and
67-
fa.getField().getDeclaringType() = api.getDeclaringType() and
68-
returnNode.getEnclosingCallable() = api and
69-
isRelevantType(api.getReturnType()) and
97+
exists(FieldToReturnConfig config, ReturnNodeExt returnNodeExt |
98+
config.hasFlow(_, returnNodeExt) and
99+
returnNodeExt.getEnclosingCallable() = api and
70100
not api.getDeclaringType() instanceof EnumType and
71-
TaintTracking::localTaint(DataFlow::exprNode(fa), returnNode)
101+
isRelevantType(returnNodeExt.getType()) and
102+
not (
103+
returnNodeExt.getKind() instanceof ValueReturnKind and
104+
exists(captureQualifierFlow(api))
105+
)
72106
|
73-
result = asTaintModel(api, "Argument[-1]", asOutput(api, returnNode))
107+
result = asTaintModel(api, "Argument[-1]", asOutput(api, returnNodeExt))
74108
)
75109
}
76110

@@ -94,12 +128,26 @@ class ParameterToFieldConfig extends TaintTracking::Configuration {
94128
}
95129

96130
override predicate isSink(DataFlow::Node sink) {
131+
thisAccess(sink.(DataFlow::PostUpdateNode).getPreUpdateNode())
132+
}
133+
134+
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
97135
exists(FieldAssignment a |
98-
a.getSource() = sink.asExpr() and
99-
a.getDest().(FieldAccess).getField().getDeclaringType() =
100-
sink.getEnclosingCallable().getDeclaringType()
136+
a.getSource() = node1.asExpr() and
137+
DataFlow::getFieldQualifier(a.getDest()) = node2.(DataFlow::PostUpdateNode).getPreUpdateNode() and
138+
isRelevantType(a.getDest().(FieldAccess).getField().getType())
101139
)
102140
}
141+
142+
override DataFlow::FlowFeature getAFeature() {
143+
result instanceof DataFlow::FeatureEqualSourceSinkCallContext
144+
}
145+
}
146+
147+
private predicate thisAccess(DataFlow::Node n) {
148+
n.asExpr().(InstanceAccess).isOwnInstanceAccess()
149+
or
150+
n.(DataFlow::ImplicitInstanceAccess).getInstanceAccess() instanceof OwnInstanceAccess
103151
}
104152

105153
/**
@@ -116,30 +164,16 @@ class ParameterToFieldConfig extends TaintTracking::Configuration {
116164
* `p;Foo;true;doSomething;(String);Argument[0];Argument[-1];taint`
117165
*/
118166
string captureFieldFlowIn(Callable api) {
119-
exists(DataFlow::PathNode source, DataFlow::PathNode sink |
167+
exists(DataFlow::Node source, ParameterToFieldConfig config |
120168
not api.isStatic() and
121-
restrictedFlow(source, sink) and
122-
source.getNode().asParameter().getCallable() = api
169+
config.hasFlow(source, _) and
170+
source.asParameter().getCallable() = api
123171
|
124172
result =
125-
asTaintModel(api, "Argument[" + source.getNode().asParameter().getPosition() + "]",
126-
"Argument[-1]")
173+
asTaintModel(api, "Argument[" + source.asParameter().getPosition() + "]", "Argument[-1]")
127174
)
128175
}
129176

130-
predicate restrictedEdge(DataFlow::PathNode n1, DataFlow::PathNode n2) {
131-
n1.getASuccessor() = n2 and
132-
n1.getNode().getEnclosingCallable().getDeclaringType() =
133-
n2.getNode().getEnclosingCallable().getDeclaringType()
134-
}
135-
136-
predicate restrictedFlow(DataFlow::PathNode src, DataFlow::PathNode sink) {
137-
src.getConfiguration() instanceof ParameterToFieldConfig and
138-
src.isSource() and
139-
src.getConfiguration().isSink(sink.getNode()) and
140-
restrictedEdge*(src, sink)
141-
}
142-
143177
class ParameterToReturnValueTaintConfig extends TaintTracking::Configuration {
144178
ParameterToReturnValueTaintConfig() { this = "ParameterToReturnValueTaintConfig" }
145179

java/ql/test/utils/model-generator/CaptureSummaryModels.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
| p;ImmutablePojo;false;or;(String);;Argument[0];ReturnValue;taint |
1010
| p;InnerClasses$CaptureMe;true;yesCm;(String);;Argument[0];ReturnValue;taint |
1111
| p;InnerClasses;true;yes;(String);;Argument[0];ReturnValue;taint |
12+
| p;InnerHolder;false;explicitSetContext;(String);;Argument[0];Argument[-1];taint |
13+
| p;InnerHolder;false;getValue;();;Argument[-1];ReturnValue;taint |
14+
| p;InnerHolder;false;setContext;(String);;Argument[0];Argument[-1];taint |
1215
| p;Joiner;false;Joiner;(CharSequence);;Argument[0];Argument[-1];taint |
1316
| p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[0];Argument[-1];taint |
1417
| p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[1];Argument[-1];taint |
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package p;
2+
3+
public final class InnerHolder {
4+
5+
private class Context {
6+
private String value;
7+
8+
Context(String value) {
9+
this.value = value;
10+
}
11+
12+
public String getValue() {
13+
return value;
14+
}
15+
}
16+
17+
private Context context = null;
18+
19+
public void setContext(String value) {
20+
context = new Context(value);
21+
}
22+
23+
public void explicitSetContext(String value) {
24+
this.context = new Context(value);
25+
}
26+
27+
public String getValue() {
28+
return context.getValue();
29+
}
30+
31+
}

java/ql/test/utils/model-generator/p/Pojo.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package p;
22

33
import java.math.BigInteger;
4+
import java.util.Arrays;
45
import java.util.Collection;
56
import java.util.List;
67

@@ -22,6 +23,12 @@ int length() {
2223

2324
private int intValue = 2;
2425

26+
private byte[] byteArray = new byte[] {1, 2, 3} ;
27+
private float[] floatArray = new float[] {1, 2, 3} ;
28+
private char[] charArray = new char[] {'a', 'b', 'c'} ;
29+
private List<Character> charList = Arrays.asList('a', 'b', 'c');
30+
private Byte[] byteObjectArray = new Byte[] { 1, 2, 3 };
31+
2532
public String getValue() {
2633
return value;
2734
}
@@ -48,15 +55,15 @@ public int[] getPrimitiveArray() {
4855
}
4956

5057
public char[] getCharArray() {
51-
return new char[] { (char) intValue };
58+
return charArray;
5259
}
5360

5461
public byte[] getByteArray() {
55-
return new byte[] { (byte) intValue };
62+
return byteArray;
5663
}
5764

5865
public float[] getFloatArray() {
59-
return new float[] { (float) intValue };
66+
return floatArray;
6067
}
6168

6269
public Integer[] getBoxedArray() {
@@ -68,11 +75,11 @@ public Collection<Integer> getBoxedCollection() {
6875
}
6976

7077
public List<Character> getBoxedChars() {
71-
return List.of((char)intValue);
78+
return charList;
7279
}
7380

7481
public Byte[] getBoxedBytes() {
75-
return new Byte[] { Byte.valueOf((byte) intValue) };
82+
return byteObjectArray;
7683
}
7784

7885
public BigInteger getBigInt() {

0 commit comments

Comments
 (0)