Skip to content

Commit 0df0d8a

Browse files
authored
Merge pull request #17236 from michaelnebel/java/viablecallableheuristic
Java: Make more finegrained dataflow dispatch viable callable heuristic.
2 parents 047a655 + 53b2471 commit 0df0d8a

File tree

17 files changed

+867
-708
lines changed

17 files changed

+867
-708
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: majorAnalysis
3+
---
4+
* A generated (Models as Data) summary model is no longer used, if there exists a source code alternative. This primarily affects the analysis, when the analysis includes generated models for the source code being analysed.

java/ql/lib/ext/java.net.model.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ extensions:
4848
- ["java.net", "URI", False, "URI", "(String,String,String)", "", "Argument[1]", "ReturnValue", "taint", "ai-manual"]
4949
- ["java.net", "URI", False, "URI", "(String)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
5050
- ["java.net", "URI", False, "create", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
51+
- ["java.net", "URI", False, "getPath", "()", "", "Argument[this]", "ReturnValue", "taint", "df-manual"]
5152
- ["java.net", "URI", False, "resolve", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
5253
- ["java.net", "URI", False, "resolve", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"]
5354
- ["java.net", "URI", False, "toASCIIString", "", "", "Argument[this]", "ReturnValue", "taint", "manual"]

java/ql/lib/ext/java.nio.model.yml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,20 @@ extensions:
55
data:
66
- ["java.nio", "ByteBuffer", False, "array", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
77
- ["java.nio", "ByteBuffer", False, "get", "", "", "Argument[this]", "ReturnValue", "taint", "manual"]
8-
- ["java.nio", "ByteBuffer", False, "wrap", "(byte[])", "", "Argument[0]", "ReturnValue", "taint", "manual"]
8+
- ["java.nio", "ByteBuffer", True, "put", "(ByteBuffer)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
9+
- ["java.nio", "ByteBuffer", True, "put", "(ByteBuffer)", "", "Argument[this]", "ReturnValue", "value", "manual"]
10+
- ["java.nio", "ByteBuffer", True, "put", "(byte)", "", "Argument[this]", "ReturnValue", "value", "manual"]
11+
- ["java.nio", "ByteBuffer", True, "put", "(byte[])", "", "Argument[0]", "Argument[this]", "taint", "manual"]
12+
- ["java.nio", "ByteBuffer", True, "put", "(byte[])", "", "Argument[this]", "ReturnValue", "value", "manual"]
13+
- ["java.nio", "ByteBuffer", True, "put", "(byte[],int,int)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
14+
- ["java.nio", "ByteBuffer", True, "put", "(byte[],int,int)", "", "Argument[this]", "ReturnValue", "value", "manual"]
15+
- ["java.nio", "ByteBuffer", True, "wrap", "(byte[])", "", "Argument[0]", "ReturnValue", "taint", "manual"]
16+
- ["java.nio", "ByteBuffer", True, "wrap", "(byte[],int,int)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
17+
- ["java.nio", "CharBuffer", True, "wrap", "(CharSequence)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
18+
- ["java.nio", "CharBuffer", True, "wrap", "(CharSequence,int,int)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
19+
- ["java.nio", "CharBuffer", True, "wrap", "(char[])", "", "Argument[0]", "ReturnValue", "taint", "manual"]
20+
- ["java.nio", "CharBuffer", True, "wrap", "(char[],int,int)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
21+
922

1023
- addsTo:
1124
pack: codeql/java-all

java/ql/lib/ext/java.security.cert.model.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ extensions:
44
extensible: sinkModel
55
data:
66
- ["java.security.cert", "X509CertSelector", False, "setSubjectPublicKey", "(byte[])", "", "Argument[0]", "credentials-key", "hq-generated"]
7+
8+
- addsTo:
9+
pack: codeql/java-all
10+
extensible: summaryModel
11+
data:
12+
- ["java.security.cert", "X509Certificate", True, "getIssuerX500Principal", "()", "", "Argument[this]", "ReturnValue", "taint", "df-manual"]
13+
- ["java.security.cert", "X509Certificate", True, "getSubjectX500Principal", "()", "", "Argument[this]", "ReturnValue", "taint", "df-manual"]
14+
715
- addsTo:
816
pack: codeql/java-all
917
extensible: neutralModel

java/ql/lib/ext/java.security.model.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ extensions:
2626
- ["java.security", "CodeSource", False, "getCertificates", "()", "", "Argument[this].SyntheticField[java.security.CodeSource.certificates].ArrayElement", "ReturnValue.ArrayElement", "value", "df-manual"]
2727
- ["java.security", "CodeSource", False, "getCodeSigners", "()", "", "Argument[this].SyntheticField[java.security.CodeSource.codeSigners].ArrayElement", "ReturnValue.ArrayElement", "value", "df-manual"]
2828
- ["java.security", "CodeSource", False, "getLocation", "()", "", "Argument[this]", "ReturnValue", "taint", "df-manual"]
29+
- ["java.security", "Permission", True, "Permission", "(String)", "", "Argument[0]", "Argument[this]", "taint", "df-manual"]
30+
- ["java.security", "Permission", True, "getName", "()", "", "Argument[this]", "ReturnValue", "taint", "df-manual"]
31+
2932
- addsTo:
3033
pack: codeql/java-all
3134
extensible: neutralModel

java/ql/lib/ext/java.util.logging.model.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,13 @@ extensions:
4646
- ["java.util.logging", "Logger", False, "getLogger", "(String)", "", "Argument[0]", "ReturnValue.SyntheticField[java.util.logging.Logger.name]", "value", "manual"]
4747
- ["java.util.logging", "Logger", False, "getName", "()", "", "Argument[this].SyntheticField[java.util.logging.Logger.name]", "ReturnValue", "value", "manual"]
4848
- ["java.util.logging", "LogRecord", False, "LogRecord", "", "", "Argument[1]", "Argument[this]", "taint", "manual"]
49+
- ["java.util.logging", "LogRecord", True, "getMessage", "()", "", "Argument[this]", "ReturnValue", "taint", "df-manual"]
50+
- ["java.util.logging", "LogRecord", True, "getParameters", "()", "", "Argument[this].SyntheticField[java.util.logging.LogRecord.parameters].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"]
51+
- ["java.util.logging", "LogRecord", True, "setParameters", "(Object[])", "", "Argument[0].ArrayElement", "Argument[this].SyntheticField[java.util.logging.LogRecord.parameters].ArrayElement", "value", "manual"]
4952
- addsTo:
5053
pack: codeql/java-all
5154
extensible: neutralModel
5255
data:
56+
- ["java.util.logging", "Handler", "getEncoding", "()", "summary", "manual"]
5357
- ["java.util.logging", "Logger", "isLoggable", "(Level)", "summary", "manual"]
58+
- ["java.util.logging", "LogRecord", "getResourceBundle", "()", "summary", "df-manual"]

java/ql/lib/ext/java.util.logging.yml

Lines changed: 0 additions & 8 deletions
This file was deleted.

java/ql/lib/ext/javax.management.model.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,7 @@ extensions:
33
pack: codeql/java-all
44
extensible: summaryModel
55
data:
6+
- ["javax.management", "Notification", True, "Notification", "(String,Object,long,String)", "", "Argument[3]", "Argument[this]", "taint", "df-manual"]
7+
- ["javax.management", "Notification", True, "Notification", "(String,Object,long,long,String)", "", "Argument[4]", "Argument[this]", "taint", "df-manual"]
8+
- ["javax.management", "Notification", True, "getMessage", "()", "", "Argument[this]", "ReturnValue", "taint", "df-manual"]
69
- ["javax.management", "ObjectName", True, "ObjectName", "(String)", "", "Argument[0]", "Argument[this]", "taint", "ai-manual"]

java/ql/lib/semmle/code/java/Element.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ class Element extends @element, Top {
3636
*/
3737
predicate fromSource() { this.getCompilationUnit().isSourceFile() }
3838

39+
/**
40+
* Holds if this element is from source and classified as a stub implementation.
41+
* An implementation is considered a stub, if the the path to the
42+
* source file contains `/stubs/`.
43+
*/
44+
predicate isStub() { this.fromSource() and this.getFile().getAbsolutePath().matches("%/stubs/%") }
45+
3946
/** Gets the compilation unit that this element belongs to. */
4047
CompilationUnit getCompilationUnit() { result = this.getFile() }
4148

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

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,32 @@ private module DispatchImpl {
4040
else any()
4141
}
4242

43-
/** Gets a viable implementation of the target of the given `Call`. */
43+
/**
44+
* Gets a viable implementation of the target of the given `Call`.
45+
* The following heuristic is applied for finding the appropriate callable:
46+
* In general, dispatch to both any existing model and any viable source dispatch.
47+
* However, if the model is generated and the static call target is in the source then
48+
* we trust the source more than the model and skip dispatch to the model.
49+
* Vice versa, if the model is manual and the source dispatch has a comparatively low
50+
* confidence then we only dispatch to the model. Additionally, manual models that
51+
* match a source dispatch exactly take precedence over the source.
52+
*/
4453
DataFlowCallable viableCallable(DataFlowCall c) {
45-
result.asCallable() = sourceDispatch(c.asCall())
46-
or
47-
result.asSummarizedCallable().getACall() = c.asCall()
54+
exists(Call call | call = c.asCall() |
55+
result.asCallable() = sourceDispatch(call)
56+
or
57+
not (
58+
// Only use summarized callables with generated summaries in case
59+
// the static call target is not in the source code.
60+
// Note that if applyGeneratedModel holds it implies that there doesn't
61+
// exist a manual model.
62+
exists(Callable staticTarget | staticTarget = call.getCallee().getSourceDeclaration() |
63+
staticTarget.fromSource() and not staticTarget.isStub()
64+
) and
65+
result.asSummarizedCallable().applyGeneratedModel()
66+
) and
67+
result.asSummarizedCallable().getACall() = call
68+
)
4869
}
4970

5071
/**

0 commit comments

Comments
 (0)