Skip to content

Commit 5e80044

Browse files
committed
Preserve taint on field-read-steps on entrypoint types
1 parent 9363d64 commit 5e80044

File tree

4 files changed

+86
-0
lines changed

4 files changed

+86
-0
lines changed

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ private import semmle.code.java.frameworks.spring.SpringController
1111
private import semmle.code.java.frameworks.spring.SpringHttp
1212
private import semmle.code.java.frameworks.Networking
1313
private import semmle.code.java.dataflow.ExternalFlow
14+
private import semmle.code.java.dataflow.FlowSources
1415
private import semmle.code.java.dataflow.internal.DataFlowPrivate
1516
import semmle.code.java.dataflow.FlowSteps
1617
private import FlowSummaryImpl as FlowSummaryImpl
@@ -91,6 +92,8 @@ private module Cached {
9192
)
9293
or
9394
FlowSummaryImpl::Private::Steps::summaryLocalStep(src, sink, false)
95+
or
96+
entrypointFieldStep(src, sink)
9497
}
9598

9699
/**
@@ -591,3 +594,18 @@ private MethodAccess callReturningSameType(Expr ref) {
591594
ref = result.getQualifier() and
592595
result.getMethod().getReturnType() = ref.getType()
593596
}
597+
598+
private SrcRefType entrypointType() {
599+
result =
600+
pragma[only_bind_out](any(RemoteFlowSource s | s instanceof DataFlow::ExplicitParameterNode))
601+
.getType()
602+
.(RefType)
603+
.getASubtype*()
604+
.getSourceDeclaration() or
605+
result = entrypointType().getAField().getType().(RefType).getSourceDeclaration()
606+
}
607+
608+
private predicate entrypointFieldStep(DataFlow::Node src, DataFlow::Node sink) {
609+
src = DataFlow::getFieldQualifier(sink.asExpr().(FieldRead)) and
610+
src.getType().(RefType).getSourceDeclaration() = entrypointType()
611+
}

java/ql/test/library-tests/dataflow/entrypoint-types/EntryPointTypesTest.expected

Whitespace-only changes.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
public class EntryPointTypesTest {
2+
3+
static class TestObject {
4+
public String field1;
5+
private String field2;
6+
private AnotherTestObject field3;
7+
8+
public String getField2() {
9+
return field2;
10+
}
11+
12+
public AnotherTestObject getField3() {
13+
return field3;
14+
}
15+
}
16+
17+
static class AnotherTestObject {
18+
public String field4;
19+
private String field5;
20+
21+
public String getField5() {
22+
return field5;
23+
}
24+
}
25+
26+
private static void sink(String sink) {}
27+
28+
public static void test(TestObject source) {
29+
sink(source.field1); // $hasTaintFlow
30+
sink(source.getField2()); // $hasTaintFlow
31+
sink(source.getField3().field4); // $hasTaintFlow
32+
sink(source.getField3().getField5()); // $hasTaintFlow
33+
}
34+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import java
2+
import semmle.code.java.dataflow.FlowSources
3+
import TestUtilities.InlineExpectationsTest
4+
5+
class TestRemoteFlowSource extends RemoteFlowSource {
6+
TestRemoteFlowSource() { this.asParameter().hasName("source") }
7+
8+
override string getSourceType() { result = "test" }
9+
}
10+
11+
class TaintFlowConf extends TaintTracking::Configuration {
12+
TaintFlowConf() { this = "qltest:dataflow:entrypoint-types-taint" }
13+
14+
override predicate isSource(DataFlow::Node n) { n instanceof RemoteFlowSource }
15+
16+
override predicate isSink(DataFlow::Node n) {
17+
exists(MethodAccess ma | ma.getMethod().hasName("sink") | n.asExpr() = ma.getAnArgument())
18+
}
19+
}
20+
21+
class HasFlowTest extends InlineExpectationsTest {
22+
HasFlowTest() { this = "HasFlowTest" }
23+
24+
override string getARelevantTag() { result = ["hasTaintFlow"] }
25+
26+
override predicate hasActualResult(Location location, string element, string tag, string value) {
27+
tag = "hasTaintFlow" and
28+
exists(DataFlow::Node src, DataFlow::Node sink, TaintFlowConf conf | conf.hasFlow(src, sink) |
29+
sink.getLocation() = location and
30+
element = sink.toString() and
31+
value = ""
32+
)
33+
}
34+
}

0 commit comments

Comments
 (0)