Merge branch 'main' into post-release-prep/codeql-cli-2.10.0

This commit is contained in:
Asger F
2022-06-27 20:37:25 +02:00
committed by GitHub
331 changed files with 13701 additions and 4340 deletions

View File

@@ -1,5 +1,10 @@
import java
from MethodAccess ma
where not exists(ma.getQualifier()) and ma.getFile().isKotlinSourceFile()
// Generally Kotlin calls will always use an explicit qualifier, except for calls
// to the synthetic instance initializer <obinit>, which use an implicit `this`.
where
not exists(ma.getQualifier()) and
ma.getFile().isKotlinSourceFile() and
not ma.getCallee() instanceof InstanceInitializer
select ma

View File

@@ -0,0 +1,83 @@
a.kt:
# 0| [CompilationUnit] a
# 1| 1: [Class] A
# 0| 1: [Method] <fn>
# 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] <fn>
# 0| 3: [TypeAccess] int
# 0| 5: [BlockStmt] { ... }
# 0| 0: [ReturnStmt] return ...
# 0| 0: [UnsafeCoerceExpr] <unsafe coerce>
# 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] <fn>
# 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] <fn_ArrayListAdd>
# 0| 3: [TypeAccess] boolean
# 0| 5: [BlockStmt] { ... }
# 0| 0: [ReturnStmt] return ...
# 0| 0: [MethodAccess] add(...)
# 0| -1: [ClassInstanceExpr] new ArrayList<Object>(...)
# 0| -3: [TypeAccess] ArrayList<Object>
# 0| 0: [IntegerLiteral] 1
# 0| 0: [NullLiteral] null
# 0| 1: [Method] <fn_LinkedHashMap>
# 0| 3: [TypeAccess] Object
# 0| 5: [BlockStmt] { ... }
# 0| 0: [ReturnStmt] return ...
# 0| 0: [MethodAccess] put(...)
# 0| -1: [ClassInstanceExpr] new LinkedHashMap<Object,Object>(...)
# 0| -3: [TypeAccess] LinkedHashMap<Object,Object>
# 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] { ... }

View File

@@ -0,0 +1 @@
semmle/code/java/PrintAst.ql

View File

@@ -0,0 +1,3 @@
class A {
fun f1() = 1
}

View File

@@ -0,0 +1,2 @@
class B {
}

View File

@@ -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)

View File

@@ -0,0 +1 @@
class C { }

View File

@@ -0,0 +1 @@
class D { }

View File

@@ -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 |

View File

@@ -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

View File

@@ -0,0 +1 @@
class E { }

View File

@@ -0,0 +1,7 @@
| a.kt:0:0:0:0 | <fn> | has body |
| a.kt:2:5:2:16 | f1 | has body |
| b.kt:0:0:0:0 | <fn> | has body |
| c.kt:0:0:0:0 | <fn> | has body |
| d.kt:0:0:0:0 | <clinit> | has body |
| e.kt:0:0:0:0 | <fn_ArrayListAdd> | has body |
| e.kt:0:0:0:0 | <fn_LinkedHashMap> | has body |

View File

@@ -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

View File

@@ -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("<unsafe-coerce>")
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("<fn_ArrayListAdd>")
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("<fn_LinkedHashMap>")
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("<fn>")
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("<fn>")
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("<fn>")
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)
}
}

View File

@@ -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 |

View File

@@ -0,0 +1,5 @@
import java
from ClassOrInterface ci
where not exists(ci.getASupertype())
select ci.getPackage(), ci.toString()

View File

@@ -0,0 +1 @@
| d.kt:0:0:0:0 | bar | d.kt:0:0:0:0 | Foobar |

View File

@@ -0,0 +1,5 @@
import java
from Field f, Expr init
where init = f.getInitializer()
select f, init

View File

@@ -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")

View File

@@ -0,0 +1,2 @@
libraryPathDependencies:
- codeql-java

View File

