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

@@ -35,8 +35,8 @@ sourceSets {
"utils/versions/v_1_5_21/*.kt",
"utils/versions/v_1_5_31/*.kt",
"utils/versions/v_1_6_10/*.kt",
"utils/versions/v_1_7_0-RC/*.kt",
// "utils/versions/v_1_6_20/*.kt",
"utils/versions/v_1_6_20/*.kt",
// "utils/versions/v_1_7_0/*.kt",
]
}
}

View File

@@ -1,5 +1,5 @@
kotlin.code.style=official
kotlinVersion=1.6.20
kotlinVersion=1.7.0
GROUP=com.github.codeql
VERSION_NAME=0.0.1

View File

@@ -21,7 +21,7 @@ def version_string_to_tuple(version):
m = re.match(r'([0-9]+)\.([0-9]+)\.([0-9]+)(.*)', version)
return tuple([int(m.group(i)) for i in range(1, 4)] + [m.group(4)])
many_versions = [ '1.4.32', '1.5.0', '1.5.10', '1.5.21', '1.5.31', '1.6.10', '1.7.0-RC', '1.6.20' ]
many_versions = [ '1.4.32', '1.5.0', '1.5.10', '1.5.21', '1.5.31', '1.6.10', '1.6.20', '1.7.0' ]
many_versions_tuples = [version_string_to_tuple(v) for v in many_versions]

View File

