Skip to content

Commit 619913b

Browse files
authored
Merge pull request github#16552 from aschackmull/java/no-source-dispatch-for-exact-mad
Java: Remove source dispatch when there's an exact match from a manual model.
2 parents 7da7416 + f353065 commit 619913b

File tree

6 files changed

+66
-23
lines changed

6 files changed

+66
-23
lines changed

java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -413,25 +413,28 @@ private string paramsStringQualified(Callable c) {
413413
}
414414

415415
private Element interpretElement0(
416-
string package, string type, boolean subtypes, string name, string signature
416+
string package, string type, boolean subtypes, string name, string signature, boolean isExact
417417
) {
418418
elementSpec(package, type, subtypes, name, signature, _) and
419419
(
420420
exists(Member m |
421421
(
422-
result = m
422+
result = m and isExact = true
423423
or
424-
subtypes = true and result.(SrcMethod).overridesOrInstantiates+(m)
424+
subtypes = true and result.(SrcMethod).overridesOrInstantiates+(m) and isExact = false
425425
) and
426426
m.hasQualifiedName(package, type, name)
427427
|
428-
signature = "" or
429-
paramsStringQualified(m) = signature or
428+
signature = ""
429+
or
430+
paramsStringQualified(m) = signature
431+
or
430432
paramsString(m) = signature
431433
)
432434
or
433435
exists(RefType t |
434436
t.hasQualifiedName(package, type) and
437+
isExact = false and
435438
(if subtypes = true then result.(SrcRefType).getASourceSupertype*() = t else result = t) and
436439
name = "" and
437440
signature = ""
@@ -442,13 +445,16 @@ private Element interpretElement0(
442445
/** Gets the source/sink/summary/neutral element corresponding to the supplied parameters. */
443446
cached
444447
Element interpretElement(
445-
string package, string type, boolean subtypes, string name, string signature, string ext
448+
string package, string type, boolean subtypes, string name, string signature, string ext,
449+
boolean isExact
446450
) {
447451
elementSpec(package, type, subtypes, name, signature, ext) and
448-
exists(Element e | e = interpretElement0(package, type, subtypes, name, signature) |
449-
ext = "" and result = e
452+
exists(Element e, boolean isExact0 |
453+
e = interpretElement0(package, type, subtypes, name, signature, isExact0)
454+
|
455+
ext = "" and result = e and isExact = isExact0
450456
or
451-
ext = "Annotated" and result.(Annotatable).getAnAnnotation().getType() = e
457+
ext = "Annotated" and result.(Annotatable).getAnAnnotation().getType() = e and isExact = false
452458
)
453459
}
454460

@@ -538,13 +544,13 @@ predicate sinkNode(Node node, string kind) { sinkNode(node, kind, _) }
538544

539545
// adapter class for converting Mad summaries to `SummarizedCallable`s
540546
private class SummarizedCallableAdapter extends SummarizedCallable {
541-
SummarizedCallableAdapter() { summaryElement(this, _, _, _, _, _) }
547+
SummarizedCallableAdapter() { summaryElement(this, _, _, _, _, _, _) }
542548

543549
private predicate relevantSummaryElementManual(
544550
string input, string output, string kind, string model
545551
) {
546552
exists(Provenance provenance |
547-
summaryElement(this, input, output, kind, provenance, model) and
553+
summaryElement(this, input, output, kind, provenance, model, _) and
548554
provenance.isManual()
549555
)
550556
}
@@ -553,11 +559,11 @@ private class SummarizedCallableAdapter extends SummarizedCallable {
553559
string input, string output, string kind, string model
554560
) {
555561
exists(Provenance provenance |
556-
summaryElement(this, input, output, kind, provenance, model) and
562+
summaryElement(this, input, output, kind, provenance, model, _) and
557563
provenance.isGenerated()
558564
) and
559565
not exists(Provenance provenance |
560-
neutralElement(this, "summary", provenance) and
566+
neutralElement(this, "summary", provenance, _) and
561567
provenance.isManual()
562568
)
563569
}
@@ -576,18 +582,23 @@ private class SummarizedCallableAdapter extends SummarizedCallable {
576582
}
577583

578584
override predicate hasProvenance(Provenance provenance) {
579-
summaryElement(this, _, _, _, provenance, _)
585+
summaryElement(this, _, _, _, provenance, _, _)
580586
}
587+
588+
override predicate hasExactModel() { summaryElement(this, _, _, _, _, _, true) }
581589
}
582590

583591
// adapter class for converting Mad neutrals to `NeutralCallable`s
584592
private class NeutralCallableAdapter extends NeutralCallable {
585593
string kind;
586594
string provenance_;
595+
boolean exact;
587596

588-
NeutralCallableAdapter() { neutralElement(this, kind, provenance_) }
597+
NeutralCallableAdapter() { neutralElement(this, kind, provenance_, exact) }
589598

590599
override string getKind() { result = kind }
591600

592601
override predicate hasProvenance(Provenance provenance) { provenance = provenance_ }
602+
603+
override predicate hasExactModel() { exact = true }
593604
}

java/ql/lib/semmle/code/java/dataflow/FlowSummary.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ private class SummarizedSyntheticCallableAdapter extends SummarizedCallable, TSy
135135
model = sc
136136
)
137137
}
138+
139+
override predicate hasExactModel() { any() }
138140
}
139141

140142
deprecated class RequiredSummaryComponentStack = Impl::Private::RequiredSummaryComponentStack;

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,21 @@ private module DispatchImpl {
1919
)
2020
}
2121

22+
private predicate hasExactManualModel(Call c, Callable tgt) {
23+
tgt = c.getCallee().getSourceDeclaration() and
24+
(
25+
exists(Impl::Public::SummarizedCallable sc |
26+
sc.getACall() = c and sc.hasExactModel() and sc.hasManualModel()
27+
)
28+
or
29+
exists(Impl::Public::NeutralSummaryCallable nc |
30+
nc.getACall() = c and nc.hasExactModel() and nc.hasManualModel()
31+
)
32+
)
33+
}
34+
2235
private Callable sourceDispatch(Call c) {
36+
not hasExactManualModel(c, result) and
2337
result = VirtualDispatch::viableCallable(c) and
2438
if VirtualDispatch::lowConfidenceDispatchTarget(c, result)
2539
then not hasHighConfidenceTarget(c)

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ private predicate relatedArgSpec(Callable c, string spec) {
131131
sourceModel(namespace, type, subtypes, name, signature, ext, spec, _, _, _) or
132132
sinkModel(namespace, type, subtypes, name, signature, ext, spec, _, _, _)
133133
|
134-
c = interpretElement(namespace, type, subtypes, name, signature, ext)
134+
c = interpretElement(namespace, type, subtypes, name, signature, ext, _)
135135
)
136136
}
137137

@@ -202,7 +202,7 @@ module SourceSinkInterpretationInput implements
202202
sourceModel(namespace, type, subtypes, name, signature, ext, originalOutput, kind, provenance,
203203
madId) and
204204
model = "MaD:" + madId.toString() and
205-
baseSource = interpretElement(namespace, type, subtypes, name, signature, ext) and
205+
baseSource = interpretElement(namespace, type, subtypes, name, signature, ext, _) and
206206
(
207207
e = baseSource and output = originalOutput
208208
or
@@ -221,7 +221,7 @@ module SourceSinkInterpretationInput implements
221221
sinkModel(namespace, type, subtypes, name, signature, ext, originalInput, kind, provenance,
222222
madId) and
223223
model = "MaD:" + madId.toString() and
224-
baseSink = interpretElement(namespace, type, subtypes, name, signature, ext) and
224+
baseSink = interpretElement(namespace, type, subtypes, name, signature, ext, _) and
225225
(
226226
e = baseSink and originalInput = input
227227
or
@@ -310,7 +310,7 @@ module Private {
310310
*/
311311
predicate summaryElement(
312312
Input::SummarizedCallableBase c, string input, string output, string kind, string provenance,
313-
string model
313+
string model, boolean isExact
314314
) {
315315
exists(
316316
string namespace, string type, boolean subtypes, string name, string signature, string ext,
@@ -320,7 +320,7 @@ module Private {
320320
summaryModel(namespace, type, subtypes, name, signature, ext, originalInput, originalOutput,
321321
kind, provenance, madId) and
322322
model = "MaD:" + madId.toString() and
323-
baseCallable = interpretElement(namespace, type, subtypes, name, signature, ext) and
323+
baseCallable = interpretElement(namespace, type, subtypes, name, signature, ext, isExact) and
324324
(
325325
c.asCallable() = baseCallable and input = originalInput and output = originalOutput
326326
or
@@ -336,10 +336,12 @@ module Private {
336336
* Holds if a neutral model exists for `c` of kind `kind`
337337
* and with provenance `provenance`.
338338
*/
339-
predicate neutralElement(Input::SummarizedCallableBase c, string kind, string provenance) {
339+
predicate neutralElement(
340+
Input::SummarizedCallableBase c, string kind, string provenance, boolean isExact
341+
) {
340342
exists(string namespace, string type, string name, string signature |
341343
neutralModel(namespace, type, name, signature, kind, provenance) and
342-
c.asCallable() = interpretElement(namespace, type, false, name, signature, "")
344+
c.asCallable() = interpretElement(namespace, type, false, name, signature, "", isExact)
343345
)
344346
}
345347
}

java/ql/src/utils/modeleditor/ModelEditor.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class Endpoint extends Callable {
7777
predicate isNeutral() {
7878
exists(string namespace, string type, string name, string signature |
7979
neutralModel(namespace, type, name, signature, _, _) and
80-
this = interpretElement(namespace, type, false, name, signature, "")
80+
this = interpretElement(namespace, type, false, name, signature, "", _)
8181
)
8282
}
8383

shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,13 @@ module Make<
253253
* that has provenance `provenance`.
254254
*/
255255
predicate hasProvenance(Provenance provenance) { provenance = "manual" }
256+
257+
/**
258+
* Holds if there exists a model for which this callable is an exact
259+
* match, that is, no overriding was used to identify this callable from
260+
* the model.
261+
*/
262+
predicate hasExactModel() { none() }
256263
}
257264

258265
final private class NeutralCallableFinal = NeutralCallable;
@@ -292,6 +299,13 @@ module Make<
292299
* Gets the kind of the neutral.
293300
*/
294301
abstract string getKind();
302+
303+
/**
304+
* Holds if there exists a model for which this callable is an exact
305+
* match, that is, no overriding was used to identify this callable from
306+
* the model.
307+
*/
308+
predicate hasExactModel() { none() }
295309
}
296310
}
297311

0 commit comments

Comments
 (0)