Merge pull request #11779 from jcogs33/jcogs33/model-more-top-jdk-apis

Java: model top JDK APIs
This commit is contained in:
Jami
2023-01-17 10:20:32 -05:00
committed by GitHub
25 changed files with 306 additions and 86 deletions

View File

@@ -0,0 +1,6 @@
---
category: minorAnalysis
---
* Added more dataflow models for frequently-used JDK APIs.
* Removed summary model for `java.lang.String#endsWith(String)` and added neutral model for this API.
* Added additional taint step for `java.lang.String#endsWith(String)` to `ConditionalBypassFlowConfig`.

View File

@@ -63,6 +63,7 @@ extensions:
- ["java.io", "File", True, "getAbsolutePath", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["java.io", "File", True, "getCanonicalFile", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["java.io", "File", True, "getCanonicalPath", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["java.io", "File", True, "getName", "()", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["java.io", "File", True, "toPath", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["java.io", "File", True, "toString", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["java.io", "File", True, "toURI", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
@@ -74,6 +75,7 @@ extensions:
- ["java.io", "InputStream", True, "readNBytes", "(int)", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["java.io", "InputStream", True, "transferTo", "(OutputStream)", "", "Argument[-1]", "Argument[0]", "taint", "manual"]
- ["java.io", "InputStreamReader", False, "InputStreamReader", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"]
- ["java.io", "IOException", False, "IOException", "(String)", "", "Argument[0]", "Argument[-1].SyntheticField[java.lang.Throwable.message]", "value", "manual"]
- ["java.io", "ObjectInput", True, "read", "", "", "Argument[-1]", "Argument[0]", "taint", "manual"]
- ["java.io", "ObjectInputStream", False, "ObjectInputStream", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"]
- ["java.io", "OutputStream", True, "write", "(byte[])", "", "Argument[0]", "Argument[-1]", "taint", "manual"]
@@ -84,3 +86,9 @@ extensions:
- ["java.io", "StringReader", False, "StringReader", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"]
- ["java.io", "Writer", True, "toString", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["java.io", "Writer", True, "write", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"]
- addsTo:
pack: codeql/java-all
extensible: neutralModel
data:
- ["java.io", "File", "exists", "()", "manual"]

View File

@@ -37,9 +37,10 @@ extensions:
- ["java.lang", "CharSequence", True, "charAt", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["java.lang", "CharSequence", True, "subSequence", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["java.lang", "CharSequence", True, "toString", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["java.lang", "Exception", False, "Exception", "(String)", "", "Argument[0]", "Argument[-1].SyntheticField[java.lang.Throwable.message]", "value", "manual"]
- ["java.lang", "IllegalArgumentException", False, "IllegalArgumentException", "(String)", "", "Argument[0]", "Argument[-1].SyntheticField[java.lang.Throwable.message]", "value", "manual"]
- ["java.lang", "IllegalStateException", False, "IllegalStateException", "(String)", "", "Argument[0]", "Argument[-1].SyntheticField[java.lang.Throwable.message]", "value", "manual"]
- ["java.lang", "Integer", False, "parseInt", "(String)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["java.lang", "IndexOutOfBoundsException", False, "IndexOutOfBoundsException", "(String)", "", "Argument[0]", "Argument[-1].SyntheticField[java.lang.Throwable.message]", "value", "manual"]
- ["java.lang", "Iterable", True, "forEach", "(Consumer)", "", "Argument[-1].Element", "Argument[0].Parameter[0]", "value", "manual"]
- ["java.lang", "Iterable", True, "iterator", "()", "", "Argument[-1].Element", "ReturnValue.Element", "value", "manual"]
- ["java.lang", "Iterable", True, "spliterator", "()", "", "Argument[-1].Element", "ReturnValue.Element", "value", "manual"]
@@ -47,12 +48,13 @@ extensions:
- ["java.lang", "Object", True, "clone", "", "", "Argument[-1].MapKey", "ReturnValue.MapKey", "value", "manual"]
- ["java.lang", "Object", True, "clone", "", "", "Argument[-1].MapValue", "ReturnValue.MapValue", "value", "manual"]
- ["java.lang", "RuntimeException", False, "RuntimeException", "(String)", "", "Argument[0]", "Argument[-1].SyntheticField[java.lang.Throwable.message]", "value", "manual"]
- ["java.lang", "RuntimeException", False, "RuntimeException", "(String,Throwable)", "", "Argument[0]", "Argument[-1].SyntheticField[java.lang.Throwable.message]", "value", "manual"]
- ["java.lang", "RuntimeException", False, "RuntimeException", "(String,Throwable)", "", "Argument[1]", "Argument[-1].SyntheticField[java.lang.Throwable.cause]", "value", "manual"]
- ["java.lang", "RuntimeException", False, "RuntimeException", "(Throwable)", "", "Argument[0]", "Argument[-1].SyntheticField[java.lang.Throwable.cause]", "value", "manual"]
- ["java.lang", "String", False, "String", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"]
- ["java.lang", "String", False, "concat", "(String)", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["java.lang", "String", False, "concat", "(String)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["java.lang", "String", False, "copyValueOf", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["java.lang", "String", False, "endsWith", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["java.lang", "String", False, "format", "(Locale,String,Object[])", "", "Argument[1]", "ReturnValue", "taint", "manual"]
- ["java.lang", "String", False, "format", "(Locale,String,Object[])", "", "Argument[2].ArrayElement", "ReturnValue", "taint", "manual"]
- ["java.lang", "String", False, "format", "(String,Object[])", "", "Argument[0]", "ReturnValue", "taint", "manual"]
@@ -87,34 +89,56 @@ extensions:
- ["java.lang", "String", False, "valueOf", "(char)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["java.lang", "String", False, "valueOf", "(char[])", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["java.lang", "String", False, "valueOf", "(char[],int,int)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["java.lang", "String", False, "valueOf", "(int)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["java.lang", "StringBuffer", True, "StringBuffer", "(CharSequence)", "", "Argument[0]", "Argument[-1]", "taint", "manual"]
- ["java.lang", "StringBuffer", True, "StringBuffer", "(String)", "", "Argument[0]", "Argument[-1]", "taint", "manual"]
- ["java.lang", "StringBuilder", True, "StringBuilder", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"]
- ["java.lang", "System", False, "arraycopy", "", "", "Argument[0]", "Argument[2]", "taint", "manual"]
- ["java.lang", "Throwable", False, "Throwable", "(Throwable)", "", "Argument[0]", "Argument[-1].SyntheticField[java.lang.Throwable.cause]", "value", "manual"]
- ["java.lang", "Throwable", False, "getCause", "()", "", "Argument[-1].SyntheticField[java.lang.Throwable.cause]", "ReturnValue", "value", "manual"]
- ["java.lang", "Throwable", False, "getMessage", "()", "", "Argument[-1].SyntheticField[java.lang.Throwable.message]", "ReturnValue", "value", "manual"]
- ["java.lang", "Throwable", True, "getCause", "()", "", "Argument[-1].SyntheticField[java.lang.Throwable.cause]", "ReturnValue", "value", "manual"]
- ["java.lang", "Throwable", True, "getMessage", "()", "", "Argument[-1].SyntheticField[java.lang.Throwable.message]", "ReturnValue", "value", "manual"]
- addsTo:
pack: codeql/java-all
extensible: neutralModel
data:
- ["java.lang", "AbstractStringBuilder", "length", "()", "manual"]
- ["java.lang", "Boolean", "equals", "(Object)", "manual"]
- ["java.lang", "Class", "getClassLoader", "()", "manual"]
- ["java.lang", "Class", "getName", "()", "manual"]
- ["java.lang", "Class", "getSimpleName", "()", "manual"]
- ["java.lang", "Class", "isAssignableFrom", "(Class)", "manual"]
- ["java.lang", "Enum", "Enum", "(String,int)", "manual"]
- ["java.lang", "Enum", "equals", "(Object)", "manual"]
- ["java.lang", "Enum", "name", "()", "manual"]
- ["java.lang", "Enum", "toString", "()", "manual"]
- ["java.lang", "Long", "equals", "(Object)", "manual"]
- ["java.lang", "Object", "equals", "(Object)", "manual"]
- ["java.lang", "Object", "getClass", "()", "manual"]
- ["java.lang", "Object", "hashCode", "()", "manual"]
- ["java.lang", "Object", "toString", "()", "manual"]
- ["java.lang", "String", "contains", "(CharSequence)", "manual"]
- ["java.lang", "String", "endsWith", "(String)", "manual"]
- ["java.lang", "String", "equals", "(Object)", "manual"]
- ["java.lang", "String", "equalsIgnoreCase", "(String)", "manual"]
- ["java.lang", "String", "hashCode", "()", "manual"]
- ["java.lang", "String", "indexOf", "(String)", "manual"]
- ["java.lang", "String", "isEmpty", "()", "manual"]
- ["java.lang", "String", "length", "()", "manual"]
- ["java.lang", "String", "startsWith", "(String)", "manual"]
- ["java.lang", "System", "currentTimeMillis", "()", "manual"]
- ["java.lang", "System", "nanoTime", "()", "manual"]
- ["java.lang", "Thread", "currentThread", "()", "manual"]
- ["java.lang", "Thread", "sleep", "(long)", "manual"]
# The below APIs have numeric flow and are currently being stored as neutral models.
# These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future.
- ["java.lang", "Integer", "intValue", "()", "manual"] # taint-numeric
- ["java.lang", "Integer", "parseInt", "(String)", "manual"] # taint-numeric
- ["java.lang", "Integer", "toString", "(int)", "manual"] # taint-numeric
- ["java.lang", "Integer", "valueOf", "(int)", "manual"] # taint-numeric
- ["java.lang", "Long", "longValue", "()", "manual"] # taint-numeric
- ["java.lang", "Long", "parseLong", "(String)", "manual"] # taint-numeric
- ["java.lang", "Long", "toString", "()", "manual"] # taint-numeric
- ["java.lang", "Math", "min", "(int,int)", "manual"] # value-numeric
- ["java.lang", "String", "valueOf", "(int)", "manual"] # taint-numeric
- ["java.lang", "String", "valueOf", "(long)", "manual"] # taint-numeric

View File

@@ -1,6 +1,12 @@
extensions:
- addsTo:
pack: codeql/java-all
extensible: summaryModel
extensible: neutralModel
data:
- ["java.math", "BigDecimal", False, "BigDecimal", "(String)", "", "Argument[0]", "Argument[-1]", "taint", "manual"]
- ["java.math", "BigDecimal", "compareTo", "(BigDecimal)", "manual"]
# The below APIs have numeric flow and are currently being stored as neutral models.
# These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future.
- ["java.math", "BigDecimal", "BigDecimal", "(String)", "manual"] # taint-numeric
- ["java.math", "BigDecimal", "valueOf", "(double)", "manual"] # taint-numeric
- ["java.math", "BigDecimal", "valueOf", "(long)", "manual"] # taint-numeric

View File

@@ -19,4 +19,16 @@ extensions:
pack: codeql/java-all
extensible: summaryModel
data:
- ["java.sql", "PreparedStatement", True, "setString", "(int,String)", "", "Argument[1]", "Argument[-1]", "value", "manual"]
- ["java.sql", "ResultSet", True, "getString", "(String)", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- addsTo:
pack: codeql/java-all
extensible: neutralModel
data:
- ["java.sql", "ResultSet", "next", "()", "manual"]
# The below APIs have numeric flow and are currently being stored as neutral models.
# These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future.
- ["java.sql", "PreparedStatement", "setInt", "(int,int)", "manual"] # value-numeric
- ["java.sql", "ResultSet", "getInt", "(String)", "manual"] # taint-numeric

View File

@@ -0,0 +1,9 @@
extensions:
- addsTo:
pack: codeql/java-all
extensible: neutralModel
data:
# The below APIs have numeric flow and are currently being stored as neutral models.
# These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future.
- ["java.text", "DateFormat", "format", "(Date)", "manual"] # taint-numeric
- ["java.text", "SimpleDateFormat", "SimpleDateFormat", "(String)", "manual"] # taint-numeric

View File

@@ -0,0 +1,11 @@
extensions:
- addsTo:
pack: codeql/java-all
extensible: neutralModel
data:
- ["java.time", "Instant", "now", "()", "manual"]
- ["java.time", "ZonedDateTime", "now", "()", "manual"]
# The below APIs have numeric flow and are currently being stored as neutral models.
# These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future.
- ["java.time", "LocalDate", "of", "(int,int,int)", "manual"] # taint-numeric

View File

@@ -0,0 +1,16 @@
extensions:
- addsTo:
pack: codeql/java-all
extensible: summaryModel
data:
- ["java.util.concurrent.atomic", "AtomicReference", False, "AtomicReference", "(Object)", "", "Argument[0]", "Argument[-1].SyntheticField[java.util.concurrent.atomic.AtomicReference.value]", "value", "manual"]
- ["java.util.concurrent.atomic", "AtomicReference", False, "get", "()", "", "Argument[-1].SyntheticField[java.util.concurrent.atomic.AtomicReference.value]", "ReturnValue", "value", "manual"]
- addsTo:
pack: codeql/java-all
extensible: neutralModel
data:
# The below APIs have numeric flow and are currently being stored as neutral models.
# These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future.
- ["java.util.concurrent.atomic", "AtomicInteger", "AtomicInteger", "(int)", "manual"] # value-numeric
- ["java.util.concurrent.atomic", "AtomicInteger", "get", "()", "manual"] # value-numeric

View File

@@ -21,3 +21,14 @@ extensions:
- ["java.util.concurrent", "TransferQueue", True, "transfer", "(Object)", "", "Argument[0]", "Argument[-1].Element", "value", "manual"]
- ["java.util.concurrent", "TransferQueue", True, "tryTransfer", "(Object)", "", "Argument[0]", "Argument[-1].Element", "value", "manual"]
- ["java.util.concurrent", "TransferQueue", True, "tryTransfer", "(Object,long,TimeUnit)", "", "Argument[0]", "Argument[-1].Element", "value", "manual"]
- addsTo:
pack: codeql/java-all
extensible: neutralModel
data:
- ["java.util.concurrent", "CountDownLatch", "countDown", "()", "manual"]
# The below APIs have numeric flow and are currently being stored as neutral models.
# These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future.
- ["java.util.concurrent", "CountDownLatch", "CountDownLatch", "(int)", "manual"] # value-numeric
- ["java.util.concurrent", "CountDownLatch", "getCount", "()", "manual"] # value-numeric

View File

@@ -335,6 +335,8 @@ extensions:
- ["java.util", "Stack", True, "peek", "()", "", "Argument[-1].Element", "ReturnValue", "value", "manual"]
- ["java.util", "Stack", True, "pop", "()", "", "Argument[-1].Element", "ReturnValue", "value", "manual"]
- ["java.util", "Stack", True, "push", "(Object)", "", "Argument[0]", "Argument[-1].Element", "value", "manual"]
- ["java.util", "StringJoiner", False, "add", "(CharSequence)", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["java.util", "StringJoiner", False, "add", "(CharSequence)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["java.util", "StringTokenizer", False, "StringTokenizer", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"]
- ["java.util", "StringTokenizer", False, "nextElement", "()", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["java.util", "StringTokenizer", False, "nextToken", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
@@ -360,8 +362,13 @@ extensions:
pack: codeql/java-all
extensible: neutralModel
data:
- ["java.util", "Collections", "emptyList", "()", "manual"]
- ["java.util", "ArrayList", "ArrayList", "(int)", "manual"]
- ["java.util", "ArrayList", "size", "()", "manual"]
- ["java.util", "Collection", "isEmpty", "()", "manual"]
- ["java.util", "Collection", "size", "()", "manual"]
- ["java.util", "Collections", "emptyList", "()", "manual"]
- ["java.util", "Collections", "emptyMap", "()", "manual"]
- ["java.util", "Collections", "emptySet", "()", "manual"]
- ["java.util", "Iterator", "hasNext", "()", "manual"]
- ["java.util", "List", "contains", "(Object)", "manual"]
- ["java.util", "List", "isEmpty", "()", "manual"]
@@ -371,6 +378,7 @@ extensions:
- ["java.util", "Map", "size", "()", "manual"]
- ["java.util", "Objects", "equals", "(Object,Object)", "manual"]
- ["java.util", "Objects", "hash", "(Object[])", "manual"]
- ["java.util", "Objects", "nonNull", "(Object)", "manual"]
- ["java.util", "Optional", "empty", "()", "manual"]
- ["java.util", "Optional", "isPresent", "()", "manual"]
- ["java.util", "Set", "contains", "(Object)", "manual"]
@@ -378,3 +386,13 @@ extensions:
- ["java.util", "Set", "size", "()", "manual"]
- ["java.util", "UUID", "randomUUID", "()", "manual"]
- ["java.util", "UUID", "toString", "()", "manual"]
# The below APIs are currently being stored as neutral models since `WithoutElement` has not yet been implemented for Java.
# When `WithoutElement` is implemented, these should be changed to summary models of the form `Argument[-1].WithoutElement -> Argument[-1]`.
- ["java.util", "List", "clear", "()", "manual"]
- ["java.util", "Map", "clear", "()", "manual"]
# The below APIs have numeric flow and are currently being stored as neutral models.
# These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future.
- ["java.util", "Date", "Date", "(long)", "manual"] # taint-numeric
- ["java.util", "Date", "getTime", "()", "manual"] # taint-numeric

View File

@@ -93,3 +93,4 @@ extensions:
extensible: neutralModel
data:
- ["java.util.stream", "Collectors", "toList", "()", "manual"]
- ["java.util.stream", "Collectors", "toSet", "()", "manual"]

View File

@@ -23,6 +23,19 @@ predicate conditionControlsMethod(MethodAccess ma, Expr e) {
)
}
/**
* Holds if `node1` to `node2` is a dataflow step through the
* `endsWith` method of the `java.lang.String` class.
*/
private predicate endsWithStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(MethodAccess ma |
ma.getMethod().getDeclaringType() instanceof TypeString and
ma.getMethod().getName() = "endsWith" and
ma.getQualifier() = node1.asExpr() and
ma = node2.asExpr()
)
}
/**
* A taint tracking configuration for untrusted data flowing to sensitive conditions.
*/
@@ -32,4 +45,8 @@ class ConditionalBypassFlowConfig extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { conditionControlsMethod(_, sink.asExpr()) }
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
endsWithStep(node1, node2)
}
}

View File

@@ -12,14 +12,8 @@ edges
| ThreadResourceAbuse.java:71:15:71:17 | parameter this [waitTime] : Number | ThreadResourceAbuse.java:74:18:74:25 | this <.field> [waitTime] : Number |
| ThreadResourceAbuse.java:74:18:74:25 | this <.field> [waitTime] : Number | ThreadResourceAbuse.java:74:18:74:25 | waitTime |
| ThreadResourceAbuse.java:141:27:141:43 | getValue(...) : String | ThreadResourceAbuse.java:144:34:144:42 | delayTime |
| ThreadResourceAbuse.java:172:19:172:50 | getHeader(...) : String | ThreadResourceAbuse.java:173:37:173:42 | header : String |
| ThreadResourceAbuse.java:172:19:172:50 | getHeader(...) : String | ThreadResourceAbuse.java:176:17:176:26 | retryAfter |
| ThreadResourceAbuse.java:173:20:173:43 | parseInt(...) : Number | ThreadResourceAbuse.java:176:17:176:26 | retryAfter |
| ThreadResourceAbuse.java:173:37:173:42 | header : String | ThreadResourceAbuse.java:173:20:173:43 | parseInt(...) : Number |
| ThreadResourceAbuse.java:206:28:206:56 | getParameter(...) : String | ThreadResourceAbuse.java:207:39:207:52 | uploadDelayStr : String |
| ThreadResourceAbuse.java:206:28:206:56 | getParameter(...) : String | ThreadResourceAbuse.java:209:49:209:59 | uploadDelay : Number |
| ThreadResourceAbuse.java:207:22:207:53 | parseInt(...) : Number | ThreadResourceAbuse.java:209:49:209:59 | uploadDelay : Number |
| ThreadResourceAbuse.java:207:39:207:52 | uploadDelayStr : String | ThreadResourceAbuse.java:207:22:207:53 | parseInt(...) : Number |
| ThreadResourceAbuse.java:209:30:209:87 | new UploadListener(...) [slowUploads] : Number | UploadListener.java:28:14:28:19 | parameter this [slowUploads] : Number |
| ThreadResourceAbuse.java:209:49:209:59 | uploadDelay : Number | ThreadResourceAbuse.java:209:30:209:87 | new UploadListener(...) [slowUploads] : Number |
| ThreadResourceAbuse.java:209:49:209:59 | uploadDelay : Number | UploadListener.java:15:24:15:44 | sleepMilliseconds : Number |
@@ -48,12 +42,8 @@ nodes
| ThreadResourceAbuse.java:141:27:141:43 | getValue(...) : String | semmle.label | getValue(...) : String |
| ThreadResourceAbuse.java:144:34:144:42 | delayTime | semmle.label | delayTime |
| ThreadResourceAbuse.java:172:19:172:50 | getHeader(...) : String | semmle.label | getHeader(...) : String |
| ThreadResourceAbuse.java:173:20:173:43 | parseInt(...) : Number | semmle.label | parseInt(...) : Number |
| ThreadResourceAbuse.java:173:37:173:42 | header : String | semmle.label | header : String |
| ThreadResourceAbuse.java:176:17:176:26 | retryAfter | semmle.label | retryAfter |
| ThreadResourceAbuse.java:206:28:206:56 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| ThreadResourceAbuse.java:207:22:207:53 | parseInt(...) : Number | semmle.label | parseInt(...) : Number |
| ThreadResourceAbuse.java:207:39:207:52 | uploadDelayStr : String | semmle.label | uploadDelayStr : String |
| ThreadResourceAbuse.java:209:30:209:87 | new UploadListener(...) [slowUploads] : Number | semmle.label | new UploadListener(...) [slowUploads] : Number |
| ThreadResourceAbuse.java:209:49:209:59 | uploadDelay : Number | semmle.label | uploadDelay : Number |
| UploadListener.java:15:24:15:44 | sleepMilliseconds : Number | semmle.label | sleepMilliseconds : Number |

View File

@@ -3,12 +3,8 @@ edges
| NFEAndroidDoS.java:13:24:13:61 | getStringExtra(...) : Object | NFEAndroidDoS.java:14:21:14:51 | parseDouble(...) |
| NFEAndroidDoS.java:22:21:22:31 | getIntent(...) : Intent | NFEAndroidDoS.java:22:21:22:55 | getStringExtra(...) : Object |
| NFEAndroidDoS.java:22:21:22:55 | getStringExtra(...) : Object | NFEAndroidDoS.java:23:15:23:40 | parseInt(...) |
| NFEAndroidDoS.java:22:21:22:55 | getStringExtra(...) : Object | NFEAndroidDoS.java:23:32:23:39 | widthStr : Object |
| NFEAndroidDoS.java:23:32:23:39 | widthStr : Object | NFEAndroidDoS.java:23:15:23:40 | parseInt(...) |
| NFEAndroidDoS.java:25:22:25:32 | getIntent(...) : Intent | NFEAndroidDoS.java:25:22:25:57 | getStringExtra(...) : Object |
| NFEAndroidDoS.java:25:22:25:57 | getStringExtra(...) : Object | NFEAndroidDoS.java:26:16:26:42 | parseInt(...) |
| NFEAndroidDoS.java:25:22:25:57 | getStringExtra(...) : Object | NFEAndroidDoS.java:26:33:26:41 | heightStr : Object |
| NFEAndroidDoS.java:26:33:26:41 | heightStr : Object | NFEAndroidDoS.java:26:16:26:42 | parseInt(...) |
| NFEAndroidDoS.java:43:24:43:34 | getIntent(...) : Intent | NFEAndroidDoS.java:43:24:43:61 | getStringExtra(...) : Object |
| NFEAndroidDoS.java:43:24:43:61 | getStringExtra(...) : Object | NFEAndroidDoS.java:44:21:44:43 | new Double(...) |
| NFEAndroidDoS.java:43:24:43:61 | getStringExtra(...) : Object | NFEAndroidDoS.java:47:21:47:47 | valueOf(...) |
@@ -19,11 +15,9 @@ nodes
| NFEAndroidDoS.java:22:21:22:31 | getIntent(...) : Intent | semmle.label | getIntent(...) : Intent |
| NFEAndroidDoS.java:22:21:22:55 | getStringExtra(...) : Object | semmle.label | getStringExtra(...) : Object |
| NFEAndroidDoS.java:23:15:23:40 | parseInt(...) | semmle.label | parseInt(...) |
| NFEAndroidDoS.java:23:32:23:39 | widthStr : Object | semmle.label | widthStr : Object |
| NFEAndroidDoS.java:25:22:25:32 | getIntent(...) : Intent | semmle.label | getIntent(...) : Intent |
| NFEAndroidDoS.java:25:22:25:57 | getStringExtra(...) : Object | semmle.label | getStringExtra(...) : Object |
| NFEAndroidDoS.java:26:16:26:42 | parseInt(...) | semmle.label | parseInt(...) |
| NFEAndroidDoS.java:26:33:26:41 | heightStr : Object | semmle.label | heightStr : Object |
| NFEAndroidDoS.java:43:24:43:34 | getIntent(...) : Intent | semmle.label | getIntent(...) : Intent |
| NFEAndroidDoS.java:43:24:43:61 | getStringExtra(...) : Object | semmle.label | getStringExtra(...) : Object |
| NFEAndroidDoS.java:44:21:44:43 | new Double(...) | semmle.label | new Double(...) |

View File

@@ -1,5 +1,15 @@
import java.io.IOException;
import java.io.File;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.StringJoiner;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
public class Test {
@@ -9,37 +19,67 @@ public class Test {
public void test() throws Exception {
Exception e1 = new RuntimeException((String)source());
sink((String)e1.getMessage()); // $hasValueFlow
// top 100 JDK APIs tests
{
Exception e1 = new RuntimeException((String)source());
sink((String)e1.getMessage()); // $hasValueFlow
Exception e2 = new RuntimeException((Throwable)source());
sink((Throwable)e2.getCause()); // $hasValueFlow
Exception e2 = new RuntimeException((Throwable)source());
sink((Throwable)e2.getCause()); // $hasValueFlow
Exception e3 = new IllegalArgumentException((String)source());
sink((String)e3.getMessage()); // $hasValueFlow
Exception e3 = new IllegalArgumentException((String)source());
sink((String)e3.getMessage()); // $hasValueFlow
Exception e4 = new IllegalStateException((String)source());
sink((String)e4.getMessage()); // $hasValueFlow
Exception e4 = new IllegalStateException((String)source());
sink((String)e4.getMessage()); // $hasValueFlow
Throwable t = new Throwable((Throwable)source());
sink((Throwable)t.getCause()); // $hasValueFlow
Throwable t = new Throwable((Throwable)source());
sink((Throwable)t.getCause()); // $hasValueFlow
Integer x = (Integer)source();
int y = x;
sink(String.valueOf(y)); // $hasTaintFlow
String s2 = (String)source();
int i = 0;
sink(s2.charAt(i)); // $hasTaintFlow
String s1 = (String)source();
sink(Integer.parseInt(s1)); // $hasTaintFlow
ResultSet rs = (ResultSet)source();
sink(rs.getString("")); // $hasTaintFlow
}
String s2 = (String)source();
int i = 0;
sink(s2.charAt(i)); // $hasTaintFlow
// top 200 JDK APIs tests
{
// java.io
Exception e1 = new IOException((String)source());
sink((String)e1.getMessage()); // $hasValueFlow
String s3 = (String)source();
sink(new BigDecimal(s3)); // $hasTaintFlow
File f = (File)source();
sink(f.getName()); // $hasTaintFlow
ResultSet rs = (ResultSet)source();
sink(rs.getString("")); // $hasTaintFlow
// java.lang
Exception e2 = new Exception((String)source());
sink((String)e2.getMessage()); // $hasValueFlow
Exception e3 = new IndexOutOfBoundsException((String)source());
sink((String)e3.getMessage()); // $hasValueFlow
Exception e4 = new RuntimeException((String)source(), (Throwable)source());
sink((String)e4.getMessage()); // $hasValueFlow
sink((Throwable)e4.getCause()); // $hasValueFlow
// java.sql
Connection con = DriverManager.getConnection("");
PreparedStatement ps1 = con.prepareStatement("UPDATE EMPLOYEES SET NAME = ? WHERE ID = ?");
ps1.setString(1, (String)source());
sink(ps1); // $hasValueFlow
// java.util.concurrent.atomic
AtomicReference ar = new AtomicReference(source());
sink(ar.get()); // $hasValueFlow
// java.util
StringJoiner sj1 = new StringJoiner(",");
sink(sj1.add((CharSequence)source())); // $hasTaintFlow
StringJoiner sj2 = (StringJoiner)source();
sink(sj2.add("test")); // $hasTaintFlow
}
}
}

View File

@@ -57,7 +57,61 @@ predicate topJdkApiName(string apiName) {
"java.nio.file.Path#resolve(String)", "java.lang.Enum#toString()",
"java.lang.RuntimeException#RuntimeException(Throwable)", "java.util.Collection#size()",
"java.lang.String#charAt(int)", "java.util.stream.Stream#forEach(Consumer)",
"java.util.Map#isEmpty()", "java.lang.String#valueOf(int)"
"java.util.Map#isEmpty()", "java.lang.String#valueOf(int)",
// top 200 JDK APIs
"java.lang.Integer#intValue()", "java.util.ArrayList#size()",
"java.util.ArrayList#ArrayList(int)", "java.util.function.Function#apply(Object)",
"java.util.stream.Stream#forEach(Consumer)", "java.util.ArrayList#get(int)",
"java.util.Set#iterator()", "java.util.stream.Collectors#toSet()",
"java.lang.String#replaceAll(String,String)", "java.lang.String#getBytes(Charset)",
"java.util.Objects#requireNonNull(Object)", "java.util.Objects#nonNull(Object)",
"java.lang.String#endsWith(String)", "java.lang.AbstractStringBuilder#length()",
"java.sql.PreparedStatement#setString(int,String)",
"java.util.regex.Pattern#matcher(CharSequence)", "java.nio.file.Path#toString()",
"java.time.Instant#now()", "java.io.File#getAbsolutePath()",
"java.util.Set#addAll(Collection)", "java.lang.Integer#valueOf(int)",
"java.util.HashSet#HashSet(Collection)", "java.lang.Integer#toString(int)",
"java.lang.StringBuilder#StringBuilder(String)", "java.lang.Thread#sleep(long)",
"java.lang.Thread#currentThread()", "java.util.Date#getTime()",
"java.io.Writer#write(String)", "java.lang.String#getBytes()", "java.io.File#exists()",
"java.lang.String#toUpperCase()", "java.lang.Long#parseLong(String)",
"java.util.Collections#emptyMap()", "java.util.Optional#orElseThrow(Supplier)",
"java.util.List#of(Object,Object)", "java.util.concurrent.CountDownLatch#countDown()",
"java.lang.Class#isAssignableFrom(Class)",
"java.lang.IndexOutOfBoundsException#IndexOutOfBoundsException(String)",
"java.lang.Throwable#getCause()", "java.util.Arrays#stream(Object[])",
"java.util.function.Supplier#get()", "java.lang.Exception#Exception(String)",
"java.util.function.Consumer#accept(Object)", "java.util.stream.Stream#anyMatch(Predicate)",
"java.util.List#clear()", "java.io.File#File(File,String)",
"java.lang.String#indexOf(String)", "java.util.List#iterator()",
"java.util.concurrent.CountDownLatch#CountDownLatch(int)", "java.sql.ResultSet#next()",
"java.sql.PreparedStatement#setInt(int,int)",
"java.util.concurrent.atomic.AtomicInteger#get()",
"java.util.stream.Collectors#toMap(Function,Function)", "java.lang.Math#min(int,int)",
"java.lang.Long#equals(Object)", "java.util.Properties#setProperty(String,String)",
"java.util.Map#getOrDefault(Object,Object)", "java.lang.System#getProperty(String)",
"java.util.stream.Stream#of(Object[])", "java.nio.file.Paths#get(String,String[])",
"java.math.BigDecimal#compareTo(BigDecimal)", "java.math.BigDecimal#valueOf(long)",
"java.lang.RuntimeException#RuntimeException(String,Throwable)",
"java.util.Collection#add(Object)", "java.util.Collections#emptySet()",
"java.util.stream.Stream#flatMap(Function)",
"java.util.concurrent.atomic.AtomicReference#get()", "java.util.Collection#isEmpty()",
"java.lang.StringBuffer#toString()", "java.util.Collections#singleton(Object)",
"java.io.File#getName()", "java.time.ZonedDateTime#now()",
"java.io.ByteArrayInputStream#ByteArrayInputStream(byte[])", "java.nio.file.Path#toFile()",
"java.util.Date#Date(long)", "java.lang.System#nanoTime()",
"java.util.Hashtable#put(Object,Object)", "java.util.Map#putAll(Map)",
"java.lang.Long#toString()", "java.util.List#toArray(Object[])", "java.io.File#toPath()",
"java.util.regex.Matcher#group(int)", "java.time.LocalDate#of(int,int,int)",
"java.lang.String#valueOf(long)", "java.math.BigDecimal#valueOf(double)",
"java.io.IOException#IOException(String)", "java.text.DateFormat#format(Date)",
"java.sql.ResultSet#getInt(String)", "java.util.Map#clear()", "java.util.HashSet#add(Object)",
"java.lang.Class#getClassLoader()", "java.lang.Boolean#equals(Object)",
"java.lang.String#concat(String)", "java.util.Collections#singletonMap(Object,Object)",
"java.util.Collection#iterator()", "java.util.Map#computeIfAbsent(Object,Function)",
"java.text.SimpleDateFormat#SimpleDateFormat(String)",
"java.util.StringJoiner#add(CharSequence)", "java.lang.Long#longValue()",
"java.util.stream.Collectors#joining(CharSequence)"
]
}
@@ -88,10 +142,16 @@ class TopJdkApi extends SummarizedCallableBase {
/** Holds if this API has a manual MaD model. */
predicate hasManualMadModel() { this.hasManualSummary() or this.hasManualNeutral() }
/*
* Note: the following top-100 APIs are not modeled with MaD:
* java.util.stream.Stream#collect(Collector) : handled separately on a case-by-case basis as it is too complex for MaD
* java.lang.String#valueOf(Object) : also a complex case; an alias for `Object.toString`, except the dispatch is hidden
* java.lang.Throwable#printStackTrace() : should probably not be a general step, but there might be specialised queries that care
* Note: the following top JDK APIs are not modeled with MaD:
* `java.lang.String#valueOf(Object)`: a complex case; an alias for `Object.toString`, except the dispatch is hidden
* `java.lang.System#getProperty(String)`: needs to be modeled by regular CodeQL matching the get and set keys to reduce FPs
* `java.lang.Throwable#printStackTrace()`: should probably not be a general step, but there might be specialised queries that care
* `java.util.function.Consumer#accept(Object)`: specialized lambda flow
* `java.util.function.Function#apply(Object)`: specialized lambda flow
* `java.util.function.Supplier#get()`: lambda flow
* `java.util.stream.Collectors#joining(CharSequence)`: cannot be modeled completely without a model for `java.util.stream.Stream#collect(Collector)` as well
* `java.util.stream.Collectors#toMap(Function,Function)`: specialized collectors flow
* `java.util.stream.Stream#collect(Collector)`: handled separately on a case-by-case basis as it is too complex for MaD
*/
}

View File

@@ -1,3 +1,9 @@
| java.lang.String#valueOf(Object) | no manual model |
| java.lang.System#getProperty(String) | no manual model |
| java.lang.Throwable#printStackTrace() | no manual model |
| java.util.function.Consumer#accept(Object) | no manual model |
| java.util.function.Function#apply(Object) | no manual model |
| java.util.function.Supplier#get() | no manual model |
| java.util.stream.Collectors#joining(CharSequence) | no manual model |
| java.util.stream.Collectors#toMap(Function,Function) | no manual model |
| java.util.stream.Stream#collect(Collector) | no manual model |

View File

@@ -1,14 +1,27 @@
import java.io.ByteArrayInputStream;
import java.lang.IllegalStateException;
import java.lang.IndexOutOfBoundsException;
import java.lang.Math;
import java.lang.System;
import java.math.BigDecimal;
import java.nio.file.Paths;
import java.sql.ResultSet;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.Map;
import java.util.HashMap;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.lang.System;
import java.lang.IllegalStateException;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class TopJdkApisTest { }

View File

@@ -58,19 +58,19 @@ public class B {
// non-whitelisted constructors don't pass taint
StringWrapper herring = new StringWrapper(complex);
sink(herring);
// toString does not pass taint yet
// toString does not pass taint yet
String valueOfObject = String.valueOf(args);
sink(valueOfObject);
// tainted equality check with constant
boolean cond = "foo" == s;
sink(cond);
// tainted logic with tainted operand
boolean logic = cond && safe();
sink(logic);
// tainted condition
sink(concat.endsWith("I'm tainted"));
// tainted
logic = safe() || cond;
sink(logic);

View File

@@ -18,7 +18,6 @@
| B.java:15:21:15:27 | taint(...) | B.java:51:10:51:21 | fluentConcat |
| B.java:15:21:15:27 | taint(...) | B.java:68:10:68:13 | cond |
| B.java:15:21:15:27 | taint(...) | B.java:71:10:71:14 | logic |
| B.java:15:21:15:27 | taint(...) | B.java:73:10:73:39 | endsWith(...) |
| B.java:15:21:15:27 | taint(...) | B.java:76:10:76:14 | logic |
| B.java:15:21:15:27 | taint(...) | B.java:79:10:79:14 | logic |
| B.java:15:21:15:27 | taint(...) | B.java:87:10:87:16 | trimmed |

View File

@@ -18,7 +18,7 @@ class ExternalApiUsage {
AtomicReference<String> ref = new AtomicReference<>(); // not supported
ref.set("foo");
String.class.isAssignableFrom(Object.class); // parameter with generic type
String.class.isAssignableFrom(Object.class); // parameter with generic type, supported as a neutral model
System.out.println(d);
System.out.println(map);

View File

@@ -1,3 +1,2 @@
| java.lang.Class#isAssignableFrom(Class) | 1 |
| java.time.Duration#ofMillis(long) | 1 |
| java.util.concurrent.atomic.AtomicReference#set(Object) | 1 |

View File

@@ -1,14 +1,10 @@
edges
| Test.java:76:27:76:60 | getProperty(...) : String | Test.java:78:37:78:48 | userProperty : String |
| Test.java:78:20:78:56 | parseInt(...) : Number | Test.java:80:31:80:34 | size |
| Test.java:78:20:78:56 | parseInt(...) : Number | Test.java:86:34:86:37 | size |
| Test.java:78:37:78:48 | userProperty : String | Test.java:78:37:78:55 | trim(...) : String |
| Test.java:78:37:78:55 | trim(...) : String | Test.java:78:20:78:56 | parseInt(...) : Number |
| Test.java:78:37:78:55 | trim(...) : String | Test.java:80:31:80:34 | size |
| Test.java:78:37:78:55 | trim(...) : String | Test.java:86:34:86:37 | size |
nodes
| Test.java:76:27:76:60 | getProperty(...) : String | semmle.label | getProperty(...) : String |
| Test.java:78:20:78:56 | parseInt(...) : Number | semmle.label | parseInt(...) : Number |
| Test.java:78:37:78:48 | userProperty : String | semmle.label | userProperty : String |
| Test.java:78:37:78:55 | trim(...) : String | semmle.label | trim(...) : String |
| Test.java:80:31:80:34 | size | semmle.label | size |

View File

@@ -1,12 +1,9 @@
edges
| Test.java:14:27:14:60 | getProperty(...) : String | Test.java:16:38:16:49 | userProperty : String |
| Test.java:16:21:16:57 | parseInt(...) : Number | Test.java:19:34:19:38 | index |
| Test.java:16:38:16:49 | userProperty : String | Test.java:16:38:16:56 | trim(...) : String |
| Test.java:16:38:16:56 | trim(...) : String | Test.java:16:21:16:57 | parseInt(...) : Number |
| Test.java:16:38:16:56 | trim(...) : String | Test.java:19:34:19:38 | index |
nodes
| Test.java:14:27:14:60 | getProperty(...) : String | semmle.label | getProperty(...) : String |
| Test.java:16:21:16:57 | parseInt(...) : Number | semmle.label | parseInt(...) : Number |
| Test.java:16:38:16:49 | userProperty : String | semmle.label | userProperty : String |
| Test.java:16:38:16:56 | trim(...) : String | semmle.label | trim(...) : String |
| Test.java:19:34:19:38 | index | semmle.label | index |

View File

@@ -11,19 +11,8 @@ edges
| ArithmeticTainted.java:19:26:19:39 | readerBuffered : BufferedReader | ArithmeticTainted.java:19:26:19:50 | readLine(...) : String |
| ArithmeticTainted.java:19:26:19:50 | readLine(...) : String | ArithmeticTainted.java:21:29:21:40 | stringNumber : String |
| ArithmeticTainted.java:19:26:19:50 | readLine(...) : String | ArithmeticTainted.java:21:29:21:40 | stringNumber : String |
| ArithmeticTainted.java:21:12:21:48 | parseInt(...) : Number | ArithmeticTainted.java:32:17:32:20 | data |
| ArithmeticTainted.java:21:12:21:48 | parseInt(...) : Number | ArithmeticTainted.java:40:17:40:20 | data |
| ArithmeticTainted.java:21:12:21:48 | parseInt(...) : Number | ArithmeticTainted.java:50:17:50:20 | data |
| ArithmeticTainted.java:21:12:21:48 | parseInt(...) : Number | ArithmeticTainted.java:64:20:64:23 | data : Number |
| ArithmeticTainted.java:21:12:21:48 | parseInt(...) : Number | ArithmeticTainted.java:95:37:95:40 | data |
| ArithmeticTainted.java:21:12:21:48 | parseInt(...) : Number | ArithmeticTainted.java:118:9:118:12 | data : Number |
| ArithmeticTainted.java:21:12:21:48 | parseInt(...) : Number | ArithmeticTainted.java:119:10:119:13 | data : Number |
| ArithmeticTainted.java:21:12:21:48 | parseInt(...) : Number | ArithmeticTainted.java:120:10:120:13 | data : Number |
| ArithmeticTainted.java:21:12:21:48 | parseInt(...) : Number | ArithmeticTainted.java:121:10:121:13 | data : Number |
| ArithmeticTainted.java:21:29:21:40 | stringNumber : String | ArithmeticTainted.java:21:29:21:47 | trim(...) : String |
| ArithmeticTainted.java:21:29:21:40 | stringNumber : String | ArithmeticTainted.java:21:29:21:47 | trim(...) : String |
| ArithmeticTainted.java:21:29:21:47 | trim(...) : String | ArithmeticTainted.java:21:12:21:48 | parseInt(...) : Number |
| ArithmeticTainted.java:21:29:21:47 | trim(...) : String | ArithmeticTainted.java:21:12:21:48 | parseInt(...) : Number |
| ArithmeticTainted.java:21:29:21:47 | trim(...) : String | ArithmeticTainted.java:32:17:32:20 | data |
| ArithmeticTainted.java:21:29:21:47 | trim(...) : String | ArithmeticTainted.java:40:17:40:20 | data |
| ArithmeticTainted.java:21:29:21:47 | trim(...) : String | ArithmeticTainted.java:50:17:50:20 | data |
@@ -64,8 +53,6 @@ nodes
| ArithmeticTainted.java:19:26:19:39 | readerBuffered : BufferedReader | semmle.label | readerBuffered : BufferedReader |
| ArithmeticTainted.java:19:26:19:50 | readLine(...) : String | semmle.label | readLine(...) : String |
| ArithmeticTainted.java:19:26:19:50 | readLine(...) : String | semmle.label | readLine(...) : String |
| ArithmeticTainted.java:21:12:21:48 | parseInt(...) : Number | semmle.label | parseInt(...) : Number |
| ArithmeticTainted.java:21:12:21:48 | parseInt(...) : Number | semmle.label | parseInt(...) : Number |
| ArithmeticTainted.java:21:29:21:40 | stringNumber : String | semmle.label | stringNumber : String |
| ArithmeticTainted.java:21:29:21:40 | stringNumber : String | semmle.label | stringNumber : String |
| ArithmeticTainted.java:21:29:21:47 | trim(...) : String | semmle.label | trim(...) : String |