diff --git a/.github/workflows/go-tests.yml b/.github/workflows/go-tests.yml
index 12e162adf29..ca126d1a3ee 100644
--- a/.github/workflows/go-tests.yml
+++ b/.github/workflows/go-tests.yml
@@ -4,6 +4,7 @@ on:
paths:
- "go/**"
- .github/workflows/go-tests.yml
+ - codeql-workspace.yml
jobs:
test-linux:
diff --git a/.github/workflows/js-ml-tests.yml b/.github/workflows/js-ml-tests.yml
index ba33779455e..65db215d8c3 100644
--- a/.github/workflows/js-ml-tests.yml
+++ b/.github/workflows/js-ml-tests.yml
@@ -5,6 +5,7 @@ on:
paths:
- "javascript/ql/experimental/adaptivethreatmodeling/**"
- .github/workflows/js-ml-tests.yml
+ - codeql-workspace.yml
branches:
- main
- "rc/*"
@@ -12,6 +13,7 @@ on:
paths:
- "javascript/ql/experimental/adaptivethreatmodeling/**"
- .github/workflows/js-ml-tests.yml
+ - codeql-workspace.yml
workflow_dispatch:
defaults:
diff --git a/.github/workflows/ql-for-ql-tests.yml b/.github/workflows/ql-for-ql-tests.yml
index a6c79237759..3b0a4963b79 100644
--- a/.github/workflows/ql-for-ql-tests.yml
+++ b/.github/workflows/ql-for-ql-tests.yml
@@ -5,10 +5,12 @@ on:
branches: [main]
paths:
- "ql/**"
+ - codeql-workspace.yml
pull_request:
branches: [main]
paths:
- "ql/**"
+ - codeql-workspace.yml
env:
CARGO_TERM_COLOR: always
diff --git a/.github/workflows/ruby-build.yml b/.github/workflows/ruby-build.yml
index 9e95839789f..c402312db0e 100644
--- a/.github/workflows/ruby-build.yml
+++ b/.github/workflows/ruby-build.yml
@@ -5,6 +5,7 @@ on:
paths:
- "ruby/**"
- .github/workflows/ruby-build.yml
+ - codeql-workspace.yml
branches:
- main
- "rc/*"
@@ -12,6 +13,7 @@ on:
paths:
- "ruby/**"
- .github/workflows/ruby-build.yml
+ - codeql-workspace.yml
branches:
- main
- "rc/*"
diff --git a/.github/workflows/ruby-qltest.yml b/.github/workflows/ruby-qltest.yml
index 463c501c765..0cf8860d8f1 100644
--- a/.github/workflows/ruby-qltest.yml
+++ b/.github/workflows/ruby-qltest.yml
@@ -5,6 +5,7 @@ on:
paths:
- "ruby/**"
- .github/workflows/ruby-qltest.yml
+ - codeql-workspace.yml
branches:
- main
- "rc/*"
@@ -12,6 +13,7 @@ on:
paths:
- "ruby/**"
- .github/workflows/ruby-qltest.yml
+ - codeql-workspace.yml
branches:
- main
- "rc/*"
diff --git a/.github/workflows/swift-qltest.yml b/.github/workflows/swift-qltest.yml
index e0cc5a1cd02..915e1f331a5 100644
--- a/.github/workflows/swift-qltest.yml
+++ b/.github/workflows/swift-qltest.yml
@@ -5,6 +5,7 @@ on:
paths:
- "swift/**"
- .github/workflows/swift-qltest.yml
+ - codeql-workspace.yml
branches:
- main
defaults:
diff --git a/config/identical-files.json b/config/identical-files.json
index d6af2fc7e1d..192144ebb4f 100644
--- a/config/identical-files.json
+++ b/config/identical-files.json
@@ -525,7 +525,8 @@
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/AccessPathSyntax.qll",
"java/ql/lib/semmle/code/java/dataflow/internal/AccessPathSyntax.qll",
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/AccessPathSyntax.qll",
- "ruby/ql/lib/codeql/ruby/dataflow/internal/AccessPathSyntax.qll"
+ "ruby/ql/lib/codeql/ruby/dataflow/internal/AccessPathSyntax.qll",
+ "python/ql/lib/semmle/python/frameworks/data/internal/AccessPathSyntax.qll"
],
"IncompleteUrlSubstringSanitization": [
"javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qll",
@@ -543,7 +544,8 @@
],
"ApiGraphModels": [
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll",
- "ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll"
+ "ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll",
+ "python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll"
],
"TaintedFormatStringQuery Ruby/JS": [
"javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringQuery.qll",
diff --git a/csharp/documentation/library-coverage/coverage.csv b/csharp/documentation/library-coverage/coverage.csv
index 4d9996c1446..2bc6ca863ac 100644
--- a/csharp/documentation/library-coverage/coverage.csv
+++ b/csharp/documentation/library-coverage/coverage.csv
@@ -1,10 +1,27 @@
package,sink,source,summary,sink:code,sink:html,sink:remote,sink:sql,sink:xss,source:local,summary:taint,summary:value
Dapper,55,,,,,,55,,,,
+JsonToItemsTaskFactory,,,7,,,,,,,7,
Microsoft.ApplicationBlocks.Data,28,,,,,,28,,,,
+Microsoft.CSharp,,,24,,,,,,,24,
Microsoft.EntityFrameworkCore,6,,,,,,6,,,,
-Microsoft.Extensions.Primitives,,,54,,,,,,,54,
-Microsoft.VisualBasic,,,4,,,,,,,,4
+Microsoft.Extensions.Caching.Distributed,,,15,,,,,,,15,
+Microsoft.Extensions.Caching.Memory,,,46,,,,,,,45,1
+Microsoft.Extensions.Configuration,,,83,,,,,,,80,3
+Microsoft.Extensions.DependencyInjection,,,62,,,,,,,62,
+Microsoft.Extensions.DependencyModel,,,12,,,,,,,12,
+Microsoft.Extensions.FileProviders,,,15,,,,,,,15,
+Microsoft.Extensions.FileSystemGlobbing,,,15,,,,,,,13,2
+Microsoft.Extensions.Hosting,,,17,,,,,,,16,1
+Microsoft.Extensions.Http,,,10,,,,,,,10,
+Microsoft.Extensions.Logging,,,37,,,,,,,37,
+Microsoft.Extensions.Options,,,8,,,,,,,8,
+Microsoft.Extensions.Primitives,,,63,,,,,,,63,
+Microsoft.Interop,,,27,,,,,,,27,
+Microsoft.NET.Build.Tasks,,,1,,,,,,,1,
+Microsoft.NETCore.Platforms.BuildTasks,,,4,,,,,,,4,
+Microsoft.VisualBasic,,,9,,,,,,,5,4
+Microsoft.Win32,,,8,,,,,,,8,
MySql.Data.MySqlClient,48,,,,,,48,,,,
Newtonsoft.Json,,,91,,,,,,,73,18
ServiceStack,194,,7,27,,75,92,,,7,
-System,28,3,2336,,4,,23,1,3,611,1725
+System,28,3,12038,,4,,23,1,3,10096,1942
diff --git a/csharp/documentation/library-coverage/coverage.rst b/csharp/documentation/library-coverage/coverage.rst
index 9863b503fbf..076d2078d4b 100644
--- a/csharp/documentation/library-coverage/coverage.rst
+++ b/csharp/documentation/library-coverage/coverage.rst
@@ -8,7 +8,7 @@ C# framework & library support
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE-079` :sub:`Cross-site scripting`
`ServiceStack `_,"``ServiceStack.*``, ``ServiceStack``",,7,194,
- System,"``System.*``, ``System``",3,2336,28,5
- Others,"``Dapper``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Primitives``, ``Microsoft.VisualBasic``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``",,149,137,
- Totals,,3,2492,359,5
+ System,"``System.*``, ``System``",3,12038,28,5
+ Others,"``Dapper``, ``JsonToItemsTaskFactory``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.NETCore.Platforms.BuildTasks``, ``Microsoft.VisualBasic``, ``Microsoft.Win32``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``",,554,137,
+ Totals,,3,12599,359,5
diff --git a/docs/codeql/support/reusables/versions-compilers.rst b/docs/codeql/support/reusables/versions-compilers.rst
index a5f68cb64e1..4dfadcfb276 100644
--- a/docs/codeql/support/reusables/versions-compilers.rst
+++ b/docs/codeql/support/reusables/versions-compilers.rst
@@ -20,10 +20,10 @@
Java,"Java 7 to 18 [4]_","javac (OpenJDK and Oracle JDK),
Eclipse compiler for Java (ECJ) [5]_",``.java``
- JavaScript,ECMAScript 2021 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_"
+ JavaScript,ECMAScript 2022 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_"
Python,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10",Not applicable,``.py``
Ruby [7]_,"up to 3.0.2",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``"
- TypeScript [8]_,"2.6-4.6",Standard TypeScript compiler,"``.ts``, ``.tsx``"
+ TypeScript [8]_,"2.6-4.7",Standard TypeScript compiler,"``.ts``, ``.tsx``, ``.mts``, ``.cts``"
.. container:: footnote-group
diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt
index d381704e28f..c47e14cb0fd 100644
--- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt
+++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt
@@ -491,11 +491,17 @@ open class KotlinFileExtractor(
private fun extractValueParameter(vp: IrValueParameter, parent: Label, idx: Int, typeSubstitution: TypeSubstitution?, parentSourceDeclaration: Label, classTypeArgsIncludingOuterClasses: List?, extractTypeAccess: Boolean, locOverride: Label? = null): TypeResults {
with("value parameter", vp) {
val location = locOverride ?: getLocation(vp, classTypeArgsIncludingOuterClasses)
+ val maybeErasedType = (vp.parent as? IrFunction)?.let {
+ if (overridesCollectionsMethodWithAlteredParameterTypes(it))
+ eraseCollectionsMethodParameterType(vp.type, it.name.asString(), idx)
+ else
+ null
+ } ?: vp.type
val id = useValueParameter(vp, parent)
if (extractTypeAccess) {
- extractTypeAccessRecursive(typeSubstitution?.let { it(vp.type, TypeContext.OTHER, pluginContext) } ?: vp.type, location, id, -1)
+ extractTypeAccessRecursive(typeSubstitution?.let { it(maybeErasedType, TypeContext.OTHER, pluginContext) } ?: maybeErasedType, location, id, -1)
}
- return extractValueParameter(id, vp.type, vp.name.asString(), location, parent, idx, typeSubstitution, useValueParameter(vp, parentSourceDeclaration), vp.isVararg)
+ return extractValueParameter(id, maybeErasedType, vp.name.asString(), location, parent, idx, typeSubstitution, useValueParameter(vp, parentSourceDeclaration), vp.isVararg)
}
}
@@ -524,7 +530,8 @@ open class KotlinFileExtractor(
pluginContext.irBuiltIns.unitType,
extensionReceiverParameter = null,
functionTypeParameters = listOf(),
- classTypeArgsIncludingOuterClasses = listOf()
+ classTypeArgsIncludingOuterClasses = listOf(),
+ overridesCollectionsMethod = false
)
val clinitId = tw.getLabelFor(clinitLabel)
val returnType = useType(pluginContext.irBuiltIns.unitType, TypeContext.RETURN)
@@ -759,7 +766,8 @@ open class KotlinFileExtractor(
with("field", f) {
DeclarationStackAdjuster(f).use {
declarationStack.push(f)
- return extractField(useField(f), f.name.asString(), f.type, parentId, tw.getLocation(f), f.visibility, f, isExternalDeclaration(f), f.isFinal)
+ 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)
}
}
}
@@ -1394,12 +1402,6 @@ open class KotlinFileExtractor(
result
}
- val javaLangObject by lazy {
- val result = pluginContext.referenceClass(FqName("java.lang.Object"))?.owner
- result?.let { extractExternalClassLater(it) }
- result
- }
-
val objectCloneMethod by lazy {
val result = javaLangObject?.declarations?.find {
it is IrFunction && it.name.asString() == "clone"
diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt
index 8bbcb2ee2dd..42ecbbff8cc 100644
--- a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt
+++ b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt
@@ -10,12 +10,14 @@ import org.jetbrains.kotlin.backend.jvm.ir.getJvmNameFromAnnotation
import org.jetbrains.kotlin.backend.jvm.ir.propertyIfAccessor
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.*
+import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.*
import org.jetbrains.kotlin.ir.util.*
+import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -32,6 +34,17 @@ open class KotlinUsesExtractor(
val pluginContext: IrPluginContext,
val globalExtensionState: KotlinExtractorGlobalState
) {
+
+ val javaLangObject by lazy {
+ val result = pluginContext.referenceClass(FqName("java.lang.Object"))?.owner
+ result?.let { extractExternalClassLater(it) }
+ result
+ }
+
+ val javaLangObjectType by lazy {
+ javaLangObject?.typeWith()
+ }
+
fun usePackage(pkg: String): Label {
return extractPackage(pkg)
}
@@ -790,6 +803,52 @@ open class KotlinUsesExtractor(
else -> null
}
+ val javaUtilCollection by lazy {
+ val result = pluginContext.referenceClass(FqName("java.util.Collection"))?.owner
+ result?.let { extractExternalClassLater(it) }
+ result
+ }
+
+ val wildcardCollectionType by lazy {
+ javaUtilCollection?.let {
+ it.symbol.typeWithArguments(listOf(IrStarProjectionImpl))
+ }
+ }
+
+ private fun makeCovariant(t: IrTypeArgument) =
+ t.typeOrNull?.let { makeTypeProjection(it, Variance.OUT_VARIANCE) } ?: t
+
+ private fun makeArgumentsCovariant(t: IrType) = (t as? IrSimpleType)?.let {
+ t.toBuilder().also { b -> b.arguments = b.arguments.map(this::makeCovariant) }.buildSimpleType()
+ } ?: t
+
+ fun eraseCollectionsMethodParameterType(t: IrType, collectionsMethodName: String, paramIdx: Int) =
+ when(collectionsMethodName) {
+ "contains", "remove", "containsKey", "containsValue", "get", "indexOf", "lastIndexOf" -> javaLangObjectType
+ "getOrDefault" -> if (paramIdx == 0) javaLangObjectType else null
+ "containsAll", "removeAll", "retainAll" -> wildcardCollectionType
+ // Kotlin defines these like addAll(Collection); Java uses addAll(Collection extends E>)
+ "putAll", "addAll" -> makeArgumentsCovariant(t)
+ else -> null
+ } ?: t
+
+ private fun overridesFunctionDefinedOn(f: IrFunction, packageName: String, className: String) =
+ (f as? IrSimpleFunction)?.let {
+ it.overriddenSymbols.any { overridden ->
+ overridden.owner.parentClassOrNull?.let { defnClass ->
+ defnClass.name.asString() == className &&
+ defnClass.packageFqName?.asString() == packageName
+ } ?: false
+ }
+ } ?: false
+
+ @OptIn(ObsoleteDescriptorBasedAPI::class)
+ fun overridesCollectionsMethodWithAlteredParameterTypes(f: IrFunction) =
+ BuiltinMethodsWithSpecialGenericSignature.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(f.descriptor) != null ||
+ (f.name.asString() == "putAll" && overridesFunctionDefinedOn(f, "kotlin.collections", "MutableMap")) ||
+ (f.name.asString() == "addAll" && overridesFunctionDefinedOn(f, "kotlin.collections", "MutableCollection")) ||
+ (f.name.asString() == "addAll" && overridesFunctionDefinedOn(f, "kotlin.collections", "MutableList"))
+
/*
* This is the normal getFunctionLabel function to use. If you want
* to refer to the function in its source class then
@@ -811,8 +870,19 @@ open class KotlinUsesExtractor(
* `java.lang.Throwable`, which isn't what we want. So we have to
* allow it to be passed in.
*/
+ @OptIn(ObsoleteDescriptorBasedAPI::class)
fun getFunctionLabel(f: IrFunction, maybeParentId: Label?, classTypeArgsIncludingOuterClasses: List?) =
- getFunctionLabel(f.parent, maybeParentId, getFunctionShortName(f).nameInDB, f.valueParameters, f.returnType, f.extensionReceiverParameter, getFunctionTypeParameters(f), classTypeArgsIncludingOuterClasses)
+ getFunctionLabel(
+ f.parent,
+ maybeParentId,
+ getFunctionShortName(f).nameInDB,
+ f.valueParameters,
+ f.returnType,
+ f.extensionReceiverParameter,
+ getFunctionTypeParameters(f),
+ classTypeArgsIncludingOuterClasses,
+ overridesCollectionsMethodWithAlteredParameterTypes(f)
+ )
/*
* This function actually generates the label for a function.
@@ -838,6 +908,9 @@ open class KotlinUsesExtractor(
functionTypeParameters: List,
// The type arguments of enclosing classes of the function.
classTypeArgsIncludingOuterClasses: List?,
+ // If true, this method implements a Java Collections interface (Collection, Map or List) and may need
+ // parameter erasure to match the way this class will appear to an external consumer of the .class file.
+ overridesCollectionsMethod: Boolean,
// The prefix used in the label. "callable", unless a property label is created, then it's "property".
prefix: String = "callable"
): String {
@@ -856,14 +929,19 @@ open class KotlinUsesExtractor(
enclosingClass?.let { notNullClass -> makeTypeGenericSubstitutionMap(notNullClass, notNullArgs) }
}
}
- val getIdForFunctionLabel = { it: IrValueParameter ->
- // Mimic the Java extractor's behaviour: functions with type parameters are named for their erased types;
+ val getIdForFunctionLabel = { it: IndexedValue ->
+ // Kotlin rewrites certain Java collections types adding additional generic constraints-- for example,
+ // Collection.remove(Object) because Collection.remove(Collection::E) in the Kotlin universe.
+ // If this has happened, erase the type again to get the correct Java signature.
+ val maybeAmendedForCollections = if (overridesCollectionsMethod) eraseCollectionsMethodParameterType(it.value.type, name, it.index) else it.value.type
+ // Now substitute any class type parameters in:
+ val maybeSubbed = maybeAmendedForCollections.substituteTypeAndArguments(substitutionMap, TypeContext.OTHER, pluginContext)
+ // Finally, mimic the Java extractor's behaviour by naming functions with type parameters for their erased types;
// those without type parameters are named for the generic type.
- val maybeSubbed = it.type.substituteTypeAndArguments(substitutionMap, TypeContext.OTHER, pluginContext)
val maybeErased = if (functionTypeParameters.isEmpty()) maybeSubbed else erase(maybeSubbed)
"{${useType(maybeErased).javaResult.id}}"
}
- val paramTypeIds = allParams.joinToString(separator = ",", transform = getIdForFunctionLabel)
+ val paramTypeIds = allParams.withIndex().joinToString(separator = ",", transform = getIdForFunctionLabel)
val labelReturnType =
if (name == "")
pluginContext.irBuiltIns.unitType
@@ -1269,6 +1347,7 @@ open class KotlinUsesExtractor(
fun useValueParameter(vp: IrValueParameter, parent: Label?): Label =
tw.getLabelFor(getValueParameterLabel(vp, parent))
+
fun isDirectlyExposedCompanionObjectField(f: IrField) =
f.hasAnnotation(FqName("kotlin.jvm.JvmField")) ||
f.correspondingPropertySymbol?.owner?.let {
@@ -1283,9 +1362,20 @@ open class KotlinUsesExtractor(
null
} ?: f.parent
+ // Gets a field's corresponding property's extension receiver type, if any
+ fun getExtensionReceiverType(f: IrField) =
+ f.correspondingPropertySymbol?.owner?.let {
+ (it.getter ?: it.setter)?.extensionReceiverParameter?.type
+ }
+
fun getFieldLabel(f: IrField): String {
val parentId = useDeclarationParent(getFieldParent(f), false)
- return "@\"field;{$parentId};${f.name.asString()}\""
+ // Distinguish backing fields of properties based on their extension receiver type;
+ // otherwise two extension properties declared in the same enclosing context will get
+ // clashing trap labels. These are always private, so we can just make up a label without
+ // worrying about their names as seen from Java.
+ val extensionPropertyDiscriminator = getExtensionReceiverType(f)?.let { "extension;${useType(it)}" } ?: ""
+ return "@\"field;{$parentId};${extensionPropertyDiscriminator}${f.name.asString()}\""
}
fun useField(f: IrField): Label =
@@ -1313,7 +1403,7 @@ open class KotlinUsesExtractor(
val returnType = getter?.returnType ?: setter?.valueParameters?.singleOrNull()?.type ?: pluginContext.irBuiltIns.unitType
val typeParams = getFunctionTypeParameters(func)
- getFunctionLabel(p.parent, parentId, p.name.asString(), listOf(), returnType, ext, typeParams, classTypeArgsIncludingOuterClasses, "property")
+ getFunctionLabel(p.parent, parentId, p.name.asString(), listOf(), returnType, ext, typeParams, classTypeArgsIncludingOuterClasses, overridesCollectionsMethod = false, prefix = "property")
}
}
diff --git a/java/ql/src/utils/model-generator/CaptureSinkModels.ql b/java/ql/src/utils/model-generator/CaptureSinkModels.ql
index 8fd2e4d2a30..fb04c4ede00 100644
--- a/java/ql/src/utils/model-generator/CaptureSinkModels.ql
+++ b/java/ql/src/utils/model-generator/CaptureSinkModels.ql
@@ -1,7 +1,9 @@
/**
* @name Capture sink models.
* @description Finds public methods that act as sinks as they flow into a a known sink.
+ * @kind diagnostic
* @id java/utils/model-generator/sink-models
+ * @tags model-generator
*/
private import internal.CaptureModels
diff --git a/java/ql/src/utils/model-generator/CaptureSourceModels.ql b/java/ql/src/utils/model-generator/CaptureSourceModels.ql
index 49e9cb34990..d37cf5e78fb 100644
--- a/java/ql/src/utils/model-generator/CaptureSourceModels.ql
+++ b/java/ql/src/utils/model-generator/CaptureSourceModels.ql
@@ -1,7 +1,9 @@
/**
* @name Capture source models.
* @description Finds APIs that act as sources as they expose already known sources.
- * @id java/utils/model-generator/sink-models
+ * @kind diagnostic
+ * @id java/utils/model-generator/source-models
+ * @tags model-generator
*/
private import internal.CaptureModels
diff --git a/java/ql/src/utils/model-generator/CaptureSummaryModels.ql b/java/ql/src/utils/model-generator/CaptureSummaryModels.ql
index 8f4eab20722..253c3d4ed46 100644
--- a/java/ql/src/utils/model-generator/CaptureSummaryModels.ql
+++ b/java/ql/src/utils/model-generator/CaptureSummaryModels.ql
@@ -1,7 +1,9 @@
/**
* @name Capture summary models.
* @description Finds applicable summary models to be used by other queries.
+ * @kind diagnostic
* @id java/utils/model-generator/summary-models
+ * @tags model-generator
*/
private import internal.CaptureModels
diff --git a/java/ql/test/kotlin/library-tests/clashing-extension-fields/test.expected b/java/ql/test/kotlin/library-tests/clashing-extension-fields/test.expected
new file mode 100644
index 00000000000..72fe7124394
--- /dev/null
+++ b/java/ql/test/kotlin/library-tests/clashing-extension-fields/test.expected
@@ -0,0 +1,9 @@
+| |
+| |
+| A |
+| B |
+| get |
+| getX |
+| invoke |
+| x$delegatepackagename$$subpackagename$$A |
+| x$delegatepackagename$$subpackagename$$B |
diff --git a/java/ql/test/kotlin/library-tests/clashing-extension-fields/test.kt b/java/ql/test/kotlin/library-tests/clashing-extension-fields/test.kt
new file mode 100644
index 00000000000..9a7c5d51801
--- /dev/null
+++ b/java/ql/test/kotlin/library-tests/clashing-extension-fields/test.kt
@@ -0,0 +1,7 @@
+package packagename.subpackagename
+
+public class A { }
+public class B { }
+
+val A.x : String by lazy { "HelloA" }
+val B.x : String by lazy { "HelloB" }
diff --git a/java/ql/test/kotlin/library-tests/clashing-extension-fields/test.ql b/java/ql/test/kotlin/library-tests/clashing-extension-fields/test.ql
new file mode 100644
index 00000000000..4c0a8d53b1f
--- /dev/null
+++ b/java/ql/test/kotlin/library-tests/clashing-extension-fields/test.ql
@@ -0,0 +1,5 @@
+import java
+
+from Class c
+where c.fromSource()
+select c.getAMember().toString()
diff --git a/java/ql/test/kotlin/library-tests/exprs/PrintAst.expected b/java/ql/test/kotlin/library-tests/exprs/PrintAst.expected
index 4a93ee5df3b..4fdd6b4d718 100644
--- a/java/ql/test/kotlin/library-tests/exprs/PrintAst.expected
+++ b/java/ql/test/kotlin/library-tests/exprs/PrintAst.expected
@@ -31,7 +31,7 @@ delegatedProperties.kt:
# 87| 0: [MethodAccess] getValue(...)
# 87| -2: [TypeAccess] Integer
# 87| -1: [TypeAccess] PropertyReferenceDelegatesKt
-# 87| 0: [VarAccess] DelegatedPropertiesKt.extDelegated$delegate
+# 87| 0: [VarAccess] DelegatedPropertiesKt.extDelegated$delegateMyClass
# 87| -1: [TypeAccess] DelegatedPropertiesKt
# 1| 1: [ExtensionReceiverAccess] this
# 87| 2: [PropertyRefExpr] ...::...
@@ -80,7 +80,7 @@ delegatedProperties.kt:
# 87| 0: [MethodAccess] setValue(...)
# 87| -2: [TypeAccess] Integer
# 87| -1: [TypeAccess] PropertyReferenceDelegatesKt
-# 87| 0: [VarAccess] DelegatedPropertiesKt.extDelegated$delegate
+# 87| 0: [VarAccess] DelegatedPropertiesKt.extDelegated$delegateMyClass
# 87| -1: [TypeAccess] DelegatedPropertiesKt
# 1| 1: [ExtensionReceiverAccess] this
# 87| 2: [PropertyRefExpr] ...::...
@@ -118,7 +118,7 @@ delegatedProperties.kt:
# 87| 0: [TypeAccess] MyClass
# 87| 1: [TypeAccess] Integer
# 87| 3: [VarAccess]
-# 87| 5: [FieldDeclaration] KMutableProperty0 extDelegated$delegate;
+# 87| 5: [FieldDeclaration] KMutableProperty0 extDelegated$delegateMyClass;
# 87| -1: [TypeAccess] KMutableProperty0
# 87| 0: [TypeAccess] Integer
# 87| 0: [PropertyRefExpr] ...::...
diff --git a/java/ql/test/kotlin/library-tests/exprs/delegatedProperties.expected b/java/ql/test/kotlin/library-tests/exprs/delegatedProperties.expected
index c60b200a2eb..7141b6d1531 100644
--- a/java/ql/test/kotlin/library-tests/exprs/delegatedProperties.expected
+++ b/java/ql/test/kotlin/library-tests/exprs/delegatedProperties.expected
@@ -16,7 +16,7 @@ delegatedProperties
| delegatedProperties.kt:77:5:77:49 | delegatedToTopLevel | delegatedToTopLevel | non-local | delegatedProperties.kt:77:34:77:49 | delegatedToTopLevel$delegate | delegatedProperties.kt:77:37:77:49 | ...::... |
| delegatedProperties.kt:79:5:79:38 | max | max | non-local | delegatedProperties.kt:79:18:79:38 | max$delegate | delegatedProperties.kt:79:21:79:38 | ...::... |
| delegatedProperties.kt:82:9:82:54 | delegatedToMember3 | delegatedToMember3 | local | delegatedProperties.kt:82:37:82:54 | KMutableProperty0 delegatedToMember3$delegate | delegatedProperties.kt:82:40:82:54 | ...::... |
-| delegatedProperties.kt:87:1:87:46 | extDelegated | extDelegated | non-local | delegatedProperties.kt:87:31:87:46 | extDelegated$delegate | delegatedProperties.kt:87:34:87:46 | ...::... |
+| delegatedProperties.kt:87:1:87:46 | extDelegated | extDelegated | non-local | delegatedProperties.kt:87:31:87:46 | extDelegated$delegateMyClass | delegatedProperties.kt:87:34:87:46 | ...::... |
delegatedPropertyTypes
| delegatedProperties.kt:6:9:9:9 | prop1 | file://:0:0:0:0 | int | file:///Lazy.class:0:0:0:0 | Lazy |
| delegatedProperties.kt:19:9:19:51 | varResource1 | file://:0:0:0:0 | int | delegatedProperties.kt:45:1:51:1 | ResourceDelegate |
diff --git a/java/ql/test/kotlin/library-tests/exprs/exprs.expected b/java/ql/test/kotlin/library-tests/exprs/exprs.expected
index a2a1e3bd941..110d9e47147 100644
--- a/java/ql/test/kotlin/library-tests/exprs/exprs.expected
+++ b/java/ql/test/kotlin/library-tests/exprs/exprs.expected
@@ -830,9 +830,9 @@
| delegatedProperties.kt:87:31:87:46 | DelegatedPropertiesKt | delegatedProperties.kt:87:31:87:46 | set | TypeAccess |
| delegatedProperties.kt:87:31:87:46 | DelegatedPropertiesKt | delegatedProperties.kt:87:31:87:46 | set | TypeAccess |
| delegatedProperties.kt:87:31:87:46 | DelegatedPropertiesKt | delegatedProperties.kt:87:31:87:46 | setExtDelegated | TypeAccess |
-| delegatedProperties.kt:87:31:87:46 | DelegatedPropertiesKt.extDelegated$delegate | delegatedProperties.kt:0:0:0:0 | | VarAccess |
-| delegatedProperties.kt:87:31:87:46 | DelegatedPropertiesKt.extDelegated$delegate | delegatedProperties.kt:87:31:87:46 | getExtDelegated | VarAccess |
-| delegatedProperties.kt:87:31:87:46 | DelegatedPropertiesKt.extDelegated$delegate | delegatedProperties.kt:87:31:87:46 | setExtDelegated | VarAccess |
+| delegatedProperties.kt:87:31:87:46 | DelegatedPropertiesKt.extDelegated$delegateMyClass | delegatedProperties.kt:0:0:0:0 | | VarAccess |
+| delegatedProperties.kt:87:31:87:46 | DelegatedPropertiesKt.extDelegated$delegateMyClass | delegatedProperties.kt:87:31:87:46 | getExtDelegated | VarAccess |
+| delegatedProperties.kt:87:31:87:46 | DelegatedPropertiesKt.extDelegated$delegateMyClass | delegatedProperties.kt:87:31:87:46 | setExtDelegated | VarAccess |
| delegatedProperties.kt:87:31:87:46 | Integer | delegatedProperties.kt:87:31:87:46 | getExtDelegated | TypeAccess |
| delegatedProperties.kt:87:31:87:46 | Integer | delegatedProperties.kt:87:31:87:46 | setExtDelegated | TypeAccess |
| delegatedProperties.kt:87:31:87:46 | Integer | file://:0:0:0:0 | | TypeAccess |
diff --git a/java/ql/test/kotlin/library-tests/java-kotlin-collection-type-generic-methods/Test.java b/java/ql/test/kotlin/library-tests/java-kotlin-collection-type-generic-methods/Test.java
new file mode 100644
index 00000000000..12a77514c3d
--- /dev/null
+++ b/java/ql/test/kotlin/library-tests/java-kotlin-collection-type-generic-methods/Test.java
@@ -0,0 +1,28 @@
+import java.util.Map;
+import java.util.AbstractMap;
+import java.util.Collection;
+import java.util.AbstractCollection;
+import java.util.List;
+import java.util.AbstractList;
+
+public class Test {
+
+ public static void test(
+ Map p1,
+ AbstractMap p2,
+ Collection p3,
+ AbstractCollection p4,
+ List p5,
+ AbstractList p6) {
+
+ // Use a method of each to ensure method prototypes are extracted:
+ p1.remove("Hello");
+ p2.remove("Hello");
+ p3.remove("Hello");
+ p4.remove("Hello");
+ p5.remove("Hello");
+ p6.remove("Hello");
+
+ }
+
+}
diff --git a/java/ql/test/kotlin/library-tests/java-kotlin-collection-type-generic-methods/test.expected b/java/ql/test/kotlin/library-tests/java-kotlin-collection-type-generic-methods/test.expected
new file mode 100644
index 00000000000..8b681d0f785
--- /dev/null
+++ b/java/ql/test/kotlin/library-tests/java-kotlin-collection-type-generic-methods/test.expected
@@ -0,0 +1,412 @@
+methodWithDuplicate
+#select
+| AbstractCollection | add | E |
+| AbstractCollection | addAll | Collection extends E> |
+| AbstractCollection | contains | Object |
+| AbstractCollection | containsAll | Collection> |
+| AbstractCollection | remove | Object |
+| AbstractCollection | removeAll | Collection> |
+| AbstractCollection | retainAll | Collection> |
+| AbstractCollection | toArray | T[] |
+| AbstractCollection | add | E |
+| AbstractCollection | addAll | Collection extends E> |
+| AbstractCollection | contains | Object |
+| AbstractCollection | containsAll | Collection> |
+| AbstractCollection | remove | Object |
+| AbstractCollection | removeAll | Collection> |
+| AbstractCollection | retainAll | Collection> |
+| AbstractCollection | toArray | T[] |
+| AbstractCollection | add | String |
+| AbstractCollection | addAll | Collection extends String> |
+| AbstractCollection | contains | Object |
+| AbstractCollection | containsAll | Collection> |
+| AbstractCollection | remove | Object |
+| AbstractCollection | removeAll | Collection> |
+| AbstractCollection | retainAll | Collection> |
+| AbstractCollection | toArray | T[] |
+| AbstractList | add | E |
+| AbstractList | add | int |
+| AbstractList | addAll | Collection extends E> |
+| AbstractList | addAll | int |
+| AbstractList | equals | Object |
+| AbstractList | get | int |
+| AbstractList | indexOf | Object |
+| AbstractList | lastIndexOf | Object |
+| AbstractList | listIterator | int |
+| AbstractList | removeAt | int |
+| AbstractList | removeRange | int |
+| AbstractList | set | E |
+| AbstractList | set | int |
+| AbstractList | subList | int |
+| AbstractList | subListRangeCheck | int |
+| AbstractList | add | E |
+| AbstractList | add | int |
+| AbstractList | addAll | Collection extends E> |
+| AbstractList | addAll | int |
+| AbstractList | equals | Object |
+| AbstractList | get | int |
+| AbstractList | indexOf | Object |
+| AbstractList | lastIndexOf | Object |
+| AbstractList | listIterator | int |
+| AbstractList | removeAt | int |
+| AbstractList | removeRange | int |
+| AbstractList | set | E |
+| AbstractList | set | int |
+| AbstractList | subList | int |
+| AbstractList | subListRangeCheck | int |
+| AbstractMap | containsEntry | Entry,?> |
+| AbstractMap | containsKey | Object |
+| AbstractMap | containsValue | Object |
+| AbstractMap | equals | Object |
+| AbstractMap | get | Object |
+| AbstractMap | put | K |
+| AbstractMap | put | V |
+| AbstractMap | putAll | Map extends K,? extends V> |
+| AbstractMap | remove | Object |
+| AbstractMap> | containsKey | Object |
+| AbstractMap> | containsValue | Object |
+| AbstractMap> | equals | Object |
+| AbstractMap> | get | Object |
+| AbstractMap> | put | Entry> |
+| AbstractMap> | put | Identity |
+| AbstractMap> | putAll | Map extends Identity,? extends Entry>> |
+| AbstractMap> | remove | Object |
+| AbstractMap | containsKey | Object |
+| AbstractMap | containsValue | Object |
+| AbstractMap | equals | Object |
+| AbstractMap | get | Object |
+| AbstractMap | put | K |
+| AbstractMap | put | V |
+| AbstractMap | putAll | Map extends K,? extends V> |
+| AbstractMap | remove | Object |
+| AbstractMap | containsEntry | Entry,?> |
+| AbstractMap | containsKey | Object |
+| AbstractMap | containsValue | Object |
+| AbstractMap | equals | Object |
+| AbstractMap | get | Object |
+| AbstractMap | put | String |
+| AbstractMap | putAll | Map extends String,? extends String> |
+| AbstractMap | remove | Object |
+| AbstractMutableCollection | add | E |
+| AbstractMutableList | add | E |
+| AbstractMutableList | add | int |
+| AbstractMutableList | removeAt | int |
+| AbstractMutableList | set | E |
+| AbstractMutableList | set | int |
+| AbstractMutableMap | put | K |
+| AbstractMutableMap | put | V |
+| Collection | add | E |
+| Collection | addAll | Collection extends E> |
+| Collection | contains | Object |
+| Collection | containsAll | Collection> |
+| Collection | equals | Object |
+| Collection | remove | Object |
+| Collection | removeAll | Collection> |
+| Collection | removeIf | Predicate super E> |
+| Collection | retainAll | Collection> |
+| Collection | toArray | IntFunction |
+| Collection | toArray | T[] |
+| Collection | add | E |
+| Collection | addAll | Collection extends E> |
+| Collection | contains | Object |
+| Collection | containsAll | Collection> |
+| Collection | remove | Object |
+| Collection | removeAll | Collection> |
+| Collection | removeIf | Predicate super E> |
+| Collection | retainAll | Collection> |
+| Collection | toArray | IntFunction |
+| Collection | toArray | T[] |
+| Collection> | add | Entry |
+| Collection> | addAll | Collection extends Entry> |
+| Collection> | contains | Object |
+| Collection> | containsAll | Collection> |
+| Collection> | remove | Object |
+| Collection> | removeAll | Collection> |
+| Collection> | removeIf | Predicate super Entry> |
+| Collection> | retainAll | Collection> |
+| Collection> | toArray | IntFunction |
+| Collection> | toArray | T[] |
+| Collection | add | K |
+| Collection | addAll | Collection extends K> |
+| Collection | contains | Object |
+| Collection | containsAll | Collection> |
+| Collection | remove | Object |
+| Collection | removeAll | Collection> |
+| Collection | removeIf | Predicate super K> |
+| Collection | retainAll | Collection> |
+| Collection | toArray | IntFunction |
+| Collection | toArray | T[] |
+| Collection | add | String |
+| Collection | addAll | Collection extends String> |
+| Collection | contains | Object |
+| Collection | containsAll | Collection> |
+| Collection | equals | Object |
+| Collection | remove | Object |
+| Collection | removeAll | Collection> |
+| Collection | removeIf | Predicate super String> |
+| Collection | retainAll | Collection> |
+| Collection | toArray | IntFunction |
+| Collection | toArray | T[] |
+| Collection | add | V |
+| Collection | addAll | Collection extends V> |
+| Collection | contains | Object |
+| Collection | containsAll | Collection> |
+| Collection | remove | Object |
+| Collection | removeAll | Collection> |
+| Collection | removeIf | Predicate super V> |
+| Collection | retainAll | Collection> |
+| Collection | toArray | IntFunction |
+| Collection | toArray | T[] |
+| List | add | E |
+| List | add | int |
+| List | addAll | Collection extends E> |
+| List | addAll | int |
+| List | contains | Object |
+| List | containsAll | Collection> |
+| List | copyOf | Collection extends E> |
+| List | equals | Object |
+| List | get | int |
+| List | indexOf | Object |
+| List | lastIndexOf | Object |
+| List | listIterator | int |
+| List | of | E |
+| List | of | E[] |
+| List | remove | Object |
+| List | remove | int |
+| List | removeAll | Collection> |
+| List | replaceAll | UnaryOperator |
+| List | retainAll | Collection> |
+| List | set | E |
+| List | set | int |
+| List | sort | Comparator super E> |
+| List | subList | int |
+| List | toArray | T[] |
+| List | add | E |
+| List | add | int |
+| List | addAll | Collection extends E> |
+| List | addAll | int |
+| List | contains | Object |
+| List | containsAll | Collection> |
+| List | copyOf | Collection extends E> |
+| List | get | int |
+| List | indexOf | Object |
+| List | lastIndexOf | Object |
+| List | listIterator | int |
+| List | of | E |
+| List | of | E[] |
+| List | remove | Object |
+| List | remove | int |
+| List | removeAll | Collection> |
+| List | replaceAll | UnaryOperator |
+| List | retainAll | Collection> |
+| List | set | E |
+| List | set | int |
+| List | sort | Comparator super E> |
+| List | subList | int |
+| List | toArray | T[] |
+| List | add | String |
+| List | add | int |
+| List | addAll | Collection extends String> |
+| List | addAll | int |
+| List | contains | Object |
+| List | containsAll | Collection> |
+| List | copyOf | Collection extends E> |
+| List | equals | Object |
+| List | get | int |
+| List | indexOf | Object |
+| List | lastIndexOf | Object |
+| List | listIterator | int |
+| List | of | E |
+| List | of | E[] |
+| List | remove | Object |
+| List | remove | int |
+| List | removeAll | Collection> |
+| List | replaceAll | UnaryOperator |
+| List | retainAll | Collection> |
+| List | set | String |
+| List | set | int |
+| List | sort | Comparator super String> |
+| List | subList | int |
+| List | toArray | T[] |
+| Map | compute | BiFunction super K,? super V,? extends V> |
+| Map | compute | K |
+| Map | computeIfAbsent | Function super K,? extends V> |
+| Map | computeIfAbsent | K |
+| Map | computeIfPresent | BiFunction super K,? super V,? extends V> |
+| Map | computeIfPresent | K |
+| Map | containsKey | Object |
+| Map | containsValue | Object |
+| Map | copyOf | Map extends K,? extends V> |
+| Map | entry | K |
+| Map | entry | V |
+| Map | equals | Object |
+| Map | forEach | BiConsumer super K,? super V> |
+| Map | get | Object |
+| Map | getOrDefault | Object |
+| Map | getOrDefault | V |
+| Map | merge | BiFunction super V,? super V,? extends V> |
+| Map | merge | K |
+| Map | merge | V |
+| Map | of | K |
+| Map | of | V |
+| Map | ofEntries | Entry extends K,? extends V>[] |
+| Map | put | K |
+| Map | put | V |
+| Map | putAll | Map extends K,? extends V> |
+| Map | putIfAbsent | K |
+| Map | putIfAbsent | V |
+| Map | remove | Object |
+| Map | replace | K |
+| Map | replace | V |
+| Map | replaceAll | BiFunction super K,? super V,? extends V> |
+| Map> | compute | BiFunction super Identity,? super Entry>,? extends Entry>> |
+| Map> | compute | Identity |
+| Map> | computeIfAbsent | Function super Identity,? extends Entry>> |
+| Map> | computeIfAbsent | Identity |
+| Map> | computeIfPresent | BiFunction super Identity,? super Entry>,? extends Entry>> |
+| Map> | computeIfPresent | Identity |
+| Map> | containsKey | Object |
+| Map> | containsValue | Object |
+| Map> | copyOf | Map extends K,? extends V> |
+| Map> | entry | K |
+| Map> | entry | V |
+| Map> | forEach | BiConsumer super Identity,? super Entry>> |
+| Map> | get | Object |
+| Map> | getOrDefault | Entry> |
+| Map> | getOrDefault | Object |
+| Map> | merge | BiFunction super Entry>,? super Entry>,? extends Entry>> |
+| Map> | merge | Entry> |
+| Map> | merge | Identity |
+| Map> | of | K |
+| Map> | of | V |
+| Map> | ofEntries | Entry extends K,? extends V>[] |
+| Map> | put | Entry> |
+| Map> | put | Identity |
+| Map> | putAll | Map extends Identity,? extends Entry>> |
+| Map> | putIfAbsent | Entry> |
+| Map> | putIfAbsent | Identity |
+| Map> | remove | Object |
+| Map> | replace | Entry> |
+| Map> | replace | Identity |
+| Map> | replaceAll | BiFunction super Identity,? super Entry>,? extends Entry>> |
+| Map | compute | BiFunction super K,? super V,? extends V> |
+| Map | compute | K |
+| Map | computeIfAbsent | Function super K,? extends V> |
+| Map | computeIfAbsent | K |
+| Map | computeIfPresent | BiFunction super K,? super V,? extends V> |
+| Map | computeIfPresent | K |
+| Map | containsKey | Object |
+| Map | containsValue | Object |
+| Map | copyOf | Map extends K,? extends V> |
+| Map | entry | K |
+| Map | entry | V |
+| Map | forEach | BiConsumer super K,? super V> |
+| Map | get | Object |
+| Map | getOrDefault | Object |
+| Map | getOrDefault | V |
+| Map | merge | BiFunction super V,? super V,? extends V> |
+| Map | merge | K |
+| Map | merge | V |
+| Map | of | K |
+| Map | of | V |
+| Map | ofEntries | Entry extends K,? extends V>[] |
+| Map | put | K |
+| Map | put | V |
+| Map | putAll | Map extends K,? extends V> |
+| Map | putIfAbsent | K |
+| Map | putIfAbsent | V |
+| Map