Skip to content

Commit a40880a

Browse files
committed
Java: Add read-as-taint and config-dependent store-as-taint.
1 parent 2f087e1 commit a40880a

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

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

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,17 @@ private module Cached {
6060
localAdditionalTaintUpdateStep(src.asExpr(),
6161
sink.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr())
6262
or
63+
exists(Content f |
64+
readStep(src, f, sink) and
65+
not sink.getTypeBound() instanceof PrimitiveType and
66+
not sink.getTypeBound() instanceof BoxedType and
67+
not sink.getTypeBound() instanceof NumberType
68+
|
69+
f instanceof ArrayContent or
70+
f instanceof CollectionContent or
71+
f instanceof MapValueContent
72+
)
73+
or
6374
FlowSummaryImpl::Private::Steps::summaryLocalStep(src, sink, false)
6475
}
6576

@@ -87,6 +98,81 @@ private module Cached {
8798

8899
import Cached
89100

101+
private module StoreTaintSteps {
102+
private import semmle.code.java.dataflow.TaintTracking
103+
private import semmle.code.java.dataflow.TaintTracking2
104+
105+
private class StoreTaintConfig extends TaintTracking::Configuration {
106+
StoreTaintConfig() { this instanceof TaintTracking::Configuration or none() }
107+
108+
override predicate isSource(DataFlow::Node n) { none() }
109+
110+
override predicate isSink(DataFlow::Node n) { none() }
111+
112+
private predicate needsTaintStore(RefType container, Type elem, Content f) {
113+
exists(DataFlow::Node arg |
114+
(isSink(arg) or isAdditionalTaintStep(arg, _)) and
115+
(arg.asExpr() instanceof Argument or arg instanceof ArgumentNode) and
116+
arg.getType() = container
117+
or
118+
needsTaintStore(_, container, _)
119+
|
120+
container.(Array).getComponentType() = elem and
121+
f instanceof ArrayContent
122+
or
123+
container.(CollectionType).getElementType() = elem and
124+
f instanceof CollectionContent
125+
or
126+
container.(MapType).getValueType() = elem and
127+
f instanceof MapValueContent
128+
)
129+
}
130+
131+
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
132+
exists(Content f, Type elem |
133+
storeStep(node1, f, node2) and
134+
needsTaintStore(_, elem, f) and
135+
not exists(Type srctyp | srctyp = node1.getTypeBound() | not compatibleTypes(srctyp, elem))
136+
)
137+
}
138+
}
139+
140+
private class StoreTaintConfig2 extends TaintTracking2::Configuration {
141+
StoreTaintConfig2() { this instanceof TaintTracking2::Configuration or none() }
142+
143+
override predicate isSource(DataFlow::Node n) { none() }
144+
145+
override predicate isSink(DataFlow::Node n) { none() }
146+
147+
private predicate needsTaintStore(RefType container, Type elem, Content f) {
148+
exists(DataFlow::Node arg |
149+
(isSink(arg) or isAdditionalTaintStep(arg, _)) and
150+
(arg.asExpr() instanceof Argument or arg instanceof ArgumentNode) and
151+
arg.getType() = container
152+
or
153+
needsTaintStore(_, container, _)
154+
|
155+
container.(Array).getComponentType() = elem and
156+
f instanceof ArrayContent
157+
or
158+
container.(CollectionType).getElementType() = elem and
159+
f instanceof CollectionContent
160+
or
161+
container.(MapType).getValueType() = elem and
162+
f instanceof MapValueContent
163+
)
164+
}
165+
166+
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
167+
exists(Content f, Type elem |
168+
storeStep(node1, f, node2) and
169+
needsTaintStore(_, elem, f) and
170+
not exists(Type srctyp | srctyp = node1.getTypeBound() | not compatibleTypes(srctyp, elem))
171+
)
172+
}
173+
}
174+
}
175+
90176
/**
91177
* Holds if taint can flow in one local step from `src` to `sink` excluding
92178
* local data flow steps. That is, `src` and `sink` are likely to represent

0 commit comments

Comments
 (0)