Merge branch 'main' into rc/3.7

This commit is contained in:
Andrew Eisenberg
2022-09-20 08:33:58 -07:00
2309 changed files with 133758 additions and 43219 deletions

View File

@@ -1,12 +1,13 @@
package,sink,source,summary,sink:bean-validation,sink:create-file,sink:groovy,sink:header-splitting,sink:information-leak,sink:intent-start,sink:jdbc-url,sink:jexl,sink:jndi-injection,sink:ldap,sink:logging,sink:mvel,sink:ognl-injection,sink:open-url,sink:pending-intent-sent,sink:regex-use[-1],sink:regex-use[0],sink:regex-use[],sink:regex-use[f-1],sink:regex-use[f1],sink:regex-use[f],sink:set-hostname-verifier,sink:sql,sink:url-open-stream,sink:url-redirect,sink:write-file,sink:xpath,sink:xslt,sink:xss,source:android-external-storage-dir,source:android-widget,source:contentprovider,source:remote,summary:taint,summary:value
android.app,16,,103,,,,,,7,,,,,,,,,9,,,,,,,,,,,,,,,,,,,18,85
android.content,24,31,108,,,,,,16,,,,,,,,,,,,,,,,,8,,,,,,,4,,27,,31,77
android.database,59,,30,,,,,,,,,,,,,,,,,,,,,,,59,,,,,,,,,,,30,
android.app,24,,103,,,,,,7,,,,,,,,,17,,,,,,,,,,,,,,,,,,,18,85
android.content,24,31,154,,,,,,16,,,,,,,,,,,,,,,,,8,,,,,,,4,,27,,63,91
android.database,59,,39,,,,,,,,,,,,,,,,,,,,,,,59,,,,,,,,,,,39,
android.net,,,60,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,45,15
android.os,,2,122,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,41,81
android.util,6,16,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,16,,
android.webkit,3,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,2,,
android.widget,,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,1,
androidx.core.app,6,,95,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,12,83
androidx.slice,2,5,88,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,5,,27,61
cn.hutool.core.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
@@ -32,7 +33,7 @@ jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,,
jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,94,55
java.beans,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
java.io,37,,39,,15,,,,,,,,,,,,,,,,,,,,,,,,22,,,,,,,,39,
java.lang,13,,58,,,,,,,,,,,8,,,,,4,,,1,,,,,,,,,,,,,,,46,12
java.lang,13,,66,,,,,,,,,,,8,,,,,4,,,1,,,,,,,,,,,,,,,54,12
java.net,10,3,7,,,,,,,,,,,,,,10,,,,,,,,,,,,,,,,,,,3,7,
java.nio,15,,11,,13,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,11,
java.sql,11,,,,,,,,,4,,,,,,,,,,,,,,,,7,,,,,,,,,,,,
@@ -52,14 +53,14 @@ javax.ws.rs.core,3,,149,,,,1,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,94,55
javax.xml.transform,1,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,6,
javax.xml.xpath,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,,
jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10
kotlin.jvm.internal,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1
kotlin,12,,1835,,10,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,1828,7
net.sf.saxon.s9api,5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,5,,,,,,,
ognl,6,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,
okhttp3,2,,47,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,22,25
org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,
org.apache.commons.collections,,,800,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17,783
org.apache.commons.collections4,,,800,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17,783
org.apache.commons.io,104,,561,,89,,,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,547,14
org.apache.commons.io,106,,556,,91,,,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,542,14
org.apache.commons.jexl2,15,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,,,,,,,,
org.apache.commons.jexl3,15,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,,,,,,,,
org.apache.commons.lang3,,,424,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,293,131
@@ -91,6 +92,7 @@ org.springframework.beans,,,30,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,30
org.springframework.boot.jdbc,1,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,
org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13
org.springframework.context,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,
org.springframework.data.repository,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1
org.springframework.http,14,,70,,,,,,,,,,,,,,14,,,,,,,,,,,,,,,,,,,,60,10
org.springframework.jdbc.core,10,,,,,,,,,,,,,,,,,,,,,,,,,10,,,,,,,,,,,,
org.springframework.jdbc.datasource,4,,,,,,,,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1 package sink source summary sink:bean-validation sink:create-file sink:groovy sink:header-splitting sink:information-leak sink:intent-start sink:jdbc-url sink:jexl sink:jndi-injection sink:ldap sink:logging sink:mvel sink:ognl-injection sink:open-url sink:pending-intent-sent sink:regex-use[-1] sink:regex-use[0] sink:regex-use[] sink:regex-use[f-1] sink:regex-use[f1] sink:regex-use[f] sink:set-hostname-verifier sink:sql sink:url-open-stream sink:url-redirect sink:write-file sink:xpath sink:xslt sink:xss source:android-external-storage-dir source:android-widget source:contentprovider source:remote summary:taint summary:value
2 android.app 16 24 103 7 9 17 18 85
3 android.content 24 31 108 154 16 8 4 27 31 63 77 91
4 android.database 59 30 39 59 30 39
5 android.net 60 45 15
6 android.os 2 122 2 41 81
7 android.util 6 16 6 16
8 android.webkit 3 2 3 2
9 android.widget 1 1 1 1
10 androidx.core.app 6 95 6 12 83
11 androidx.slice 2 5 88 2 5 27 61
12 cn.hutool.core.codec 1 1
13 com.esotericsoftware.kryo.io 1 1
33 jakarta.ws.rs.core 2 149 2 94 55
34 java.beans 1 1
35 java.io 37 39 15 22 39
36 java.lang 13 58 66 8 4 1 46 54 12
37 java.net 10 3 7 10 3 7
38 java.nio 15 11 13 2 11
39 java.sql 11 4 7
53 javax.xml.transform 1 6 1 6
54 javax.xml.xpath 3 3
55 jodd.json 10 10
56 kotlin.jvm.internal kotlin 12 1 1835 10 2 1828 1 7
57 net.sf.saxon.s9api 5 5
58 ognl 6 6
59 okhttp3 2 47 2 22 25
60 org.apache.commons.codec 6 6
61 org.apache.commons.collections 800 17 783
62 org.apache.commons.collections4 800 17 783
63 org.apache.commons.io 104 106 561 556 89 91 15 547 542 14
64 org.apache.commons.jexl2 15 15
65 org.apache.commons.jexl3 15 15
66 org.apache.commons.lang3 424 293 131
92 org.springframework.boot.jdbc 1 1
93 org.springframework.cache 13 13
94 org.springframework.context 3 3
95 org.springframework.data.repository 1 1
96 org.springframework.http 14 70 14 60 10
97 org.springframework.jdbc.core 10 10
98 org.springframework.jdbc.datasource 4 4

View File

@@ -7,17 +7,17 @@ Java framework & library support
:widths: auto
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE022` :sub:`Path injection`,`CWE036` :sub:`Path traversal`,`CWE079` :sub:`Cross-site scripting`,`CWE089` :sub:`SQL injection`,`CWE090` :sub:`LDAP injection`,`CWE094` :sub:`Code injection`,`CWE319` :sub:`Cleartext transmission`
Android,``android.*``,52,424,108,,,3,67,,,
Android,``android.*``,52,479,116,,,3,67,,,
`Apache Commons Collections <https://commons.apache.org/proper/commons-collections/>`_,"``org.apache.commons.collections``, ``org.apache.commons.collections4``",,1600,,,,,,,,
`Apache Commons IO <https://commons.apache.org/proper/commons-io/>`_,``org.apache.commons.io``,,561,104,89,,,,,,15
`Apache Commons IO <https://commons.apache.org/proper/commons-io/>`_,``org.apache.commons.io``,,556,106,91,,,,,,15
`Apache Commons Lang <https://commons.apache.org/proper/commons-lang/>`_,``org.apache.commons.lang3``,,424,,,,,,,,
`Apache Commons Text <https://commons.apache.org/proper/commons-text/>`_,``org.apache.commons.text``,,272,,,,,,,,
`Apache HttpComponents <https://hc.apache.org/>`_,"``org.apache.hc.core5.*``, ``org.apache.http``",5,136,28,,,3,,,,25
`Google Guava <https://guava.dev/>`_,``com.google.common.*``,,728,39,,6,,,,,
`JSON-java <https://github.com/stleary/JSON-java>`_,``org.json``,,236,,,,,,,,
Java Standard Library,``java.*``,3,577,130,28,,,7,,,10
Java Standard Library,``java.*``,3,585,130,28,,,7,,,10
Java extensions,"``javax.*``, ``jakarta.*``",63,609,32,,,4,,1,1,2
`Spring <https://spring.io/>`_,``org.springframework.*``,29,476,101,,,,19,14,,29
Others,"``androidx.slice``, ``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.rabbitmq.client``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``kotlin.jvm.internal``, ``net.sf.saxon.s9api``, ``ognl``, ``okhttp3``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.logging.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jboss.logging``, ``org.jdbi.v3.core``, ``org.jooq``, ``org.mvel2``, ``org.scijava.log``, ``org.slf4j``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``retrofit2``",65,395,932,,,,14,18,,3
Totals,,217,6438,1474,117,6,10,107,33,1,84
`Spring <https://spring.io/>`_,``org.springframework.*``,29,477,101,,,,19,14,,29
Others,"``androidx.core.app``, ``androidx.slice``, ``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.rabbitmq.client``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``kotlin``, ``net.sf.saxon.s9api``, ``ognl``, ``okhttp3``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.logging.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jboss.logging``, ``org.jdbi.v3.core``, ``org.jooq``, ``org.mvel2``, ``org.scijava.log``, ``org.slf4j``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``retrofit2``",65,2324,950,10,,,14,18,,5
Totals,,217,8426,1502,129,6,10,107,33,1,86

View File

