mirror of
https://github.com/github/codeql.git
synced 2026-07-20 18:58:36 +02:00
Merge pull request #9122 from smowton/smowton/admin/update-kotlin
Kotlin: Apply changes since https://github.com/github/codeql/pull/9109 branched away from kotlin-main
This commit is contained in:
@@ -93,9 +93,9 @@ class ExternalDeclExtractor(val logger: FileLogger, val invocationTrapFile: Stri
|
||||
ftw.writeHasLocation(ftw.fileId, ftw.getWholeFileLocation())
|
||||
ftw.writeCupackage(ftw.fileId, pkgId)
|
||||
|
||||
fileExtractor.extractClassSource(irDecl, !irDecl.isFileClass, false)
|
||||
fileExtractor.extractClassSource(irDecl, extractDeclarations = !irDecl.isFileClass, extractStaticInitializer = false, extractPrivateMembers = false, extractFunctionBodies = false)
|
||||
} else {
|
||||
fileExtractor.extractDeclaration(irDecl)
|
||||
fileExtractor.extractDeclaration(irDecl, extractPrivateMembers = false, extractFunctionBodies = false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ open class KotlinFileExtractor(
|
||||
}
|
||||
}
|
||||
|
||||
file.declarations.map { extractDeclaration(it) }
|
||||
file.declarations.map { extractDeclaration(it, extractPrivateMembers = true, extractFunctionBodies = true) }
|
||||
extractStaticInitializer(file, null)
|
||||
CommentExtractor(this, file, tw.fileId).extract()
|
||||
}
|
||||
@@ -91,20 +91,29 @@ open class KotlinFileExtractor(
|
||||
return false
|
||||
}
|
||||
|
||||
fun extractDeclaration(declaration: IrDeclaration) {
|
||||
private fun shouldExtractDecl(declaration: IrDeclaration, extractPrivateMembers: Boolean) =
|
||||
extractPrivateMembers ||
|
||||
when(declaration) {
|
||||
is IrDeclarationWithVisibility -> declaration.visibility.let { it != DescriptorVisibilities.PRIVATE && it != DescriptorVisibilities.PRIVATE_TO_THIS }
|
||||
else -> true
|
||||
}
|
||||
|
||||
fun extractDeclaration(declaration: IrDeclaration, extractPrivateMembers: Boolean, extractFunctionBodies: Boolean) {
|
||||
with("declaration", declaration) {
|
||||
if (!shouldExtractDecl(declaration, extractPrivateMembers))
|
||||
return
|
||||
when (declaration) {
|
||||
is IrClass -> {
|
||||
if (isExternalDeclaration(declaration)) {
|
||||
extractExternalClassLater(declaration)
|
||||
} else {
|
||||
extractClassSource(declaration, extractDeclarations = true, extractStaticInitializer = true)
|
||||
extractClassSource(declaration, extractDeclarations = true, extractStaticInitializer = true, extractPrivateMembers = extractPrivateMembers, extractFunctionBodies = extractFunctionBodies)
|
||||
}
|
||||
}
|
||||
is IrFunction -> {
|
||||
val parentId = useDeclarationParent(declaration.parent, false)?.cast<DbReftype>()
|
||||
if (parentId != null) {
|
||||
extractFunction(declaration, parentId, true, null, listOf())
|
||||
extractFunction(declaration, parentId, extractBody = extractFunctionBodies, extractMethodAndParameterTypeAccesses = extractFunctionBodies, null, listOf())
|
||||
}
|
||||
Unit
|
||||
}
|
||||
@@ -114,14 +123,14 @@ open class KotlinFileExtractor(
|
||||
is IrProperty -> {
|
||||
val parentId = useDeclarationParent(declaration.parent, false)?.cast<DbReftype>()
|
||||
if (parentId != null) {
|
||||
extractProperty(declaration, parentId, true, null, listOf())
|
||||
extractProperty(declaration, parentId, extractBackingField = true, extractFunctionBodies = extractFunctionBodies, null, listOf())
|
||||
}
|
||||
Unit
|
||||
}
|
||||
is IrEnumEntry -> {
|
||||
val parentId = useDeclarationParent(declaration.parent, false)?.cast<DbReftype>()
|
||||
if (parentId != null) {
|
||||
extractEnumEntry(declaration, parentId)
|
||||
extractEnumEntry(declaration, parentId, extractFunctionBodies)
|
||||
}
|
||||
Unit
|
||||
}
|
||||
@@ -320,7 +329,7 @@ open class KotlinFileExtractor(
|
||||
|
||||
// `argsIncludingOuterClasses` can be null to describe a raw generic type.
|
||||
// For non-generic types it will be zero-length list.
|
||||
fun extractMemberPrototypes(c: IrClass, argsIncludingOuterClasses: List<IrTypeArgument>?, id: Label<out DbClassorinterface>) {
|
||||
fun extractNonPrivateMemberPrototypes(c: IrClass, argsIncludingOuterClasses: List<IrTypeArgument>?, id: Label<out DbClassorinterface>) {
|
||||
with("member prototypes", c) {
|
||||
val typeParamSubstitution =
|
||||
when (argsIncludingOuterClasses) {
|
||||
@@ -339,17 +348,19 @@ open class KotlinFileExtractor(
|
||||
}
|
||||
|
||||
c.declarations.map {
|
||||
when(it) {
|
||||
is IrFunction -> extractFunction(it, id, false, typeParamSubstitution, argsIncludingOuterClasses)
|
||||
is IrProperty -> extractProperty(it, id, false, typeParamSubstitution, argsIncludingOuterClasses)
|
||||
else -> {}
|
||||
if (shouldExtractDecl(it, false)) {
|
||||
when(it) {
|
||||
is IrFunction -> extractFunction(it, id, extractBody = false, extractMethodAndParameterTypeAccesses = false, typeParamSubstitution, argsIncludingOuterClasses)
|
||||
is IrProperty -> extractProperty(it, id, extractBackingField = false, extractFunctionBodies = false, typeParamSubstitution, argsIncludingOuterClasses)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractLocalTypeDeclStmt(c: IrClass, callable: Label<out DbCallable>, parent: Label<out DbStmtparent>, idx: Int) {
|
||||
val id = extractClassSource(c, extractDeclarations = true, extractStaticInitializer = true).cast<DbClass>()
|
||||
val id = extractClassSource(c, extractDeclarations = true, extractStaticInitializer = true, extractPrivateMembers = true, extractFunctionBodies = true).cast<DbClass>()
|
||||
extractLocalTypeDeclStmt(id, c, callable, parent, idx)
|
||||
}
|
||||
|
||||
@@ -361,7 +372,7 @@ open class KotlinFileExtractor(
|
||||
tw.writeHasLocation(stmtId, locId)
|
||||
}
|
||||
|
||||
fun extractClassSource(c: IrClass, extractDeclarations: Boolean, extractStaticInitializer: Boolean): Label<out DbClassorinterface> {
|
||||
fun extractClassSource(c: IrClass, extractDeclarations: Boolean, extractStaticInitializer: Boolean, extractPrivateMembers: Boolean, extractFunctionBodies: Boolean): Label<out DbClassorinterface> {
|
||||
with("class source", c) {
|
||||
DeclarationStackAdjuster(c).use {
|
||||
|
||||
@@ -395,7 +406,7 @@ open class KotlinFileExtractor(
|
||||
|
||||
c.typeParameters.mapIndexed { idx, param -> extractTypeParameter(param, idx) }
|
||||
if (extractDeclarations) {
|
||||
c.declarations.map { extractDeclaration(it) }
|
||||
c.declarations.map { extractDeclaration(it, extractPrivateMembers = extractPrivateMembers, extractFunctionBodies = extractFunctionBodies) }
|
||||
if (extractStaticInitializer)
|
||||
extractStaticInitializer(c, id)
|
||||
}
|
||||
@@ -442,7 +453,7 @@ open class KotlinFileExtractor(
|
||||
val instance = useCompanionObjectClassInstance(innerDeclaration)
|
||||
if (instance != null) {
|
||||
val type = useSimpleTypeClass(innerDeclaration, emptyList(), false)
|
||||
tw.writeFields(instance.id, instance.name, type.javaResult.id, innerId, instance.id)
|
||||
tw.writeFields(instance.id, instance.name, type.javaResult.id, parentId, instance.id)
|
||||
tw.writeFieldsKotlinType(instance.id, type.kotlinResult.id)
|
||||
tw.writeHasLocation(instance.id, innerLocId)
|
||||
addModifiers(instance.id, "public", "static", "final")
|
||||
@@ -500,11 +511,11 @@ open class KotlinFileExtractor(
|
||||
return FieldResult(instanceId, instanceName)
|
||||
}
|
||||
|
||||
private fun extractValueParameter(vp: IrValueParameter, parent: Label<out DbCallable>, idx: Int, typeSubstitution: TypeSubstitution?, parentSourceDeclaration: Label<out DbCallable>, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?): TypeResults {
|
||||
private fun extractValueParameter(vp: IrValueParameter, parent: Label<out DbCallable>, idx: Int, typeSubstitution: TypeSubstitution?, parentSourceDeclaration: Label<out DbCallable>, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?, extractTypeAccess: Boolean): TypeResults {
|
||||
with("value parameter", vp) {
|
||||
val location = getLocation(vp, classTypeArgsIncludingOuterClasses)
|
||||
val id = useValueParameter(vp, parent)
|
||||
if (!isExternalDeclaration(vp)) {
|
||||
if (extractTypeAccess) {
|
||||
extractTypeAccessRecursive(vp.type, location, id, -1)
|
||||
}
|
||||
return extractValueParameter(id, vp.type, vp.name.asString(), location, parent, idx, typeSubstitution, useValueParameter(vp, parentSourceDeclaration), vp.isVararg)
|
||||
@@ -539,7 +550,7 @@ open class KotlinFileExtractor(
|
||||
classTypeArgsIncludingOuterClasses = listOf()
|
||||
)
|
||||
val clinitId = tw.getLabelFor<DbMethod>(clinitLabel)
|
||||
val returnType = useType(pluginContext.irBuiltIns.unitType)
|
||||
val returnType = useType(pluginContext.irBuiltIns.unitType, TypeContext.RETURN)
|
||||
tw.writeMethods(clinitId, "<clinit>", "<clinit>()", returnType.javaResult.id, parentId, clinitId)
|
||||
tw.writeMethodsKotlinType(clinitId, returnType.kotlinResult.id)
|
||||
|
||||
@@ -665,7 +676,7 @@ open class KotlinFileExtractor(
|
||||
}
|
||||
}
|
||||
|
||||
fun extractFunction(f: IrFunction, parentId: Label<out DbReftype>, extractBody: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?, idOverride: Label<DbMethod>? = null): Label<out DbCallable>? {
|
||||
fun extractFunction(f: IrFunction, parentId: Label<out DbReftype>, extractBody: Boolean, extractMethodAndParameterTypeAccesses: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?, idOverride: Label<DbMethod>? = null): Label<out DbCallable>? {
|
||||
if (isFake(f)) return null
|
||||
|
||||
with("function", f) {
|
||||
@@ -678,7 +689,9 @@ open class KotlinFileExtractor(
|
||||
?: if (f.isLocalFunction())
|
||||
getLocallyVisibleFunctionLabels(f).function
|
||||
else
|
||||
useFunction<DbCallable>(f, parentId, classTypeArgsIncludingOuterClasses)
|
||||
// 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)
|
||||
@@ -689,13 +702,13 @@ open class KotlinFileExtractor(
|
||||
val extReceiver = f.extensionReceiverParameter
|
||||
val idxOffset = if (extReceiver != null) 1 else 0
|
||||
val paramTypes = f.valueParameters.mapIndexed { i, vp ->
|
||||
extractValueParameter(vp, id, i + idxOffset, typeSubstitution, sourceDeclaration, classTypeArgsIncludingOuterClasses)
|
||||
extractValueParameter(vp, id, i + idxOffset, typeSubstitution, sourceDeclaration, classTypeArgsIncludingOuterClasses, extractTypeAccess = extractMethodAndParameterTypeAccesses)
|
||||
}
|
||||
val allParamTypes = if (extReceiver != null) {
|
||||
val extendedType = useType(extReceiver.type)
|
||||
tw.writeKtExtensionFunctions(id.cast<DbMethod>(), extendedType.javaResult.id, extendedType.kotlinResult.id)
|
||||
|
||||
val t = extractValueParameter(extReceiver, id, 0, null, sourceDeclaration, classTypeArgsIncludingOuterClasses)
|
||||
val t = extractValueParameter(extReceiver, id, 0, null, sourceDeclaration, classTypeArgsIncludingOuterClasses, extractTypeAccess = extractMethodAndParameterTypeAccesses)
|
||||
listOf(t) + paramTypes
|
||||
} else {
|
||||
paramTypes
|
||||
@@ -724,7 +737,7 @@ open class KotlinFileExtractor(
|
||||
tw.writeMethods(methodId, shortName.nameInDB, "${shortName.nameInDB}$paramsSignature", returnType.javaResult.id, parentId, sourceDeclaration.cast<DbMethod>())
|
||||
tw.writeMethodsKotlinType(methodId, returnType.kotlinResult.id)
|
||||
|
||||
if (!isExternalDeclaration(f)) {
|
||||
if (extractMethodAndParameterTypeAccesses) {
|
||||
extractTypeAccessRecursive(f.returnType, locId, id, -1)
|
||||
}
|
||||
|
||||
@@ -791,14 +804,14 @@ open class KotlinFileExtractor(
|
||||
return id
|
||||
}
|
||||
|
||||
fun extractProperty(p: IrProperty, parentId: Label<out DbReftype>, extractBackingField: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgs: List<IrTypeArgument>?) {
|
||||
fun extractProperty(p: IrProperty, parentId: Label<out DbReftype>, extractBackingField: Boolean, extractFunctionBodies: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?) {
|
||||
with("property", p) {
|
||||
if (isFake(p)) return
|
||||
|
||||
DeclarationStackAdjuster(p).use {
|
||||
|
||||
val id = useProperty(p, parentId)
|
||||
val locId = getLocation(p, classTypeArgs)
|
||||
val id = useProperty(p, parentId, classTypeArgsIncludingOuterClasses)
|
||||
val locId = getLocation(p, classTypeArgsIncludingOuterClasses)
|
||||
tw.writeKtProperties(id, p.name.asString())
|
||||
tw.writeHasLocation(id, locId)
|
||||
|
||||
@@ -807,7 +820,7 @@ open class KotlinFileExtractor(
|
||||
val setter = p.setter
|
||||
|
||||
if (getter != null) {
|
||||
val getterId = extractFunction(getter, parentId, extractBackingField, typeSubstitution, classTypeArgs)?.cast<DbMethod>()
|
||||
val getterId = extractFunction(getter, parentId, extractBody = extractFunctionBodies, extractMethodAndParameterTypeAccesses = extractFunctionBodies, typeSubstitution, classTypeArgsIncludingOuterClasses)?.cast<DbMethod>()
|
||||
if (getterId != null) {
|
||||
tw.writeKtPropertyGetters(id, getterId)
|
||||
}
|
||||
@@ -821,7 +834,7 @@ open class KotlinFileExtractor(
|
||||
if (!p.isVar) {
|
||||
logger.errorElement("!isVar property with a setter", p)
|
||||
}
|
||||
val setterId = extractFunction(setter, parentId, extractBackingField, typeSubstitution, classTypeArgs)?.cast<DbMethod>()
|
||||
val setterId = extractFunction(setter, parentId, extractBody = extractFunctionBodies, extractMethodAndParameterTypeAccesses = extractFunctionBodies, typeSubstitution, classTypeArgsIncludingOuterClasses)?.cast<DbMethod>()
|
||||
if (setterId != null) {
|
||||
tw.writeKtPropertySetters(id, setterId)
|
||||
}
|
||||
@@ -857,7 +870,7 @@ open class KotlinFileExtractor(
|
||||
}
|
||||
}
|
||||
|
||||
fun extractEnumEntry(ee: IrEnumEntry, parentId: Label<out DbReftype>) {
|
||||
fun extractEnumEntry(ee: IrEnumEntry, parentId: Label<out DbReftype>, extractTypeAccess: Boolean) {
|
||||
with("enum entry", ee) {
|
||||
DeclarationStackAdjuster(ee).use {
|
||||
val id = useEnumEntry(ee)
|
||||
@@ -867,7 +880,7 @@ open class KotlinFileExtractor(
|
||||
val locId = tw.getLocation(ee)
|
||||
tw.writeHasLocation(id, locId)
|
||||
|
||||
if (!isExternalDeclaration(ee)) {
|
||||
if (extractTypeAccess) {
|
||||
val fieldDeclarationId = tw.getFreshIdLabel<DbFielddecl>()
|
||||
tw.writeFielddecls(fieldDeclarationId, parentId)
|
||||
tw.writeFieldDeclaredIn(id, fieldDeclarationId, 0)
|
||||
@@ -1341,6 +1354,23 @@ open class KotlinFileExtractor(
|
||||
return result
|
||||
}
|
||||
|
||||
private fun findTopLevelFunctionOrWarn(functionFilter: String, type: String, warnAgainstElement: IrElement): IrFunction? {
|
||||
|
||||
val fn = pluginContext.referenceFunctions(FqName(functionFilter))
|
||||
.firstOrNull { it.owner.parentClassOrNull?.fqNameWhenAvailable?.asString() == type }
|
||||
?.owner
|
||||
|
||||
if (fn != null) {
|
||||
if (fn.parentClassOrNull != null) {
|
||||
extractExternalClassLater(fn.parentAsClass)
|
||||
}
|
||||
} else {
|
||||
logger.errorElement("Couldn't find JVM intrinsic function $functionFilter in $type", warnAgainstElement)
|
||||
}
|
||||
|
||||
return fn
|
||||
}
|
||||
|
||||
val javaLangString by lazy {
|
||||
val result = pluginContext.referenceClass(FqName("java.lang.String"))?.owner
|
||||
result?.let { extractExternalClassLater(it) }
|
||||
@@ -1854,6 +1884,11 @@ open class KotlinFileExtractor(
|
||||
}
|
||||
}
|
||||
}
|
||||
isFunction(target, "kotlin", "(some array type)", { isArrayType(it) }, "iterator") && c.origin == IrStatementOrigin.FOR_LOOP_ITERATOR -> {
|
||||
findTopLevelFunctionOrWarn("kotlin.jvm.internal.iterator", "kotlin.jvm.internal.ArrayIteratorKt", c)?.let { iteratorFn ->
|
||||
extractRawMethodAccess(iteratorFn, c, callable, parent, idx, enclosingStmt, listOf(c.dispatchReceiver), null, null, listOf((c.dispatchReceiver!!.type as IrSimpleType).arguments.first().typeOrNull!!))
|
||||
}
|
||||
}
|
||||
isFunction(target, "kotlin", "(some array type)", { isArrayType(it) }, "get") && c.origin == IrStatementOrigin.GET_ARRAY_ELEMENT -> {
|
||||
val id = tw.getFreshIdLabel<DbArrayaccess>()
|
||||
val type = useType(c.type)
|
||||
@@ -3976,7 +4011,7 @@ open class KotlinFileExtractor(
|
||||
helper.extractParameterToFieldAssignmentInConstructor("<fn>", functionType, fieldId, 0, 1)
|
||||
|
||||
// add implementation function
|
||||
extractFunction(samMember, classId, false, null, null, ids.function)
|
||||
extractFunction(samMember, classId, extractBody = false, extractMethodAndParameterTypeAccesses = true, null, null, ids.function)
|
||||
|
||||
//body
|
||||
val blockId = tw.getFreshIdLabel<DbBlock>()
|
||||
@@ -4152,7 +4187,7 @@ open class KotlinFileExtractor(
|
||||
val id = extractGeneratedClass(ids, superTypes, tw.getLocation(localFunction), localFunction)
|
||||
|
||||
// Extract local function as a member
|
||||
extractFunction(localFunction, id, true, null, listOf())
|
||||
extractFunction(localFunction, id, extractBody = true, extractMethodAndParameterTypeAccesses = true, null, listOf())
|
||||
|
||||
return id
|
||||
}
|
||||
|
||||
@@ -4,21 +4,19 @@ import com.github.codeql.utils.*
|
||||
import com.github.codeql.utils.versions.isRawType
|
||||
import com.semmle.extractor.java.OdasaOutput
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||
import org.jetbrains.kotlin.backend.common.ir.allOverridden
|
||||
import org.jetbrains.kotlin.backend.common.lower.parentsWithSelf
|
||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||
import org.jetbrains.kotlin.ir.types.impl.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
@@ -49,6 +47,41 @@ open class KotlinUsesExtractor(
|
||||
TypeResult(fakeKotlinType(), "", "")
|
||||
)
|
||||
|
||||
private data class MethodKey(val className: FqName, val functionName: Name)
|
||||
|
||||
private fun makeDescription(className: FqName, functionName: String) = MethodKey(className, Name.guessByFirstCharacter(functionName))
|
||||
|
||||
// This essentially mirrors SpecialBridgeMethods.kt, a backend pass which isn't easily available to our extractor.
|
||||
private val specialFunctions = mapOf(
|
||||
makeDescription(StandardNames.FqNames.collection, "<get-size>") to "size",
|
||||
makeDescription(FqName("java.util.Collection"), "<get-size>") to "size",
|
||||
makeDescription(StandardNames.FqNames.map, "<get-size>") to "size",
|
||||
makeDescription(FqName("java.util.Map"), "<get-size>") to "size",
|
||||
makeDescription(StandardNames.FqNames.charSequence.toSafe(), "<get-length>") to "length",
|
||||
makeDescription(FqName("java.lang.CharSequence"), "<get-length>") to "length",
|
||||
makeDescription(StandardNames.FqNames.map, "<get-keys>") to "keySet",
|
||||
makeDescription(FqName("java.util.Map"), "<get-keys>") to "keySet",
|
||||
makeDescription(StandardNames.FqNames.map, "<get-values>") to "values",
|
||||
makeDescription(FqName("java.util.Map"), "<get-values>") to "values",
|
||||
makeDescription(StandardNames.FqNames.map, "<get-entries>") to "entrySet",
|
||||
makeDescription(FqName("java.util.Map"), "<get-entries>") to "entrySet"
|
||||
)
|
||||
|
||||
private val specialFunctionShortNames = specialFunctions.keys.map { it.functionName }.toSet()
|
||||
|
||||
fun getSpecialJvmName(f: IrFunction): String? {
|
||||
if (specialFunctionShortNames.contains(f.name) && f is IrSimpleFunction) {
|
||||
f.allOverridden(true).forEach { overriddenFunc ->
|
||||
overriddenFunc.parentAsClass.fqNameWhenAvailable?.let { parentFqName ->
|
||||
specialFunctions[MethodKey(parentFqName, f.name)]?.let {
|
||||
return it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun getJvmName(container: IrAnnotationContainer): String? {
|
||||
for(a: IrConstructorCall in container.annotations) {
|
||||
val t = a.type
|
||||
@@ -67,7 +100,7 @@ open class KotlinUsesExtractor(
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
return (container as? IrFunction)?.let { getSpecialJvmName(container) }
|
||||
}
|
||||
|
||||
@OptIn(kotlin.ExperimentalStdlibApi::class) // Annotation required by kotlin versions < 1.5
|
||||
@@ -122,10 +155,7 @@ open class KotlinUsesExtractor(
|
||||
}
|
||||
|
||||
fun getJavaEquivalentClass(c: IrClass) =
|
||||
c.fqNameWhenAvailable?.toUnsafe()
|
||||
?.let { JavaToKotlinClassMap.mapKotlinToJava(it) }
|
||||
?.let { pluginContext.referenceClass(it.asSingleFqName()) }
|
||||
?.owner
|
||||
getJavaEquivalentClassId(c)?.let { pluginContext.referenceClass(it.asSingleFqName()) }?.owner
|
||||
|
||||
/**
|
||||
* Gets a KotlinFileExtractor based on this one, except it attributes locations to the file that declares the given class.
|
||||
@@ -380,7 +410,7 @@ open class KotlinUsesExtractor(
|
||||
if (inReceiverContext && globalExtensionState.genericSpecialisationsExtracted.add(classLabelResult.classLabel)) {
|
||||
val supertypeMode = if (argsIncludingOuterClasses == null) ExtractSupertypesMode.Raw else ExtractSupertypesMode.Specialised(argsIncludingOuterClasses)
|
||||
extractorWithCSource.extractClassSupertypes(c, classLabel, supertypeMode, true)
|
||||
extractorWithCSource.extractMemberPrototypes(c, argsIncludingOuterClasses, classLabel)
|
||||
extractorWithCSource.extractNonPrivateMemberPrototypes(c, argsIncludingOuterClasses, classLabel)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -696,8 +726,26 @@ open class KotlinUsesExtractor(
|
||||
}
|
||||
|
||||
when (f) {
|
||||
getter -> return FunctionNames(getJvmName(getter) ?: JvmAbi.getterName(propName), JvmAbi.getterName(propName))
|
||||
setter -> return FunctionNames(getJvmName(setter) ?: JvmAbi.setterName(propName), JvmAbi.setterName(propName))
|
||||
getter -> {
|
||||
val defaultFunctionName = JvmAbi.getterName(propName)
|
||||
val defaultDbName = if (getter.visibility == DescriptorVisibilities.PRIVATE && getter.origin == IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR) {
|
||||
// In JVM these functions don't exist, instead the backing field is accessed directly
|
||||
defaultFunctionName + "\$private"
|
||||
} else {
|
||||
defaultFunctionName
|
||||
}
|
||||
return FunctionNames(getJvmName(getter) ?: defaultDbName, defaultFunctionName)
|
||||
}
|
||||
setter -> {
|
||||
val defaultFunctionName = JvmAbi.setterName(propName)
|
||||
val defaultDbName = if (setter.visibility == DescriptorVisibilities.PRIVATE && setter.origin == IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR) {
|
||||
// In JVM these functions don't exist, instead the backing field is accessed directly
|
||||
defaultFunctionName + "\$private"
|
||||
} else {
|
||||
defaultFunctionName
|
||||
}
|
||||
return FunctionNames(getJvmName(setter) ?: defaultDbName, defaultFunctionName)
|
||||
}
|
||||
else -> {
|
||||
logger.error(
|
||||
"Function has a corresponding property, but is neither the getter nor the setter"
|
||||
@@ -774,7 +822,9 @@ open class KotlinUsesExtractor(
|
||||
// The type parameters of the function. This does not include type parameters of enclosing classes.
|
||||
functionTypeParameters: List<IrTypeParameter>,
|
||||
// The type arguments of enclosing classes of the function.
|
||||
classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?
|
||||
classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?,
|
||||
// The prefix used in the label. "callable", unless a property label is created, then it's "property".
|
||||
prefix: String = "callable"
|
||||
): String {
|
||||
val parentId = maybeParentId ?: useDeclarationParent(parent, false, classTypeArgsIncludingOuterClasses, true)
|
||||
val allParams = if (extensionReceiverParameter == null) {
|
||||
@@ -810,7 +860,7 @@ open class KotlinUsesExtractor(
|
||||
// method (and presumably that disambiguation is never needed when the method belongs to a parameterized
|
||||
// instance of a generic class), but as of now I don't know when the raw method would be referred to.
|
||||
val typeArgSuffix = if (functionTypeParameters.isNotEmpty() && classTypeArgsIncludingOuterClasses.isNullOrEmpty()) "<${functionTypeParameters.size}>" else "";
|
||||
return "@\"callable;{$parentId}.$name($paramTypeIds){$returnTypeId}${typeArgSuffix}\""
|
||||
return "@\"$prefix;{$parentId}.$name($paramTypeIds){$returnTypeId}${typeArgSuffix}\""
|
||||
}
|
||||
|
||||
protected fun IrFunction.isLocalFunction(): Boolean {
|
||||
@@ -867,17 +917,62 @@ open class KotlinUsesExtractor(
|
||||
return id
|
||||
}
|
||||
|
||||
fun <T: DbCallable> useFunction(f: IrFunction, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>? = null): Label<out T> {
|
||||
// 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.
|
||||
private val expectedMissingEquivalents = setOf(
|
||||
"kotlin.Boolean", "kotlin.Byte", "kotlin.Char", "kotlin.Double", "kotlin.Float", "kotlin.Int", "kotlin.Long", "kotlin.Number", "kotlin.Short"
|
||||
)
|
||||
|
||||
fun kotlinFunctionToJavaEquivalent(f: IrFunction, noReplace: Boolean) =
|
||||
if (noReplace)
|
||||
f
|
||||
else
|
||||
f.parentClassOrNull?.let { parentClass ->
|
||||
getJavaEquivalentClass(parentClass)?.let { javaClass ->
|
||||
if (javaClass != parentClass)
|
||||
// Look for an exact type match...
|
||||
javaClass.declarations.find { decl ->
|
||||
decl is IrFunction &&
|
||||
decl.name == f.name &&
|
||||
decl.valueParameters.size == f.valueParameters.size &&
|
||||
// Note matching by classifier not the whole type so that generic arguments are allowed to differ,
|
||||
// as they always will for method type parameters occurring in parameter types (e.g. <T> toArray(T[] array)
|
||||
// Differing only by nullability would also be insignificant if it came up.
|
||||
decl.valueParameters.zip(f.valueParameters).all { p -> p.first.type.classifierOrNull == p.second.type.classifierOrNull }
|
||||
} ?:
|
||||
// Or if there is none, look for the only viable overload
|
||||
javaClass.declarations.singleOrNull { decl ->
|
||||
decl is IrFunction &&
|
||||
decl.name == f.name &&
|
||||
decl.valueParameters.size == f.valueParameters.size
|
||||
} ?:
|
||||
run {
|
||||
val parentFqName = parentClass.fqNameWhenAvailable?.asString()
|
||||
if (!expectedMissingEquivalents.contains(parentFqName)) {
|
||||
logger.warn("Couldn't find a Java equivalent function to $parentFqName.${f.name} in ${javaClass.fqNameWhenAvailable}")
|
||||
}
|
||||
null
|
||||
}
|
||||
else
|
||||
null
|
||||
}
|
||||
} as IrFunction? ?: f
|
||||
|
||||
fun <T: DbCallable> useFunction(f: IrFunction, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>? = null, noReplace: Boolean = false): Label<out T> {
|
||||
if (f.isLocalFunction()) {
|
||||
val ids = getLocallyVisibleFunctionLabels(f)
|
||||
return ids.function.cast<T>()
|
||||
} else {
|
||||
return useFunctionCommon<T>(f, getFunctionLabel(f, classTypeArgsIncludingOuterClasses))
|
||||
val realFunction = kotlinFunctionToJavaEquivalent(f, noReplace)
|
||||
return useFunctionCommon<T>(realFunction, getFunctionLabel(realFunction, classTypeArgsIncludingOuterClasses))
|
||||
}
|
||||
}
|
||||
|
||||
fun <T: DbCallable> useFunction(f: IrFunction, parentId: Label<out DbElement>, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?) =
|
||||
useFunctionCommon<T>(f, getFunctionLabel(f, parentId, classTypeArgsIncludingOuterClasses))
|
||||
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
|
||||
@@ -941,6 +1036,9 @@ open class KotlinUsesExtractor(
|
||||
is IrFunction -> {
|
||||
"{${useFunction<DbMethod>(parent)}}.$cls"
|
||||
}
|
||||
is IrField -> {
|
||||
"{${useField(parent)}}.$cls"
|
||||
}
|
||||
else -> {
|
||||
if (pkg.isEmpty()) cls else "$pkg.$cls"
|
||||
}
|
||||
@@ -1111,15 +1209,20 @@ open class KotlinUsesExtractor(
|
||||
* `parent` is null.
|
||||
*/
|
||||
fun getValueParameterLabel(vp: IrValueParameter, parent: Label<out DbCallable>?): String {
|
||||
val parentId = parent ?: useDeclarationParent(vp.parent, false)
|
||||
val idx = vp.index
|
||||
val declarationParent = vp.parent
|
||||
val parentId = parent ?: useDeclarationParent(declarationParent, false)
|
||||
|
||||
val idx = if (declarationParent is IrFunction && declarationParent.extensionReceiverParameter != null)
|
||||
// For extension functions increase the index to match what the java extractor sees:
|
||||
vp.index + 1
|
||||
else
|
||||
vp.index
|
||||
|
||||
if (idx < 0) {
|
||||
val p = vp.parent
|
||||
if (p !is IrFunction || p.extensionReceiverParameter != vp) {
|
||||
// We're not extracting this and this@TYPE parameters of functions:
|
||||
logger.error("Unexpected negative index for parameter")
|
||||
}
|
||||
// We're not extracting this and this@TYPE parameters of functions:
|
||||
logger.error("Unexpected negative index for parameter")
|
||||
}
|
||||
|
||||
return "@\"params;{$parentId};$idx\""
|
||||
}
|
||||
|
||||
@@ -1140,24 +1243,29 @@ open class KotlinUsesExtractor(
|
||||
if (parentId == null) {
|
||||
return null
|
||||
} else {
|
||||
return getPropertyLabel(p, parentId)
|
||||
return getPropertyLabel(p, parentId, null)
|
||||
}
|
||||
}
|
||||
|
||||
fun getPropertyLabel(p: IrProperty, parentId: Label<out DbElement>) =
|
||||
"@\"property;{$parentId};${p.name.asString()}\""
|
||||
private fun getPropertyLabel(p: IrProperty, parentId: Label<out DbElement>, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?): String {
|
||||
val getter = p.getter
|
||||
val setter = p.setter
|
||||
|
||||
fun useProperty(p: IrProperty): Label<out DbKt_property>? {
|
||||
val label = getPropertyLabel(p)
|
||||
if (label == null) {
|
||||
return null
|
||||
val func = getter ?: setter
|
||||
val ext = func?.extensionReceiverParameter
|
||||
|
||||
return if (ext == null) {
|
||||
"@\"property;{$parentId};${p.name.asString()}\""
|
||||
} else {
|
||||
return tw.getLabelFor<DbKt_property>(label).also { extractPropertyLaterIfExternalFileMember(p) }
|
||||
val returnType = getter?.returnType ?: setter?.valueParameters?.singleOrNull()?.type ?: pluginContext.irBuiltIns.unitType
|
||||
val typeParams = getFunctionTypeParameters(func)
|
||||
|
||||
getFunctionLabel(p.parent, parentId, p.name.asString(), listOf(), returnType, ext, typeParams, classTypeArgsIncludingOuterClasses, "property")
|
||||
}
|
||||
}
|
||||
|
||||
fun useProperty(p: IrProperty, parentId: Label<out DbElement>): Label<out DbKt_property> =
|
||||
tw.getLabelFor<DbKt_property>(getPropertyLabel(p, parentId)).also { extractPropertyLaterIfExternalFileMember(p) }
|
||||
fun useProperty(p: IrProperty, parentId: Label<out DbElement>, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?): Label<out DbKt_property> =
|
||||
tw.getLabelFor<DbKt_property>(getPropertyLabel(p, parentId, classTypeArgsIncludingOuterClasses)).also { extractPropertyLaterIfExternalFileMember(p) }
|
||||
|
||||
fun getEnumEntryLabel(ee: IrEnumEntry): String {
|
||||
val parentId = useDeclarationParent(ee.parent, false)
|
||||
|
||||
@@ -7,7 +7,9 @@ import org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClass
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
|
||||
|
||||
@@ -84,4 +86,7 @@ fun getContainingClassOrSelf(decl: IrDeclaration): IrClass? {
|
||||
is IrClass -> decl
|
||||
else -> decl.parentClassOrNull
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getJavaEquivalentClassId(c: IrClass) =
|
||||
c.fqNameWhenAvailable?.toUnsafe()?.let { JavaToKotlinClassMap.mapKotlinToJava(it) }
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.github.codeql.utils
|
||||
|
||||
import com.github.codeql.KotlinUsesExtractor
|
||||
import com.github.codeql.getJavaEquivalentClassId
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
@@ -19,6 +20,7 @@ import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||
import org.jetbrains.kotlin.ir.util.classId
|
||||
import org.jetbrains.kotlin.ir.util.constructedClassType
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
@@ -195,13 +197,25 @@ fun IrTypeArgument.withQuestionMark(b: Boolean): IrTypeArgument =
|
||||
|
||||
typealias TypeSubstitution = (IrType, KotlinUsesExtractor.TypeContext, IrPluginContext) -> IrType
|
||||
|
||||
fun matchingTypeParameters(l: IrTypeParameter?, r: IrTypeParameter): Boolean {
|
||||
if (l === r)
|
||||
return true
|
||||
if (l == null)
|
||||
return false
|
||||
// Special case: match List's E and MutableList's E, for example, because in the JVM lowering they will map to the same thing.
|
||||
val lParent = l.parent as? IrClass ?: return false
|
||||
val rParent = r.parent as? IrClass ?: return false
|
||||
val lJavaId = getJavaEquivalentClassId(lParent) ?: lParent.classId
|
||||
return (getJavaEquivalentClassId(rParent) ?: rParent.classId) == lJavaId && l.name == r.name
|
||||
}
|
||||
|
||||
// Returns true if type is C<T1, T2, ...> where C is declared `class C<T1, T2, ...> { ... }`
|
||||
fun isUnspecialised(paramsContainer: IrTypeParametersContainer, args: List<IrTypeArgument>): Boolean {
|
||||
val unspecialisedHere = paramsContainer.typeParameters.zip(args).all { paramAndArg ->
|
||||
(paramAndArg.second as? IrTypeProjection)?.let {
|
||||
// Type arg refers to the class' own type parameter?
|
||||
it.variance == Variance.INVARIANT &&
|
||||
it.type.classifierOrNull?.owner === paramAndArg.first
|
||||
matchingTypeParameters(it.type.classifierOrNull?.owner as? IrTypeParameter, paramAndArg.first)
|
||||
} ?: false
|
||||
}
|
||||
val remainingArgs = args.drop(paramsContainer.typeParameters.size)
|
||||
|
||||
@@ -143,6 +143,7 @@ private module Frameworks {
|
||||
private import semmle.code.java.frameworks.JMS
|
||||
private import semmle.code.java.frameworks.RabbitMQ
|
||||
private import semmle.code.java.regex.RegexFlowModels
|
||||
private import semmle.code.java.frameworks.KotlinStdLib
|
||||
}
|
||||
|
||||
private predicate sourceModelCsv(string row) {
|
||||
|
||||
11
java/ql/lib/semmle/code/java/frameworks/KotlinStdLib.qll
Normal file
11
java/ql/lib/semmle/code/java/frameworks/KotlinStdLib.qll
Normal file
@@ -0,0 +1,11 @@
|
||||
/** Definitions of taint steps in the KotlinStdLib framework */
|
||||
|
||||
import java
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
private class KotlinStdLibSummaryCsv extends SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
"kotlin.jvm.internal;ArrayIteratorKt;false;iterator;(Object[]);;Argument[0].ArrayElement;ReturnValue.Element;value"
|
||||
}
|
||||
}
|
||||
@@ -578,7 +578,7 @@ generic_anonymous.kt:
|
||||
# 3| 1: [ExprStmt] <Expr>;
|
||||
# 3| 0: [ClassInstanceExpr] new (...)
|
||||
# 3| -3: [TypeAccess] Object
|
||||
# 3| 5: [Method] getX
|
||||
# 3| 5: [Method] getX$private
|
||||
# 3| 3: [TypeAccess] new Object(...) { ... }
|
||||
# 3| 0: [TypeAccess] T
|
||||
# 3| 5: [BlockStmt] { ... }
|
||||
@@ -590,8 +590,69 @@ generic_anonymous.kt:
|
||||
# 7| 5: [BlockStmt] { ... }
|
||||
# 7| 0: [ReturnStmt] return ...
|
||||
# 7| 0: [MethodAccess] getMember(...)
|
||||
# 7| -1: [MethodAccess] getX(...)
|
||||
# 7| -1: [MethodAccess] getX$private(...)
|
||||
# 7| -1: [ThisAccess] this
|
||||
localClassField.kt:
|
||||
# 0| [CompilationUnit] localClassField
|
||||
# 1| 1: [Class] A
|
||||
# 1| 1: [Constructor] A
|
||||
# 1| 5: [BlockStmt] { ... }
|
||||
# 1| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 1| 1: [BlockStmt] { ... }
|
||||
# 2| 0: [ExprStmt] <Expr>;
|
||||
# 2| 0: [KtInitializerAssignExpr] ...=...
|
||||
# 2| 0: [VarAccess] x
|
||||
# 7| 1: [ExprStmt] <Expr>;
|
||||
# 7| 0: [KtInitializerAssignExpr] ...=...
|
||||
# 7| 0: [VarAccess] y
|
||||
# 2| 2: [Method] getX
|
||||
# 2| 3: [TypeAccess] Object
|
||||
# 2| 5: [BlockStmt] { ... }
|
||||
# 2| 0: [ReturnStmt] return ...
|
||||
# 2| 0: [VarAccess] this.x
|
||||
# 2| -1: [ThisAccess] this
|
||||
# 2| 2: [FieldDeclaration] Object x;
|
||||
# 2| -1: [TypeAccess] Object
|
||||
# 2| 0: [WhenExpr] when ...
|
||||
# 2| 0: [WhenBranch] ... -> ...
|
||||
# 2| 0: [BooleanLiteral] true
|
||||
# 2| 1: [BlockStmt] { ... }
|
||||
# 3| 0: [LocalTypeDeclStmt] class ...
|
||||
# 3| 0: [LocalClass] L
|
||||
# 3| 1: [Constructor] L
|
||||
# 3| 5: [BlockStmt] { ... }
|
||||
# 3| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 3| 1: [BlockStmt] { ... }
|
||||
# 4| 1: [ExprStmt] <Expr>;
|
||||
# 4| 0: [ClassInstanceExpr] new L(...)
|
||||
# 4| -3: [TypeAccess] L
|
||||
# 2| 1: [WhenBranch] ... -> ...
|
||||
# 2| 0: [BooleanLiteral] true
|
||||
# 5| 1: [BlockStmt] { ... }
|
||||
# 7| 4: [Method] getY
|
||||
# 7| 3: [TypeAccess] Object
|
||||
# 7| 5: [BlockStmt] { ... }
|
||||
# 7| 0: [ReturnStmt] return ...
|
||||
# 7| 0: [VarAccess] this.y
|
||||
# 7| -1: [ThisAccess] this
|
||||
# 7| 4: [FieldDeclaration] Object y;
|
||||
# 7| -1: [TypeAccess] Object
|
||||
# 7| 0: [WhenExpr] when ...
|
||||
# 7| 0: [WhenBranch] ... -> ...
|
||||
# 7| 0: [BooleanLiteral] true
|
||||
# 7| 1: [BlockStmt] { ... }
|
||||
# 8| 0: [LocalTypeDeclStmt] class ...
|
||||
# 8| 0: [LocalClass] L
|
||||
# 8| 1: [Constructor] L
|
||||
# 8| 5: [BlockStmt] { ... }
|
||||
# 8| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 8| 1: [BlockStmt] { ... }
|
||||
# 9| 1: [ExprStmt] <Expr>;
|
||||
# 9| 0: [ClassInstanceExpr] new L(...)
|
||||
# 9| -3: [TypeAccess] L
|
||||
# 7| 1: [WhenBranch] ... -> ...
|
||||
# 7| 0: [BooleanLiteral] true
|
||||
# 10| 1: [BlockStmt] { ... }
|
||||
local_anonymous.kt:
|
||||
# 0| [CompilationUnit] local_anonymous
|
||||
# 3| 1: [Class] Class1
|
||||
|
||||
@@ -37,6 +37,9 @@
|
||||
| generic_anonymous.kt:0:0:0:0 | Generic_anonymousKt | Generic_anonymousKt | final, public |
|
||||
| generic_anonymous.kt:1:1:9:1 | Generic | Generic | final, private |
|
||||
| generic_anonymous.kt:3:19:5:3 | new Object(...) { ... } | <anonymous class> | final, private |
|
||||
| localClassField.kt:1:1:11:1 | A | A | final, public |
|
||||
| localClassField.kt:3:9:3:19 | L | A$L | final, private |
|
||||
| localClassField.kt:8:9:8:19 | L | A$L | final, private |
|
||||
| local_anonymous.kt:3:1:36:1 | Class1 | LocalAnonymous.Class1 | final, public |
|
||||
| local_anonymous.kt:5:16:7:9 | new Object(...) { ... } | <anonymous class> | final, private |
|
||||
| local_anonymous.kt:11:9:11:24 | | Class1$ | final, private |
|
||||
|
||||
@@ -36,6 +36,9 @@ superCall
|
||||
| classes.kt:129:17:131:17 | super(...) |
|
||||
| generic_anonymous.kt:1:1:9:1 | super(...) |
|
||||
| generic_anonymous.kt:3:19:5:3 | super(...) |
|
||||
| localClassField.kt:1:1:11:1 | super(...) |
|
||||
| localClassField.kt:3:9:3:19 | super(...) |
|
||||
| localClassField.kt:8:9:8:19 | super(...) |
|
||||
| local_anonymous.kt:3:1:36:1 | super(...) |
|
||||
| local_anonymous.kt:5:16:7:9 | super(...) |
|
||||
| local_anonymous.kt:11:9:11:24 | super(...) |
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
| generic_anonymous.kt:4:20:4:20 | Generic.this | Generic |
|
||||
| generic_anonymous.kt:4:20:4:20 | getT(...) | T |
|
||||
| generic_anonymous.kt:7:3:7:22 | T | T |
|
||||
| generic_anonymous.kt:7:15:7:15 | getX(...) | new Object(...) { ... } |
|
||||
| generic_anonymous.kt:7:15:7:15 | getX$private(...) | new Object(...) { ... } |
|
||||
| generic_anonymous.kt:7:15:7:15 | this | Generic |
|
||||
| generic_anonymous.kt:7:17:7:22 | getMember(...) | T |
|
||||
| generic_anonymous.kt:11:1:11:56 | String | String |
|
||||
|
||||
@@ -2,5 +2,7 @@
|
||||
| classes.kt:118:9:123:9 | class ... | classes.kt:118:9:123:9 | | classes.kt:117:5:124:5 | fn2 | classes.kt:109:1:136:1 | C1 |
|
||||
| classes.kt:119:13:121:13 | class ... | classes.kt:119:13:121:13 | Local2 | classes.kt:118:9:123:9 | localFn | classes.kt:109:1:136:1 | C1 |
|
||||
| classes.kt:129:17:131:17 | class ... | classes.kt:129:17:131:17 | Local3 | classes.kt:128:13:133:13 | fn | classes.kt:127:16:134:9 | new Object(...) { ... } |
|
||||
| localClassField.kt:3:9:3:19 | class ... | localClassField.kt:3:9:3:19 | L | localClassField.kt:1:1:11:1 | A | localClassField.kt:1:1:11:1 | A |
|
||||
| localClassField.kt:8:9:8:19 | class ... | localClassField.kt:8:9:8:19 | L | localClassField.kt:1:1:11:1 | A | localClassField.kt:1:1:11:1 | A |
|
||||
| local_anonymous.kt:11:9:11:24 | class ... | local_anonymous.kt:11:9:11:24 | | local_anonymous.kt:10:5:13:5 | fn2 | local_anonymous.kt:3:1:36:1 | Class1 |
|
||||
| local_anonymous.kt:25:9:25:27 | class ... | local_anonymous.kt:25:9:25:27 | LocalClass | local_anonymous.kt:24:5:27:5 | fn5 | local_anonymous.kt:3:1:36:1 | Class1 |
|
||||
|
||||
11
java/ql/test/kotlin/library-tests/classes/localClassField.kt
Normal file
11
java/ql/test/kotlin/library-tests/classes/localClassField.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
class A {
|
||||
val x = if (true) {
|
||||
class L { }
|
||||
L()
|
||||
} else {}
|
||||
|
||||
val y = if (true) {
|
||||
class L { }
|
||||
L()
|
||||
} else {}
|
||||
}
|
||||
@@ -49,6 +49,9 @@
|
||||
| file://<external>/SuperChain2.class:0:0:0:0 | SuperChain2<T5,String> | file://<external>/SuperChain1.class:0:0:0:0 | SuperChain1<T5,String> |
|
||||
| generic_anonymous.kt:1:1:9:1 | Generic | file://<external>/Object.class:0:0:0:0 | Object |
|
||||
| generic_anonymous.kt:3:19:5:3 | new Object(...) { ... } | file://<external>/Object.class:0:0:0:0 | Object |
|
||||
| localClassField.kt:1:1:11:1 | A | file://<external>/Object.class:0:0:0:0 | Object |
|
||||
| localClassField.kt:3:9:3:19 | L | file://<external>/Object.class:0:0:0:0 | Object |
|
||||
| localClassField.kt:8:9:8:19 | L | file://<external>/Object.class:0:0:0:0 | Object |
|
||||
| local_anonymous.kt:3:1:36:1 | Class1 | file://<external>/Object.class:0:0:0:0 | Object |
|
||||
| local_anonymous.kt:5:16:7:9 | new Object(...) { ... } | file://<external>/Object.class:0:0:0:0 | Object |
|
||||
| local_anonymous.kt:11:9:11:24 | | file://<external>/Object.class:0:0:0:0 | Object |
|
||||
|
||||
@@ -12,7 +12,7 @@ commentOwners
|
||||
| comments.kt:4:1:11:3 | /**\n * A group of *members*.\n *\n * This class has no useful logic; it's just a documentation example.\n *\n * @property name the name of this group.\n * @constructor Creates an empty group.\n */ | comments.kt:12:1:31:1 | Group |
|
||||
| comments.kt:14:5:16:7 | /**\n * Members of this group.\n */ | comments.kt:17:5:17:46 | members |
|
||||
| comments.kt:14:5:16:7 | /**\n * Members of this group.\n */ | comments.kt:17:5:17:46 | members |
|
||||
| comments.kt:14:5:16:7 | /**\n * Members of this group.\n */ | comments.kt:17:13:17:46 | getMembers |
|
||||
| comments.kt:14:5:16:7 | /**\n * Members of this group.\n */ | comments.kt:17:13:17:46 | getMembers$private |
|
||||
| comments.kt:19:5:22:7 | /**\n * Adds a [member] to this group.\n * @return the new size of the group.\n */ | comments.kt:23:5:26:5 | add |
|
||||
| comments.kt:35:5:35:34 | /** Medium is in the middle */ | comments.kt:36:5:36:14 | Medium |
|
||||
| comments.kt:37:5:37:23 | /** This is high */ | comments.kt:38:5:38:11 | High |
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
| companion_objects.kt:1:1:6:1 | MyClass | companion_objects.kt:3:5:5:5 | MyClassCompanion | companion_objects.kt:3:5:5:5 | MyClassCompanion | final,public,static |
|
||||
| companion_objects.kt:8:1:13:1 | MyInterface | companion_objects.kt:10:5:12:5 | MyInterfaceCompanion | companion_objects.kt:10:5:12:5 | MyInterfaceCompanion | final,public,static |
|
||||
| companion_objects.kt:1:1:6:1 | MyClass | companion_objects.kt:3:5:5:5 | MyClassCompanion | companion_objects.kt:3:5:5:5 | MyClassCompanion | companion_objects.kt:1:1:6:1 | MyClass | final,public,static |
|
||||
| companion_objects.kt:8:1:13:1 | MyInterface | companion_objects.kt:10:5:12:5 | MyInterfaceCompanion | companion_objects.kt:10:5:12:5 | MyInterfaceCompanion | companion_objects.kt:8:1:13:1 | MyInterface | final,public,static |
|
||||
|
||||
@@ -5,4 +5,4 @@ where
|
||||
c.fromSource() and
|
||||
cco = c.getCompanionObject() and
|
||||
f = cco.getInstance()
|
||||
select c, f, cco, concat(f.getAModifier().toString(), ",")
|
||||
select c, f, cco, f.getDeclaringType(), concat(f.getAModifier().toString(), ",")
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
| dc.kt:0:0:0:0 | times(...) | Int.times |
|
||||
| dc.kt:0:0:0:0 | toString(...) | Arrays.toString |
|
||||
| dc.kt:0:0:0:0 | toString(...) | Arrays.toString |
|
||||
| dc.kt:1:1:1:71 | super(...) | Any.Any |
|
||||
| dc.kt:1:1:1:71 | super(...) | Object.Object |
|
||||
|
||||
22
java/ql/test/kotlin/library-tests/dataflow/foreach/C1.java
Normal file
22
java/ql/test/kotlin/library-tests/dataflow/foreach/C1.java
Normal file
@@ -0,0 +1,22 @@
|
||||
public final class C1 {
|
||||
public final String taint(String t) {
|
||||
return t;
|
||||
}
|
||||
|
||||
public final void sink(Object a) {
|
||||
}
|
||||
|
||||
public final void test() {
|
||||
String[] l = new String[]{this.taint("a"), ""};
|
||||
this.sink(l);
|
||||
this.sink(l[0]);
|
||||
|
||||
for(int i = 0; i < l.length; i++) {
|
||||
this.sink(l[i]);
|
||||
}
|
||||
|
||||
for (String s : l) {
|
||||
this.sink(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
18
java/ql/test/kotlin/library-tests/dataflow/foreach/C2.kt
Normal file
18
java/ql/test/kotlin/library-tests/dataflow/foreach/C2.kt
Normal file
@@ -0,0 +1,18 @@
|
||||
class C2 {
|
||||
fun taint(t: String): String {
|
||||
return t
|
||||
}
|
||||
|
||||
fun sink(a: Any?) {}
|
||||
fun test() {
|
||||
val l = arrayOf(taint("a"), "")
|
||||
sink(l)
|
||||
sink(l[0])
|
||||
for (i in l.indices) {
|
||||
sink(l[i])
|
||||
}
|
||||
for (s in l) {
|
||||
sink(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
| C1.java:10:44:10:46 | "a" | C1.java:11:17:11:17 | l |
|
||||
| C1.java:10:44:10:46 | "a" | C1.java:12:17:12:20 | ...[...] |
|
||||
| C1.java:10:44:10:46 | "a" | C1.java:15:20:15:23 | ...[...] |
|
||||
| C1.java:10:44:10:46 | "a" | C1.java:19:20:19:20 | s |
|
||||
| C2.kt:8:32:8:32 | a | C2.kt:9:14:9:14 | l |
|
||||
| C2.kt:8:32:8:32 | a | C2.kt:10:14:10:17 | ...[...] |
|
||||
| C2.kt:8:32:8:32 | a | C2.kt:12:18:12:21 | ...[...] |
|
||||
| C2.kt:8:32:8:32 | a | C2.kt:15:18:15:18 | s |
|
||||
19
java/ql/test/kotlin/library-tests/dataflow/foreach/test.ql
Normal file
19
java/ql/test/kotlin/library-tests/dataflow/foreach/test.ql
Normal file
@@ -0,0 +1,19 @@
|
||||
import java
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
class Conf extends TaintTracking::Configuration {
|
||||
Conf() { this = "qltest:foreach-array-iterator" }
|
||||
|
||||
override predicate isSource(DataFlow::Node n) {
|
||||
n.asExpr().(Argument).getCall().getCallee().hasName("taint")
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node n) {
|
||||
n.asExpr().(Argument).getCall().getCallee().hasName("sink")
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow::Node src, DataFlow::Node sink, Conf conf
|
||||
where conf.hasFlow(src, sink)
|
||||
select src, sink
|
||||
@@ -1717,86 +1717,6 @@
|
||||
| exprs.kt:268:3:268:9 | updated | exprs.kt:261:1:270:1 | inPlaceOperators | VarAccess |
|
||||
| exprs.kt:268:3:268:14 | ...%=... | exprs.kt:261:1:270:1 | inPlaceOperators | AssignRemExpr |
|
||||
| exprs.kt:268:14:268:14 | 1 | exprs.kt:261:1:270:1 | inPlaceOperators | IntegerLiteral |
|
||||
| file:///!unknown-binary-location/SomePredicate.class:0:0:0:0 | T | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/SomePredicate.class:0:0:0:0 | boolean | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function0.class:0:0:0:0 | R | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function1.class:0:0:0:0 | P1 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function1.class:0:0:0:0 | R | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function2.class:0:0:0:0 | P1 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function2.class:0:0:0:0 | P2 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function2.class:0:0:0:0 | R | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P1 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P2 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P3 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P4 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P5 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P6 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P7 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P8 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P9 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P10 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P11 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P12 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P13 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P14 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P15 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P16 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P17 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P18 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P19 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P20 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P21 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | P22 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function22.class:0:0:0:0 | R | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P1 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P2 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P3 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P4 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P5 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P6 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P7 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P8 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P9 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P10 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P11 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P12 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P13 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P14 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P15 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P16 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P17 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P18 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P19 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P20 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P21 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P22 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | P23 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function23.class:0:0:0:0 | R | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P1 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P2 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P3 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P4 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P5 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P6 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P7 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P8 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P9 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P10 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P11 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P12 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P13 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P14 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P15 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P16 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P17 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P18 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P19 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P20 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P21 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P22 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P23 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | P24 | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| file:///!unknown-binary-location/kotlin/Function24.class:0:0:0:0 | R | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| funcExprs.kt:1:1:1:46 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| funcExprs.kt:1:26:1:37 | Function0<Integer> | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| funcExprs.kt:1:26:1:37 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
|
||||
5
java/ql/test/kotlin/library-tests/extensions/A.java
Normal file
5
java/ql/test/kotlin/library-tests/extensions/A.java
Normal file
@@ -0,0 +1,5 @@
|
||||
class A {
|
||||
void method() {
|
||||
ExtensionsKt.someFun(new SomeClass(), "");
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
| A.java:3:9:3:49 | someFun(...) | A.java:3:9:3:20 | ExtensionsKt | A.java:3:30:3:44 | new SomeClass(...) |
|
||||
| A.java:3:9:3:49 | someFun(...) | A.java:3:9:3:20 | ExtensionsKt | A.java:3:47:3:48 | "" |
|
||||
| extensions.kt:21:17:21:38 | someClassMethod(...) | extensions.kt:21:5:21:15 | new SomeClass(...) | extensions.kt:21:34:21:36 | foo |
|
||||
| extensions.kt:22:17:22:30 | someFun(...) | extensions.kt:22:17:22:30 | ExtensionsKt | extensions.kt:22:5:22:15 | new SomeClass(...) |
|
||||
| extensions.kt:22:17:22:30 | someFun(...) | extensions.kt:22:17:22:30 | ExtensionsKt | extensions.kt:22:26:22:28 | foo |
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
| A.java:2:10:2:15 | method | file://:0:0:0:0 | void |
|
||||
| extensions.kt:3:5:3:38 | someClassMethod | file://:0:0:0:0 | void |
|
||||
| extensions.kt:6:5:6:41 | anotherClassMethod | file://:0:0:0:0 | void |
|
||||
| extensions.kt:9:1:9:36 | someFun | file://:0:0:0:0 | void |
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
parametersWithArgs
|
||||
| extensions.kt:3:25:3:34 | p1 | 0 | extensions.kt:21:34:21:36 | foo |
|
||||
| extensions.kt:6:28:6:37 | p1 | 0 | extensions.kt:25:40:25:42 | foo |
|
||||
| extensions.kt:9:5:9:13 | <this> | 0 | A.java:3:30:3:44 | new SomeClass(...) |
|
||||
| extensions.kt:9:5:9:13 | <this> | 0 | extensions.kt:22:5:22:15 | new SomeClass(...) |
|
||||
| extensions.kt:9:23:9:32 | p1 | 1 | A.java:3:47:3:48 | "" |
|
||||
| extensions.kt:9:23:9:32 | p1 | 1 | extensions.kt:22:26:22:28 | foo |
|
||||
| extensions.kt:10:5:10:16 | <this> | 0 | extensions.kt:26:5:26:18 | new AnotherClass(...) |
|
||||
| extensions.kt:10:29:10:38 | p1 | 1 | extensions.kt:26:32:26:34 | foo |
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
| Test.java:25:5:25:16 | hashCode(...) | hashCode | Object |
|
||||
| Test.java:26:5:26:17 | inheritMe(...) | inheritMe | Test |
|
||||
| Test.java:28:5:28:34 | inheritedInterfaceMethodJ(...) | inheritedInterfaceMethodJ | ParentIf |
|
||||
| Test.kt:23:7:23:16 | toString(...) | toString | Any |
|
||||
| Test.kt:24:7:24:15 | equals(...) | equals | Any |
|
||||
| Test.kt:25:7:25:16 | hashCode(...) | hashCode | Any |
|
||||
| Test.kt:23:7:23:16 | toString(...) | toString | Object |
|
||||
| Test.kt:24:7:24:15 | equals(...) | equals | Object |
|
||||
| Test.kt:25:7:25:16 | hashCode(...) | hashCode | Object |
|
||||
| Test.kt:26:7:26:17 | inheritMe(...) | inheritMe | TestKt |
|
||||
| Test.kt:28:9:28:35 | inheritedInterfaceMethodK(...) | inheritedInterfaceMethodK | ParentIf |
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
| Integer |
|
||||
| Object |
|
||||
@@ -0,0 +1 @@
|
||||
fun test(m: Map<Int, Int>) = m.getOrDefault(1, 2)
|
||||
@@ -0,0 +1,4 @@
|
||||
import java
|
||||
|
||||
from MethodAccess ma
|
||||
select ma.getCallee().getAParameter().getType().toString()
|
||||
@@ -0,0 +1 @@
|
||||
| clinit.kt:0:0:0:0 | <clinit> | file://:0:0:0:0 | void |
|
||||
3
java/ql/test/kotlin/library-tests/methods/clinit.kt
Normal file
3
java/ql/test/kotlin/library-tests/methods/clinit.kt
Normal file
@@ -0,0 +1,3 @@
|
||||
package foo.bar
|
||||
|
||||
var topLevelInt: Int = 0
|
||||
5
java/ql/test/kotlin/library-tests/methods/clinit.ql
Normal file
5
java/ql/test/kotlin/library-tests/methods/clinit.ql
Normal file
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
|
||||
from Method m
|
||||
where m.getName() = "<clinit>"
|
||||
select m, m.getReturnType()
|
||||
@@ -1,3 +1,17 @@
|
||||
| clinit.kt:3:1:3:24 | ...=... | AssignExpr |
|
||||
| clinit.kt:3:1:3:24 | ...=... | KtInitializerAssignExpr |
|
||||
| clinit.kt:3:1:3:24 | <set-?> | VarAccess |
|
||||
| clinit.kt:3:1:3:24 | ClinitKt | TypeAccess |
|
||||
| clinit.kt:3:1:3:24 | ClinitKt | TypeAccess |
|
||||
| clinit.kt:3:1:3:24 | ClinitKt | TypeAccess |
|
||||
| clinit.kt:3:1:3:24 | ClinitKt.topLevelInt | VarAccess |
|
||||
| clinit.kt:3:1:3:24 | ClinitKt.topLevelInt | VarAccess |
|
||||
| clinit.kt:3:1:3:24 | ClinitKt.topLevelInt | VarAccess |
|
||||
| clinit.kt:3:1:3:24 | Unit | TypeAccess |
|
||||
| clinit.kt:3:1:3:24 | int | TypeAccess |
|
||||
| clinit.kt:3:1:3:24 | int | TypeAccess |
|
||||
| clinit.kt:3:1:3:24 | int | TypeAccess |
|
||||
| clinit.kt:3:24:3:24 | 0 | IntegerLiteral |
|
||||
| methods2.kt:4:1:5:1 | Unit | TypeAccess |
|
||||
| methods2.kt:4:26:4:31 | int | TypeAccess |
|
||||
| methods2.kt:4:34:4:39 | int | TypeAccess |
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
methods
|
||||
| clinit.kt:0:0:0:0 | ClinitKt | clinit.kt:0:0:0:0 | <clinit> | <clinit>() | |
|
||||
| clinit.kt:0:0:0:0 | ClinitKt | clinit.kt:3:1:3:24 | getTopLevelInt | getTopLevelInt() | public, static |
|
||||
| clinit.kt:0:0:0:0 | ClinitKt | clinit.kt:3:1:3:24 | setTopLevelInt | setTopLevelInt(int) | public, static |
|
||||
| methods2.kt:0:0:0:0 | Methods2Kt | methods2.kt:4:1:5:1 | fooBarTopLevelMethod | fooBarTopLevelMethod(int,int) | public, static |
|
||||
| methods2.kt:7:1:10:1 | Class2 | methods2.kt:8:5:9:5 | fooBarClassMethod | fooBarClassMethod(int,int) | public |
|
||||
| methods3.kt:0:0:0:0 | Methods3Kt | methods3.kt:3:1:3:42 | fooBarTopLevelMethodExt | fooBarTopLevelMethodExt(int,int) | public, static |
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
| clinit.kt:3:1:3:24 | setTopLevelInt | clinit.kt:3:1:3:24 | <set-?> | 0 |
|
||||
| methods2.kt:4:1:5:1 | fooBarTopLevelMethod | methods2.kt:4:26:4:31 | x | 0 |
|
||||
| methods2.kt:4:1:5:1 | fooBarTopLevelMethod | methods2.kt:4:34:4:39 | y | 1 |
|
||||
| methods2.kt:8:5:9:5 | fooBarClassMethod | methods2.kt:8:27:8:32 | x | 0 |
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
| modifiers.kt:1:6:25:1 | X | Constructor | public |
|
||||
| modifiers.kt:2:5:2:21 | a | Field | private |
|
||||
| modifiers.kt:2:5:2:21 | a | Property | private |
|
||||
| modifiers.kt:2:13:2:21 | getA | Method | private |
|
||||
| modifiers.kt:2:13:2:21 | getA$private | Method | private |
|
||||
| modifiers.kt:3:5:3:23 | b | Field | private |
|
||||
| modifiers.kt:3:5:3:23 | b | Property | protected |
|
||||
| modifiers.kt:3:15:3:23 | getB | Method | protected |
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
class Ext : A<String>("Hello") { }
|
||||
@@ -0,0 +1,18 @@
|
||||
| file:///!unknown-binary-location/A.class:0:0:0:0 | A<String> | file:///!unknown-binary-location/A.class:0:0:0:0 | A<String> |
|
||||
| file:///!unknown-binary-location/A.class:0:0:0:0 | A<String> | file:///!unknown-binary-location/A.class:0:0:0:0 | getAnonType |
|
||||
| file:///!unknown-binary-location/If.class:0:0:0:0 | If<String> | file:///!unknown-binary-location/If.class:0:0:0:0 | getX |
|
||||
| file:///!unknown-binary-location/If.class:0:0:0:0 | If<T> | file:///!unknown-binary-location/If.class:0:0:0:0 | getX |
|
||||
| other.kt:1:1:1:34 | Ext | other.kt:1:1:1:34 | Ext |
|
||||
| test.kt:0:0:0:0 | TestKt | test.kt:19:1:19:38 | user |
|
||||
| test.kt:1:1:5:1 | If | test.kt:3:3:3:11 | getX |
|
||||
| test.kt:7:1:17:1 | A | test.kt:7:6:17:1 | A |
|
||||
| test.kt:7:1:17:1 | A | test.kt:9:3:11:3 | anonType |
|
||||
| test.kt:7:1:17:1 | A | test.kt:9:3:11:3 | getAnonType |
|
||||
| test.kt:7:1:17:1 | A | test.kt:13:3:15:3 | privateAnonType |
|
||||
| test.kt:7:1:17:1 | A | test.kt:13:11:15:3 | getPrivateAnonType$private |
|
||||
| test.kt:9:18:11:3 | new If<T>(...) { ... } | test.kt:9:18:11:3 | |
|
||||
| test.kt:9:18:11:3 | new If<T>(...) { ... } | test.kt:10:5:10:22 | x |
|
||||
| test.kt:9:18:11:3 | new If<T>(...) { ... } | test.kt:10:14:10:22 | getX |
|
||||
| test.kt:13:33:15:3 | new If<T>(...) { ... } | test.kt:13:33:15:3 | |
|
||||
| test.kt:13:33:15:3 | new If<T>(...) { ... } | test.kt:14:5:14:22 | x |
|
||||
| test.kt:13:33:15:3 | new If<T>(...) { ... } | test.kt:14:14:14:22 | getX |
|
||||
@@ -0,0 +1,19 @@
|
||||
interface If<T> {
|
||||
|
||||
val x : T
|
||||
|
||||
}
|
||||
|
||||
open class A<T>(t: T) {
|
||||
|
||||
val anonType = object : If<T> {
|
||||
override val x = t
|
||||
}
|
||||
|
||||
private val privateAnonType = object : If<T> {
|
||||
override val x = t
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun user(x: A<String>) = x.anonType.x
|
||||
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
|
||||
from ClassOrInterface ci, Member m
|
||||
where m = ci.getAMember() and ci.getSourceDeclaration().fromSource()
|
||||
select ci, m
|
||||
@@ -20,6 +20,8 @@ fieldDeclarations
|
||||
| properties.kt:38:5:38:34 | int internalProp; | properties.kt:38:5:38:34 | internalProp | 0 |
|
||||
| properties.kt:67:1:67:23 | int constVal; | properties.kt:67:1:67:23 | constVal | 0 |
|
||||
| properties.kt:70:5:70:16 | int prop; | properties.kt:70:5:70:16 | prop | 0 |
|
||||
| properties.kt:84:5:84:29 | int data; | properties.kt:84:5:84:29 | data | 0 |
|
||||
| properties.kt:92:5:93:18 | int data; | properties.kt:92:5:93:18 | data | 0 |
|
||||
#select
|
||||
| properties.kt:2:27:2:50 | constructorProp | properties.kt:2:27:2:50 | getConstructorProp | file://:0:0:0:0 | <none> | properties.kt:2:27:2:50 | constructorProp | public |
|
||||
| properties.kt:2:53:2:83 | mutableConstructorProp | properties.kt:2:53:2:83 | getMutableConstructorProp | properties.kt:2:53:2:83 | setMutableConstructorProp | properties.kt:2:53:2:83 | mutableConstructorProp | public |
|
||||
@@ -40,9 +42,13 @@ fieldDeclarations
|
||||
| properties.kt:30:5:31:29 | overrideGetterUseField | properties.kt:31:13:31:29 | getOverrideGetterUseField | properties.kt:30:5:31:29 | setOverrideGetterUseField | properties.kt:30:5:31:29 | overrideGetterUseField | public |
|
||||
| properties.kt:32:5:33:29 | useField | properties.kt:33:13:33:29 | getUseField | file://:0:0:0:0 | <none> | properties.kt:32:5:33:29 | useField | public |
|
||||
| properties.kt:34:5:34:36 | lateInitVar | properties.kt:34:14:34:36 | getLateInitVar | properties.kt:34:14:34:36 | setLateInitVar | properties.kt:34:5:34:36 | lateInitVar | public |
|
||||
| properties.kt:35:5:35:32 | privateProp | properties.kt:35:13:35:32 | getPrivateProp | file://:0:0:0:0 | <none> | properties.kt:35:5:35:32 | privateProp | private |
|
||||
| properties.kt:35:5:35:32 | privateProp | properties.kt:35:13:35:32 | getPrivateProp$private | file://:0:0:0:0 | <none> | properties.kt:35:5:35:32 | privateProp | private |
|
||||
| properties.kt:36:5:36:36 | protectedProp | properties.kt:36:15:36:36 | getProtectedProp | file://:0:0:0:0 | <none> | properties.kt:36:5:36:36 | protectedProp | protected |
|
||||
| properties.kt:37:5:37:30 | publicProp | properties.kt:37:12:37:30 | getPublicProp | file://:0:0:0:0 | <none> | properties.kt:37:5:37:30 | publicProp | public |
|
||||
| properties.kt:38:5:38:34 | internalProp | properties.kt:38:14:38:34 | getInternalProp | file://:0:0:0:0 | <none> | properties.kt:38:5:38:34 | internalProp | internal |
|
||||
| properties.kt:67:1:67:23 | constVal | properties.kt:67:7:67:23 | getConstVal | file://:0:0:0:0 | <none> | properties.kt:67:1:67:23 | constVal | public |
|
||||
| properties.kt:70:5:70:16 | prop | properties.kt:70:5:70:16 | getProp | file://:0:0:0:0 | <none> | properties.kt:70:5:70:16 | prop | public |
|
||||
| properties.kt:78:1:79:13 | x | properties.kt:79:5:79:13 | getX | file://:0:0:0:0 | <none> | file://:0:0:0:0 | <none> | public |
|
||||
| properties.kt:80:1:81:13 | x | properties.kt:81:5:81:13 | getX | file://:0:0:0:0 | <none> | file://:0:0:0:0 | <none> | public |
|
||||
| properties.kt:84:5:84:29 | data | properties.kt:84:13:84:29 | getData$private | properties.kt:84:13:84:29 | setData$private | properties.kt:84:5:84:29 | data | private |
|
||||
| properties.kt:92:5:93:18 | data | properties.kt:93:9:93:18 | getData | properties.kt:92:13:93:18 | setData$private | properties.kt:92:5:93:18 | data | private |
|
||||
|
||||
@@ -73,3 +73,26 @@ class C<T> {
|
||||
println(c.prop)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val Int.x : Int
|
||||
get() = 5
|
||||
val Double.x : Int
|
||||
get() = 5
|
||||
|
||||
class A {
|
||||
private var data: Int = 0
|
||||
|
||||
fun setData(p: Int) {
|
||||
data = p
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
private var data: Int = 5
|
||||
get() = 42
|
||||
|
||||
fun setData(p: Int) {
|
||||
data = p
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ reflection.kt:
|
||||
# 47| 0: [MethodAccess] get(...)
|
||||
# 47| -1: [ExtensionReceiverAccess] this
|
||||
# 47| 0: [SubExpr] ... - ...
|
||||
# 47| 0: [MethodAccess] getLength(...)
|
||||
# 47| 0: [MethodAccess] length(...)
|
||||
# 47| -1: [ExtensionReceiverAccess] this
|
||||
# 47| 1: [IntegerLiteral] 1
|
||||
# 49| 2: [Method] fn2
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
| test.kt:1:84:1:89 | length(...) | length |
|
||||
| test.kt:1:97:1:100 | size(...) | size |
|
||||
| test.kt:1:108:1:111 | size(...) | size |
|
||||
| test.kt:1:119:1:122 | keySet(...) | keySet |
|
||||
| test.kt:1:124:1:127 | size(...) | size |
|
||||
| test.kt:1:135:1:140 | values(...) | values |
|
||||
| test.kt:1:142:1:145 | size(...) | size |
|
||||
| test.kt:1:153:1:159 | entrySet(...) | entrySet |
|
||||
| test.kt:1:161:1:164 | size(...) | size |
|
||||
@@ -0,0 +1 @@
|
||||
fun test(cs: CharSequence, col: Collection<String>, map: Map<String, String>) = cs.length + col.size + map.size + map.keys.size + map.values.size + map.entries.size
|
||||
@@ -0,0 +1,4 @@
|
||||
import java
|
||||
|
||||
from MethodAccess ma
|
||||
select ma, ma.getCallee().toString()
|
||||
@@ -1,13 +1,13 @@
|
||||
| this.kt:2:1:58:1 | super(...) | Any |
|
||||
| this.kt:3:5:53:5 | super(...) | Any |
|
||||
| this.kt:2:1:58:1 | super(...) | Object |
|
||||
| this.kt:3:5:53:5 | super(...) | Object |
|
||||
| this.kt:9:66:17:13 | ...->... | |
|
||||
| this.kt:9:66:17:13 | super(...) | Any |
|
||||
| this.kt:9:66:17:13 | super(...) | Object |
|
||||
| this.kt:12:82:16:17 | ...->... | |
|
||||
| this.kt:12:82:16:17 | super(...) | Any |
|
||||
| this.kt:12:82:16:17 | super(...) | Object |
|
||||
| this.kt:19:42:21:13 | ...->... | |
|
||||
| this.kt:19:42:21:13 | super(...) | Any |
|
||||
| this.kt:19:42:21:13 | super(...) | Object |
|
||||
| this.kt:23:30:25:13 | ...->... | |
|
||||
| this.kt:23:30:25:13 | super(...) | Any |
|
||||
| this.kt:23:30:25:13 | super(...) | Object |
|
||||
| this.kt:36:13:36:25 | topLevelFun(...) | topLevelFun |
|
||||
| this.kt:37:13:37:22 | outerFun(...) | outerFun |
|
||||
| this.kt:38:13:38:22 | innerFun(...) | innerFun |
|
||||
@@ -19,5 +19,5 @@
|
||||
| this.kt:44:18:44:35 | topLevelInnerFun(...) | topLevelInnerFun |
|
||||
| this.kt:45:18:45:32 | outerInnerFun(...) | outerInnerFun |
|
||||
| this.kt:46:18:46:40 | topLevelOuterInnerFun(...) | topLevelOuterInnerFun |
|
||||
| this.kt:64:1:65:1 | super(...) | Any |
|
||||
| this.kt:67:1:68:1 | super(...) | Any |
|
||||
| this.kt:64:1:65:1 | super(...) | Object |
|
||||
| this.kt:67:1:68:1 | super(...) | Object |
|
||||
|
||||
@@ -1406,7 +1406,6 @@
|
||||
| ListIterator | GenericType, Interface, ParameterizedType |
|
||||
| ListIterator<> | Interface, RawType |
|
||||
| ListIterator<E> | Interface, ParameterizedType |
|
||||
| ListIterator<T> | Interface, ParameterizedType |
|
||||
| LoadOperation | GenericType, Interface, ParameterizedType |
|
||||
| LoadOperation<> | Interface, RawType |
|
||||
| LoadOperation<ByteBuffer,V,E,S> | Interface, ParameterizedType |
|
||||
|
||||
Reference in New Issue
Block a user