Skip to content

Commit 2535055

Browse files
committed
Java: Re-factor implementation to use the new model generator interface.
1 parent 0016fbf commit 2535055

15 files changed

+165
-145
lines changed

java/ql/src/utils/modelgenerator/CaptureContentSummaryModels.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
import internal.CaptureModels
10+
import SummaryModels
1011

1112
from DataFlowSummaryTargetApi api, string flow
1213
where flow = ContentSensitive::captureFlow(api, _)

java/ql/src/utils/modelgenerator/CaptureNeutralModels.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
import internal.CaptureModels
10+
import SummaryModels
1011

1112
from DataFlowSummaryTargetApi api, string noflow
1213
where noflow = captureNeutral(api)

java/ql/src/utils/modelgenerator/CaptureSinkModels.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
import internal.CaptureModels
10+
import SinkModels
1011

1112
from DataFlowSinkTargetApi api, string sink
1213
where sink = Heuristic::captureSink(api)

java/ql/src/utils/modelgenerator/CaptureSourceModels.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
import internal.CaptureModels
10+
import SourceModels
1011

1112
from DataFlowSourceTargetApi api, string source
1213
where source = Heuristic::captureSource(api)

java/ql/src/utils/modelgenerator/CaptureSummaryModels.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
import internal.CaptureModels
10+
import SummaryModels
1011

1112
from DataFlowSummaryTargetApi api, string flow
1213
where flow = captureFlow(api, _)

java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPartialPath.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java
1212
import semmle.code.java.dataflow.DataFlow
1313
import utils.modelgenerator.internal.CaptureModels
14+
import SummaryModels
1415
import PartialFlow::PartialPathGraph
1516

1617
int explorationLimit() { result = 3 }

java/ql/src/utils/modelgenerator/debug/CaptureSummaryModelsPath.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java
1212
import semmle.code.java.dataflow.DataFlow
1313
import utils.modelgenerator.internal.CaptureModels
14+
import SummaryModels
1415
import Heuristic
1516
import PropagateFlow::PathGraph
1617

java/ql/src/utils/modelgenerator/internal/CaptureModels.qll

Lines changed: 149 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,20 @@ predicate isPrimitiveTypeUsedForBulkData(J::Type t) {
2525
t.hasName(["byte", "char", "Byte", "Character"])
2626
}
2727