@@ -86,7 +86,8 @@ def compile_to_dir(srcs, classpath, java_classpath, output):
run_process([kotlinc,
# kotlinc can default to 256M, which isn't enough when we are extracting the build
'-J-Xmx2G',
'-Xopt-in=kotlin.RequiresOptIn',
'-Werror',
'-opt-in=kotlin.RequiresOptIn',
'-d', output,
'-module-name', 'codeql-kotlin-extractor',
'-no-reflect', '-no-stdlib',

View File

@@ -171,13 +171,12 @@ with open('src/main/kotlin/KotlinExtractorDbScheme.kt', 'w') as kt:
for num, typ in mapping:
genTable(kt, relname, columns, enum, kind, num, typ)
kt.write('sealed interface AnyDbType\n')
for typ in sorted(supertypes):
kt.write('sealed interface Db' + upperFirst(typ))
kt.write('sealed interface Db' + upperFirst(typ) + ': AnyDbType')
# Sorting makes the output deterministic.
names = sorted(supertypes[typ])
if names:
kt.write(': ')
kt.write(', '.join(map(lambda name: 'Db' + upperFirst(name), names)))
kt.write(''.join(map(lambda name: ', Db' + upperFirst(name), names)))
kt.write('\n')
for alias in sorted(type_aliases):
kt.write('typealias Db' + upperFirst(alias) + ' = Db' + upperFirst(type_aliases[alias]) + '\n')

View File

@@ -255,17 +255,6 @@ public class OdasaOutput {
* Trap writers.
*/
/**
* A {@link TrapFileManager} to output facts for the given source file,
* or <code>null</code> if the source file should not be populated.
*/
private TrapFileManager getTrapWriterForCurrentSourceFile() {
File trapFile = getTrapFileForCurrentSourceFile();
if (trapFile==null)
return null;
return trapWriter(trapFile, null, null);
}
/**
* Get a {@link TrapFileManager} to write members
* about a declaration, or <code>null</code> if the declaration shouldn't be populated.

View File

@@ -354,7 +354,12 @@ private fun getTrapFileWriter(compression: Compression, logger: FileLogger, trap
return when (compression) {
Compression.NONE -> NonCompressedTrapFileWriter(logger, trapFileName)
Compression.GZIP -> GZipCompressedTrapFileWriter(logger, trapFileName)
Compression.BROTLI -> throw Exception("Brotli compression is not supported by the Kotlin extractor")
Compression.BROTLI -> {
// Brotli should have been replaced with gzip earlier, but
// if we somehow manage to get here then keep going
logger.error("Impossible Brotli compression requested. Using Gzip instead.")
getTrapFileWriter(Compression.GZIP, logger, trapFileName)
}
}
}

View File

@@ -83,8 +83,12 @@ open class KotlinFileExtractor(
}
file.declarations.forEach { extractDeclaration(it, extractPrivateMembers = true, extractFunctionBodies = true) }
extractStaticInitializer(file, null)
extractStaticInitializer(file, { extractFileClass(file) })
CommentExtractor(this, file, tw.fileId).extract()
if (!declarationStack.isEmpty()) {
logger.errorElement("Declaration stack is not empty after processing the file", file)
}
}
}
@@ -159,31 +163,6 @@ open class KotlinFileExtractor(
}
}
fun getLabel(element: IrElement) : String? {
when (element) {
is IrClass -> return getClassLabel(element, listOf()).classLabel
is IrTypeParameter -> return getTypeParameterLabel(element)
is IrFunction -> return getFunctionLabel(element, null)
is IrValueParameter -> return getValueParameterLabel(element, null)
is IrProperty -> return getPropertyLabel(element)
is IrField -> return getFieldLabel(element)
is IrEnumEntry -> return getEnumEntryLabel(element)
is IrTypeAlias -> return getTypeAliasLabel(element)
// Fresh entities:
is IrBody -> return null
is IrExpression -> return null
// todo add others:
else -> {
logger.errorElement("Unhandled element type: ${element::class}", element)
return null
}
}
}
private fun extractTypeParameter(tp: IrTypeParameter, apparentIndex: Int, javaTypeParameter: JavaTypeParameter?): Label<out DbTypevariable>? {
with("type parameter", tp) {
val parentId = getTypeParameterParentLabel(tp) ?: return null
@@ -331,7 +310,7 @@ open class KotlinFileExtractor(
}
}.firstOrNull { it != null } ?: false)
extractEnclosingClass(c, id, locId, if (useBoundOuterType) argsIncludingOuterClasses?.drop(c.typeParameters.size) else listOf())
extractEnclosingClass(c.parent, id, c, locId, if (useBoundOuterType) argsIncludingOuterClasses?.drop(c.typeParameters.size) else listOf())
return id
}
@@ -414,11 +393,7 @@ open class KotlinFileExtractor(
with("class source", c) {
DeclarationStackAdjuster(c).use {
val id = if (c.isAnonymousObject) {
useAnonymousClass(c).javaResult.id.cast<DbClass>()
} else {
useClassSource(c)
}
val id = useClassSource(c)
val pkg = c.packageFqName?.asString() ?: ""
val cls = if (c.isAnonymousObject) "" else c.name.asString()
val pkgId = extractPackage(pkg)
@@ -444,7 +419,7 @@ open class KotlinFileExtractor(
val locId = tw.getLocation(c)
tw.writeHasLocation(id, locId)
extractEnclosingClass(c, id, locId, listOf())
extractEnclosingClass(c.parent, id, c, locId, listOf())
val javaClass = (c.source as? JavaSourceElement)?.javaElement as? JavaClass
@@ -452,7 +427,7 @@ open class KotlinFileExtractor(
if (extractDeclarations) {
c.declarations.forEach { extractDeclaration(it, extractPrivateMembers = extractPrivateMembers, extractFunctionBodies = extractFunctionBodies) }
if (extractStaticInitializer)
extractStaticInitializer(c, id)
extractStaticInitializer(c, { id })
extractJvmStaticProxyMethods(c, id, extractPrivateMembers, extractFunctionBodies)
}
if (c.isNonCompanionObject) {
@@ -551,10 +526,21 @@ open class KotlinFileExtractor(
}
}
// If `parentClassTypeArguments` is null, the parent class is a raw type.
private fun extractEnclosingClass(innerDeclaration: IrDeclaration, innerId: Label<out DbClassorinterface>, innerLocId: Label<DbLocation>, parentClassTypeArguments: List<IrTypeArgument>?) {
with("enclosing class", innerDeclaration) {
var parent: IrDeclarationParent? = innerDeclaration.parent
/**
* This function traverses the declaration-parent hierarchy upwards, and retrieves the enclosing class of a class to extract the `enclInReftype` relation.
* Additionally, it extracts a companion field for a companion object into its parent class.
*
* Note that the nested class can also be a local class declared inside a function, so the upwards traversal is skipping the non-class parents. Also, in some cases the file class is the enclosing one, which has no IR representation.
*/
private fun extractEnclosingClass(
declarationParent: IrDeclarationParent, // The declaration parent of the element for which we are extracting the enclosing class
innerId: Label<out DbClassorinterface>, // ID of the inner class
innerClass: IrClass?, // The inner class, if available. It's not available if the enclosing class of a generated class is being extracted
innerLocId: Label<DbLocation>, // Location of the inner class
parentClassTypeArguments: List<IrTypeArgument>? // Type arguments of the parent class. If `parentClassTypeArguments` is null, the parent class is a raw type
) {
with("enclosing class", declarationParent) {
var parent: IrDeclarationParent? = declarationParent
while (parent != null) {
if (parent is IrClass) {
val parentId =
@@ -564,13 +550,13 @@ open class KotlinFileExtractor(
useClassInstance(parent, parentClassTypeArguments).typeResult.id
}
tw.writeEnclInReftype(innerId, parentId)
if (innerDeclaration is IrClass && innerDeclaration.isCompanion) {
if (innerClass != null && innerClass.isCompanion) {
// If we are a companion then our parent has a
// public static final ParentClass$CompanionObjectClass CompanionObjectName;
// that we need to fabricate here
val instance = useCompanionObjectClassInstance(innerDeclaration)
val instance = useCompanionObjectClassInstance(innerClass)
if (instance != null) {
val type = useSimpleTypeClass(innerDeclaration, emptyList(), false)
val type = useSimpleTypeClass(innerClass, emptyList(), false)
tw.writeFields(instance.id, instance.name, type.javaResult.id, parentId, instance.id)
tw.writeFieldsKotlinType(instance.id, type.kotlinResult.id)
tw.writeHasLocation(instance.id, innerLocId)
@@ -581,7 +567,7 @@ open class KotlinFileExtractor(
break
} else if (parent is IrFile) {
if (innerDeclaration is IrClass) {
if (innerClass != null) {
// We don't have to extract file class containers for classes
break
}
@@ -667,13 +653,18 @@ open class KotlinFileExtractor(
return type
}
private fun extractStaticInitializer(container: IrDeclarationContainer, classLabel: Label<out DbClassorinterface>?) {
/**
* mkContainerLabel is a lambda so that we get laziness: If the
* container is a file, then we don't want to extract the file class
* unless something actually needs it.
*/
private fun extractStaticInitializer(container: IrDeclarationContainer, mkContainerLabel: () -> Label<out DbClassorinterface>) {
with("static initializer extraction", container) {
extractDeclInitializers(container.declarations, true) {
val parentId = classLabel ?: extractFileClass(container as IrFile)
val containerId = mkContainerLabel()
val clinitLabel = getFunctionLabel(
container,
parentId,
containerId,
"<clinit>",
listOf(),
pluginContext.irBuiltIns.unitType,
@@ -686,7 +677,7 @@ open class KotlinFileExtractor(
)
val clinitId = tw.getLabelFor<DbMethod>(clinitLabel)
val returnType = useType(pluginContext.irBuiltIns.unitType, TypeContext.RETURN)
tw.writeMethods(clinitId, "<clinit>", "<clinit>()", returnType.javaResult.id, parentId, clinitId)
tw.writeMethods(clinitId, "<clinit>", "<clinit>()", returnType.javaResult.id, containerId, clinitId)
tw.writeMethodsKotlinType(clinitId, returnType.kotlinResult.id)
tw.writeCompiler_generated(clinitId, CompilerGeneratedKinds.CLASS_INITIALISATION_METHOD.kind)
@@ -934,7 +925,6 @@ open class KotlinFileExtractor(
private fun extractField(f: IrField, parentId: Label<out DbReftype>): Label<out DbField> {
with("field", f) {
DeclarationStackAdjuster(f).use {
declarationStack.push(f)
val fNameSuffix = getExtensionReceiverType(f)?.let { it.classFqName?.asString()?.replace(".", "$$") } ?: ""
return extractField(useField(f), "${f.name.asString()}$fNameSuffix", f.type, parentId, tw.getLocation(f), f.visibility, f, isExternalDeclaration(f), f.isFinal)
}
@@ -1343,6 +1333,14 @@ open class KotlinFileExtractor(
val receiverClass = receiverType.classifier.owner as? IrClass ?: return listOf()
val ancestorTypes = ArrayList<IrSimpleType>()
// KFunctionX doesn't implement FunctionX on versions before 1.7.0:
if ((callTarget.name.asString() == "invoke") &&
(receiverClass.fqNameWhenAvailable?.asString()?.startsWith("kotlin.reflect.KFunction") == true) &&
(callTarget.parentClassOrNull?.fqNameWhenAvailable?.asString()?.startsWith("kotlin.Function") == true)
) {
return receiverType.arguments
}
// Populate ancestorTypes with the path from receiverType's class to its ancestor, callTarget's declaring type.
fun walkFrom(c: IrClass): Boolean {
if(declaringType == c)
@@ -1361,16 +1359,25 @@ open class KotlinFileExtractor(
}
// If a path was found, repeatedly substitute types to get the corresponding specialisation of that ancestor.
return if (!walkFrom(receiverClass)) {
if (!walkFrom(receiverClass)) {
logger.errorElement("Failed to find a class declaring ${callTarget.name} starting at ${receiverClass.name}", callTarget)
listOf()
return listOf()
} else {
var subbedType = receiverType
var subbedType: IrSimpleType = receiverType
ancestorTypes.forEach {
val thisClass = subbedType.classifier.owner as IrClass
subbedType = it.substituteTypeArguments(thisClass.typeParameters, subbedType.arguments) as IrSimpleType
val thisClass = subbedType.classifier.owner
if (thisClass !is IrClass) {
logger.errorElement("Found ancestor with unexpected type ${thisClass.javaClass}", callTarget)
return listOf()
}
val itSubbed = it.substituteTypeArguments(thisClass.typeParameters, subbedType.arguments)
if (itSubbed !is IrSimpleType) {
logger.errorElement("Substituted type has unexpected type ${itSubbed.javaClass}", callTarget)
return listOf()
}
subbedType = itSubbed
}
subbedType.arguments
return subbedType.arguments
}
}
@@ -1452,12 +1459,14 @@ open class KotlinFileExtractor(
// type arguments at index -2, -3, ...
extractTypeArguments(typeArguments, locId, id, enclosingCallable, enclosingStmt, -2, true)
val isFunctionInvoke = drType != null
&& drType is IrSimpleType
&& drType.isFunctionOrKFunction()
&& callTarget.name.asString() == OperatorNameConventions.INVOKE.asString()
val isBigArityFunctionInvoke = isFunctionInvoke
&& (drType as IrSimpleType).arguments.size > BuiltInFunctionArity.BIG_ARITY
val (isFunctionInvoke, isBigArityFunctionInvoke) =
if (drType is IrSimpleType &&
drType.isFunctionOrKFunction() &&
callTarget.name.asString() == OperatorNameConventions.INVOKE.asString()) {
Pair(true, drType.arguments.size > BuiltInFunctionArity.BIG_ARITY)
} else {
Pair(false, false)
}
if (callTarget.isLocalFunction()) {
val ids = getLocallyVisibleFunctionLabels(callTarget)
@@ -1468,7 +1477,7 @@ open class KotlinFileExtractor(
extractNewExprForLocalFunction(ids, id, locId, enclosingCallable, enclosingStmt)
} else {
val methodId =
if (drType != null && extractClassTypeArguments && drType is IrSimpleType && !isUnspecialised(drType)) {
if (extractClassTypeArguments && drType is IrSimpleType && !isUnspecialised(drType, logger)) {
val extractionMethod = if (isFunctionInvoke) {
// For `kotlin.FunctionX` and `kotlin.reflect.KFunctionX` interfaces, we're making sure that we
@@ -1544,19 +1553,18 @@ open class KotlinFileExtractor(
}
private fun extractStaticTypeAccessQualifier(target: IrDeclaration, parentExpr: Label<out DbExprparent>, locId: Label<DbLocation>, enclosingCallable: Label<out DbCallable>, enclosingStmt: Label<out DbStmt>) {
if (target.shouldExtractAsStaticMemberOfClass) {
extractTypeAccessRecursive(target.parentAsClass.toRawType(), locId, parentExpr, -1, enclosingCallable, enclosingStmt)
} else if (target.shouldExtractAsStaticMemberOfFile) {
extractTypeAccess(useFileClassType(target.parent as IrFile), locId, parentExpr, -1, enclosingCallable, enclosingStmt)
if (target.shouldExtractAsStatic) {
val parent = target.parent
if (parent is IrClass) {
extractTypeAccessRecursive(parent.toRawType(), locId, parentExpr, -1, enclosingCallable, enclosingStmt)
} else if (parent is IrFile) {
extractTypeAccess(useFileClassType(parent), locId, parentExpr, -1, enclosingCallable, enclosingStmt)
} else {
logger.warnElement("Unexpected static type access qualifer ${parent.javaClass}", target)
}
}
}
private val IrDeclaration.shouldExtractAsStaticMemberOfClass: Boolean
get() = this.shouldExtractAsStatic && parent is IrClass
private val IrDeclaration.shouldExtractAsStaticMemberOfFile: Boolean
get() = this.shouldExtractAsStatic && parent is IrFile
private fun isStaticAnnotatedNonCompanionMember(f: IrSimpleFunction) =
f.parentClassOrNull?.isNonCompanionObject == true &&
(f.hasAnnotation(jvmStaticFqName) || f.correspondingPropertySymbol?.owner?.hasAnnotation(jvmStaticFqName) == true)
@@ -1584,7 +1592,7 @@ open class KotlinFileExtractor(
}
}
private fun findFunction(cls: IrClass, name: String): IrFunction? = cls.declarations.find { it is IrFunction && it.name.asString() == name } as IrFunction?
private fun findFunction(cls: IrClass, name: String): IrFunction? = cls.declarations.findSubType<IrFunction> { it.name.asString() == name }
val jvmIntrinsicsClass by lazy {
val result = pluginContext.referenceClass(FqName("kotlin.jvm.internal.Intrinsics"))?.owner
@@ -1600,11 +1608,13 @@ open class KotlinFileExtractor(
return result
}
private fun findTopLevelFunctionOrWarn(functionFilter: String, type: String, warnAgainstElement: IrElement): IrFunction? {
private fun findTopLevelFunctionOrWarn(functionFilter: String, type: String, parameterTypes: Array<String>, warnAgainstElement: IrElement): IrFunction? {
val fn = pluginContext.referenceFunctions(FqName(functionFilter))
.firstOrNull { it.owner.parentClassOrNull?.fqNameWhenAvailable?.asString() == type }
?.owner
.firstOrNull { fnSymbol ->
fnSymbol.owner.parentClassOrNull?.fqNameWhenAvailable?.asString() == type &&
fnSymbol.owner.valueParameters.map { it.type.classFqName?.asString() }.toTypedArray() contentEquals parameterTypes
}?.owner
if (fn != null) {
if (fn.parentClassOrNull != null) {
@@ -1641,12 +1651,11 @@ open class KotlinFileExtractor(
}
val stringValueOfObjectMethod by lazy {
val result = javaLangString?.declarations?.find {
it is IrFunction &&
val result = javaLangString?.declarations?.findSubType<IrFunction> {
it.name.asString() == "valueOf" &&
it.valueParameters.size == 1 &&
it.valueParameters[0].type == pluginContext.irBuiltIns.anyNType
} as IrFunction?
}
if (result == null) {
logger.error("Couldn't find declaration java.lang.String.valueOf(Object)")
}
@@ -1654,9 +1663,9 @@ open class KotlinFileExtractor(
}
val objectCloneMethod by lazy {
val result = javaLangObject?.declarations?.find {
it is IrFunction && it.name.asString() == "clone"
} as IrFunction?
val result = javaLangObject?.declarations?.findSubType<IrFunction> {
it.name.asString() == "clone"
}
if (result == null) {
logger.error("Couldn't find declaration java.lang.Object.clone(...)")
}
@@ -1670,10 +1679,9 @@ open class KotlinFileExtractor(
}
val kotlinNoWhenBranchMatchedConstructor by lazy {
val result = kotlinNoWhenBranchMatchedExn?.declarations?.find {
it is IrConstructor &&
val result = kotlinNoWhenBranchMatchedExn?.declarations?.findSubType<IrConstructor> {
it.valueParameters.isEmpty()
} as IrConstructor?
}
if (result == null) {
logger.error("Couldn't find no-arg constructor for kotlin.NoWhenBranchMatchedException")
}
@@ -1686,7 +1694,7 @@ open class KotlinFileExtractor(
result
}
private fun isFunction(target: IrFunction, pkgName: String, classNameLogged: String, classNamePredicate: (String) -> Boolean, fName: String, hasQuestionMark: Boolean? = false): Boolean {
private fun isFunction(target: IrFunction, pkgName: String, classNameLogged: String, classNamePredicate: (String) -> Boolean, fName: String, isNullable: Boolean? = false): Boolean {
val verbose = false
fun verboseln(s: String) { if(verbose) println(s) }
verboseln("Attempting match for $pkgName $classNameLogged $fName")
@@ -1696,14 +1704,14 @@ open class KotlinFileExtractor(
}
val extensionReceiverParameter = target.extensionReceiverParameter
val targetClass = if (extensionReceiverParameter == null) {
if (hasQuestionMark == true) {
if (isNullable == true) {
verboseln("Nullablility of type didn't match (target is not an extension method)")
return false
}
target.parent
} else {
val st = extensionReceiverParameter.type as? IrSimpleType
if (hasQuestionMark != null && st?.hasQuestionMark != hasQuestionMark) {
if (isNullable != null && st?.isNullable() != isNullable) {
verboseln("Nullablility of type didn't match")
return false
}
@@ -1730,8 +1738,8 @@ open class KotlinFileExtractor(
return true
}
private fun isFunction(target: IrFunction, pkgName: String, className: String, fName: String, hasQuestionMark: Boolean? = false) =
isFunction(target, pkgName, className, { it == className }, fName, hasQuestionMark)
private fun isFunction(target: IrFunction, pkgName: String, className: String, fName: String, isNullable: Boolean? = false) =
isFunction(target, pkgName, className, { it == className }, fName, isNullable)
private fun isNumericFunction(target: IrFunction, fName: String): Boolean {
return isFunction(target, "kotlin", "Int", fName) ||
@@ -1756,6 +1764,12 @@ open class KotlinFileExtractor(
else -> false
}
private fun isGenericArrayType(typeName: String) =
when(typeName) {
"Array" -> true
else -> false
}
private fun extractCall(c: IrCall, callable: Label<out DbCallable>, stmtExprParent: StmtExprParent) {
with("call", c) {
val target = tryReplaceSyntheticFunction(c.symbol.owner)
@@ -1798,13 +1812,35 @@ open class KotlinFileExtractor(
return
}
val func = ((c.getTypeArgument(0) as? IrSimpleType)?.classifier?.owner as? IrClass)?.declarations?.find { it is IrFunction && it.name.asString() == fnName }
if (func == null) {
logger.errorElement("Couldn't find function $fnName on enum type", c)
val enumType = (c.getTypeArgument(0) as? IrSimpleType)?.classifier?.owner
if (enumType == null) {
logger.errorElement("Couldn't find type of enum type", c)
return
}
extractMethodAccess(func as IrFunction, false)
if (enumType is IrClass) {
val func = enumType.declarations.findSubType<IrFunction> { it.name.asString() == fnName }
if (func == null) {
logger.errorElement("Couldn't find function $fnName on enum type", c)
return
}
extractMethodAccess(func, false)
} else if (enumType is IrTypeParameter && enumType.isReified) {
// A call to `enumValues<T>()` is being extracted, where `T` is a reified type parameter of an `inline` function.
// We can't generate a valid expression here, because we would need to know the type of T on the call site.
// TODO: replace error expression with something that better shows this expression is unrepresentable.
val id = tw.getFreshIdLabel<DbErrorexpr>()
val type = useType(c.type)
tw.writeExprs_errorexpr(id, type.javaResult.id, parent, idx)
tw.writeExprsKotlinType(id, type.kotlinResult.id)
tw.writeHasLocation(id, tw.getLocation(c))
tw.writeCallableEnclosingExpr(id, callable)
tw.writeStatementEnclosingExpr(id, enclosingStmt)
} else {
logger.errorElement("Unexpected enum type rep ${enumType.javaClass}", c)
}
}
fun binopReceiver(id: Label<out DbExpr>, receiver: IrExpression?, receiverDescription: String) {
@@ -2177,30 +2213,47 @@ open class KotlinFileExtractor(
extractRawMethodAccess(getter, c, callable, parent, idx, enclosingStmt, listOf(), null, ext, typeArguments)
}
}
isFunction(target, "kotlin", "(some array type)", { isArrayType(it) }, "iterator") && c.origin == IrStatementOrigin.FOR_LOOP_ITERATOR -> {
findTopLevelFunctionOrWarn("kotlin.jvm.internal.iterator", "kotlin.jvm.internal.ArrayIteratorKt", c)?.let { iteratorFn ->
isFunction(target, "kotlin", "(some array type)", { isArrayType(it) }, "iterator") -> {
val parentClass = target.parent
if (parentClass !is IrClass) {
logger.errorElement("Iterator parent is not a class", c)
return
}
var typeFilter = if (isGenericArrayType(parentClass.name.asString())) {
"kotlin.jvm.internal.ArrayIteratorKt"
} else {
"kotlin.jvm.internal.ArrayIteratorsKt"
}
findTopLevelFunctionOrWarn("kotlin.jvm.internal.iterator", typeFilter, arrayOf(parentClass.kotlinFqName.asString()), c)?.let { iteratorFn ->
val dispatchReceiver = c.dispatchReceiver
if (dispatchReceiver == null) {
logger.errorElement("No dispatch receiver found for array iterator call", c)
} else {
val typeArgs = (dispatchReceiver.type as IrSimpleType).arguments.map {
when(it) {
is IrTypeProjection -> it.type
else -> pluginContext.irBuiltIns.anyNType
val drType = dispatchReceiver.type
if (drType !is IrSimpleType) {
logger.errorElement("Dispatch receiver with unexpected type rep found for array iterator call: ${drType.javaClass}", c)
} else {
val typeArgs = drType.arguments.map {
when(it) {
is IrTypeProjection -> it.type
else -> pluginContext.irBuiltIns.anyNType
}
}
extractRawMethodAccess(iteratorFn, c, callable, parent, idx, enclosingStmt, listOf(c.dispatchReceiver), null, null, typeArgs)
}
extractRawMethodAccess(iteratorFn, c, callable, parent, idx, enclosingStmt, listOf(c.dispatchReceiver), null, null, typeArgs)
}
}
}
isFunction(target, "kotlin", "(some array type)", { isArrayType(it) }, "get") && c.origin == IrStatementOrigin.GET_ARRAY_ELEMENT -> {
isFunction(target, "kotlin", "(some array type)", { isArrayType(it) }, "get") && c.origin == IrStatementOrigin.GET_ARRAY_ELEMENT && c.dispatchReceiver != null -> {
val id = tw.getFreshIdLabel<DbArrayaccess>()
val type = useType(c.type)
tw.writeExprs_arrayaccess(id, type.javaResult.id, parent, idx)
tw.writeExprsKotlinType(id, type.kotlinResult.id)
binopDisp(id)
}
isFunction(target, "kotlin", "(some array type)", { isArrayType(it) }, "set") && c.origin == IrStatementOrigin.EQ -> {
isFunction(target, "kotlin", "(some array type)", { isArrayType(it) }, "set") && c.origin == IrStatementOrigin.EQ && c.dispatchReceiver != null -> {
val array = c.dispatchReceiver
val arrayIdx = c.getValueArgument(0)
val assignedValue = c.getValueArgument(1)
@@ -2273,10 +2326,10 @@ open class KotlinFileExtractor(
logger.errorElement("Argument to dataClassArrayMemberToString not a class", c)
return
}
val realCallee = javaUtilArrays?.declarations?.find { decl ->
decl is IrFunction && decl.name.asString() == "toString" && decl.valueParameters.size == 1 &&
val realCallee = javaUtilArrays?.declarations?.findSubType<IrFunction> { decl ->
decl.name.asString() == "toString" && decl.valueParameters.size == 1 &&
decl.valueParameters[0].type.classOrNull?.let { it == realArrayClass } == true
} as IrFunction?
}
if (realCallee == null) {
logger.errorElement("Couldn't find a java.lang.Arrays.toString method matching class ${realArrayClass.owner.name}", c)
} else {
@@ -2300,10 +2353,10 @@ open class KotlinFileExtractor(
logger.errorElement("Argument to dataClassArrayMemberHashCode not a class", c)
return
}
val realCallee = javaUtilArrays?.declarations?.find { decl ->
decl is IrFunction && decl.name.asString() == "hashCode" && decl.valueParameters.size == 1 &&
val realCallee = javaUtilArrays?.declarations?.findSubType<IrFunction> { decl ->
decl.name.asString() == "hashCode" && decl.valueParameters.size == 1 &&
decl.valueParameters[0].type.classOrNull?.let { it == realArrayClass } == true
} as IrFunction?
}
if (realCallee == null) {
logger.errorElement("Couldn't find a java.lang.Arrays.hashCode method matching class ${realArrayClass.owner.name}", c)
} else {
@@ -2380,18 +2433,27 @@ open class KotlinFileExtractor(
callable: Label<out DbCallable>,
enclosingStmt: Label<out DbStmt>
) {
val isAnonymous = e.type.isAnonymous
val eType = e.type
if (eType !is IrSimpleType) {
logger.errorElement("Constructor call has non-simple type ${eType.javaClass}", e)
return
}
val isAnonymous = eType.isAnonymous
val type: TypeResults = if (isAnonymous) {
if (e.typeArgumentsCount > 0) {
logger.warn("Unexpected type arguments for anonymous class constructor call")
logger.warnElement("Unexpected type arguments (${e.typeArgumentsCount}) for anonymous class constructor call", e)
}
val c = eType.classifier.owner
if (c !is IrClass) {
logger.errorElement("Anonymous constructor call type not a class (${c.javaClass})", e)
return
}
val c = (e.type as IrSimpleType).classifier.owner as IrClass
useAnonymousClass(c)
} else {
useType(e.type)
useType(eType)
}
val locId = tw.getLocation(e)
val id = extractNewExpr(e.symbol.owner, (e.type as? IrSimpleType)?.arguments, type, locId, parent, idx, callable, enclosingStmt)
val id = extractNewExpr(e.symbol.owner, eType.arguments, type, locId, parent, idx, callable, enclosingStmt)
if (isAnonymous) {
tw.writeIsAnonymClass(type.javaResult.id.cast<DbClass>(), id)
@@ -2405,8 +2467,11 @@ open class KotlinFileExtractor(
}
val typeAccessType = if (isAnonymous) {
val c = (e.type as IrSimpleType).classifier.owner as IrClass
if (c.superTypes.size == 1) {
val c = eType.classifier.owner
if (c !is IrClass) {
logger.warnElement("Anonymous type not a class (${c.javaClass})", e)
}
if ((c as? IrClass)?.superTypes?.size == 1) {
useType(c.superTypes.first())
} else {
useType(pluginContext.irBuiltIns.anyType)
@@ -2416,7 +2481,7 @@ open class KotlinFileExtractor(
}
if (e is IrConstructorCall) {
extractConstructorTypeAccess(e.type, typeAccessType, e.symbol, locId, id, -3, callable, enclosingStmt)
extractConstructorTypeAccess(eType, typeAccessType, e.symbol, locId, id, -3, callable, enclosingStmt)
} else {
val typeAccessId =
extractTypeAccess(typeAccessType, locId, id, -3, callable, enclosingStmt)
@@ -2425,9 +2490,6 @@ open class KotlinFileExtractor(
}
}
// todo: calculating the enclosing ref type could be done through this, instead of walking up the declaration parent chain
private val declarationStack: Stack<IrDeclaration> = Stack()
abstract inner class StmtExprParent {
abstract fun stmt(e: IrExpression, callable: Label<out DbCallable>): StmtParent
abstract fun expr(e: IrExpression, callable: Label<out DbCallable>): ExprParent
@@ -2520,8 +2582,8 @@ open class KotlinFileExtractor(
indexVarDecl.initializer?.let { indexVarInitializer ->
(e.statements[2] as? IrCall)?.let { arraySetCall ->
if (isFunction(arraySetCall.symbol.owner, "kotlin", "(some array type)", { isArrayType(it) }, "set")) {
val updateRhs = arraySetCall.getValueArgument(1)
if (updateRhs == null) {
val updateRhs0 = arraySetCall.getValueArgument(1)
if (updateRhs0 == null) {
logger.errorElement("Update RHS not found", e)
return false
}
@@ -2534,7 +2596,7 @@ open class KotlinFileExtractor(
receiverVal -> receiverVal.symbol.owner == arrayVarDecl.symbol.owner
} ?: false
},
updateRhs
updateRhs0
)?.let { updateRhs ->
val origin = e.origin
if (origin == null) {
@@ -2601,8 +2663,15 @@ open class KotlinFileExtractor(
val irCallable = declarationStack.peek()
val delegatingClass = e.symbol.owner.parent as IrClass
val currentClass = irCallable.parent as IrClass
val delegatingClass = e.symbol.owner.parent
val currentClass = irCallable.parent
if (delegatingClass !is IrClass) {
logger.warnElement("Delegating class isn't a class: " + delegatingClass.javaClass, e)
}
if (currentClass !is IrClass) {
logger.warnElement("Current class isn't a class: " + currentClass.javaClass, e)
}
val id: Label<out DbStmt>
if (delegatingClass != currentClass) {
@@ -3036,7 +3105,14 @@ open class KotlinFileExtractor(
extractTypeOperatorCall(e, callable, exprParent.parent, exprParent.idx, exprParent.enclosingStmt)
}
is IrVararg -> {
logger.errorElement("Unexpected IrVararg", e)
var spread = e.elements.getOrNull(0) as? IrSpreadElement
if (spread == null || e.elements.size != 1) {
logger.errorElement("Unexpected IrVararg", e)
return
}
// There are lowered IR cases when the vararg expression is not within a call, such as
// val temp0 = [*expr]
extractExpression(spread.expression, callable, parent)
}
is IrGetObjectValue -> {
// For `object MyObject { ... }`, the .class has an
@@ -3345,15 +3421,11 @@ open class KotlinFileExtractor(
data class ReceiverInfo(val receiver: IrExpression, val type: IrType, val field: Label<DbField>, val indexOffset: Int)
private fun makeReceiverInfo(callableReferenceExpr: IrCallableReference<out IrSymbol>, receiver: IrExpression?, indexOffset: Int): ReceiverInfo? {
private fun makeReceiverInfo(receiver: IrExpression?, indexOffset: Int): ReceiverInfo? {
if (receiver == null) {
return null
}
val type = receiver.type
if (type == null) {
logger.warnElement("Receiver has no type", callableReferenceExpr)
return null
}
val field: Label<DbField> = tw.getFreshIdLabel()
return ReceiverInfo(receiver, type, field, indexOffset)
}
@@ -3366,8 +3438,8 @@ open class KotlinFileExtractor(
: GeneratedClassHelper(locId, ids) {
// Only one of the receivers can be non-null, but we defensively handle the case when both are null anyway
private val dispatchReceiverInfo = makeReceiverInfo(callableReferenceExpr, callableReferenceExpr.dispatchReceiver, 0)
private val extensionReceiverInfo = makeReceiverInfo(callableReferenceExpr, callableReferenceExpr.extensionReceiver, if (dispatchReceiverInfo == null) 0 else 1)
private val dispatchReceiverInfo = makeReceiverInfo(callableReferenceExpr.dispatchReceiver, 0)
private val extensionReceiverInfo = makeReceiverInfo(callableReferenceExpr.extensionReceiver, if (dispatchReceiverInfo == null) 0 else 1)
fun extractReceiverField() {
val firstAssignmentStmtIdx = 1
@@ -3658,6 +3730,11 @@ open class KotlinFileExtractor(
logger.errorElement("Cannot find class for kPropertyType. ${kPropertyType.classFqName?.asString()}", propertyReferenceExpr)
return
}
val parameterTypes = kPropertyType.arguments.map { it as? IrType }.requireNoNullsOrNull()
if (parameterTypes == null) {
logger.errorElement("Unexpected: Non-IrType parameter.", propertyReferenceExpr)
return
}
val locId = tw.getLocation(propertyReferenceExpr)
@@ -3670,15 +3747,14 @@ open class KotlinFileExtractor(
constructorBlock = tw.getFreshIdLabel()
)
val currentDeclaration = declarationStack.peek()
val declarationParent = declarationStack.peekAsDeclarationParent(propertyReferenceExpr) ?: return
val prefix = if (kPropertyClass.owner.name.asString().startsWith("KMutableProperty")) "Mutable" else ""
val baseClass = pluginContext.referenceClass(FqName("kotlin.jvm.internal.${prefix}PropertyReference${kPropertyType.arguments.size - 1}"))?.owner?.typeWith()
?: pluginContext.irBuiltIns.anyType
val classId = extractGeneratedClass(ids, listOf(baseClass, kPropertyType), locId, currentDeclaration)
val classId = extractGeneratedClass(ids, listOf(baseClass, kPropertyType), locId, propertyReferenceExpr, declarationParent)
val helper = PropertyReferenceHelper(propertyReferenceExpr, locId, ids)
val parameterTypes = kPropertyType.arguments.map { it as IrType }
helper.extractReceiverField()
@@ -3825,7 +3901,11 @@ open class KotlinFileExtractor(
return
}
val parameterTypes = type.arguments.map { it as IrType }
val parameterTypes = type.arguments.map { it as? IrType }.requireNoNullsOrNull()
if (parameterTypes == null) {
logger.errorElement("Unexpected: Non-IrType parameter.", functionReferenceExpr)
return
}
val dispatchReceiverIdx: Int
val expressionTypeArguments: List<IrType>
@@ -3874,12 +3954,12 @@ open class KotlinFileExtractor(
if (fnInterfaceType == null) {
logger.warnElement("Cannot find functional interface type for function reference", functionReferenceExpr)
} else {
val currentDeclaration = declarationStack.peek()
val declarationParent = declarationStack.peekAsDeclarationParent(functionReferenceExpr) ?: return
// `FunctionReference` base class is required, because that's implementing `KFunction`.
val baseClass = pluginContext.referenceClass(FqName("kotlin.jvm.internal.FunctionReference"))?.owner?.typeWith()
?: pluginContext.irBuiltIns.anyType
val classId = extractGeneratedClass(ids, listOf(baseClass, fnInterfaceType), locId, currentDeclaration)
val classId = extractGeneratedClass(ids, listOf(baseClass, fnInterfaceType), locId, functionReferenceExpr, declarationParent)
helper.extractReceiverField()
@@ -4233,6 +4313,8 @@ open class KotlinFileExtractor(
* Extracts a type access expression and its child type access expressions in case of a generic type. Nested generics are also handled.
*/
private fun extractTypeAccessRecursive(t: IrType, location: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int, enclosingCallable: Label<out DbCallable>, enclosingStmt: Label<out DbStmt>, typeContext: TypeContext = TypeContext.OTHER): Label<out DbExpr> {
// TODO: `useType` substitutes types to their java equivalent, and sometimes that also means changing the number of type arguments. The below logic doesn't take this into account.
// For example `KFunction2<Int,Double,String>` becomes `KFunction<String>` with three child type access expressions: `Int`, `Double`, `String`.
val typeAccessId = extractTypeAccess(useType(t, typeContext), location, parent, idx, enclosingCallable, enclosingStmt)
if (t is IrSimpleType) {
extractTypeArguments(t.arguments.filterIsInstance<IrType>(), location, typeAccessId, enclosingCallable, enclosingStmt)
@@ -4452,7 +4534,7 @@ open class KotlinFileExtractor(
return
}
val invokeMethod = functionType.classOrNull?.owner?.declarations?.filterIsInstance<IrFunction>()?.find { it.name.asString() == OperatorNameConventions.INVOKE.asString()}
val invokeMethod = functionType.classOrNull?.owner?.declarations?.findSubType<IrFunction> { it.name.asString() == OperatorNameConventions.INVOKE.asString()}
if (invokeMethod == null) {
logger.errorElement("Couldn't find `invoke` method on functional interface.", e)
return
@@ -4463,7 +4545,7 @@ open class KotlinFileExtractor(
logger.errorElement("Expected to find SAM conversion to IrClass. Found '${typeOwner.javaClass}' instead. Can't implement SAM interface.", e)
return
}
val samMember = typeOwner.declarations.filterIsInstance<IrFunction>().find { it is IrOverridableMember && it.modality == Modality.ABSTRACT }
val samMember = typeOwner.declarations.findSubType<IrFunction> { it is IrOverridableMember && it.modality == Modality.ABSTRACT }
if (samMember == null) {
logger.errorElement("Couldn't find SAM member in type '${typeOwner.kotlinFqName.asString()}'. Can't implement SAM interface.", e)
return
@@ -4481,8 +4563,8 @@ open class KotlinFileExtractor(
val locId = tw.getLocation(e)
val helper = GeneratedClassHelper(locId, ids)
val currentDeclaration = declarationStack.peek()
val classId = extractGeneratedClass(ids, listOf(pluginContext.irBuiltIns.anyType, e.typeOperand), locId, currentDeclaration)
val declarationParent = declarationStack.peekAsDeclarationParent(e) ?: return
val classId = extractGeneratedClass(ids, listOf(pluginContext.irBuiltIns.anyType, e.typeOperand), locId, e, declarationParent)
// add field
val fieldId = tw.getFreshIdLabel<DbField>()
@@ -4624,7 +4706,8 @@ open class KotlinFileExtractor(
ids: GeneratedClassLabels,
superTypes: List<IrType>,
locId: Label<DbLocation>,
currentDeclaration: IrDeclaration
elementToReportOn: IrElement,
declarationParent: IrDeclarationParent
): Label<out DbClass> {
// Write class
val id = ids.type.javaResult.id.cast<DbClass>()
@@ -4647,23 +4730,27 @@ open class KotlinFileExtractor(
// Super call
val baseClass = superTypes.first().classOrNull
if (baseClass == null) {
logger.warnElement("Cannot find base class", currentDeclaration)
logger.warnElement("Cannot find base class", elementToReportOn)
} else {
val superCallId = tw.getFreshIdLabel<DbSuperconstructorinvocationstmt>()
tw.writeStmts_superconstructorinvocationstmt(superCallId, constructorBlockId, 0, ids.constructor)
val baseConstructor = baseClass.owner.declarations.findSubType<IrFunction> { it.symbol is IrConstructorSymbol }
if (baseConstructor == null) {
logger.warnElement("Cannot find base constructor", elementToReportOn)
} else {
val superCallId = tw.getFreshIdLabel<DbSuperconstructorinvocationstmt>()
tw.writeStmts_superconstructorinvocationstmt(superCallId, constructorBlockId, 0, ids.constructor)
val baseConstructor = baseClass.owner.declarations.find { it is IrFunction && it.symbol is IrConstructorSymbol }
val baseConstructorId = useFunction<DbConstructor>(baseConstructor as IrFunction)
val baseConstructorId = useFunction<DbConstructor>(baseConstructor)
tw.writeHasLocation(superCallId, locId)
tw.writeCallableBinding(superCallId.cast<DbCaller>(), baseConstructorId)
tw.writeHasLocation(superCallId, locId)
tw.writeCallableBinding(superCallId.cast<DbCaller>(), baseConstructorId)
}
}
addModifiers(id, "final")
addVisibilityModifierToLocalOrAnonymousClass(id)
extractClassSupertypes(superTypes, listOf(), id, inReceiverContext = true)
extractEnclosingClass(currentDeclaration, id, locId, listOf())
extractEnclosingClass(declarationParent, id, null, locId, listOf())
return id
}
@@ -4675,7 +4762,7 @@ open class KotlinFileExtractor(
with("generated class", localFunction) {
val ids = getLocallyVisibleFunctionLabels(localFunction)
val id = extractGeneratedClass(ids, superTypes, tw.getLocation(localFunction), localFunction)
val id = extractGeneratedClass(ids, superTypes, tw.getLocation(localFunction), localFunction, localFunction.parent)
// Extract local function as a member
extractFunction(localFunction, id, extractBody = true, extractMethodAndParameterTypeAccesses = true, null, listOf())
@@ -4684,6 +4771,34 @@ open class KotlinFileExtractor(
}
}
// todo: calculating the enclosing ref type could be done through this, instead of walking up the declaration parent chain
private val declarationStack = DeclarationStack()
private inner class DeclarationStack {
private val stack: Stack<IrDeclaration> = Stack()
fun push(item: IrDeclaration) = stack.push(item)
fun pop() = stack.pop()
fun isEmpty() = stack.isEmpty()
fun peek() = stack.peek()
fun peekAsDeclarationParent(elementToReportOn: IrElement): IrDeclarationParent? {
val trapWriter = tw
if (isEmpty() && trapWriter is SourceFileTrapWriter) {
// If the current declaration is used as a parent, we might end up with an empty stack. In this case, the source file is the parent.
return trapWriter.irFile
}
val dp = peek() as? IrDeclarationParent
if (dp == null) {
logger.errorElement("Couldn't find current declaration parent", elementToReportOn)
}
return dp
}
}
private inner class DeclarationStackAdjuster(declaration: IrDeclaration): Closeable {
init {

View File

@@ -220,7 +220,7 @@ open class KotlinUsesExtractor(
val extractedTypeArgs = when {
extractClass.symbol.isKFunction() && typeArgs != null && typeArgs.isNotEmpty() -> listOf(typeArgs.last())
extractClass.fqNameWhenAvailable == FqName("kotlin.jvm.functions.FunctionN") && typeArgs != null && typeArgs.isNotEmpty() -> listOf(typeArgs.last())
typeArgs != null && isUnspecialised(c, typeArgs) -> listOf()
typeArgs != null && isUnspecialised(c, typeArgs, logger) -> listOf()
else -> typeArgs
}
@@ -326,11 +326,11 @@ open class KotlinUsesExtractor(
if (replacementClass === parentClass)
return f
return globalExtensionState.syntheticToRealFunctionMap.getOrPut(f) {
val result = replacementClass.declarations.find { replacementDecl ->
replacementDecl is IrSimpleFunction && replacementDecl.name == f.name && replacementDecl.valueParameters.size == f.valueParameters.size && replacementDecl.valueParameters.zip(f.valueParameters).all {
val result = replacementClass.declarations.findSubType<IrSimpleFunction> { replacementDecl ->
replacementDecl.name == f.name && replacementDecl.valueParameters.size == f.valueParameters.size && replacementDecl.valueParameters.zip(f.valueParameters).all {
erase(it.first.type) == erase(it.second.type)
}
} as IrFunction?
}
if (result == null) {
logger.warn("Failed to replace synthetic class function ${f.name}")
} else {
@@ -351,9 +351,9 @@ open class KotlinUsesExtractor(
if (replacementClass === parentClass)
return f
return globalExtensionState.syntheticToRealFieldMap.getOrPut(f) {
val result = replacementClass.declarations.find { replacementDecl ->
replacementDecl is IrField && replacementDecl.name == f.name
} as IrField?
val result = replacementClass.declarations.findSubType<IrField> { replacementDecl ->
replacementDecl.name == f.name
}
if (result == null) {
logger.warn("Failed to replace synthetic class field ${f.name}")
} else {
@@ -479,7 +479,7 @@ open class KotlinUsesExtractor(
fun useSimpleTypeClass(c: IrClass, args: List<IrTypeArgument>?, hasQuestionMark: Boolean): TypeResults {
if (c.isAnonymousObject) {
args?.let {
if (it.isNotEmpty() && !isUnspecialised(c, it)) {
if (it.isNotEmpty() && !isUnspecialised(c, it, logger)) {
logger.error("Unexpected specialised instance of generic anonymous class")
}
}
@@ -539,15 +539,52 @@ open class KotlinUsesExtractor(
)
}
private fun useArrayType(arrayType: IrSimpleType, componentType: IrType, elementType: IrType, dimensions: Int, isPrimitiveArray: Boolean): TypeResults {
data class ArrayInfo(val elementTypeResults: TypeResults,
val componentTypeResults: TypeResults,
val dimensions: Int)
// Ensure we extract Array<Int> as Integer[], not int[], for example:
fun nullableIfNotPrimitive(type: IrType) = if (type.isPrimitiveType() && !isPrimitiveArray) type.makeNullable() else type
/**
* `t` is somewhere in a stack of array types, or possibly the
* element type of the innermost array. For example, in
* `Array<Array<Int>>`, we will be called with `t` being
* `Array<Array<Int>>`, then `Array<Int>`, then `Int`.
* `isPrimitiveArray` is true if we are immediately nested
* inside a primitive array.
*/
private fun useArrayType(t: IrType, isPrimitiveArray: Boolean): ArrayInfo {
val componentTypeResults = useType(nullableIfNotPrimitive(componentType))
val elementTypeLabel = useType(nullableIfNotPrimitive(elementType)).javaResult.id
if (!t.isBoxedArray && !t.isPrimitiveArray()) {
val nullableT = if (t.isPrimitiveType() && !isPrimitiveArray) t.makeNullable() else t
val typeResults = useType(nullableT)
return ArrayInfo(typeResults, typeResults, 0)
}
val javaShortName = componentTypeResults.javaResult.shortName + "[]"
if (t !is IrSimpleType) {
logger.error("Unexpected non-simple array type: ${t.javaClass}")
return ArrayInfo(extractErrorType(), extractErrorType(), 0)
}
val arrayClass = t.classifier.owner
if (arrayClass !is IrClass) {
logger.error("Unexpected owner type for array type: ${arrayClass.javaClass}")
return ArrayInfo(extractErrorType(), extractErrorType(), 0)
}
// Because Java's arrays are covariant, Kotlin will render
// Array<in X> as Object[], Array<Array<in X>> as Object[][] etc.
val elementType = if ((t.arguments.singleOrNull() as? IrTypeProjection)?.variance == Variance.IN_VARIANCE) {
pluginContext.irBuiltIns.anyType
} else {
t.getArrayElementType(pluginContext.irBuiltIns)
}
val recInfo = useArrayType(elementType, t.isPrimitiveArray())
val javaShortName = recInfo.componentTypeResults.javaResult.shortName + "[]"
val kotlinShortName = recInfo.componentTypeResults.kotlinResult.shortName + "[]"
val elementTypeLabel = recInfo.elementTypeResults.javaResult.id
val componentTypeLabel = recInfo.componentTypeResults.javaResult.id
val dimensions = recInfo.dimensions + 1
val id = tw.getLabelFor<DbArray>("@\"array;$dimensions;{${elementTypeLabel}}\"") {
tw.writeArrays(
@@ -555,9 +592,9 @@ open class KotlinUsesExtractor(
javaShortName,
elementTypeLabel,
dimensions,
componentTypeResults.javaResult.id)
componentTypeLabel)
extractClassSupertypes(arrayType.classifier.owner as IrClass, it, ExtractSupertypesMode.Specialised(arrayType.arguments))
extractClassSupertypes(arrayClass, it, ExtractSupertypesMode.Specialised(t.arguments))
// array.length
val length = tw.getLabelFor<DbField>("@\"field;{$it};length\"")
@@ -568,7 +605,7 @@ open class KotlinUsesExtractor(
// Note we will only emit one `clone()` method per Java array type, so we choose `Array<C?>` as its Kotlin
// return type, where C is the component type with any nested arrays themselves invariant and nullable.
val kotlinCloneReturnType = getInvariantNullableArrayType(arrayType).makeNullable()
val kotlinCloneReturnType = getInvariantNullableArrayType(t).makeNullable()
val kotlinCloneReturnTypeLabel = useType(kotlinCloneReturnType).kotlinResult.id
val clone = tw.getLabelFor<DbMethod>("@\"callable;{$it}.clone(){$it}\"")
@@ -579,11 +616,15 @@ open class KotlinUsesExtractor(
val javaResult = TypeResult(
id,
componentTypeResults.javaResult.signature + "[]",
recInfo.componentTypeResults.javaResult.signature + "[]",
javaShortName)
val kotlinResult = TypeResult(
fakeKotlinType(),
recInfo.componentTypeResults.kotlinResult.signature + "[]",
kotlinShortName)
val typeResults = TypeResults(javaResult, kotlinResult)
val arrayClassResult = useSimpleTypeClass(arrayType.classifier.owner as IrClass, arrayType.arguments, arrayType.hasQuestionMark)
return TypeResults(javaResult, arrayClassResult.kotlinResult)
return ArrayInfo(recInfo.elementTypeResults, typeResults, dimensions)
}
enum class TypeContext {
@@ -609,7 +650,7 @@ open class KotlinUsesExtractor(
otherIsPrimitive: Boolean,
javaClass: IrClass,
kotlinPackageName: String, kotlinClassName: String): TypeResults {
val javaResult = if ((context == TypeContext.RETURN || (context == TypeContext.OTHER && otherIsPrimitive)) && !s.hasQuestionMark && primitiveName != null) {
val javaResult = if ((context == TypeContext.RETURN || (context == TypeContext.OTHER && otherIsPrimitive)) && !s.isNullable() && primitiveName != null) {
val label: Label<DbPrimitive> = tw.getLabelFor("@\"type;$primitiveName\"", {
tw.writePrimitives(it, primitiveName)
})
@@ -619,7 +660,7 @@ open class KotlinUsesExtractor(
}
val kotlinClassId = useClassInstance(kotlinClass, listOf()).typeResult.id
val kotlinResult = if (true) TypeResult(fakeKotlinType(), "TODO", "TODO") else
if (s.hasQuestionMark) {
if (s.isNullable()) {
val kotlinSignature = "$kotlinPackageName.$kotlinClassName?" // TODO: Is this right?
val kotlinLabel = "@\"kt_type;nullable;$kotlinPackageName.$kotlinClassName\""
val kotlinId: Label<DbKt_nullable_type> = tw.getLabelFor(kotlinLabel, {
@@ -637,66 +678,39 @@ open class KotlinUsesExtractor(
return TypeResults(javaResult, kotlinResult)
}
val owner = s.classifier.owner
val primitiveInfo = primitiveTypeMapping.getPrimitiveInfo(s)
when {
primitiveInfo != null -> return primitiveType(
s.classifier.owner as IrClass,
primitiveInfo.primitiveName, primitiveInfo.otherIsPrimitive,
primitiveInfo.javaClass,
primitiveInfo.kotlinPackageName, primitiveInfo.kotlinClassName
)
primitiveInfo != null -> {
if (owner is IrClass) {
return primitiveType(
owner,
primitiveInfo.primitiveName, primitiveInfo.otherIsPrimitive,
primitiveInfo.javaClass,
primitiveInfo.kotlinPackageName, primitiveInfo.kotlinClassName
)
} else {
logger.error("Got primitive info for non-class (${owner.javaClass}) for ${s.render()}")
return extractErrorType()
}
}
(s.isBoxedArray && s.arguments.isNotEmpty()) || s.isPrimitiveArray() -> {
fun replaceComponentTypeWithAny(t: IrSimpleType, dimensions: Int): IrSimpleType =
if (dimensions == 0)
pluginContext.irBuiltIns.anyType as IrSimpleType
else
t.toBuilder().also { it.arguments = (it.arguments[0] as IrTypeProjection)
.let { oldArg ->
listOf(makeTypeProjection(replaceComponentTypeWithAny(oldArg.type as IrSimpleType, dimensions - 1), oldArg.variance))
}
}.buildSimpleType()
var componentType = s.getArrayElementType(pluginContext.irBuiltIns)
var isPrimitiveArray = false
var dimensions = 0
var elementType: IrType = s
while (elementType.isBoxedArray || elementType.isPrimitiveArray()) {
dimensions++
if (elementType.isPrimitiveArray())
isPrimitiveArray = true
if (((elementType as IrSimpleType).arguments.singleOrNull() as? IrTypeProjection)?.variance == Variance.IN_VARIANCE) {
// Because Java's arrays are covariant, Kotlin will render Array<in X> as Object[], Array<Array<in X>> as Object[][] etc.
componentType = replaceComponentTypeWithAny(s, dimensions - 1)
elementType = pluginContext.irBuiltIns.anyType as IrSimpleType
break
}
elementType = elementType.getArrayElementType(pluginContext.irBuiltIns)
}
return useArrayType(
s,
componentType,
elementType,
dimensions,
isPrimitiveArray
)
val arrayInfo = useArrayType(s, false)
return arrayInfo.componentTypeResults
}
s.classifier.owner is IrClass -> {
val classifier: IrClassifierSymbol = s.classifier
val cls: IrClass = classifier.owner as IrClass
owner is IrClass -> {
val args = if (s.isRawType()) null else s.arguments
return useSimpleTypeClass(cls, args, s.hasQuestionMark)
return useSimpleTypeClass(owner, args, s.isNullable())
}
s.classifier.owner is IrTypeParameter -> {
val javaResult = useTypeParameter(s.classifier.owner as IrTypeParameter)
owner is IrTypeParameter -> {
val javaResult = useTypeParameter(owner)
val aClassId = makeClass("kotlin", "TypeParam") // TODO: Wrong
val kotlinResult = if (true) TypeResult(fakeKotlinType(), "TODO", "TODO") else
if (s.hasQuestionMark) {
if (s.isNullable()) {
val kotlinSignature = "${javaResult.signature}?" // TODO: Wrong
val kotlinLabel = "@\"kt_type;nullable;type_param\"" // TODO: Wrong
val kotlinId: Label<DbKt_nullable_type> = tw.getLabelFor(kotlinLabel, {
@@ -905,10 +919,17 @@ open class KotlinUsesExtractor(
}
private fun extendsAdditionAllowed(t: IrType) =
if (t.isBoxedArray)
arrayExtendsAdditionAllowed(t as IrSimpleType)
else
if (t.isBoxedArray) {
if (t is IrSimpleType) {
arrayExtendsAdditionAllowed(t)
} else {
logger.warn("Boxed array of unexpected kind ${t.javaClass}")
// Return false, for no particular reason
false
}
} else {
((t as? IrSimpleType)?.classOrNull?.owner?.isFinalClass) != true
}
private fun wildcardAdditionAllowed(v: Variance, t: IrType, addByDefault: Boolean) =
when {
@@ -1097,7 +1118,7 @@ open class KotlinUsesExtractor(
return f.returnType
}
val otherKeySet = parentClass.declarations.filterIsInstance<IrFunction>().find { it.name.asString() == "keySet" && it.valueParameters.size == 1 }
val otherKeySet = parentClass.declarations.findSubType<IrFunction> { it.name.asString() == "keySet" && it.valueParameters.size == 1 }
?: return f.returnType
return otherKeySet.returnType.codeQlWithHasQuestionMark(false)
@@ -1117,10 +1138,6 @@ open class KotlinUsesExtractor(
// Note not using `parentsWithSelf` as that only works if `d` is an IrDeclarationParent
d.parents.any { (it as? IrAnnotationContainer)?.hasAnnotation(jvmWildcardSuppressionAnnotaton) == true }
protected fun IrFunction.isLocalFunction(): Boolean {
return this.visibility == DescriptorVisibilities.LOCAL
}
/**
* Class to hold labels for generated classes around local functions, lambdas, function references, and property references.
*/
@@ -1162,6 +1179,14 @@ open class KotlinUsesExtractor(
return res
}
fun getExistingLocallyVisibleFunctionLabel(f: IrFunction): Label<DbMethod>? {
if (!f.isLocalFunction()){
return null
}
return tw.lm.locallyVisibleFunctionLabelMapping[f]?.function
}
// These are classes with Java equivalents, but whose methods don't all exist on those Java equivalents--
// for example, the numeric classes define arithmetic functions (Int.plus, Long.or and so on) that lower to
// primitive arithmetic on the JVM, but which we extract as calls to reflect the source syntax more closely.
@@ -1169,17 +1194,17 @@ open class KotlinUsesExtractor(
"kotlin.Boolean", "kotlin.Byte", "kotlin.Char", "kotlin.Double", "kotlin.Float", "kotlin.Int", "kotlin.Long", "kotlin.Number", "kotlin.Short"
)
private fun kotlinFunctionToJavaEquivalent(f: IrFunction, noReplace: Boolean) =
private fun kotlinFunctionToJavaEquivalent(f: IrFunction, noReplace: Boolean): IrFunction =
if (noReplace)
f
else
f.parentClassOrNull?.let { parentClass ->
getJavaEquivalentClass(parentClass)?.let { javaClass ->
if (javaClass != parentClass)
if (javaClass != parentClass) {
val jvmName = getJvmName(f) ?: f.name.asString()
// Look for an exact type match...
javaClass.declarations.find { decl ->
decl is IrFunction &&
decl.name == f.name &&
javaClass.declarations.findSubType<IrFunction> { decl ->
decl.name.asString() == jvmName &&
decl.valueParameters.size == f.valueParameters.size &&
// Note matching by classifier not the whole type so that generic arguments are allowed to differ,
// as they always will for method type parameters occurring in parameter types (e.g. <T> toArray(T[] array)
@@ -1187,23 +1212,20 @@ open class KotlinUsesExtractor(
decl.valueParameters.zip(f.valueParameters).all { p -> p.first.type.classifierOrNull == p.second.type.classifierOrNull }
} ?:
// Or if there is none, look for the only viable overload
javaClass.declarations.singleOrNull { decl ->
decl is IrFunction &&
decl.name == f.name &&
javaClass.declarations.singleOrNullSubType<IrFunction> { decl ->
decl.name.asString() == jvmName &&
decl.valueParameters.size == f.valueParameters.size
} ?:
// Or check property accessors:
if (f.isAccessor) {
val prop = javaClass.declarations.filterIsInstance<IrProperty>().find { decl ->
decl.name == (f.propertyIfAccessor as IrProperty).name
(f.propertyIfAccessor as? IrProperty)?.let { kotlinProp ->
val javaProp = javaClass.declarations.findSubType<IrProperty> { decl ->
decl.name == kotlinProp.name
}
if (prop?.getter?.name == f.name)
prop.getter
else if (prop?.setter?.name == f.name)
prop.setter
if (javaProp?.getter?.name == f.name)
javaProp.getter
else if (javaProp?.setter?.name == f.name)
javaProp.setter
else null
} else {
null
} ?: run {
val parentFqName = parentClass.fqNameWhenAvailable?.asString()
if (!expectedMissingEquivalents.contains(parentFqName)) {
@@ -1211,10 +1233,11 @@ open class KotlinUsesExtractor(
}
null
}
}
else
null
}
} as IrFunction? ?: f
} ?: f
fun <T: DbCallable> useFunction(f: IrFunction, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>? = null, noReplace: Boolean = false): Label<out T> {
return useFunction(f, null, classTypeArgsIncludingOuterClasses, noReplace)
@@ -1416,12 +1439,11 @@ open class KotlinUsesExtractor(
for(t in subbedSupertypes) {
when(t) {
is IrSimpleType -> {
when (t.classifier.owner) {
val owner = t.classifier.owner
when (owner) {
is IrClass -> {
val classifier: IrClassifierSymbol = t.classifier
val tcls: IrClass = classifier.owner as IrClass
val typeArgs = if (t.arguments.isNotEmpty() && mode is ExtractSupertypesMode.Raw) null else t.arguments
val l = useClassInstance(tcls, typeArgs, inReceiverContext).typeResult.id
val l = useClassInstance(owner, typeArgs, inReceiverContext).typeResult.id
tw.writeExtendsReftype(id, l)
}
else -> {
@@ -1459,13 +1481,13 @@ open class KotlinUsesExtractor(
return eraseTypeParameter(owner)
}
if (t.isArray() || t.isNullableArray()) {
val elementType = t.getArrayElementType(pluginContext.irBuiltIns)
val erasedElementType = erase(elementType)
return (classifier as IrClassSymbol).typeWith(erasedElementType).codeQlWithHasQuestionMark(t.hasQuestionMark)
}
if (owner is IrClass) {
if (t.isArray() || t.isNullableArray()) {
val elementType = t.getArrayElementType(pluginContext.irBuiltIns)
val erasedElementType = erase(elementType)
return owner.typeWith(erasedElementType).codeQlWithHasQuestionMark(t.isNullable())
}
return if (t.arguments.isNotEmpty())
t.addAnnotations(listOf(RawTypeAnnotation.annotationConstructor))
else

View File

@@ -6,8 +6,8 @@ import java.io.StringWriter
/**
* This represents a label (`#...`) in a TRAP file.
*/
interface Label<T> {
fun <U> cast(): Label<U> {
interface Label<T: AnyDbType> {
fun <U: AnyDbType> cast(): Label<U> {
@Suppress("UNCHECKED_CAST")
return this as Label<U>
}
@@ -17,7 +17,7 @@ interface Label<T> {
* The label `#i`, e.g. `#123`. Most labels we generate are of this
* form.
*/
class IntLabel<T>(val i: Int): Label<T> {
class IntLabel<T: AnyDbType>(val i: Int): Label<T> {
override fun toString(): String = "#$i"
}
@@ -26,6 +26,6 @@ class IntLabel<T>(val i: Int): Label<T> {
* shared between different components (e.g. when both the interceptor
* and the extractor need to refer to the same label).
*/
class StringLabel<T>(val name: String): Label<T> {
class StringLabel<T: AnyDbType>(val name: String): Label<T> {
override fun toString(): String = "#$name"
}

View File

@@ -26,7 +26,7 @@ class TrapLabelManager {
private var nextInt: Int = 100
/** Returns a fresh label. */
fun <T> getFreshLabel(): Label<T> {
fun <T: AnyDbType> getFreshLabel(): Label<T> {
return IntLabel(nextInt++)
}
@@ -64,7 +64,7 @@ open class TrapWriter (protected val loggerBase: LoggerBase, val lm: TrapLabelMa
* `getLabelFor` instead, which allows non-existent labels to be
* initialised.
*/
fun <T> getExistingLabelFor(key: String): Label<T>? {
fun <T: AnyDbType> getExistingLabelFor(key: String): Label<T>? {
return lm.labelMapping.get(key)?.cast<T>()
}
/**
@@ -73,7 +73,7 @@ open class TrapWriter (protected val loggerBase: LoggerBase, val lm: TrapLabelMa
* is run on it, and it is returned.
*/
@JvmOverloads // Needed so Java can call a method with an optional argument
fun <T> getLabelFor(key: String, initialise: (Label<T>) -> Unit = {}): Label<T> {
fun <T: AnyDbType> getLabelFor(key: String, initialise: (Label<T>) -> Unit = {}): Label<T> {
val maybeLabel: Label<T>? = getExistingLabelFor(key)
if(maybeLabel == null) {
val label: Label<T> = lm.getFreshLabel()
@@ -89,7 +89,7 @@ open class TrapWriter (protected val loggerBase: LoggerBase, val lm: TrapLabelMa
/**
* Returns a label for a fresh ID (i.e. a new label bound to `*`).
*/
fun <T> getFreshIdLabel(): Label<T> {
fun <T: AnyDbType> getFreshIdLabel(): Label<T> {
val label: Label<T> = lm.getFreshLabel()
writeTrap("$label = *\n")
return label
@@ -319,7 +319,7 @@ class SourceFileTrapWriter (
lm: TrapLabelManager,
bw: BufferedWriter,
diagnosticTrapWriter: TrapWriter?,
irFile: IrFile,
val irFile: IrFile,
populateFileTables: Boolean) :
FileTrapWriter(loggerBase, lm, bw, diagnosticTrapWriter, irFile.path, populateFileTables) {

View File

@@ -2,11 +2,15 @@ package com.github.codeql.comments
import com.github.codeql.*
import com.github.codeql.utils.IrVisitorLookup
import com.github.codeql.utils.isLocalFunction
import com.github.codeql.utils.versions.Psi2Ir
import com.intellij.psi.PsiComment
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.util.parentClassOrNull
import org.jetbrains.kotlin.kdoc.psi.api.KDoc
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtVisitor
@@ -89,38 +93,88 @@ class CommentExtractor(private val fileExtractor: KotlinFileExtractor, private v
file.accept(IrVisitorLookup(psi2Ir, ownerPsi, file), owners)
for (ownerIr in owners) {
val ownerLabel =
if (ownerIr == file)
fileLabel
else {
if (ownerIr is IrValueParameter && ownerIr.index == -1) {
// Don't attribute comments to the implicit `this` parameter of a function.
continue
}
val label: String
val existingLabel = if (ownerIr is IrVariable) {
label = "variable ${ownerIr.name.asString()}"
tw.getExistingVariableLabelFor(ownerIr)
} else {
label = fileExtractor.getLabel(ownerIr) ?: continue
tw.getExistingLabelFor<DbTop>(label)
}
if (existingLabel == null) {
logger.warn("Couldn't get existing label for $label")
continue
}
existingLabel
}
tw.writeKtCommentOwners(commentLabel, ownerLabel)
val ownerLabel = getLabel(ownerIr)
if (ownerLabel != null) {
tw.writeKtCommentOwners(commentLabel, ownerLabel)
}
}
}
private fun getKDocOwner(comment: KDoc) : PsiElement? {
val owner = comment.owner
if (owner == null) {
logger.warn("Couldn't get owner of KDoc.")
logger.warn("Couldn't get owner of KDoc. The comment is extracted without an owner.")
}
return owner
}
private fun getLabel(element: IrElement): Label<out DbTop>? {
if (element == file)
return fileLabel
if (element is IrValueParameter && element.index == -1) {
// Don't attribute comments to the implicit `this` parameter of a function.
return null
}
val label: String
val existingLabel = if (element is IrVariable) {
// local variables are not named globally, so we need to get them from the variable label cache
label = "variable ${element.name.asString()}"
tw.getExistingVariableLabelFor(element)
} else if (element is IrFunction && element.isLocalFunction()) {
// local functions are not named globally, so we need to get them from the local function label cache
label = "local function ${element.name.asString()}"
fileExtractor.getExistingLocallyVisibleFunctionLabel(element)
}
else {
label = getLabelForNamedElement(element) ?: return null
tw.getExistingLabelFor<DbTop>(label)
}
if (existingLabel == null) {
logger.warn("Couldn't get existing label for $label")
return null
}
return existingLabel
}
private fun getLabelForNamedElement(element: IrElement) : String? {
when (element) {
is IrClass -> return fileExtractor.getClassLabel(element, listOf()).classLabel
is IrTypeParameter -> return fileExtractor.getTypeParameterLabel(element)
is IrFunction -> {
return if (element.isLocalFunction()) {
null
} else {
fileExtractor.getFunctionLabel(element, null)
}
}
is IrValueParameter -> return fileExtractor.getValueParameterLabel(element, null)
is IrProperty -> return fileExtractor.getPropertyLabel(element)
is IrField -> return fileExtractor.getFieldLabel(element)
is IrEnumEntry -> return fileExtractor.getEnumEntryLabel(element)
is IrTypeAlias -> return fileExtractor.getTypeAliasLabel(element)
is IrAnonymousInitializer -> {
val parentClass = element.parentClassOrNull
if (parentClass == null) {
logger.warnElement("Parent of anonymous initializer is not a class", element)
return null
}
// Assign the comment to the class. The content of the `init` blocks might be extracted in multiple constructors.
return getLabelForNamedElement(parentClass)
}
// Fresh entities, not named elements:
is IrBody -> return null
is IrExpression -> return null
// todo add others:
else -> {
logger.warnElement("Unhandled element type found during comment extraction: ${element::class}", element)
return null
}
}
}
}
}

View File

@@ -0,0 +1,8 @@
package com.github.codeql.utils
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.declarations.IrFunction
fun IrFunction.isLocalFunction(): Boolean {
return this.visibility == DescriptorVisibilities.LOCAL
}

View File

@@ -0,0 +1,26 @@
package com.github.codeql
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
/**
* This behaves the same as Iterable<IrDeclaration>.find, but requires
* that the value found is of the subtype S, and it casts
* the result for you appropriately.
*/
inline fun <reified S: IrDeclaration> Iterable<IrDeclaration>.findSubType(
predicate: (S) -> Boolean
): S? {
return this.find { it is S && predicate(it) } as S?
}
/**
* This behaves the same as Iterable<IrDeclaration>.singleOrNull, but
* requires that the value found is of the subtype S, and it casts
* the result for you appropriately.
*/
inline fun <reified S: IrDeclaration> Iterable<IrDeclaration>.singleOrNullSubType(
predicate: (S) -> Boolean
): S? {
return this.singleOrNull { it is S && predicate(it) } as S?
}

View File

@@ -12,10 +12,10 @@ package com.github.codeql
* `shortName` is a Java primitive name (e.g. "int"), a class short name with Java-style type arguments ("InnerClass<E>" or
* "OuterClass<ConcreteArgument>" or "OtherClass<? extends Bound>") or an array ("componentShortName[]").
*/
data class TypeResultGeneric<SignatureType,out LabelType>(val id: Label<out LabelType>, val signature: SignatureType, val shortName: String) {
fun <U> cast(): TypeResult<U> {
data class TypeResultGeneric<SignatureType,out LabelType: AnyDbType>(val id: Label<out LabelType>, val signature: SignatureType, val shortName: String) {
fun <U: AnyDbType> cast(): TypeResultGeneric<SignatureType,U> {
@Suppress("UNCHECKED_CAST")
return this as TypeResult<U>
return this as TypeResultGeneric<SignatureType,U>
}
}
data class TypeResultsGeneric<SignatureType>(val javaResult: TypeResultGeneric<SignatureType,DbType>, val kotlinResult: TypeResultGeneric<SignatureType,DbKt_type>)
@@ -25,6 +25,6 @@ typealias TypeResultWithoutSignature<T> = TypeResultGeneric<Unit,T>
typealias TypeResults = TypeResultsGeneric<String>
typealias TypeResultsWithoutSignatures = TypeResultsGeneric<Unit>
fun <T> TypeResult<T>.forgetSignature(): TypeResultWithoutSignature<T> {
fun <T: AnyDbType> TypeResult<T>.forgetSignature(): TypeResultWithoutSignature<T> {
return TypeResultWithoutSignature(this.id, Unit, this.shortName)
}

View File

@@ -1,6 +1,7 @@
package com.github.codeql.utils
import com.github.codeql.KotlinUsesExtractor
import com.github.codeql.Logger
import com.github.codeql.getJavaEquivalentClassId
import com.github.codeql.utils.versions.codeQlWithHasQuestionMark
import com.github.codeql.utils.versions.createImplicitParameterDeclarationWithWrappedDescriptor
@@ -25,6 +26,7 @@ import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.classId
import org.jetbrains.kotlin.ir.util.constructedClassType
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.kotlinFqName
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance
@@ -54,7 +56,7 @@ private fun IrSimpleType.substituteTypeArguments(substitutionMap: Map<IrTypePara
return IrSimpleTypeImpl(
classifier,
hasQuestionMark,
isNullable(),
newArguments,
annotations
)
@@ -90,7 +92,7 @@ private fun subProjectedType(substitutionMap: Map<IrTypeParameterSymbol, IrTypeA
if (conflictingVariance(outerVariance, substitutedTypeArg.variance))
IrStarProjectionImpl
else {
val newProjectedType = substitutedTypeArg.type.let { if (t.hasQuestionMark) it.codeQlWithHasQuestionMark(true) else it }
val newProjectedType = substitutedTypeArg.type.let { if (t.isNullable()) it.codeQlWithHasQuestionMark(true) else it }
val newVariance = combineVariance(outerVariance, substitutedTypeArg.variance)
makeTypeProjection(newProjectedType, newVariance)
}
@@ -123,14 +125,17 @@ private fun IrTypeArgument.lowerBound(context: IrPluginContext) =
fun IrType.substituteTypeAndArguments(substitutionMap: Map<IrTypeParameterSymbol, IrTypeArgument>?, useContext: KotlinUsesExtractor.TypeContext, pluginContext: IrPluginContext): IrType =
substitutionMap?.let { substMap ->
this.classifierOrNull?.let { typeClassifier ->
if (this is IrSimpleType) {
val typeClassifier = this.classifier
substMap[typeClassifier]?.let {
when(useContext) {
KotlinUsesExtractor.TypeContext.RETURN -> it.upperBound(pluginContext)
else -> it.lowerBound(pluginContext)
}
} ?: (this as IrSimpleType).substituteTypeArguments(substMap)
} ?: this
} ?: this.substituteTypeArguments(substMap)
} else {
this
}
} ?: this
object RawTypeAnnotation {
@@ -191,7 +196,7 @@ fun IrTypeArgument.withQuestionMark(b: Boolean): IrTypeArgument =
is IrStarProjection -> this
is IrTypeProjection ->
this.type.let { when(it) {
is IrSimpleType -> if (it.hasQuestionMark == b) this else makeTypeProjection(it.codeQlWithHasQuestionMark(b), this.variance)
is IrSimpleType -> if (it.isNullable() == b) this else makeTypeProjection(it.codeQlWithHasQuestionMark(b), this.variance)
else -> this
}}
else -> this
@@ -212,27 +217,34 @@ private fun matchingTypeParameters(l: IrTypeParameter?, r: IrTypeParameter): Boo
}
// Returns true if type is C<T1, T2, ...> where C is declared `class C<T1, T2, ...> { ... }`
fun isUnspecialised(paramsContainer: IrTypeParametersContainer, args: List<IrTypeArgument>): Boolean {
fun isUnspecialised(paramsContainer: IrTypeParametersContainer, args: List<IrTypeArgument>, logger: Logger): Boolean {
return isUnspecialised(paramsContainer, args, logger, paramsContainer)
}
private fun isUnspecialised(paramsContainer: IrTypeParametersContainer, args: List<IrTypeArgument>, logger: Logger, origParamsContainer: IrTypeParametersContainer): Boolean {
val unspecialisedHere = paramsContainer.typeParameters.zip(args).all { paramAndArg ->
(paramAndArg.second as? IrTypeProjection)?.let {
// Type arg refers to the class' own type parameter?
it.variance == Variance.INVARIANT &&
matchingTypeParameters(it.type.classifierOrNull?.owner as? IrTypeParameter, paramAndArg.first)
matchingTypeParameters(it.type.classifierOrNull?.owner as? IrTypeParameter, paramAndArg.first)
} ?: false
}
val remainingArgs = args.drop(paramsContainer.typeParameters.size)
val parentClass = paramsContainer.parents.firstIsInstanceOrNull<IrClass>()
val parentTypeContainer = paramsContainer.parents.firstIsInstanceOrNull<IrTypeParametersContainer>()
val parentUnspecialised = when {
remainingArgs.isEmpty() -> true
parentClass == null -> false
else -> isUnspecialised(parentClass, remainingArgs)
parentTypeContainer == null -> {
logger.error("Found more type arguments than parameters: ${origParamsContainer.kotlinFqName.asString()}")
false
}
else -> isUnspecialised(parentTypeContainer, remainingArgs, logger, origParamsContainer)
}
return unspecialisedHere && parentUnspecialised
}
// Returns true if type is C<T1, T2, ...> where C is declared `class C<T1, T2, ...> { ... }`
fun isUnspecialised(type: IrSimpleType) = (type.classifier.owner as? IrClass)?.let {
isUnspecialised(it, type.arguments)
fun isUnspecialised(type: IrSimpleType, logger: Logger) = (type.classifier.owner as? IrClass)?.let {
isUnspecialised(it, type.arguments, logger)
} ?: false

View File

@@ -0,0 +1,25 @@
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Kotlin application project to get you started.
* For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
* User Manual available at https://docs.gradle.org/7.0.2/userguide/building_java_projects.html
*/
plugins {
// Apply the org.jetbrains.kotlin.jvm Plugin to add support for Kotlin.
id 'org.jetbrains.kotlin.jvm' version '1.7.0'
// Apply the application plugin to add support for building a CLI application in Java.
id 'application'
}
repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
}
application {
// Define the main class for the application.
mainClass = 'testProject.AppKt'
}

View File

@@ -0,0 +1,15 @@
/*
* This Kotlin source file was generated by the Gradle 'init' task.
*/
package testProject
class App {
val greeting: String
get() {
return "Hello World!"
}
}
fun main() {
// TODO: println(App().greeting)
}

View File

@@ -0,0 +1,15 @@
| 0 | -Xallow-no-source-files |
| 1 | -classpath |
| 2 | <PATH> |
| 3 | -d |
| 4 | app/build/classes/kotlin/main |
| 5 | -jdk-home |
| 6 | <PATH> |
| 7 | -module-name |
| 8 | app |
| 9 | -no-reflect |
| 10 | -no-stdlib |
| 11 | <PLUGINS> |
| 12 | app/src/main/kotlin/testProject/App.kt |
| 13 | -jvm-target |
| 14 | 1.8 |

View File

@@ -0,0 +1,15 @@
import java
private string getArgument(Compilation c, int i) {
exists(string arg | arg = c.getArgument(i) |
if exists(arg.indexOf("-Xplugin="))
then result = "<PLUGINS>"
else
if c.getArgument(i - 1) = ["-classpath", "-jdk-home"]
then result = "<PATH>"
else result = arg
)
}
from Compilation c, int i
select i, getArgument(c, i)

View File

@@ -0,0 +1,11 @@
/*
* This file was generated by the Gradle 'init' task.
*
* The settings file is used to specify which projects to include in your build.
*
* Detailed information about configuring a multi-project build in Gradle can be found
* in the user manual at https://docs.gradle.org/7.0.2/userguide/multi_project_builds.html
*/
rootProject.name = 'testProject'
include('app')

View File

@@ -0,0 +1,5 @@
from create_database_utils import *
run_codeql_database_create(
["gradle build --no-daemon --no-build-cache"], lang="java")
runSuccessfully(["gradle", "clean"])

View File

@@ -0,0 +1,25 @@
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Kotlin application project to get you started.
* For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
* User Manual available at https://docs.gradle.org/7.0.2/userguide/building_java_projects.html
*/
plugins {
// Apply the org.jetbrains.kotlin.jvm Plugin to add support for Kotlin.
id 'org.jetbrains.kotlin.jvm' version '1.6.20'
// Apply the application plugin to add support for building a CLI application in Java.
id 'application'
}
repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
}
application {
// Define the main class for the application.
mainClass = 'testProject.AppKt'
}

View File

@@ -0,0 +1,10 @@
import kotlin.reflect.*
fun fn() {
val ref: KFunction2<Ccc, Int, Double> = Ccc::m
ref.invoke(Ccc(), 1)
}
class Ccc {
fun m(i:Int):Double = 5.0
}

View File

@@ -0,0 +1,4 @@
import java
import semmle.code.java.Diagnostics
query predicate diag(Diagnostic d) { any() }

View File

@@ -0,0 +1,11 @@
/*
* This file was generated by the Gradle 'init' task.
*
* The settings file is used to specify which projects to include in your build.
*
* Detailed information about configuring a multi-project build in Gradle can be found
* in the user manual at https://docs.gradle.org/7.0.2/userguide/multi_project_builds.html
*/
rootProject.name = 'testProject'
include('app')

View File

@@ -0,0 +1,5 @@
from create_database_utils import *
run_codeql_database_create(
["gradle build --no-daemon --no-build-cache --rerun-tasks"], lang="java")
runSuccessfully(["gradle", "clean"])

View File

@@ -0,0 +1,7 @@
---
category: deprecated
---
* The predicate `Annotation.getAValue()` has been deprecated because it might lead to obtaining the value of the wrong annotation element by accident. `getValue(string)` (or one of the value type specific predicates) should be used to explicitly specify the name of the annotation element.
* The predicate `Annotation.getAValue(string)` has been renamed to `getAnArrayValue(string)`.
* The predicate `SuppressWarningsAnnotation.getASuppressedWarningLiteral()` has been deprecated because it unnecessarily restricts the result type; `getASuppressedWarning()` should be used instead.
* The predicates `TargetAnnotation.getATargetExpression()` and `RetentionAnnotation.getRetentionPolicyExpression()` have been deprecated because getting the enum constant read expression is rarely useful, instead the corresponding predicates for getting the name of the referenced enum constants should be used.

View File

@@ -0,0 +1,9 @@
---
category: feature
---
* The predicates of the CodeQL class `Annotation` have been improved:
* Convenience value type specific predicates have been added, such as `getEnumConstantValue(string)` or `getStringValue(string)`.
* Convenience predicates for elements with array values have been added, such as `getAnEnumConstantArrayValue(string)`. While the behavior of the existing predicates has not changed, usage of them should be reviewed (or replaced with the newly added predicate) to make sure they work correctly for elements with array values.
* Some internal CodeQL usage of the `Annotation` predicates has been adjusted and corrected; this might affect the results of some queries.
* New predicates have been added to the CodeQL class `Annotatable` to support getting declared and associated annotations. As part of that, `hasAnnotation()` has been changed to also consider inherited annotations, to be consistent with `hasAnnotation(string, string)` and `getAnAnnotation()`. The newly added predicate `hasDeclaredAnnotation()` can be used as replacement for the old functionality.
* New predicates have been added to the CodeQL class `AnnotationType` to simplify getting information about usage of JDK meta-annotations, such as `@Retention`.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Added a new predicate, `allowsBackup`, in the `AndroidApplicationXmlElement` class. This predicate detects if the application element does not disable the `android:allowBackup` attribute.

View File

@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* Added taint flow models for the `java.lang.String.(charAt|getBytes)` methods.
* Improved taint flow models for the `java.lang.String.(replace|replaceFirst|replaceAll)` methods. Additional results may be found where users do not properly sanitize their inputs.

View File

@@ -0,0 +1,10 @@
---
category: minorAnalysis
---
* Added new flow steps for the following Android classes:
* `android.content.ContentResolver`
* `android.content.ContentProviderClient`
* `android.content.ContentProviderOperation`
* `android.content.ContentProviderOperation$Builder`
* `android.content.ContentProviderResult`
* `android.database.Cursor`

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added flow summary for `org.springframework.data.repository.CrudRepository.save()`.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added flow sinks, sources and summaries for the Kotlin standard library.

View File

@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* Added new flow steps for `androidx.core.app.NotificationCompat` and its inner classes.

View File

@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* Added new sinks to the query `java/android/implict-pendingintents` to take into account the classes `androidx.core.app.NotificationManagerCompat` and `androidx.core.app.AlarmManagerCompat`.

View File

@@ -0,0 +1,4 @@
---
category: fix
---
* Fixed an issue in the taint tracking analysis where implicit reads were not allowed by default in sinks or additional taint steps that used flow states.

View File

@@ -0,0 +1,4 @@
---
category: breaking
---
* The `Member.getQualifiedName()` predicate result now includes the qualified name of the declaring type.

View File

@@ -0,0 +1,4 @@
---
category: majorAnalysis
---
* The virtual dispatch relation used in data flow now favors summary models over source code for dispatch to interface methods from `java.util` unless there is evidence that a specific source implementation is reachable. This should provide increased precision for any projects that include, for example, custom `List` or `Map` implementations.

View File

@@ -19,7 +19,7 @@
### Minor Analysis Improvements
* Added new flow steps for the classes `java.io.Path` and `java.nio.Paths`.
* Added new flow steps for the classes `java.nio.file.Path` and `java.nio.file.Paths`.
* The class `AndroidFragment` now also models the Android Jetpack version of the `Fragment` class (`androidx.fragment.app.Fragment`).
* Java 19 builds can now be extracted. There are no non-preview new language features in this release, so the only user-visible change is that the CodeQL extractor will now correctly trace compilations using the JDK 19 release of `javac`.
* Classes and methods that are seen with several different paths during the extraction process (for example, packaged into different JAR files) now report an arbitrarily selected location via their `getLocation` and `hasLocationInfo` predicates, rather than reporting all of them. This may lead to reduced alert duplication.

View File

@@ -216,7 +216,7 @@ private predicate fixedHasLocation(Top l, Location loc, File f) {
min(Location candidateLoc |
hasLocation(l, candidateLoc)
|
candidateLoc order by candidateLoc.getFile().toString()
candidateLoc order by candidateLoc.getFile().getAbsolutePath()
) and
not hasSourceLocation(l, _, _) and
locations_default(loc, f, _, _, _, _)

View File

@@ -44,12 +44,100 @@ class Annotation extends @annotation, Expr {
result = this.getType().getAnnotationElement(name)
}
/** Gets a value of an annotation element. */
Expr getAValue() { filteredAnnotValue(this, _, result) }
/**
* DEPRECATED: Getting the value of _any_ annotation element is error-prone because
* it could lead to selecting the value of the wrong element by accident (for example
* when an annotation type is extended in the future). Prefer the predicate `getValue(string)`
* and explicitly specify the element name. Use `getValue(_)` if it is really desired to
* get the value of any element.
*
* Gets a value of an annotation element. This includes default values in case
* no explicit value is specified. For elements with an array value type this
* might have an `ArrayInit` as result. To properly handle array values, prefer
* the predicate `getAnArrayValue`.
*/
deprecated Expr getAValue() { filteredAnnotValue(this, _, result) }
/** Gets the value of the annotation element with the specified `name`. */
/**
* Gets the value of the annotation element with the specified `name`.
* This includes default values in case no explicit value is specified.
* For elements with an array value type this might get an `ArrayInit` instance.
* To properly handle array values, prefer the predicate `getAnArrayValue`.
*/
Expr getValue(string name) { filteredAnnotValue(this, this.getAnnotationElement(name), result) }
/**
* Gets the value of the annotation element, if its type is not an array.
* This guarantees that for consistency even elements of type array with a
* single value have no result, to prevent accidental error-prone usage.
*/
private Expr getNonArrayValue(string name) {
result = this.getValue(name) and
not this.getAnnotationElement(name).getType() instanceof Array
}
/**
* If the value type of the annotation element with the specified `name` is an enum type,
* gets the enum constant used as value for that element. This includes default values in
* case no explicit value is specified.
*
* If the element value type is an enum type array, use `getAnEnumConstantArrayValue`.
*/
EnumConstant getEnumConstantValue(string name) {
result = this.getNonArrayValue(name).(FieldRead).getField()
}
/**
* If the value type of the annotation element with the specified `name` is `String`,
* gets the string value used for that element. This includes default values in case no
* explicit value is specified.
*
* If the element value type is a string array, use `getAStringArrayValue`.
*/
string getStringValue(string name) {
// Uses CompileTimeConstantExpr instead of StringLiteral because this can for example
// be a read from a final variable as well.
result = this.getNonArrayValue(name).(CompileTimeConstantExpr).getStringValue()
}
/**
* If the value type of the annotation element with the specified `name` is `int` or
* a smaller integral type or `char`, gets the int value used for that element.
* This includes default values in case no explicit value is specified.
*
* If the element value type is an `int` array or an array of a smaller integral
* type or `char`, use `getAnIntArrayValue`.
*/
int getIntValue(string name) {
// Uses CompileTimeConstantExpr instead of IntegerLiteral because this can for example
// be a read from a final variable as well.
result = this.getNonArrayValue(name).(CompileTimeConstantExpr).getIntValue() and
// Verify that type is integral; ignore floating point elements with IntegerLiteral as value
this.getAnnotationElement(name).getType().hasName(["byte", "short", "int", "char"])
}
/**
* If the value type of the annotation element with the specified `name` is `boolean`,
* gets the boolean value used for that element. This includes default values in case
* no explicit value is specified.
*/
boolean getBooleanValue(string name) {
// Uses CompileTimeConstantExpr instead of BooleanLiteral because this can for example
// be a read from a final variable as well.
result = this.getNonArrayValue(name).(CompileTimeConstantExpr).getBooleanValue()
}
/**
* If the value type of the annotation element with the specified `name` is `java.lang.Class`,
* gets the type referred to by that `Class`. This includes default values in case no explicit
* value is specified.
*
* If the element value type is a `Class` array, use `getATypeArrayValue`.
*/
Type getTypeValue(string name) {
result = this.getNonArrayValue(name).(TypeLiteral).getReferencedType()
}
/** Gets the element being annotated. */
Element getTarget() { result = this.getAnnotatedElement() }
@@ -60,16 +148,83 @@ class Annotation extends @annotation, Expr {
/**
* Gets a value of the annotation element with the specified `name`, which must be declared as an array
* type.
* type. This includes default values in case no explicit value is specified.
*
* If the annotation element is defined with an array initializer, then the returned value will
* be one of the elements of that array. Otherwise, the returned value will be the single
* expression defined for the value.
* If the annotation element is defined with an array initializer, then the result will be one of the
* elements of that array. Otherwise, the result will be the single expression used as value.
*/
Expr getAValue(string name) {
Expr getAnArrayValue(string name) { result = this.getArrayValue(name, _) }
/**
* DEPRECATED: Predicate has been renamed to `getAnArrayValue`
*/
deprecated Expr getAValue(string name) { result = this.getAnArrayValue(name) }
/**
* Gets a value of the annotation element with the specified `name`, which must be declared as an enum
* type array. This includes default values in case no explicit value is specified.
*
* If the annotation element is defined with an array initializer, then the result will be one of the
* elements of that array. Otherwise, the result will be the single expression used as value.
*/
EnumConstant getAnEnumConstantArrayValue(string name) {
result = this.getAnArrayValue(name).(FieldRead).getField()
}
/**
* Gets a value of the annotation element with the specified `name`, which must be declared as a string
* array. This includes default values in case no explicit value is specified.
*
* If the annotation element is defined with an array initializer, then the result will be one of the
* elements of that array. Otherwise, the result will be the single expression used as value.
*/
string getAStringArrayValue(string name) {
result = this.getAnArrayValue(name).(CompileTimeConstantExpr).getStringValue()
}
/**
* Gets a value of the annotation element with the specified `name`, which must be declared as an `int`
* array or an array of a smaller integral type or `char`. This includes default values in case no
* explicit value is specified.
*
* If the annotation element is defined with an array initializer, then the result will be one of the
* elements of that array. Otherwise, the result will be the single expression used as value.
*/
int getAnIntArrayValue(string name) {
result = this.getAnArrayValue(name).(CompileTimeConstantExpr).getIntValue() and
// Verify that type is integral; ignore floating point elements with IntegerLiteral as value
this.getAnnotationElement(name).getType().hasName(["byte[]", "short[]", "int[]", "char[]"])
}
/**
* Gets a value of the annotation element with the specified `name`, which must be declared as a `Class`
* array. This includes default values in case no explicit value is specified.
*
* If the annotation element is defined with an array initializer, then the result will be one of the
* elements of that array. Otherwise, the result will be the single expression used as value.
*/
Type getATypeArrayValue(string name) {
result = this.getAnArrayValue(name).(TypeLiteral).getReferencedType()
}
/**
* Gets the value at a given index of the annotation element with the specified `name`, which must be
* declared as an array type. This includes default values in case no explicit value is specified.
*
* If the annotation element is defined with an array initializer, then the result will be the element
* at the given index of that array, starting at 0. Otherwise, the result will be the single expression
* defined for the value and the `index` will be 0.
*/
Expr getArrayValue(string name, int index) {
this.getType().getAnnotationElement(name).getType() instanceof Array and
exists(Expr value | value = this.getValue(name) |
if value instanceof ArrayInit then result = value.(ArrayInit).getAnInit() else result = value
if value instanceof ArrayInit
then
// TODO: Currently reports incorrect index values in some cases, see https://github.com/github/codeql/issues/8645
result = value.(ArrayInit).getInit(index)
else (
index = 0 and result = value
)
)
}
@@ -99,19 +254,86 @@ private predicate sourceAnnotValue(Annotation a, Method m, Expr val) {
/** An abstract representation of language elements that can be annotated. */
class Annotatable extends Element {
/** Holds if this element has an annotation. */
predicate hasAnnotation() { exists(Annotation a | a.getAnnotatedElement() = this) }
/**
* Holds if this element has an annotation, including inherited annotations.
* The retention policy of the annotation type is not considered.
*/
predicate hasAnnotation() { exists(this.getAnAnnotation()) }
/** Holds if this element has the specified annotation. */
/**
* Holds if this element has a declared annotation, excluding inherited annotations.
* The retention policy of the annotation type is not considered.
*/
predicate hasDeclaredAnnotation() { exists(this.getADeclaredAnnotation()) }
/**
* Holds if this element has the specified annotation, including inherited
* annotations. The retention policy of the annotation type is not considered.
*/
predicate hasAnnotation(string package, string name) {
exists(AnnotationType at | at = this.getAnAnnotation().getType() |
at.nestedName() = name and at.getPackage().getName() = package
)
}
/** Gets an annotation that applies to this element. */
/**
* Gets an annotation that applies to this element, including inherited annotations.
* The results only include _direct_ annotations; _indirect_ annotations, that is
* repeated annotations in an (implicit) container annotation, are not included.
* The retention policy of the annotation type is not considered.
*/
cached
Annotation getAnAnnotation() { result.getAnnotatedElement() = this }
Annotation getAnAnnotation() {
// This predicate is overridden by Class to consider inherited annotations
result = this.getADeclaredAnnotation()
}
/**
* Gets an annotation that is declared on this element, excluding inherited annotations.
* The retention policy of the annotation type is not considered.
*/
Annotation getADeclaredAnnotation() { result.getAnnotatedElement() = this }
/** Gets an _indirect_ (= repeated) annotation. */
private Annotation getAnIndirectAnnotation() {
// 'indirect' as defined by https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/reflect/AnnotatedElement.html
exists(AnnotationType t, Annotation containerAnn |
t = result.getType() and
containerAnn = this.getADeclaredAnnotation() and
containerAnn.getType() = t.getContainingAnnotationType()
|
result = containerAnn.getAnArrayValue("value")
)
}
private Annotation getADeclaredAssociatedAnnotation(AnnotationType t) {
// Direct or indirect annotation
result.getType() = t and
result = [this.getADeclaredAnnotation(), this.getAnIndirectAnnotation()]
}
private Annotation getAnAssociatedAnnotation(AnnotationType t) {
// 'associated' as defined by https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/reflect/AnnotatedElement.html
if exists(this.getADeclaredAssociatedAnnotation(t))
then result = this.getADeclaredAssociatedAnnotation(t)
else (
// Only if neither a direct nor an indirect annotation is present look for an inherited one
t.isInherited() and
// @Inherited only works for classes; cast to Annotatable is necessary because predicate is private
result = this.(Class).getASupertype().(Class).(Annotatable).getAnAssociatedAnnotation(t)
)
}
/**
* Gets an annotation _associated_ with this element, that is:
* - An annotation directly present on this element, or
* - An annotation indirectly present on this element (in the form of a repeated annotation), or
* - If an annotation of a type is neither directly nor indirectly present
* the result is an associated inherited annotation (recursively)
*
* The retention policy of the annotation type is not considered.
*/
Annotation getAnAssociatedAnnotation() { result = this.getAnAssociatedAnnotation(_) }
/**
* Holds if this or any enclosing `Annotatable` has a `@SuppressWarnings("<category>")`
@@ -128,6 +350,11 @@ class Annotatable extends Element {
or
this.(NestedClass).getEnclosingType().suppressesWarningsAbout(category)
or
this.(LocalClassOrInterface)
.getLocalTypeDeclStmt()
.getEnclosingCallable()
.suppressesWarningsAbout(category)
or
this.(LocalVariableDecl).getCallable().suppressesWarningsAbout(category)
}
}
@@ -146,10 +373,79 @@ class AnnotationType extends Interface {
/** Holds if this annotation type is annotated with the meta-annotation `@Inherited`. */
predicate isInherited() {
exists(Annotation ann |
ann.getAnnotatedElement() = this and
ann.getType().hasQualifiedName("java.lang.annotation", "Inherited")
)
this.getADeclaredAnnotation().getType().hasQualifiedName("java.lang.annotation", "Inherited")
}
/** Holds if this annotation type is annotated with the meta-annotation `@Documented`. */
predicate isDocumented() {
this.getADeclaredAnnotation().getType().hasQualifiedName("java.lang.annotation", "Documented")
}
/**
* Gets the retention policy of this annotation type, that is, the name of one of the
* enum constants of `java.lang.annotation.RetentionPolicy`. If this annotation type
* has no `@Retention` annotation, the result is `CLASS`.
*/
string getRetentionPolicy() {
if this.getADeclaredAnnotation() instanceof RetentionAnnotation
then result = this.getADeclaredAnnotation().(RetentionAnnotation).getRetentionPolicy()
else
// If not explicitly specified retention is CLASS
result = "CLASS"
}
/**
* Holds if the element type is a possible target for this annotation type.
* The `elementType` is the name of one of the `java.lang.annotation.ElementType`
* enum constants.
*
* If this annotation type has no `@Target` annotation, it is considered to be applicable
* in all declaration contexts. This matches the behavior of the latest Java versions
* but differs from the behavior of older Java versions. This predicate must only be
* called with names of `ElementType` enum constants; for other values it might hold
* erroneously.
*/
bindingset[elementType]
predicate isATargetType(string elementType) {
/*
* Note: Cannot use a predicate with string as result because annotation type without
* explicit @Target can be applied in all declaration contexts, requiring to hardcode
* element types here; then the results could become outdated if this predicate is not
* updated for future JDK versions, or it could have irritating results, e.g. RECORD_COMPONENT
* for a database created for Java 8.
*
* Could in theory read java.lang.annotation.ElementType constants from database, but might
* be brittle in case ElementType is not present in the database for whatever reason.
*/
if this.getADeclaredAnnotation() instanceof TargetAnnotation
then elementType = this.getADeclaredAnnotation().(TargetAnnotation).getATargetElementType()
else
/*
* Behavior for missing @Target annotation changed between Java versions. In older Java
* versions it allowed usage in most (but not all) declaration contexts. Then for Java 14
* JDK-8231435 changed it to allow usage in all declaration and type contexts. In Java 17
* it was changed by JDK-8261610 to only allow usage in all declaration contexts, but not
* in type contexts anymore. However, during these changes javac did not always comply with
* the specification, see for example JDK-8254023.
*
* For simplicity pretend the latest behavior defined by the JLS applied in all versions;
* that means any declaration context is allowed, but type contexts (represented by TYPE_USE,
* see JLS 17 section 9.6.4.1) are not allowed.
*/
elementType != "TYPE_USE"
}
/** Holds if this annotation type is annotated with the meta-annotation `@Repeatable`. */
predicate isRepeatable() { this.getADeclaredAnnotation() instanceof RepeatableAnnotation }
/**
* If this annotation type is annotated with the meta-annotation `@Repeatable`,
* gets the annotation type which acts as _containing annotation type_.
*/
AnnotationType getContainingAnnotationType() {
result = this.getADeclaredAnnotation().(RepeatableAnnotation).getContainingType()
}
}

View File

@@ -71,7 +71,8 @@ predicate depends(RefType t, RefType dep) {
a.getAnnotatedElement().(Member).getDeclaringType() = t
|
usesType(a.getType(), dep) or
usesType(a.getAValue().getType(), dep)
usesType(a.getValue(_).getType(), dep) or
usesType(a.getAnArrayValue(_).getType(), dep)
)
or
// the type accessed in an `instanceof` expression in `t`.

View File

@@ -90,7 +90,7 @@ predicate numDepends(RefType t, RefType dep, int value) {
|
elem = a and usesType(a.getType(), dep)
or
elem = a.getAValue() and
elem = [a.getValue(_), a.getAnArrayValue(_)] and
elem.getFile().getExtension() = "java" and
usesType(elem.(Expr).getType(), dep)
)

View File

@@ -18,14 +18,16 @@ class OverrideAnnotation extends Annotation {
class SuppressWarningsAnnotation extends Annotation {
SuppressWarningsAnnotation() { this.getType().hasQualifiedName("java.lang", "SuppressWarnings") }
/** Gets the `StringLiteral` of a warning suppressed by this annotation. */
StringLiteral getASuppressedWarningLiteral() {
result = this.getAValue() or
result = this.getAValue().(ArrayInit).getAnInit()
}
/**
* DEPRECATED: This predicate restricts the results to `StringLiteral`; prefer `getASuppressedWarning()`
* to get the name of a suppressed warning.
*
* Gets the `StringLiteral` of a warning suppressed by this annotation.
*/
deprecated StringLiteral getASuppressedWarningLiteral() { result = this.getAnArrayValue("value") }
/** Gets the name of a warning suppressed by this annotation. */
string getASuppressedWarning() { result = this.getASuppressedWarningLiteral().getValue() }
string getASuppressedWarning() { result = this.getAStringArrayValue("value") }
}
/** A `@Target` annotation. */
@@ -33,18 +35,15 @@ class TargetAnnotation extends Annotation {
TargetAnnotation() { this.getType().hasQualifiedName("java.lang.annotation", "Target") }
/**
* DEPRECATED: Getting the field access expression is rarely useful. Use `getATargetElementType()`
* to get the name of the target element.
*
* Gets a target expression within this annotation.
*
* For example, the field access `ElementType.FIELD` is a target expression in
* `@Target({ElementType.FIELD, ElementType.METHOD})`.
*/
Expr getATargetExpression() {
not result instanceof ArrayInit and
(
result = this.getAValue() or
result = this.getAValue().(ArrayInit).getAnInit()
)
}
deprecated Expr getATargetExpression() { result = this.getAnArrayValue("value") }
/**
* Gets the name of a target element type.
@@ -52,14 +51,7 @@ class TargetAnnotation extends Annotation {
* For example, `METHOD` is the name of a target element type in
* `@Target({ElementType.FIELD, ElementType.METHOD})`.
*/
string getATargetElementType() {
exists(EnumConstant ec |
ec = this.getATargetExpression().(VarAccess).getVariable() and
ec.getDeclaringType().hasQualifiedName("java.lang.annotation", "ElementType")
|
result = ec.getName()
)
}
string getATargetElementType() { result = this.getAnEnumConstantArrayValue("value").getName() }
}
/** A `@Retention` annotation. */
@@ -67,12 +59,15 @@ class RetentionAnnotation extends Annotation {
RetentionAnnotation() { this.getType().hasQualifiedName("java.lang.annotation", "Retention") }
/**
* DEPRECATED: Getting the field access expression is rarely useful. Use `getRetentionPolicy()`
* to get the name of the retention policy.
*
* Gets the retention policy expression within this annotation.
*
* For example, the field access `RetentionPolicy.RUNTIME` is the
* retention policy expression in `@Retention(RetentionPolicy.RUNTIME)`.
*/
Expr getRetentionPolicyExpression() { result = this.getValue("value") }
deprecated Expr getRetentionPolicyExpression() { result = this.getValue("value") }
/**
* Gets the name of the retention policy of this annotation.
@@ -80,14 +75,18 @@ class RetentionAnnotation extends Annotation {
* For example, `RUNTIME` is the name of the retention policy
* in `@Retention(RetentionPolicy.RUNTIME)`.
*/
string getRetentionPolicy() {
exists(EnumConstant ec |
ec = this.getRetentionPolicyExpression().(VarAccess).getVariable() and
ec.getDeclaringType().hasQualifiedName("java.lang.annotation", "RetentionPolicy")
|
result = ec.getName()
)
}
string getRetentionPolicy() { result = this.getEnumConstantValue("value").getName() }
}
/** A `@Repeatable` annotation. */
class RepeatableAnnotation extends Annotation {
RepeatableAnnotation() { this.getType().hasQualifiedName("java.lang.annotation", "Repeatable") }
/**
* Gets the annotation type which acts as _containing type_, grouping multiple
* repeatable annotations together.
*/
AnnotationType getContainingType() { result = this.getTypeValue("value") }
}
/**
@@ -119,11 +118,7 @@ abstract class NonReflectiveAnnotation extends Annotation { }
library class StandardNonReflectiveAnnotation extends NonReflectiveAnnotation {
StandardNonReflectiveAnnotation() {
exists(AnnotationType anntp | anntp = this.getType() |
anntp.hasQualifiedName("java.lang", "Override") or
anntp.hasQualifiedName("java.lang", "Deprecated") or
anntp.hasQualifiedName("java.lang", "SuppressWarnings") or
anntp.hasQualifiedName("java.lang", "SafeVarargs")
)
this.getType()
.hasQualifiedName("java.lang", ["Override", "Deprecated", "SuppressWarnings", "SafeVarargs"])
}
}

View File

@@ -27,7 +27,7 @@ class MXBean extends ManagedBean {
class RegisteredManagedBeanImpl extends Class {
RegisteredManagedBeanImpl() {
this.getAnAncestor() instanceof ManagedBean and
exists(JMXRegistrationCall registerCall | registerCall.getObjectArgument().getType() = this)
exists(JmxRegistrationCall registerCall | registerCall.getObjectArgument().getType() = this)
}
/**
@@ -39,32 +39,35 @@ class RegisteredManagedBeanImpl extends Class {
/**
* A call that registers an object with the `MBeanServer`, directly or indirectly.
*/
class JMXRegistrationCall extends MethodAccess {
JMXRegistrationCall() { this.getCallee() instanceof JMXRegistrationMethod }
class JmxRegistrationCall extends MethodAccess {
JmxRegistrationCall() { this.getCallee() instanceof JmxRegistrationMethod }
/**
* Gets the argument that represents the object in the registration call.
*/
Expr getObjectArgument() {
result = this.getArgument(this.getCallee().(JMXRegistrationMethod).getObjectPosition())
result = this.getArgument(this.getCallee().(JmxRegistrationMethod).getObjectPosition())
}
}
/** DEPRECATED: Alias for JmxRegistrationCall */
deprecated class JMXRegistrationCall = JmxRegistrationCall;
/**
* A method used to register `MBean` and `MXBean` instances with the `MBeanServer`.
*
* This is either the `registerMBean` method on `MBeanServer`, or it is a wrapper around that
* registration method.
*/
class JMXRegistrationMethod extends Method {
JMXRegistrationMethod() {
class JmxRegistrationMethod extends Method {
JmxRegistrationMethod() {
// A direct registration with the `MBeanServer`.
this.getDeclaringType().hasQualifiedName("javax.management", "MBeanServer") and
this.getName() = "registerMBean"
or
// The `MBeanServer` is often wrapped by an application specific management class, so identify
// methods that wrap a call to another `JMXRegistrationMethod`.
exists(JMXRegistrationCall c |
// methods that wrap a call to another `JmxRegistrationMethod`.
exists(JmxRegistrationCall c |
// This must be a call to another JMX registration method, where the object argument is an access
// of one of the parameters of this method.
c.getObjectArgument().(VarAccess).getVariable() = this.getAParameter()
@@ -81,25 +84,37 @@ class JMXRegistrationMethod extends Method {
result = 0
or
// Identify the position in this method where the object parameter should be passed.
exists(JMXRegistrationCall c |
exists(JmxRegistrationCall c |
c.getObjectArgument().(VarAccess).getVariable() = this.getParameter(result)
)
}
}
/** DEPRECATED: Alias for JmxRegistrationMethod */
deprecated class JMXRegistrationMethod = JmxRegistrationMethod;
/** The class `javax.management.remote.JMXConnectorFactory`. */
class TypeJMXConnectorFactory extends Class {
TypeJMXConnectorFactory() {
class TypeJmxConnectorFactory extends Class {
TypeJmxConnectorFactory() {
this.hasQualifiedName("javax.management.remote", "JMXConnectorFactory")
}
}
/** DEPRECATED: Alias for TypeJmxConnectorFactory */
deprecated class TypeJMXConnectorFactory = TypeJmxConnectorFactory;
/** The class `javax.management.remote.JMXServiceURL`. */
class TypeJMXServiceURL extends Class {
TypeJMXServiceURL() { this.hasQualifiedName("javax.management.remote", "JMXServiceURL") }
class TypeJmxServiceUrl extends Class {
TypeJmxServiceUrl() { this.hasQualifiedName("javax.management.remote", "JMXServiceURL") }
}
/** DEPRECATED: Alias for TypeJmxServiceUrl */
deprecated class TypeJMXServiceURL = TypeJmxServiceUrl;
/** The class `javax.management.remote.rmi.RMIConnector`. */
class TypeRMIConnector extends Class {
TypeRMIConnector() { this.hasQualifiedName("javax.management.remote.rmi", "RMIConnector") }
class TypeRmiConnector extends Class {
TypeRmiConnector() { this.hasQualifiedName("javax.management.remote.rmi", "RMIConnector") }
}
/** DEPRECATED: Alias for TypeRmiConnector */
deprecated class TypeRMIConnector = TypeRmiConnector;

View File

@@ -20,8 +20,14 @@ class Member extends Element, Annotatable, Modifiable, @member {
/** Gets the type in which this member is declared. */
RefType getDeclaringType() { declaresMember(result, this) }
/** Gets the qualified name of this member. */
string getQualifiedName() { result = this.getDeclaringType().getName() + "." + this.getName() }
/**
* Gets the qualified name of this member.
* This is useful for debugging, but for normal use `hasQualifiedName`
* is recommended, as it is more efficient.
*/
string getQualifiedName() {
result = this.getDeclaringType().getQualifiedName() + "." + this.getName()
}
/**
* Holds if this member has the specified name and is declared in the

View File

@@ -7,7 +7,13 @@ import Element
/** A modifier such as `private`, `static` or `abstract`. */
class Modifier extends Element, @modifier {
/** Gets the element to which this modifier applies. */
Element getElement() { hasModifier(result, this) }
Element getElement() {
hasModifier(result, this) and
// Kotlin "internal" elements may also get "public" modifiers, so we want to filter those out
not exists(Modifier mod2 |
hasModifier(result, mod2) and modifiers(this, "public") and modifiers(mod2, "internal")
)
}
override string getAPrimaryQlClass() { result = "Modifier" }
}
@@ -20,7 +26,7 @@ abstract class Modifiable extends Element {
* For most purposes, the more specialized predicates `isAbstract`, `isPublic`, etc.
* should be used.
*
* Both this method and those specialized predicates take implicit modifiers into account.
* Those specialized predicates also take implicit modifiers into account.
* For instance, non-default instance methods in interfaces are implicitly
* abstract, so `isAbstract()` will hold for them even if `hasModifier("abstract")`
* does not.

View File

@@ -15,7 +15,7 @@ private class SpecialMethodAccess extends MethodAccess {
this.getQualifier().getType().(RefType).hasQualifiedName("java.lang", klass)
}
predicate throwsNFE() {
predicate throwsNfe() {
this.isParseMethod("Byte", "parseByte") or
this.isParseMethod("Short", "parseShort") or
this.isParseMethod("Integer", "parseInt") or
@@ -33,6 +33,9 @@ private class SpecialMethodAccess extends MethodAccess {
this.isValueOfMethod("Float") or
this.isValueOfMethod("Double")
}
/** DEPRECATED: Alias for throwsNfe */
deprecated predicate throwsNFE() { this.throwsNfe() }
}
/** A `ClassInstanceExpr` that constructs a number from its string representation. */
@@ -43,7 +46,7 @@ private class SpecialClassInstanceExpr extends ClassInstanceExpr {
this.getNumArgument() = 1
}
predicate throwsNFE() {
predicate throwsNfe() {
this.isStringConstructor("Byte") or
this.isStringConstructor("Short") or
this.isStringConstructor("Integer") or
@@ -51,6 +54,9 @@ private class SpecialClassInstanceExpr extends ClassInstanceExpr {
this.isStringConstructor("Float") or
this.isStringConstructor("Double")
}
/** DEPRECATED: Alias for throwsNfe */
deprecated predicate throwsNFE() { this.throwsNfe() }
}
/** The class `java.lang.NumberFormatException`. */
@@ -59,7 +65,7 @@ class NumberFormatException extends RefType {
}
/** Holds if `java.lang.NumberFormatException` is caught. */
predicate catchesNFE(TryStmt t) {
predicate catchesNfe(TryStmt t) {
exists(CatchClause cc, LocalVariableDeclExpr v |
t.getACatchClause() = cc and
cc.getVariable() = v and
@@ -67,7 +73,13 @@ predicate catchesNFE(TryStmt t) {
)
}
/** DEPRECATED: Alias for catchesNfe */
deprecated predicate catchesNFE = catchesNfe/1;
/** Holds if `java.lang.NumberFormatException` can be thrown. */
predicate throwsNFE(Expr e) {
e.(SpecialClassInstanceExpr).throwsNFE() or e.(SpecialMethodAccess).throwsNFE()
predicate throwsNfe(Expr e) {
e.(SpecialClassInstanceExpr).throwsNfe() or e.(SpecialMethodAccess).throwsNfe()
}
/** DEPRECATED: Alias for throwsNfe */
deprecated predicate throwsNFE = throwsNfe/1;

View File

@@ -120,7 +120,7 @@ private newtype TPrintAstNode =
shouldPrint(lvde, _) and lvde.getParent() instanceof SingleLocalVarDeclParent
} or
TAnnotationsNode(Annotatable ann) {
shouldPrint(ann, _) and ann.hasAnnotation() and not partOfAnnotation(ann)
shouldPrint(ann, _) and ann.hasDeclaredAnnotation() and not partOfAnnotation(ann)
} or
TParametersNode(Callable c) { shouldPrint(c, _) and not c.hasNoParameters() } or
TBaseTypesNode(ClassOrInterface ty) { shouldPrint(ty, _) } or

View File

@@ -161,15 +161,13 @@ class TestNGTestMethod extends Method {
exists(TestNGTestAnnotation testAnnotation |
testAnnotation = this.getAnAnnotation() and
// The data provider must have the same name as the referenced data provider
result.getDataProviderName() =
testAnnotation.getValue("dataProvider").(StringLiteral).getValue()
result.getDataProviderName() = testAnnotation.getStringValue("dataProvider")
|
// Either the data provider should be on the current class, or a supertype
this.getDeclaringType().getAnAncestor() = result.getDeclaringType()
or
// Or the data provider class should be declared
result.getDeclaringType() =
testAnnotation.getValue("dataProviderClass").(TypeLiteral).getReferencedType()
result.getDeclaringType() = testAnnotation.getTypeValue("dataProviderClass")
)
}
}
@@ -227,9 +225,7 @@ class TestNGListenersAnnotation extends TestNGAnnotation {
/**
* Gets a listener defined in this annotation.
*/
TestNGListenerImpl getAListener() {
result = this.getAValue("value").(TypeLiteral).getReferencedType()
}
TestNGListenerImpl getAListener() { result = this.getATypeArrayValue("value") }
}
/**

View File

@@ -12,6 +12,7 @@
* `namespace; type; subtypes; name; signature; ext; input; output; kind; provenance`
* - Negative Summaries:
* `namespace; type; name; signature; provenance`
* A negative summary is used to indicate that there is no flow via a callable.
*
* The interpretation of a row is similar to API-graphs with a left-to-right
* reading.
@@ -116,10 +117,12 @@ private module Frameworks {
private import semmle.code.java.frameworks.Retrofit
private import semmle.code.java.frameworks.Stream
private import semmle.code.java.frameworks.Strings
private import semmle.code.java.frameworks.Thymeleaf
private import semmle.code.java.frameworks.ratpack.Ratpack
private import semmle.code.java.frameworks.ratpack.RatpackExec
private import semmle.code.java.frameworks.spring.SpringCache
private import semmle.code.java.frameworks.spring.SpringContext
private import semmle.code.java.frameworks.spring.SpringData
private import semmle.code.java.frameworks.spring.SpringHttp
private import semmle.code.java.frameworks.spring.SpringUtil
private import semmle.code.java.frameworks.spring.SpringUi
@@ -139,6 +142,7 @@ private module Frameworks {
private import semmle.code.java.security.LdapInjection
private import semmle.code.java.security.MvelInjection
private import semmle.code.java.security.OgnlInjection
private import semmle.code.java.security.TemplateInjection
private import semmle.code.java.security.XPath
private import semmle.code.java.security.XsltInjection
private import semmle.code.java.frameworks.Jdbc
@@ -151,7 +155,7 @@ private module Frameworks {
private import semmle.code.java.frameworks.JMS
private import semmle.code.java.frameworks.RabbitMQ
private import semmle.code.java.regex.RegexFlowModels
private import semmle.code.java.frameworks.KotlinStdLib
private import semmle.code.java.frameworks.kotlin.StdLib
}
/**
@@ -623,7 +627,7 @@ module CsvValidation {
"open-url", "jndi-injection", "ldap", "sql", "jdbc-url", "logging", "mvel", "xpath",
"groovy", "xss", "ognl-injection", "intent-start", "pending-intent-sent",
"url-open-stream", "url-redirect", "create-file", "write-file", "set-hostname-verifier",
"header-splitting", "information-leak", "xslt", "jexl", "bean-validation"
"header-splitting", "information-leak", "xslt", "jexl", "bean-validation", "ssti"
] and
not kind.matches("regex-use%") and
not kind.matches("qltest%") and

View File

@@ -88,7 +88,7 @@ private class ReverseDnsSource extends RemoteFlowSource {
ReverseDnsSource() {
// Try not to trigger on `localhost`.
exists(MethodAccess m | m = this.asExpr() |
m.getMethod() instanceof ReverseDNSMethod and
m.getMethod() instanceof ReverseDnsMethod and
not exists(MethodAccess l |
(variableStep(l, m.getQualifier()) or l = m.getQualifier()) and
l.getMethod().getName() = "getLocalHost"
@@ -221,8 +221,8 @@ class TypeInetAddr extends RefType {
}
/** A reverse DNS method. */
class ReverseDNSMethod extends Method {
ReverseDNSMethod() {
class ReverseDnsMethod extends Method {
ReverseDnsMethod() {
this.getDeclaringType() instanceof TypeInetAddr and
(
this.getName() = "getHostName" or
@@ -231,6 +231,9 @@ class ReverseDNSMethod extends Method {
}
}
/** DEPRECATED: Alias for ReverseDnsMethod */
deprecated class ReverseDNSMethod = ReverseDnsMethod;
/** Android `Intent` that may have come from a hostile application. */
class AndroidIntentInput extends DataFlow::Node {
Type receiverType;

View File

@@ -53,6 +53,16 @@ private class TypeFlowNode extends TTypeFlowNode {
}
}
private int getNodeKind(TypeFlowNode n) {
result = 1 and n instanceof TField
or
result = 2 and n instanceof TSsa
or
result = 3 and n instanceof TExpr
or
result = 4 and n instanceof TMethod
}
/** Gets `t` if it is a `RefType` or the boxed type if `t` is a primitive type. */
private RefType boxIfNeeded(Type t) {
t.(PrimitiveType).getBoxedType() = result or
@@ -146,46 +156,199 @@ private predicate joinStep(TypeFlowNode n1, TypeFlowNode n2) {
joinStep0(n1, n2) and not isNull(n1)
}
private predicate joinStepRank1(int r, TypeFlowNode n1, TypeFlowNode n2) {
n1 =
rank[r](TypeFlowNode n |
joinStep(n, n2)
|
n order by n.getLocation().getStartLine(), n.getLocation().getStartColumn()
private predicate anyStep(TypeFlowNode n1, TypeFlowNode n2) { joinStep(n1, n2) or step(n1, n2) }
private import SccReduction
/**
* SCC reduction.
*
* This ought to be as easy as `equivalenceRelation(sccEdge/2)(n, scc)`, but
* this HOP is not currently supported for newtypes.
*
* A straightforward implementation would be:
* ```ql
* predicate sccRepr(TypeFlowNode n, TypeFlowNode scc) {
* scc =
* max(TypeFlowNode n2 |
* sccEdge+(n, n2)
* |
* n2
* order by
* n2.getLocation().getStartLine(), n2.getLocation().getStartColumn(), getNodeKind(n2)
* )
* }
*
* ```
* but this is quadratic in the size of the SCCs.
*
* Instead we find local maxima by following SCC edges and determine the SCC
* representatives from those.
* (This is still worst-case quadratic in the size of the SCCs, but generally
* performs better.)
*/
private module SccReduction {
private predicate sccEdge(TypeFlowNode n1, TypeFlowNode n2) {
anyStep(n1, n2) and anyStep+(n2, n1)
}
private predicate sccEdgeWithMax(TypeFlowNode n1, TypeFlowNode n2, TypeFlowNode m) {
sccEdge(n1, n2) and
m =
max(TypeFlowNode n |
n = [n1, n2]
|
n order by n.getLocation().getStartLine(), n.getLocation().getStartColumn(), getNodeKind(n)
)
}
private predicate hasLargerNeighbor(TypeFlowNode n) {
exists(TypeFlowNode n2 |
sccEdgeWithMax(n, n2, n2) and
not sccEdgeWithMax(n, n2, n)
or
sccEdgeWithMax(n2, n, n2) and
not sccEdgeWithMax(n2, n, n)
)
}
private predicate localMax(TypeFlowNode m) {
sccEdgeWithMax(_, _, m) and
not hasLargerNeighbor(m)
}
private predicate sccReprFromLocalMax(TypeFlowNode scc) {
exists(TypeFlowNode m |
localMax(m) and
scc =
max(TypeFlowNode n2 |
sccEdge+(m, n2) and localMax(n2)
|
n2
order by
n2.getLocation().getStartLine(), n2.getLocation().getStartColumn(), getNodeKind(n2)
)
)
}
/** Holds if `n` is part of an SCC of size 2 or more represented by `scc`. */
predicate sccRepr(TypeFlowNode n, TypeFlowNode scc) {
sccEdge+(n, scc) and sccReprFromLocalMax(scc)
}
predicate sccJoinStep(TypeFlowNode n, TypeFlowNode scc) {
exists(TypeFlowNode mid |
joinStep(n, mid) and
sccRepr(mid, scc) and
not sccRepr(n, scc)
)
}
}
private predicate joinStepRank2(int r2, int r1, TypeFlowNode n) {
r1 = rank[r2](int r | joinStepRank1(r, _, n) | r)
private signature predicate edgeSig(TypeFlowNode n1, TypeFlowNode n2);
private signature module RankedEdge {
predicate edgeRank(int r, TypeFlowNode n1, TypeFlowNode n2);
int lastRank(TypeFlowNode n);
}
private predicate joinStepRank(int r, TypeFlowNode n1, TypeFlowNode n2) {
exists(int r1 |
joinStepRank1(r1, n1, n2) and
joinStepRank2(r, r1, n2)
)
private module RankEdge<edgeSig/2 edge> implements RankedEdge {
/**
* Holds if `r` is a ranking of the incoming edges `(n1,n2)` to `n2`. The used
* ordering is not necessarily total, so the ranking may have gaps.
*/
private predicate edgeRank1(int r, TypeFlowNode n1, TypeFlowNode n2) {
n1 =
rank[r](TypeFlowNode n |
edge(n, n2)
|
n order by n.getLocation().getStartLine(), n.getLocation().getStartColumn()
)
}
/**
* Holds if `r2` is a ranking of the ranks from `edgeRank1`. This removes the
* gaps from the ranking.
*/
private predicate edgeRank2(int r2, int r1, TypeFlowNode n) {
r1 = rank[r2](int r | edgeRank1(r, _, n) | r)
}
/** Holds if `r` is a ranking of the incoming edges `(n1,n2)` to `n2`. */
predicate edgeRank(int r, TypeFlowNode n1, TypeFlowNode n2) {
exists(int r1 |
edgeRank1(r1, n1, n2) and
edgeRank2(r, r1, n2)
)
}
int lastRank(TypeFlowNode n) { result = max(int r | edgeRank(r, _, n)) }
}
private int lastRank(TypeFlowNode n) { result = max(int r | joinStepRank(r, _, n)) }
private signature module TypePropagation {
class Typ;
predicate candType(TypeFlowNode n, Typ t);
bindingset[t]
predicate supportsType(TypeFlowNode n, Typ t);
}
/** Implements recursion through `forall` by way of edge ranking. */
private module ForAll<RankedEdge Edge, TypePropagation T> {
/**
* Holds if `t` is a bound that holds on one of the incoming edges to `n` and
* thus is a candidate bound for `n`.
*/
pragma[nomagic]
private predicate candJoinType(TypeFlowNode n, T::Typ t) {
exists(TypeFlowNode mid |
T::candType(mid, t) and
Edge::edgeRank(_, mid, n)
)
}
/**
* Holds if `t` is a candidate bound for `n` that is also valid for data coming
* through the edges into `n` ranked from `1` to `r`.
*/
private predicate flowJoin(int r, TypeFlowNode n, T::Typ t) {
(
r = 1 and candJoinType(n, t)
or
flowJoin(r - 1, n, t) and Edge::edgeRank(r, _, n)
) and
forall(TypeFlowNode mid | Edge::edgeRank(r, mid, n) | T::supportsType(mid, t))
}
/**
* Holds if `t` is a candidate bound for `n` that is also valid for data
* coming through all the incoming edges, and therefore is a valid bound for
* `n`.
*/
predicate flowJoin(TypeFlowNode n, T::Typ t) { flowJoin(Edge::lastRank(n), n, t) }
}
module RankedJoinStep = RankEdge<joinStep/2>;
module RankedSccJoinStep = RankEdge<sccJoinStep/2>;
private predicate exactTypeBase(TypeFlowNode n, RefType t) {
exists(ClassInstanceExpr e |
n.asExpr() = e and
e.getType() = t and
not e instanceof FunctionalExpr and
exists(RefType sub | sub.getASourceSupertype() = t.getSourceDeclaration())
exists(SrcRefType sub | sub.getASourceSupertype() = t.getSourceDeclaration())
)
}
private predicate exactTypeRank(int r, TypeFlowNode n, RefType t) {
forall(TypeFlowNode mid | joinStepRank(r, mid, n) | exactType(mid, t)) and
joinStepRank(r, _, n)
}
private module ExactTypePropagation implements TypePropagation {
class Typ = RefType;
private predicate exactTypeJoin(int r, TypeFlowNode n, RefType t) {
exactTypeRank(1, n, t) and r = 1
or
exactTypeJoin(r - 1, n, t) and exactTypeRank(r, n, t)
predicate candType = exactType/2;
predicate supportsType = exactType/2;
}
/**
@@ -199,43 +362,60 @@ private predicate exactType(TypeFlowNode n, RefType t) {
or
// The following is an optimized version of
// `forex(TypeFlowNode mid | joinStep(mid, n) | exactType(mid, t))`
exactTypeJoin(lastRank(n), n, t)
ForAll<RankedJoinStep, ExactTypePropagation>::flowJoin(n, t)
or
exists(TypeFlowNode scc |
sccRepr(n, scc) and
// Optimized version of
// `forex(TypeFlowNode mid | sccJoinStep(mid, scc) | exactType(mid, t))`
ForAll<RankedSccJoinStep, ExactTypePropagation>::flowJoin(scc, t)
)
}
/**
* Holds if `n` occurs in a position where type information might be discarded;
* `t` is the potentially boxed type of `n`, `t1` is the erasure of `t`, and
* `t2` is the erased type of the implicit or explicit cast.
* `t1` is the type of `n`, `t1e` is the erasure of `t1`, `t2` is the type of
* the implicit or explicit cast, and `t2e` is the erasure of `t2`.
*/
pragma[noinline]
private predicate upcastCand(TypeFlowNode n, RefType t, RefType t1, RefType t2) {
t = boxIfNeeded(n.getType()) and
t.getErasure() = t1 and
(
exists(Variable v | v.getAnAssignedValue() = n.asExpr() and t2 = v.getType().getErasure())
or
exists(CastingExpr c | c.getExpr() = n.asExpr() and t2 = c.getType().getErasure())
or
exists(ReturnStmt ret |
ret.getResult() = n.asExpr() and t2 = ret.getEnclosingCallable().getReturnType().getErasure()
)
or
exists(MethodAccess ma | viableImpl_v1(ma) = n.asMethod() and t2 = ma.getType())
or
exists(Parameter p | privateParamArg(p, n.asExpr()) and t2 = p.getType().getErasure())
or
exists(ChooseExpr cond |
cond.getAResultExpr() = n.asExpr() and
t2 = cond.getType().getErasure()
)
pragma[nomagic]
private predicate upcastCand(TypeFlowNode n, RefType t1, RefType t1e, RefType t2, RefType t2e) {
exists(TypeFlowNode next | step(n, next) or joinStep(n, next) |
n.getType() = t1 and
next.getType() = t2 and
t1.getErasure() = t1e and
t2.getErasure() = t2e and
t1 != t2
)
}
private predicate unconstrained(BoundedType t) {
t.(Wildcard).isUnconstrained()
or
t.getUpperBoundType() instanceof TypeObject and
not t.(Wildcard).hasLowerBound()
or
unconstrained(t.getUpperBoundType())
or
unconstrained(t.(Wildcard).getLowerBoundType())
}
/** Holds if `t` is a raw type or parameterised type with unrestricted type arguments. */
private predicate unbound(RefType t) {
t instanceof RawType
or
exists(ParameterizedType pt | pt = t |
forex(RefType arg | arg = pt.getATypeArgument() | unconstrained(arg))
)
}
/** Holds if `n` occurs in a position where type information is discarded. */
private predicate upcast(TypeFlowNode n, RefType t) {
exists(RefType t1, RefType t2 |
upcastCand(n, t, t1, t2) and
t1.getASourceSupertype+() = t2
private predicate upcast(TypeFlowNode n, RefType t1) {
exists(RefType t1e, RefType t2, RefType t2e | upcastCand(n, t1, t1e, t2, t2e) |
t1e.getASourceSupertype+() = t2e
or
t1e = t2e and
unbound(t2) and
not unbound(t1)
)
}
@@ -322,9 +502,10 @@ predicate arrayInstanceOfGuarded(ArrayAccess aa, RefType t) {
/**
* Holds if `n` has type `t` and this information is discarded, such that `t`
* might be a better type bound for nodes where `n` flows to.
* might be a better type bound for nodes where `n` flows to. This might include
* multiple bounds for a single node.
*/
private predicate typeFlowBase(TypeFlowNode n, RefType t) {
private predicate typeFlowBaseCand(TypeFlowNode n, RefType t) {
exists(RefType srctype |
upcast(n, srctype) or
upcastEnhancedForStmt(n.asSsa(), srctype) or
@@ -340,29 +521,36 @@ private predicate typeFlowBase(TypeFlowNode n, RefType t) {
}
/**
* Holds if `t` is a bound that holds on one of the incoming edges to `n` and
* thus is a candidate bound for `n`.
* Holds if `n` has type `t` and this information is discarded, such that `t`
* might be a better type bound for nodes where `n` flows to. This only includes
* the best such bound for each node.
*/
pragma[noinline]
private predicate typeFlowJoinCand(TypeFlowNode n, RefType t) {
exists(TypeFlowNode mid | joinStep(mid, n) | typeFlow(mid, t))
private predicate typeFlowBase(TypeFlowNode n, RefType t) {
exists(RefType te |
typeFlowBaseCand(n, t) and
te = t.getErasure() and
not exists(RefType better |
typeFlowBaseCand(n, better) and
better != t and
not t.getASupertype+() = better
|
better.getASupertype+() = t or
better.getErasure().(RefType).getASourceSupertype+() = te
)
)
}
/**
* Holds if `t` is a candidate bound for `n` that is also valid for data coming
* through the edges into `n` ranked from `1` to `r`.
*/
private predicate typeFlowJoin(int r, TypeFlowNode n, RefType t) {
(
r = 1 and typeFlowJoinCand(n, t)
or
typeFlowJoin(r - 1, n, t) and joinStepRank(r, _, n)
) and
forall(TypeFlowNode mid | joinStepRank(r, mid, n) |
private module TypeFlowPropagation implements TypePropagation {
class Typ = RefType;
predicate candType = typeFlow/2;
bindingset[t]
predicate supportsType(TypeFlowNode mid, RefType t) {
exists(RefType midtyp | exactType(mid, midtyp) or typeFlow(mid, midtyp) |
pragma[only_bind_out](midtyp).getAnAncestor() = t
)
)
}
}
/**
@@ -374,7 +562,12 @@ private predicate typeFlow(TypeFlowNode n, RefType t) {
or
exists(TypeFlowNode mid | typeFlow(mid, t) and step(mid, n))
or
typeFlowJoin(lastRank(n), n, t)
ForAll<RankedJoinStep, TypeFlowPropagation>::flowJoin(n, t)
or
exists(TypeFlowNode scc |
sccRepr(n, scc) and
ForAll<RankedSccJoinStep, TypeFlowPropagation>::flowJoin(scc, t)
)
}
pragma[nomagic]
@@ -429,6 +622,175 @@ private predicate bestTypeFlow(TypeFlowNode n, RefType t) {
not irrelevantBound(n, t)
}
private predicate bestTypeFlow(TypeFlowNode n, RefType t, boolean exact) {
exactType(n, t) and exact = true
or
not exactType(n, _) and bestTypeFlow(n, t) and exact = false
}
private predicate bestTypeFlowOrTypeFlowBase(TypeFlowNode n, RefType t, boolean exact) {
bestTypeFlow(n, t, exact)
or
typeFlowBase(n, t) and
exact = false and
not bestTypeFlow(n, _, _)
}
/**
* Holds if `n` has type `t` and this information is not propagated as a
* universal bound to a subsequent node, such that `t` might form the basis for
* a union type bound for that node.
*/
private predicate unionTypeFlowBaseCand(TypeFlowNode n, RefType t, boolean exact) {
exists(TypeFlowNode next |
joinStep(n, next) and
bestTypeFlowOrTypeFlowBase(n, t, exact) and
not bestTypeFlowOrTypeFlowBase(next, t, exact) and
not exactType(next, _)
)
}
/**
* Holds if `ioe` checks `v`, its true-successor is `bb`, and `bb` has multiple
* predecessors.
*/
private predicate instanceofDisjunct(InstanceOfExpr ioe, BasicBlock bb, BaseSsaVariable v) {
ioe.getExpr() = v.getAUse() and
strictcount(bb.getABBPredecessor()) > 1 and
exists(ConditionBlock cb | cb.getCondition() = ioe and cb.getTestSuccessor(true) = bb)
}
/** Holds if `bb` is disjunctively guarded by multiple `instanceof` tests on `v`. */
private predicate instanceofDisjunction(BasicBlock bb, BaseSsaVariable v) {
strictcount(InstanceOfExpr ioe | instanceofDisjunct(ioe, bb, v)) =
strictcount(bb.getABBPredecessor())
}
/**
* Holds if `n` is a value that is guarded by a disjunction of
* `instanceof t_i` where `t` is one of those `t_i`.
*/
private predicate instanceofDisjunctionGuarded(TypeFlowNode n, RefType t) {
exists(BasicBlock bb, InstanceOfExpr ioe, BaseSsaVariable v, VarAccess va |
instanceofDisjunction(bb, v) and
bb.bbDominates(va.getBasicBlock()) and
va = v.getAUse() and
instanceofDisjunct(ioe, bb, v) and
t = ioe.getCheckedType() and
n.asExpr() = va
)
}
private module HasUnionTypePropagation implements TypePropagation {
class Typ = Unit;
predicate candType(TypeFlowNode mid, Unit unit) {
exists(unit) and
(unionTypeFlowBaseCand(mid, _, _) or hasUnionTypeFlow(mid))
}
predicate supportsType = candType/2;
}
/**
* Holds if all incoming type flow can be traced back to a
* `unionTypeFlowBaseCand`, such that we can compute a union type bound for `n`.
* Disregards nodes for which we have an exact bound.
*/
private predicate hasUnionTypeFlow(TypeFlowNode n) {
not exactType(n, _) and
(
// Optimized version of
// `forex(TypeFlowNode mid | joinStep(mid, n) | unionTypeFlowBaseCand(mid, _, _) or hasUnionTypeFlow(mid))`
ForAll<RankedJoinStep, HasUnionTypePropagation>::flowJoin(n, _)
or
exists(TypeFlowNode scc |
sccRepr(n, scc) and
// Optimized version of
// `forex(TypeFlowNode mid | sccJoinStep(mid, scc) | unionTypeFlowBaseCand(mid, _, _) or hasUnionTypeFlow(mid))`
ForAll<RankedSccJoinStep, HasUnionTypePropagation>::flowJoin(scc, _)
)
or
exists(TypeFlowNode mid | step(mid, n) and hasUnionTypeFlow(mid))
or
instanceofDisjunctionGuarded(n, _)
)
}
pragma[nomagic]
private RefType getTypeBound(TypeFlowNode n) {
bestTypeFlow(n, result)
or
not bestTypeFlow(n, _) and result = n.getType()
}
pragma[nomagic]
private predicate unionTypeFlow0(TypeFlowNode n, RefType t, boolean exact) {
hasUnionTypeFlow(n) and
(
exists(TypeFlowNode mid | anyStep(mid, n) |
unionTypeFlowBaseCand(mid, t, exact) or unionTypeFlow(mid, t, exact)
)
or
instanceofDisjunctionGuarded(n, t) and exact = false
)
}
/** Holds if we have a union type bound for `n` and `t` is one of its parts. */
private predicate unionTypeFlow(TypeFlowNode n, RefType t, boolean exact) {
unionTypeFlow0(n, t, exact) and
// filter impossible union parts:
if exact = true
then t.getErasure().(RefType).getASourceSupertype*() = getTypeBound(n).getErasure()
else haveIntersection(getTypeBound(n), t)
}
/**
* Holds if the inferred union type bound for `n` contains the best universal
* bound and thus is irrelevant.
*/
private predicate irrelevantUnionType(TypeFlowNode n) {
exists(RefType t, RefType nt, RefType te, RefType nte |
unionTypeFlow(n, t, false) and
nt = getTypeBound(n) and
te = t.getErasure() and
nte = nt.getErasure()
|
nt.getASupertype*() = t
or
nte.getASourceSupertype+() = te
or
nte = te and unbound(t)
)
}
/**
* Holds if `t` is an irrelevant part of the union type bound for `n` due to
* being contained in another part of the union type bound.
*/
private predicate irrelevantUnionTypePart(TypeFlowNode n, RefType t, boolean exact) {
unionTypeFlow(n, t, exact) and
not irrelevantUnionType(n) and
exists(RefType weaker |
unionTypeFlow(n, weaker, false) and
t.getASupertype*() = weaker
|
exact = true or not weaker.getASupertype*() = t
)
}
/**
* Holds if the runtime type of `n` is bounded by a union type and if this
* bound is likely to be better than the static type of `n`. The union type is
* made up of the types `t` related to `n` by this predicate, and the flag
* `exact` indicates whether `t` is an exact bound or merely an upper bound.
*/
private predicate bestUnionType(TypeFlowNode n, RefType t, boolean exact) {
unionTypeFlow(n, t, exact) and
not irrelevantUnionType(n) and
not irrelevantUnionTypePart(n, t, exact)
}
cached
private module TypeFlowBounds {
/**
@@ -440,11 +802,7 @@ private module TypeFlowBounds {
predicate fieldTypeFlow(Field f, RefType t, boolean exact) {
exists(TypeFlowNode n |
n.asField() = f and
(
exactType(n, t) and exact = true
or
not exactType(n, _) and bestTypeFlow(n, t) and exact = false
)
bestTypeFlow(n, t, exact)
)
}
@@ -457,11 +815,21 @@ private module TypeFlowBounds {
predicate exprTypeFlow(Expr e, RefType t, boolean exact) {
exists(TypeFlowNode n |
n.asExpr() = e and
(
exactType(n, t) and exact = true
or
not exactType(n, _) and bestTypeFlow(n, t) and exact = false
)
bestTypeFlow(n, t, exact)
)
}
/**
* Holds if the runtime type of `e` is bounded by a union type and if this
* bound is likely to be better than the static type of `e`. The union type is
* made up of the types `t` related to `e` by this predicate, and the flag
* `exact` indicates whether `t` is an exact bound or merely an upper bound.
*/
cached
predicate exprUnionTypeFlow(Expr e, RefType t, boolean exact) {
exists(TypeFlowNode n |
n.asExpr() = e and
bestUnionType(n, t, exact)
)
}
}

View File

@@ -4,11 +4,31 @@ private import DataFlowUtil
private import semmle.code.java.dataflow.InstanceAccess
private import semmle.code.java.dataflow.FlowSummary
private import semmle.code.java.dispatch.VirtualDispatch as VirtualDispatch
private import semmle.code.java.dataflow.TypeFlow
private import semmle.code.java.dispatch.internal.Unification
private module DispatchImpl {
private predicate hasHighConfidenceTarget(Call c) {
exists(SummarizedCallable sc |
sc = c.getCallee().getSourceDeclaration() and not sc.isAutoGenerated()
)
or
exists(Callable srcTgt |
srcTgt = VirtualDispatch::viableCallable(c) and
not VirtualDispatch::lowConfidenceDispatchTarget(c, srcTgt)
)
}
private Callable sourceDispatch(Call c) {
result = VirtualDispatch::viableCallable(c) and
if VirtualDispatch::lowConfidenceDispatchTarget(c, result)
then not hasHighConfidenceTarget(c)
else any()
}
/** Gets a viable implementation of the target of the given `Call`. */
DataFlowCallable viableCallable(DataFlowCall c) {
result.asCallable() = VirtualDispatch::viableCallable(c.asCall())
result.asCallable() = sourceDispatch(c.asCall())
or
result.asSummarizedCallable() = c.asCall().getCallee().getSourceDeclaration()
}
@@ -20,7 +40,7 @@ private module DispatchImpl {
*/
private predicate mayBenefitFromCallContext(MethodAccess ma, Callable c, int i) {
exists(Parameter p |
2 <= strictcount(VirtualDispatch::viableImpl(ma)) and
2 <= strictcount(sourceDispatch(ma)) and
ma.getQualifier().(VarAccess).getVariable() = p and
p.getPosition() = i and
c.getAParameter() = p and
@@ -29,7 +49,7 @@ private module DispatchImpl {
)
or
exists(OwnInstanceAccess ia |
2 <= strictcount(VirtualDispatch::viableImpl(ma)) and
2 <= strictcount(sourceDispatch(ma)) and
(ia.isExplicit(ma.getQualifier()) or ia.isImplicitMethodQualifier(ma)) and
i = -1 and
c = ma.getEnclosingCallable()
@@ -45,7 +65,7 @@ private module DispatchImpl {
private predicate relevantContext(Call ctx, int i) {
exists(Callable c |
mayBenefitFromCallContext(_, c, i) and
c = VirtualDispatch::viableCallable(ctx)
c = sourceDispatch(ctx)
)
}
@@ -62,15 +82,21 @@ private module DispatchImpl {
private predicate contextArgHasType(Call ctx, int i, RefType t, boolean exact) {
relevantContext(ctx, i) and
exists(RefType srctype |
exists(Expr arg, Expr src |
exists(Expr arg |
i = -1 and
ctx.getQualifier() = arg
or
ctx.getArgument(i) = arg
|
src = VirtualDispatch::variableTrack(arg) and
srctype = getPreciseType(src) and
if src instanceof ClassInstanceExpr then exact = true else exact = false
exprTypeFlow(arg, srctype, exact)
or
not exprTypeFlow(arg, _, _) and
exprUnionTypeFlow(arg, srctype, exact)
or
not exprTypeFlow(arg, _, _) and
not exprUnionTypeFlow(arg, _, _) and
srctype = getPreciseType(arg) and
if arg instanceof ClassInstanceExpr then exact = true else exact = false
)
or
exists(Node arg |
@@ -115,74 +141,20 @@ private module DispatchImpl {
exact = false and
exists(RefType t2 |
result.asCallable() = VirtualDispatch::viableMethodImpl(def, t.getSourceDeclaration(), t2) and
not failsUnification(t, t2)
not Unification::failsUnification(t, t2)
)
or
result.asSummarizedCallable() = def
)
}
pragma[noinline]
private predicate unificationTargetLeft(ParameterizedType t1, GenericType g) {
contextArgHasType(_, _, t1, _) and t1.getGenericType() = g
private predicate unificationTargetLeft(ParameterizedType t1) { contextArgHasType(_, _, t1, _) }
private predicate unificationTargetRight(ParameterizedType t2) {
exists(VirtualDispatch::viableMethodImpl(_, _, t2))
}
pragma[noinline]
private predicate unificationTargetRight(ParameterizedType t2, GenericType g) {
exists(VirtualDispatch::viableMethodImpl(_, _, t2)) and t2.getGenericType() = g
}
private predicate unificationTargets(Type t1, Type t2) {
exists(GenericType g | unificationTargetLeft(t1, g) and unificationTargetRight(t2, g))
or
exists(Array a1, Array a2 |
unificationTargets(a1, a2) and
t1 = a1.getComponentType() and
t2 = a2.getComponentType()
)
or
exists(ParameterizedType pt1, ParameterizedType pt2, int pos |
unificationTargets(pt1, pt2) and
not pt1.getSourceDeclaration() != pt2.getSourceDeclaration() and
t1 = pt1.getTypeArgument(pos) and
t2 = pt2.getTypeArgument(pos)
)
}
pragma[noinline]
private predicate typeArgsOfUnificationTargets(
ParameterizedType t1, ParameterizedType t2, int pos, RefType arg1, RefType arg2
) {
unificationTargets(t1, t2) and
arg1 = t1.getTypeArgument(pos) and
arg2 = t2.getTypeArgument(pos)
}
private predicate failsUnification(Type t1, Type t2) {
unificationTargets(t1, t2) and
(
exists(RefType arg1, RefType arg2 |
typeArgsOfUnificationTargets(t1, t2, _, arg1, arg2) and
failsUnification(arg1, arg2)
)
or
failsUnification(t1.(Array).getComponentType(), t2.(Array).getComponentType())
or
not (
t1 instanceof Array and t2 instanceof Array
or
t1.(PrimitiveType) = t2.(PrimitiveType)
or
t1.(Class).getSourceDeclaration() = t2.(Class).getSourceDeclaration()
or
t1.(Interface).getSourceDeclaration() = t2.(Interface).getSourceDeclaration()
or
t1 instanceof BoundedType and t2 instanceof RefType
or
t1 instanceof RefType and t2 instanceof BoundedType
)
)
}
private module Unification = MkUnification<unificationTargetLeft/1, unificationTargetRight/1>;
private int parameterPosition() { result in [-1, any(Parameter p).getPosition()] }

View File

@@ -226,15 +226,6 @@ module Public {
none()
}
/**
* Holds if values stored inside `content` are cleared on objects passed as
* arguments at position `pos` to this callable.
*
* TODO: Remove once all languages support `WithoutContent` tokens.
*/
pragma[nomagic]
predicate clearsContent(ParameterPosition pos, ContentSet content) { none() }
/**
* Holds if the summary is auto generated.
*/
@@ -328,23 +319,6 @@ module Private {
SummaryComponentStack::singleton(TArgumentSummaryComponent(_))) and
preservesValue = preservesValue1.booleanAnd(preservesValue2)
)
or
exists(ParameterPosition ppos, ContentSet cs |
c.clearsContent(ppos, cs) and
input = SummaryComponentStack::push(SummaryComponent::withoutContent(cs), output) and
output = SummaryComponentStack::argument(ppos) and
preservesValue = true
)
}
private class MkClearStack extends RequiredSummaryComponentStack {
override predicate required(SummaryComponent head, SummaryComponentStack tail) {
exists(SummarizedCallable sc, ParameterPosition ppos, ContentSet cs |
sc.clearsContent(ppos, cs) and
head = SummaryComponent::withoutContent(cs) and
tail = SummaryComponentStack::argument(ppos)
)
}
}
/**
@@ -945,8 +919,7 @@ module Private {
AccessPath inSpec, AccessPath outSpec, string kind
) {
summaryElement(this, inSpec, outSpec, kind, true) and
not summaryElement(this, _, _, _, false) and
not this.clearsContent(_, _)
not summaryElement(this, _, _, _, false)
}
private predicate relevantSummaryElement(AccessPath inSpec, AccessPath outSpec, string kind) {

View File

@@ -0,0 +1,9 @@
/** Provides modules for importing negative summaries. */
/**
* A module importing the frameworks that provide external flow data,
* ensuring that they are visible to the taint tracking / data flow library.
*/
private module Frameworks {
private import semmle.code.java.frameworks.GeneratedNegative
}

View File

@@ -251,7 +251,7 @@ private predicate qualifierToArgumentStep(Expr tracked, Expr sink) {
/** Access to a method that passes taint from the qualifier. */
private predicate qualifierToMethodStep(Expr tracked, MethodAccess sink) {
(taintPreservingQualifierToMethod(sink.getMethod()) or unsafeEscape(sink)) and
taintPreservingQualifierToMethod(sink.getMethod()) and
tracked = sink.getQualifier()
}
@@ -282,28 +282,6 @@ private predicate taintPreservingQualifierToMethod(Method m) {
)
}
private class StringReplaceMethod extends TaintPreservingCallable {
StringReplaceMethod() {
this.getDeclaringType() instanceof TypeString and
(
this.hasName("replace") or
this.hasName("replaceAll") or
this.hasName("replaceFirst")
)
}
override predicate returnsTaintFrom(int arg) { arg = 1 }
}
private predicate unsafeEscape(MethodAccess ma) {
// Removing `<script>` tags using a string-replace method is
// unsafe if such a tag is embedded inside another one (e.g. `<scr<script>ipt>`).
exists(StringReplaceMethod m | ma.getMethod() = m |
ma.getArgument(0).(StringLiteral).getValue() = "(<script>)" and
ma.getArgument(1).(StringLiteral).getValue() = ""
)
}
/** Access to a method that passes taint from an argument. */
private predicate argToMethodStep(Expr tracked, MethodAccess sink) {
exists(Method m, int i |

View File

@@ -172,7 +172,12 @@ abstract class Configuration extends DataFlow::Configuration {
}
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
(
this.isSink(node) or
this.isSink(node, _) or
this.isAdditionalTaintStep(node, _) or
this.isAdditionalTaintStep(node, _, _, _)
) and
defaultImplicitTaintRead(node, c)
}

View File

@@ -172,7 +172,12 @@ abstract class Configuration extends DataFlow::Configuration {
}
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
(
this.isSink(node) or
this.isSink(node, _) or
this.isAdditionalTaintStep(node, _) or
this.isAdditionalTaintStep(node, _, _, _)
) and
defaultImplicitTaintRead(node, c)
}

View File

@@ -172,7 +172,12 @@ abstract class Configuration extends DataFlow::Configuration {
}
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
(
this.isSink(node) or
this.isSink(node, _) or
this.isAdditionalTaintStep(node, _) or
this.isAdditionalTaintStep(node, _, _, _)
) and
defaultImplicitTaintRead(node, c)
}

View File

@@ -162,7 +162,7 @@ class LiveClass extends SourceClassOrInterface {
exists(LiveField f | f.getDeclaringType() = this |
// A `serialVersionUID` field is considered to be a live field, but is
// not be enough to be make this class live.
not f instanceof SerialVersionUIDField
not f instanceof SerialVersionUidField
)
or
// If this is a namespace class, it is live if there is at least one live nested class.
@@ -250,7 +250,7 @@ class DeadMethod extends Callable {
// These getters and setters are often generated in an ad-hoc way by the developer, which leads to
// methods that are theoretically dead, but uninteresting. We therefore ignore them, so long as
// they are "simple".
not exists(JPAReadField readField | this.getDeclaringType() = readField.getDeclaringType() |
not exists(JpaReadField readField | this.getDeclaringType() = readField.getDeclaringType() |
this.(GetterMethod).getField() = readField or
this.(SetterMethod).getField() = readField
)

View File

@@ -87,8 +87,8 @@ abstract class WhitelistedLiveField extends Field { }
* A static, final, long field named `serialVersionUID` in a class that extends `Serializable` acts as
* a version number for the serialization framework.
*/
class SerialVersionUIDField extends ReflectivelyReadField {
SerialVersionUIDField() {
class SerialVersionUidField extends ReflectivelyReadField {
SerialVersionUidField() {
this.hasName("serialVersionUID") and
this.isStatic() and
this.isFinal() and
@@ -97,6 +97,9 @@ class SerialVersionUIDField extends ReflectivelyReadField {
}
}
/** DEPRECATED: Alias for SerialVersionUidField */
deprecated class SerialVersionUIDField = SerialVersionUidField;
/**
* A field is read by the JAXB during serialization if it is a JAXB bound field, and if the
* containing class is considered "live".
@@ -154,8 +157,8 @@ class JacksonMixinReflextivelyReadField extends ReflectivelyReadField {
/**
* A field which is read by a JPA compatible Java persistence framework.
*/
class JPAReadField extends ReflectivelyReadField {
JPAReadField() {
class JpaReadField extends ReflectivelyReadField {
JpaReadField() {
exists(PersistentEntity entity |
this = entity.getAField() and
(
@@ -169,3 +172,6 @@ class JPAReadField extends ReflectivelyReadField {
)
}
}
/** DEPRECATED: Alias for JpaReadField */
deprecated class JPAReadField = JpaReadField;

View File

@@ -128,8 +128,9 @@ class JacksonMixinCallableEntryPoint extends EntryPoint {
override Callable getALiveCallable() { result = this }
}
class JAXAnnotationReflectivelyConstructedClass extends ReflectivelyConstructedClass {
JAXAnnotationReflectivelyConstructedClass() {
/** A JAX annotation seen as a reflectively constructed class. */
class JaxAnnotationReflectivelyConstructedClass extends ReflectivelyConstructedClass {
JaxAnnotationReflectivelyConstructedClass() {
this instanceof JaxWsEndpoint or
this instanceof JaxbXmlRegistry or
this instanceof JaxRsResourceClass or
@@ -137,6 +138,10 @@ class JAXAnnotationReflectivelyConstructedClass extends ReflectivelyConstructedC
}
}
/** DEPRECATED: Alias for JaxAnnotationReflectivelyConstructedClass */
deprecated class JAXAnnotationReflectivelyConstructedClass =
JaxAnnotationReflectivelyConstructedClass;
class DeserializedClass extends ReflectivelyConstructedClass {
DeserializedClass() {
exists(CastingExpr cast, ReadObjectMethod readObject |
@@ -342,8 +347,9 @@ class GsonDeserializationEntryPoint extends ReflectivelyConstructedClass {
}
}
class JAXBDeserializationEntryPoint extends ReflectivelyConstructedClass {
JAXBDeserializationEntryPoint() {
/** A JAXB deserialization entry point seen as a reflectively constructed class. */
class JaxbDeserializationEntryPoint extends ReflectivelyConstructedClass {
JaxbDeserializationEntryPoint() {
// A class can be deserialized by JAXB if it's an `XmlRootElement`...
this.getAnAnnotation().getType().hasQualifiedName("javax.xml.bind.annotation", "XmlRootElement")
or
@@ -356,6 +362,9 @@ class JAXBDeserializationEntryPoint extends ReflectivelyConstructedClass {
}
}
/** DEPRECATED: Alias for JaxbDeserializationEntryPoint */
deprecated class JAXBDeserializationEntryPoint = JaxbDeserializationEntryPoint;
/**
* A `javax.annotation` for a method that is called after or before dependency injection on a type.
*

View File

@@ -104,8 +104,8 @@ class SpringAspect extends CallableEntryPoint {
/**
* Spring Shell provides annotations for identifying methods that contribute CLI commands.
*/
class SpringCLI extends CallableEntryPoint {
SpringCLI() {
class SpringCli extends CallableEntryPoint {
SpringCli() {
(
hasAnnotation("org.springframework.shell.core.annotation", "CliCommand") or
hasAnnotation("org.springframework.shell.core.annotation", "CliAvailabilityIndicator")
@@ -116,6 +116,9 @@ class SpringCLI extends CallableEntryPoint {
}
}
/** DEPRECATED: Alias for SpringCli */
deprecated class SpringCLI = SpringCli;
/**
* An entry point which acts as a remote API for a Flex application to access a Spring application.
*/

View File

@@ -58,15 +58,18 @@ class ServletFilterClass extends ReflectivelyConstructedClass {
/**
* An entry point into a GWT application.
*/
class GWTEntryPointConstructedClass extends ReflectivelyConstructedClass {
GWTEntryPointConstructedClass() { this.(GwtEntryPointClass).isLive() }
class GwtEntryPointConstructedClass extends ReflectivelyConstructedClass {
GwtEntryPointConstructedClass() { this.(GwtEntryPointClass).isLive() }
}
/** DEPRECATED: Alias for GwtEntryPointConstructedClass */
deprecated class GWTEntryPointConstructedClass = GwtEntryPointConstructedClass;
/**
* Servlets referred to from a GWT module config file.
*/
class GWTServletClass extends ReflectivelyConstructedClass {
GWTServletClass() {
class GwtServletClass extends ReflectivelyConstructedClass {
GwtServletClass() {
this instanceof ServletClass and
// There must be evidence that GWT is being used, otherwise missing `*.gwt.xml` files could cause
// all `Servlet`s to be live.
@@ -81,6 +84,9 @@ class GWTServletClass extends ReflectivelyConstructedClass {
}
}
/** DEPRECATED: Alias for GwtServletClass */
deprecated class GWTServletClass = GwtServletClass;
/**
* Methods that may be called reflectively by the UiHandler framework.
*/

View File

@@ -15,6 +15,7 @@ private import semmle.code.java.dataflow.internal.DataFlowUtil
private import semmle.code.java.dataflow.internal.DataFlowPrivate
private import semmle.code.java.dataflow.internal.ContainerFlow
private import semmle.code.java.dataflow.InstanceAccess
private import semmle.code.java.dispatch.internal.Unification
/**
* Gets a viable dispatch target for `ma`. This is the input dispatch relation.
@@ -266,67 +267,10 @@ Method viableImpl_out(MethodAccess ma) {
)
}
private module Unification {
pragma[noinline]
private predicate unificationTargetLeft(ParameterizedType t1, GenericType g) {
objectToStringQualType(_, t1) and t1.getGenericType() = g
}
private predicate unificationTargetLeft(ParameterizedType t1) { objectToStringQualType(_, t1) }
pragma[noinline]
private predicate unificationTargetRight(ParameterizedType t2, GenericType g) {
exists(viableMethodImpl(_, _, t2)) and t2.getGenericType() = g
}
private predicate unificationTargets(Type t1, Type t2) {
exists(GenericType g | unificationTargetLeft(t1, g) and unificationTargetRight(t2, g))
or
exists(Array a1, Array a2 |
unificationTargets(a1, a2) and
t1 = a1.getComponentType() and
t2 = a2.getComponentType()
)
or
exists(ParameterizedType pt1, ParameterizedType pt2, int pos |
unificationTargets(pt1, pt2) and
not pt1.getSourceDeclaration() != pt2.getSourceDeclaration() and
t1 = pt1.getTypeArgument(pos) and
t2 = pt2.getTypeArgument(pos)
)
}
pragma[noinline]
private predicate typeArgsOfUnificationTargets(
ParameterizedType t1, ParameterizedType t2, int pos, RefType arg1, RefType arg2
) {
unificationTargets(t1, t2) and
arg1 = t1.getTypeArgument(pos) and
arg2 = t2.getTypeArgument(pos)
}
pragma[nomagic]
predicate failsUnification(Type t1, Type t2) {
unificationTargets(t1, t2) and
(
exists(RefType arg1, RefType arg2 |
typeArgsOfUnificationTargets(t1, t2, _, arg1, arg2) and
failsUnification(arg1, arg2)
)
or
failsUnification(t1.(Array).getComponentType(), t2.(Array).getComponentType())
or
not (
t1 instanceof Array and t2 instanceof Array
or
t1.(PrimitiveType) = t2.(PrimitiveType)
or
t1.(Class).getSourceDeclaration() = t2.(Class).getSourceDeclaration()
or
t1.(Interface).getSourceDeclaration() = t2.(Interface).getSourceDeclaration()
or
t1 instanceof BoundedType and t2 instanceof RefType
or
t1 instanceof RefType and t2 instanceof BoundedType
)
)
}
private predicate unificationTargetRight(ParameterizedType t2) {
exists(viableMethodImpl(_, _, t2))
}
private module Unification = MkUnification<unificationTargetLeft/1, unificationTargetRight/1>;

View File

@@ -9,6 +9,7 @@ private import DispatchFlow as DispatchFlow
private import ObjFlow as ObjFlow
private import semmle.code.java.dataflow.internal.BaseSSA
private import semmle.code.java.controlflow.Guards
private import semmle.code.java.dispatch.internal.Unification
/**
* A conservative analysis that returns a single method - if we can establish
@@ -53,6 +54,16 @@ private module Dispatch {
cached
Method viableImpl(MethodAccess ma) { result = ObjFlow::viableImpl_out(ma) }
/**
* Holds if `m` is a viable implementation of the method called in `ma` for
* which we only have imprecise open-world type-based dispatch resolution, and
* the dispatch type is likely to yield implausible dispatch targets.
*/
cached
predicate lowConfidenceDispatchTarget(MethodAccess ma, Method m) {
m = viableImpl(ma) and lowConfidenceDispatch(ma)
}
/**
* INTERNAL: Use `viableImpl` instead.
*
@@ -61,8 +72,42 @@ private module Dispatch {
cached
Method viableImpl_v3(MethodAccess ma) { result = DispatchFlow::viableImpl_out(ma) }
private predicate qualType(VirtualMethodAccess ma, RefType t, boolean exact) {
exprTypeFlow(ma.getQualifier(), t, exact)
/**
* Holds if the best type bounds for the qualifier of `ma` are likely to
* contain implausible dispatch targets.
*/
private predicate lowConfidenceDispatch(VirtualMethodAccess ma) {
exists(RefType t | hasQualifierType(ma, t, false) |
lowConfidenceDispatchType(t.getSourceDeclaration())
) and
(
not qualType(ma, _, _)
or
exists(RefType t | qualType(ma, t, false) |
lowConfidenceDispatchType(t.getSourceDeclaration())
)
) and
(
not qualUnionType(ma, _, _)
or
exists(RefType t | qualUnionType(ma, t, false) |
lowConfidenceDispatchType(t.getSourceDeclaration())
)
)
}
private predicate lowConfidenceDispatchType(SrcRefType t) {
t instanceof TypeObject
or
t instanceof FunctionalInterface
or
t.hasQualifiedName("java.io", "Serializable")
or
t.hasQualifiedName("java.lang", "Cloneable")
or
t.getPackage().hasName("java.util") and t instanceof Interface
or
t.hasQualifiedName("java.util", "Hashtable")
}
/**
@@ -72,6 +117,35 @@ private module Dispatch {
*/
cached
Method viableImpl_v2(MethodAccess ma) {
result = viableImpl_v2_cand(pragma[only_bind_into](ma)) and
exists(Method def, RefType t, boolean exact |
qualUnionType(pragma[only_bind_into](ma), pragma[only_bind_into](t),
pragma[only_bind_into](exact)) and
def = ma.getMethod().getSourceDeclaration()
|
exact = true and result = exactMethodImpl(def, t.getSourceDeclaration())
or
exact = false and
exists(RefType t2 |
result = viableMethodImpl(def, t.getSourceDeclaration(), t2) and
not Unification_v2::failsUnification(t, t2)
)
)
or
result = viableImpl_v2_cand(ma) and
not qualUnionType(ma, _, _)
}
private predicate qualUnionType(VirtualMethodAccess ma, RefType t, boolean exact) {
exprUnionTypeFlow(ma.getQualifier(), t, exact)
}
private predicate unificationTargetLeft_v2(ParameterizedType t1) { qualUnionType(_, t1, _) }
private module Unification_v2 =
MkUnification<unificationTargetLeft_v2/1, unificationTargetRight/1>;
private Method viableImpl_v2_cand(MethodAccess ma) {
result = viableImpl_v1(ma) and
(
exists(Method def, RefType t, boolean exact |
@@ -83,7 +157,7 @@ private module Dispatch {
exact = false and
exists(RefType t2 |
result = viableMethodImpl(def, t.getSourceDeclaration(), t2) and
not Unification_v2::failsUnification(t, t2)
not Unification_v2_cand::failsUnification(t, t2)
)
)
or
@@ -91,70 +165,15 @@ private module Dispatch {
)
}
private module Unification_v2 {
pragma[noinline]
private predicate unificationTargetLeft(ParameterizedType t1, GenericType g) {
qualType(_, t1, _) and t1.getGenericType() = g
}
pragma[noinline]
private predicate unificationTargetRight(ParameterizedType t2, GenericType g) {
exists(viableMethodImpl(_, _, t2)) and t2.getGenericType() = g
}
private predicate unificationTargets(Type t1, Type t2) {
exists(GenericType g | unificationTargetLeft(t1, g) and unificationTargetRight(t2, g))
or
exists(Array a1, Array a2 |
unificationTargets(a1, a2) and
t1 = a1.getComponentType() and
t2 = a2.getComponentType()
)
or
exists(ParameterizedType pt1, ParameterizedType pt2, int pos |
unificationTargets(pt1, pt2) and
not pt1.getSourceDeclaration() != pt2.getSourceDeclaration() and
t1 = pt1.getTypeArgument(pos) and
t2 = pt2.getTypeArgument(pos)
)
}
pragma[noinline]
private predicate typeArgsOfUnificationTargets(
ParameterizedType t1, ParameterizedType t2, int pos, RefType arg1, RefType arg2
) {
unificationTargets(t1, t2) and
arg1 = t1.getTypeArgument(pos) and
arg2 = t2.getTypeArgument(pos)
}
predicate failsUnification(Type t1, Type t2) {
unificationTargets(t1, t2) and
(
exists(RefType arg1, RefType arg2 |
typeArgsOfUnificationTargets(t1, t2, _, arg1, arg2) and
failsUnification(arg1, arg2)
)
or
failsUnification(t1.(Array).getComponentType(), t2.(Array).getComponentType())
or
not (
t1 instanceof Array and t2 instanceof Array
or
t1.(PrimitiveType) = t2.(PrimitiveType)
or
t1.(Class).getSourceDeclaration() = t2.(Class).getSourceDeclaration()
or
t1.(Interface).getSourceDeclaration() = t2.(Interface).getSourceDeclaration()
or
t1 instanceof BoundedType and t2 instanceof RefType
or
t1 instanceof RefType and t2 instanceof BoundedType
)
)
}
private predicate qualType(VirtualMethodAccess ma, RefType t, boolean exact) {
exprTypeFlow(ma.getQualifier(), t, exact)
}
private predicate unificationTargetLeft_v2_cand(ParameterizedType t1) { qualType(_, t1, _) }
private module Unification_v2_cand =
MkUnification<unificationTargetLeft_v2_cand/1, unificationTargetRight/1>;
/**
* INTERNAL: Use `viableImpl` instead.
*
@@ -203,70 +222,15 @@ private module Dispatch {
else result = source.getMethod().getSourceDeclaration()
}
private module Unification_v1 {
pragma[noinline]
private predicate unificationTargetLeft(ParameterizedType t1, GenericType g) {
hasQualifierType(_, t1, _) and t1.getGenericType() = g
}
private predicate unificationTargetLeft_v1(ParameterizedType t1) { hasQualifierType(_, t1, _) }
pragma[noinline]
private predicate unificationTargetRight(ParameterizedType t2, GenericType g) {
exists(viableMethodImpl(_, _, t2)) and t2.getGenericType() = g
}
private predicate unificationTargets(Type t1, Type t2) {
exists(GenericType g | unificationTargetLeft(t1, g) and unificationTargetRight(t2, g))
or
exists(Array a1, Array a2 |
unificationTargets(a1, a2) and
t1 = a1.getComponentType() and
t2 = a2.getComponentType()
)
or
exists(ParameterizedType pt1, ParameterizedType pt2, int pos |
unificationTargets(pt1, pt2) and
not pt1.getSourceDeclaration() != pt2.getSourceDeclaration() and
t1 = pt1.getTypeArgument(pos) and
t2 = pt2.getTypeArgument(pos)
)
}
pragma[noinline]
private predicate typeArgsOfUnificationTargets(
ParameterizedType t1, ParameterizedType t2, int pos, RefType arg1, RefType arg2
) {
unificationTargets(t1, t2) and
arg1 = t1.getTypeArgument(pos) and
arg2 = t2.getTypeArgument(pos)
}
predicate failsUnification(Type t1, Type t2) {
unificationTargets(t1, t2) and
(
exists(RefType arg1, RefType arg2 |
typeArgsOfUnificationTargets(t1, t2, _, arg1, arg2) and
failsUnification(arg1, arg2)
)
or
failsUnification(t1.(Array).getComponentType(), t2.(Array).getComponentType())
or
not (
t1 instanceof Array and t2 instanceof Array
or
t1.(PrimitiveType) = t2.(PrimitiveType)
or
t1.(Class).getSourceDeclaration() = t2.(Class).getSourceDeclaration()
or
t1.(Interface).getSourceDeclaration() = t2.(Interface).getSourceDeclaration()
or
t1 instanceof BoundedType and t2 instanceof RefType
or
t1 instanceof RefType and t2 instanceof BoundedType
)
)
}
private predicate unificationTargetRight(ParameterizedType t2) {
exists(viableMethodImpl(_, _, t2))
}
private module Unification_v1 =
MkUnification<unificationTargetLeft_v1/1, unificationTargetRight/1>;
private RefType getPreciseType(Expr e) {
result = e.(FunctionalExpr).getConstructedType()
or
@@ -274,9 +238,8 @@ private module Dispatch {
}
private predicate hasQualifierType(VirtualMethodAccess ma, RefType t, boolean exact) {
exists(Expr src | src = variableTrack(ma.getQualifier()) |
// If we have a qualifier, then we track it through variable assignments
// and take the type of the assigned value.
exists(Expr src | src = ma.getQualifier() |
// If we have a qualifier, then we take its type.
exists(RefType srctype | srctype = getPreciseType(src) |
exists(BoundedType bd | bd = srctype |
t = bd.getAnUltimateUpperBoundType()
@@ -324,43 +287,20 @@ private module Dispatch {
exists(Method m | t.hasMethod(m, _, _) and impl = m.getSourceDeclaration())
}
private predicate isAbstractWithSubclass(SrcRefType t) {
t.isAbstract() and exists(Class c | c.getASourceSupertype() = t)
}
private predicate hasViableSubtype(RefType t, SrcRefType sub) {
sub.extendsOrImplements*(t) and
not sub instanceof Interface and
not sub.isAbstract()
not isAbstractWithSubclass(sub)
}
}
import Dispatch
private Expr variableTrackStep(Expr use) {
exists(Variable v |
pragma[only_bind_out](use) = v.getAnAccess() and
use.getType() instanceof RefType and
not result instanceof NullLiteral and
not v.(LocalVariableDecl).getDeclExpr().hasImplicitInit()
|
not v instanceof Parameter and
result = v.getAnAssignedValue()
or
exists(Parameter p | p = v and p.getCallable().isPrivate() |
result = p.getAnAssignedValue() or
result = p.getAnArgument()
)
)
}
private Expr variableTrackPath(Expr use) {
result = variableTrackStep*(use) and
not exists(variableTrackStep(result))
}
/**
* Gets an expression by tracking `use` backwards through variable assignments.
* DEPRECATED: Use `TypeFlow` instead.
*/
pragma[inline]
Expr variableTrack(Expr use) {
result = variableTrackPath(use)
or
not exists(variableTrackPath(use)) and result = use
}
deprecated Expr variableTrack(Expr use) { result = use }

View File

@@ -0,0 +1,136 @@
/**
* Provides a module to check whether two `ParameterizedType`s are unifiable.
*/
import java
/** Holds if `t` is a relevant type to consider for unification. */
signature predicate unificationTarget(ParameterizedType t);
/**
* Given two sets of parameterised types to consider for unification, returns
* the set of pairs that are not unifiable.
*/
module MkUnification<unificationTarget/1 targetLeft, unificationTarget/1 targetRight> {
pragma[noinline]
private predicate unificationTargetLeft(ParameterizedType t1, GenericType g) {
targetLeft(t1) and t1.getGenericType() = g
}
pragma[noinline]
private predicate unificationTargetRight(ParameterizedType t2, GenericType g) {
targetRight(t2) and t2.getGenericType() = g
}
private predicate unificationTargets(Type t1, Type t2) {
exists(GenericType g | unificationTargetLeft(t1, g) and unificationTargetRight(t2, g))
or
exists(Array a1, Array a2 |
unificationTargets(a1, a2) and
t1 = a1.getComponentType() and
t2 = a2.getComponentType()
)
or
exists(ParameterizedType pt1, ParameterizedType pt2, int pos |
unificationTargets(pt1, pt2) and
not pt1.getSourceDeclaration() != pt2.getSourceDeclaration() and
t1 = pt1.getTypeArgument(pos) and
t2 = pt2.getTypeArgument(pos)
)
}
pragma[noinline]
private predicate typeArgsOfUnificationTargets(
ParameterizedType t1, ParameterizedType t2, int pos, RefType arg1, RefType arg2
) {
unificationTargets(t1, t2) and
arg1 = t1.getTypeArgument(pos) and
arg2 = t2.getTypeArgument(pos)
}
private RefType getUpperBound(RefType t) {
if t instanceof BoundedType
then result = t.(BoundedType).getAnUltimateUpperBoundType()
else result = t
}
/**
* Holds if `t1` and `t2` are not unifiable.
*
* Restricted to only consider pairs of types such that `targetLeft(t1)`,
* `targetRight(t2)`, and that both are parameterised instances of the same
* generic type.
*/
pragma[nomagic]
predicate failsUnification(Type t1, Type t2) {
unificationTargets(t1, t2) and
(
exists(RefType arg1, RefType arg2 |
typeArgsOfUnificationTargets(t1, t2, _, arg1, arg2) and
failsUnification(arg1, arg2)
)
or
failsUnification(t1.(Array).getComponentType(), t2.(Array).getComponentType())
or
// Can't unify an `extends` bound against a concrete type that doesn't
// descend from that upper bound:
exists(RefType upperbound, RefType other |
t1.(BoundedType).getAnUltimateUpperBoundType().getSourceDeclaration() = upperbound and
t2.(RefType).getSourceDeclaration() = other and
not t2 instanceof BoundedType
or
t2.(BoundedType).getAnUltimateUpperBoundType().getSourceDeclaration() = upperbound and
t1.(RefType).getSourceDeclaration() = other and
not t1 instanceof BoundedType
|
not other.getASourceSupertype*() = upperbound
)
or
// Can't unify two `extends` bounds that don't intersect:
exists(RefType upperbound1, RefType upperbound2 |
t1.(BoundedType).getAnUltimateUpperBoundType() = upperbound1 and
t2.(BoundedType).getAnUltimateUpperBoundType() = upperbound2 and
notHaveIntersection(upperbound1, upperbound2)
)
or
// Can't unify `? super X` against `Y` or `_ extends Y` where `Y` isn't an
// ancestor of `X`:
exists(RefType lowerbound, RefType upperbound |
t1.(Wildcard).getLowerBoundType().(RefType).getSourceDeclaration() = lowerbound and
getUpperBound(t2).getSourceDeclaration() = upperbound
or
t2.(Wildcard).getLowerBoundType().(RefType).getSourceDeclaration() = lowerbound and
getUpperBound(t1).getSourceDeclaration() = upperbound
|
not lowerbound instanceof BoundedType and
not lowerbound.getASourceSupertype*() = upperbound
)
or
// Can't unify `? super T`, where `T` is a type variable `T extends S`,
// with a type that doesn't intersect with `S`:
exists(BoundedType lowerbound, RefType upperbound |
t1.(Wildcard).getLowerBoundType() = lowerbound and
getUpperBound(t2) = upperbound
or
t2.(Wildcard).getLowerBoundType() = lowerbound and
getUpperBound(t1) = upperbound
|
notHaveIntersection(lowerbound.getUpperBoundType(), upperbound)
)
or
not (
t1 instanceof Array and t2 instanceof Array
or
t1.(PrimitiveType) = t2.(PrimitiveType)
or
t1.(Class).getSourceDeclaration() = t2.(Class).getSourceDeclaration()
or
t1.(Interface).getSourceDeclaration() = t2.(Interface).getSourceDeclaration()
or
t1 instanceof BoundedType and t2 instanceof RefType
or
t1 instanceof RefType and t2 instanceof BoundedType
)
)
}
}

View File

@@ -13,7 +13,7 @@ import semmle.code.java.frameworks.camel.CamelJavaAnnotations
class CamelToUri extends string {
CamelToUri() {
exists(SpringCamelXmlToElement toXmlElement | this = toXmlElement.getUri()) or
exists(CamelJavaDSLToDecl toJavaDSL | this = toJavaDSL.getUri())
exists(CamelJavaDslToDecl toJavaDsl | this = toJavaDsl.getUri())
}
}
@@ -77,13 +77,13 @@ class CamelTargetClass extends Class {
this = xmlMethod.getBeanType()
)
or
exists(CamelJavaDSLMethodDecl methodDecl | this = methodDecl.getABean())
exists(CamelJavaDslMethodDecl methodDecl | this = methodDecl.getABean())
or
// Any beans referred to in Java DSL bean or beanRef elements are considered as possible
// targets. Whether the route builder is ever constructed or called is not considered.
exists(CamelJavaDSLBeanDecl beanDecl | this = beanDecl.getABeanClass())
exists(CamelJavaDslBeanDecl beanDecl | this = beanDecl.getABeanClass())
or
exists(CamelJavaDSLBeanRefDecl beanRefDecl | this = beanRefDecl.getABeanClass())
exists(CamelJavaDslBeanRefDecl beanRefDecl | this = beanRefDecl.getABeanClass())
}
/**

View File

@@ -0,0 +1,8 @@
/** Provides a module for importing negative models. */
/**
* A module importing all generated negative Models as Data models.
*/
private module GeneratedFrameworks {
private import apache.NegativeIOGenerated
}

View File

@@ -2,20 +2,26 @@
import semmle.code.java.Type
library class JAXBElement extends Class {
JAXBElement() {
library class JaxbElement extends Class {
JaxbElement() {
this.getAnAncestor().getQualifiedName() = "javax.xml.bind.JAXBElement" or
this.getAnAnnotation().getType().getName() = "XmlRootElement"
}
}
library class JAXBMarshalMethod extends Method {
JAXBMarshalMethod() {
/** DEPRECATED: Alias for JaxbElement */
deprecated class JAXBElement = JaxbElement;
library class JaxbMarshalMethod extends Method {
JaxbMarshalMethod() {
this.getDeclaringType().getQualifiedName() = "javax.xml.bind.Marshaller" and
this.getName() = "marshal"
}
}
/** DEPRECATED: Alias for JaxbMarshalMethod */
deprecated class JAXBMarshalMethod = JaxbMarshalMethod;
class JaxbAnnotationType extends AnnotationType {
JaxbAnnotationType() { this.getPackage().getName() = "javax.xml.bind.annotation" }
}
@@ -54,7 +60,7 @@ class JaxbType extends Class {
this.getAnAnnotation() = a and
a.getType().(JaxbAnnotationType).hasName("XmlAccessorType")
|
result.getAnAccess() = a.getValue("value")
result = a.getEnumConstantValue("value")
)
}

View File

@@ -64,5 +64,5 @@ class RunWithAnnotation extends Annotation {
/**
* Gets the runner that will be used.
*/
Type getRunner() { result = this.getValue("value").(TypeLiteral).getReferencedType() }
Type getRunner() { result = this.getTypeValue("value") }
}

View File

@@ -296,11 +296,7 @@ class JaxRSProducesAnnotation extends JaxRSAnnotation {
/**
* Gets a declared content type that can be produced by this resource.
*/
Expr getADeclaredContentTypeExpr() {
result = this.getAValue() and not result instanceof ArrayInit
or
result = this.getAValue().(ArrayInit).getAnInit()
}
Expr getADeclaredContentTypeExpr() { result = this.getAnArrayValue("value") }
}
/** An `@Consumes` annotation that describes content types can be consumed by this resource. */

View File

@@ -1,11 +0,0 @@
/** Definitions of taint steps in the KotlinStdLib framework */
import java
private import semmle.code.java.dataflow.ExternalFlow
private class KotlinStdLibSummaryCsv extends SummaryModelCsv {
override predicate row(string row) {
row =
"kotlin.jvm.internal;ArrayIteratorKt;false;iterator;(Object[]);;Argument[0].ArrayElement;ReturnValue.Element;value;manual"
}
}

View File

@@ -85,9 +85,7 @@ class IbatisSqlOperationAnnotation extends Annotation {
/**
* Gets this annotation's SQL statement string.
*/
string getSqlValue() {
result = this.getAValue("value").(CompileTimeConstantExpr).getStringValue()
}
string getSqlValue() { result = this.getAStringArrayValue("value") }
}
/**

View File

@@ -20,10 +20,17 @@ private class StringSummaryCsv extends SummaryModelCsv {
"java.lang;String;false;formatted;(Object[]);;Argument[0].ArrayElement;ReturnValue;taint;manual",
"java.lang;String;false;getChars;;;Argument[-1];Argument[2];taint;manual",
"java.lang;String;false;getBytes;;;Argument[-1];ReturnValue;taint;manual",
"java.lang;String;false;getBytes;;;Argument[-1];Argument[2];taint;manual",
"java.lang;String;false;indent;;;Argument[-1];ReturnValue;taint;manual",
"java.lang;String;false;intern;;;Argument[-1];ReturnValue;taint;manual",
"java.lang;String;false;join;;;Argument[0..1];ReturnValue;taint;manual",
"java.lang;String;false;repeat;(int);;Argument[-1];ReturnValue;taint;manual",
"java.lang;String;false;replace;;;Argument[-1];ReturnValue;taint;manual",
"java.lang;String;false;replace;;;Argument[1];ReturnValue;taint;manual",
"java.lang;String;false;replaceAll;;;Argument[-1];ReturnValue;taint;manual",
"java.lang;String;false;replaceAll;;;Argument[1];ReturnValue;taint;manual",
"java.lang;String;false;replaceFirst;;;Argument[-1];ReturnValue;taint;manual",
"java.lang;String;false;replaceFirst;;;Argument[1];ReturnValue;taint;manual",
"java.lang;String;false;split;;;Argument[-1];ReturnValue;taint;manual",
"java.lang;String;false;String;;;Argument[0];Argument[-1];taint;manual",
"java.lang;String;false;strip;;;Argument[-1];ReturnValue;taint;manual",
@@ -55,6 +62,7 @@ private class StringSummaryCsv extends SummaryModelCsv {
"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;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"
]

View File

@@ -0,0 +1,16 @@
/**
* Provides classes and predicates for working with the Thymeleaf template engine.
*/
import java
private import semmle.code.java.dataflow.ExternalFlow
private class ThymeleafSummaryModels extends SummaryModelCsv {
override predicate row(string row) {
row =
[
"org.thymeleaf;TemplateSpec;false;TemplateSpec;;;Argument[0];Argument[-1];taint;manual",
"org.thymeleaf;TemplateSpec;false;getTemplate;;;Argument[-1];ReturnValue;taint;manual",
]
}
}

View File

@@ -58,13 +58,16 @@ class MethodUnboundIdFilterCreate extends Method {
}
/** A method with the name `createANDFilter` declared in `com.unboundid.ldap.sdk.Filter`. */
class MethodUnboundIdFilterCreateANDFilter extends Method {
MethodUnboundIdFilterCreateANDFilter() {
class MethodUnboundIdFilterCreateAndFilter extends Method {
MethodUnboundIdFilterCreateAndFilter() {
this.getDeclaringType() instanceof TypeUnboundIdLdapFilter and
this.hasName("createANDFilter")
}
}
/** DEPRECATED: Alias for MethodUnboundIdFilterCreateAndFilter */
deprecated class MethodUnboundIdFilterCreateANDFilter = MethodUnboundIdFilterCreateAndFilter;
/** A method with the name `createORFilter` declared in `com.unboundid.ldap.sdk.Filter`. */
class MethodUnboundIdFilterCreateORFilter extends Method {
MethodUnboundIdFilterCreateORFilter() {
@@ -73,9 +76,12 @@ class MethodUnboundIdFilterCreateORFilter extends Method {
}
}
/** DEPRECATED: Alias for MethodUnboundIdFilterCreateNOTFilter */
deprecated class MethodUnboundIdFilterCreateNOTFilter = MethodUnboundIdFilterCreateNotFilter;
/** A method with the name `createNOTFilter` declared in `com.unboundid.ldap.sdk.Filter`. */
class MethodUnboundIdFilterCreateNOTFilter extends Method {
MethodUnboundIdFilterCreateNOTFilter() {
class MethodUnboundIdFilterCreateNotFilter extends Method {
MethodUnboundIdFilterCreateNotFilter() {
this.getDeclaringType() instanceof TypeUnboundIdLdapFilter and
this.hasName("createNOTFilter")
}

View File

@@ -53,7 +53,64 @@ private class SummaryModels extends SummaryModelCsv {
"android.content;ContentValues;false;put;;;Argument[0];Argument[-1].MapKey;value;manual",
"android.content;ContentValues;false;put;;;Argument[1];Argument[-1].MapValue;value;manual",
"android.content;ContentValues;false;putAll;;;Argument[0].MapKey;Argument[-1].MapKey;value;manual",
"android.content;ContentValues;false;putAll;;;Argument[0].MapValue;Argument[-1].MapValue;value;manual"
"android.content;ContentValues;false;putAll;;;Argument[0].MapValue;Argument[-1].MapValue;value;manual",
"android.content;ContentResolver;true;acquireContentProviderClient;;;Argument[0];ReturnValue;taint;manual",
"android.content;ContentResolver;true;acquireUnstableContentProviderClient;;;Argument[0];ReturnValue;taint;manual",
"android.content;ContentResolver;true;acquireUnstableContentProviderClient;;;Argument[0];ReturnValue;taint;manual",
"android.content;ContentResolver;true;applyBatch;;;Argument[1];ReturnValue;taint;manual",
"android.content;ContentResolver;true;call;;;Argument[0];ReturnValue;taint;manual",
"android.content;ContentResolver;true;canonicalize;;;Argument[0];ReturnValue;taint;manual",
"android.content;ContentResolver;true;getStreamTypes;;;Argument[0];ReturnValue;taint;manual",
"android.content;ContentResolver;true;getType;;;Argument[0];ReturnValue;taint;manual",
"android.content;ContentResolver;true;insert;;;Argument[0];ReturnValue;taint;manual",
"android.content;ContentResolver;true;query;;;Argument[0];ReturnValue;taint;manual",
"android.content;ContentResolver;true;uncanonicalize;;;Argument[0];ReturnValue;taint;manual",
"android.content;ContentResolver;true;wrap;;;Argument[0];ReturnValue;taint;manual",
// ContentProviderClient is tainted at its creation, not by its arguments
"android.content;ContentProviderClient;true;applyBatch;;;Argument[-1];ReturnValue;taint;manual",
"android.content;ContentProviderClient;true;call;;;Argument[-1];ReturnValue;taint;manual",
"android.content;ContentProviderClient;true;canonicalize;;;Argument[-1];ReturnValue;taint;manual",
"android.content;ContentProviderClient;true;getLocalContentProvider;;;Argument[-1];ReturnValue;taint;manual",
"android.content;ContentProviderClient;true;getStreamTypes;;;Argument[-1];ReturnValue;taint;manual",
"android.content;ContentProviderClient;true;insert;;;Argument[-1];ReturnValue;taint;manual",
"android.content;ContentProviderClient;true;query;;;Argument[-1];ReturnValue;taint;manual",
"android.content;ContentProviderClient;true;uncanonicalize;;;Argument[-1];ReturnValue;taint;manual",
"android.content;ContentProviderOperation;false;apply;;;Argument[-1];ReturnValue;taint;manual",
"android.content;ContentProviderOperation;false;apply;;;Argument[0];ReturnValue;taint;manual",
"android.content;ContentProviderOperation;false;getUri;;;Argument[-1];ReturnValue;taint;manual",
"android.content;ContentProviderOperation;false;newAssertQuery;;;Argument[0];ReturnValue;taint;manual",
"android.content;ContentProviderOperation;false;newCall;;;Argument[0];ReturnValue;taint;manual",
"android.content;ContentProviderOperation;false;newDelete;;;Argument[0];ReturnValue;taint;manual",
"android.content;ContentProviderOperation;false;newInsert;;;Argument[0];ReturnValue;taint;manual",
"android.content;ContentProviderOperation;false;newUpdate;;;Argument[0];ReturnValue;taint;manual",
"android.content;ContentProviderOperation;false;resolveExtrasBackReferences;;;Argument[0];ReturnValue;taint;manual",
"android.content;ContentProviderOperation;false;resolveSelectionArgsBackReferences;;;Argument[0];ReturnValue;taint;manual",
"android.content;ContentProviderOperation;false;resolveValueBackReferences;;;Argument[0];ReturnValue;taint;manual",
"android.content;ContentProviderOperation$Builder;false;build;;;Argument[-1];ReturnValue;taint;manual",
"android.content;ContentProviderOperation$Builder;false;withExceptionAllowed;;;Argument[-1];ReturnValue;value;manual",
"android.content;ContentProviderOperation$Builder;false;withExpectedCount;;;Argument[-1];ReturnValue;value;manual",
"android.content;ContentProviderOperation$Builder;false;withExtra;;;Argument[-1];ReturnValue;value;manual",
"android.content;ContentProviderOperation$Builder;false;withExtraBackReference;;;Argument[-1];ReturnValue;value;manual",
"android.content;ContentProviderOperation$Builder;false;withExtras;;;Argument[-1];ReturnValue;value;manual",
"android.content;ContentProviderOperation$Builder;false;withSelection;;;Argument[-1];ReturnValue;value;manual",
"android.content;ContentProviderOperation$Builder;false;withSelectionBackReference;;;Argument[-1];ReturnValue;value;manual",
"android.content;ContentProviderOperation$Builder;false;withValue;;;Argument[-1];ReturnValue;value;manual",
"android.content;ContentProviderOperation$Builder;false;withValueBackReference;;;Argument[-1];ReturnValue;value;manual",
"android.content;ContentProviderOperation$Builder;false;withValues;;;Argument[-1];ReturnValue;value;manual",
"android.content;ContentProviderOperation$Builder;false;withYieldAllowed;;;Argument[-1];ReturnValue;value;manual",
"android.content;ContentProviderResult;false;ContentProviderResult;(Uri);;Argument[0];Argument[-1].Field[android.content.ContentProviderResult.uri];value;manual",
"android.content;ContentProviderResult;false;ContentProviderResult;(Bundle);;Argument[0];Argument[-1].Field[android.content.ContentProviderResult.extras];value;manual",
"android.content;ContentProviderResult;false;ContentProviderResult;(Throwable);;Argument[0];Argument[-1].Field[android.content.ContentProviderResult.exception];value;manual",
"android.content;ContentProviderResult;false;ContentProviderResult;(Parcel);;Argument[0];Argument[-1];taint;manual",
"android.database;Cursor;true;copyStringToBuffer;;;Argument[-1];Argument[1];taint;manual",
"android.database;Cursor;true;getBlob;;;Argument[-1];ReturnValue;taint;manual",
"android.database;Cursor;true;getColumnName;;;Argument[-1];ReturnValue;taint;manual",
"android.database;Cursor;true;getColumnNames;;;Argument[-1];ReturnValue;taint;manual",
"android.database;Cursor;true;getExtras;;;Argument[-1];ReturnValue;taint;manual",
"android.database;Cursor;true;getNotificationUri;;;Argument[-1];ReturnValue;taint;manual",
"android.database;Cursor;true;getNotificationUris;;;Argument[-1];ReturnValue;taint;manual",
"android.database;Cursor;true;getString;;;Argument[-1];ReturnValue;taint;manual",
"android.database;Cursor;true;respond;;;Argument[-1];ReturnValue;taint;manual"
]
}
}

View File

@@ -19,6 +19,17 @@ private class NotificationBuildersSummaryModels extends SummaryModelCsv {
"android.app;Notification$Action$Builder;true;build;;;Argument[-1];ReturnValue;taint;manual",
"android.app;Notification$Action$Builder;true;build;;;Argument[-1].SyntheticField[android.content.Intent.extras];ReturnValue.SyntheticField[android.content.Intent.extras];value;manual",
"android.app;Notification$Action$Builder;true;getExtras;;;Argument[-1].SyntheticField[android.content.Intent.extras];ReturnValue;value;manual",
"androidx.core.app;NotificationCompat$Action;true;Action;(int,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint;manual",
"androidx.core.app;NotificationCompat$Action;true;Action;(IconCompat,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint;manual",
"androidx.core.app;NotificationCompat$Action;true;getExtras;;;Argument[-1].SyntheticField[android.content.Intent.extras];ReturnValue;value;manual",
"androidx.core.app;NotificationCompat$Action$Builder;true;Builder;(int,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint;manual",
"androidx.core.app;NotificationCompat$Action$Builder;true;Builder;(IconCompat,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint;manual",
"androidx.core.app;NotificationCompat$Action$Builder;true;Builder;(Action);;Argument[0];Argument[-1];taint;manual",
"androidx.core.app;NotificationCompat$Action$Builder;true;addExtras;;;Argument[0].MapKey;Argument[-1].SyntheticField[android.content.Intent.extras].MapKey;value;manual",
"androidx.core.app;NotificationCompat$Action$Builder;true;addExtras;;;Argument[0].MapValue;Argument[-1].SyntheticField[android.content.Intent.extras].MapValue;value;manual",
"androidx.core.app;NotificationCompat$Action$Builder;true;build;;;Argument[-1];ReturnValue;taint;manual",
"androidx.core.app;NotificationCompat$Action$Builder;true;build;;;Argument[-1].SyntheticField[android.content.Intent.extras];ReturnValue.SyntheticField[android.content.Intent.extras];value;manual",
"androidx.core.app;NotificationCompat$Action$Builder;true;getExtras;;;Argument[-1].SyntheticField[android.content.Intent.extras];ReturnValue;value;manual",
"android.app;Notification$Builder;true;addAction;(int,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint;manual",
"android.app;Notification$Builder;true;addAction;(Action);;Argument[0];Argument[-1];taint;manual",
"android.app;Notification$Builder;true;addExtras;;;Argument[0].MapKey;Argument[-1].SyntheticField[android.content.Intent.extras].MapKey;value;manual",
@@ -32,18 +43,30 @@ private class NotificationBuildersSummaryModels extends SummaryModelCsv {
"android.app;Notification$Builder;true;setExtras;;;Argument[0];Argument[-1].SyntheticField[android.content.Intent.extras];value;manual",
"android.app;Notification$Builder;true;setDeleteIntent;;;Argument[0];Argument[-1];taint;manual",
"android.app;Notification$Builder;true;setPublicVersion;;;Argument[0];Argument[-1];taint;manual",
"androidx.core.app;NotificationCompat$Builder;true;addAction;(int,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint;manual",
"androidx.core.app;NotificationCompat$Builder;true;addAction;(Action);;Argument[0];Argument[-1];taint;manual",
"androidx.core.app;NotificationCompat$Builder;true;addExtras;;;Argument[0].MapKey;Argument[-1].SyntheticField[android.content.Intent.extras].MapKey;value;manual",
"androidx.core.app;NotificationCompat$Builder;true;addExtras;;;Argument[0].MapValue;Argument[-1].SyntheticField[android.content.Intent.extras].MapValue;value;manual",
"androidx.core.app;NotificationCompat$Builder;true;build;;;Argument[-1];ReturnValue;taint;manual",
"androidx.core.app;NotificationCompat$Builder;true;build;;;Argument[-1].SyntheticField[android.content.Intent.extras];ReturnValue.Field[android.app.Notification.extras];value;manual",
"androidx.core.app;NotificationCompat$Builder;true;setContentIntent;;;Argument[0];Argument[-1];taint;manual",
"androidx.core.app;NotificationCompat$Builder;true;getExtras;;;Argument[-1].SyntheticField[android.content.Intent.extras];ReturnValue;value;manual",
"androidx.core.app;NotificationCompat$Builder;true;setExtras;;;Argument[0];Argument[-1].SyntheticField[android.content.Intent.extras];value;manual",
"androidx.core.app;NotificationCompat$Builder;true;setDeleteIntent;;;Argument[0];Argument[-1];taint;manual",
"androidx.core.app;NotificationCompat$Builder;true;setPublicVersion;;;Argument[0];Argument[-1];taint;manual",
"android.app;Notification$Style;true;build;;;Argument[-1];ReturnValue;taint;manual",
"android.app;Notification$BigPictureStyle;true;BigPictureStyle;(Builder);;Argument[0];Argument[-1];taint;manual",
"android.app;Notification$BigTextStyle;true;BigTextStyle;(Builder);;Argument[0];Argument[-1];taint;manual",
"android.app;Notification$InboxStyle;true;InboxStyle;(Builder);;Argument[0];Argument[-1];taint;manual",
"android.app;Notification$MediaStyle;true;MediaStyle;(Builder);;Argument[0];Argument[-1];taint;manual",
// Fluent models
"android.app;Notification$Action$Builder;true;" +
["android.app;Notification", "androidx.core.app;NotificationCompat"] +
"$Action$Builder;true;" +
[
"addExtras", "addRemoteInput", "extend", "setAllowGeneratedReplies",
"setAuthenticationRequired", "setContextual", "setSemanticAction"
] + ";;;Argument[-1];ReturnValue;value;manual",
"android.app;Notification$Builder;true;" +
["android.app;Notification", "androidx.core.app;NotificationCompat"] + "$Builder;true;" +
[
"addAction", "addExtras", "addPerson", "extend", "setActions", "setAutoCancel",
"setBadgeIconType", "setBubbleMetadata", "setCategory", "setChannelId",
@@ -58,15 +81,16 @@ private class NotificationBuildersSummaryModels extends SummaryModelCsv {
"setSubText", "setTicker", "setTimeoutAfter", "setUsesChronometer", "setVibrate",
"setVisibility", "setWhen"
] + ";;;Argument[-1];ReturnValue;value;manual",
"android.app;Notification$BigPictureStyle;true;" +
["android.app;Notification", "androidx.core.app;NotificationCompat"] +
"$BigPictureStyle;true;" +
[
"bigLargeIcon", "bigPicture", "setBigContentTitle", "setContentDescription",
"setSummaryText", "showBigPictureWhenCollapsed"
] + ";;;Argument[-1];ReturnValue;value;manual",
"android.app;Notification$BigTextStyle;true;" +
["bigText", "setBigContentTitle", "setSummaryText"] +
["android.app;Notification", "androidx.core.app;NotificationCompat"] + "$BigTextStyle;true;"
+ ["bigText", "setBigContentTitle", "setSummaryText"] +
";;;Argument[-1];ReturnValue;value;manual",
"android.app;Notification$InboxStyle;true;" +
["android.app;Notification", "androidx.core.app;NotificationCompat"] + "$InboxStyle;true;" +
["addLine", "setBigContentTitle", "setSummaryText"] +
";;;Argument[-1];ReturnValue;value;manual",
"android.app;Notification$MediaStyle;true;" +

View File

@@ -13,7 +13,9 @@ private class IOGeneratedSinksCsv extends SinkModelCsv {
"org.apache.commons.io.file;PathFilter;true;accept;(Path,BasicFileAttributes);;Argument[0];create-file;generated",
"org.apache.commons.io.file;PathUtils;false;copyFile;(URL,Path,CopyOption[]);;Argument[0];open-url;generated",
"org.apache.commons.io.file;PathUtils;false;copyFile;(URL,Path,CopyOption[]);;Argument[1];create-file;generated",
"org.apache.commons.io.file;PathUtils;false;copyFileToDirectory;(Path,Path,CopyOption[]);;Argument[1];create-file;generated",
"org.apache.commons.io.file;PathUtils;false;copyFileToDirectory;(URL,Path,CopyOption[]);;Argument[0];open-url;generated",
"org.apache.commons.io.file;PathUtils;false;copyFileToDirectory;(URL,Path,CopyOption[]);;Argument[1];create-file;generated",
"org.apache.commons.io.file;PathUtils;false;newOutputStream;(Path,boolean);;Argument[0];create-file;generated",
"org.apache.commons.io.file;PathUtils;false;writeString;(Path,CharSequence,Charset,OpenOption[]);;Argument[0];create-file;generated",
"org.apache.commons.io.filefilter;FileFilterUtils;true;filter;(IOFileFilter,File[]);;Argument[1];create-file;generated",
@@ -631,14 +633,10 @@ private class IOGeneratedSummaryCsv extends SummaryModelCsv {
"org.apache.commons.io;IOUtils;true;readLines;(InputStream,Charset);;Argument[0];ReturnValue;taint;generated",
"org.apache.commons.io;IOUtils;true;readLines;(InputStream,String);;Argument[0];ReturnValue;taint;generated",
"org.apache.commons.io;IOUtils;true;readLines;(Reader);;Argument[0];ReturnValue;taint;generated",
"org.apache.commons.io;IOUtils;true;toBufferedInputStream;(InputStream);;Argument[0];ReturnValue;taint;generated",
"org.apache.commons.io;IOUtils;true;toBufferedInputStream;(InputStream,int);;Argument[0];ReturnValue;taint;generated",
"org.apache.commons.io;IOUtils;true;toBufferedReader;(Reader);;Argument[0];ReturnValue;taint;generated",
"org.apache.commons.io;IOUtils;true;toBufferedReader;(Reader,int);;Argument[0];ReturnValue;taint;generated",
"org.apache.commons.io;IOUtils;true;toByteArray;(InputStream,int);;Argument[0];ReturnValue;taint;generated",
"org.apache.commons.io;IOUtils;true;toByteArray;(InputStream,long);;Argument[0];ReturnValue;taint;generated",
"org.apache.commons.io;IOUtils;true;toByteArray;(Reader);;Argument[0];ReturnValue;taint;generated",
"org.apache.commons.io;IOUtils;true;toByteArray;(Reader,String);;Argument[0];ReturnValue;taint;generated",
"org.apache.commons.io;IOUtils;true;toByteArray;(String);;Argument[0];ReturnValue;taint;generated",
"org.apache.commons.io;IOUtils;true;toCharArray;(InputStream);;Argument[0];ReturnValue;taint;generated",
"org.apache.commons.io;IOUtils;true;toCharArray;(InputStream,Charset);;Argument[0];ReturnValue;taint;generated",
@@ -669,7 +667,6 @@ private class IOGeneratedSummaryCsv extends SummaryModelCsv {
"org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream);;Argument[1];Argument[2];taint;generated",
"org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream,Charset);;Argument[1];Argument[2];taint;generated",
"org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream,String);;Argument[1];Argument[2];taint;generated",
"org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,Writer);;Argument[0].Element;Argument[2];taint;generated",
"org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,Writer);;Argument[1];Argument[2];taint;generated",
"org.apache.commons.io;IOUtils;true;writer;(Appendable);;Argument[0];ReturnValue;taint;generated",
"org.apache.commons.io;LineIterator;true;LineIterator;(Reader);;Argument[0];Argument[-1];taint;generated",

View File

@@ -0,0 +1,769 @@
/**
* THIS FILE IS AN AUTO-GENERATED MODELS AS DATA FILE. DO NOT EDIT.
* Definitions of negative summaries in the IOGenerated framework.
*/
import java
private import semmle.code.java.dataflow.ExternalFlow
private class IOGeneratedNegativesummaryCsv extends NegativeSummaryModelCsv {
override predicate row(string row) {
row =
[
"org.apache.commons.io.charset;CharsetDecoders;CharsetDecoders;();generated",
"org.apache.commons.io.charset;CharsetEncoders;CharsetEncoders;();generated",
"org.apache.commons.io.comparator;DefaultFileComparator;DefaultFileComparator;();generated",
"org.apache.commons.io.comparator;DirectoryFileComparator;DirectoryFileComparator;();generated",
"org.apache.commons.io.comparator;ExtensionFileComparator;ExtensionFileComparator;();generated",
"org.apache.commons.io.comparator;ExtensionFileComparator;ExtensionFileComparator;(IOCase);generated",
"org.apache.commons.io.comparator;ExtensionFileComparator;toString;();generated",
"org.apache.commons.io.comparator;LastModifiedFileComparator;LastModifiedFileComparator;();generated",
"org.apache.commons.io.comparator;NameFileComparator;NameFileComparator;();generated",
"org.apache.commons.io.comparator;NameFileComparator;NameFileComparator;(IOCase);generated",
"org.apache.commons.io.comparator;NameFileComparator;toString;();generated",
"org.apache.commons.io.comparator;PathFileComparator;PathFileComparator;();generated",
"org.apache.commons.io.comparator;PathFileComparator;PathFileComparator;(IOCase);generated",
"org.apache.commons.io.comparator;PathFileComparator;toString;();generated",
"org.apache.commons.io.comparator;SizeFileComparator;SizeFileComparator;();generated",
"org.apache.commons.io.comparator;SizeFileComparator;SizeFileComparator;(boolean);generated",
"org.apache.commons.io.comparator;SizeFileComparator;toString;();generated",
"org.apache.commons.io.file.attribute;FileTimes;minusMillis;(FileTime,long);generated",
"org.apache.commons.io.file.attribute;FileTimes;minusNanos;(FileTime,long);generated",
"org.apache.commons.io.file.attribute;FileTimes;minusSeconds;(FileTime,long);generated",
"org.apache.commons.io.file.attribute;FileTimes;now;();generated",
"org.apache.commons.io.file.attribute;FileTimes;ntfsTimeToDate;(long);generated",
"org.apache.commons.io.file.attribute;FileTimes;ntfsTimeToFileTime;(long);generated",
"org.apache.commons.io.file.attribute;FileTimes;plusMillis;(FileTime,long);generated",
"org.apache.commons.io.file.attribute;FileTimes;plusNanos;(FileTime,long);generated",
"org.apache.commons.io.file.attribute;FileTimes;plusSeconds;(FileTime,long);generated",
"org.apache.commons.io.file.attribute;FileTimes;setLastModifiedTime;(Path);generated",
"org.apache.commons.io.file.attribute;FileTimes;toDate;(FileTime);generated",
"org.apache.commons.io.file.attribute;FileTimes;toFileTime;(Date);generated",
"org.apache.commons.io.file.attribute;FileTimes;toNtfsTime;(Date);generated",
"org.apache.commons.io.file.attribute;FileTimes;toNtfsTime;(FileTime);generated",
"org.apache.commons.io.file.spi;FileSystemProviders;getFileSystemProvider;(Path);generated",
"org.apache.commons.io.file.spi;FileSystemProviders;installed;();generated",
"org.apache.commons.io.file;AccumulatorPathVisitor;AccumulatorPathVisitor;();generated",
"org.apache.commons.io.file;AccumulatorPathVisitor;relativizeDirectories;(Path,boolean,Comparator);generated",
"org.apache.commons.io.file;AccumulatorPathVisitor;relativizeFiles;(Path,boolean,Comparator);generated",
"org.apache.commons.io.file;AccumulatorPathVisitor;withBigIntegerCounters;();generated",
"org.apache.commons.io.file;AccumulatorPathVisitor;withLongCounters;();generated",
"org.apache.commons.io.file;CleaningPathVisitor;withBigIntegerCounters;();generated",
"org.apache.commons.io.file;CleaningPathVisitor;withLongCounters;();generated",
"org.apache.commons.io.file;Counters$Counter;add;(long);generated",
"org.apache.commons.io.file;Counters$Counter;get;();generated",
"org.apache.commons.io.file;Counters$Counter;getBigInteger;();generated",
"org.apache.commons.io.file;Counters$Counter;getLong;();generated",
"org.apache.commons.io.file;Counters$Counter;increment;();generated",
"org.apache.commons.io.file;Counters$Counter;reset;();generated",
"org.apache.commons.io.file;Counters$PathCounters;getByteCounter;();generated",
"org.apache.commons.io.file;Counters$PathCounters;getDirectoryCounter;();generated",
"org.apache.commons.io.file;Counters$PathCounters;getFileCounter;();generated",
"org.apache.commons.io.file;Counters$PathCounters;reset;();generated",
"org.apache.commons.io.file;Counters;Counters;();generated",
"org.apache.commons.io.file;Counters;bigIntegerCounter;();generated",
"org.apache.commons.io.file;Counters;bigIntegerPathCounters;();generated",
"org.apache.commons.io.file;Counters;longCounter;();generated",
"org.apache.commons.io.file;Counters;longPathCounters;();generated",
"org.apache.commons.io.file;Counters;noopCounter;();generated",
"org.apache.commons.io.file;Counters;noopPathCounters;();generated",
"org.apache.commons.io.file;CountingPathVisitor;toString;();generated",
"org.apache.commons.io.file;CountingPathVisitor;withBigIntegerCounters;();generated",
"org.apache.commons.io.file;CountingPathVisitor;withLongCounters;();generated",
"org.apache.commons.io.file;DeletingPathVisitor;withBigIntegerCounters;();generated",
"org.apache.commons.io.file;DeletingPathVisitor;withLongCounters;();generated",
"org.apache.commons.io.file;NoopPathVisitor;NoopPathVisitor;();generated",
"org.apache.commons.io.file;PathFilter;accept;(Path,BasicFileAttributes);generated",
"org.apache.commons.io.file;PathUtils;cleanDirectory;(Path);generated",
"org.apache.commons.io.file;PathUtils;cleanDirectory;(Path,DeleteOption[]);generated",
"org.apache.commons.io.file;PathUtils;copyDirectory;(Path,Path,CopyOption[]);generated",
"org.apache.commons.io.file;PathUtils;copyFileToDirectory;(Path,Path,CopyOption[]);generated",
"org.apache.commons.io.file;PathUtils;countDirectory;(Path);generated",
"org.apache.commons.io.file;PathUtils;countDirectoryAsBigInteger;(Path);generated",
"org.apache.commons.io.file;PathUtils;createParentDirectories;(Path,FileAttribute[]);generated",
"org.apache.commons.io.file;PathUtils;createParentDirectories;(Path,LinkOption,FileAttribute[]);generated",
"org.apache.commons.io.file;PathUtils;current;();generated",
"org.apache.commons.io.file;PathUtils;delete;(Path);generated",
"org.apache.commons.io.file;PathUtils;delete;(Path,DeleteOption[]);generated",
"org.apache.commons.io.file;PathUtils;delete;(Path,LinkOption[],DeleteOption[]);generated",
"org.apache.commons.io.file;PathUtils;deleteDirectory;(Path);generated",
"org.apache.commons.io.file;PathUtils;deleteDirectory;(Path,DeleteOption[]);generated",
"org.apache.commons.io.file;PathUtils;deleteDirectory;(Path,LinkOption[],DeleteOption[]);generated",
"org.apache.commons.io.file;PathUtils;deleteFile;(Path);generated",
"org.apache.commons.io.file;PathUtils;deleteFile;(Path,DeleteOption[]);generated",
"org.apache.commons.io.file;PathUtils;deleteFile;(Path,LinkOption[],DeleteOption[]);generated",
"org.apache.commons.io.file;PathUtils;directoryAndFileContentEquals;(Path,Path);generated",
"org.apache.commons.io.file;PathUtils;directoryAndFileContentEquals;(Path,Path,LinkOption[],OpenOption[],FileVisitOption[]);generated",
"org.apache.commons.io.file;PathUtils;directoryContentEquals;(Path,Path);generated",
"org.apache.commons.io.file;PathUtils;directoryContentEquals;(Path,Path,int,LinkOption[],FileVisitOption[]);generated",
"org.apache.commons.io.file;PathUtils;fileContentEquals;(Path,Path);generated",
"org.apache.commons.io.file;PathUtils;fileContentEquals;(Path,Path,LinkOption[],OpenOption[]);generated",
"org.apache.commons.io.file;PathUtils;filter;(PathFilter,Path[]);generated",
"org.apache.commons.io.file;PathUtils;getAclEntryList;(Path);generated",
"org.apache.commons.io.file;PathUtils;getAclFileAttributeView;(Path,LinkOption[]);generated",
"org.apache.commons.io.file;PathUtils;getDosFileAttributeView;(Path,LinkOption[]);generated",
"org.apache.commons.io.file;PathUtils;getPosixFileAttributeView;(Path,LinkOption[]);generated",
"org.apache.commons.io.file;PathUtils;getTempDirectory;();generated",
"org.apache.commons.io.file;PathUtils;isDirectory;(Path,LinkOption[]);generated",
"org.apache.commons.io.file;PathUtils;isEmpty;(Path);generated",
"org.apache.commons.io.file;PathUtils;isEmptyDirectory;(Path);generated",
"org.apache.commons.io.file;PathUtils;isEmptyFile;(Path);generated",
"org.apache.commons.io.file;PathUtils;isNewer;(Path,ChronoZonedDateTime,LinkOption[]);generated",
"org.apache.commons.io.file;PathUtils;isNewer;(Path,FileTime,LinkOption[]);generated",
"org.apache.commons.io.file;PathUtils;isNewer;(Path,Instant,LinkOption[]);generated",
"org.apache.commons.io.file;PathUtils;isNewer;(Path,Path);generated",
"org.apache.commons.io.file;PathUtils;isNewer;(Path,long,LinkOption[]);generated",
"org.apache.commons.io.file;PathUtils;isOlder;(Path,FileTime,LinkOption[]);generated",
"org.apache.commons.io.file;PathUtils;isOlder;(Path,Instant,LinkOption[]);generated",
"org.apache.commons.io.file;PathUtils;isOlder;(Path,Path);generated",
"org.apache.commons.io.file;PathUtils;isOlder;(Path,long,LinkOption[]);generated",
"org.apache.commons.io.file;PathUtils;isPosix;(Path,LinkOption[]);generated",
"org.apache.commons.io.file;PathUtils;isRegularFile;(Path,LinkOption[]);generated",
"org.apache.commons.io.file;PathUtils;newDirectoryStream;(Path,PathFilter);generated",
"org.apache.commons.io.file;PathUtils;newOutputStream;(Path,boolean);generated",
"org.apache.commons.io.file;PathUtils;noFollowLinkOptionArray;();generated",
"org.apache.commons.io.file;PathUtils;readAttributes;(Path,Class,LinkOption[]);generated",
"org.apache.commons.io.file;PathUtils;readBasicFileAttributes;(Path);generated",
"org.apache.commons.io.file;PathUtils;readBasicFileAttributes;(Path,LinkOption[]);generated",
"org.apache.commons.io.file;PathUtils;readBasicFileAttributesUnchecked;(Path);generated",
"org.apache.commons.io.file;PathUtils;readDosFileAttributes;(Path,LinkOption[]);generated",
"org.apache.commons.io.file;PathUtils;readOsFileAttributes;(Path,LinkOption[]);generated",
"org.apache.commons.io.file;PathUtils;readPosixFileAttributes;(Path,LinkOption[]);generated",
"org.apache.commons.io.file;PathUtils;readString;(Path,Charset);generated",
"org.apache.commons.io.file;PathUtils;setLastModifiedTime;(Path,Path);generated",
"org.apache.commons.io.file;PathUtils;sizeOf;(Path);generated",
"org.apache.commons.io.file;PathUtils;sizeOfAsBigInteger;(Path);generated",
"org.apache.commons.io.file;PathUtils;sizeOfDirectory;(Path);generated",
"org.apache.commons.io.file;PathUtils;sizeOfDirectoryAsBigInteger;(Path);generated",
"org.apache.commons.io.file;PathUtils;waitFor;(Path,Duration,LinkOption[]);generated",
"org.apache.commons.io.file;PathUtils;walk;(Path,PathFilter,int,boolean,FileVisitOption[]);generated",
"org.apache.commons.io.file;StandardDeleteOption;overrideReadOnly;(DeleteOption[]);generated",
"org.apache.commons.io.filefilter;AbstractFileFilter;AbstractFileFilter;();generated",
"org.apache.commons.io.filefilter;AbstractFileFilter;toString;();generated",
"org.apache.commons.io.filefilter;AgeFileFilter;AgeFileFilter;(Date);generated",
"org.apache.commons.io.filefilter;AgeFileFilter;AgeFileFilter;(Date,boolean);generated",
"org.apache.commons.io.filefilter;AgeFileFilter;AgeFileFilter;(File);generated",
"org.apache.commons.io.filefilter;AgeFileFilter;AgeFileFilter;(File,boolean);generated",
"org.apache.commons.io.filefilter;AgeFileFilter;AgeFileFilter;(long);generated",
"org.apache.commons.io.filefilter;AgeFileFilter;AgeFileFilter;(long,boolean);generated",
"org.apache.commons.io.filefilter;AndFileFilter;AndFileFilter;();generated",
"org.apache.commons.io.filefilter;ConditionalFileFilter;addFileFilter;(IOFileFilter);generated",
"org.apache.commons.io.filefilter;ConditionalFileFilter;getFileFilters;();generated",
"org.apache.commons.io.filefilter;ConditionalFileFilter;removeFileFilter;(IOFileFilter);generated",
"org.apache.commons.io.filefilter;ConditionalFileFilter;setFileFilters;(List);generated",
"org.apache.commons.io.filefilter;FalseFileFilter;toString;();generated",
"org.apache.commons.io.filefilter;FileFilterUtils;FileFilterUtils;();generated",
"org.apache.commons.io.filefilter;FileFilterUtils;ageFileFilter;(Date);generated",
"org.apache.commons.io.filefilter;FileFilterUtils;ageFileFilter;(Date,boolean);generated",
"org.apache.commons.io.filefilter;FileFilterUtils;ageFileFilter;(File);generated",
"org.apache.commons.io.filefilter;FileFilterUtils;ageFileFilter;(File,boolean);generated",
"org.apache.commons.io.filefilter;FileFilterUtils;ageFileFilter;(long);generated",
"org.apache.commons.io.filefilter;FileFilterUtils;ageFileFilter;(long,boolean);generated",
"org.apache.commons.io.filefilter;FileFilterUtils;directoryFileFilter;();generated",
"org.apache.commons.io.filefilter;FileFilterUtils;falseFileFilter;();generated",
"org.apache.commons.io.filefilter;FileFilterUtils;fileFileFilter;();generated",
"org.apache.commons.io.filefilter;FileFilterUtils;filter;(IOFileFilter,File[]);generated",
"org.apache.commons.io.filefilter;FileFilterUtils;filter;(IOFileFilter,Iterable);generated",
"org.apache.commons.io.filefilter;FileFilterUtils;filterList;(IOFileFilter,File[]);generated",
"org.apache.commons.io.filefilter;FileFilterUtils;filterList;(IOFileFilter,Iterable);generated",
"org.apache.commons.io.filefilter;FileFilterUtils;filterSet;(IOFileFilter,File[]);generated",
"org.apache.commons.io.filefilter;FileFilterUtils;filterSet;(IOFileFilter,Iterable);generated",
"org.apache.commons.io.filefilter;FileFilterUtils;sizeFileFilter;(long);generated",
"org.apache.commons.io.filefilter;FileFilterUtils;sizeFileFilter;(long,boolean);generated",
"org.apache.commons.io.filefilter;FileFilterUtils;sizeRangeFileFilter;(long,long);generated",
"org.apache.commons.io.filefilter;FileFilterUtils;trueFileFilter;();generated",
"org.apache.commons.io.filefilter;IOFileFilter;and;(IOFileFilter);generated",
"org.apache.commons.io.filefilter;IOFileFilter;negate;();generated",
"org.apache.commons.io.filefilter;IOFileFilter;or;(IOFileFilter);generated",
"org.apache.commons.io.filefilter;OrFileFilter;OrFileFilter;();generated",
"org.apache.commons.io.filefilter;RegexFileFilter;RegexFileFilter;(String);generated",
"org.apache.commons.io.filefilter;RegexFileFilter;RegexFileFilter;(String,IOCase);generated",
"org.apache.commons.io.filefilter;RegexFileFilter;RegexFileFilter;(String,int);generated",
"org.apache.commons.io.filefilter;SizeFileFilter;SizeFileFilter;(long);generated",
"org.apache.commons.io.filefilter;SizeFileFilter;SizeFileFilter;(long,boolean);generated",
"org.apache.commons.io.filefilter;SizeFileFilter;toString;();generated",
"org.apache.commons.io.filefilter;SymbolicLinkFileFilter;SymbolicLinkFileFilter;(FileVisitResult,FileVisitResult);generated",
"org.apache.commons.io.filefilter;TrueFileFilter;toString;();generated",
"org.apache.commons.io.function;IOBiConsumer;accept;(Object,Object);generated",
"org.apache.commons.io.function;IOBiConsumer;andThen;(IOBiConsumer);generated",
"org.apache.commons.io.function;IOBiFunction;andThen;(Function);generated",
"org.apache.commons.io.function;IOBiFunction;andThen;(IOFunction);generated",
"org.apache.commons.io.function;IOBiFunction;apply;(Object,Object);generated",
"org.apache.commons.io.function;IOConsumer;accept;(Object);generated",
"org.apache.commons.io.function;IOConsumer;andThen;(IOConsumer);generated",
"org.apache.commons.io.function;IOConsumer;forEach;(Object[],IOConsumer);generated",
"org.apache.commons.io.function;IOConsumer;forEachIndexed;(Stream,IOConsumer);generated",
"org.apache.commons.io.function;IOConsumer;noop;();generated",
"org.apache.commons.io.function;IOFunction;andThen;(Consumer);generated",
"org.apache.commons.io.function;IOFunction;andThen;(Function);generated",
"org.apache.commons.io.function;IOFunction;andThen;(IOConsumer);generated",
"org.apache.commons.io.function;IOFunction;andThen;(IOFunction);generated",
"org.apache.commons.io.function;IOFunction;apply;(Object);generated",
"org.apache.commons.io.function;IOFunction;compose;(Function);generated",
"org.apache.commons.io.function;IOFunction;compose;(IOFunction);generated",
"org.apache.commons.io.function;IOFunction;compose;(IOSupplier);generated",
"org.apache.commons.io.function;IOFunction;compose;(Supplier);generated",
"org.apache.commons.io.function;IOFunction;identity;();generated",
"org.apache.commons.io.function;IORunnable;run;();generated",
"org.apache.commons.io.function;IOSupplier;get;();generated",
"org.apache.commons.io.function;IOTriFunction;andThen;(Function);generated",
"org.apache.commons.io.function;IOTriFunction;andThen;(IOFunction);generated",
"org.apache.commons.io.function;IOTriFunction;apply;(Object,Object,Object);generated",
"org.apache.commons.io.input.buffer;CircularByteBuffer;CircularByteBuffer;();generated",
"org.apache.commons.io.input.buffer;CircularByteBuffer;CircularByteBuffer;(int);generated",
"org.apache.commons.io.input.buffer;CircularByteBuffer;add;(byte);generated",
"org.apache.commons.io.input.buffer;CircularByteBuffer;add;(byte[],int,int);generated",
"org.apache.commons.io.input.buffer;CircularByteBuffer;clear;();generated",
"org.apache.commons.io.input.buffer;CircularByteBuffer;getCurrentNumberOfBytes;();generated",
"org.apache.commons.io.input.buffer;CircularByteBuffer;getSpace;();generated",
"org.apache.commons.io.input.buffer;CircularByteBuffer;hasBytes;();generated",
"org.apache.commons.io.input.buffer;CircularByteBuffer;hasSpace;();generated",
"org.apache.commons.io.input.buffer;CircularByteBuffer;hasSpace;(int);generated",
"org.apache.commons.io.input.buffer;CircularByteBuffer;peek;(byte[],int,int);generated",
"org.apache.commons.io.input.buffer;CircularByteBuffer;read;();generated",
"org.apache.commons.io.input.buffer;CircularByteBuffer;read;(byte[],int,int);generated",
"org.apache.commons.io.input.buffer;PeekableInputStream;peek;(byte[]);generated",
"org.apache.commons.io.input.buffer;PeekableInputStream;peek;(byte[],int,int);generated",
"org.apache.commons.io.input;AutoCloseInputStream;AutoCloseInputStream;(InputStream);generated",
"org.apache.commons.io.input;BOMInputStream;BOMInputStream;(InputStream);generated",
"org.apache.commons.io.input;BOMInputStream;BOMInputStream;(InputStream,boolean);generated",
"org.apache.commons.io.input;BOMInputStream;hasBOM;();generated",
"org.apache.commons.io.input;BOMInputStream;hasBOM;(ByteOrderMark);generated",
"org.apache.commons.io.input;BoundedInputStream;isPropagateClose;();generated",
"org.apache.commons.io.input;BoundedInputStream;setPropagateClose;(boolean);generated",
"org.apache.commons.io.input;BoundedInputStream;toString;();generated",
"org.apache.commons.io.input;BrokenInputStream;BrokenInputStream;();generated",
"org.apache.commons.io.input;BrokenInputStream;BrokenInputStream;(IOException);generated",
"org.apache.commons.io.input;BrokenReader;BrokenReader;();generated",
"org.apache.commons.io.input;BrokenReader;BrokenReader;(IOException);generated",
"org.apache.commons.io.input;BufferedFileChannelInputStream;BufferedFileChannelInputStream;(File);generated",
"org.apache.commons.io.input;BufferedFileChannelInputStream;BufferedFileChannelInputStream;(File,int);generated",
"org.apache.commons.io.input;BufferedFileChannelInputStream;BufferedFileChannelInputStream;(Path);generated",
"org.apache.commons.io.input;BufferedFileChannelInputStream;BufferedFileChannelInputStream;(Path,int);generated",
"org.apache.commons.io.input;CharSequenceInputStream;CharSequenceInputStream;(CharSequence,Charset);generated",
"org.apache.commons.io.input;CharSequenceInputStream;CharSequenceInputStream;(CharSequence,Charset,int);generated",
"org.apache.commons.io.input;CharSequenceInputStream;CharSequenceInputStream;(CharSequence,String);generated",
"org.apache.commons.io.input;CharSequenceInputStream;CharSequenceInputStream;(CharSequence,String,int);generated",
"org.apache.commons.io.input;CharacterFilterReader;CharacterFilterReader;(Reader,int);generated",
"org.apache.commons.io.input;CharacterSetFilterReader;CharacterSetFilterReader;(Reader,Integer[]);generated",
"org.apache.commons.io.input;CharacterSetFilterReader;CharacterSetFilterReader;(Reader,Set);generated",
"org.apache.commons.io.input;CloseShieldInputStream;CloseShieldInputStream;(InputStream);generated",
"org.apache.commons.io.input;CloseShieldReader;CloseShieldReader;(Reader);generated",
"org.apache.commons.io.input;CloseShieldReader;wrap;(Reader);generated",
"org.apache.commons.io.input;ClosedInputStream;ClosedInputStream;();generated",
"org.apache.commons.io.input;ClosedReader;ClosedReader;();generated",
"org.apache.commons.io.input;CountingInputStream;CountingInputStream;(InputStream);generated",
"org.apache.commons.io.input;CountingInputStream;getByteCount;();generated",
"org.apache.commons.io.input;CountingInputStream;getCount;();generated",
"org.apache.commons.io.input;CountingInputStream;resetByteCount;();generated",
"org.apache.commons.io.input;CountingInputStream;resetCount;();generated",
"org.apache.commons.io.input;DemuxInputStream;DemuxInputStream;();generated",
"org.apache.commons.io.input;DemuxInputStream;bindStream;(InputStream);generated",
"org.apache.commons.io.input;MarkShieldInputStream;MarkShieldInputStream;(InputStream);generated",
"org.apache.commons.io.input;MemoryMappedFileInputStream;MemoryMappedFileInputStream;(Path);generated",
"org.apache.commons.io.input;MemoryMappedFileInputStream;MemoryMappedFileInputStream;(Path,int);generated",
"org.apache.commons.io.input;MessageDigestCalculatingInputStream;MessageDigestCalculatingInputStream;(InputStream);generated",
"org.apache.commons.io.input;MessageDigestCalculatingInputStream;MessageDigestCalculatingInputStream;(InputStream,String);generated",
"org.apache.commons.io.input;NullInputStream;NullInputStream;();generated",
"org.apache.commons.io.input;NullInputStream;NullInputStream;(long);generated",
"org.apache.commons.io.input;NullInputStream;NullInputStream;(long,boolean,boolean);generated",
"org.apache.commons.io.input;NullInputStream;getPosition;();generated",
"org.apache.commons.io.input;NullInputStream;getSize;();generated",
"org.apache.commons.io.input;NullReader;NullReader;();generated",
"org.apache.commons.io.input;NullReader;NullReader;(long);generated",
"org.apache.commons.io.input;NullReader;NullReader;(long,boolean,boolean);generated",
"org.apache.commons.io.input;NullReader;getPosition;();generated",
"org.apache.commons.io.input;NullReader;getSize;();generated",
"org.apache.commons.io.input;ObservableInputStream$Observer;Observer;();generated",
"org.apache.commons.io.input;ObservableInputStream$Observer;closed;();generated",
"org.apache.commons.io.input;ObservableInputStream$Observer;data;(byte[],int,int);generated",
"org.apache.commons.io.input;ObservableInputStream$Observer;data;(int);generated",
"org.apache.commons.io.input;ObservableInputStream$Observer;error;(IOException);generated",
"org.apache.commons.io.input;ObservableInputStream$Observer;finished;();generated",
"org.apache.commons.io.input;ObservableInputStream;ObservableInputStream;(InputStream);generated",
"org.apache.commons.io.input;ObservableInputStream;consume;();generated",
"org.apache.commons.io.input;ObservableInputStream;remove;(Observer);generated",
"org.apache.commons.io.input;ObservableInputStream;removeAllObservers;();generated",
"org.apache.commons.io.input;ProxyInputStream;ProxyInputStream;(InputStream);generated",
"org.apache.commons.io.input;ProxyReader;ProxyReader;(Reader);generated",
"org.apache.commons.io.input;QueueInputStream;QueueInputStream;();generated",
"org.apache.commons.io.input;QueueInputStream;QueueInputStream;(BlockingQueue);generated",
"org.apache.commons.io.input;QueueInputStream;newQueueOutputStream;();generated",
"org.apache.commons.io.input;RandomAccessFileInputStream;availableLong;();generated",
"org.apache.commons.io.input;RandomAccessFileInputStream;isCloseOnClose;();generated",
"org.apache.commons.io.input;ReversedLinesFileReader;ReversedLinesFileReader;(File);generated",
"org.apache.commons.io.input;ReversedLinesFileReader;ReversedLinesFileReader;(File,Charset);generated",
"org.apache.commons.io.input;ReversedLinesFileReader;ReversedLinesFileReader;(File,int,Charset);generated",
"org.apache.commons.io.input;ReversedLinesFileReader;ReversedLinesFileReader;(File,int,String);generated",
"org.apache.commons.io.input;ReversedLinesFileReader;ReversedLinesFileReader;(Path,Charset);generated",
"org.apache.commons.io.input;ReversedLinesFileReader;ReversedLinesFileReader;(Path,int,Charset);generated",
"org.apache.commons.io.input;ReversedLinesFileReader;ReversedLinesFileReader;(Path,int,String);generated",
"org.apache.commons.io.input;SwappedDataInputStream;SwappedDataInputStream;(InputStream);generated",
"org.apache.commons.io.input;TaggedInputStream;TaggedInputStream;(InputStream);generated",
"org.apache.commons.io.input;TaggedInputStream;isCauseOf;(Throwable);generated",
"org.apache.commons.io.input;TaggedInputStream;throwIfCauseOf;(Throwable);generated",
"org.apache.commons.io.input;TaggedReader;TaggedReader;(Reader);generated",
"org.apache.commons.io.input;TaggedReader;isCauseOf;(Throwable);generated",
"org.apache.commons.io.input;TaggedReader;throwIfCauseOf;(Throwable);generated",
"org.apache.commons.io.input;Tailer$RandomAccessResourceBridge;getPointer;();generated",
"org.apache.commons.io.input;Tailer$RandomAccessResourceBridge;read;(byte[]);generated",
"org.apache.commons.io.input;Tailer$RandomAccessResourceBridge;seek;(long);generated",
"org.apache.commons.io.input;Tailer$Tailable;getRandomAccess;(String);generated",
"org.apache.commons.io.input;Tailer$Tailable;isNewer;(FileTime);generated",
"org.apache.commons.io.input;Tailer$Tailable;lastModifiedFileTime;();generated",
"org.apache.commons.io.input;Tailer$Tailable;size;();generated",
"org.apache.commons.io.input;Tailer;getDelay;();generated",
"org.apache.commons.io.input;Tailer;stop;();generated",
"org.apache.commons.io.input;TailerListener;fileNotFound;();generated",
"org.apache.commons.io.input;TailerListener;fileRotated;();generated",
"org.apache.commons.io.input;TailerListener;handle;(Exception);generated",
"org.apache.commons.io.input;TailerListener;handle;(String);generated",
"org.apache.commons.io.input;TailerListener;init;(Tailer);generated",
"org.apache.commons.io.input;TailerListenerAdapter;TailerListenerAdapter;();generated",
"org.apache.commons.io.input;TailerListenerAdapter;endOfFileReached;();generated",
"org.apache.commons.io.input;TimestampedObserver;TimestampedObserver;();generated",
"org.apache.commons.io.input;TimestampedObserver;getOpenToCloseDuration;();generated",
"org.apache.commons.io.input;TimestampedObserver;getOpenToNowDuration;();generated",
"org.apache.commons.io.input;UncheckedFilterInputStream;UncheckedFilterInputStream;(InputStream);generated",
"org.apache.commons.io.input;UncheckedFilterReader;UncheckedFilterReader;(Reader);generated",
"org.apache.commons.io.input;UncheckedFilterReader;on;(Reader);generated",
"org.apache.commons.io.input;XmlStreamReader;XmlStreamReader;(File);generated",
"org.apache.commons.io.input;XmlStreamReader;XmlStreamReader;(Path);generated",
"org.apache.commons.io.input;XmlStreamReader;XmlStreamReader;(URL);generated",
"org.apache.commons.io.monitor;FileAlterationListener;onDirectoryChange;(File);generated",
"org.apache.commons.io.monitor;FileAlterationListener;onDirectoryCreate;(File);generated",
"org.apache.commons.io.monitor;FileAlterationListener;onDirectoryDelete;(File);generated",
"org.apache.commons.io.monitor;FileAlterationListener;onFileChange;(File);generated",
"org.apache.commons.io.monitor;FileAlterationListener;onFileCreate;(File);generated",
"org.apache.commons.io.monitor;FileAlterationListener;onFileDelete;(File);generated",
"org.apache.commons.io.monitor;FileAlterationListener;onStart;(FileAlterationObserver);generated",
"org.apache.commons.io.monitor;FileAlterationListener;onStop;(FileAlterationObserver);generated",
"org.apache.commons.io.monitor;FileAlterationListenerAdaptor;FileAlterationListenerAdaptor;();generated",
"org.apache.commons.io.monitor;FileAlterationMonitor;FileAlterationMonitor;();generated",
"org.apache.commons.io.monitor;FileAlterationMonitor;FileAlterationMonitor;(long);generated",
"org.apache.commons.io.monitor;FileAlterationMonitor;getInterval;();generated",
"org.apache.commons.io.monitor;FileAlterationMonitor;removeObserver;(FileAlterationObserver);generated",
"org.apache.commons.io.monitor;FileAlterationMonitor;start;();generated",
"org.apache.commons.io.monitor;FileAlterationMonitor;stop;();generated",
"org.apache.commons.io.monitor;FileAlterationMonitor;stop;(long);generated",
"org.apache.commons.io.monitor;FileAlterationObserver;checkAndNotify;();generated",
"org.apache.commons.io.monitor;FileAlterationObserver;destroy;();generated",
"org.apache.commons.io.monitor;FileAlterationObserver;initialize;();generated",
"org.apache.commons.io.monitor;FileAlterationObserver;removeListener;(FileAlterationListener);generated",
"org.apache.commons.io.monitor;FileEntry;getLastModified;();generated",
"org.apache.commons.io.monitor;FileEntry;getLength;();generated",
"org.apache.commons.io.monitor;FileEntry;getLevel;();generated",
"org.apache.commons.io.monitor;FileEntry;isDirectory;();generated",
"org.apache.commons.io.monitor;FileEntry;isExists;();generated",
"org.apache.commons.io.monitor;FileEntry;refresh;(File);generated",
"org.apache.commons.io.monitor;FileEntry;setDirectory;(boolean);generated",
"org.apache.commons.io.monitor;FileEntry;setExists;(boolean);generated",
"org.apache.commons.io.monitor;FileEntry;setLastModified;(long);generated",
"org.apache.commons.io.monitor;FileEntry;setLength;(long);generated",
"org.apache.commons.io.output;AbstractByteArrayOutputStream;AbstractByteArrayOutputStream;();generated",
"org.apache.commons.io.output;AbstractByteArrayOutputStream;reset;();generated",
"org.apache.commons.io.output;AbstractByteArrayOutputStream;size;();generated",
"org.apache.commons.io.output;AbstractByteArrayOutputStream;toByteArray;();generated",
"org.apache.commons.io.output;AbstractByteArrayOutputStream;toInputStream;();generated",
"org.apache.commons.io.output;AbstractByteArrayOutputStream;write;(InputStream);generated",
"org.apache.commons.io.output;AbstractByteArrayOutputStream;writeTo;(OutputStream);generated",
"org.apache.commons.io.output;BrokenOutputStream;BrokenOutputStream;();generated",
"org.apache.commons.io.output;BrokenOutputStream;BrokenOutputStream;(IOException);generated",
"org.apache.commons.io.output;BrokenWriter;BrokenWriter;();generated",
"org.apache.commons.io.output;BrokenWriter;BrokenWriter;(IOException);generated",
"org.apache.commons.io.output;ByteArrayOutputStream;ByteArrayOutputStream;();generated",
"org.apache.commons.io.output;ByteArrayOutputStream;ByteArrayOutputStream;(int);generated",
"org.apache.commons.io.output;ByteArrayOutputStream;toBufferedInputStream;(InputStream);generated",
"org.apache.commons.io.output;ByteArrayOutputStream;toBufferedInputStream;(InputStream,int);generated",
"org.apache.commons.io.output;ChunkedWriter;ChunkedWriter;(Writer);generated",
"org.apache.commons.io.output;ChunkedWriter;ChunkedWriter;(Writer,int);generated",
"org.apache.commons.io.output;CloseShieldWriter;CloseShieldWriter;(Writer);generated",
"org.apache.commons.io.output;CloseShieldWriter;wrap;(Writer);generated",
"org.apache.commons.io.output;ClosedOutputStream;ClosedOutputStream;();generated",
"org.apache.commons.io.output;ClosedWriter;ClosedWriter;();generated",
"org.apache.commons.io.output;CountingOutputStream;getByteCount;();generated",
"org.apache.commons.io.output;CountingOutputStream;getCount;();generated",
"org.apache.commons.io.output;CountingOutputStream;resetByteCount;();generated",
"org.apache.commons.io.output;CountingOutputStream;resetCount;();generated",
"org.apache.commons.io.output;DeferredFileOutputStream;isInMemory;();generated",
"org.apache.commons.io.output;DeferredFileOutputStream;toInputStream;();generated",
"org.apache.commons.io.output;DemuxOutputStream;DemuxOutputStream;();generated",
"org.apache.commons.io.output;DemuxOutputStream;bindStream;(OutputStream);generated",
"org.apache.commons.io.output;FileWriterWithEncoding;FileWriterWithEncoding;(File,Charset);generated",
"org.apache.commons.io.output;FileWriterWithEncoding;FileWriterWithEncoding;(File,Charset,boolean);generated",
"org.apache.commons.io.output;FileWriterWithEncoding;FileWriterWithEncoding;(File,CharsetEncoder);generated",
"org.apache.commons.io.output;FileWriterWithEncoding;FileWriterWithEncoding;(File,CharsetEncoder,boolean);generated",
"org.apache.commons.io.output;FileWriterWithEncoding;FileWriterWithEncoding;(File,String);generated",
"org.apache.commons.io.output;FileWriterWithEncoding;FileWriterWithEncoding;(File,String,boolean);generated",
"org.apache.commons.io.output;FileWriterWithEncoding;FileWriterWithEncoding;(String,Charset);generated",
"org.apache.commons.io.output;FileWriterWithEncoding;FileWriterWithEncoding;(String,Charset,boolean);generated",
"org.apache.commons.io.output;FileWriterWithEncoding;FileWriterWithEncoding;(String,CharsetEncoder);generated",
"org.apache.commons.io.output;FileWriterWithEncoding;FileWriterWithEncoding;(String,CharsetEncoder,boolean);generated",
"org.apache.commons.io.output;FileWriterWithEncoding;FileWriterWithEncoding;(String,String);generated",
"org.apache.commons.io.output;FileWriterWithEncoding;FileWriterWithEncoding;(String,String,boolean);generated",
"org.apache.commons.io.output;LockableFileWriter;LockableFileWriter;(File);generated",
"org.apache.commons.io.output;LockableFileWriter;LockableFileWriter;(File,Charset);generated",
"org.apache.commons.io.output;LockableFileWriter;LockableFileWriter;(File,String);generated",
"org.apache.commons.io.output;LockableFileWriter;LockableFileWriter;(File,boolean);generated",
"org.apache.commons.io.output;LockableFileWriter;LockableFileWriter;(String);generated",
"org.apache.commons.io.output;LockableFileWriter;LockableFileWriter;(String,boolean);generated",
"org.apache.commons.io.output;NullOutputStream;NullOutputStream;();generated",
"org.apache.commons.io.output;NullPrintStream;NullPrintStream;();generated",
"org.apache.commons.io.output;NullWriter;NullWriter;();generated",
"org.apache.commons.io.output;ProxyWriter;ProxyWriter;(Writer);generated",
"org.apache.commons.io.output;QueueOutputStream;QueueOutputStream;();generated",
"org.apache.commons.io.output;QueueOutputStream;QueueOutputStream;(BlockingQueue);generated",
"org.apache.commons.io.output;QueueOutputStream;newQueueInputStream;();generated",
"org.apache.commons.io.output;StringBuilderWriter;StringBuilderWriter;();generated",
"org.apache.commons.io.output;StringBuilderWriter;StringBuilderWriter;(int);generated",
"org.apache.commons.io.output;TaggedOutputStream;isCauseOf;(Exception);generated",
"org.apache.commons.io.output;TaggedOutputStream;throwIfCauseOf;(Exception);generated",
"org.apache.commons.io.output;TaggedWriter;TaggedWriter;(Writer);generated",
"org.apache.commons.io.output;TaggedWriter;isCauseOf;(Exception);generated",
"org.apache.commons.io.output;TaggedWriter;throwIfCauseOf;(Exception);generated",
"org.apache.commons.io.output;ThresholdingOutputStream;ThresholdingOutputStream;(int);generated",
"org.apache.commons.io.output;ThresholdingOutputStream;getByteCount;();generated",
"org.apache.commons.io.output;ThresholdingOutputStream;getThreshold;();generated",
"org.apache.commons.io.output;ThresholdingOutputStream;isThresholdExceeded;();generated",
"org.apache.commons.io.output;UncheckedFilterWriter;on;(Writer);generated",
"org.apache.commons.io.output;UnsynchronizedByteArrayOutputStream;UnsynchronizedByteArrayOutputStream;();generated",
"org.apache.commons.io.output;UnsynchronizedByteArrayOutputStream;UnsynchronizedByteArrayOutputStream;(int);generated",
"org.apache.commons.io.output;UnsynchronizedByteArrayOutputStream;toBufferedInputStream;(InputStream);generated",
"org.apache.commons.io.output;UnsynchronizedByteArrayOutputStream;toBufferedInputStream;(InputStream,int);generated",
"org.apache.commons.io.output;XmlStreamWriter;XmlStreamWriter;(File);generated",
"org.apache.commons.io.serialization;ClassNameMatcher;matches;(String);generated",
"org.apache.commons.io;ByteOrderMark;get;(int);generated",
"org.apache.commons.io;ByteOrderMark;getBytes;();generated",
"org.apache.commons.io;ByteOrderMark;length;();generated",
"org.apache.commons.io;ByteOrderParser;parseByteOrder;(String);generated",
"org.apache.commons.io;Charsets;Charsets;();generated",
"org.apache.commons.io;Charsets;requiredCharsets;();generated",
"org.apache.commons.io;Charsets;toCharset;(Charset);generated",
"org.apache.commons.io;Charsets;toCharset;(String);generated",
"org.apache.commons.io;CopyUtils;CopyUtils;();generated",
"org.apache.commons.io;CopyUtils;copy;(Reader,OutputStream);generated",
"org.apache.commons.io;CopyUtils;copy;(Reader,OutputStream,String);generated",
"org.apache.commons.io;CopyUtils;copy;(String,OutputStream);generated",
"org.apache.commons.io;CopyUtils;copy;(String,OutputStream,String);generated",
"org.apache.commons.io;DirectoryWalker$CancelException;getDepth;();generated",
"org.apache.commons.io;EndianUtils;EndianUtils;();generated",
"org.apache.commons.io;EndianUtils;readSwappedDouble;(InputStream);generated",
"org.apache.commons.io;EndianUtils;readSwappedDouble;(byte[],int);generated",
"org.apache.commons.io;EndianUtils;readSwappedFloat;(InputStream);generated",
"org.apache.commons.io;EndianUtils;readSwappedFloat;(byte[],int);generated",
"org.apache.commons.io;EndianUtils;readSwappedInteger;(InputStream);generated",
"org.apache.commons.io;EndianUtils;readSwappedInteger;(byte[],int);generated",
"org.apache.commons.io;EndianUtils;readSwappedLong;(InputStream);generated",
"org.apache.commons.io;EndianUtils;readSwappedLong;(byte[],int);generated",
"org.apache.commons.io;EndianUtils;readSwappedShort;(InputStream);generated",
"org.apache.commons.io;EndianUtils;readSwappedShort;(byte[],int);generated",
"org.apache.commons.io;EndianUtils;readSwappedUnsignedInteger;(InputStream);generated",
"org.apache.commons.io;EndianUtils;readSwappedUnsignedInteger;(byte[],int);generated",
"org.apache.commons.io;EndianUtils;readSwappedUnsignedShort;(InputStream);generated",
"org.apache.commons.io;EndianUtils;readSwappedUnsignedShort;(byte[],int);generated",
"org.apache.commons.io;EndianUtils;swapDouble;(double);generated",
"org.apache.commons.io;EndianUtils;swapFloat;(float);generated",
"org.apache.commons.io;EndianUtils;swapInteger;(int);generated",
"org.apache.commons.io;EndianUtils;swapLong;(long);generated",
"org.apache.commons.io;EndianUtils;swapShort;(short);generated",
"org.apache.commons.io;EndianUtils;writeSwappedDouble;(OutputStream,double);generated",
"org.apache.commons.io;EndianUtils;writeSwappedDouble;(byte[],int,double);generated",
"org.apache.commons.io;EndianUtils;writeSwappedFloat;(OutputStream,float);generated",
"org.apache.commons.io;EndianUtils;writeSwappedFloat;(byte[],int,float);generated",
"org.apache.commons.io;EndianUtils;writeSwappedInteger;(OutputStream,int);generated",
"org.apache.commons.io;EndianUtils;writeSwappedInteger;(byte[],int,int);generated",
"org.apache.commons.io;EndianUtils;writeSwappedLong;(OutputStream,long);generated",
"org.apache.commons.io;EndianUtils;writeSwappedLong;(byte[],int,long);generated",
"org.apache.commons.io;EndianUtils;writeSwappedShort;(OutputStream,short);generated",
"org.apache.commons.io;EndianUtils;writeSwappedShort;(byte[],int,short);generated",
"org.apache.commons.io;FileCleaner;FileCleaner;();generated",
"org.apache.commons.io;FileCleaner;exitWhenFinished;();generated",
"org.apache.commons.io;FileCleaner;getInstance;();generated",
"org.apache.commons.io;FileCleaner;getTrackCount;();generated",
"org.apache.commons.io;FileCleaner;track;(File,Object);generated",
"org.apache.commons.io;FileCleaner;track;(File,Object,FileDeleteStrategy);generated",
"org.apache.commons.io;FileCleaner;track;(String,Object);generated",
"org.apache.commons.io;FileCleaner;track;(String,Object,FileDeleteStrategy);generated",
"org.apache.commons.io;FileCleaningTracker;FileCleaningTracker;();generated",
"org.apache.commons.io;FileCleaningTracker;exitWhenFinished;();generated",
"org.apache.commons.io;FileCleaningTracker;getTrackCount;();generated",
"org.apache.commons.io;FileCleaningTracker;track;(File,Object);generated",
"org.apache.commons.io;FileCleaningTracker;track;(File,Object,FileDeleteStrategy);generated",
"org.apache.commons.io;FileCleaningTracker;track;(String,Object);generated",
"org.apache.commons.io;FileCleaningTracker;track;(String,Object,FileDeleteStrategy);generated",
"org.apache.commons.io;FileDeleteStrategy;delete;(File);generated",
"org.apache.commons.io;FileDeleteStrategy;deleteQuietly;(File);generated",
"org.apache.commons.io;FileExistsException;FileExistsException;();generated",
"org.apache.commons.io;FileExistsException;FileExistsException;(File);generated",
"org.apache.commons.io;FileExistsException;FileExistsException;(String);generated",
"org.apache.commons.io;FileSystem;getCurrent;();generated",
"org.apache.commons.io;FileSystem;getIllegalFileNameChars;();generated",
"org.apache.commons.io;FileSystem;getMaxFileNameLength;();generated",
"org.apache.commons.io;FileSystem;getMaxPathLength;();generated",
"org.apache.commons.io;FileSystem;getNameSeparator;();generated",
"org.apache.commons.io;FileSystem;getReservedFileNames;();generated",
"org.apache.commons.io;FileSystem;isCasePreserving;();generated",
"org.apache.commons.io;FileSystem;isCaseSensitive;();generated",
"org.apache.commons.io;FileSystem;isLegalFileName;(CharSequence);generated",
"org.apache.commons.io;FileSystem;isReservedFileName;(CharSequence);generated",
"org.apache.commons.io;FileSystem;normalizeSeparators;(String);generated",
"org.apache.commons.io;FileSystem;supportsDriveLetter;();generated",
"org.apache.commons.io;FileSystemUtils;FileSystemUtils;();generated",
"org.apache.commons.io;FileSystemUtils;freeSpace;(String);generated",
"org.apache.commons.io;FileSystemUtils;freeSpaceKb;();generated",
"org.apache.commons.io;FileSystemUtils;freeSpaceKb;(String);generated",
"org.apache.commons.io;FileSystemUtils;freeSpaceKb;(String,long);generated",
"org.apache.commons.io;FileSystemUtils;freeSpaceKb;(long);generated",
"org.apache.commons.io;FileUtils;FileUtils;();generated",
"org.apache.commons.io;FileUtils;byteCountToDisplaySize;(BigInteger);generated",
"org.apache.commons.io;FileUtils;byteCountToDisplaySize;(Number);generated",
"org.apache.commons.io;FileUtils;byteCountToDisplaySize;(long);generated",
"org.apache.commons.io;FileUtils;checksumCRC32;(File);generated",
"org.apache.commons.io;FileUtils;cleanDirectory;(File);generated",
"org.apache.commons.io;FileUtils;contentEquals;(File,File);generated",
"org.apache.commons.io;FileUtils;contentEqualsIgnoreEOL;(File,File,String);generated",
"org.apache.commons.io;FileUtils;copyDirectory;(File,File);generated",
"org.apache.commons.io;FileUtils;copyDirectory;(File,File,FileFilter);generated",
"org.apache.commons.io;FileUtils;copyDirectory;(File,File,FileFilter,boolean);generated",
"org.apache.commons.io;FileUtils;copyDirectory;(File,File,FileFilter,boolean,CopyOption[]);generated",
"org.apache.commons.io;FileUtils;copyDirectory;(File,File,boolean);generated",
"org.apache.commons.io;FileUtils;copyDirectoryToDirectory;(File,File);generated",
"org.apache.commons.io;FileUtils;copyFile;(File,File);generated",
"org.apache.commons.io;FileUtils;copyFile;(File,File,CopyOption[]);generated",
"org.apache.commons.io;FileUtils;copyFile;(File,File,boolean);generated",
"org.apache.commons.io;FileUtils;copyFile;(File,File,boolean,CopyOption[]);generated",
"org.apache.commons.io;FileUtils;copyFile;(File,OutputStream);generated",
"org.apache.commons.io;FileUtils;copyFileToDirectory;(File,File);generated",
"org.apache.commons.io;FileUtils;copyFileToDirectory;(File,File,boolean);generated",
"org.apache.commons.io;FileUtils;copyInputStreamToFile;(InputStream,File);generated",
"org.apache.commons.io;FileUtils;copyToDirectory;(File,File);generated",
"org.apache.commons.io;FileUtils;copyToDirectory;(Iterable,File);generated",
"org.apache.commons.io;FileUtils;copyToFile;(InputStream,File);generated",
"org.apache.commons.io;FileUtils;copyURLToFile;(URL,File);generated",
"org.apache.commons.io;FileUtils;copyURLToFile;(URL,File,int,int);generated",
"org.apache.commons.io;FileUtils;createParentDirectories;(File);generated",
"org.apache.commons.io;FileUtils;current;();generated",
"org.apache.commons.io;FileUtils;deleteDirectory;(File);generated",
"org.apache.commons.io;FileUtils;deleteQuietly;(File);generated",
"org.apache.commons.io;FileUtils;directoryContains;(File,File);generated",
"org.apache.commons.io;FileUtils;forceDelete;(File);generated",
"org.apache.commons.io;FileUtils;forceDeleteOnExit;(File);generated",
"org.apache.commons.io;FileUtils;forceMkdir;(File);generated",
"org.apache.commons.io;FileUtils;forceMkdirParent;(File);generated",
"org.apache.commons.io;FileUtils;getTempDirectory;();generated",
"org.apache.commons.io;FileUtils;getTempDirectoryPath;();generated",
"org.apache.commons.io;FileUtils;getUserDirectory;();generated",
"org.apache.commons.io;FileUtils;getUserDirectoryPath;();generated",
"org.apache.commons.io;FileUtils;isDirectory;(File,LinkOption[]);generated",
"org.apache.commons.io;FileUtils;isEmptyDirectory;(File);generated",
"org.apache.commons.io;FileUtils;isFileNewer;(File,ChronoLocalDate);generated",
"org.apache.commons.io;FileUtils;isFileNewer;(File,ChronoLocalDate,LocalTime);generated",
"org.apache.commons.io;FileUtils;isFileNewer;(File,ChronoLocalDateTime);generated",
"org.apache.commons.io;FileUtils;isFileNewer;(File,ChronoLocalDateTime,ZoneId);generated",
"org.apache.commons.io;FileUtils;isFileNewer;(File,ChronoZonedDateTime);generated",
"org.apache.commons.io;FileUtils;isFileNewer;(File,Date);generated",
"org.apache.commons.io;FileUtils;isFileNewer;(File,File);generated",
"org.apache.commons.io;FileUtils;isFileNewer;(File,FileTime);generated",
"org.apache.commons.io;FileUtils;isFileNewer;(File,Instant);generated",
"org.apache.commons.io;FileUtils;isFileNewer;(File,long);generated",
"org.apache.commons.io;FileUtils;isFileOlder;(File,ChronoLocalDate);generated",
"org.apache.commons.io;FileUtils;isFileOlder;(File,ChronoLocalDate,LocalTime);generated",
"org.apache.commons.io;FileUtils;isFileOlder;(File,ChronoLocalDateTime);generated",
"org.apache.commons.io;FileUtils;isFileOlder;(File,ChronoLocalDateTime,ZoneId);generated",
"org.apache.commons.io;FileUtils;isFileOlder;(File,ChronoZonedDateTime);generated",
"org.apache.commons.io;FileUtils;isFileOlder;(File,Date);generated",
"org.apache.commons.io;FileUtils;isFileOlder;(File,File);generated",
"org.apache.commons.io;FileUtils;isFileOlder;(File,FileTime);generated",
"org.apache.commons.io;FileUtils;isFileOlder;(File,Instant);generated",
"org.apache.commons.io;FileUtils;isFileOlder;(File,long);generated",
"org.apache.commons.io;FileUtils;isRegularFile;(File,LinkOption[]);generated",
"org.apache.commons.io;FileUtils;isSymlink;(File);generated",
"org.apache.commons.io;FileUtils;iterateFiles;(File,IOFileFilter,IOFileFilter);generated",
"org.apache.commons.io;FileUtils;iterateFiles;(File,String[],boolean);generated",
"org.apache.commons.io;FileUtils;iterateFilesAndDirs;(File,IOFileFilter,IOFileFilter);generated",
"org.apache.commons.io;FileUtils;lastModified;(File);generated",
"org.apache.commons.io;FileUtils;lastModifiedFileTime;(File);generated",
"org.apache.commons.io;FileUtils;lastModifiedUnchecked;(File);generated",
"org.apache.commons.io;FileUtils;lineIterator;(File);generated",
"org.apache.commons.io;FileUtils;lineIterator;(File,String);generated",
"org.apache.commons.io;FileUtils;listFiles;(File,IOFileFilter,IOFileFilter);generated",
"org.apache.commons.io;FileUtils;listFiles;(File,String[],boolean);generated",
"org.apache.commons.io;FileUtils;listFilesAndDirs;(File,IOFileFilter,IOFileFilter);generated",
"org.apache.commons.io;FileUtils;moveDirectory;(File,File);generated",
"org.apache.commons.io;FileUtils;moveDirectoryToDirectory;(File,File,boolean);generated",
"org.apache.commons.io;FileUtils;moveFile;(File,File);generated",
"org.apache.commons.io;FileUtils;moveFile;(File,File,CopyOption[]);generated",
"org.apache.commons.io;FileUtils;moveFileToDirectory;(File,File,boolean);generated",
"org.apache.commons.io;FileUtils;moveToDirectory;(File,File,boolean);generated",
"org.apache.commons.io;FileUtils;newOutputStream;(File,boolean);generated",
"org.apache.commons.io;FileUtils;openInputStream;(File);generated",
"org.apache.commons.io;FileUtils;openOutputStream;(File);generated",
"org.apache.commons.io;FileUtils;openOutputStream;(File,boolean);generated",
"org.apache.commons.io;FileUtils;readFileToByteArray;(File);generated",
"org.apache.commons.io;FileUtils;readFileToString;(File);generated",
"org.apache.commons.io;FileUtils;readFileToString;(File,Charset);generated",
"org.apache.commons.io;FileUtils;readFileToString;(File,String);generated",
"org.apache.commons.io;FileUtils;readLines;(File);generated",
"org.apache.commons.io;FileUtils;readLines;(File,Charset);generated",
"org.apache.commons.io;FileUtils;readLines;(File,String);generated",
"org.apache.commons.io;FileUtils;sizeOf;(File);generated",
"org.apache.commons.io;FileUtils;sizeOfAsBigInteger;(File);generated",
"org.apache.commons.io;FileUtils;sizeOfDirectory;(File);generated",
"org.apache.commons.io;FileUtils;sizeOfDirectoryAsBigInteger;(File);generated",
"org.apache.commons.io;FileUtils;streamFiles;(File,boolean,String[]);generated",
"org.apache.commons.io;FileUtils;toFile;(URL);generated",
"org.apache.commons.io;FileUtils;toFiles;(URL[]);generated",
"org.apache.commons.io;FileUtils;touch;(File);generated",
"org.apache.commons.io;FileUtils;waitFor;(File,int);generated",
"org.apache.commons.io;FileUtils;write;(File,CharSequence);generated",
"org.apache.commons.io;FileUtils;write;(File,CharSequence,Charset);generated",
"org.apache.commons.io;FileUtils;write;(File,CharSequence,Charset,boolean);generated",
"org.apache.commons.io;FileUtils;write;(File,CharSequence,String);generated",
"org.apache.commons.io;FileUtils;write;(File,CharSequence,String,boolean);generated",
"org.apache.commons.io;FileUtils;write;(File,CharSequence,boolean);generated",
"org.apache.commons.io;FileUtils;writeByteArrayToFile;(File,byte[]);generated",
"org.apache.commons.io;FileUtils;writeByteArrayToFile;(File,byte[],boolean);generated",
"org.apache.commons.io;FileUtils;writeByteArrayToFile;(File,byte[],int,int);generated",
"org.apache.commons.io;FileUtils;writeByteArrayToFile;(File,byte[],int,int,boolean);generated",
"org.apache.commons.io;FileUtils;writeLines;(File,Collection);generated",
"org.apache.commons.io;FileUtils;writeLines;(File,Collection,String);generated",
"org.apache.commons.io;FileUtils;writeLines;(File,Collection,String,boolean);generated",
"org.apache.commons.io;FileUtils;writeLines;(File,Collection,boolean);generated",
"org.apache.commons.io;FileUtils;writeLines;(File,String,Collection);generated",
"org.apache.commons.io;FileUtils;writeLines;(File,String,Collection,String);generated",
"org.apache.commons.io;FileUtils;writeLines;(File,String,Collection,String,boolean);generated",
"org.apache.commons.io;FileUtils;writeLines;(File,String,Collection,boolean);generated",
"org.apache.commons.io;FileUtils;writeStringToFile;(File,String);generated",
"org.apache.commons.io;FileUtils;writeStringToFile;(File,String,Charset);generated",
"org.apache.commons.io;FileUtils;writeStringToFile;(File,String,Charset,boolean);generated",
"org.apache.commons.io;FileUtils;writeStringToFile;(File,String,String);generated",
"org.apache.commons.io;FileUtils;writeStringToFile;(File,String,String,boolean);generated",
"org.apache.commons.io;FileUtils;writeStringToFile;(File,String,boolean);generated",
"org.apache.commons.io;FilenameUtils;FilenameUtils;();generated",
"org.apache.commons.io;FilenameUtils;directoryContains;(String,String);generated",
"org.apache.commons.io;FilenameUtils;equals;(String,String);generated",
"org.apache.commons.io;FilenameUtils;equals;(String,String,boolean,IOCase);generated",
"org.apache.commons.io;FilenameUtils;equalsNormalized;(String,String);generated",
"org.apache.commons.io;FilenameUtils;equalsNormalizedOnSystem;(String,String);generated",
"org.apache.commons.io;FilenameUtils;equalsOnSystem;(String,String);generated",
"org.apache.commons.io;FilenameUtils;getPrefixLength;(String);generated",
"org.apache.commons.io;FilenameUtils;indexOfExtension;(String);generated",
"org.apache.commons.io;FilenameUtils;indexOfLastSeparator;(String);generated",
"org.apache.commons.io;FilenameUtils;isExtension;(String,Collection);generated",
"org.apache.commons.io;FilenameUtils;isExtension;(String,String);generated",
"org.apache.commons.io;FilenameUtils;isExtension;(String,String[]);generated",
"org.apache.commons.io;FilenameUtils;separatorsToSystem;(String);generated",
"org.apache.commons.io;FilenameUtils;separatorsToUnix;(String);generated",
"org.apache.commons.io;FilenameUtils;separatorsToWindows;(String);generated",
"org.apache.commons.io;FilenameUtils;wildcardMatch;(String,String);generated",
"org.apache.commons.io;FilenameUtils;wildcardMatch;(String,String,IOCase);generated",
"org.apache.commons.io;FilenameUtils;wildcardMatchOnSystem;(String,String);generated",
"org.apache.commons.io;HexDump;HexDump;();generated",
"org.apache.commons.io;HexDump;dump;(byte[],long,OutputStream,int);generated",
"org.apache.commons.io;IOCase;checkCompareTo;(String,String);generated",
"org.apache.commons.io;IOCase;checkEndsWith;(String,String);generated",
"org.apache.commons.io;IOCase;checkEquals;(String,String);generated",
"org.apache.commons.io;IOCase;checkIndexOf;(String,int,String);generated",
"org.apache.commons.io;IOCase;checkRegionMatches;(String,int,String);generated",
"org.apache.commons.io;IOCase;checkStartsWith;(String,String);generated",
"org.apache.commons.io;IOCase;forName;(String);generated",
"org.apache.commons.io;IOCase;getName;();generated",
"org.apache.commons.io;IOCase;isCaseSensitive;();generated",
"org.apache.commons.io;IOCase;isCaseSensitive;(IOCase);generated",
"org.apache.commons.io;IOCase;toString;();generated",
"org.apache.commons.io;IOCase;value;(IOCase,IOCase);generated",
"org.apache.commons.io;IOExceptionList;checkEmpty;(List,Object);generated",
"org.apache.commons.io;IOExceptionList;getCause;(int,Class);generated",
"org.apache.commons.io;IOExceptionWithCause;IOExceptionWithCause;(String,Throwable);generated",
"org.apache.commons.io;IOExceptionWithCause;IOExceptionWithCause;(Throwable);generated",
"org.apache.commons.io;IOIndexedException;IOIndexedException;(int,Throwable);generated",
"org.apache.commons.io;IOIndexedException;getIndex;();generated",
"org.apache.commons.io;IOUtils;IOUtils;();generated",
"org.apache.commons.io;IOUtils;byteArray;();generated",
"org.apache.commons.io;IOUtils;byteArray;(int);generated",
"org.apache.commons.io;IOUtils;close;(Closeable);generated",
"org.apache.commons.io;IOUtils;close;(Closeable,IOConsumer);generated",
"org.apache.commons.io;IOUtils;close;(Closeable[]);generated",
"org.apache.commons.io;IOUtils;close;(URLConnection);generated",
"org.apache.commons.io;IOUtils;closeQuietly;(Closeable);generated",
"org.apache.commons.io;IOUtils;closeQuietly;(Closeable,Consumer);generated",
"org.apache.commons.io;IOUtils;closeQuietly;(Closeable[]);generated",
"org.apache.commons.io;IOUtils;closeQuietly;(InputStream);generated",
"org.apache.commons.io;IOUtils;closeQuietly;(OutputStream);generated",
"org.apache.commons.io;IOUtils;closeQuietly;(Reader);generated",
"org.apache.commons.io;IOUtils;closeQuietly;(Selector);generated",
"org.apache.commons.io;IOUtils;closeQuietly;(ServerSocket);generated",
"org.apache.commons.io;IOUtils;closeQuietly;(Socket);generated",
"org.apache.commons.io;IOUtils;closeQuietly;(Writer);generated",
"org.apache.commons.io;IOUtils;consume;(InputStream);generated",
"org.apache.commons.io;IOUtils;contentEquals;(InputStream,InputStream);generated",
"org.apache.commons.io;IOUtils;contentEquals;(Reader,Reader);generated",
"org.apache.commons.io;IOUtils;contentEqualsIgnoreEOL;(Reader,Reader);generated",
"org.apache.commons.io;IOUtils;copy;(ByteArrayOutputStream);generated",
"org.apache.commons.io;IOUtils;copy;(Reader,OutputStream);generated",
"org.apache.commons.io;IOUtils;copy;(Reader,OutputStream,Charset);generated",
"org.apache.commons.io;IOUtils;copy;(Reader,OutputStream,String);generated",
"org.apache.commons.io;IOUtils;copy;(URL,File);generated",
"org.apache.commons.io;IOUtils;copy;(URL,OutputStream);generated",
"org.apache.commons.io;IOUtils;length;(CharSequence);generated",
"org.apache.commons.io;IOUtils;length;(Object[]);generated",
"org.apache.commons.io;IOUtils;length;(byte[]);generated",
"org.apache.commons.io;IOUtils;length;(char[]);generated",
"org.apache.commons.io;IOUtils;resourceToByteArray;(String);generated",
"org.apache.commons.io;IOUtils;resourceToByteArray;(String,ClassLoader);generated",
"org.apache.commons.io;IOUtils;resourceToString;(String,Charset);generated",
"org.apache.commons.io;IOUtils;resourceToString;(String,Charset,ClassLoader);generated",
"org.apache.commons.io;IOUtils;resourceToURL;(String);generated",
"org.apache.commons.io;IOUtils;resourceToURL;(String,ClassLoader);generated",
"org.apache.commons.io;IOUtils;skip;(InputStream,long);generated",
"org.apache.commons.io;IOUtils;skip;(ReadableByteChannel,long);generated",
"org.apache.commons.io;IOUtils;skip;(Reader,long);generated",
"org.apache.commons.io;IOUtils;skipFully;(InputStream,long);generated",
"org.apache.commons.io;IOUtils;skipFully;(ReadableByteChannel,long);generated",
"org.apache.commons.io;IOUtils;skipFully;(Reader,long);generated",
"org.apache.commons.io;IOUtils;toBufferedInputStream;(InputStream);generated",
"org.apache.commons.io;IOUtils;toBufferedInputStream;(InputStream,int);generated",
"org.apache.commons.io;IOUtils;toByteArray;(InputStream);generated",
"org.apache.commons.io;IOUtils;toByteArray;(Reader);generated",
"org.apache.commons.io;IOUtils;toByteArray;(Reader,Charset);generated",
"org.apache.commons.io;IOUtils;toByteArray;(Reader,String);generated",
"org.apache.commons.io;IOUtils;toByteArray;(URI);generated",
"org.apache.commons.io;IOUtils;toByteArray;(URL);generated",
"org.apache.commons.io;IOUtils;toByteArray;(URLConnection);generated",
"org.apache.commons.io;IOUtils;toString;(URI);generated",
"org.apache.commons.io;IOUtils;toString;(URI,Charset);generated",
"org.apache.commons.io;IOUtils;toString;(URI,String);generated",
"org.apache.commons.io;IOUtils;toString;(URL);generated",
"org.apache.commons.io;IOUtils;toString;(URL,Charset);generated",
"org.apache.commons.io;IOUtils;toString;(URL,String);generated",
"org.apache.commons.io;IOUtils;write;(CharSequence,OutputStream);generated",
"org.apache.commons.io;IOUtils;write;(CharSequence,OutputStream,Charset);generated",
"org.apache.commons.io;IOUtils;write;(CharSequence,OutputStream,String);generated",
"org.apache.commons.io;IOUtils;write;(String,OutputStream);generated",
"org.apache.commons.io;IOUtils;write;(String,OutputStream,Charset);generated",
"org.apache.commons.io;IOUtils;write;(String,OutputStream,String);generated",
"org.apache.commons.io;IOUtils;write;(StringBuffer,OutputStream);generated",
"org.apache.commons.io;IOUtils;write;(StringBuffer,OutputStream,String);generated",
"org.apache.commons.io;IOUtils;write;(char[],OutputStream);generated",
"org.apache.commons.io;IOUtils;write;(char[],OutputStream,Charset);generated",
"org.apache.commons.io;IOUtils;write;(char[],OutputStream,String);generated",
"org.apache.commons.io;LineIterator;closeQuietly;(LineIterator);generated",
"org.apache.commons.io;RandomAccessFileMode;create;(File);generated",
"org.apache.commons.io;RandomAccessFileMode;create;(Path);generated",
"org.apache.commons.io;RandomAccessFileMode;create;(String);generated",
"org.apache.commons.io;RandomAccessFileMode;toString;();generated",
"org.apache.commons.io;StandardLineSeparator;getBytes;(Charset);generated",
"org.apache.commons.io;StandardLineSeparator;getString;();generated",
"org.apache.commons.io;TaggedIOException;isTaggedWith;(Throwable,Object);generated",
"org.apache.commons.io;TaggedIOException;throwCauseIfTaggedWith;(Throwable,Object);generated",
"org.apache.commons.io;UncheckedIO;UncheckedIO;();generated",
"org.apache.commons.io;UncheckedIO;accept;(IOConsumer,Object);generated",
"org.apache.commons.io;UncheckedIO;apply;(IOBiFunction,Object,Object);generated",
"org.apache.commons.io;UncheckedIO;get;(IOSupplier);generated",
"org.apache.commons.io;UncheckedIO;run;(IORunnable);generated",
"org.apache.commons.io;UncheckedIOExceptions;UncheckedIOExceptions;();generated",
"org.apache.commons.io;UncheckedIOExceptions;create;(Object);generated",
"org.apache.commons.io;UncheckedIOExceptions;wrap;(IOException,Object);generated"
]
}
}

View File

@@ -35,8 +35,8 @@ library class ProcessorDefinitionElement extends MethodAccess {
*
* This declares a "target" for this route, described by the URI given as the first argument.
*/
class CamelJavaDSLToDecl extends ProcessorDefinitionElement {
CamelJavaDSLToDecl() { getMethod().hasName("to") }
class CamelJavaDslToDecl extends ProcessorDefinitionElement {
CamelJavaDslToDecl() { getMethod().hasName("to") }
/**
* Gets the URI specified by this `to` declaration.
@@ -47,14 +47,17 @@ class CamelJavaDSLToDecl extends ProcessorDefinitionElement {
deprecated string getURI() { result = getUri() }
}
/** DEPRECATED: Alias for CamelJavaDslToDecl */
deprecated class CamelJavaDSLToDecl = CamelJavaDslToDecl;
/**
* A declaration of a "bean" target in the Apache Camel Java DSL.
*
* This declares a bean to call for this route. The bean is defined either by a Class<?> reference,
* or the bean object itself.
*/
class CamelJavaDSLBeanDecl extends ProcessorDefinitionElement {
CamelJavaDSLBeanDecl() { getMethod().hasName("bean") }
class CamelJavaDslBeanDecl extends ProcessorDefinitionElement {
CamelJavaDslBeanDecl() { getMethod().hasName("bean") }
/**
* Gets a bean class that may be registered as a target by this `bean()` declaration.
@@ -71,6 +74,9 @@ class CamelJavaDSLBeanDecl extends ProcessorDefinitionElement {
}
}
/** DEPRECATED: Alias for CamelJavaDslBeanDecl */
deprecated class CamelJavaDSLBeanDecl = CamelJavaDslBeanDecl;
/**
* A declaration of a "beanRef" target in the Apache Camel Java DSL.
*
@@ -78,8 +84,8 @@ class CamelJavaDSLBeanDecl extends ProcessorDefinitionElement {
* the bean reference is dependent on which registries are used by Apache Camel, but we make the
* assumption that it either represetns a qualified name, or a Srping bean identifier.
*/
class CamelJavaDSLBeanRefDecl extends ProcessorDefinitionElement {
CamelJavaDSLBeanRefDecl() { getMethod().hasName("beanRef") }
class CamelJavaDslBeanRefDecl extends ProcessorDefinitionElement {
CamelJavaDslBeanRefDecl() { getMethod().hasName("beanRef") }
/**
* Gets the string describing the bean referred to.
@@ -98,13 +104,16 @@ class CamelJavaDSLBeanRefDecl extends ProcessorDefinitionElement {
}
}
/** DEPRECATED: Alias for CamelJavaDslBeanRefDecl */
deprecated class CamelJavaDSLBeanRefDecl = CamelJavaDslBeanRefDecl;
/**
* A "method" Camel expression in the Apache Camel Java DSL.
*
* An expression that represents a call to a bean, or particular method on a bean.
*/
class CamelJavaDSLMethodDecl extends MethodAccess {
CamelJavaDSLMethodDecl() {
class CamelJavaDslMethodDecl extends MethodAccess {
CamelJavaDslMethodDecl() {
getMethod()
.getDeclaringType()
.getSourceDeclaration()
@@ -129,3 +138,6 @@ class CamelJavaDSLMethodDecl extends MethodAccess {
else result = getArgument(0).getType()
}
}
/** DEPRECATED: Alias for CamelJavaDslMethodDecl */
deprecated class CamelJavaDSLMethodDecl = CamelJavaDslMethodDecl;

View File

@@ -6,4 +6,5 @@ import java
private module GeneratedFrameworks {
private import apache.IOGenerated
private import kotlin.StdLibGenerated
}

View File

@@ -33,12 +33,12 @@ class PersistentEntity extends RefType {
}
/**
* Gets the access type for this entity as defined by a `@javax.persistence.Access` annotation, if any.
* Gets the access type for this entity as defined by a `@javax.persistence.Access` annotation,
* if any, in lower case.
*/
string getAccessTypeFromAnnotation() {
exists(AccessAnnotation accessType | accessType = this.getAnAnnotation() |
result =
accessType.getValue("value").(FieldRead).getField().(EnumConstant).getName().toLowerCase()
result = accessType.getEnumConstantValue("value").getName().toLowerCase()
)
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
/** Definitions of taint steps in the KotlinStdLib framework */
import java
private import semmle.code.java.dataflow.ExternalFlow
private class KotlinStdLibSummaryCsv extends SummaryModelCsv {
override predicate row(string row) {
row =
[
"kotlin.jvm.internal;ArrayIteratorKt;false;iterator;(Object[]);;Argument[0].ArrayElement;ReturnValue.Element;value;manual",
"kotlin.collections;ArraysKt;false;withIndex;(Object[]);;Argument[0].ArrayElement;ReturnValue;taint;manual"
]
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -13,6 +13,7 @@ import semmle.code.java.frameworks.spring.SpringContext
import semmle.code.java.frameworks.spring.SpringComponentScan
import semmle.code.java.frameworks.spring.SpringConstructorArg
import semmle.code.java.frameworks.spring.SpringController
import semmle.code.java.frameworks.spring.SpringData
import semmle.code.java.frameworks.spring.SpringDescription
import semmle.code.java.frameworks.spring.SpringEntry
import semmle.code.java.frameworks.spring.SpringFlex

View File

@@ -311,9 +311,7 @@ class SpringQualifierDefinitionAnnotation extends Annotation {
/**
* Gets the value of the qualifier field for this qualifier.
*/
string getQualifierValue() {
result = this.getValue("value").(CompileTimeConstantExpr).getStringValue()
}
string getQualifierValue() { result = this.getStringValue("value") }
}
/**
@@ -325,9 +323,7 @@ class SpringQualifierAnnotation extends Annotation {
/**
* Gets the value of the qualifier field for this qualifier.
*/
string getQualifierValue() {
result = this.getValue("value").(CompileTimeConstantExpr).getStringValue()
}
string getQualifierValue() { result = this.getStringValue("value") }
/**
* Gets the bean definition in an XML file that this qualifier resolves to, if any.
@@ -350,9 +346,7 @@ class SpringResourceAnnotation extends Annotation {
/**
* Gets the specified name value, if any.
*/
string getNameValue() {
result = this.getValue("name").(CompileTimeConstantExpr).getStringValue()
}
string getNameValue() { result = this.getStringValue("name") }
/**
* Gets the bean definition in an XML file that the resource resolves to, if any.

View File

@@ -40,16 +40,10 @@ class SpringComponentScan extends Annotation {
*/
string getBasePackages() {
// "value" and "basePackages" are synonymous, and are simple strings
result = this.getAValue("basePackages").(StringLiteral).getValue()
result = this.getAStringArrayValue(["basePackages", "value"])
or
result = this.getAValue("value").(StringLiteral).getValue()
or
exists(TypeLiteral typeLiteral |
// Base package classes are type literals whose package should be considered a base package.
typeLiteral = this.getAValue("basePackageClasses")
|
result = typeLiteral.getReferencedType().(RefType).getPackage().getName()
)
// Base package classes are type literals whose package should be considered a base package.
result = this.getATypeArrayValue("basePackageClasses").(RefType).getPackage().getName()
}
}
@@ -144,8 +138,7 @@ class SpringComponent extends RefType {
if exists(this.getComponentAnnotation().getValue("value"))
then
// If the name has been specified in the component annotation, use that.
result =
this.getComponentAnnotation().getValue("value").(CompileTimeConstantExpr).getStringValue()
result = this.getComponentAnnotation().getStringValue("value")
else
// Otherwise use the name of the class, with the initial letter lower cased.
exists(string name | name = this.getName() |
@@ -204,7 +197,7 @@ class SpringComponent extends RefType {
.getType()
.hasQualifiedName("org.springframework.context.annotation", "Profile")
|
result = profileAnnotation.getAValue("value").(StringLiteral).getValue()
result = profileAnnotation.getAStringArrayValue("value")
)
}
}

View File

@@ -154,9 +154,7 @@ class SpringRequestMappingMethod extends SpringControllerMethod {
}
/** Gets the "value" @RequestMapping annotation value, if present. */
string getValue() {
result = requestMappingAnnotation.getValue("value").(CompileTimeConstantExpr).getStringValue()
}
string getValue() { result = requestMappingAnnotation.getStringValue("value") }
/** Holds if this is considered an `@ResponseBody` method. */
predicate isResponseBody() {

View File

@@ -0,0 +1,17 @@
/**
* Provides classes and predicates for working with Spring classes and interfaces from
* `org.springframework.data`.
*/
import java
private import semmle.code.java.dataflow.ExternalFlow
/**
* Provides models for the `org.springframework.data` package.
*/
private class FlowSummaries extends SummaryModelCsv {
override predicate row(string row) {
row =
"org.springframework.data.repository;CrudRepository;true;save;;;Argument[0];ReturnValue;value;manual"
}
}

View File

@@ -34,5 +34,5 @@ class StrutsActionsAnnotation extends StrutsAnnotation {
/**
* Gets an Action annotation contained in this Actions annotation.
*/
StrutsActionAnnotation getAnAction() { result = this.getAValue("value") }
StrutsActionAnnotation getAnAction() { result = this.getAnArrayValue("value") }
}

View File

@@ -49,7 +49,7 @@ private class Serializable extends ClassStore {
/** The instantiation of a marshallable class, which can be stored to disk as XML. */
private class Marshallable extends ClassStore {
Marshallable() { this.getConstructor().getDeclaringType() instanceof JAXBElement }
Marshallable() { this.getConstructor().getDeclaringType() instanceof JaxbElement }
/** Gets a store, for example `marshaller.marshal(instance)`. */
override Expr getAStore() {
@@ -69,7 +69,7 @@ private Expr getInstanceInput(DataFlow::Node instance, RefType t) {
fa.getField().getDeclaringType() = t
|
t.getASourceSupertype*() instanceof TypeSerializable or
t instanceof JAXBElement
t instanceof JaxbElement
)
}
@@ -98,7 +98,7 @@ private predicate serializableStore(DataFlow::Node instance, Expr store) {
private predicate marshallableStore(DataFlow::Node instance, Expr store) {
exists(MethodAccess m |
store = m and
m.getMethod() instanceof JAXBMarshalMethod and
m.getMethod() instanceof JaxbMarshalMethod and
instance.asExpr() = m.getArgument(0)
)
}

View File

@@ -24,7 +24,7 @@ private class DefaultSafeExternalApiMethod extends SafeExternalApiMethod {
or
this.getDeclaringType().hasQualifiedName("org.apache.commons.lang3", "Validate")
or
this.getQualifiedName() = "Objects.equals"
this.hasQualifiedName("java.util", "Objects", "equals")
or
this.getDeclaringType() instanceof TypeString and this.getName() = "equals"
or
@@ -92,10 +92,7 @@ class ExternalApiDataNode extends DataFlow::Node {
int getIndex() { result = i }
/** Gets the description of the method being called. */
string getMethodDescription() {
result =
this.getMethod().getDeclaringType().getPackage() + "." + this.getMethod().getQualifiedName()
}
string getMethodDescription() { result = this.getMethod().getQualifiedName() }
}
/** DEPRECATED: Alias for ExternalApiDataNode */

View File

@@ -102,11 +102,25 @@ private class PendingIntentSentSinkModels extends SinkModelCsv {
"android.app;NotificationManager;true;notify;(String,int,Notification);;Argument[2];pending-intent-sent;manual",
"android.app;NotificationManager;true;notifyAsPackage;(String,String,int,Notification);;Argument[3];pending-intent-sent;manual",
"android.app;NotificationManager;true;notifyAsUser;(String,int,Notification,UserHandle);;Argument[2];pending-intent-sent;manual",
"androidx.core.app;NotificationManagerCompat;true;notify;(int,Notification);;Argument[1];pending-intent-sent;manual",
"androidx.core.app;NotificationManagerCompat;true;notify;(String,int,Notification);;Argument[2];pending-intent-sent;manual",
"android.app;PendingIntent;false;send;(Context,int,Intent,OnFinished,Handler,String,Bundle);;Argument[2];pending-intent-sent;manual",
"android.app;PendingIntent;false;send;(Context,int,Intent,OnFinished,Handler,String);;Argument[2];pending-intent-sent;manual",
"android.app;PendingIntent;false;send;(Context,int,Intent,OnFinished,Handler);;Argument[2];pending-intent-sent;manual",
"android.app;PendingIntent;false;send;(Context,int,Intent);;Argument[2];pending-intent-sent;manual",
"android.app;Activity;true;setResult;(int,Intent);;Argument[1];pending-intent-sent;manual"
"android.app;Activity;true;setResult;(int,Intent);;Argument[1];pending-intent-sent;manual",
"android.app;AlarmManager;true;set;(int,long,PendingIntent);;Argument[2];pending-intent-sent;manual",
"android.app;AlarmManager;true;setAlarmClock;;;Argument[1];pending-intent-sent;manual",
"android.app;AlarmManager;true;setAndAllowWhileIdle;;;Argument[2];pending-intent-sent;manual",
"android.app;AlarmManager;true;setExact;(int,long,PendingIntent);;Argument[2];pending-intent-sent;manual",
"android.app;AlarmManager;true;setExactAndAllowWhileIdle;;;Argument[2];pending-intent-sent;manual",
"android.app;AlarmManager;true;setInexactRepeating;;;Argument[3];pending-intent-sent;manual",
"android.app;AlarmManager;true;setRepeating;;;Argument[3];pending-intent-sent;manual",
"android.app;AlarmManager;true;setWindow;(int,long,long,PendingIntent);;Argument[3];pending-intent-sent;manual",
"androidx.core.app;AlarmManagerCompat;true;setAlarmClock;;;Argument[2..3];pending-intent-sent;manual",
"androidx.core.app;AlarmManagerCompat;true;setAndAllowWhileIdle;;;Argument[3];pending-intent-sent;manual",
"androidx.core.app;AlarmManagerCompat;true;setExact;;;Argument[3];pending-intent-sent;manual",
"androidx.core.app;AlarmManagerCompat;true;setExactAndAllowWhileIdle;;;Argument[3];pending-intent-sent;manual",
]
}
}

View File

@@ -176,7 +176,7 @@ private predicate nameAddStep(DataFlow::ExprNode n1, DataFlow::ExprNode n2) {
* by calling `new JMXServiceURL(tainted)`.
*/
private predicate jmxServiceUrlStep(DataFlow::ExprNode n1, DataFlow::ExprNode n2) {
exists(ConstructorCall cc | cc.getConstructedType() instanceof TypeJMXServiceURL |
exists(ConstructorCall cc | cc.getConstructedType() instanceof TypeJmxServiceUrl |
n1.asExpr() = cc.getAnArgument() and
n2.asExpr() = cc
)
@@ -189,7 +189,7 @@ private predicate jmxServiceUrlStep(DataFlow::ExprNode n1, DataFlow::ExprNode n2
private predicate jmxConnectorStep(DataFlow::ExprNode n1, DataFlow::ExprNode n2) {
exists(MethodAccess ma, Method m | n1.asExpr() = ma.getArgument(0) and n2.asExpr() = ma |
ma.getMethod() = m and
m.getDeclaringType() instanceof TypeJMXConnectorFactory and
m.getDeclaringType() instanceof TypeJmxConnectorFactory and
m.hasName("newJMXConnector")
)
}
@@ -199,7 +199,7 @@ private predicate jmxConnectorStep(DataFlow::ExprNode n1, DataFlow::ExprNode n2)
* `RMIConnector` by calling `new RMIConnector(tainted)`.
*/
private predicate rmiConnectorStep(DataFlow::ExprNode n1, DataFlow::ExprNode n2) {
exists(ConstructorCall cc | cc.getConstructedType() instanceof TypeRMIConnector |
exists(ConstructorCall cc | cc.getConstructedType() instanceof TypeRmiConnector |
n1.asExpr() = cc.getAnArgument() and
n2.asExpr() = cc
)

View File

@@ -140,8 +140,8 @@ private predicate filterStep(DataFlow::ExprNode n1, DataFlow::ExprNode n2) {
ma.getMethod() = m
|
m instanceof MethodUnboundIdFilterCreate or
m instanceof MethodUnboundIdFilterCreateANDFilter or
m instanceof MethodUnboundIdFilterCreateNOTFilter or
m instanceof MethodUnboundIdFilterCreateAndFilter or
m instanceof MethodUnboundIdFilterCreateNotFilter or
m instanceof MethodUnboundIdFilterCreateORFilter or
m instanceof MethodUnboundIdFilterSimplifyFilter
)

Some files were not shown because too many files have changed in this diff Show More