@@ -0,0 +1,8 @@
package extlib;
public class BoundedGenericTest<T extends CharSequence> {
public void method(T t) { }
}

View File

@@ -0,0 +1,8 @@
package extlib;
public class ComplexBoundedGenericTest<A extends CharSequence, B extends A> {
public void method(A a, B b) { }
}

View File

@@ -0,0 +1,10 @@
package extlib;
public class GenericTest<T> {
public void method(T t) { }
public void takesSelfMethod(GenericTest<T> selfLike) { }
}

View File

@@ -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<String> simpleGeneric,
BoundedGenericTest<String> boundedGeneric,
ComplexBoundedGenericTest<CharSequence, String> complexBoundedGeneric,
int[] primitiveArray,
Integer[] boxedTypeArray,
int [][] multiDimensionalPrimitiveArray,
Integer[][] multiDimensionalBoxedTypeArray,
List<String>[] genericTypeArray,
List<? extends CharSequence> producerWildcard,
List<? super CharSequence> consumerWildcard,
List<? extends List<? extends CharSequence>> nestedWildcard,
List<?> unboundedWildcard) { }
public List<Integer> returnErasureTest() { return null; }
public <T> void paramErasureTest(List<String> param) { }
}

View File

@@ -0,0 +1,52 @@
parameterTypes
| extlib.jar/extlib/GenericTest.class:0:0:0:0 | p0 | GenericTest<String> |
| 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<String> |
| javasrc/extlib/Lib.java:18:5:18:45 | boundedGeneric | BoundedGenericTest<String> |
| javasrc/extlib/Lib.java:19:5:19:73 | complexBoundedGeneric | ComplexBoundedGenericTest<CharSequence,String> |
| 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<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<? extends CharSequence>> |
| 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<String>[] | List<String> | 1 | List<String> |
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<? extends CharSequence> | upper | List<? extends CharSequence> |
| 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> | String |
| javasrc/extlib/GenericTest.java:7:31:7:53 | selfLike | GenericTest | T |
| javasrc/extlib/Lib.java:17:5:17:37 | simpleGeneric | GenericTest<String> | String |
| javasrc/extlib/Lib.java:18:5:18:45 | boundedGeneric | BoundedGenericTest<String> | String |
| javasrc/extlib/Lib.java:19:5:19:73 | complexBoundedGeneric | ComplexBoundedGenericTest<CharSequence,String> | CharSequence |
| javasrc/extlib/Lib.java:19:5:19:73 | complexBoundedGeneric | ComplexBoundedGenericTest<CharSequence,String> | String |
| javasrc/extlib/Lib.java:25:5:25:49 | producerWildcard | List<? extends CharSequence> | ? extends CharSequence |
| javasrc/extlib/Lib.java:26:5:26:47 | consumerWildcard | List<? super CharSequence> | ? super CharSequence |
| javasrc/extlib/Lib.java:27:5:27:63 | nestedWildcard | List<? extends List<? extends CharSequence>> | ? extends List<? extends CharSequence> |
| 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 |

View File

@@ -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") }

View File

@@ -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")

View File

@@ -0,0 +1,45 @@
import extlib.*
import java.util.*
fun test() {
// Pending better varargs support, avoiding listOf and mutableListOf
val stringList = ArrayList<String>()
val objectList = ArrayList<Any>()
val stringStringList = ArrayList<ArrayList<String>>()
val lib = Lib()
lib.testParameterTypes(
'a',
1,
2,
3,
4,
5.0f,
6.0,
true,
Lib(),
GenericTest<String>(),
BoundedGenericTest<String>(),
ComplexBoundedGenericTest<CharSequence, String>(),
intArrayOf(1),
arrayOf(1),
arrayOf(intArrayOf(1)),
arrayOf(arrayOf(1)),
arrayOf(stringList),
stringList,
objectList,
stringStringList,
objectList)
val returnedList = lib.returnErasureTest()
lib.paramErasureTest<Int>(listOf("Hello"))
// Check trap labelling consistency for methods that instantiate a generic type
// with its own generic parameters -- for example, class MyList<T> { void addAll(MyList<T> l) { } },
// which has the trap labelling oddity of looking like plain MyList, not MyList<T>, even though
// this is a generic instantiation.
val takesSelfTest = GenericTest<String>()
takesSelfTest.takesSelfMethod(takesSelfTest)
}

