diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/PrintAst.expected b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/PrintAst.expected new file mode 100644 index 00000000000..a4d9d37a8e2 --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/PrintAst.expected @@ -0,0 +1,83 @@ +a.kt: +# 0| [CompilationUnit] a +# 1| 1: [Class] A +# 0| 1: [Method] +# 0| 3: [TypeAccess] int +# 0| 5: [BlockStmt] { ... } +# 0| 0: [ReturnStmt] return ... +# 0| 0: [IntegerLiteral] 42 +# 1| 2: [Constructor] A +# 1| 5: [BlockStmt] { ... } +# 1| 0: [SuperConstructorInvocationStmt] super(...) +# 1| 1: [BlockStmt] { ... } +# 2| 3: [Method] f1 +# 2| 3: [TypeAccess] int +# 2| 5: [BlockStmt] { ... } +# 2| 0: [ReturnStmt] return ... +# 2| 0: [IntegerLiteral] 1 +b.kt: +# 0| [CompilationUnit] b +# 1| 1: [Class] B +# 0| 1: [Method] +# 0| 3: [TypeAccess] int +# 0| 5: [BlockStmt] { ... } +# 0| 0: [ReturnStmt] return ... +# 0| 0: [UnsafeCoerceExpr] +# 0| 0: [TypeAccess] int +# 0| 1: [IntegerLiteral] 1 +# 1| 2: [Constructor] B +# 1| 5: [BlockStmt] { ... } +# 1| 0: [SuperConstructorInvocationStmt] super(...) +# 1| 1: [BlockStmt] { ... } +c.kt: +# 0| [CompilationUnit] c +# 1| 1: [Class] C +# 0| 1: [Method] +# 0| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 0| 0: [Parameter] param +# 0| 0: [TypeAccess] ProcessBuilder +# 0| 5: [BlockStmt] { ... } +# 0| 0: [ReturnStmt] return ... +# 0| 0: [MethodAccess] start(...) +# 0| -1: [VarAccess] param +# 1| 2: [Constructor] C +# 1| 5: [BlockStmt] { ... } +# 1| 0: [SuperConstructorInvocationStmt] super(...) +# 1| 1: [BlockStmt] { ... } +d.kt: +# 0| [CompilationUnit] d +# 1| 1: [Class] D +# 0| 1: [FieldDeclaration] String bar; +# 0| -1: [TypeAccess] String +# 0| 0: [StringLiteral] Foobar +# 1| 3: [Constructor] D +# 1| 5: [BlockStmt] { ... } +# 1| 0: [SuperConstructorInvocationStmt] super(...) +# 1| 1: [BlockStmt] { ... } +e.kt: +# 0| [CompilationUnit] e +# 1| 1: [Class] E +# 0| 1: [Method] +# 0| 3: [TypeAccess] boolean +# 0| 5: [BlockStmt] { ... } +# 0| 0: [ReturnStmt] return ... +# 0| 0: [MethodAccess] add(...) +# 0| -1: [ClassInstanceExpr] new ArrayList(...) +# 0| -3: [TypeAccess] ArrayList +# 0| 0: [IntegerLiteral] 1 +# 0| 0: [NullLiteral] null +# 0| 1: [Method] +# 0| 3: [TypeAccess] Object +# 0| 5: [BlockStmt] { ... } +# 0| 0: [ReturnStmt] return ... +# 0| 0: [MethodAccess] put(...) +# 0| -1: [ClassInstanceExpr] new LinkedHashMap(...) +# 0| -3: [TypeAccess] LinkedHashMap +# 0| 0: [IntegerLiteral] 1 +# 0| 0: [NullLiteral] null +# 0| 1: [NullLiteral] null +# 1| 3: [Constructor] E +# 1| 5: [BlockStmt] { ... } +# 1| 0: [SuperConstructorInvocationStmt] super(...) +# 1| 1: [BlockStmt] { ... } diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/PrintAst.qlref b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/PrintAst.qlref new file mode 100644 index 00000000000..c7fd5faf239 --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/java/PrintAst.ql \ No newline at end of file diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/a.kt b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/a.kt new file mode 100644 index 00000000000..922e7e86703 --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/a.kt @@ -0,0 +1,3 @@ +class A { + fun f1() = 1 +} diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/b.kt b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/b.kt new file mode 100644 index 00000000000..7d95eb64996 --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/b.kt @@ -0,0 +1,2 @@ +class B { +} diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/build_plugin b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/build_plugin new file mode 100755 index 00000000000..c38ab33eb75 --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/build_plugin @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 + +import subprocess +import shutil +import os +import os.path +import sys +import shlex + + +def run_process(cmd): + try: + print("Running command: " + shlex.join(cmd)) + return subprocess.run(cmd, check=True, capture_output=True) + except subprocess.CalledProcessError as e: + print("In: " + os.getcwd(), file=sys.stderr) + print("Command failed: " + shlex.join(cmd), file=sys.stderr) + print("stdout output:\n" + e.stdout.decode(encoding='UTF-8', + errors='strict'), file=sys.stderr) + print("stderr output:\n" + e.stderr.decode(encoding='UTF-8', + errors='strict'), file=sys.stderr) + raise e + +root = '../../../../../../../../..' + +sys.path.append(root + '/ql/java/kotlin-extractor') +import kotlin_plugin_versions +defaultKotlinDependencyVersion = kotlin_plugin_versions.get_single_version() + +builddir = 'build' +dependency_dir = root + '/resources/kotlin-dependencies/' +dependencies = ['kotlin-stdlib-' + defaultKotlinDependencyVersion + + '.jar', 'kotlin-compiler-' + defaultKotlinDependencyVersion + '.jar'] +classpath = ':'.join([dependency_dir + dep for dep in dependencies]) +srcs = ['plugin/Plugin.kt'] +output = 'plugin.jar' + +if os.path.exists(builddir): + shutil.rmtree(builddir) +os.makedirs(builddir) + +run_process(['kotlinc', + '-J-Xmx2G', + '-d', builddir, + '-module-name', 'test', + '-no-reflect', '-no-stdlib', + '-jvm-target', '1.8', + '-classpath', classpath] + srcs) + +run_process(['jar', '-c', '-f', output, + '-C', builddir, '.', + '-C', 'plugin/resources', 'META-INF']) +shutil.rmtree(builddir) diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/c.kt b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/c.kt new file mode 100644 index 00000000000..b0a84db03d1 --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/c.kt @@ -0,0 +1 @@ +class C { } diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/d.kt b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/d.kt new file mode 100644 index 00000000000..8472937f6bc --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/d.kt @@ -0,0 +1 @@ +class D { } diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/diagnostics.expected b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/diagnostics.expected new file mode 100644 index 00000000000..183abf9a986 --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/diagnostics.expected @@ -0,0 +1,2 @@ +| CodeQL Kotlin extractor | 2 | | IrProperty without a getter | d.kt:0:0:0:0 | d.kt:0:0:0:0 | +| CodeQL Kotlin extractor | 2 | | Not rewriting trap file for: Boolean -1.0-0- -1.0-0-null test-db/trap/java/classes/kotlin/Boolean.members.trap.gz | file://:0:0:0:0 | file://:0:0:0:0 | diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/diagnostics.ql b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/diagnostics.ql new file mode 100755 index 00000000000..57ec32bb048 --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/diagnostics.ql @@ -0,0 +1,13 @@ +import java + +from string genBy, int severity, string tag, string msg, Location l +where + diagnostics(_, genBy, severity, tag, msg, _, l) and + ( + // Different installations get different sets of these messages, + // so we filter out all but one that happens everywhere. + msg.matches("Not rewriting trap file for: %") + implies + msg.matches("Not rewriting trap file for: Boolean %") + ) +select genBy, severity, tag, msg, l diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/e.kt b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/e.kt new file mode 100644 index 00000000000..f4b8aa5df61 --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/e.kt @@ -0,0 +1 @@ +class E { } diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/methods.expected b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/methods.expected new file mode 100644 index 00000000000..c485610e7b3 --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/methods.expected @@ -0,0 +1,7 @@ +| a.kt:0:0:0:0 | | has body | +| a.kt:2:5:2:16 | f1 | has body | +| b.kt:0:0:0:0 | | has body | +| c.kt:0:0:0:0 | | has body | +| d.kt:0:0:0:0 | | has body | +| e.kt:0:0:0:0 | | has body | +| e.kt:0:0:0:0 | | has body | diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/methods.ql b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/methods.ql new file mode 100755 index 00000000000..adb7c8784e5 --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/methods.ql @@ -0,0 +1,7 @@ +import java + +from Method m, string body +where + m.fromSource() and + if exists(m.getBody()) then body = "has body" else body = "has no body" +select m, body diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/plugin/Plugin.kt b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/plugin/Plugin.kt new file mode 100644 index 00000000000..c88410ca9db --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/plugin/Plugin.kt @@ -0,0 +1,280 @@ +package com.github.codeql + +import com.intellij.mock.MockProject +import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension +import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext +import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor +import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder +import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI +import org.jetbrains.kotlin.ir.builders.declarations.* +import org.jetbrains.kotlin.ir.builders.irCall +import org.jetbrains.kotlin.ir.builders.irExprBody +import org.jetbrains.kotlin.ir.builders.irGet +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.defaultType +import org.jetbrains.kotlin.ir.types.typeWith +import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name + +class TestComponentRegistrar : ComponentRegistrar { + override fun registerProjectComponents( + project: MockProject, + configuration: CompilerConfiguration + ) { + IrGenerationExtension.registerExtension(project, IrAdder()) + } +} + +@OptIn(ObsoleteDescriptorBasedAPI::class) +class IrAdder : IrGenerationExtension { + override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) { + + class AndroidSymbols { + private val irFactory: IrFactory = IrFactoryImpl + private val kotlinJvmInternalPackage: IrPackageFragment = createPackage("kotlin.jvm.internal") + private val javaUtil: IrPackageFragment = createPackage("java.util") + + private fun createPackage(packageName: String): IrPackageFragment = + IrExternalPackageFragmentImpl.createEmptyExternalPackageFragment( + moduleFragment.descriptor, + FqName(packageName) + ) + + private fun createClass( + irPackage: IrPackageFragment, + shortName: String, + classKind: ClassKind, + classModality: Modality + ): IrClassSymbol = irFactory.buildClass { + name = Name.identifier(shortName) + kind = classKind + modality = classModality + }.apply { + parent = irPackage + createImplicitParameterDeclarationWithWrappedDescriptor() + }.symbol + + val unsafeCoerceIntrinsic: IrSimpleFunctionSymbol = + irFactory.buildFun { + name = Name.special("") + origin = IrDeclarationOrigin.IR_BUILTINS_STUB + }.apply { + parent = kotlinJvmInternalPackage + val src = addTypeParameter("T", pluginContext.irBuiltIns.anyNType) + val dst = addTypeParameter("R", pluginContext.irBuiltIns.anyNType) + addValueParameter("v", src.defaultType) + returnType = dst.defaultType + }.symbol + + val javaUtilArrayList: IrClassSymbol = + createClass(javaUtil, "ArrayList", ClassKind.CLASS, Modality.OPEN) + + val javaUtilLinkedHashMap: IrClassSymbol = + createClass(javaUtil, "LinkedHashMap", ClassKind.CLASS, Modality.OPEN) + + val arrayListConstructor: IrConstructorSymbol = javaUtilArrayList.owner.addConstructor().apply { + addValueParameter("p_0", pluginContext.irBuiltIns.intType) + }.symbol + + val arrayListAdd: IrSimpleFunctionSymbol = + javaUtilArrayList.owner.addFunction("add", pluginContext.irBuiltIns.booleanType).apply { + addValueParameter("p_0", pluginContext.irBuiltIns.anyNType) + }.symbol + + val linkedHashMapConstructor: IrConstructorSymbol = + javaUtilLinkedHashMap.owner.addConstructor().apply { + addValueParameter("p_0", pluginContext.irBuiltIns.intType) + }.symbol + + val linkedHashMapPut: IrSimpleFunctionSymbol = + javaUtilLinkedHashMap.owner.addFunction("put", pluginContext.irBuiltIns.anyNType).apply { + addValueParameter("p_0", pluginContext.irBuiltIns.anyNType) + addValueParameter("p_1", pluginContext.irBuiltIns.anyNType) + }.symbol + } + + moduleFragment.transform(object: IrElementTransformerVoidWithContext() { + override fun visitClassNew(declaration: IrClass): IrStatement { + if (declaration.name.asString() == "A") { + addFunWithExprBody(declaration) + } else if (declaration.name.asString() == "B") { + addFunWithUnsafeCoerce(declaration) + } else if (declaration.name.asString() == "C") { + addFunWithStubClass(declaration) + } else if (declaration.name.asString() == "D") { + addStaticFieldWithExprInit(declaration) + } else if (declaration.name.asString() == "E") { + addFunWithArrayListAdd(declaration) + addFunWithLinkedHashMapPut(declaration) + } + + return super.visitClassNew(declaration) + } + + fun unsafeCoerce(value: IrExpression, fromType: IrType, toType: IrType): IrExpression { + return IrCallImpl.fromSymbolOwner(-1, -1, toType, AndroidSymbols().unsafeCoerceIntrinsic).apply { + putTypeArgument(0, fromType) + putTypeArgument(1, toType) + putValueArgument(0, value) + } + } + + private fun arrayListAdd(): IrExpression { + // ArrayList(1).add(null) + var androidSymbols = AndroidSymbols() + return IrCallImpl.fromSymbolOwner(-1, -1, pluginContext.irBuiltIns.booleanType, androidSymbols.arrayListAdd).apply { + dispatchReceiver = IrConstructorCallImpl.fromSymbolOwner(-1,-1, androidSymbols.javaUtilArrayList.typeWith(), androidSymbols.arrayListConstructor).apply { + putValueArgument(0, IrConstImpl.int(-1, -1, pluginContext.irBuiltIns.intType, 1)) + } + putValueArgument(0, IrConstImpl.constNull(-1,-1, pluginContext.irBuiltIns.anyNType)) + } + } + + private fun linkedHashMapPut(): IrExpression { + // LinkedHashMap(1).put(null, null) + var androidSymbols = AndroidSymbols() + return IrCallImpl.fromSymbolOwner(-1, -1, pluginContext.irBuiltIns.anyNType, androidSymbols.linkedHashMapPut).apply { + dispatchReceiver = IrConstructorCallImpl.fromSymbolOwner(-1,-1, androidSymbols.javaUtilLinkedHashMap.typeWith(), androidSymbols.linkedHashMapConstructor).apply { + putValueArgument(0, IrConstImpl.int(-1, -1, pluginContext.irBuiltIns.intType, 1)) + } + putValueArgument(0, IrConstImpl.constNull(-1,-1, pluginContext.irBuiltIns.anyNType)) + putValueArgument(1, IrConstImpl.constNull(-1,-1, pluginContext.irBuiltIns.anyNType)) + } + } + + private fun addFunWithArrayListAdd(declaration: IrClass) { + declaration.declarations.add(pluginContext.irFactory.buildFun { + name = Name.identifier("") + returnType = pluginContext.irBuiltIns.booleanType + }. also { + it.body = DeclarationIrBuilder(pluginContext, it.symbol) + .irExprBody( + arrayListAdd() + ) + it.parent = declaration + }) + } + + private fun addFunWithLinkedHashMapPut(declaration: IrClass) { + declaration.declarations.add(pluginContext.irFactory.buildFun { + name = Name.identifier("") + returnType = pluginContext.irBuiltIns.anyNType + }. also { + it.body = DeclarationIrBuilder(pluginContext, it.symbol) + .irExprBody( + linkedHashMapPut() + ) + it.parent = declaration + }) + } + + private fun addFunWithUnsafeCoerce(declaration: IrClass) { + val uintType = pluginContext.referenceClass(FqName("kotlin.UInt"))!!.owner.typeWith() + declaration.declarations.add(pluginContext.irFactory.buildFun { + name = Name.identifier("") + returnType = uintType + }. also { + it.body = DeclarationIrBuilder(pluginContext, it.symbol) + .irExprBody( + unsafeCoerce(IrConstImpl.int(-1, -1, pluginContext.irBuiltIns.intType, 1), pluginContext.irBuiltIns.intType, uintType) + ) + it.parent = declaration + }) + } + + private fun addFunWithExprBody(declaration: IrClass) { + declaration.declarations.add(pluginContext.irFactory.buildFun { + name = Name.identifier("") + returnType = pluginContext.irBuiltIns.intType + }. also { + it.body = DeclarationIrBuilder(pluginContext, it.symbol) + .irExprBody( + IrConstImpl.int(-1, -1, pluginContext.irBuiltIns.intType, 42) + ) + it.parent = declaration + }) + } + + private fun addStaticFieldWithExprInit(declaration: IrClass) { + declaration.declarations.add(pluginContext.irFactory.buildProperty { + name = Name.identifier("bar") + isConst = true + visibility = DescriptorVisibilities.PRIVATE + }.also { irProperty -> + irProperty.backingField = pluginContext.irFactory.buildField { + name = Name.identifier("bar") + type = pluginContext.irBuiltIns.stringType + isStatic = true + visibility = DescriptorVisibilities.PRIVATE + }.also { irField -> + irField.initializer = DeclarationIrBuilder(pluginContext, irField.symbol) + .irExprBody( + IrConstImpl.string(-1, -1, pluginContext.irBuiltIns.stringType, "Foobar") + ) + irField.parent = declaration + } + irProperty.parent = declaration + }) + } + + val javaLangPackage = IrExternalPackageFragmentImpl.createEmptyExternalPackageFragment(pluginContext.moduleDescriptor, FqName("java.lang")) + + private fun makeJavaLangClass(fnName: String) = pluginContext.irFactory.buildClass { + name = Name.identifier(fnName) + kind = ClassKind.CLASS + origin = IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB + }.apply { + parent = javaLangPackage + createImplicitParameterDeclarationWithWrappedDescriptor() + } + + // This adds a function with a parameter whose type is a real class without its supertypes specified, + // mimicking the behaviour of the Kotlin android extensions gradle plugin, which refers to some real + // Android classes through these sorts of synthetic, incomplete references. The extractor should + // respond by replacing them with the real version available on the classpath. + // I pick the particular java.lang class "ProcessBuilder" since it is (a) always available and + // (b) not normally extracted by this project. + private fun addFunWithStubClass(declaration: IrClass) { + declaration.declarations.add(pluginContext.irFactory.buildFun { + name = Name.identifier("") + returnType = pluginContext.irBuiltIns.unitType + }. also { addedFn -> + val processBuilderStub = makeJavaLangClass("ProcessBuilder") + val processBuilderStubType = processBuilderStub.defaultType + val startProcessMethod = processBuilderStub.addFunction { + name = Name.identifier("start") + origin = IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB + modality = Modality.FINAL + returnType = pluginContext.referenceClass(FqName("java.lang.Process"))!!.owner.defaultType + }.apply { + addDispatchReceiver { type = processBuilderStubType } + } + + val paramSymbol = addedFn.addValueParameter("param", processBuilderStubType) + DeclarationIrBuilder(pluginContext, addedFn.symbol).apply { + addedFn.body = irExprBody(irCall(startProcessMethod).apply { dispatchReceiver = irGet(paramSymbol) }) + addedFn.parent = declaration + } + }) + } + }, null) + } +} diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/plugin/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/plugin/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar new file mode 100644 index 00000000000..5d546a3b00a --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/plugin/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar @@ -0,0 +1 @@ +com.github.codeql.TestComponentRegistrar diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/rootClasses.expected b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/rootClasses.expected new file mode 100644 index 00000000000..1f41ac1e6bb --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/rootClasses.expected @@ -0,0 +1,4 @@ +| file://:0:0:0:0 | fake.kotlin | FakeKotlinClass | +| file://:0:0:0:0 | java.lang | Object | +| file://:0:0:0:0 | kotlin | Any | +| file://:0:0:0:0 | kotlin | TypeParam | diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/rootClasses.ql b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/rootClasses.ql new file mode 100644 index 00000000000..640ae984d14 --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/rootClasses.ql @@ -0,0 +1,5 @@ +import java + +from ClassOrInterface ci +where not exists(ci.getASupertype()) +select ci.getPackage(), ci.toString() diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/staticinit.expected b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/staticinit.expected new file mode 100644 index 00000000000..606bbd3f338 --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/staticinit.expected @@ -0,0 +1 @@ +| d.kt:0:0:0:0 | bar | d.kt:0:0:0:0 | Foobar | diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/staticinit.ql b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/staticinit.ql new file mode 100644 index 00000000000..de6bd1ca92e --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/staticinit.ql @@ -0,0 +1,5 @@ +import java + +from Field f, Expr init +where init = f.getInitializer() +select f, init diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/test.py b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/test.py new file mode 100644 index 00000000000..98610959b58 --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/test.py @@ -0,0 +1,6 @@ +from create_database_utils import * +import subprocess + +subprocess.call("./build_plugin", shell=True) +run_codeql_database_create( + ["kotlinc -J-Xmx2G -Xplugin=plugin.jar a.kt b.kt c.kt d.kt e.kt"], lang="java") diff --git a/java/ql/integration-tests/linux-only/kotlin/qlpack.yml b/java/ql/integration-tests/linux-only/kotlin/qlpack.yml new file mode 100644 index 00000000000..11adb1f538b --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/qlpack.yml @@ -0,0 +1,2 @@ +libraryPathDependencies: + - codeql-java diff --git a/java/ql/integration-tests/linux-only/kotlin/use_java_library/javasrc/extlib/BoundedGenericTest.java b/java/ql/integration-tests/linux-only/kotlin/use_java_library/javasrc/extlib/BoundedGenericTest.java new file mode 100644 index 00000000000..1bc13098a62 --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/use_java_library/javasrc/extlib/BoundedGenericTest.java @@ -0,0 +1,8 @@ +package extlib; + +public class BoundedGenericTest { + + public void method(T t) { } + +} + diff --git a/java/ql/integration-tests/linux-only/kotlin/use_java_library/javasrc/extlib/ComplexBoundedGenericTest.java b/java/ql/integration-tests/linux-only/kotlin/use_java_library/javasrc/extlib/ComplexBoundedGenericTest.java new file mode 100644 index 00000000000..16d0d950e0c --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/use_java_library/javasrc/extlib/ComplexBoundedGenericTest.java @@ -0,0 +1,8 @@ +package extlib; + +public class ComplexBoundedGenericTest { + + public void method(A a, B b) { } + +} + diff --git a/java/ql/integration-tests/linux-only/kotlin/use_java_library/javasrc/extlib/GenericTest.java b/java/ql/integration-tests/linux-only/kotlin/use_java_library/javasrc/extlib/GenericTest.java new file mode 100644 index 00000000000..d953cf90b98 --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/use_java_library/javasrc/extlib/GenericTest.java @@ -0,0 +1,10 @@ +package extlib; + +public class GenericTest { + + public void method(T t) { } + + public void takesSelfMethod(GenericTest selfLike) { } + +} + diff --git a/java/ql/integration-tests/linux-only/kotlin/use_java_library/javasrc/extlib/Lib.java b/java/ql/integration-tests/linux-only/kotlin/use_java_library/javasrc/extlib/Lib.java new file mode 100644 index 00000000000..f533e43c527 --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/use_java_library/javasrc/extlib/Lib.java @@ -0,0 +1,35 @@ +package extlib; + +import java.util.*; + +public class Lib { + + public void testParameterTypes( + char p1, + byte p2, + short p3, + int p4, + long p5, + float p6, + double p7, + boolean p8, + Lib simpleClass, + GenericTest simpleGeneric, + BoundedGenericTest boundedGeneric, + ComplexBoundedGenericTest complexBoundedGeneric, + int[] primitiveArray, + Integer[] boxedTypeArray, + int [][] multiDimensionalPrimitiveArray, + Integer[][] multiDimensionalBoxedTypeArray, + List[] genericTypeArray, + List producerWildcard, + List consumerWildcard, + List> nestedWildcard, + List unboundedWildcard) { } + + public List returnErasureTest() { return null; } + + public void paramErasureTest(List param) { } + +} + diff --git a/java/ql/integration-tests/linux-only/kotlin/use_java_library/parameterTypes.expected b/java/ql/integration-tests/linux-only/kotlin/use_java_library/parameterTypes.expected new file mode 100644 index 00000000000..605c9628bff --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/use_java_library/parameterTypes.expected @@ -0,0 +1,52 @@ +parameterTypes +| extlib.jar/extlib/GenericTest.class:0:0:0:0 | p0 | GenericTest | +| javasrc/extlib/GenericTest.java:7:31:7:53 | selfLike | GenericTest | +| javasrc/extlib/Lib.java:8:5:8:11 | p1 | char | +| javasrc/extlib/Lib.java:9:5:9:11 | p2 | byte | +| javasrc/extlib/Lib.java:10:5:10:12 | p3 | short | +| javasrc/extlib/Lib.java:11:5:11:10 | p4 | int | +| javasrc/extlib/Lib.java:12:5:12:11 | p5 | long | +| javasrc/extlib/Lib.java:13:5:13:12 | p6 | float | +| javasrc/extlib/Lib.java:14:5:14:13 | p7 | double | +| javasrc/extlib/Lib.java:15:5:15:14 | p8 | boolean | +| javasrc/extlib/Lib.java:16:5:16:19 | simpleClass | Lib | +| javasrc/extlib/Lib.java:17:5:17:37 | simpleGeneric | GenericTest | +| javasrc/extlib/Lib.java:18:5:18:45 | boundedGeneric | BoundedGenericTest | +| javasrc/extlib/Lib.java:19:5:19:73 | complexBoundedGeneric | ComplexBoundedGenericTest | +| javasrc/extlib/Lib.java:20:5:20:24 | primitiveArray | int[] | +| javasrc/extlib/Lib.java:21:5:21:28 | boxedTypeArray | Integer[] | +| javasrc/extlib/Lib.java:22:5:22:43 | multiDimensionalPrimitiveArray | int[][] | +| javasrc/extlib/Lib.java:23:5:23:46 | multiDimensionalBoxedTypeArray | Integer[][] | +| javasrc/extlib/Lib.java:24:5:24:35 | genericTypeArray | List[] | +| javasrc/extlib/Lib.java:25:5:25:49 | producerWildcard | List | +| javasrc/extlib/Lib.java:26:5:26:47 | consumerWildcard | List | +| javasrc/extlib/Lib.java:27:5:27:63 | nestedWildcard | List> | +| javasrc/extlib/Lib.java:28:5:28:29 | unboundedWildcard | List | +arrayTypes +| javasrc/extlib/Lib.java:20:5:20:24 | primitiveArray | file://:0:0:0:0 | int[] | int | 1 | int | +| javasrc/extlib/Lib.java:21:5:21:28 | boxedTypeArray | file://:0:0:0:0 | Integer[] | Integer | 1 | Integer | +| javasrc/extlib/Lib.java:22:5:22:43 | multiDimensionalPrimitiveArray | file://:0:0:0:0 | int[][] | int | 2 | int[] | +| javasrc/extlib/Lib.java:23:5:23:46 | multiDimensionalBoxedTypeArray | file://:0:0:0:0 | Integer[][] | Integer | 2 | Integer[] | +| javasrc/extlib/Lib.java:24:5:24:35 | genericTypeArray | file://:0:0:0:0 | List[] | List | 1 | List | +wildcardTypes +| javasrc/extlib/Lib.java:25:5:25:49 | producerWildcard | file://:0:0:0:0 | ? extends CharSequence | upper | CharSequence | +| javasrc/extlib/Lib.java:26:5:26:47 | consumerWildcard | file://:0:0:0:0 | ? super CharSequence | lower | CharSequence | +| javasrc/extlib/Lib.java:26:5:26:47 | consumerWildcard | file://:0:0:0:0 | ? super CharSequence | upper | Object | +| javasrc/extlib/Lib.java:27:5:27:63 | nestedWildcard | file://:0:0:0:0 | ? extends List | upper | List | +| javasrc/extlib/Lib.java:28:5:28:29 | unboundedWildcard | file://:0:0:0:0 | ? | upper | Object | +parameterizedTypes +| extlib.jar/extlib/GenericTest.class:0:0:0:0 | p0 | GenericTest | String | +| javasrc/extlib/GenericTest.java:7:31:7:53 | selfLike | GenericTest | T | +| javasrc/extlib/Lib.java:17:5:17:37 | simpleGeneric | GenericTest | String | +| javasrc/extlib/Lib.java:18:5:18:45 | boundedGeneric | BoundedGenericTest | String | +| javasrc/extlib/Lib.java:19:5:19:73 | complexBoundedGeneric | ComplexBoundedGenericTest | CharSequence | +| javasrc/extlib/Lib.java:19:5:19:73 | complexBoundedGeneric | ComplexBoundedGenericTest | String | +| javasrc/extlib/Lib.java:25:5:25:49 | producerWildcard | List | ? extends CharSequence | +| javasrc/extlib/Lib.java:26:5:26:47 | consumerWildcard | List | ? super CharSequence | +| javasrc/extlib/Lib.java:27:5:27:63 | nestedWildcard | List> | ? extends List | +| javasrc/extlib/Lib.java:28:5:28:29 | unboundedWildcard | List | ? | +libCallables +| javasrc/extlib/Lib.java:5:14:5:16 | Lib | +| javasrc/extlib/Lib.java:7:15:7:32 | testParameterTypes | +| javasrc/extlib/Lib.java:30:24:30:40 | returnErasureTest | +| javasrc/extlib/Lib.java:32:19:32:34 | paramErasureTest | diff --git a/java/ql/integration-tests/linux-only/kotlin/use_java_library/parameterTypes.ql b/java/ql/integration-tests/linux-only/kotlin/use_java_library/parameterTypes.ql new file mode 100644 index 00000000000..31397f18ac8 --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/use_java_library/parameterTypes.ql @@ -0,0 +1,40 @@ +import java + +class ExtLibParameter extends Parameter { + ExtLibParameter() { this.getCallable().getName() = ["testParameterTypes", "takesSelfMethod"] } +} + +query predicate parameterTypes(ExtLibParameter p, string t) { p.getType().toString() = t } + +query predicate arrayTypes( + ExtLibParameter p, Array at, string elementType, int dimension, string componentType +) { + p.getType() = at and + at.getElementType().toString() = elementType and + at.getDimension() = dimension and + at.getComponentType().toString() = componentType +} + +query predicate wildcardTypes(ExtLibParameter p, Wildcard wc, string boundKind, string bound) { + // Expose details of wildcard types: + wc = + [ + p.getType().(ParameterizedType).getATypeArgument(), + p.getType().(ParameterizedType).getATypeArgument().(ParameterizedType).getATypeArgument() + ] and + ( + boundKind = "upper" and bound = wc.getUpperBoundType().toString() + or + boundKind = "lower" and bound = wc.getLowerBoundType().toString() + ) +} + +query predicate parameterizedTypes(ExtLibParameter p, string ptstr, string typeArg) { + exists(ParameterizedType pt | + p.getType() = pt and + pt.getATypeArgument().toString() = typeArg and + ptstr = pt.toString() + ) +} + +query predicate libCallables(Callable c) { c.getFile().getBaseName().matches("%Lib.java") } diff --git a/java/ql/integration-tests/linux-only/kotlin/use_java_library/test.py b/java/ql/integration-tests/linux-only/kotlin/use_java_library/test.py new file mode 100644 index 00000000000..13230ceeb43 --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/use_java_library/test.py @@ -0,0 +1,8 @@ +from create_database_utils import * +import glob + +os.mkdir('build') +javaccmd = " ".join(["javac"] + glob.glob("javasrc/extlib/*.java") + ["-d", "build"]) +jarcmd = " ".join(["jar", "-c", "-f", "extlib.jar", "-C", "build", "extlib"]) +run_codeql_database_create([javaccmd, jarcmd, "kotlinc user.kt -cp extlib.jar"], lang="java") + diff --git a/java/ql/integration-tests/linux-only/kotlin/use_java_library/user.kt b/java/ql/integration-tests/linux-only/kotlin/use_java_library/user.kt new file mode 100644 index 00000000000..d2c0a5bf341 --- /dev/null +++ b/java/ql/integration-tests/linux-only/kotlin/use_java_library/user.kt @@ -0,0 +1,45 @@ +import extlib.* +import java.util.* + +fun test() { + + // Pending better varargs support, avoiding listOf and mutableListOf + val stringList = ArrayList() + val objectList = ArrayList() + val stringStringList = ArrayList>() + + val lib = Lib() + lib.testParameterTypes( + 'a', + 1, + 2, + 3, + 4, + 5.0f, + 6.0, + true, + Lib(), + GenericTest(), + BoundedGenericTest(), + ComplexBoundedGenericTest(), + intArrayOf(1), + arrayOf(1), + arrayOf(intArrayOf(1)), + arrayOf(arrayOf(1)), + arrayOf(stringList), + stringList, + objectList, + stringStringList, + objectList) + + val returnedList = lib.returnErasureTest() + lib.paramErasureTest(listOf("Hello")) + + // Check trap labelling consistency for methods that instantiate a generic type + // with its own generic parameters -- for example, class MyList { void addAll(MyList l) { } }, + // which has the trap labelling oddity of looking like plain MyList, not MyList, even though + // this is a generic instantiation. + val takesSelfTest = GenericTest() + takesSelfTest.takesSelfMethod(takesSelfTest) + +} diff --git a/java/ql/integration-tests/posix-only/kotlin/enabling/KotlinDefault.kt b/java/ql/integration-tests/posix-only/kotlin/enabling/KotlinDefault.kt new file mode 100644 index 00000000000..3defce70dac --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/enabling/KotlinDefault.kt @@ -0,0 +1 @@ +class KotlinDefault {} diff --git a/java/ql/integration-tests/posix-only/kotlin/enabling/KotlinDisabled.kt b/java/ql/integration-tests/posix-only/kotlin/enabling/KotlinDisabled.kt new file mode 100644 index 00000000000..7e1bd360129 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/enabling/KotlinDisabled.kt @@ -0,0 +1 @@ +class KotlinDisabled {} diff --git a/java/ql/integration-tests/posix-only/kotlin/enabling/KotlinEnabled.kt b/java/ql/integration-tests/posix-only/kotlin/enabling/KotlinEnabled.kt new file mode 100644 index 00000000000..7d7dcff7040 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/enabling/KotlinEnabled.kt @@ -0,0 +1 @@ +class KotlinEnabled {} diff --git a/java/ql/integration-tests/posix-only/kotlin/enabling/build.py b/java/ql/integration-tests/posix-only/kotlin/enabling/build.py new file mode 100644 index 00000000000..63f29878915 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/enabling/build.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 + +from create_database_utils import * + +runSuccessfully(["kotlinc", "KotlinDefault.kt"]) +os.environ['CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN'] = 'true' +runSuccessfully(["kotlinc", "KotlinDisabled.kt"]) +del(os.environ['CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN']) +os.environ['CODEQL_EXTRACTOR_JAVA_AGENT_ENABLE_KOTLIN'] = 'true' +runSuccessfully(["kotlinc", "KotlinEnabled.kt"]) diff --git a/java/ql/integration-tests/posix-only/kotlin/enabling/class.expected b/java/ql/integration-tests/posix-only/kotlin/enabling/class.expected new file mode 100644 index 00000000000..8c8a04f83ce --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/enabling/class.expected @@ -0,0 +1 @@ +| KotlinEnabled.kt:1:1:1:22 | KotlinEnabled | diff --git a/java/ql/integration-tests/posix-only/kotlin/enabling/class.ql b/java/ql/integration-tests/posix-only/kotlin/enabling/class.ql new file mode 100644 index 00000000000..35cdaef9da7 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/enabling/class.ql @@ -0,0 +1,5 @@ +import java + +from Class c +where c.fromSource() +select c diff --git a/java/ql/integration-tests/posix-only/kotlin/enabling/test.py b/java/ql/integration-tests/posix-only/kotlin/enabling/test.py new file mode 100644 index 00000000000..4bcf7ada880 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/enabling/test.py @@ -0,0 +1,9 @@ +from create_database_utils import * + +for var in ['CODEQL_EXTRACTOR_JAVA_AGENT_ENABLE_KOTLIN', + 'CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN']: + if var in os.environ: + del(os.environ[var]) + +run_codeql_database_create(['"%s" build.py' % sys.executable], lang="java") + diff --git a/java/ql/integration-tests/posix-only/kotlin/extractor_crash/classes.expected b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/classes.expected new file mode 100644 index 00000000000..e84dc8f218d --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/classes.expected @@ -0,0 +1,2 @@ +| code/A.kt:2:1:2:10 | A | +| code/C.kt:2:1:2:10 | C | diff --git a/java/ql/integration-tests/posix-only/kotlin/extractor_crash/classes.ql b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/classes.ql new file mode 100644 index 00000000000..35cdaef9da7 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/classes.ql @@ -0,0 +1,5 @@ +import java + +from Class c +where c.fromSource() +select c diff --git a/java/ql/integration-tests/posix-only/kotlin/extractor_crash/code/A.kt b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/code/A.kt new file mode 100644 index 00000000000..d11e54e922f --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/code/A.kt @@ -0,0 +1,3 @@ + +class A {} + diff --git a/java/ql/integration-tests/posix-only/kotlin/extractor_crash/code/B.kt b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/code/B.kt new file mode 100644 index 00000000000..a4d3b9876ee --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/code/B.kt @@ -0,0 +1,3 @@ + +class B {} + diff --git a/java/ql/integration-tests/posix-only/kotlin/extractor_crash/code/C.kt b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/code/C.kt new file mode 100644 index 00000000000..ddd7c69e28c --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/code/C.kt @@ -0,0 +1,3 @@ + +class C {} + diff --git a/java/ql/integration-tests/posix-only/kotlin/extractor_crash/code/build.py b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/code/build.py new file mode 100644 index 00000000000..db077b5e41e --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/code/build.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import os +import subprocess + +os.environ['CODEQL_KOTLIN_INTERNAL_EXCEPTION_WHILE_EXTRACTING_FILE'] = 'B.kt' + +subprocess.check_call(['kotlinc', 'A.kt', 'B.kt', 'C.kt', ]) diff --git a/java/ql/integration-tests/posix-only/kotlin/extractor_crash/compilationFiles.expected b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/compilationFiles.expected new file mode 100644 index 00000000000..48a0d4ec87b --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/compilationFiles.expected @@ -0,0 +1,3 @@ +| | 0 | code/A.kt:0:0:0:0 | A | Extraction successful | Not recoverable errors | Not non-recoverable errors | +| | 1 | code/B.kt:0:0:0:0 | code/B.kt | Not extraction successful | Not recoverable errors | Non-recoverable errors | +| | 2 | code/C.kt:0:0:0:0 | C | Extraction successful | Not recoverable errors | Not non-recoverable errors | diff --git a/java/ql/integration-tests/posix-only/kotlin/extractor_crash/compilationFiles.ql b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/compilationFiles.ql new file mode 100644 index 00000000000..b3c9437c3d4 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/compilationFiles.ql @@ -0,0 +1,24 @@ +import java + +class AnonymousCompilation extends Compilation { + override string toString() { result = "" } +} + +from Compilation c, int i, File f +where f = c.getFileCompiled(i) +select c, i, f, + any(string s | + if c.fileCompiledSuccessful(i) + then s = "Extraction successful" + else s = "Not extraction successful" + ), + any(string s | + if c.fileCompiledRecoverableErrors(i) + then s = "Recoverable errors" + else s = "Not recoverable errors" + ), + any(string s | + if c.fileCompiledNonRecoverableErrors(i) + then s = "Non-recoverable errors" + else s = "Not non-recoverable errors" + ) diff --git a/java/ql/integration-tests/posix-only/kotlin/extractor_crash/compilations.expected b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/compilations.expected new file mode 100644 index 00000000000..c87bb373166 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/compilations.expected @@ -0,0 +1 @@ +| | Normal termination | Not extraction successful | Not recoverable errors | Non-recoverable errors | diff --git a/java/ql/integration-tests/posix-only/kotlin/extractor_crash/compilations.ql b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/compilations.ql new file mode 100644 index 00000000000..13d4ce46f51 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/compilations.ql @@ -0,0 +1,24 @@ +import java + +class AnonymousCompilation extends Compilation { + override string toString() { result = "" } +} + +from Compilation c +select c, + any(string s | + if c.normalTermination() then s = "Normal termination" else s = "Not normal termination" + ), + any(string s | + if c.extractionSuccessful() + then s = "Extraction successful" + else s = "Not extraction successful" + ), + any(string s | + if c.recoverableErrors() then s = "Recoverable errors" else s = "Not recoverable errors" + ), + any(string s | + if c.nonRecoverableErrors() + then s = "Non-recoverable errors" + else s = "Not non-recoverable errors" + ) diff --git a/java/ql/integration-tests/posix-only/kotlin/extractor_crash/test.py b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/test.py new file mode 100644 index 00000000000..9abcb43e304 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/extractor_crash/test.py @@ -0,0 +1,7 @@ +import sys + +from create_database_utils import * + +run_codeql_database_create( + ['"%s" build.py' % sys.executable], + source="code", lang="java") diff --git a/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/app/build.gradle b/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/app/build.gradle new file mode 100644 index 00000000000..16aad9297b0 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/app/build.gradle @@ -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.5.31' + + // 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' +} diff --git a/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/app/src/main/kotlin/testProject/App.kt b/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/app/src/main/kotlin/testProject/App.kt new file mode 100644 index 00000000000..0ed9df24a57 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/app/src/main/kotlin/testProject/App.kt @@ -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) +} diff --git a/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/compilations.expected b/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/compilations.expected new file mode 100644 index 00000000000..2a4f078a25f --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/compilations.expected @@ -0,0 +1 @@ +| 1 | diff --git a/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/compilations.ql b/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/compilations.ql new file mode 100644 index 00000000000..7ddd497d555 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/compilations.ql @@ -0,0 +1,3 @@ +import java + +select count(Compilation c) diff --git a/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/methods.expected b/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/methods.expected new file mode 100644 index 00000000000..9f5adb7d6e5 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/methods.expected @@ -0,0 +1,2 @@ +| app/src/main/kotlin/testProject/App.kt:8:9:10:9 | getGreeting | +| app/src/main/kotlin/testProject/App.kt:13:1:15:1 | main | diff --git a/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/methods.ql b/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/methods.ql new file mode 100644 index 00000000000..9d32c93e69c --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/methods.ql @@ -0,0 +1,5 @@ +import java + +from Method m +where exists(m.getFile().getRelativePath()) +select m diff --git a/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/settings.gradle b/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/settings.gradle new file mode 100644 index 00000000000..a56fb7dd11c --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/settings.gradle @@ -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') diff --git a/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/test.py b/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/test.py new file mode 100644 index 00000000000..7f44398cd12 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/gradle_groovy_app/test.py @@ -0,0 +1,4 @@ +from create_database_utils import * + +run_codeql_database_create(["gradle build --no-daemon --no-build-cache"], lang="java") +runSuccessfully(["gradle", "clean"]) diff --git a/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/PrintAst.expected b/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/PrintAst.expected new file mode 100644 index 00000000000..f5a92b6fd3d --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/PrintAst.expected @@ -0,0 +1,432 @@ +app/src/main/kotlin/testProject/App.kt: +# 0| [CompilationUnit] App +# 7| 1: [Class] Project +# 0| 1: [Constructor] Project +#-----| 4: (Parameters) +# 0| 0: [Parameter] seen1 +# 0| 0: [TypeAccess] int +# 0| 1: [Parameter] name +# 0| 0: [TypeAccess] String +# 0| 2: [Parameter] language +# 0| 0: [TypeAccess] int +# 0| 3: [Parameter] serializationConstructorMarker +# 0| 0: [TypeAccess] SerializationConstructorMarker +# 7| 5: [BlockStmt] { ... } +# 7| 0: [ExprStmt] ; +# 7| 0: [WhenExpr] when ... +# 7| 0: [WhenBranch] ... -> ... +# 7| 0: [ValueNEExpr] ... (value not-equals) ... +# 7| 0: [IntegerLiteral] 3 +# 7| 1: [MethodAccess] and(...) +# 7| -1: [IntegerLiteral] 3 +# 7| 0: [VarAccess] seen1 +# 7| 1: [ExprStmt] ; +# 7| 0: [MethodAccess] throwMissingFieldException(...) +# 7| -1: [TypeAccess] PluginExceptionsKt +# 7| 0: [VarAccess] seen1 +# 7| 1: [IntegerLiteral] 3 +# 7| 2: [MethodAccess] getDescriptor(...) +# 7| -1: [VarAccess] INSTANCE +# 7| 1: [SuperConstructorInvocationStmt] super(...) +# 7| 2: [ExprStmt] ; +# 7| 0: [AssignExpr] ...=... +# 7| 0: [VarAccess] Project.this.name +# 7| -1: [ThisAccess] Project.this +# 7| 0: [TypeAccess] Project +# 7| 1: [VarAccess] name +# 7| 3: [ExprStmt] ; +# 7| 0: [AssignExpr] ...=... +# 7| 0: [VarAccess] Project.this.language +# 7| -1: [ThisAccess] Project.this +# 7| 0: [TypeAccess] Project +# 7| 1: [VarAccess] language +# 0| 1: [Method] write$Self +# 0| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 0| 0: [Parameter] self +# 0| 0: [TypeAccess] Project +# 0| 1: [Parameter] output +# 0| 0: [TypeAccess] CompositeEncoder +# 0| 2: [Parameter] serialDesc +# 0| 0: [TypeAccess] SerialDescriptor +# 7| 5: [BlockStmt] { ... } +# 7| 0: [ExprStmt] ; +# 7| 0: [MethodAccess] encodeStringElement(...) +# 7| -1: [VarAccess] output +# 7| 0: [VarAccess] serialDesc +# 7| 1: [IntegerLiteral] 0 +# 7| 2: [MethodAccess] getName(...) +# 7| -1: [VarAccess] self +# 7| 1: [ExprStmt] ; +# 7| 0: [MethodAccess] encodeIntElement(...) +# 7| -1: [VarAccess] output +# 7| 0: [VarAccess] serialDesc +# 7| 1: [IntegerLiteral] 1 +# 7| 2: [MethodAccess] getLanguage(...) +# 7| -1: [VarAccess] self +# 0| 1: [Method] component1 +# 0| 3: [TypeAccess] String +# 0| 5: [BlockStmt] { ... } +# 0| 0: [ReturnStmt] return ... +# 0| 0: [VarAccess] this.name +# 0| -1: [ThisAccess] this +# 0| 1: [Method] component2 +# 0| 3: [TypeAccess] int +# 0| 5: [BlockStmt] { ... } +# 0| 0: [ReturnStmt] return ... +# 0| 0: [VarAccess] this.language +# 0| -1: [ThisAccess] this +# 0| 1: [Method] copy +# 0| 3: [TypeAccess] Project +#-----| 4: (Parameters) +# 8| 0: [Parameter] name +# 8| 0: [TypeAccess] String +# 8| 1: [Parameter] language +# 8| 0: [TypeAccess] int +# 0| 5: [BlockStmt] { ... } +# 0| 0: [ReturnStmt] return ... +# 0| 0: [ClassInstanceExpr] new Project(...) +# 0| -3: [TypeAccess] Project +# 0| 0: [VarAccess] name +# 0| 1: [VarAccess] language +# 0| 1: [Method] toString +# 0| 3: [TypeAccess] String +# 0| 5: [BlockStmt] { ... } +# 0| 0: [ReturnStmt] return ... +# 0| 0: [StringTemplateExpr] "..." +# 0| 0: [StringLiteral] Project( +# 0| 1: [StringLiteral] name= +# 0| 2: [VarAccess] this.name +# 0| -1: [ThisAccess] this +# 0| 3: [StringLiteral] , +# 0| 4: [StringLiteral] language= +# 0| 5: [VarAccess] this.language +# 0| -1: [ThisAccess] this +# 0| 6: [StringLiteral] ) +# 0| 1: [Method] hashCode +# 0| 3: [TypeAccess] int +# 0| 5: [BlockStmt] { ... } +# 0| 0: [LocalVariableDeclStmt] var ...; +# 0| 1: [LocalVariableDeclExpr] result +# 0| 0: [MethodAccess] hashCode(...) +# 0| -1: [VarAccess] this.name +# 0| -1: [ThisAccess] this +# 0| 1: [ExprStmt] ; +# 0| 0: [AssignExpr] ...=... +# 0| 0: [VarAccess] result +# 0| 1: [MethodAccess] plus(...) +# 0| -1: [MethodAccess] times(...) +# 0| -1: [VarAccess] result +# 0| 0: [IntegerLiteral] 31 +# 0| 0: [MethodAccess] hashCode(...) +# 0| -1: [VarAccess] this.language +# 0| -1: [ThisAccess] this +# 0| 2: [ReturnStmt] return ... +# 0| 0: [VarAccess] result +# 0| 1: [Method] equals +# 0| 3: [TypeAccess] boolean +#-----| 4: (Parameters) +# 0| 0: [Parameter] other +# 0| 0: [TypeAccess] Object +# 0| 5: [BlockStmt] { ... } +# 0| 0: [ExprStmt] ; +# 0| 0: [WhenExpr] when ... +# 0| 0: [WhenBranch] ... -> ... +# 0| 0: [EQExpr] ... == ... +# 0| 0: [ThisAccess] this +# 0| 1: [VarAccess] other +# 0| 1: [ReturnStmt] return ... +# 0| 0: [BooleanLiteral] true +# 0| 1: [ExprStmt] ; +# 0| 0: [WhenExpr] when ... +# 0| 0: [WhenBranch] ... -> ... +# 0| 0: [NotInstanceOfExpr] ... !is ... +# 0| 0: [VarAccess] other +# 0| 1: [TypeAccess] Project +# 0| 1: [ReturnStmt] return ... +# 0| 0: [BooleanLiteral] false +# 0| 2: [LocalVariableDeclStmt] var ...; +# 0| 1: [LocalVariableDeclExpr] tmp0_other_with_cast +# 0| 0: [CastExpr] (...)... +# 0| 0: [TypeAccess] Project +# 0| 1: [VarAccess] other +# 0| 3: [ExprStmt] ; +# 0| 0: [WhenExpr] when ... +# 0| 0: [WhenBranch] ... -> ... +# 0| 0: [ValueNEExpr] ... (value not-equals) ... +# 0| 0: [VarAccess] this.name +# 0| -1: [ThisAccess] this +# 0| 1: [VarAccess] tmp0_other_with_cast.name +# 0| -1: [VarAccess] tmp0_other_with_cast +# 0| 1: [ReturnStmt] return ... +# 0| 0: [BooleanLiteral] false +# 0| 4: [ExprStmt] ; +# 0| 0: [WhenExpr] when ... +# 0| 0: [WhenBranch] ... -> ... +# 0| 0: [ValueNEExpr] ... (value not-equals) ... +# 0| 0: [VarAccess] this.language +# 0| -1: [ThisAccess] this +# 0| 1: [VarAccess] tmp0_other_with_cast.language +# 0| -1: [VarAccess] tmp0_other_with_cast +# 0| 1: [ReturnStmt] return ... +# 0| 0: [BooleanLiteral] false +# 0| 5: [ReturnStmt] return ... +# 0| 0: [BooleanLiteral] true +# 7| 9: [Class] Companion +# 0| 1: [Method] serializer +# 0| 3: [TypeAccess] KSerializer +# 0| 0: [TypeAccess] Project +# 7| 5: [BlockStmt] { ... } +# 7| 0: [ReturnStmt] return ... +# 7| 0: [VarAccess] INSTANCE +# 7| 2: [Constructor] Companion +# 7| 5: [BlockStmt] { ... } +# 7| 0: [SuperConstructorInvocationStmt] super(...) +# 7| 1: [BlockStmt] { ... } +# 7| 9: [Class] $serializer +# 0| 1: [Method] getDescriptor +# 0| 3: [TypeAccess] SerialDescriptor +# 0| 5: [BlockStmt] { ... } +# 0| 0: [ReturnStmt] return ... +# 0| 0: [VarAccess] this.descriptor +# 0| -1: [ThisAccess] this +# 0| 1: [FieldDeclaration] SerialDescriptor descriptor; +# 0| -1: [TypeAccess] SerialDescriptor +# 0| 1: [Method] childSerializers +# 0| 3: [TypeAccess] KSerializer[] +# 0| 0: [TypeAccess] KSerializer +# 0| 0: [WildcardTypeAccess] ? ... +# 7| 5: [BlockStmt] { ... } +# 7| 0: [ReturnStmt] return ... +# 7| 0: [ArrayCreationExpr] new KSerializer[] +# 7| -2: [ArrayInit] {...} +# 7| 0: [VarAccess] INSTANCE +# 7| 1: [VarAccess] INSTANCE +# 7| -1: [TypeAccess] KSerializer +# 7| 0: [IntegerLiteral] 2 +# 0| 1: [Method] deserialize +# 0| 3: [TypeAccess] Project +#-----| 4: (Parameters) +# 0| 0: [Parameter] decoder +# 0| 0: [TypeAccess] Decoder +# 7| 5: [BlockStmt] { ... } +# 7| 0: [LocalVariableDeclStmt] var ...; +# 7| 1: [LocalVariableDeclExpr] tmp0_desc +# 7| 0: [MethodAccess] getDescriptor(...) +# 7| -1: [ThisAccess] this +# 7| 1: [LocalVariableDeclStmt] var ...; +# 7| 1: [LocalVariableDeclExpr] tmp1_flag +# 7| 0: [BooleanLiteral] true +# 7| 2: [LocalVariableDeclStmt] var ...; +# 7| 1: [LocalVariableDeclExpr] tmp2_index +# 7| 0: [IntegerLiteral] 0 +# 7| 3: [LocalVariableDeclStmt] var ...; +# 7| 1: [LocalVariableDeclExpr] tmp3_bitMask0 +# 7| 0: [IntegerLiteral] 0 +# 7| 4: [LocalVariableDeclStmt] var ...; +# 7| 1: [LocalVariableDeclExpr] tmp4_local0 +# 7| 0: [NullLiteral] null +# 7| 5: [LocalVariableDeclStmt] var ...; +# 7| 1: [LocalVariableDeclExpr] tmp5_local1 +# 7| 0: [IntegerLiteral] 0 +# 7| 6: [LocalVariableDeclStmt] var ...; +# 7| 1: [LocalVariableDeclExpr] tmp6_input +# 7| 0: [MethodAccess] beginStructure(...) +# 7| -1: [VarAccess] decoder +# 7| 0: [VarAccess] tmp0_desc +# 7| 7: [ExprStmt] ; +# 7| 0: [WhenExpr] when ... +# 7| 0: [WhenBranch] ... -> ... +# 7| 0: [MethodAccess] decodeSequentially(...) +# 7| -1: [VarAccess] tmp6_input +# 7| 1: [BlockStmt] { ... } +# 7| 0: [BlockStmt] { ... } +# 7| 0: [ExprStmt] ; +# 7| 0: [AssignExpr] ...=... +# 7| 0: [VarAccess] tmp4_local0 +# 7| 1: [MethodAccess] decodeStringElement(...) +# 7| -1: [VarAccess] tmp6_input +# 7| 0: [VarAccess] tmp0_desc +# 7| 1: [IntegerLiteral] 0 +# 7| 1: [ExprStmt] ; +# 7| 0: [AssignExpr] ...=... +# 7| 0: [VarAccess] tmp3_bitMask0 +# 7| 1: [MethodAccess] or(...) +# 7| -1: [VarAccess] tmp3_bitMask0 +# 7| 0: [IntegerLiteral] 1 +# 7| 1: [BlockStmt] { ... } +# 7| 0: [ExprStmt] ; +# 7| 0: [AssignExpr] ...=... +# 7| 0: [VarAccess] tmp5_local1 +# 7| 1: [MethodAccess] decodeIntElement(...) +# 7| -1: [VarAccess] tmp6_input +# 7| 0: [VarAccess] tmp0_desc +# 7| 1: [IntegerLiteral] 1 +# 7| 1: [ExprStmt] ; +# 7| 0: [AssignExpr] ...=... +# 7| 0: [VarAccess] tmp3_bitMask0 +# 7| 1: [MethodAccess] or(...) +# 7| -1: [VarAccess] tmp3_bitMask0 +# 7| 0: [IntegerLiteral] 2 +# 7| 1: [WhenBranch] ... -> ... +# 7| 0: [BooleanLiteral] true +# 7| 1: [WhileStmt] while (...) +# 7| 0: [VarAccess] tmp1_flag +# 7| 1: [BlockStmt] { ... } +# 7| 0: [ExprStmt] ; +# 7| 0: [AssignExpr] ...=... +# 7| 0: [VarAccess] tmp2_index +# 7| 1: [MethodAccess] decodeElementIndex(...) +# 7| -1: [VarAccess] tmp6_input +# 7| 0: [VarAccess] tmp0_desc +# 7| 1: [ExprStmt] ; +# 7| 0: [WhenExpr] when ... +# 7| 0: [WhenBranch] ... -> ... +# 7| 0: [ValueEQExpr] ... (value equals) ... +# 7| 0: [VarAccess] tmp2_index +# 7| 1: [IntegerLiteral] -1 +# 7| 1: [ExprStmt] ; +# 7| 0: [AssignExpr] ...=... +# 7| 0: [VarAccess] tmp1_flag +# 7| 1: [BooleanLiteral] false +# 7| 1: [WhenBranch] ... -> ... +# 7| 0: [ValueEQExpr] ... (value equals) ... +# 7| 0: [VarAccess] tmp2_index +# 7| 1: [IntegerLiteral] 0 +# 7| 1: [BlockStmt] { ... } +# 7| 0: [ExprStmt] ; +# 7| 0: [AssignExpr] ...=... +# 7| 0: [VarAccess] tmp4_local0 +# 7| 1: [MethodAccess] decodeStringElement(...) +# 7| -1: [VarAccess] tmp6_input +# 7| 0: [VarAccess] tmp0_desc +# 7| 1: [IntegerLiteral] 0 +# 7| 1: [ExprStmt] ; +# 7| 0: [AssignExpr] ...=... +# 7| 0: [VarAccess] tmp3_bitMask0 +# 7| 1: [MethodAccess] or(...) +# 7| -1: [VarAccess] tmp3_bitMask0 +# 7| 0: [IntegerLiteral] 1 +# 7| 2: [WhenBranch] ... -> ... +# 7| 0: [ValueEQExpr] ... (value equals) ... +# 7| 0: [VarAccess] tmp2_index +# 7| 1: [IntegerLiteral] 1 +# 7| 1: [BlockStmt] { ... } +# 7| 0: [ExprStmt] ; +# 7| 0: [AssignExpr] ...=... +# 7| 0: [VarAccess] tmp5_local1 +# 7| 1: [MethodAccess] decodeIntElement(...) +# 7| -1: [VarAccess] tmp6_input +# 7| 0: [VarAccess] tmp0_desc +# 7| 1: [IntegerLiteral] 1 +# 7| 1: [ExprStmt] ; +# 7| 0: [AssignExpr] ...=... +# 7| 0: [VarAccess] tmp3_bitMask0 +# 7| 1: [MethodAccess] or(...) +# 7| -1: [VarAccess] tmp3_bitMask0 +# 7| 0: [IntegerLiteral] 2 +# 7| 3: [WhenBranch] ... -> ... +# 7| 0: [BooleanLiteral] true +# 7| 1: [ThrowStmt] throw ... +# 7| 0: [ClassInstanceExpr] new UnknownFieldException(...) +# 7| -3: [TypeAccess] UnknownFieldException +# 7| 0: [VarAccess] tmp2_index +# 7| 8: [ExprStmt] ; +# 7| 0: [MethodAccess] endStructure(...) +# 7| -1: [VarAccess] tmp6_input +# 7| 0: [VarAccess] tmp0_desc +# 7| 9: [ReturnStmt] return ... +# 7| 0: [ClassInstanceExpr] new Project(...) +# 7| -3: [TypeAccess] Project +# 7| 0: [VarAccess] tmp3_bitMask0 +# 7| 1: [VarAccess] tmp4_local0 +# 7| 2: [VarAccess] tmp5_local1 +# 7| 3: [NullLiteral] null +# 0| 1: [Method] serialize +# 0| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 0| 0: [Parameter] encoder +# 0| 0: [TypeAccess] Encoder +# 0| 1: [Parameter] value +# 0| 0: [TypeAccess] Project +# 7| 5: [BlockStmt] { ... } +# 7| 0: [LocalVariableDeclStmt] var ...; +# 7| 1: [LocalVariableDeclExpr] tmp0_desc +# 7| 0: [MethodAccess] getDescriptor(...) +# 7| -1: [ThisAccess] this +# 7| 1: [LocalVariableDeclStmt] var ...; +# 7| 1: [LocalVariableDeclExpr] tmp1_output +# 7| 0: [MethodAccess] beginStructure(...) +# 7| -1: [VarAccess] encoder +# 7| 0: [VarAccess] tmp0_desc +# 7| 2: [ExprStmt] ; +# 7| 0: [MethodAccess] write$Self(...) +# 7| -1: [TypeAccess] Project +# 7| 0: [VarAccess] value +# 7| 1: [VarAccess] tmp1_output +# 7| 2: [VarAccess] tmp0_desc +# 7| 3: [ExprStmt] ; +# 7| 0: [MethodAccess] endStructure(...) +# 7| -1: [VarAccess] tmp1_output +# 7| 0: [VarAccess] tmp0_desc +# 7| 6: [Constructor] $serializer +# 7| 5: [BlockStmt] { ... } +# 7| 0: [SuperConstructorInvocationStmt] super(...) +# 7| 1: [BlockStmt] { ... } +# 7| 0: [LocalVariableDeclStmt] var ...; +# 7| 1: [LocalVariableDeclExpr] tmp0_serialDesc +# 7| 0: [ClassInstanceExpr] new PluginGeneratedSerialDescriptor(...) +# 7| -3: [TypeAccess] PluginGeneratedSerialDescriptor +# 7| 0: [StringLiteral] testProject.Project +# 7| 1: [ThisAccess] $serializer.this +# 7| 0: [TypeAccess] $serializer +# 7| 2: [IntegerLiteral] 2 +# 7| 1: [ExprStmt] ; +# 7| 0: [MethodAccess] addElement(...) +# 7| -1: [VarAccess] tmp0_serialDesc +# 7| 0: [StringLiteral] name +# 7| 1: [BooleanLiteral] false +# 7| 2: [ExprStmt] ; +# 7| 0: [MethodAccess] addElement(...) +# 7| -1: [VarAccess] tmp0_serialDesc +# 7| 0: [StringLiteral] language +# 7| 1: [BooleanLiteral] false +# 7| 3: [ExprStmt] ; +# 7| 0: [AssignExpr] ...=... +# 7| 0: [VarAccess] $serializer.this.descriptor +# 7| -1: [ThisAccess] $serializer.this +# 7| 0: [TypeAccess] $serializer +# 7| 1: [VarAccess] tmp0_serialDesc +# 8| 11: [Constructor] Project +#-----| 4: (Parameters) +# 8| 0: [Parameter] name +# 8| 0: [TypeAccess] String +# 8| 1: [Parameter] language +# 8| 0: [TypeAccess] int +# 7| 5: [BlockStmt] { ... } +# 7| 0: [SuperConstructorInvocationStmt] super(...) +# 8| 1: [BlockStmt] { ... } +# 8| 0: [ExprStmt] ; +# 8| 0: [KtInitializerAssignExpr] ...=... +# 8| 0: [VarAccess] name +# 8| 1: [ExprStmt] ; +# 8| 0: [KtInitializerAssignExpr] ...=... +# 8| 0: [VarAccess] language +# 8| 12: [Method] getName +# 8| 3: [TypeAccess] String +# 8| 5: [BlockStmt] { ... } +# 8| 0: [ReturnStmt] return ... +# 8| 0: [VarAccess] this.name +# 8| -1: [ThisAccess] this +# 8| 12: [FieldDeclaration] String name; +# 8| -1: [TypeAccess] String +# 8| 0: [VarAccess] name +# 8| 14: [Method] getLanguage +# 8| 3: [TypeAccess] int +# 8| 5: [BlockStmt] { ... } +# 8| 0: [ReturnStmt] return ... +# 8| 0: [VarAccess] this.language +# 8| -1: [ThisAccess] this +# 8| 14: [FieldDeclaration] int language; +# 8| -1: [TypeAccess] int +# 8| 0: [VarAccess] language diff --git a/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/PrintAst.qlref b/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/PrintAst.qlref new file mode 100644 index 00000000000..c7fd5faf239 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/java/PrintAst.ql \ No newline at end of file diff --git a/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/app/build.gradle b/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/app/build.gradle new file mode 100644 index 00000000000..528b73cabc5 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/app/build.gradle @@ -0,0 +1,13 @@ +plugins { + id 'org.jetbrains.kotlin.jvm' version '1.6.10' + id 'org.jetbrains.kotlin.plugin.serialization' version '1.6.10' +} + +repositories { + mavenCentral() +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-serialization:1.6.10" + implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2" +} diff --git a/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/app/src/main/kotlin/testProject/App.kt b/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/app/src/main/kotlin/testProject/App.kt new file mode 100644 index 00000000000..373fc924c15 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/app/src/main/kotlin/testProject/App.kt @@ -0,0 +1,8 @@ +package testProject + +import kotlinx.serialization.* +import kotlinx.serialization.json.* +import kotlinx.serialization.Serializable + +@Serializable +data class Project(val name: String, val language: Int) \ No newline at end of file diff --git a/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/diagnostics.expected b/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/diagnostics.expected new file mode 100644 index 00000000000..751839721f7 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/diagnostics.expected @@ -0,0 +1 @@ +| CodeQL Kotlin extractor | 2 | | Unbound object value, trying to use class stub from descriptor | app/src/main/kotlin/testProject/App.kt:7:1:8:55 | app/src/main/kotlin/testProject/App.kt:7:1:8:55 | diff --git a/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/diagnostics.ql b/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/diagnostics.ql new file mode 100644 index 00000000000..031278ff260 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/diagnostics.ql @@ -0,0 +1,5 @@ +import java + +from string genBy, int severity, string tag, string msg, Location l +where diagnostics(_, genBy, severity, tag, msg, _, l) +select genBy, severity, tag, msg, l diff --git a/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/settings.gradle b/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/settings.gradle new file mode 100644 index 00000000000..a56fb7dd11c --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/settings.gradle @@ -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') diff --git a/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/test.py b/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/test.py new file mode 100644 index 00000000000..7f44398cd12 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/test.py @@ -0,0 +1,4 @@ +from create_database_utils import * + +run_codeql_database_create(["gradle build --no-daemon --no-build-cache"], lang="java") +runSuccessfully(["gradle", "clean"]) diff --git a/java/ql/integration-tests/posix-only/kotlin/java_kotlin_extraction_orders/test.expected b/java/ql/integration-tests/posix-only/kotlin/java_kotlin_extraction_orders/test.expected new file mode 100644 index 00000000000..fcee4129121 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/java_kotlin_extraction_orders/test.expected @@ -0,0 +1,24 @@ +| JavaSeesFirst/JarMtimesEqual/ClassFileMtimesEqual/seen_by_kotlin/dep.jar/Dep___JavaSeesFirst___JarMtimesEqual___ClassFileMtimesEqual.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___JarMtimesEqual___ClassFileMtimesEqual | +| JavaSeesFirst/JarMtimesEqual/JavaClassFileNewer/seen_by_kotlin/dep.jar/Dep___JavaSeesFirst___JarMtimesEqual___JavaClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___JarMtimesEqual___JavaClassFileNewer | +| JavaSeesFirst/JarMtimesEqual/KotlinClassFileNewer/seen_by_kotlin/dep.jar/Dep___JavaSeesFirst___JarMtimesEqual___KotlinClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___JarMtimesEqual___KotlinClassFileNewer | +| JavaSeesFirst/JavaJarNewer/ClassFileMtimesEqual/seen_by_kotlin/dep.jar/Dep___JavaSeesFirst___JavaJarNewer___ClassFileMtimesEqual.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___JavaJarNewer___ClassFileMtimesEqual | +| JavaSeesFirst/JavaJarNewer/JavaClassFileNewer/seen_by_kotlin/dep.jar/Dep___JavaSeesFirst___JavaJarNewer___JavaClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___JavaJarNewer___JavaClassFileNewer | +| JavaSeesFirst/JavaJarNewer/KotlinClassFileNewer/seen_by_kotlin/dep.jar/Dep___JavaSeesFirst___JavaJarNewer___KotlinClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___JavaJarNewer___KotlinClassFileNewer | +| JavaSeesFirst/KotlinJarNewer/ClassFileMtimesEqual/seen_by_kotlin/dep.jar/Dep___JavaSeesFirst___KotlinJarNewer___ClassFileMtimesEqual.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___KotlinJarNewer___ClassFileMtimesEqual | +| JavaSeesFirst/KotlinJarNewer/JavaClassFileNewer/seen_by_kotlin/dep.jar/Dep___JavaSeesFirst___KotlinJarNewer___JavaClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___KotlinJarNewer___JavaClassFileNewer | +| JavaSeesFirst/KotlinJarNewer/KotlinClassFileNewer/seen_by_kotlin/dep.jar/Dep___JavaSeesFirst___KotlinJarNewer___KotlinClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___KotlinJarNewer___KotlinClassFileNewer | +| JavaSeesFirst/NoJar/ClassFileMtimesEqual/seen_by_kotlin/Dep___JavaSeesFirst___NoJar___ClassFileMtimesEqual.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___NoJar___ClassFileMtimesEqual | +| JavaSeesFirst/NoJar/JavaClassFileNewer/seen_by_kotlin/Dep___JavaSeesFirst___NoJar___JavaClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___NoJar___JavaClassFileNewer | +| JavaSeesFirst/NoJar/KotlinClassFileNewer/seen_by_kotlin/Dep___JavaSeesFirst___NoJar___KotlinClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___JavaSeesFirst___NoJar___KotlinClassFileNewer | +| KotlinSeesFirst/JarMtimesEqual/ClassFileMtimesEqual/seen_by_kotlin/dep.jar/Dep___KotlinSeesFirst___JarMtimesEqual___ClassFileMtimesEqual.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___JarMtimesEqual___ClassFileMtimesEqual | +| KotlinSeesFirst/JarMtimesEqual/JavaClassFileNewer/seen_by_kotlin/dep.jar/Dep___KotlinSeesFirst___JarMtimesEqual___JavaClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___JarMtimesEqual___JavaClassFileNewer | +| KotlinSeesFirst/JarMtimesEqual/KotlinClassFileNewer/seen_by_kotlin/dep.jar/Dep___KotlinSeesFirst___JarMtimesEqual___KotlinClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___JarMtimesEqual___KotlinClassFileNewer | +| KotlinSeesFirst/JavaJarNewer/ClassFileMtimesEqual/seen_by_kotlin/dep.jar/Dep___KotlinSeesFirst___JavaJarNewer___ClassFileMtimesEqual.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___JavaJarNewer___ClassFileMtimesEqual | +| KotlinSeesFirst/JavaJarNewer/JavaClassFileNewer/seen_by_kotlin/dep.jar/Dep___KotlinSeesFirst___JavaJarNewer___JavaClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___JavaJarNewer___JavaClassFileNewer | +| KotlinSeesFirst/JavaJarNewer/KotlinClassFileNewer/seen_by_kotlin/dep.jar/Dep___KotlinSeesFirst___JavaJarNewer___KotlinClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___JavaJarNewer___KotlinClassFileNewer | +| KotlinSeesFirst/KotlinJarNewer/ClassFileMtimesEqual/seen_by_kotlin/dep.jar/Dep___KotlinSeesFirst___KotlinJarNewer___ClassFileMtimesEqual.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___KotlinJarNewer___ClassFileMtimesEqual | +| KotlinSeesFirst/KotlinJarNewer/JavaClassFileNewer/seen_by_kotlin/dep.jar/Dep___KotlinSeesFirst___KotlinJarNewer___JavaClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___KotlinJarNewer___JavaClassFileNewer | +| KotlinSeesFirst/KotlinJarNewer/KotlinClassFileNewer/seen_by_kotlin/dep.jar/Dep___KotlinSeesFirst___KotlinJarNewer___KotlinClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___KotlinJarNewer___KotlinClassFileNewer | +| KotlinSeesFirst/NoJar/ClassFileMtimesEqual/seen_by_kotlin/Dep___KotlinSeesFirst___NoJar___ClassFileMtimesEqual.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___NoJar___ClassFileMtimesEqual | +| KotlinSeesFirst/NoJar/JavaClassFileNewer/seen_by_kotlin/Dep___KotlinSeesFirst___NoJar___JavaClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___NoJar___JavaClassFileNewer | +| KotlinSeesFirst/NoJar/KotlinClassFileNewer/seen_by_kotlin/Dep___KotlinSeesFirst___NoJar___KotlinClassFileNewer.class:0:0:0:0 | memberOnlySeenByKotlin | Dep___KotlinSeesFirst___NoJar___KotlinClassFileNewer | diff --git a/java/ql/integration-tests/posix-only/kotlin/java_kotlin_extraction_orders/test.py b/java/ql/integration-tests/posix-only/kotlin/java_kotlin_extraction_orders/test.py new file mode 100644 index 00000000000..476db9203d5 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/java_kotlin_extraction_orders/test.py @@ -0,0 +1,128 @@ +from create_database_utils import * +import os +import os.path +import subprocess + +# Build a family of dependencies outside tracing, then refer to them from a traced build: + +older_datetime = "202201010101" +newer_datetime = "202202020202" + +classpath_entries = dict() + +extraction_orders = ["JavaSeesFirst", "KotlinSeesFirst"] +jar_states = ["NoJar", "JarMtimesEqual", "JavaJarNewer", "KotlinJarNewer"] +class_file_states = ["ClassFileMtimesEqual", "JavaClassFileNewer", "KotlinClassFileNewer"] + +# Create test classes for each combination of which extractor will see the file first, the relative timestamps of the jar files seen by each, and the relative timestamps of the class file inside: + +jobs = [] + +for first_extraction in extraction_orders: + for jar_state in jar_states: + for class_file_state in class_file_states: + dep_dir = os.path.join(first_extraction, jar_state, class_file_state) + dep_classname = "Dep___%s___%s___%s" % (first_extraction, jar_state, class_file_state) + dep_seen_by_java_dir = os.path.join(dep_dir, "seen_by_java") + dep_seen_by_kotlin_dir = os.path.join(dep_dir, "seen_by_kotlin") + os.makedirs(dep_seen_by_java_dir) + os.makedirs(dep_seen_by_kotlin_dir) + dep_seen_by_java_sourcefile = os.path.join(dep_seen_by_java_dir, dep_classname + ".java") + dep_seen_by_kotlin_sourcefile = os.path.join(dep_seen_by_kotlin_dir, dep_classname + ".java") + with open(dep_seen_by_java_sourcefile, "w") as f: + f.write("public class %s { }" % dep_classname) + with open(dep_seen_by_kotlin_sourcefile, "w") as f: + f.write("public class %s { void memberOnlySeenByKotlin() { } }" % dep_classname) + jobs.append({ + "first_extraction": first_extraction, + "jar_state": jar_state, + "class_file_state": class_file_state, + "dep_dir": dep_dir, + "dep_classname": dep_classname, + "dep_seen_by_java_dir": dep_seen_by_java_dir, + "dep_seen_by_kotlin_dir": dep_seen_by_kotlin_dir, + "dep_seen_by_java_sourcefile": dep_seen_by_java_sourcefile, + "dep_seen_by_kotlin_sourcefile": dep_seen_by_kotlin_sourcefile + }) + +# Compile all the test classes we just generated, in two commands (since javac objects to seeing the same class file twice in one run) + +subprocess.check_call(["javac"] + [j["dep_seen_by_java_sourcefile"] for j in jobs]) +subprocess.check_call(["javac"] + [j["dep_seen_by_kotlin_sourcefile"] for j in jobs]) + +# Create jar files and set class and jar files' relative timestamps for each dependency the two extractors will see: + +for j in jobs: + os.remove(j["dep_seen_by_java_sourcefile"]) + os.remove(j["dep_seen_by_kotlin_sourcefile"]) + dep_seen_by_java_classfile = j["dep_seen_by_java_sourcefile"].replace(".java", ".class") + dep_seen_by_kotlin_classfile = j["dep_seen_by_kotlin_sourcefile"].replace(".java", ".class") + + subprocess.check_call(["touch", "-t", newer_datetime if j["class_file_state"] == "JavaClassFileNewer" else older_datetime, dep_seen_by_java_classfile]) + subprocess.check_call(["touch", "-t", newer_datetime if j["class_file_state"] == "KotlinClassFileNewer" else older_datetime, dep_seen_by_kotlin_classfile]) + + if j["jar_state"] != "NoJar": + classfile_name = os.path.basename(dep_seen_by_java_classfile) + jar_command = ["jar", "cf", "dep.jar", classfile_name] + subprocess.check_call(jar_command, cwd = j["dep_seen_by_java_dir"]) + subprocess.check_call(jar_command, cwd = j["dep_seen_by_kotlin_dir"]) + jar_seen_by_java = os.path.join(j["dep_seen_by_java_dir"], "dep.jar") + jar_seen_by_kotlin = os.path.join(j["dep_seen_by_kotlin_dir"], "dep.jar") + subprocess.check_call(["touch", "-t", newer_datetime if j["jar_state"] == "JavaJarNewer" else older_datetime, jar_seen_by_java]) + subprocess.check_call(["touch", "-t", newer_datetime if j["jar_state"] == "KotlinJarNewer" else older_datetime, jar_seen_by_kotlin]) + j["javac_classpath_entry"] = jar_seen_by_java + j["kotlinc_classpath_entry"] = jar_seen_by_kotlin + else: + # No jar file involved, just add the dependency build directory to the classpath: + j["javac_classpath_entry"] = j["dep_seen_by_java_dir"] + j["kotlinc_classpath_entry"] = j["dep_seen_by_kotlin_dir"] + +# Create source files that instantiate each dependency type: + +kotlin_first_jobs = [j for j in jobs if j["first_extraction"] == "KotlinSeesFirst"] +java_first_jobs = [j for j in jobs if j["first_extraction"] == "JavaSeesFirst"] +kotlin_first_classes = [j["dep_classname"] for j in kotlin_first_jobs] +java_first_classes = [j["dep_classname"] for j in java_first_jobs] + +kotlin_first_user = "kotlinFirstUser.kt" +kotlin_second_user = "kotlinSecondUser.kt" +java_first_user = "JavaFirstUser.java" +java_second_user = "JavaSecondUser.java" + +def kotlin_instantiate_classes(classes): + return "; ".join(["noop(%s())" % c for c in classes]) + +def make_kotlin_user(user_filename, classes): + with open(user_filename, "w") as f: + f.write("fun noop(x: Any) { } fun user() { %s }" % kotlin_instantiate_classes(classes)) + +make_kotlin_user(kotlin_first_user, kotlin_first_classes) +make_kotlin_user(kotlin_second_user, java_first_classes) + +def java_instantiate_classes(classes): + return " ".join(["noop(new %s());" % c for c in classes]) + +def make_java_user(user_filename, classes): + with open(user_filename, "w") as f: + f.write("public class %s { private static void noop(Object x) { } public static void user() { %s } }" % (user_filename.replace(".java", ""), java_instantiate_classes(classes))) + +make_java_user(java_first_user, java_first_classes) +make_java_user(java_second_user, kotlin_first_classes) + +# Now finally make a database, including classes where Java sees them first followed by Kotlin and vice versa. +# In all cases the Kotlin extraction should take precedence. + +def make_classpath(jobs, entry_name): + return ":".join([j[entry_name] for j in jobs]) + +kotlin_first_classpath = make_classpath(kotlin_first_jobs, "kotlinc_classpath_entry") +java_first_classpath = make_classpath(java_first_jobs, "javac_classpath_entry") +kotlin_second_classpath = make_classpath(java_first_jobs, "kotlinc_classpath_entry") +java_second_classpath = make_classpath(kotlin_first_jobs, "javac_classpath_entry") + +run_codeql_database_create([ + "kotlinc -cp %s %s" % (kotlin_first_classpath, kotlin_first_user), + "javac -cp %s %s" % (java_first_classpath, java_first_user), + "kotlinc -cp %s %s" % (kotlin_second_classpath, kotlin_second_user), + "javac -cp %s %s" % (java_second_classpath, java_second_user) +], lang="java") diff --git a/java/ql/integration-tests/posix-only/kotlin/java_kotlin_extraction_orders/test.ql b/java/ql/integration-tests/posix-only/kotlin/java_kotlin_extraction_orders/test.ql new file mode 100644 index 00000000000..637735f68ea --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/java_kotlin_extraction_orders/test.ql @@ -0,0 +1,5 @@ +import java + +from Method m +where m.getName() = "memberOnlySeenByKotlin" +select m, m.getDeclaringType().getName() diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_compiler_java_source/J.java b/java/ql/integration-tests/posix-only/kotlin/kotlin_compiler_java_source/J.java new file mode 100644 index 00000000000..d1cc30d651d --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_compiler_java_source/J.java @@ -0,0 +1 @@ +public class J { } diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_compiler_java_source/K.kt b/java/ql/integration-tests/posix-only/kotlin/kotlin_compiler_java_source/K.kt new file mode 100644 index 00000000000..d07b8bd8d03 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_compiler_java_source/K.kt @@ -0,0 +1 @@ +fun user1(j: J) { } diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_compiler_java_source/K2.kt b/java/ql/integration-tests/posix-only/kotlin/kotlin_compiler_java_source/K2.kt new file mode 100644 index 00000000000..f01cd4d1304 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_compiler_java_source/K2.kt @@ -0,0 +1 @@ +fun user2(j: J) { } diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_compiler_java_source/jlocs.expected b/java/ql/integration-tests/posix-only/kotlin/kotlin_compiler_java_source/jlocs.expected new file mode 100644 index 00000000000..5be9218762e --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_compiler_java_source/jlocs.expected @@ -0,0 +1,3 @@ +| J.java:1:14:1:14 | J | +| build/J.class:0:0:0:0 | J | +| file:///!unknown-binary-location/J.class:0:0:0:0 | J | diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_compiler_java_source/jlocs.ql b/java/ql/integration-tests/posix-only/kotlin/kotlin_compiler_java_source/jlocs.ql new file mode 100644 index 00000000000..d0d4beee9f9 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_compiler_java_source/jlocs.ql @@ -0,0 +1,5 @@ +import java + +from Class c +where c.getSourceDeclaration().getName() = "J" +select c diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_compiler_java_source/test.py b/java/ql/integration-tests/posix-only/kotlin/kotlin_compiler_java_source/test.py new file mode 100644 index 00000000000..2b44384c1dc --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_compiler_java_source/test.py @@ -0,0 +1,8 @@ +from create_database_utils import * + +os.mkdir('build') +# Steps: +# 1. Compile Kotlin passing Java source code. J.class is extracted with an unknown binary location +# 2. Compile Java producing a class file. J.class should be re-extracted this time with a known binary location +# 3. Compile a Kotlin user passing a Java class file on the classpath. Should reference the class file location that step 1 didn't know, but step 2 did. +run_codeql_database_create(["kotlinc J.java K.kt -d build", "javac J.java -d build", "kotlinc K2.kt -cp build -d build"], lang="java") diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_file_import/libsrc/longsig.kt b/java/ql/integration-tests/posix-only/kotlin/kotlin_file_import/libsrc/longsig.kt new file mode 100644 index 00000000000..25dda426865 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_file_import/libsrc/longsig.kt @@ -0,0 +1,7 @@ +package abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij; + +class Param { + +} + +fun f(p1: Param, p2: Param, p3: Param, p4: Param, p5: Param) { } diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_file_import/test.expected b/java/ql/integration-tests/posix-only/kotlin/kotlin_file_import/test.expected new file mode 100644 index 00000000000..d99bf44e5fb --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_file_import/test.expected @@ -0,0 +1 @@ +| /abcdefghij/abcdefghij/abcdefghij/abcdefghij/abcdefghij/abcdefghij/abcdefghij/abcdefghij/abcdefghij/abcdefghij/LongsigKt.class:0:0:0:0 | f | diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_file_import/test.py b/java/ql/integration-tests/posix-only/kotlin/kotlin_file_import/test.py new file mode 100644 index 00000000000..a5987b0c08f --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_file_import/test.py @@ -0,0 +1,11 @@ +from create_database_utils import * +import glob + +# Compile library Kotlin file untraced. Note the library is hidden under `libsrc` so the Kotlin compiler +# will certainly reference the jar, not the source or class file. + +os.mkdir('build') +runSuccessfully(["kotlinc"] + glob.glob("libsrc/*.kt") + ["-d", "build"]) +runSuccessfully(["jar", "cf", "extlib.jar", "-C", "build", "abcdefghij", "-C", "build", "META-INF"]) +run_codeql_database_create(["kotlinc user.kt -cp extlib.jar"], lang="java") + diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_file_import/test.ql b/java/ql/integration-tests/posix-only/kotlin/kotlin_file_import/test.ql new file mode 100644 index 00000000000..f514be114a7 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_file_import/test.ql @@ -0,0 +1,7 @@ +import java + +from Method m +where m.getDeclaringType().getName() = "LongsigKt" +select m.getLocation() + .toString() + .regexpReplaceAll(".*(extlib.jar|!unknown-binary-location)/", "/"), m.toString() diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_file_import/user.kt b/java/ql/integration-tests/posix-only/kotlin/kotlin_file_import/user.kt new file mode 100644 index 00000000000..8c60c53fc03 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_file_import/user.kt @@ -0,0 +1,7 @@ +import abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.* + +fun user() { + + f(Param(), Param(), Param(), Param(), Param()) + +} diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/JavaDefns.java b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/JavaDefns.java new file mode 100644 index 00000000000..c8e4daaa5f0 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/JavaDefns.java @@ -0,0 +1,18 @@ +public class JavaDefns { + + // Currently known not to work: the Comparable case, which Kotlin sees as Comparable<*> because the + // wildcard goes the opposite direction to the variance declared on Comparable's type parameter. + + public static void takesComparable(Comparable invar, Comparable contravar) { } + + public static void takesNestedComparable(Comparable> innerContravar, Comparable> outerContravar) { } + + public static void takesArrayOfComparable(Comparable[] invar, Comparable[] contravar) { } + + public static Comparable returnsWildcard() { return null; } + + public static Comparable returnsInvariant() { return null; } + + public JavaDefns(Comparable invar, Comparable contravar) { } + +} diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/JavaUser.java b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/JavaUser.java new file mode 100644 index 00000000000..cbc0544e9fe --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/JavaUser.java @@ -0,0 +1,54 @@ +import java.util.List; + +public class JavaUser { + + public static void test() { + + KotlinDefns kd = new KotlinDefns(); + + kd.takesInvariantType((List)null, (List)null, (List)null); + + kd.takesCovariantType((List)null, (List)null); + + kd.takesContravariantType((Comparable)null, (Comparable)null); + + kd.takesNestedType((List>) null, (List>)null, (Comparable>)null, (List>)null, (Comparable>)null); + + kd.takesFinalParameter((List)null, (List)null, (Comparable)null); + + kd.takesFinalParameterForceWildcard((List)null, (List)null, (Comparable)null); + + kd.takesAnyParameter((List)null, (List)null, (Comparable)null); + + kd.takesAnyQParameter((List)null, (List)null, (Comparable)null); + + kd.takesAnyParameterForceWildcard((List)null, (List)null, (Comparable)null); + + kd.takesVariantTypesSuppressedWildcards((List)null, (Comparable)null); + + List r1 = kd.returnsInvar(); + + List r2 = kd.returnsCovar(); + + Comparable r3 = kd.returnsContravar(); + + List r4 = kd.returnsCovarForced(); + + Comparable r5 = kd.returnsContravarForced(); + + KotlinDefnsSuppressedOuter kdso = new KotlinDefnsSuppressedOuter(); + kdso.outerFn((List)null, (Comparable)null); + KotlinDefnsSuppressedOuter.Inner kdsoi = new KotlinDefnsSuppressedOuter.Inner(); + kdsoi.innerFn((List)null, (Comparable)null); + + KotlinDefnsSuppressedInner kdsi = new KotlinDefnsSuppressedInner(); + kdsi.outerFn((List)null, (Comparable)null); + KotlinDefnsSuppressedInner.Inner kdsii = new KotlinDefnsSuppressedInner.Inner(); + kdsii.innerFn((List)null, (Comparable)null); + + KotlinDefnsSuppressedFn kdsf = new KotlinDefnsSuppressedFn(); + kdsf.outerFn((List)null, (Comparable)null); + + } + +} \ No newline at end of file diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/kotlindefns.kt b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/kotlindefns.kt new file mode 100644 index 00000000000..671c1ae0ecc --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/kotlindefns.kt @@ -0,0 +1,78 @@ +// Note throughout, using: +// MutableList as a type whose parameter is invariant +// List as a type whose parameter is covariant (List) +// Comparable as a type whose parameter is contravariant (Comparable) +// CharSequence as a non-final type +// String as a final type + +class ComparableCs : Comparable { + override fun compareTo(other: CharSequence): Int = 1 +} + +class KotlinDefns { + + fun takesInvariantType(noUseSiteVariance: MutableList, useSiteCovariant: MutableList, useSiteContravariant: MutableList) { } + + // Note List is a static error (contradictory variance) + fun takesCovariantType(noUseSiteVariance: List, useSiteCovariant: List) { } + + // Note Comparable is a static error (contradictory variance) + fun takesContravariantType(noUseSiteVariance: Comparable, useSiteContravariant: Comparable) { } + + fun takesNestedType(invar: MutableList>, covar: List>, contravar: Comparable>, mixed1: List>, mixed2: Comparable>) { } + + fun takesFinalParameter(invar: MutableList, covar: List, contravar: Comparable) { } + + fun takesFinalParameterForceWildcard(invar: MutableList<@JvmWildcard String>, covar: List<@JvmWildcard String>, contravar: Comparable<@JvmWildcard String>) { } + + fun takesAnyParameter(invar: MutableList, covar: List, contravar: Comparable) { } + + fun takesAnyQParameter(invar: MutableList, covar: List, contravar: Comparable) { } + + fun takesAnyParameterForceWildcard(invar: MutableList<@JvmWildcard Any>, covar: List<@JvmWildcard Any>, contravar: Comparable<@JvmWildcard Any>) { } + + fun takesVariantTypesSuppressedWildcards(covar: List<@JvmSuppressWildcards CharSequence>, contravar: Comparable<@JvmSuppressWildcards CharSequence>) { } + + fun returnsInvar() : MutableList = mutableListOf() + + fun returnsCovar(): List = listOf() + + fun returnsContravar(): Comparable = ComparableCs() + + fun returnsCovarForced(): List<@JvmWildcard CharSequence> = listOf() + + fun returnsContravarForced(): Comparable<@JvmWildcard CharSequence> = ComparableCs() + +} + +@JvmSuppressWildcards +class KotlinDefnsSuppressedOuter { + + fun outerFn(covar: List, contravar: Comparable) { } + + class Inner { + + fun innerFn(covar: List, contravar: Comparable) { } + + } + +} + +class KotlinDefnsSuppressedInner { + + fun outerFn(covar: List, contravar: Comparable) { } + + @JvmSuppressWildcards + class Inner { + + fun innerFn(covar: List, contravar: Comparable) { } + + } + +} + +class KotlinDefnsSuppressedFn { + + @JvmSuppressWildcards fun outerFn(covar: List, contravar: Comparable) { } + +} \ No newline at end of file diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/kotlinuser.kt b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/kotlinuser.kt new file mode 100644 index 00000000000..535b03b902f --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/kotlinuser.kt @@ -0,0 +1,10 @@ + +fun user() { + val cs = ComparableCs() + val acs = arrayOf(cs) + + JavaDefns.takesComparable(cs, cs) + JavaDefns.takesArrayOfComparable(acs, acs) + + val constructed = JavaDefns(cs, cs) +} diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/test.expected b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/test.expected new file mode 100644 index 00000000000..a0c58e6b492 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/test.expected @@ -0,0 +1,54 @@ +| JavaDefns | JavaDefns | contravar | Comparable | +| JavaDefns | JavaDefns | invar | Comparable | +| JavaDefns | returnsInvariant | return | Comparable | +| JavaDefns | returnsWildcard | return | Comparable | +| JavaDefns | takesArrayOfComparable | contravar | Comparable[] | +| JavaDefns | takesArrayOfComparable | invar | Comparable[] | +| JavaDefns | takesComparable | contravar | Comparable | +| JavaDefns | takesComparable | invar | Comparable | +| JavaDefns | takesNestedComparable | innerContravar | Comparable> | +| JavaDefns | takesNestedComparable | outerContravar | Comparable> | +| KotlinDefns | returnsContravar | return | Comparable | +| KotlinDefns | returnsContravarForced | return | Comparable | +| KotlinDefns | returnsCovar | return | List | +| KotlinDefns | returnsCovarForced | return | List | +| KotlinDefns | returnsInvar | return | List | +| KotlinDefns | takesAnyParameter | contravar | Comparable | +| KotlinDefns | takesAnyParameter | covar | List | +| KotlinDefns | takesAnyParameter | invar | List | +| KotlinDefns | takesAnyParameterForceWildcard | contravar | Comparable | +| KotlinDefns | takesAnyParameterForceWildcard | covar | List | +| KotlinDefns | takesAnyParameterForceWildcard | invar | List | +| KotlinDefns | takesAnyQParameter | contravar | Comparable | +| KotlinDefns | takesAnyQParameter | covar | List | +| KotlinDefns | takesAnyQParameter | invar | List | +| KotlinDefns | takesContravariantType | noUseSiteVariance | Comparable | +| KotlinDefns | takesContravariantType | useSiteContravariant | Comparable | +| KotlinDefns | takesCovariantType | noUseSiteVariance | List | +| KotlinDefns | takesCovariantType | useSiteCovariant | List | +| KotlinDefns | takesFinalParameter | contravar | Comparable | +| KotlinDefns | takesFinalParameter | covar | List | +| KotlinDefns | takesFinalParameter | invar | List | +| KotlinDefns | takesFinalParameterForceWildcard | contravar | Comparable | +| KotlinDefns | takesFinalParameterForceWildcard | covar | List | +| KotlinDefns | takesFinalParameterForceWildcard | invar | List | +| KotlinDefns | takesInvariantType | noUseSiteVariance | List | +| KotlinDefns | takesInvariantType | useSiteContravariant | List | +| KotlinDefns | takesInvariantType | useSiteCovariant | List | +| KotlinDefns | takesNestedType | contravar | Comparable> | +| KotlinDefns | takesNestedType | covar | List> | +| KotlinDefns | takesNestedType | invar | List> | +| KotlinDefns | takesNestedType | mixed1 | List> | +| KotlinDefns | takesNestedType | mixed2 | Comparable> | +| KotlinDefns | takesVariantTypesSuppressedWildcards | contravar | Comparable | +| KotlinDefns | takesVariantTypesSuppressedWildcards | covar | List | +| KotlinDefnsSuppressedFn | outerFn | contravar | Comparable | +| KotlinDefnsSuppressedFn | outerFn | covar | List | +| KotlinDefnsSuppressedInner | outerFn | contravar | Comparable | +| KotlinDefnsSuppressedInner | outerFn | covar | List | +| KotlinDefnsSuppressedInner$Inner | innerFn | contravar | Comparable | +| KotlinDefnsSuppressedInner$Inner | innerFn | covar | List | +| KotlinDefnsSuppressedOuter | outerFn | contravar | Comparable | +| KotlinDefnsSuppressedOuter | outerFn | covar | List | +| KotlinDefnsSuppressedOuter$Inner | innerFn | contravar | Comparable | +| KotlinDefnsSuppressedOuter$Inner | innerFn | covar | List | diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/test.py b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/test.py new file mode 100644 index 00000000000..76e58dc728b --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/test.py @@ -0,0 +1,3 @@ +from create_database_utils import * + +run_codeql_database_create(["kotlinc kotlindefns.kt", "javac JavaUser.java JavaDefns.java -cp .", "kotlinc -cp . kotlinuser.kt"], lang="java") diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/test.ql b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/test.ql new file mode 100644 index 00000000000..36dd57871b7 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_lowering_wildcards/test.ql @@ -0,0 +1,22 @@ +import java + +predicate isInterestingClass(Class c) { + [c, c.(NestedType).getEnclosingType()].getName().matches(["KotlinDefns%", "JavaDefns"]) +} + +from Callable c, string paramOrReturnName, Type paramOrReturnType +where + isInterestingClass(c.getDeclaringType()) and + ( + exists(Parameter p | + p = c.getAParameter() and + paramOrReturnName = p.getName() and + paramOrReturnType = p.getType() + ) + or + paramOrReturnName = "return" and + paramOrReturnType = c.getReturnType() and + not paramOrReturnType instanceof VoidType + ) +select c.getDeclaringType().getQualifiedName(), c.getName(), paramOrReturnName, + paramOrReturnType.toString() diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_java_static_fields/ReadsFields.java b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_static_fields/ReadsFields.java new file mode 100644 index 00000000000..02bf6ff5255 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_static_fields/ReadsFields.java @@ -0,0 +1,13 @@ +public class ReadsFields { + + public static void read() { + + sink(HasFields.constField); + sink(HasFields.lateinitField); + sink(HasFields.jvmFieldAnnotatedField); + + } + + public static void sink(String x) { } + +} diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_java_static_fields/hasFields.kt b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_static_fields/hasFields.kt new file mode 100644 index 00000000000..a7fde8fa33b --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_static_fields/hasFields.kt @@ -0,0 +1,17 @@ +public class HasFields { + + companion object { + + const val constField = "taint" + + lateinit var lateinitField: String + + @JvmField val jvmFieldAnnotatedField = "taint" + + } + + fun doLateInit() { + lateinitField = "taint" + } + +} diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_java_static_fields/test.expected b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_static_fields/test.expected new file mode 100644 index 00000000000..3581a178422 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_static_fields/test.expected @@ -0,0 +1,26 @@ +edges +| hasFields.kt:5:5:5:34 | constField : String | ReadsFields.java:5:10:5:29 | HasFields.constField | +| hasFields.kt:5:28:5:34 | taint : String | hasFields.kt:5:5:5:34 | constField : String | +| hasFields.kt:7:5:7:38 | lateinitField : String | ReadsFields.java:6:10:6:32 | HasFields.lateinitField | +| hasFields.kt:7:14:7:38 | : String | hasFields.kt:7:5:7:38 | lateinitField : String | +| hasFields.kt:7:14:7:38 | : String | hasFields.kt:7:14:7:38 | : String | +| hasFields.kt:9:5:9:50 | jvmFieldAnnotatedField : String | ReadsFields.java:7:10:7:41 | HasFields.jvmFieldAnnotatedField | +| hasFields.kt:9:44:9:50 | taint : String | hasFields.kt:9:5:9:50 | jvmFieldAnnotatedField : String | +| hasFields.kt:14:22:14:26 | taint : String | hasFields.kt:7:14:7:38 | : String | +nodes +| ReadsFields.java:5:10:5:29 | HasFields.constField | semmle.label | HasFields.constField | +| ReadsFields.java:6:10:6:32 | HasFields.lateinitField | semmle.label | HasFields.lateinitField | +| ReadsFields.java:7:10:7:41 | HasFields.jvmFieldAnnotatedField | semmle.label | HasFields.jvmFieldAnnotatedField | +| hasFields.kt:5:5:5:34 | constField : String | semmle.label | constField : String | +| hasFields.kt:5:28:5:34 | taint : String | semmle.label | taint : String | +| hasFields.kt:7:5:7:38 | lateinitField : String | semmle.label | lateinitField : String | +| hasFields.kt:7:14:7:38 | : String | semmle.label | : String | +| hasFields.kt:7:14:7:38 | : String | semmle.label | : String | +| hasFields.kt:9:5:9:50 | jvmFieldAnnotatedField : String | semmle.label | jvmFieldAnnotatedField : String | +| hasFields.kt:9:44:9:50 | taint : String | semmle.label | taint : String | +| hasFields.kt:14:22:14:26 | taint : String | semmle.label | taint : String | +subpaths +#select +| hasFields.kt:5:28:5:34 | taint : String | hasFields.kt:5:28:5:34 | taint : String | ReadsFields.java:5:10:5:29 | HasFields.constField | flow path | +| hasFields.kt:9:44:9:50 | taint : String | hasFields.kt:9:44:9:50 | taint : String | ReadsFields.java:7:10:7:41 | HasFields.jvmFieldAnnotatedField | flow path | +| hasFields.kt:14:22:14:26 | taint : String | hasFields.kt:14:22:14:26 | taint : String | ReadsFields.java:6:10:6:32 | HasFields.lateinitField | flow path | diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_java_static_fields/test.py b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_static_fields/test.py new file mode 100644 index 00000000000..07bf397a81e --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_static_fields/test.py @@ -0,0 +1,4 @@ +from create_database_utils import * + +os.mkdir('build') +run_codeql_database_create(["kotlinc ReadsFields.java hasFields.kt -d kbuild", "javac ReadsFields.java -cp kbuild"], lang="java") diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_java_static_fields/test.ql b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_static_fields/test.ql new file mode 100644 index 00000000000..f7702b2ac38 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_java_static_fields/test.ql @@ -0,0 +1,17 @@ +import java +import semmle.code.java.dataflow.DataFlow +import DataFlow::PathGraph + +class Config extends DataFlow::Configuration { + Config() { this = "Config" } + + override predicate isSource(DataFlow::Node n) { n.asExpr().(StringLiteral).getValue() = "taint" } + + override predicate isSink(DataFlow::Node n) { + n.asExpr().(Argument).getCall().getCallee().getName() = "sink" + } +} + +from DataFlow::PathNode source, DataFlow::PathNode sink, Config c +where c.hasFlowPath(source, sink) +select source, source, sink, "flow path" diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/FileA.kt b/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/FileA.kt new file mode 100644 index 00000000000..1b471fcea51 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/FileA.kt @@ -0,0 +1,9 @@ +package foo.bar; + +// import foo.bar.ClassB; + +class ClassA { + fun f(b: ClassB) { + b.called(); + } +} diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/FileB.kt b/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/FileB.kt new file mode 100644 index 00000000000..43f5f870d52 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/FileB.kt @@ -0,0 +1,8 @@ +package foo.bar; + +class ClassB { + fun called() { + } + fun notCalled() { + } +} diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/build.py b/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/build.py new file mode 100644 index 00000000000..09d42100362 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/build.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +from create_database_utils import * + +runSuccessfully(["kotlinc", "FileA.kt", "FileB.kt"]) + diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/compilations.expected b/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/compilations.expected new file mode 100644 index 00000000000..2a4f078a25f --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/compilations.expected @@ -0,0 +1 @@ +| 1 | diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/compilations.ql b/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/compilations.ql new file mode 100644 index 00000000000..7ddd497d555 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/compilations.ql @@ -0,0 +1,3 @@ +import java + +select count(Compilation c) diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/methods.expected b/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/methods.expected new file mode 100644 index 00000000000..873b5d7debc --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/methods.expected @@ -0,0 +1,3 @@ +| FileA.kt:6:2:8:2 | f | +| FileB.kt:4:2:5:2 | called | +| FileB.kt:6:2:7:2 | notCalled | diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/methods.ql b/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/methods.ql new file mode 100644 index 00000000000..9d32c93e69c --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/methods.ql @@ -0,0 +1,5 @@ +import java + +from Method m +where exists(m.getFile().getRelativePath()) +select m diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/test.py b/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/test.py new file mode 100644 index 00000000000..074931bbe89 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlinc_multi/test.py @@ -0,0 +1,3 @@ +from create_database_utils import * + +run_codeql_database_create(['"%s" ./build.py' % sys.executable], lang="java") diff --git a/java/ql/integration-tests/posix-only/kotlin/logs/build.py b/java/ql/integration-tests/posix-only/kotlin/logs/build.py new file mode 100644 index 00000000000..eedddd8ba5c --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/logs/build.py @@ -0,0 +1,18 @@ +#!/usr/bin/python + +from create_database_utils import * + +# Make a source file to keep codeql happy +srcDir = os.environ['CODEQL_EXTRACTOR_JAVA_SOURCE_ARCHIVE_DIR'] +srcFile = srcDir + '/Source.java' +os.makedirs(srcDir) +with open(srcFile, 'w') as f: + pass + +for t in ['Test1', 'sun.something.Test2']: + print('Test ' + t + ' started.') + sys.stdout.flush() + runSuccessfully(['java', t]) + print('Test ' + t + ' ended.') + sys.stdout.flush() + diff --git a/java/ql/integration-tests/posix-only/kotlin/logs/index_logs.py b/java/ql/integration-tests/posix-only/kotlin/logs/index_logs.py new file mode 100644 index 00000000000..c7b94ad024d --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/logs/index_logs.py @@ -0,0 +1,41 @@ +#!/usr/bin/python + +import csv +import json +import re +import sys +from create_database_utils import * + +# Make a source file to keep codeql happy +src_dir = os.environ['CODEQL_EXTRACTOR_JAVA_SOURCE_ARCHIVE_DIR'] +src_file = src_dir + '/Source.java' +os.makedirs(src_dir) +with open(src_file, 'w') as f: + pass + +line_index = 0 +file_index = 0 +with open('logs.csv', 'w', newline='') as f_out: + csv_writer = csv.writer(f_out) + def write_line(origin, kind, msg): + global file_index, line_index + csv_writer.writerow([str(file_index), str(line_index), origin, kind, msg]) + line_index += 1 + log_dir = 'kt-db/log' + for file_name in os.listdir(log_dir): + if file_name.startswith('kotlin-extractor'): + file_index += 1 + line_index = 1 + write_line('Test script', 'Log file', str(file_index)) + with open(log_dir + '/' + file_name) as f_in: + for line in f_in: + j = json.loads(line) + msg = j['message'] + msg = re.sub('(?<=Extraction for invocation TRAP file ).*/kt-db/trap/java/invocations/kotlin\..*\.trap', '', msg) + if msg.startswith('Peak memory: '): + # Peak memory information varies from run to run, so just ignore it + continue + write_line(j['origin'], j['kind'], msg) + +runSuccessfully(["codeql", "database", "index-files", "--language=csv", "--include=logs.csv", "test-db"]) + diff --git a/java/ql/integration-tests/posix-only/kotlin/logs/logs.expected b/java/ql/integration-tests/posix-only/kotlin/logs/logs.expected new file mode 100644 index 00000000000..9c5116e850f --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/logs/logs.expected @@ -0,0 +1,5 @@ +| 1 | 1 | Test script | Log file | 1 | +| 1 | 2 | CodeQL Kotlin extractor | INFO | Extraction started | +| 1 | 3 | CodeQL Kotlin extractor | INFO | Extraction for invocation TRAP file | +| 1 | 4 | CodeQL Kotlin extractor | INFO | Extracting file test.kt | +| 1 | 5 | CodeQL Kotlin extractor | INFO | Extraction completed | diff --git a/java/ql/integration-tests/posix-only/kotlin/logs/logs.ql b/java/ql/integration-tests/posix-only/kotlin/logs/logs.ql new file mode 100644 index 00000000000..5a3d30fc5b2 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/logs/logs.ql @@ -0,0 +1,5 @@ +import external.ExternalArtifact + +from ExternalData ed +where ed.getDataPath().matches("%logs.csv") +select ed.getFieldAsInt(0), ed.getFieldAsInt(1), ed.getField(2), ed.getField(3), ed.getField(4) diff --git a/java/ql/integration-tests/posix-only/kotlin/logs/test.kt b/java/ql/integration-tests/posix-only/kotlin/logs/test.kt new file mode 100644 index 00000000000..2fc18b1217a --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/logs/test.kt @@ -0,0 +1,2 @@ +class Test { +} diff --git a/java/ql/integration-tests/posix-only/kotlin/logs/test.py b/java/ql/integration-tests/posix-only/kotlin/logs/test.py new file mode 100644 index 00000000000..6203650ac3f --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/logs/test.py @@ -0,0 +1,4 @@ +from create_database_utils import * + +run_codeql_database_create(['kotlinc test.kt'], test_db="kt-db", db=None, lang="java") +run_codeql_database_create(['"%s" ./index_logs.py' % sys.executable], lang="java") diff --git a/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/JavaUser.java b/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/JavaUser.java new file mode 100644 index 00000000000..3c79f5828c8 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/JavaUser.java @@ -0,0 +1,26 @@ +import extlib.*; + +public class JavaUser { + + public static void test() { + + OuterGeneric.InnerGeneric a = (new OuterGeneric()).new InnerGeneric('a'); + OuterGeneric.InnerGeneric a2 = (new OuterGeneric()).new InnerGeneric('a'); + OuterGeneric.InnerGeneric a3 = (new OuterGeneric()).new InnerGeneric('a', "Hello world"); + OuterGeneric.InnerNotGeneric b = (new OuterGeneric()).new InnerNotGeneric(); + OuterGeneric.InnerNotGeneric b2 = (new OuterGeneric()).new InnerNotGeneric(); + OuterNotGeneric.InnerGeneric c = (new OuterNotGeneric()).new InnerGeneric(); + OuterGeneric.InnerStaticGeneric d = new OuterGeneric.InnerStaticGeneric('a', "Hello world"); + OuterManyParams.MiddleManyParams.InnerManyParams e = ((new OuterManyParams(1, "hello")).new MiddleManyParams(1.0f, 1.0)).new InnerManyParams(1L, (short)1); + + String result1 = a.returnsecond(0, "hello"); + String result1a = a.returnsecond(0, "hello", 'a'); + Integer result2 = b.identity(5); + String result2b = b2.identity("hello"); + String result3 = c.identity("world"); + String result4 = d.identity("goodbye"); + Short result5 = e.returnSixth(1, "hello", 1.0f, 1.0, 1L, (short)1); + + } + +} diff --git a/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/KotlinUser.kt b/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/KotlinUser.kt new file mode 100644 index 00000000000..01102e86881 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/KotlinUser.kt @@ -0,0 +1,27 @@ +package testuser + +import extlib.* + +class User { + + fun test() { + + val a = OuterGeneric().InnerGeneric('a') + val a2 = OuterGeneric().InnerGeneric('a', "hello world") + val b = OuterGeneric().InnerNotGeneric() + val b2 = OuterGeneric().InnerNotGeneric() + val c = OuterNotGeneric().InnerGeneric() + val d = OuterGeneric.InnerStaticGeneric('a', "hello world") + val e = OuterManyParams(1, "hello").MiddleManyParams(1.0f, 1.0).InnerManyParams(1L, 1.toShort()) + + val result1 = a.returnsecond(0, "hello") + val result1a = a.returnsecond(0, "hello", 'a') + val result2 = b.identity(5) + val result2b = b2.identity("hello") + val result3 = c.identity("world") + val result4 = d.identity("goodbye") + val result5 = e.returnSixth(1, "hello", 1.0f, 1.0, 1L, 1.toShort()) + + } + +} diff --git a/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/libsrc/extlib/OuterGeneric.java b/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/libsrc/extlib/OuterGeneric.java new file mode 100644 index 00000000000..36706f2cd42 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/libsrc/extlib/OuterGeneric.java @@ -0,0 +1,32 @@ +package extlib; + +public class OuterGeneric { + + public class InnerNotGeneric { + + public T identity(T t) { return t; } + + } + + public class InnerGeneric { + + public InnerGeneric(R r) { } + + public InnerGeneric(R r, S s) { } + + public S returnsecond(T t, S s) { return s; } + + public S returnsecond(T t, S s, R r) { return s; } + + } + + public static class InnerStaticGeneric { + + public InnerStaticGeneric(R r, S s) { } + + public S identity(S s) { return s; } + + } + +} + diff --git a/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/libsrc/extlib/OuterManyParams.java b/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/libsrc/extlib/OuterManyParams.java new file mode 100644 index 00000000000..f21493ba9f9 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/libsrc/extlib/OuterManyParams.java @@ -0,0 +1,22 @@ +package extlib; + +public class OuterManyParams { + + public OuterManyParams(A a, B b) { } + + public class MiddleManyParams { + + public MiddleManyParams(C c, D d) { } + + public class InnerManyParams { + + public InnerManyParams(E e, F f) { } + + public F returnSixth(A a, B b, C c, D d, E e, F f) { return f; } + + } + + } + +} + diff --git a/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/libsrc/extlib/OuterNotGeneric.java b/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/libsrc/extlib/OuterNotGeneric.java new file mode 100644 index 00000000000..8f998968960 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/libsrc/extlib/OuterNotGeneric.java @@ -0,0 +1,11 @@ +package extlib; + +public class OuterNotGeneric { + + public class InnerGeneric { + + public S identity(S s) { return s; } + + } + +} diff --git a/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/test.expected b/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/test.expected new file mode 100644 index 00000000000..e7c0acaa8f6 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/test.expected @@ -0,0 +1,275 @@ +callArgs +| JavaUser.java:7:52:7:110 | new InnerGeneric(...) | JavaUser.java:7:53:7:79 | new OuterGeneric(...) | -2 | +| JavaUser.java:7:52:7:110 | new InnerGeneric(...) | JavaUser.java:7:86:7:105 | InnerGeneric | -3 | +| JavaUser.java:7:52:7:110 | new InnerGeneric(...) | JavaUser.java:7:107:7:109 | 'a' | 0 | +| JavaUser.java:7:53:7:79 | new OuterGeneric(...) | JavaUser.java:7:57:7:77 | OuterGeneric | -3 | +| JavaUser.java:8:53:8:123 | new InnerGeneric(...) | JavaUser.java:8:54:8:80 | new OuterGeneric(...) | -2 | +| JavaUser.java:8:53:8:123 | new InnerGeneric(...) | JavaUser.java:8:88:8:96 | Character | -4 | +| JavaUser.java:8:53:8:123 | new InnerGeneric(...) | JavaUser.java:8:99:8:118 | InnerGeneric | -3 | +| JavaUser.java:8:53:8:123 | new InnerGeneric(...) | JavaUser.java:8:120:8:122 | 'a' | 0 | +| JavaUser.java:8:54:8:80 | new OuterGeneric(...) | JavaUser.java:8:58:8:78 | OuterGeneric | -3 | +| JavaUser.java:9:53:9:138 | new InnerGeneric(...) | JavaUser.java:9:54:9:80 | new OuterGeneric(...) | -2 | +| JavaUser.java:9:53:9:138 | new InnerGeneric(...) | JavaUser.java:9:88:9:96 | Character | -4 | +| JavaUser.java:9:53:9:138 | new InnerGeneric(...) | JavaUser.java:9:99:9:118 | InnerGeneric | -3 | +| JavaUser.java:9:53:9:138 | new InnerGeneric(...) | JavaUser.java:9:120:9:122 | 'a' | 0 | +| JavaUser.java:9:53:9:138 | new InnerGeneric(...) | JavaUser.java:9:125:9:137 | "Hello world" | 1 | +| JavaUser.java:9:54:9:80 | new OuterGeneric(...) | JavaUser.java:9:58:9:78 | OuterGeneric | -3 | +| JavaUser.java:10:47:10:97 | new InnerNotGeneric(...) | JavaUser.java:10:48:10:74 | new OuterGeneric(...) | -2 | +| JavaUser.java:10:47:10:97 | new InnerNotGeneric(...) | JavaUser.java:10:81:10:95 | InnerNotGeneric | -3 | +| JavaUser.java:10:48:10:74 | new OuterGeneric(...) | JavaUser.java:10:52:10:72 | OuterGeneric | -3 | +| JavaUser.java:11:47:11:96 | new InnerNotGeneric(...) | JavaUser.java:11:48:11:73 | new OuterGeneric(...) | -2 | +| JavaUser.java:11:47:11:96 | new InnerNotGeneric(...) | JavaUser.java:11:80:11:94 | InnerNotGeneric | -3 | +| JavaUser.java:11:48:11:73 | new OuterGeneric(...) | JavaUser.java:11:52:11:71 | OuterGeneric | -3 | +| JavaUser.java:12:46:12:95 | new InnerGeneric(...) | JavaUser.java:12:47:12:67 | new OuterNotGeneric(...) | -2 | +| JavaUser.java:12:46:12:95 | new InnerGeneric(...) | JavaUser.java:12:74:12:93 | InnerGeneric | -3 | +| JavaUser.java:12:47:12:67 | new OuterNotGeneric(...) | JavaUser.java:12:51:12:65 | OuterNotGeneric | -3 | +| JavaUser.java:13:49:13:111 | new InnerStaticGeneric(...) | JavaUser.java:13:53:13:91 | OuterGeneric<>.InnerStaticGeneric | -3 | +| JavaUser.java:13:49:13:111 | new InnerStaticGeneric(...) | JavaUser.java:13:93:13:95 | 'a' | 0 | +| JavaUser.java:13:49:13:111 | new InnerStaticGeneric(...) | JavaUser.java:13:98:13:110 | "Hello world" | 1 | +| JavaUser.java:14:103:14:248 | new InnerManyParams(...) | JavaUser.java:14:104:14:200 | new MiddleManyParams(...) | -2 | +| JavaUser.java:14:103:14:248 | new InnerManyParams(...) | JavaUser.java:14:207:14:234 | InnerManyParams | -3 | +| JavaUser.java:14:103:14:248 | new InnerManyParams(...) | JavaUser.java:14:236:14:237 | 1L | 0 | +| JavaUser.java:14:103:14:248 | new InnerManyParams(...) | JavaUser.java:14:240:14:247 | (...)... | 1 | +| JavaUser.java:14:104:14:200 | new MiddleManyParams(...) | JavaUser.java:14:105:14:152 | new OuterManyParams(...) | -2 | +| JavaUser.java:14:104:14:200 | new MiddleManyParams(...) | JavaUser.java:14:159:14:189 | MiddleManyParams | -3 | +| JavaUser.java:14:104:14:200 | new MiddleManyParams(...) | JavaUser.java:14:191:14:194 | 1.0f | 0 | +| JavaUser.java:14:104:14:200 | new MiddleManyParams(...) | JavaUser.java:14:197:14:199 | 1.0 | 1 | +| JavaUser.java:14:105:14:152 | new OuterManyParams(...) | JavaUser.java:14:109:14:140 | OuterManyParams | -3 | +| JavaUser.java:14:105:14:152 | new OuterManyParams(...) | JavaUser.java:14:142:14:142 | 1 | 0 | +| JavaUser.java:14:105:14:152 | new OuterManyParams(...) | JavaUser.java:14:145:14:151 | "hello" | 1 | +| JavaUser.java:16:22:16:47 | returnsecond(...) | JavaUser.java:16:22:16:22 | a | -1 | +| JavaUser.java:16:22:16:47 | returnsecond(...) | JavaUser.java:16:37:16:37 | 0 | 0 | +| JavaUser.java:16:22:16:47 | returnsecond(...) | JavaUser.java:16:40:16:46 | "hello" | 1 | +| JavaUser.java:17:23:17:53 | returnsecond(...) | JavaUser.java:17:23:17:23 | a | -1 | +| JavaUser.java:17:23:17:53 | returnsecond(...) | JavaUser.java:17:38:17:38 | 0 | 0 | +| JavaUser.java:17:23:17:53 | returnsecond(...) | JavaUser.java:17:41:17:47 | "hello" | 1 | +| JavaUser.java:17:23:17:53 | returnsecond(...) | JavaUser.java:17:50:17:52 | 'a' | 2 | +| JavaUser.java:18:23:18:35 | identity(...) | JavaUser.java:18:23:18:23 | b | -1 | +| JavaUser.java:18:23:18:35 | identity(...) | JavaUser.java:18:34:18:34 | 5 | 0 | +| JavaUser.java:19:23:19:42 | identity(...) | JavaUser.java:19:23:19:24 | b2 | -1 | +| JavaUser.java:19:23:19:42 | identity(...) | JavaUser.java:19:35:19:41 | "hello" | 0 | +| JavaUser.java:20:22:20:40 | identity(...) | JavaUser.java:20:22:20:22 | c | -1 | +| JavaUser.java:20:22:20:40 | identity(...) | JavaUser.java:20:33:20:39 | "world" | 0 | +| JavaUser.java:21:22:21:42 | identity(...) | JavaUser.java:21:22:21:22 | d | -1 | +| JavaUser.java:21:22:21:42 | identity(...) | JavaUser.java:21:33:21:41 | "goodbye" | 0 | +| JavaUser.java:22:21:22:70 | returnSixth(...) | JavaUser.java:22:21:22:21 | e | -1 | +| JavaUser.java:22:21:22:70 | returnSixth(...) | JavaUser.java:22:35:22:35 | 1 | 0 | +| JavaUser.java:22:21:22:70 | returnSixth(...) | JavaUser.java:22:38:22:44 | "hello" | 1 | +| JavaUser.java:22:21:22:70 | returnSixth(...) | JavaUser.java:22:47:22:50 | 1.0f | 2 | +| JavaUser.java:22:21:22:70 | returnSixth(...) | JavaUser.java:22:53:22:55 | 1.0 | 3 | +| JavaUser.java:22:21:22:70 | returnSixth(...) | JavaUser.java:22:58:22:59 | 1L | 4 | +| JavaUser.java:22:21:22:70 | returnSixth(...) | JavaUser.java:22:62:22:69 | (...)... | 5 | +| KotlinUser.kt:9:13:9:31 | new OuterGeneric(...) | KotlinUser.kt:9:13:9:31 | OuterGeneric | -3 | +| KotlinUser.kt:9:33:9:63 | new InnerGeneric(...) | KotlinUser.kt:9:13:9:31 | new OuterGeneric(...) | -2 | +| KotlinUser.kt:9:33:9:63 | new InnerGeneric(...) | KotlinUser.kt:9:33:9:63 | InnerGeneric | -3 | +| KotlinUser.kt:9:33:9:63 | new InnerGeneric(...) | KotlinUser.kt:9:60:9:62 | a | 0 | +| KotlinUser.kt:10:14:10:32 | new OuterGeneric(...) | KotlinUser.kt:10:14:10:32 | OuterGeneric | -3 | +| KotlinUser.kt:10:34:10:65 | new InnerGeneric(...) | KotlinUser.kt:10:14:10:32 | new OuterGeneric(...) | -2 | +| KotlinUser.kt:10:34:10:65 | new InnerGeneric(...) | KotlinUser.kt:10:34:10:65 | InnerGeneric | -3 | +| KotlinUser.kt:10:34:10:65 | new InnerGeneric(...) | KotlinUser.kt:10:47:10:49 | a | 0 | +| KotlinUser.kt:10:34:10:65 | new InnerGeneric(...) | KotlinUser.kt:10:53:10:63 | hello world | 1 | +| KotlinUser.kt:11:13:11:31 | new OuterGeneric(...) | KotlinUser.kt:11:13:11:31 | OuterGeneric | -3 | +| KotlinUser.kt:11:33:11:49 | new InnerNotGeneric<>(...) | KotlinUser.kt:11:13:11:31 | new OuterGeneric(...) | -2 | +| KotlinUser.kt:11:33:11:49 | new InnerNotGeneric<>(...) | KotlinUser.kt:11:33:11:49 | InnerNotGeneric<> | -3 | +| KotlinUser.kt:12:14:12:35 | new OuterGeneric(...) | KotlinUser.kt:12:14:12:35 | OuterGeneric | -3 | +| KotlinUser.kt:12:37:12:53 | new InnerNotGeneric<>(...) | KotlinUser.kt:12:14:12:35 | new OuterGeneric(...) | -2 | +| KotlinUser.kt:12:37:12:53 | new InnerNotGeneric<>(...) | KotlinUser.kt:12:37:12:53 | InnerNotGeneric<> | -3 | +| KotlinUser.kt:13:13:13:29 | new OuterNotGeneric(...) | KotlinUser.kt:13:13:13:29 | OuterNotGeneric | -3 | +| KotlinUser.kt:13:31:13:52 | new InnerGeneric(...) | KotlinUser.kt:13:13:13:29 | new OuterNotGeneric(...) | -2 | +| KotlinUser.kt:13:31:13:52 | new InnerGeneric(...) | KotlinUser.kt:13:31:13:52 | InnerGeneric | -3 | +| KotlinUser.kt:14:26:14:63 | new InnerStaticGeneric(...) | KotlinUser.kt:14:26:14:63 | InnerStaticGeneric | -3 | +| KotlinUser.kt:14:26:14:63 | new InnerStaticGeneric(...) | KotlinUser.kt:14:45:14:47 | a | 0 | +| KotlinUser.kt:14:26:14:63 | new InnerStaticGeneric(...) | KotlinUser.kt:14:51:14:61 | hello world | 1 | +| KotlinUser.kt:15:13:15:39 | new OuterManyParams(...) | KotlinUser.kt:15:13:15:39 | OuterManyParams | -3 | +| KotlinUser.kt:15:13:15:39 | new OuterManyParams(...) | KotlinUser.kt:15:29:15:29 | 1 | 0 | +| KotlinUser.kt:15:13:15:39 | new OuterManyParams(...) | KotlinUser.kt:15:33:15:37 | hello | 1 | +| KotlinUser.kt:15:41:15:67 | new MiddleManyParams(...) | KotlinUser.kt:15:13:15:39 | new OuterManyParams(...) | -2 | +| KotlinUser.kt:15:41:15:67 | new MiddleManyParams(...) | KotlinUser.kt:15:41:15:67 | MiddleManyParams | -3 | +| KotlinUser.kt:15:41:15:67 | new MiddleManyParams(...) | KotlinUser.kt:15:58:15:61 | 1.0 | 0 | +| KotlinUser.kt:15:41:15:67 | new MiddleManyParams(...) | KotlinUser.kt:15:64:15:66 | 1.0 | 1 | +| KotlinUser.kt:15:69:15:100 | new InnerManyParams(...) | KotlinUser.kt:15:41:15:67 | new MiddleManyParams(...) | -2 | +| KotlinUser.kt:15:69:15:100 | new InnerManyParams(...) | KotlinUser.kt:15:69:15:100 | InnerManyParams | -3 | +| KotlinUser.kt:15:69:15:100 | new InnerManyParams(...) | KotlinUser.kt:15:85:15:86 | 1 | 0 | +| KotlinUser.kt:15:69:15:100 | new InnerManyParams(...) | KotlinUser.kt:15:91:15:99 | shortValue(...) | 1 | +| KotlinUser.kt:15:91:15:99 | shortValue(...) | KotlinUser.kt:15:89:15:89 | 1 | -1 | +| KotlinUser.kt:17:21:17:44 | returnsecond(...) | KotlinUser.kt:17:19:17:19 | a | -1 | +| KotlinUser.kt:17:21:17:44 | returnsecond(...) | KotlinUser.kt:17:34:17:34 | 0 | 0 | +| KotlinUser.kt:17:21:17:44 | returnsecond(...) | KotlinUser.kt:17:38:17:42 | hello | 1 | +| KotlinUser.kt:18:22:18:50 | returnsecond(...) | KotlinUser.kt:18:20:18:20 | a | -1 | +| KotlinUser.kt:18:22:18:50 | returnsecond(...) | KotlinUser.kt:18:22:18:50 | Character | -2 | +| KotlinUser.kt:18:22:18:50 | returnsecond(...) | KotlinUser.kt:18:35:18:35 | 0 | 0 | +| KotlinUser.kt:18:22:18:50 | returnsecond(...) | KotlinUser.kt:18:39:18:43 | hello | 1 | +| KotlinUser.kt:18:22:18:50 | returnsecond(...) | KotlinUser.kt:18:47:18:49 | a | 2 | +| KotlinUser.kt:19:21:19:31 | identity(...) | KotlinUser.kt:19:19:19:19 | b | -1 | +| KotlinUser.kt:19:21:19:31 | identity(...) | KotlinUser.kt:19:30:19:30 | 5 | 0 | +| KotlinUser.kt:20:23:20:39 | identity(...) | KotlinUser.kt:20:20:20:21 | b2 | -1 | +| KotlinUser.kt:20:23:20:39 | identity(...) | KotlinUser.kt:20:33:20:37 | hello | 0 | +| KotlinUser.kt:21:21:21:37 | identity(...) | KotlinUser.kt:21:19:21:19 | c | -1 | +| KotlinUser.kt:21:21:21:37 | identity(...) | KotlinUser.kt:21:31:21:35 | world | 0 | +| KotlinUser.kt:22:21:22:39 | identity(...) | KotlinUser.kt:22:19:22:19 | d | -1 | +| KotlinUser.kt:22:21:22:39 | identity(...) | KotlinUser.kt:22:31:22:37 | goodbye | 0 | +| KotlinUser.kt:23:21:23:71 | returnSixth(...) | KotlinUser.kt:23:19:23:19 | e | -1 | +| KotlinUser.kt:23:21:23:71 | returnSixth(...) | KotlinUser.kt:23:33:23:33 | 1 | 0 | +| KotlinUser.kt:23:21:23:71 | returnSixth(...) | KotlinUser.kt:23:37:23:41 | hello | 1 | +| KotlinUser.kt:23:21:23:71 | returnSixth(...) | KotlinUser.kt:23:45:23:48 | 1.0 | 2 | +| KotlinUser.kt:23:21:23:71 | returnSixth(...) | KotlinUser.kt:23:51:23:53 | 1.0 | 3 | +| KotlinUser.kt:23:21:23:71 | returnSixth(...) | KotlinUser.kt:23:56:23:57 | 1 | 4 | +| KotlinUser.kt:23:21:23:71 | returnSixth(...) | KotlinUser.kt:23:62:23:70 | shortValue(...) | 5 | +| KotlinUser.kt:23:62:23:70 | shortValue(...) | KotlinUser.kt:23:60:23:60 | 1 | -1 | +genericTypes +| extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | S | +| extlib.jar/extlib/OuterGeneric$InnerStaticGeneric.class:0:0:0:0 | InnerStaticGeneric | extlib.jar/extlib/OuterGeneric$InnerStaticGeneric.class:0:0:0:0 | S | +| extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | T | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | E | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | F | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | C | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | D | +| extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | OuterManyParams | extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | A | +| extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | OuterManyParams | extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | B | +| extlib.jar/extlib/OuterNotGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | extlib.jar/extlib/OuterNotGeneric$InnerGeneric.class:0:0:0:0 | S | +paramTypes +| extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | S | +| extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | String | +| extlib.jar/extlib/OuterGeneric$InnerStaticGeneric.class:0:0:0:0 | InnerStaticGeneric | S | +| extlib.jar/extlib/OuterGeneric$InnerStaticGeneric.class:0:0:0:0 | InnerStaticGeneric | String | +| extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | T | +| extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | Integer | +| extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | String | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | E | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | F | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | Long | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | Short | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | C | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | D | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | Double | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | Float | +| extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | OuterManyParams | A | +| extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | OuterManyParams | B | +| extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | OuterManyParams | Integer | +| extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | OuterManyParams | String | +| extlib.jar/extlib/OuterNotGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | S | +| extlib.jar/extlib/OuterNotGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | String | +constructors +| extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | InnerGeneric(java.lang.Object) | +| extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | InnerGeneric(java.lang.Object,java.lang.Object) | +| extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | InnerGeneric(java.lang.Object) | +| extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | InnerGeneric(java.lang.Object,java.lang.String) | +| extlib.jar/extlib/OuterGeneric$InnerNotGeneric.class:0:0:0:0 | InnerNotGeneric | InnerNotGeneric() | +| extlib.jar/extlib/OuterGeneric$InnerNotGeneric.class:0:0:0:0 | InnerNotGeneric<> | InnerNotGeneric<>() | +| extlib.jar/extlib/OuterGeneric$InnerNotGeneric.class:0:0:0:0 | InnerNotGeneric<> | InnerNotGeneric<>() | +| extlib.jar/extlib/OuterGeneric$InnerStaticGeneric.class:0:0:0:0 | InnerStaticGeneric | InnerStaticGeneric(java.lang.Object,java.lang.Object) | +| extlib.jar/extlib/OuterGeneric$InnerStaticGeneric.class:0:0:0:0 | InnerStaticGeneric | InnerStaticGeneric(java.lang.Object,java.lang.String) | +| extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | OuterGeneric() | +| extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | OuterGeneric() | +| extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | OuterGeneric() | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | InnerManyParams(java.lang.Object,java.lang.Object) | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | InnerManyParams(java.lang.Long,java.lang.Short) | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | MiddleManyParams(java.lang.Object,java.lang.Object) | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | MiddleManyParams(java.lang.Float,java.lang.Double) | +| extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | OuterManyParams | OuterManyParams(java.lang.Object,java.lang.Object) | +| extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | OuterManyParams | OuterManyParams(java.lang.Integer,java.lang.String) | +| extlib.jar/extlib/OuterNotGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | InnerGeneric() | +| extlib.jar/extlib/OuterNotGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | InnerGeneric() | +| extlib.jar/extlib/OuterNotGeneric.class:0:0:0:0 | OuterNotGeneric | OuterNotGeneric() | +methods +| extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | returnsecond | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | returnsecond(java.lang.Object,java.lang.Object) | +| extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | returnsecond | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | returnsecond(java.lang.Object,java.lang.Object,java.lang.Object) | +| extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | returnsecond | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | returnsecond(java.lang.Integer,java.lang.String) | +| extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | returnsecond | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | returnsecond(java.lang.Integer,java.lang.String,java.lang.Object) | +| extlib.jar/extlib/OuterGeneric$InnerNotGeneric.class:0:0:0:0 | identity | extlib.jar/extlib/OuterGeneric$InnerNotGeneric.class:0:0:0:0 | InnerNotGeneric | identity(java.lang.Object) | +| extlib.jar/extlib/OuterGeneric$InnerNotGeneric.class:0:0:0:0 | identity | extlib.jar/extlib/OuterGeneric$InnerNotGeneric.class:0:0:0:0 | InnerNotGeneric<> | identity(java.lang.Integer) | +| extlib.jar/extlib/OuterGeneric$InnerNotGeneric.class:0:0:0:0 | identity | extlib.jar/extlib/OuterGeneric$InnerNotGeneric.class:0:0:0:0 | InnerNotGeneric<> | identity(java.lang.String) | +| extlib.jar/extlib/OuterGeneric$InnerStaticGeneric.class:0:0:0:0 | identity | extlib.jar/extlib/OuterGeneric$InnerStaticGeneric.class:0:0:0:0 | InnerStaticGeneric | identity(java.lang.Object) | +| extlib.jar/extlib/OuterGeneric$InnerStaticGeneric.class:0:0:0:0 | identity | extlib.jar/extlib/OuterGeneric$InnerStaticGeneric.class:0:0:0:0 | InnerStaticGeneric | identity(java.lang.String) | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | returnSixth | extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | returnSixth(java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object) | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | returnSixth | extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | returnSixth(java.lang.Integer,java.lang.String,java.lang.Float,java.lang.Double,java.lang.Long,java.lang.Short) | +| extlib.jar/extlib/OuterNotGeneric$InnerGeneric.class:0:0:0:0 | identity | extlib.jar/extlib/OuterNotGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | identity(java.lang.Object) | +| extlib.jar/extlib/OuterNotGeneric$InnerGeneric.class:0:0:0:0 | identity | extlib.jar/extlib/OuterNotGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | identity(java.lang.String) | +nestedTypes +| extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | +| extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | +| extlib.jar/extlib/OuterGeneric$InnerNotGeneric.class:0:0:0:0 | InnerNotGeneric | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | +| extlib.jar/extlib/OuterGeneric$InnerNotGeneric.class:0:0:0:0 | InnerNotGeneric<> | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | +| extlib.jar/extlib/OuterGeneric$InnerNotGeneric.class:0:0:0:0 | InnerNotGeneric<> | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | +| extlib.jar/extlib/OuterGeneric$InnerStaticGeneric.class:0:0:0:0 | InnerStaticGeneric | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | +| extlib.jar/extlib/OuterGeneric$InnerStaticGeneric.class:0:0:0:0 | InnerStaticGeneric | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | OuterManyParams | +| extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | OuterManyParams | +| extlib.jar/extlib/OuterNotGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | extlib.jar/extlib/OuterNotGeneric.class:0:0:0:0 | OuterNotGeneric | +| extlib.jar/extlib/OuterNotGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | extlib.jar/extlib/OuterNotGeneric.class:0:0:0:0 | OuterNotGeneric | +javaKotlinCalleeAgreement +| JavaUser.java:16:22:16:47 | returnsecond(...) | KotlinUser.kt:17:21:17:44 | returnsecond(...) | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | returnsecond | +| JavaUser.java:17:23:17:53 | returnsecond(...) | KotlinUser.kt:18:22:18:50 | returnsecond(...) | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | returnsecond | +| JavaUser.java:18:23:18:35 | identity(...) | KotlinUser.kt:19:21:19:31 | identity(...) | extlib.jar/extlib/OuterGeneric$InnerNotGeneric.class:0:0:0:0 | identity | +| JavaUser.java:19:23:19:42 | identity(...) | KotlinUser.kt:20:23:20:39 | identity(...) | extlib.jar/extlib/OuterGeneric$InnerNotGeneric.class:0:0:0:0 | identity | +| JavaUser.java:20:22:20:40 | identity(...) | KotlinUser.kt:21:21:21:37 | identity(...) | extlib.jar/extlib/OuterNotGeneric$InnerGeneric.class:0:0:0:0 | identity | +| JavaUser.java:21:22:21:42 | identity(...) | KotlinUser.kt:22:21:22:39 | identity(...) | extlib.jar/extlib/OuterGeneric$InnerStaticGeneric.class:0:0:0:0 | identity | +| JavaUser.java:22:21:22:70 | returnSixth(...) | KotlinUser.kt:23:21:23:71 | returnSixth(...) | extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | returnSixth | +javaKotlinConstructorAgreement +| JavaUser.java:7:52:7:110 | new InnerGeneric(...) | KotlinUser.kt:9:33:9:63 | new InnerGeneric(...) | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | +| JavaUser.java:7:53:7:79 | new OuterGeneric(...) | KotlinUser.kt:9:13:9:31 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | +| JavaUser.java:7:53:7:79 | new OuterGeneric(...) | KotlinUser.kt:10:14:10:32 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | +| JavaUser.java:7:53:7:79 | new OuterGeneric(...) | KotlinUser.kt:11:13:11:31 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | +| JavaUser.java:8:53:8:123 | new InnerGeneric(...) | KotlinUser.kt:9:33:9:63 | new InnerGeneric(...) | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | +| JavaUser.java:8:54:8:80 | new OuterGeneric(...) | KotlinUser.kt:9:13:9:31 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | +| JavaUser.java:8:54:8:80 | new OuterGeneric(...) | KotlinUser.kt:10:14:10:32 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | +| JavaUser.java:8:54:8:80 | new OuterGeneric(...) | KotlinUser.kt:11:13:11:31 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | +| JavaUser.java:9:53:9:138 | new InnerGeneric(...) | KotlinUser.kt:10:34:10:65 | new InnerGeneric(...) | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | +| JavaUser.java:9:54:9:80 | new OuterGeneric(...) | KotlinUser.kt:9:13:9:31 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | +| JavaUser.java:9:54:9:80 | new OuterGeneric(...) | KotlinUser.kt:10:14:10:32 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | +| JavaUser.java:9:54:9:80 | new OuterGeneric(...) | KotlinUser.kt:11:13:11:31 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | +| JavaUser.java:10:48:10:74 | new OuterGeneric(...) | KotlinUser.kt:9:13:9:31 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | +| JavaUser.java:10:48:10:74 | new OuterGeneric(...) | KotlinUser.kt:10:14:10:32 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | +| JavaUser.java:10:48:10:74 | new OuterGeneric(...) | KotlinUser.kt:11:13:11:31 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | +| JavaUser.java:11:48:11:73 | new OuterGeneric(...) | KotlinUser.kt:12:14:12:35 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | +| JavaUser.java:12:46:12:95 | new InnerGeneric(...) | KotlinUser.kt:13:31:13:52 | new InnerGeneric(...) | extlib.jar/extlib/OuterNotGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | +| JavaUser.java:12:47:12:67 | new OuterNotGeneric(...) | KotlinUser.kt:13:13:13:29 | new OuterNotGeneric(...) | extlib.jar/extlib/OuterNotGeneric.class:0:0:0:0 | OuterNotGeneric | +| JavaUser.java:13:49:13:111 | new InnerStaticGeneric(...) | KotlinUser.kt:14:26:14:63 | new InnerStaticGeneric(...) | extlib.jar/extlib/OuterGeneric$InnerStaticGeneric.class:0:0:0:0 | InnerStaticGeneric | +| JavaUser.java:14:103:14:248 | new InnerManyParams(...) | KotlinUser.kt:15:69:15:100 | new InnerManyParams(...) | extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | +| JavaUser.java:14:104:14:200 | new MiddleManyParams(...) | KotlinUser.kt:15:41:15:67 | new MiddleManyParams(...) | extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | +| JavaUser.java:14:105:14:152 | new OuterManyParams(...) | KotlinUser.kt:15:13:15:39 | new OuterManyParams(...) | extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | OuterManyParams | +javaKotlinLocalTypeAgreement +| JavaUser.java:7:5:7:111 | InnerGeneric a | KotlinUser.kt:9:5:9:63 | InnerGeneric a | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | +| JavaUser.java:7:5:7:111 | InnerGeneric a | KotlinUser.kt:10:5:10:65 | InnerGeneric a2 | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | +| JavaUser.java:8:5:8:124 | InnerGeneric a2 | KotlinUser.kt:9:5:9:63 | InnerGeneric a | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | +| JavaUser.java:8:5:8:124 | InnerGeneric a2 | KotlinUser.kt:10:5:10:65 | InnerGeneric a2 | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | +| JavaUser.java:9:5:9:139 | InnerGeneric a3 | KotlinUser.kt:9:5:9:63 | InnerGeneric a | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | +| JavaUser.java:9:5:9:139 | InnerGeneric a3 | KotlinUser.kt:10:5:10:65 | InnerGeneric a2 | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | +| JavaUser.java:10:5:10:98 | InnerNotGeneric<> b | KotlinUser.kt:11:5:11:49 | InnerNotGeneric<> b | extlib.jar/extlib/OuterGeneric$InnerNotGeneric.class:0:0:0:0 | InnerNotGeneric<> | +| JavaUser.java:11:5:11:97 | InnerNotGeneric<> b2 | KotlinUser.kt:12:5:12:53 | InnerNotGeneric<> b2 | extlib.jar/extlib/OuterGeneric$InnerNotGeneric.class:0:0:0:0 | InnerNotGeneric<> | +| JavaUser.java:12:5:12:96 | InnerGeneric c | KotlinUser.kt:13:5:13:52 | InnerGeneric c | extlib.jar/extlib/OuterNotGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | +| JavaUser.java:13:5:13:112 | InnerStaticGeneric d | KotlinUser.kt:14:5:14:63 | InnerStaticGeneric d | extlib.jar/extlib/OuterGeneric$InnerStaticGeneric.class:0:0:0:0 | InnerStaticGeneric | +| JavaUser.java:14:5:14:249 | InnerManyParams e | KotlinUser.kt:15:5:15:100 | InnerManyParams e | extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | +#select +| JavaUser.java:7:52:7:110 | new InnerGeneric(...) | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | JavaUser.java:7:99:7:104 | String | +| JavaUser.java:7:53:7:79 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | JavaUser.java:7:70:7:76 | Integer | +| JavaUser.java:8:53:8:123 | new InnerGeneric(...) | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | JavaUser.java:8:112:8:117 | String | +| JavaUser.java:8:54:8:80 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | JavaUser.java:8:71:8:77 | Integer | +| JavaUser.java:9:53:9:138 | new InnerGeneric(...) | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | JavaUser.java:9:112:9:117 | String | +| JavaUser.java:9:54:9:80 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | JavaUser.java:9:71:9:77 | Integer | +| JavaUser.java:10:48:10:74 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | JavaUser.java:10:65:10:71 | Integer | +| JavaUser.java:11:48:11:73 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | JavaUser.java:11:65:11:70 | String | +| JavaUser.java:12:46:12:95 | new InnerGeneric(...) | extlib.jar/extlib/OuterNotGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | extlib.jar/extlib/OuterNotGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | JavaUser.java:12:87:12:92 | String | +| JavaUser.java:13:49:13:111 | new InnerStaticGeneric(...) | extlib.jar/extlib/OuterGeneric$InnerStaticGeneric.class:0:0:0:0 | InnerStaticGeneric | extlib.jar/extlib/OuterGeneric$InnerStaticGeneric.class:0:0:0:0 | InnerStaticGeneric | JavaUser.java:13:85:13:90 | String | +| JavaUser.java:14:103:14:248 | new InnerManyParams(...) | extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | JavaUser.java:14:223:14:226 | Long | +| JavaUser.java:14:103:14:248 | new InnerManyParams(...) | extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | JavaUser.java:14:229:14:233 | Short | +| JavaUser.java:14:104:14:200 | new MiddleManyParams(...) | extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | JavaUser.java:14:176:14:180 | Float | +| JavaUser.java:14:104:14:200 | new MiddleManyParams(...) | extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | JavaUser.java:14:183:14:188 | Double | +| JavaUser.java:14:105:14:152 | new OuterManyParams(...) | extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | OuterManyParams | extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | OuterManyParams | JavaUser.java:14:125:14:131 | Integer | +| JavaUser.java:14:105:14:152 | new OuterManyParams(...) | extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | OuterManyParams | extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | OuterManyParams | JavaUser.java:14:134:14:139 | String | +| KotlinUser.kt:9:13:9:31 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | KotlinUser.kt:9:13:9:31 | Integer | +| KotlinUser.kt:9:33:9:63 | new InnerGeneric(...) | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | KotlinUser.kt:9:33:9:63 | String | +| KotlinUser.kt:10:14:10:32 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | KotlinUser.kt:10:14:10:32 | Integer | +| KotlinUser.kt:10:34:10:65 | new InnerGeneric(...) | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | extlib.jar/extlib/OuterGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | KotlinUser.kt:10:34:10:65 | String | +| KotlinUser.kt:11:13:11:31 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | KotlinUser.kt:11:13:11:31 | Integer | +| KotlinUser.kt:12:14:12:35 | new OuterGeneric(...) | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | extlib.jar/extlib/OuterGeneric.class:0:0:0:0 | OuterGeneric | KotlinUser.kt:12:14:12:35 | String | +| KotlinUser.kt:13:31:13:52 | new InnerGeneric(...) | extlib.jar/extlib/OuterNotGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | extlib.jar/extlib/OuterNotGeneric$InnerGeneric.class:0:0:0:0 | InnerGeneric | KotlinUser.kt:13:31:13:52 | String | +| KotlinUser.kt:14:26:14:63 | new InnerStaticGeneric(...) | extlib.jar/extlib/OuterGeneric$InnerStaticGeneric.class:0:0:0:0 | InnerStaticGeneric | extlib.jar/extlib/OuterGeneric$InnerStaticGeneric.class:0:0:0:0 | InnerStaticGeneric | KotlinUser.kt:14:26:14:63 | String | +| KotlinUser.kt:15:13:15:39 | new OuterManyParams(...) | extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | OuterManyParams | extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | OuterManyParams | KotlinUser.kt:15:13:15:39 | Integer | +| KotlinUser.kt:15:13:15:39 | new OuterManyParams(...) | extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | OuterManyParams | extlib.jar/extlib/OuterManyParams.class:0:0:0:0 | OuterManyParams | KotlinUser.kt:15:13:15:39 | String | +| KotlinUser.kt:15:41:15:67 | new MiddleManyParams(...) | extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | KotlinUser.kt:15:41:15:67 | Double | +| KotlinUser.kt:15:41:15:67 | new MiddleManyParams(...) | extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | extlib.jar/extlib/OuterManyParams$MiddleManyParams.class:0:0:0:0 | MiddleManyParams | KotlinUser.kt:15:41:15:67 | Float | +| KotlinUser.kt:15:69:15:100 | new InnerManyParams(...) | extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | KotlinUser.kt:15:69:15:100 | Long | +| KotlinUser.kt:15:69:15:100 | new InnerManyParams(...) | extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | extlib.jar/extlib/OuterManyParams$MiddleManyParams$InnerManyParams.class:0:0:0:0 | InnerManyParams | KotlinUser.kt:15:69:15:100 | Short | diff --git a/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/test.py b/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/test.py new file mode 100644 index 00000000000..a2eab7dc171 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/test.py @@ -0,0 +1,11 @@ +from create_database_utils import * +import glob + +# Compile Java untraced. Note the Java source is hidden under `javasrc` so the Kotlin compiler +# will certainly reference the jar, not the source or class file for extlib.Lib + +os.mkdir('build') +runSuccessfully(["javac"] + glob.glob("libsrc/extlib/*.java") + ["-d", "build"]) +runSuccessfully(["jar", "cf", "extlib.jar", "-C", "build", "extlib"]) +run_codeql_database_create(["javac JavaUser.java -cp extlib.jar", "kotlinc KotlinUser.kt -cp extlib.jar"], lang="java") + diff --git a/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/test.ql b/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/test.ql new file mode 100644 index 00000000000..5e6bd22674a --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/nested_generic_types/test.ql @@ -0,0 +1,63 @@ +import java + +query predicate callArgs(Call gc, Expr arg, int idx) { + arg.getParent() = gc and idx = arg.getIndex() +} + +query predicate genericTypes(GenericType rt, TypeVariable param) { + rt.getPackage().getName() = "extlib" and + param = rt.getATypeParameter() +} + +query predicate paramTypes(ParameterizedType rt, string typeArg) { + rt.getPackage().getName() = "extlib" and + typeArg = rt.getATypeArgument().toString() +} + +query predicate constructors(Constructor c, string signature) { + c.getDeclaringType().getPackage().getName() = "extlib" and + signature = c.getSignature() +} + +query predicate methods(Method m, RefType declType, string signature) { + declType = m.getDeclaringType() and + signature = m.getSignature() and + declType.getPackage().getName() = "extlib" +} + +query predicate nestedTypes(NestedType nt, RefType parent) { + nt.getPackage().getName() = "extlib" and + parent = nt.getEnclosingType() +} + +query predicate javaKotlinCalleeAgreement( + MethodAccess javaMa, MethodAccess kotlinMa, Callable callee +) { + javaMa.getCallee() = callee and + kotlinMa.getCallee() = callee and + javaMa.getFile().getExtension() = "java" and + kotlinMa.getFile().getExtension() = "kt" +} + +query predicate javaKotlinConstructorAgreement( + ClassInstanceExpr javaCie, ClassInstanceExpr kotlinCie, Constructor constructor +) { + javaCie.getConstructor() = constructor and + kotlinCie.getConstructor() = constructor and + javaCie.getFile().getExtension() = "java" and + kotlinCie.getFile().getExtension() = "kt" +} + +query predicate javaKotlinLocalTypeAgreement( + LocalVariableDecl javaDecl, LocalVariableDecl kotlinDecl, RefType agreedType +) { + javaDecl.getType() = agreedType and + kotlinDecl.getType() = agreedType and + javaDecl.getFile().getExtension() = "java" and + kotlinDecl.getFile().getExtension() = "kt" and + agreedType.getPackage().getName() = "extlib" +} + +from ClassInstanceExpr cie +where cie.getFile().isSourceFile() +select cie, cie.getConstructedType(), cie.getConstructor(), cie.getATypeArgument() diff --git a/java/ql/integration-tests/posix-only/kotlin/qlpack.yml b/java/ql/integration-tests/posix-only/kotlin/qlpack.yml new file mode 100644 index 00000000000..11adb1f538b --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/qlpack.yml @@ -0,0 +1,2 @@ +libraryPathDependencies: + - codeql-java diff --git a/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/JavaUser.java b/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/JavaUser.java new file mode 100644 index 00000000000..bcdf24297a9 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/JavaUser.java @@ -0,0 +1,14 @@ +import extlib.GenericTypeJava; +import extlib.RawTypesInSignatureJava; + +class JavaUser { + + public static void user() { + + GenericTypeJava rawGt = GenericTypeJava.getRaw(); + RawTypesInSignatureJava rtis = new RawTypesInSignatureJava(); + rtis.directParameter(null); + + } + +} diff --git a/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/KotlinUser.kt b/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/KotlinUser.kt new file mode 100644 index 00000000000..238a80ad815 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/KotlinUser.kt @@ -0,0 +1,11 @@ +import extlib.GenericTypeKotlin; +import extlib.RawTypesInSignatureKotlin; + +fun test() { + + val rawGt = GenericTypeKotlin.getRaw() + val rtis = RawTypesInSignatureKotlin() + rtis.directParameter(null) + +} + diff --git a/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/libsrc/extlib/GenericTypeJava.java b/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/libsrc/extlib/GenericTypeJava.java new file mode 100644 index 00000000000..c45d751dfe2 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/libsrc/extlib/GenericTypeJava.java @@ -0,0 +1,12 @@ +package extlib; + +import java.util.*; + +class BoundJava {} + +class InheritsGenericJava { } + +public class GenericTypeJava extends InheritsGenericJava { + public static GenericTypeJava getRaw() { return new GenericTypeJava(); } +} + diff --git a/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/libsrc/extlib/GenericTypeKotlin.java b/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/libsrc/extlib/GenericTypeKotlin.java new file mode 100644 index 00000000000..829272760c9 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/libsrc/extlib/GenericTypeKotlin.java @@ -0,0 +1,12 @@ +package extlib; + +import java.util.*; + +class BoundKotlin {} + +class InheritsGenericKotlin { } + +public class GenericTypeKotlin extends InheritsGenericKotlin { + public static GenericTypeKotlin getRaw() { return new GenericTypeKotlin(); } +} + diff --git a/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/libsrc/extlib/RawTypesInSignatureJava.java b/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/libsrc/extlib/RawTypesInSignatureJava.java new file mode 100644 index 00000000000..afa78d3e32d --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/libsrc/extlib/RawTypesInSignatureJava.java @@ -0,0 +1,23 @@ +package extlib; + +class ContainerJava { } + +public class RawTypesInSignatureJava { + + public GenericTypeJava directReturn() { return null; } + + public void directParameter(GenericTypeJava param) { } + + public ContainerJava genericParamReturn() { return null; } + + public void genericParamParameter(ContainerJava param) { } + + public ContainerJava genericParamExtendsReturn() { return null; } + + public void genericParamExtendsParameter(ContainerJava param) { } + + public ContainerJava genericParamSuperReturn() { return null; } + + public void genericParamSuperParameter(ContainerJava param) { } + +} diff --git a/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/libsrc/extlib/RawTypesInSignatureKotlin.java b/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/libsrc/extlib/RawTypesInSignatureKotlin.java new file mode 100644 index 00000000000..55e5dd68543 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/libsrc/extlib/RawTypesInSignatureKotlin.java @@ -0,0 +1,23 @@ +package extlib; + +class ContainerKotlin { } + +public class RawTypesInSignatureKotlin { + + public GenericTypeKotlin directReturn() { return null; } + + public void directParameter(GenericTypeKotlin param) { } + + public ContainerKotlin genericParamReturn() { return null; } + + public void genericParamParameter(ContainerKotlin param) { } + + public ContainerKotlin genericParamExtendsReturn() { return null; } + + public void genericParamExtendsParameter(ContainerKotlin param) { } + + public ContainerKotlin genericParamSuperReturn() { return null; } + + public void genericParamSuperParameter(ContainerKotlin param) { } + +} diff --git a/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/test.expected b/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/test.expected new file mode 100644 index 00000000000..b0ea074a062 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/test.expected @@ -0,0 +1,24 @@ +rawTypeSupertypes +| extlib.jar/extlib/ContainerJava.class:0:0:0:0 | ContainerJava<> | file:///Object.class:0:0:0:0 | Object | +| extlib.jar/extlib/ContainerKotlin.class:0:0:0:0 | ContainerKotlin<> | file:///Object.class:0:0:0:0 | Object | +| extlib.jar/extlib/GenericTypeJava.class:0:0:0:0 | GenericTypeJava<> | extlib.jar/extlib/InheritsGenericJava.class:0:0:0:0 | InheritsGenericJava<> | +| extlib.jar/extlib/GenericTypeKotlin.class:0:0:0:0 | GenericTypeKotlin<> | extlib.jar/extlib/InheritsGenericKotlin.class:0:0:0:0 | InheritsGenericKotlin<> | +| extlib.jar/extlib/InheritsGenericJava.class:0:0:0:0 | InheritsGenericJava<> | file:///Object.class:0:0:0:0 | Object | +| extlib.jar/extlib/InheritsGenericKotlin.class:0:0:0:0 | InheritsGenericKotlin<> | file:///Object.class:0:0:0:0 | Object | +rawTypeMethod +| extlib.jar/extlib/RawTypesInSignatureJava.class:0:0:0:0 | RawTypesInSignatureJava | directParameter | directParameter(extlib.GenericTypeJava) | GenericTypeJava<> | void | +| extlib.jar/extlib/RawTypesInSignatureJava.class:0:0:0:0 | RawTypesInSignatureJava | directReturn | directReturn() | No parameter | GenericTypeJava<> | +| extlib.jar/extlib/RawTypesInSignatureJava.class:0:0:0:0 | RawTypesInSignatureJava | genericParamExtendsParameter | genericParamExtendsParameter(extlib.ContainerJava) | ContainerJava> | void | +| extlib.jar/extlib/RawTypesInSignatureJava.class:0:0:0:0 | RawTypesInSignatureJava | genericParamExtendsReturn | genericParamExtendsReturn() | No parameter | ContainerJava> | +| extlib.jar/extlib/RawTypesInSignatureJava.class:0:0:0:0 | RawTypesInSignatureJava | genericParamParameter | genericParamParameter(extlib.ContainerJava) | ContainerJava> | void | +| extlib.jar/extlib/RawTypesInSignatureJava.class:0:0:0:0 | RawTypesInSignatureJava | genericParamReturn | genericParamReturn() | No parameter | ContainerJava> | +| extlib.jar/extlib/RawTypesInSignatureJava.class:0:0:0:0 | RawTypesInSignatureJava | genericParamSuperParameter | genericParamSuperParameter(extlib.ContainerJava) | ContainerJava> | void | +| extlib.jar/extlib/RawTypesInSignatureJava.class:0:0:0:0 | RawTypesInSignatureJava | genericParamSuperReturn | genericParamSuperReturn() | No parameter | ContainerJava> | +| extlib.jar/extlib/RawTypesInSignatureKotlin.class:0:0:0:0 | RawTypesInSignatureKotlin | directParameter | directParameter(extlib.GenericTypeKotlin) | GenericTypeKotlin<> | void | +| extlib.jar/extlib/RawTypesInSignatureKotlin.class:0:0:0:0 | RawTypesInSignatureKotlin | directReturn | directReturn() | No parameter | GenericTypeKotlin<> | +| extlib.jar/extlib/RawTypesInSignatureKotlin.class:0:0:0:0 | RawTypesInSignatureKotlin | genericParamExtendsParameter | genericParamExtendsParameter(extlib.ContainerKotlin) | ContainerKotlin> | void | +| extlib.jar/extlib/RawTypesInSignatureKotlin.class:0:0:0:0 | RawTypesInSignatureKotlin | genericParamExtendsReturn | genericParamExtendsReturn() | No parameter | ContainerKotlin> | +| extlib.jar/extlib/RawTypesInSignatureKotlin.class:0:0:0:0 | RawTypesInSignatureKotlin | genericParamParameter | genericParamParameter(extlib.ContainerKotlin) | ContainerKotlin> | void | +| extlib.jar/extlib/RawTypesInSignatureKotlin.class:0:0:0:0 | RawTypesInSignatureKotlin | genericParamReturn | genericParamReturn() | No parameter | ContainerKotlin> | +| extlib.jar/extlib/RawTypesInSignatureKotlin.class:0:0:0:0 | RawTypesInSignatureKotlin | genericParamSuperParameter | genericParamSuperParameter(extlib.ContainerKotlin) | ContainerKotlin> | void | +| extlib.jar/extlib/RawTypesInSignatureKotlin.class:0:0:0:0 | RawTypesInSignatureKotlin | genericParamSuperReturn | genericParamSuperReturn() | No parameter | ContainerKotlin> | diff --git a/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/test.py b/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/test.py new file mode 100644 index 00000000000..520c75a556f --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/test.py @@ -0,0 +1,10 @@ +from create_database_utils import * +import glob + +# Compile Java untraced. Note the Java source is hidden under `javasrc` so the Kotlin compiler +# will certainly reference the jar, not the source or class file for extlib.Lib + +os.mkdir('build') +runSuccessfully(["javac"] + glob.glob("libsrc/extlib/*.java") + ["-d", "build"]) +runSuccessfully(["jar", "cf", "extlib.jar", "-C", "build", "extlib"]) +run_codeql_database_create(["javac JavaUser.java -cp extlib.jar", "kotlinc KotlinUser.kt -cp extlib.jar"], lang="java") diff --git a/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/test.ql b/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/test.ql new file mode 100644 index 00000000000..6416917a38b --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/raw_generic_types/test.ql @@ -0,0 +1,30 @@ +import java + +// Stop external filepaths from appearing in the results +class ClassOrInterfaceLocation extends ClassOrInterface { + override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { + exists(string fullPath | super.hasLocationInfo(fullPath, sl, sc, el, ec) | + if exists(this.getFile().getRelativePath()) + then path = fullPath + else path = fullPath.regexpReplaceAll(".*/", "/") + ) + } +} + +query predicate rawTypeSupertypes(RawType rt, RefType superType) { + rt.getFile().getURL().matches("%extlib%") and + rt.getASupertype() = superType +} + +query predicate rawTypeMethod(RefType rt, string name, string sig, string paramType, string retType) { + exists(Method m | m.getDeclaringType() = rt and rt.getName().matches("RawTypesInSignature%") | + name = m.getName() and + sig = m.getSignature() and + ( + if exists(m.getAParamType()) + then paramType = m.getAParamType().toString() + else paramType = "No parameter" + ) and + retType = m.getReturnType().toString() + ) +}