@@ -6,9 +6,11 @@ import com.semmle.extractor.java.OdasaOutput
import com.semmle.util.data.StringDigestor
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.isFileClass
import org.jetbrains.kotlin.ir.util.packageFqName
import org.jetbrains.kotlin.ir.util.parentClassOrNull
import org.jetbrains.kotlin.name.FqName
import java.io.File
import java.util.ArrayList
import java.util.HashSet
@@ -16,18 +18,20 @@ import java.util.zip.GZIPOutputStream
class ExternalDeclExtractor(val logger: FileLogger, val invocationTrapFile: String, val sourceFilePath: String, val primitiveTypeMapping: PrimitiveTypeMapping, val pluginContext: IrPluginContext, val globalExtensionState: KotlinExtractorGlobalState, val diagnosticTrapWriter: TrapWriter) {
val externalDeclsDone = HashSet<IrDeclaration>()
val declBinaryNames = HashMap<IrDeclaration, String>()
val externalDeclsDone = HashSet<Pair<String, String>>()
val externalDeclWorkList = ArrayList<Pair<IrDeclaration, String>>()
val propertySignature = ";property"
val fieldSignature = ";field"
fun extractLater(d: IrDeclaration, signature: String): Boolean {
fun extractLater(d: IrDeclarationWithName, signature: String): Boolean {
if (d !is IrClass && !isExternalFileClassMember(d)) {
logger.errorElement("External declaration is neither a class, nor a top-level declaration", d)
return false
}
val ret = externalDeclsDone.add(d)
val declBinaryName = declBinaryNames.getOrPut(d) { getIrDeclBinaryName(d) }
val ret = externalDeclsDone.add(Pair(declBinaryName, signature))
if (ret) externalDeclWorkList.add(Pair(d, signature))
return ret
}

View File

@@ -41,7 +41,7 @@ open class KotlinFileExtractor(
globalExtensionState: KotlinExtractorGlobalState
): KotlinUsesExtractor(logger, tw, dependencyCollector, externalClassExtractor, primitiveTypeMapping, pluginContext, globalExtensionState) {
inline fun <T> with(kind: String, element: IrElement, f: () -> T): T {
private inline fun <T> with(kind: String, element: IrElement, f: () -> T): T {
val name = when (element) {
is IrFile -> element.name
is IrDeclarationWithName -> element.name.asString()
@@ -86,6 +86,7 @@ open class KotlinFileExtractor(
}
}
@OptIn(ObsoleteDescriptorBasedAPI::class)
private fun isFake(d: IrDeclarationWithVisibility): Boolean {
val visibility = d.visibility
if (visibility is DelegatedDescriptorVisibility && visibility.delegate == Visibilities.InvisibleFake) {
@@ -94,6 +95,9 @@ open class KotlinFileExtractor(
if (d.isFakeOverride) {
return true
}
if ((d as? IrFunction)?.descriptor?.isHiddenToOvercomeSignatureClash == true) {
return true
}
return false
}
@@ -367,6 +371,27 @@ open class KotlinFileExtractor(
tw.writeHasLocation(stmtId, locId)
}
fun extractObinitFunction(c: IrClass, parentId: Label<out DbClassorinterface>) {
// add method:
val obinitLabel = getObinitLabel(c)
val obinitId = tw.getLabelFor<DbMethod>(obinitLabel)
val returnType = useType(pluginContext.irBuiltIns.unitType, TypeContext.RETURN)
tw.writeMethods(obinitId, "<obinit>", "<obinit>()", returnType.javaResult.id, parentId, obinitId)
tw.writeMethodsKotlinType(obinitId, returnType.kotlinResult.id)
val locId = tw.getLocation(c)
tw.writeHasLocation(obinitId, locId)
addModifiers(obinitId, "private")
// add body:
val blockId = tw.getFreshIdLabel<DbBlock>()
tw.writeStmts_block(blockId, obinitId, 0, obinitId)
tw.writeHasLocation(blockId, locId)
extractDeclInitializers(c.declarations, false) { Pair(blockId, obinitId) }
}
fun extractClassSource(c: IrClass, extractDeclarations: Boolean, extractStaticInitializer: Boolean, extractPrivateMembers: Boolean, extractFunctionBodies: Boolean): Label<out DbClassorinterface> {
with("class source", c) {
DeclarationStackAdjuster(c).use {
@@ -421,6 +446,9 @@ open class KotlinFileExtractor(
addModifiers(instance.id, "public", "static", "final")
tw.writeClass_object(id.cast<DbClass>(), instance.id)
}
if (extractFunctionBodies && needsObinitFunction(c)) {
extractObinitFunction(c, id)
}
extractClassModifiers(c, id)
extractClassSupertypes(c, id, inReceiverContext = true) // inReceiverContext = true is specified to force extraction of member prototypes of base types
@@ -567,6 +595,8 @@ open class KotlinFileExtractor(
tw.writeMethods(clinitId, "<clinit>", "<clinit>()", returnType.javaResult.id, parentId, clinitId)
tw.writeMethodsKotlinType(clinitId, returnType.kotlinResult.id)
tw.writeCompiler_generated(clinitId, CompilerGeneratedKinds.CLASS_INITIALISATION_METHOD.kind)
val locId = tw.getWholeFileLocation()
tw.writeHasLocation(clinitId, locId)
@@ -704,12 +734,9 @@ open class KotlinFileExtractor(
val id =
idOverride
?: if (f.isLocalFunction())
getLocallyVisibleFunctionLabels(f).function
else
// If this is a class that would ordinarily be replaced by a Java equivalent (e.g. kotlin.Map -> java.util.Map),
// don't replace here, really extract the Kotlin version:
useFunction<DbCallable>(f, parentId, classTypeArgsIncludingOuterClasses, noReplace = true)
?: // If this is a class that would ordinarily be replaced by a Java equivalent (e.g. kotlin.Map -> java.util.Map),
// don't replace here, really extract the Kotlin version:
useFunction<DbCallable>(f, parentId, classTypeArgsIncludingOuterClasses, noReplace = true)
val sourceDeclaration =
if (typeSubstitution != null && idOverride == null)
@@ -755,6 +782,14 @@ open class KotlinFileExtractor(
val methodId = id.cast<DbMethod>()
tw.writeMethods(methodId, shortName.nameInDB, "${shortName.nameInDB}$paramsSignature", returnType.javaResult.id, parentId, sourceDeclaration.cast<DbMethod>())
tw.writeMethodsKotlinType(methodId, returnType.kotlinResult.id)
when (f.origin) {
IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER ->
tw.writeCompiler_generated(methodId, CompilerGeneratedKinds.GENERATED_DATA_CLASS_MEMBER.kind)
IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR ->
tw.writeCompiler_generated(methodId, CompilerGeneratedKinds.DEFAULT_PROPERTY_ACCESSOR.kind)
IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER ->
tw.writeCompiler_generated(methodId, CompilerGeneratedKinds.ENUM_CLASS_SPECIAL_MEMBER.kind)
}
if (extractMethodAndParameterTypeAccesses) {
extractTypeAccessRecursive(substReturnType, locId, id, -1)
@@ -1045,7 +1080,7 @@ open class KotlinFileExtractor(
tw.writeKtLocalFunction(ids.function)
if (s.origin == IrDeclarationOrigin.ADAPTER_FOR_CALLABLE_REFERENCE) {
tw.writeCompiler_generated(classId, 1)
tw.writeCompiler_generated(classId, CompilerGeneratedKinds.DECLARING_CLASSES_OF_ADAPTER_FUNCTIONS.kind)
}
} else {
logger.errorElement("Expected to find local function", s)
@@ -2101,6 +2136,22 @@ open class KotlinFileExtractor(
enclosingStmt: Label<out DbStmt>
): Label<DbNewexpr> = extractNewExpr(useFunction<DbConstructor>(calledConstructor, constructorTypeArgs), constructedType, locId, parent, idx, callable, enclosingStmt)
private fun needsObinitFunction(c: IrClass) = c.primaryConstructor == null && c.constructors.count() > 1
private fun getObinitLabel(c: IrClass) = getFunctionLabel(
c,
null,
"<obinit>",
listOf(),
pluginContext.irBuiltIns.unitType,
null,
functionTypeParameters = listOf(),
classTypeArgsIncludingOuterClasses = listOf(),
overridesCollectionsMethod = false,
javaSignature = null,
addParameterWildcardsByDefault = false
)
private fun extractConstructorCall(
e: IrFunctionAccessExpression,
parent: Label<out DbExprparent>,
@@ -2153,8 +2204,6 @@ open class KotlinFileExtractor(
}
}
private val loopIdMap: MutableMap<IrLoop, Label<out DbKtloopstmt>> = mutableMapOf()
// todo: calculating the enclosing ref type could be done through this, instead of walking up the declaration parent chain
private val declarationStack: Stack<IrDeclaration> = Stack()
@@ -2192,7 +2241,7 @@ open class KotlinFileExtractor(
}
}
fun getStatementOriginOperator(origin: IrStatementOrigin?) = when (origin) {
private fun getStatementOriginOperator(origin: IrStatementOrigin?) = when (origin) {
IrStatementOrigin.PLUSEQ -> "plus"
IrStatementOrigin.MINUSEQ -> "minus"
IrStatementOrigin.MULTEQ -> "times"
@@ -2402,41 +2451,35 @@ open class KotlinFileExtractor(
}
}
is IrWhileLoop -> {
val stmtParent = parent.stmt(e, callable)
val id = tw.getFreshIdLabel<DbWhilestmt>()
loopIdMap[e] = id
val locId = tw.getLocation(e)
tw.writeStmts_whilestmt(id, stmtParent.parent, stmtParent.idx, callable)
tw.writeHasLocation(id, locId)
extractExpressionExpr(e.condition, callable, id, 0, id)
val body = e.body
if(body != null) {
extractExpressionStmt(body, callable, id, 1)
}
loopIdMap.remove(e)
extractLoop(e, parent, callable)
}
is IrDoWhileLoop -> {
val stmtParent = parent.stmt(e, callable)
val id = tw.getFreshIdLabel<DbDostmt>()
loopIdMap[e] = id
val locId = tw.getLocation(e)
tw.writeStmts_dostmt(id, stmtParent.parent, stmtParent.idx, callable)
tw.writeHasLocation(id, locId)
extractExpressionExpr(e.condition, callable, id, 0, id)
val body = e.body
if(body != null) {
extractExpressionStmt(body, callable, id, 1)
}
loopIdMap.remove(e)
extractLoop(e, parent, callable)
}
is IrInstanceInitializerCall -> {
val stmtParent = parent.stmt(e, callable)
val irConstructor = declarationStack.peek() as? IrConstructor
if (irConstructor == null) {
logger.errorElement("IrInstanceInitializerCall outside constructor", e)
return
}
extractInstanceInitializerBlock(stmtParent, irConstructor)
if (needsObinitFunction(irConstructor.parentAsClass)) {
val exprParent = parent.expr(e, callable)
val id = tw.getFreshIdLabel<DbMethodaccess>()
val type = useType(pluginContext.irBuiltIns.unitType)
val locId = tw.getLocation(e)
val methodLabel = getObinitLabel(irConstructor.parentAsClass)
val methodId = tw.getLabelFor<DbMethod>(methodLabel)
tw.writeExprs_methodaccess(id, type.javaResult.id, exprParent.parent, exprParent.idx)
tw.writeExprsKotlinType(id, type.kotlinResult.id)
tw.writeHasLocation(id, locId)
tw.writeCallableEnclosingExpr(id, callable)
tw.writeStatementEnclosingExpr(id, exprParent.enclosingStmt)
tw.writeCallableBinding(id, methodId)
}
else {
val stmtParent = parent.stmt(e, callable)
extractInstanceInitializerBlock(stmtParent, irConstructor)
}
}
is IrConstructorCall -> {
val exprParent = parent.expr(e, callable)
@@ -2928,6 +2971,49 @@ open class KotlinFileExtractor(
}
}
private fun extractLoop(
loop: IrLoop,
stmtExprParent: StmtExprParent,
callable: Label<out DbCallable>
) {
val stmtParent = stmtExprParent.stmt(loop, callable)
val locId = tw.getLocation(loop)
val idx: Int
val parent: Label<out DbStmtparent>
val label = loop.label
if (label != null) {
val labeledStmt = tw.getFreshIdLabel<DbLabeledstmt>()
tw.writeStmts_labeledstmt(labeledStmt, stmtParent.parent, stmtParent.idx, callable)
tw.writeHasLocation(labeledStmt, locId)
tw.writeNamestrings(label, "", labeledStmt)
idx = 0
parent = labeledStmt
} else {
idx = stmtParent.idx
parent = stmtParent.parent
}
val id = if (loop is IrWhileLoop) {
val id = tw.getFreshIdLabel<DbWhilestmt>()
tw.writeStmts_whilestmt(id, parent, idx, callable)
id
} else {
val id = tw.getFreshIdLabel<DbDostmt>()
tw.writeStmts_dostmt(id, parent, idx, callable)
id
}
tw.writeHasLocation(id, locId)
extractExpressionExpr(loop.condition, callable, id, 0, id)
val body = loop.body
if (body != null) {
extractExpressionStmt(body, callable, id, 1)
}
}
private fun IrValueParameter.isExtensionReceiver(): Boolean {
val parentFun = parent as? IrFunction ?: return false
return parentFun.extensionReceiverParameter == this
@@ -4201,7 +4287,7 @@ open class KotlinFileExtractor(
private fun extractBreakContinue(
e: IrBreakContinue,
id: Label<out DbBreakcontinuestmt>
id: Label<out DbNamedexprorstmt>
) {
with("break/continue", e) {
val locId = tw.getLocation(e)
@@ -4210,14 +4296,6 @@ open class KotlinFileExtractor(
if (label != null) {
tw.writeNamestrings(label, "", id)
}
val loopId = loopIdMap[e.loop]
if (loopId == null) {
logger.errorElement("Missing break/continue target", e)
return
}
tw.writeKtBreakContinueTargets(id, loopId)
}
}
@@ -4299,4 +4377,12 @@ open class KotlinFileExtractor(
declarationStack.pop()
}
}
private enum class CompilerGeneratedKinds(val kind: Int) {
DECLARING_CLASSES_OF_ADAPTER_FUNCTIONS(1),
GENERATED_DATA_CLASS_MEMBER(2),
DEFAULT_PROPERTY_ACCESSOR(3),
CLASS_INITIALISATION_METHOD(4),
ENUM_CLASS_SPECIAL_MEMBER(5)
}
}

View File

@@ -190,7 +190,7 @@ open class KotlinUsesExtractor(
}
// The Kotlin compiler internal representation of Outer<A, B>.Inner<C, D>.InnerInner<E, F>.someFunction<G, H>.LocalClass<I, J> is LocalClass<I, J, G, H, E, F, C, D, A, B>. This function returns [A, B, C, D, E, F, G, H, I, J].
fun orderTypeArgsLeftToRight(c: IrClass, argsIncludingOuterClasses: List<IrTypeArgument>?): List<IrTypeArgument>? {
private fun orderTypeArgsLeftToRight(c: IrClass, argsIncludingOuterClasses: List<IrTypeArgument>?): List<IrTypeArgument>? {
if(argsIncludingOuterClasses.isNullOrEmpty())
return argsIncludingOuterClasses
val ret = ArrayList<IrTypeArgument>()
@@ -237,7 +237,7 @@ open class KotlinUsesExtractor(
return UseClassInstanceResult(classTypeResult, extractClass)
}
fun isArray(t: IrSimpleType) = t.isBoxedArray || t.isPrimitiveArray()
private fun isArray(t: IrSimpleType) = t.isBoxedArray || t.isPrimitiveArray()
fun extractClassLaterIfExternal(c: IrClass) {
if (isExternalDeclaration(c)) {
@@ -1146,15 +1146,6 @@ open class KotlinUsesExtractor(
return res
}
fun <T: DbCallable> useFunctionCommon(f: IrFunction, label: String): Label<out T> {
val id: Label<T> = tw.getLabelFor(label)
if (isExternalDeclaration(f)) {
extractFunctionLaterIfExternalFileMember(f)
extractExternalEnclosingClassLater(f)
}
return id
}
// These are classes with Java equivalents, but whose methods don't all exist on those Java equivalents--
// for example, the numeric classes define arithmetic functions (Int.plus, Long.or and so on) that lower to
// primitive arithmetic on the JVM, but which we extract as calls to reflect the source syntax more closely.
@@ -1210,20 +1201,24 @@ open class KotlinUsesExtractor(
} as IrFunction? ?: f
fun <T: DbCallable> useFunction(f: IrFunction, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>? = null, noReplace: Boolean = false): Label<out T> {
return useFunction(f, null, classTypeArgsIncludingOuterClasses, noReplace)
}
fun <T: DbCallable> useFunction(f: IrFunction, parentId: Label<out DbElement>?, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?, noReplace: Boolean = false): Label<out T> {
if (f.isLocalFunction()) {
val ids = getLocallyVisibleFunctionLabels(f)
return ids.function.cast<T>()
} else {
val realFunction = kotlinFunctionToJavaEquivalent(f, noReplace)
return useFunctionCommon<T>(realFunction, getFunctionLabel(realFunction, classTypeArgsIncludingOuterClasses))
}
val javaFun = kotlinFunctionToJavaEquivalent(f, noReplace)
val label = getFunctionLabel(javaFun, parentId, classTypeArgsIncludingOuterClasses)
val id: Label<T> = tw.getLabelFor(label)
if (isExternalDeclaration(javaFun)) {
extractFunctionLaterIfExternalFileMember(javaFun)
extractExternalEnclosingClassLater(javaFun)
}
return id
}
fun <T: DbCallable> useFunction(f: IrFunction, parentId: Label<out DbElement>, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?, noReplace: Boolean = false) =
kotlinFunctionToJavaEquivalent(f, noReplace).let {
useFunctionCommon<T>(it, getFunctionLabel(it, parentId, classTypeArgsIncludingOuterClasses))
}
fun getTypeArgumentLabel(
arg: IrTypeArgument
): TypeResult<DbReftype> {
@@ -1464,7 +1459,7 @@ open class KotlinUsesExtractor(
return t
}
fun eraseTypeParameter(t: IrTypeParameter) =
private fun eraseTypeParameter(t: IrTypeParameter) =
erase(t.superTypes[0])
/**

View File

@@ -1,14 +1,21 @@
package com.github.codeql
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IdSignatureValues
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.name.FqName
class PrimitiveTypeMapping(val logger: Logger, val pluginContext: IrPluginContext) {
fun getPrimitiveInfo(s: IrSimpleType) = mapping[s.classifier.signature]
fun getPrimitiveInfo(s: IrSimpleType) =
s.classOrNull?.let {
if ((it.owner.parent as? IrPackageFragment)?.fqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME)
mapping[it.owner.name]
else
null
}
data class PrimitiveTypeInfo(
val primitiveName: String?,
@@ -60,25 +67,25 @@ class PrimitiveTypeMapping(val logger: Logger, val pluginContext: IrPluginContex
val javaLangVoid = findClass("java.lang.Void", kotlinNothing)
mapOf(
IdSignatureValues._byte to PrimitiveTypeInfo("byte", true, javaLangByte, "kotlin", "Byte"),
IdSignatureValues._short to PrimitiveTypeInfo("short", true, javaLangShort, "kotlin", "Short"),
IdSignatureValues._int to PrimitiveTypeInfo("int", true, javaLangInteger, "kotlin", "Int"),
IdSignatureValues._long to PrimitiveTypeInfo("long", true, javaLangLong, "kotlin", "Long"),
StandardNames.FqNames._byte.shortName() to PrimitiveTypeInfo("byte", true, javaLangByte, "kotlin", "Byte"),
StandardNames.FqNames._short.shortName() to PrimitiveTypeInfo("short", true, javaLangShort, "kotlin", "Short"),
StandardNames.FqNames._int.shortName() to PrimitiveTypeInfo("int", true, javaLangInteger, "kotlin", "Int"),
StandardNames.FqNames._long.shortName() to PrimitiveTypeInfo("long", true, javaLangLong, "kotlin", "Long"),
IdSignatureValues.uByte to PrimitiveTypeInfo("byte", true, kotlinUByte, "kotlin", "UByte"),
IdSignatureValues.uShort to PrimitiveTypeInfo("short", true, kotlinUShort, "kotlin", "UShort"),
IdSignatureValues.uInt to PrimitiveTypeInfo("int", true, kotlinUInt, "kotlin", "UInt"),
IdSignatureValues.uLong to PrimitiveTypeInfo("long", true, kotlinULong, "kotlin", "ULong"),
StandardNames.FqNames.uByteFqName.shortName() to PrimitiveTypeInfo("byte", true, kotlinUByte, "kotlin", "UByte"),
StandardNames.FqNames.uShortFqName.shortName() to PrimitiveTypeInfo("short", true, kotlinUShort, "kotlin", "UShort"),
StandardNames.FqNames.uIntFqName.shortName() to PrimitiveTypeInfo("int", true, kotlinUInt, "kotlin", "UInt"),
StandardNames.FqNames.uLongFqName.shortName() to PrimitiveTypeInfo("long", true, kotlinULong, "kotlin", "ULong"),
IdSignatureValues._double to PrimitiveTypeInfo("double", true, javaLangDouble, "kotlin", "Double"),
IdSignatureValues._float to PrimitiveTypeInfo("float", true, javaLangFloat, "kotlin", "Float"),
StandardNames.FqNames._double.shortName() to PrimitiveTypeInfo("double", true, javaLangDouble, "kotlin", "Double"),
StandardNames.FqNames._float.shortName() to PrimitiveTypeInfo("float", true, javaLangFloat, "kotlin", "Float"),
IdSignatureValues._boolean to PrimitiveTypeInfo("boolean", true, javaLangBoolean, "kotlin", "Boolean"),
StandardNames.FqNames._boolean.shortName() to PrimitiveTypeInfo("boolean", true, javaLangBoolean, "kotlin", "Boolean"),
IdSignatureValues._char to PrimitiveTypeInfo("char", true, javaLangCharacter, "kotlin", "Char"),
StandardNames.FqNames._char.shortName() to PrimitiveTypeInfo("char", true, javaLangCharacter, "kotlin", "Char"),
IdSignatureValues.unit to PrimitiveTypeInfo("void", false, kotlinUnit, "kotlin", "Unit"),
IdSignatureValues.nothing to PrimitiveTypeInfo(null, true, javaLangVoid, "kotlin", "Nothing"),
StandardNames.FqNames.unit.shortName() to PrimitiveTypeInfo("void", false, kotlinUnit, "kotlin", "Unit"),
StandardNames.FqNames.nothing.shortName() to PrimitiveTypeInfo(null, true, javaLangVoid, "kotlin", "Nothing"),
)
}()
}

View File

@@ -40,4 +40,4 @@ fun AutoCloseable?.closeFinallyAC(cause: Throwable?) = when {
} catch (closeException: Throwable) {
cause.addSuppressed(closeException)
}
}
}

View File

@@ -207,20 +207,6 @@ open class LoggerBase(val logCounter: LogCounter) {
}
open class Logger(val loggerBase: LoggerBase, open val tw: TrapWriter) {
private fun getDiagnosticLocation(): String? {
val st = Exception().stackTrace
for(x in st) {
when(x.className) {
"com.github.codeql.Logger",
"com.github.codeql.FileLogger" -> {}
else -> {
return x.toString()
}
}
}
return null
}
fun flush() {
tw.flush()
loggerBase.flush()
@@ -240,7 +226,7 @@ open class Logger(val loggerBase: LoggerBase, open val tw: TrapWriter) {
loggerBase.info(tw, msg)
}
fun warn(msg: String, extraInfo: String?) {
private fun warn(msg: String, extraInfo: String?) {
loggerBase.warn(tw, msg, extraInfo)
}
fun warn(msg: String, exn: Throwable) {
@@ -250,7 +236,7 @@ open class Logger(val loggerBase: LoggerBase, open val tw: TrapWriter) {
warn(msg, null)
}
fun error(msg: String, extraInfo: String?) {
private fun error(msg: String, extraInfo: String?) {
loggerBase.error(tw, msg, extraInfo)
}
fun error(msg: String) {

View File

@@ -1,9 +0,0 @@
package com.github.codeql.utils.versions
import com.github.codeql.KotlinUsesExtractor
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
fun <TIrStub> KotlinUsesExtractor.getIrStubFromDescriptor(generateStub: (DeclarationStubGenerator) -> TIrStub) : TIrStub? {
logger.error("Descriptors not yet supported for Kotlin 1.7")
return null
}

View File

@@ -0,0 +1,27 @@
package com.github.codeql.utils.versions
import com.github.codeql.KotlinUsesExtractor
import org.jetbrains.kotlin.backend.common.serialization.DescriptorByIdSignatureFinderImpl
import org.jetbrains.kotlin.idea.MainFunctionDetector
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmDescriptorMangler
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.psi2ir.generators.DeclarationStubGeneratorImpl
@OptIn(ObsoleteDescriptorBasedAPI::class)
fun <TIrStub> KotlinUsesExtractor.getIrStubFromDescriptor(generateStub: (DeclarationStubGenerator) -> TIrStub) : TIrStub? =
(pluginContext.symbolTable as? SymbolTable) ?.let {
// Copying the construction seen in JvmIrLinker.kt
val mangler = JvmDescriptorMangler(MainFunctionDetector(pluginContext.bindingContext, pluginContext.languageVersionSettings))
val descriptorFinder = DescriptorByIdSignatureFinderImpl(
pluginContext.moduleDescriptor,
mangler,
DescriptorByIdSignatureFinderImpl.LookupMode.MODULE_ONLY
)
val stubGenerator = DeclarationStubGeneratorImpl(pluginContext.moduleDescriptor, it, pluginContext.irBuiltIns, descriptorFinder)
generateStub(stubGenerator)
} ?: run {
logger.error("Plugin context has no symbol table, couldn't get IR stub")
null
}

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

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