View File

@@ -0,0 +1 @@
class KotlinDefault {}

View File

@@ -0,0 +1 @@
class KotlinDisabled {}

View File

@@ -0,0 +1 @@
class KotlinEnabled {}

View File

@@ -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"])

View File

@@ -0,0 +1 @@
| KotlinEnabled.kt:1:1:1:22 | KotlinEnabled |

View File

@@ -0,0 +1,5 @@
import java
from Class c
where c.fromSource()
select c

View File

@@ -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")

View File

@@ -0,0 +1,2 @@
| code/A.kt:2:1:2:10 | A |
| code/C.kt:2:1:2:10 | C |

View File

@@ -0,0 +1,5 @@
import java
from Class c
where c.fromSource()
select c

View File

@@ -0,0 +1,3 @@
class A {}

View File

@@ -0,0 +1,3 @@
class B {}

View File

@@ -0,0 +1,3 @@
class C {}

View File

@@ -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', ])

View File

@@ -0,0 +1,3 @@
| <compilation> | 0 | code/A.kt:0:0:0:0 | A | Extraction successful | Not recoverable errors | Not non-recoverable errors |
| <compilation> | 1 | code/B.kt:0:0:0:0 | code/B.kt | Not extraction successful | Not recoverable errors | Non-recoverable errors |
| <compilation> | 2 | code/C.kt:0:0:0:0 | C | Extraction successful | Not recoverable errors | Not non-recoverable errors |

View File

@@ -0,0 +1,24 @@
import java
class AnonymousCompilation extends Compilation {
override string toString() { result = "<compilation>" }
}
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"
)

View File

@@ -0,0 +1 @@
| <compilation> | Normal termination | Not extraction successful | Not recoverable errors | Non-recoverable errors |

View File

@@ -0,0 +1,24 @@
import java
class AnonymousCompilation extends Compilation {
override string toString() { result = "<compilation>" }
}
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"
)

View File

@@ -0,0 +1,7 @@
import sys
from create_database_utils import *
run_codeql_database_create(
['"%s" build.py' % sys.executable],
source="code", lang="java")

View File

@@ -0,0 +1,25 @@
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Kotlin application project to get you started.
* For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
* User Manual available at https://docs.gradle.org/7.0.2/userguide/building_java_projects.html
*/
plugins {
// Apply the org.jetbrains.kotlin.jvm Plugin to add support for Kotlin.
id 'org.jetbrains.kotlin.jvm' version '1.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'
}

View File

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

View File

@@ -0,0 +1,3 @@
import java
select count(Compilation c)

View File

@@ -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 |

View File

@@ -0,0 +1,5 @@
import java
from Method m
where exists(m.getFile().getRelativePath())
select m

View File

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

View File

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

View File

@@ -0,0 +1,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] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 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<Project>
# 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] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 7| 0: [WhenExpr] when ...
# 7| 0: [WhenBranch] ... -> ...
# 7| 0: [ValueEQExpr] ... (value equals) ...
# 7| 0: [VarAccess] tmp2_index
# 7| 1: [IntegerLiteral] -1
# 7| 1: [ExprStmt] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 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] <Expr>;
# 7| 0: [MethodAccess] addElement(...)
# 7| -1: [VarAccess] tmp0_serialDesc
# 7| 0: [StringLiteral] name
# 7| 1: [BooleanLiteral] false
# 7| 2: [ExprStmt] <Expr>;
# 7| 0: [MethodAccess] addElement(...)
# 7| -1: [VarAccess] tmp0_serialDesc
# 7| 0: [StringLiteral] language
# 7| 1: [BooleanLiteral] false
# 7| 3: [ExprStmt] <Expr>;
# 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] <Expr>;
# 8| 0: [KtInitializerAssignExpr] ...=...
# 8| 0: [VarAccess] name
# 8| 1: [ExprStmt] <Expr>;
# 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