28-
module ModelGeneratorInput implements ModelGeneratorInputSig<Location, JavaDataFlow> {
28+
private predicate isInfrequentlyUsed(J::CompilationUnit cu) {
29+
cu.getPackage().getName().matches("javax.swing%") or
30+
cu.getPackage().getName().matches("java.awt%")
31+
}
32+
33+
private predicate relevant(Callable api) {
34+
api.isPublic() and
35+
api.getDeclaringType().isPublic() and
36+
api.fromSource() and
37+
not isUninterestingForModels(api) and
38+
not isInfrequentlyUsed(api.getCompilationUnit())
39+
}
40+
41+
module ModelGeneratorCommonInput implements ModelGeneratorCommonInputSig<Location, JavaDataFlow> {
2942
class Type = J::Type;
3043

3144
class Parameter = J::Parameter;
@@ -34,96 +47,8 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, JavaDataF
3447

3548
class NodeExtended = DataFlow::Node;
3649

37-
Callable getAsExprEnclosingCallable(NodeExtended node) {
38-
result = node.asExpr().getEnclosingCallable()
39-
}
40-
4150
Callable getEnclosingCallable(NodeExtended node) { result = node.getEnclosingCallable() }
4251

43-
Parameter asParameter(NodeExtended node) { result = node.asParameter() }
44-
45-
private predicate isInfrequentlyUsed(J::CompilationUnit cu) {
46-
cu.getPackage().getName().matches("javax.swing%") or
47-
cu.getPackage().getName().matches("java.awt%")
48-
}
49-
50-
private predicate relevant(Callable api) {
51-
api.isPublic() and
52-
api.getDeclaringType().isPublic() and
53-
api.fromSource() and
54-
not isUninterestingForModels(api) and
55-
not isInfrequentlyUsed(api.getCompilationUnit())
56-
}
57-
58-
private J::Method getARelevantOverride(J::Method m) {
59-
result = m.getAnOverride() and
60-
relevant(result) and
61-
// Other exclusions for overrides.
62-
not m instanceof J::ToStringMethod
63-
}
64-
65-
/**
66-
* Gets the super implementation of `m` if it is relevant.
67-
* If such a super implementations does not exist, returns `m` if it is relevant.
68-
*/
69-
private J::Callable liftedImpl(J::Callable m) {
70-
(
71-
result = getARelevantOverride(m)
72-
or
73-
result = m and relevant(m)
74-
) and
75-
not exists(getARelevantOverride(result))
76-
}
77-
78-
private predicate hasManualSummaryModel(Callable api) {
79-
api = any(FlowSummaryImpl::Public::SummarizedCallable sc | sc.applyManualModel()).asCallable() or
80-
api = any(FlowSummaryImpl::Public::NeutralSummaryCallable sc | sc.hasManualModel()).asCallable()
81-
}
82-
83-
private predicate hasManualSourceModel(Callable api) {
84-
api = any(ExternalFlow::SourceCallable sc | sc.hasManualModel()) or
85-
api = any(FlowSummaryImpl::Public::NeutralSourceCallable sc | sc.hasManualModel()).asCallable()
86-
}
87-
88-
private predicate hasManualSinkModel(Callable api) {
89-
api = any(ExternalFlow::SinkCallable sc | sc.hasManualModel()) or
90-
api = any(FlowSummaryImpl::Public::NeutralSinkCallable sc | sc.hasManualModel()).asCallable()
91-
}
92-
93-
predicate isUninterestingForDataFlowModels(Callable api) {
94-
api.getDeclaringType() instanceof J::Interface and not exists(api.getBody())
95-
}
96-
97-
predicate isUninterestingForHeuristicDataFlowModels(Callable api) { none() }
98-
99-
class SourceOrSinkTargetApi extends Callable {
100-
SourceOrSinkTargetApi() { relevant(this) }
101-
}
102-
103-
class SinkTargetApi extends SourceOrSinkTargetApi {
104-
SinkTargetApi() { not hasManualSinkModel(this) }
105-
}
106-
107-
class SourceTargetApi extends SourceOrSinkTargetApi {
108-
SourceTargetApi() { not hasManualSourceModel(this) }
109-
}
110-
111-
class SummaryTargetApi extends Callable {
112-
private Callable lift;
113-
114-
SummaryTargetApi() {
115-
lift = liftedImpl(this) and
116-
not hasManualSummaryModel(lift)
117-
}
118-
119-
Callable lift() { result = lift }
120-
121-
predicate isRelevant() {
122-
relevant(this) and
123-
not hasManualSummaryModel(this)
124-
}
125-
}
126-
12752
private string isExtensible(Callable c) {
12853
if c.getDeclaringType().isFinal() then result = "false" else result = "true"
12954
}
@@ -204,49 +129,89 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, JavaDataF
204129
node.asExpr().(J::ThisAccess).isOwnInstanceAccess()
205130
}
206131

207-
predicate sinkModelSanitizer(DataFlow::Node node) {
208-
// exclude variable capture jump steps
209-
exists(Ssa::SsaImplicitInit closure |
210-
closure.captures(_) and
211-
node.asExpr() = closure.getAFirstUse()
212-
)
132+
predicate containerContent = DataFlowPrivate::containerContent/1;
133+
134+
string partialModelRow(Callable api, int i) {
135+
i = 0 and qualifiedName(api, result, _) // package
136+
or
137+
i = 1 and qualifiedName(api, _, result) // type
138+
or
139+
i = 2 and result = isExtensible(api) // extensible
140+
or
141+
i = 3 and result = api.getName() // name
142+
or
143+
i = 4 and result = ExternalFlow::paramsString(api) // parameters
144+
or
145+
i = 5 and result = "" and exists(api) // ext
213146
}
214147

215-
predicate apiSource(DataFlow::Node source) {
148+
string partialNeutralModelRow(Callable api, int i) {
149+
i = 0 and qualifiedName(api, result, _) // package
150+
or
151+
i = 1 and qualifiedName(api, _, result) // type
152+
or
153+
i = 2 and result = api.getName() // name
154+
or
155+
i = 3 and result = ExternalFlow::paramsString(api) // parameters
156+
}
157+
}
158+
159+
private import ModelGeneratorCommonInput
160+
private import MakeModelGeneratorFactory<Location, JavaDataFlow, JavaTaintTracking, ModelGeneratorCommonInput>
161+
162+
module SummaryModelGeneratorInput implements SummaryModelGeneratorInputSig {
163+
Callable getAsExprEnclosingCallable(NodeExtended node) {
164+
result = node.asExpr().getEnclosingCallable()
165+
}
166+
167+
Parameter asParameter(NodeExtended node) { result = node.asParameter() }
168+
169+
private J::Method getARelevantOverride(J::Method m) {
170+
result = m.getAnOverride() and
171+
relevant(result) and
172+
// Other exclusions for overrides.
173+
not m instanceof J::ToStringMethod
174+
}
175+
176+
/**
177+
* Gets the super implementation of `m` if it is relevant.
178+
* If such a super implementations does not exist, returns `m` if it is relevant.
179+
*/
180+
private J::Callable liftedImpl(J::Callable m) {
216181
(
217-
source.asExpr().(J::FieldAccess).isOwnFieldAccess() or
218-
source instanceof DataFlow::ParameterNode
182+
result = getARelevantOverride(m)
183+
or
184+
result = m and relevant(m)
219185
) and
220-
exists(J::RefType t |
221-
t = source.getEnclosingCallable().getDeclaringType().getAnAncestor() and
222-
not t instanceof J::TypeObject and
223-
t.isPublic()
224-
)
186+
not exists(getARelevantOverride(result))
225187
}
226188

227-
predicate irrelevantSourceSinkApi(Callable source, SourceTargetApi api) { none() }
228-
229-
string getInputArgument(DataFlow::Node source) {
230-
exists(int pos |
231-
source.(DataFlow::ParameterNode).isParameterOf(_, pos) and
232-
if pos >= 0 then result = "Argument[" + pos + "]" else result = qualifierString()
233-
)
234-
or
235-
source.asExpr() instanceof J::FieldAccess and
236-
result = qualifierString()
189+
private predicate hasManualSummaryModel(Callable api) {
190+
api = any(FlowSummaryImpl::Public::SummarizedCallable sc | sc.applyManualModel()).asCallable() or
191+
api = any(FlowSummaryImpl::Public::NeutralSummaryCallable sc | sc.hasManualModel()).asCallable()
237192
}
238193

239-
bindingset[kind]
240-
predicate isRelevantSinkKind(string kind) {
241-
not kind = "log-injection" and
242-
not kind.matches("regex-use%") and
243-
not kind = "file-content-store"
194+
class SummaryTargetApi extends Callable {
195+
private Callable lift;
196+
197+
SummaryTargetApi() {
198+
lift = liftedImpl(this) and
199+
not hasManualSummaryModel(lift)
200+
}
201+
202+
Callable lift() { result = lift }
203+
204+
predicate isRelevant() {
205+
relevant(this) and
206+
not hasManualSummaryModel(this)
207+
}
244208
}
245209

246-
bindingset[kind]
247-
predicate isRelevantSourceKind(string kind) { any() }
210+
predicate isUninterestingForDataFlowModels(Callable api) {
211+
api.getDeclaringType() instanceof J::Interface and not exists(api.getBody())
212+
}
248213

249-
predicate containerContent = DataFlowPrivate::containerContent/1;
214+
predicate isUninterestingForHeuristicDataFlowModels(Callable api) { none() }
250215

251216
predicate isAdditionalContentFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
252217
TaintTracking::defaultAdditionalTaintStep(node1, node2, _) and
@@ -287,34 +252,76 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, JavaDataF
287252
or
288253
c instanceof DataFlowUtil::MapKeyContent and result = "MapKey"
289254
}
255+
}
290256

291-
string partialModelRow(Callable api, int i) {
292-
i = 0 and qualifiedName(api, result, _) // package
293-
or
294-
i = 1 and qualifiedName(api, _, result) // type
295-
or
296-
i = 2 and result = isExtensible(api) // extensible
297-
or
298-
i = 3 and result = api.getName() // name
299-
or
300-
i = 4 and result = ExternalFlow::paramsString(api) // parameters
301-
or
302-
i = 5 and result = "" and exists(api) // ext
257+
private module SourceModelGeneratorInput implements SourceModelGeneratorInputSig {
258+
private predicate hasManualSourceModel(Callable api) {
259+
api = any(ExternalFlow::SourceCallable sc | sc.hasManualModel()) or
260+
api = any(FlowSummaryImpl::Public::NeutralSourceCallable sc | sc.hasManualModel()).asCallable()
303261
}
304262

305-
string partialNeutralModelRow(Callable api, int i) {
306-
i = 0 and qualifiedName(api, result, _) // package
307-
or
308-
i = 1 and qualifiedName(api, _, result) // type
309-
or
310-
i = 2 and result = api.getName() // name
311-
or
312-
i = 3 and result = ExternalFlow::paramsString(api) // parameters
263+
class SourceTargetApi extends Callable {
264+
SourceTargetApi() { relevant(this) and not hasManualSourceModel(this) }
313265
}
314266

267+
predicate irrelevantSourceSinkApi(Callable source, SourceTargetApi api) { none() }
268+
269+
bindingset[kind]
270+
predicate isRelevantSourceKind(string kind) { any() }
271+
315272
predicate sourceNode = ExternalFlow::sourceNode/2;
273+
}
274+
275+
private module SinkModelGeneratorInput implements SinkModelGeneratorInputSig {
276+
private predicate hasManualSinkModel(Callable api) {
277+
api = any(ExternalFlow::SinkCallable sc | sc.hasManualModel()) or
278+
api = any(FlowSummaryImpl::Public::NeutralSinkCallable sc | sc.hasManualModel()).asCallable()
279+
}
280+
281+
class SinkTargetApi extends Callable {
282+
SinkTargetApi() { relevant(this) and not hasManualSinkModel(this) }
283+
}
284+
285+
predicate sinkModelSanitizer(DataFlow::Node node) {
286+
// exclude variable capture jump steps
287+
exists(Ssa::SsaImplicitInit closure |
288+
closure.captures(_) and
289+
node.asExpr() = closure.getAFirstUse()
290+
)
291+
}
292+
293+
predicate apiSource(DataFlow::Node source) {
294+
(
295+
source.asExpr().(J::FieldAccess).isOwnFieldAccess() or
296+
source instanceof DataFlow::ParameterNode
297+
) and
298+
exists(J::RefType t |
299+
t = source.getEnclosingCallable().getDeclaringType().getAnAncestor() and
300+
not t instanceof J::TypeObject and
301+
t.isPublic()
302+
)
303+
}
304+
305+
string getInputArgument(DataFlow::Node source) {
306+
exists(int pos |
307+
source.(DataFlow::ParameterNode).isParameterOf(_, pos) and
308+
if pos >= 0 then result = "Argument[" + pos + "]" else result = qualifierString()
309+
)
310+
or
311+
source.asExpr() instanceof J::FieldAccess and
312+
result = qualifierString()
313+
}
314+
315+
bindingset[kind]
316+
predicate isRelevantSinkKind(string kind) {
317+
not kind = "log-injection" and
318+
not kind.matches("regex-use%") and
319+
not kind = "file-content-store"
320+
}
316321

317322
predicate sinkNode = ExternalFlow::sinkNode/2;
318323
}
319324

320-
import MakeModelGenerator<Location, JavaDataFlow, JavaTaintTracking, ModelGeneratorInput>
325+
import MakeSummaryModelGenerator<SummaryModelGeneratorInput> as SummaryModels
326+
import MakeSourceModelGenerator<SourceModelGeneratorInput> as SourceModels
327+
import MakeSinkModelGenerator<SinkModelGeneratorInput> as SinkModels

0 commit comments

Comments
 (0)