View File

@@ -0,0 +1 @@
semmle/code/java/PrintAst.ql

View File

@@ -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"
}

View File

@@ -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)

View File

@@ -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 |

View File

@@ -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

View File

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

View File

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

View File

@@ -0,0 +1,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 |

View File

@@ -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")

View File

@@ -0,0 +1,5 @@
import java
from Method m
where m.getName() = "memberOnlySeenByKotlin"
select m, m.getDeclaringType().getName()

View File

@@ -0,0 +1 @@
public class J<T> { }

View File

@@ -0,0 +1 @@
fun user1(j: J<Int>) { }

View File

@@ -0,0 +1 @@
fun user2(j: J<String>) { }

View File

@@ -0,0 +1,3 @@
| J.java:1:14:1:14 | J |
| build/J.class:0:0:0:0 | J<String> |
| file:///!unknown-binary-location/J.class:0:0:0:0 | J<Integer> |

View File

@@ -0,0 +1,5 @@
import java
from Class c
where c.getSourceDeclaration().getName() = "J"
select c

View File

@@ -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")

View File

@@ -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) { }

View File

@@ -0,0 +1 @@
| <prefix>/abcdefghij/abcdefghij/abcdefghij/abcdefghij/abcdefghij/abcdefghij/abcdefghij/abcdefghij/abcdefghij/abcdefghij/LongsigKt.class:0:0:0:0 | f |

View File

@@ -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")

View File

@@ -0,0 +1,7 @@
import java
from Method m
where m.getDeclaringType().getName() = "LongsigKt"
select m.getLocation()
.toString()
.regexpReplaceAll(".*(extlib.jar|!unknown-binary-location)/", "<prefix>/"), m.toString()

View File

@@ -0,0 +1,7 @@
import abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.abcdefghij.*
fun user() {
f(Param(), Param(), Param(), Param(), Param())
}

View File

@@ -0,0 +1,18 @@
public class JavaDefns {
// Currently known not to work: the Comparable<? extends X> 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<CharSequence> invar, Comparable<? super CharSequence> contravar) { }
public static void takesNestedComparable(Comparable<Comparable<? super CharSequence>> innerContravar, Comparable<? super Comparable<CharSequence>> outerContravar) { }
public static void takesArrayOfComparable(Comparable<CharSequence>[] invar, Comparable<? super CharSequence>[] contravar) { }
public static Comparable<? super CharSequence> returnsWildcard() { return null; }
public static Comparable<CharSequence> returnsInvariant() { return null; }
public JavaDefns(Comparable<CharSequence> invar, Comparable<? super CharSequence> contravar) { }
}

View File

@@ -0,0 +1,54 @@
import java.util.List;
public class JavaUser {
public static void test() {
KotlinDefns kd = new KotlinDefns();
kd.takesInvariantType((List<CharSequence>)null, (List<? extends CharSequence>)null, (List<? super CharSequence>)null);
kd.takesCovariantType((List<? extends CharSequence>)null, (List<? extends CharSequence>)null);
kd.takesContravariantType((Comparable<? super CharSequence>)null, (Comparable<? super CharSequence>)null);
kd.takesNestedType((List<List<CharSequence>>) null, (List<? extends List<? extends CharSequence>>)null, (Comparable<? super Comparable<? super CharSequence>>)null, (List<? extends Comparable<? super CharSequence>>)null, (Comparable<? super List<? extends CharSequence>>)null);
kd.takesFinalParameter((List<String>)null, (List<String>)null, (Comparable<? super String>)null);
kd.takesFinalParameterForceWildcard((List<String>)null, (List<? extends String>)null, (Comparable<? super String>)null);
kd.takesAnyParameter((List<Object>)null, (List<? extends Object>)null, (Comparable<Object>)null);
kd.takesAnyQParameter((List<Object>)null, (List<? extends Object>)null, (Comparable<Object>)null);
kd.takesAnyParameterForceWildcard((List<Object>)null, (List<? extends Object>)null, (Comparable<? super Object>)null);
kd.takesVariantTypesSuppressedWildcards((List<CharSequence>)null, (Comparable<CharSequence>)null);
List<CharSequence> r1 = kd.returnsInvar();
List<CharSequence> r2 = kd.returnsCovar();
Comparable<CharSequence> r3 = kd.returnsContravar();
List<? extends CharSequence> r4 = kd.returnsCovarForced();
Comparable<? super CharSequence> r5 = kd.returnsContravarForced();
KotlinDefnsSuppressedOuter kdso = new KotlinDefnsSuppressedOuter();
kdso.outerFn((List<CharSequence>)null, (Comparable<CharSequence>)null);
KotlinDefnsSuppressedOuter.Inner kdsoi = new KotlinDefnsSuppressedOuter.Inner();
kdsoi.innerFn((List<CharSequence>)null, (Comparable<CharSequence>)null);
KotlinDefnsSuppressedInner kdsi = new KotlinDefnsSuppressedInner();
kdsi.outerFn((List<? extends CharSequence>)null, (Comparable<? super CharSequence>)null);
KotlinDefnsSuppressedInner.Inner kdsii = new KotlinDefnsSuppressedInner.Inner();
kdsii.innerFn((List<CharSequence>)null, (Comparable<CharSequence>)null);
KotlinDefnsSuppressedFn kdsf = new KotlinDefnsSuppressedFn();
kdsf.outerFn((List<CharSequence>)null, (Comparable<CharSequence>)null);
}
}

View File

@@ -0,0 +1,78 @@
// Note throughout, using:
// MutableList as a type whose parameter is invariant
// List as a type whose parameter is covariant (List<out T>)
// Comparable as a type whose parameter is contravariant (Comparable<int T>)
// CharSequence as a non-final type
// String as a final type
class ComparableCs : Comparable<CharSequence> {
override fun compareTo(other: CharSequence): Int = 1
}
class KotlinDefns {
fun takesInvariantType(noUseSiteVariance: MutableList<CharSequence>, useSiteCovariant: MutableList<out CharSequence>, useSiteContravariant: MutableList<in CharSequence>) { }
// Note List<in CharSequence> is a static error (contradictory variance)
fun takesCovariantType(noUseSiteVariance: List<CharSequence>, useSiteCovariant: List<out CharSequence>) { }
// Note Comparable<out CharSequence> is a static error (contradictory variance)
fun takesContravariantType(noUseSiteVariance: Comparable<CharSequence>, useSiteContravariant: Comparable<in CharSequence>) { }
fun takesNestedType(invar: MutableList<MutableList<CharSequence>>, covar: List<List<CharSequence>>, contravar: Comparable<Comparable<CharSequence>>, mixed1: List<Comparable<CharSequence>>, mixed2: Comparable<List<CharSequence>>) { }
fun takesFinalParameter(invar: MutableList<String>, covar: List<String>, contravar: Comparable<String>) { }
fun takesFinalParameterForceWildcard(invar: MutableList<@JvmWildcard String>, covar: List<@JvmWildcard String>, contravar: Comparable<@JvmWildcard String>) { }
fun takesAnyParameter(invar: MutableList<Any>, covar: List<Any>, contravar: Comparable<Any>) { }
fun takesAnyQParameter(invar: MutableList<Any?>, covar: List<Any?>, contravar: Comparable<Any?>) { }
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<CharSequence> = mutableListOf()
fun returnsCovar(): List<CharSequence> = listOf()
fun returnsContravar(): Comparable<CharSequence> = ComparableCs()
fun returnsCovarForced(): List<@JvmWildcard CharSequence> = listOf()
fun returnsContravarForced(): Comparable<@JvmWildcard CharSequence> = ComparableCs()
}
@JvmSuppressWildcards
class KotlinDefnsSuppressedOuter {
fun outerFn(covar: List<CharSequence>, contravar: Comparable<CharSequence>) { }
class Inner {
fun innerFn(covar: List<CharSequence>, contravar: Comparable<CharSequence>) { }
}
}
class KotlinDefnsSuppressedInner {
fun outerFn(covar: List<CharSequence>, contravar: Comparable<CharSequence>) { }
@JvmSuppressWildcards
class Inner {
fun innerFn(covar: List<CharSequence>, contravar: Comparable<CharSequence>) { }
}
}
class KotlinDefnsSuppressedFn {
@JvmSuppressWildcards fun outerFn(covar: List<CharSequence>, contravar: Comparable<CharSequence>) { }
}

View File

@@ -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)
}

View File

@@ -0,0 +1,54 @@
| JavaDefns | JavaDefns | contravar | Comparable<? super CharSequence> |
| JavaDefns | JavaDefns | invar | Comparable<CharSequence> |
| JavaDefns | returnsInvariant | return | Comparable<CharSequence> |
| JavaDefns | returnsWildcard | return | Comparable<? super CharSequence> |
| JavaDefns | takesArrayOfComparable | contravar | Comparable<? super CharSequence>[] |
| JavaDefns | takesArrayOfComparable | invar | Comparable<CharSequence>[] |
| JavaDefns | takesComparable | contravar | Comparable<? super CharSequence> |
| JavaDefns | takesComparable | invar | Comparable<CharSequence> |
| JavaDefns | takesNestedComparable | innerContravar | Comparable<Comparable<? super CharSequence>> |
| JavaDefns | takesNestedComparable | outerContravar | Comparable<? super Comparable<CharSequence>> |
| KotlinDefns | returnsContravar | return | Comparable<CharSequence> |
| KotlinDefns | returnsContravarForced | return | Comparable<? super CharSequence> |
| KotlinDefns | returnsCovar | return | List<CharSequence> |
| KotlinDefns | returnsCovarForced | return | List<? extends CharSequence> |
| KotlinDefns | returnsInvar | return | List<CharSequence> |
| KotlinDefns | takesAnyParameter | contravar | Comparable<Object> |
| KotlinDefns | takesAnyParameter | covar | List<? extends Object> |
| KotlinDefns | takesAnyParameter | invar | List<Object> |
| KotlinDefns | takesAnyParameterForceWildcard | contravar | Comparable<? super Object> |
| KotlinDefns | takesAnyParameterForceWildcard | covar | List<? extends Object> |
| KotlinDefns | takesAnyParameterForceWildcard | invar | List<Object> |
| KotlinDefns | takesAnyQParameter | contravar | Comparable<Object> |
| KotlinDefns | takesAnyQParameter | covar | List<? extends Object> |
| KotlinDefns | takesAnyQParameter | invar | List<Object> |
| KotlinDefns | takesContravariantType | noUseSiteVariance | Comparable<? super CharSequence> |
| KotlinDefns | takesContravariantType | useSiteContravariant | Comparable<? super CharSequence> |
| KotlinDefns | takesCovariantType | noUseSiteVariance | List<? extends CharSequence> |
| KotlinDefns | takesCovariantType | useSiteCovariant | List<? extends CharSequence> |
| KotlinDefns | takesFinalParameter | contravar | Comparable<? super String> |
| KotlinDefns | takesFinalParameter | covar | List<String> |
| KotlinDefns | takesFinalParameter | invar | List<String> |
| KotlinDefns | takesFinalParameterForceWildcard | contravar | Comparable<? super String> |
| KotlinDefns | takesFinalParameterForceWildcard | covar | List<? extends String> |
| KotlinDefns | takesFinalParameterForceWildcard | invar | List<String> |
| KotlinDefns | takesInvariantType | noUseSiteVariance | List<CharSequence> |
| KotlinDefns | takesInvariantType | useSiteContravariant | List<? super CharSequence> |
| KotlinDefns | takesInvariantType | useSiteCovariant | List<? extends CharSequence> |
| KotlinDefns | takesNestedType | contravar | Comparable<? super Comparable<? super CharSequence>> |
| KotlinDefns | takesNestedType | covar | List<? extends List<? extends CharSequence>> |
| KotlinDefns | takesNestedType | invar | List<List<CharSequence>> |
| KotlinDefns | takesNestedType | mixed1 | List<? extends Comparable<? super CharSequence>> |
| KotlinDefns | takesNestedType | mixed2 | Comparable<? super List<? extends CharSequence>> |
| KotlinDefns | takesVariantTypesSuppressedWildcards | contravar | Comparable<CharSequence> |
| KotlinDefns | takesVariantTypesSuppressedWildcards | covar | List<CharSequence> |
| KotlinDefnsSuppressedFn | outerFn | contravar | Comparable<CharSequence> |
| KotlinDefnsSuppressedFn | outerFn | covar | List<CharSequence> |
| KotlinDefnsSuppressedInner | outerFn | contravar | Comparable<? super CharSequence> |
| KotlinDefnsSuppressedInner | outerFn | covar | List<? extends CharSequence> |
| KotlinDefnsSuppressedInner$Inner | innerFn | contravar | Comparable<CharSequence> |
| KotlinDefnsSuppressedInner$Inner | innerFn | covar | List<CharSequence> |
| KotlinDefnsSuppressedOuter | outerFn | contravar | Comparable<CharSequence> |
| KotlinDefnsSuppressedOuter | outerFn | covar | List<CharSequence> |
| KotlinDefnsSuppressedOuter$Inner | innerFn | contravar | Comparable<CharSequence> |
| KotlinDefnsSuppressedOuter$Inner | innerFn | covar | List<CharSequence> |

View File

@@ -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")

View File

@@ -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()

View File

@@ -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) { }
}

View File

@@ -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"
}
}

View File

@@ -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 | <set-?> : String | hasFields.kt:7:5:7:38 | lateinitField : String |
| hasFields.kt:7:14:7:38 | <set-?> : String | hasFields.kt:7:14:7:38 | <set-?> : 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 | <set-?> : 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 | <set-?> : String | semmle.label | <set-?> : String |
| hasFields.kt:7:14:7:38 | <set-?> : String | semmle.label | <set-?> : 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 |

View File

@@ -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")

View File

@@ -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"

View File

@@ -0,0 +1,9 @@
package foo.bar;
// import foo.bar.ClassB;
class ClassA {
fun f(b: ClassB) {
b.called();
}
}

View File

@@ -0,0 +1,8 @@
package foo.bar;
class ClassB {
fun called() {
}
fun notCalled() {
}
}

View File

@@ -0,0 +1,6 @@
#!/usr/bin/env python3
from create_database_utils import *
runSuccessfully(["kotlinc", "FileA.kt", "FileB.kt"])

View File

@@ -0,0 +1,3 @@
import java
select count(Compilation c)

View File

@@ -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 |

View File

@@ -0,0 +1,5 @@
import java
from Method m
where exists(m.getFile().getRelativePath())
select m

View File

@@ -0,0 +1,3 @@
from create_database_utils import *
run_codeql_database_create(['"%s" ./build.py' % sys.executable], lang="java")

View File

@@ -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()

View File

@@ -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', '<FILENAME>', 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"])

View File

@@ -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 <FILENAME> |
| 1 | 4 | CodeQL Kotlin extractor | INFO | Extracting file test.kt |
| 1 | 5 | CodeQL Kotlin extractor | INFO | Extraction completed |

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