mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
Merge branch 'main' into jcogs33/update-externalapi-charpredicate
This commit is contained in:
@@ -119,7 +119,7 @@ class ExternalDeclExtractor(val logger: FileLogger, val invocationTrapFile: Stri
|
||||
|
||||
fileExtractor.extractClassSource(irDecl, extractDeclarations = !irDecl.isFileClass, extractStaticInitializer = false, extractPrivateMembers = false, extractFunctionBodies = false)
|
||||
} else {
|
||||
fileExtractor.extractDeclaration(irDecl, extractPrivateMembers = false, extractFunctionBodies = false)
|
||||
fileExtractor.extractDeclaration(irDecl, extractPrivateMembers = false, extractFunctionBodies = false, extractAnnotations = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,6 +207,7 @@ class KotlinExtractorGlobalState {
|
||||
val syntheticToRealClassMap = HashMap<IrClass, IrClass?>()
|
||||
val syntheticToRealFunctionMap = HashMap<IrFunction, IrFunction?>()
|
||||
val syntheticToRealFieldMap = HashMap<IrField, IrField?>()
|
||||
val syntheticRepeatableAnnotationContainers = HashMap<IrClass, IrClass>()
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -40,11 +40,15 @@ open class KotlinUsesExtractor(
|
||||
val pluginContext: IrPluginContext,
|
||||
val globalExtensionState: KotlinExtractorGlobalState
|
||||
) {
|
||||
val javaLangObject by lazy {
|
||||
val result = pluginContext.referenceClass(FqName("java.lang.Object"))?.owner
|
||||
result?.let { extractExternalClassLater(it) }
|
||||
result
|
||||
}
|
||||
fun referenceExternalClass(name: String) =
|
||||
pluginContext.referenceClass(FqName(name))?.owner.also {
|
||||
if (it == null)
|
||||
logger.warn("Unable to resolve external class $name")
|
||||
else
|
||||
extractExternalClassLater(it)
|
||||
}
|
||||
|
||||
val javaLangObject by lazy { referenceExternalClass("java.lang.Object") }
|
||||
|
||||
val javaLangObjectType by lazy {
|
||||
javaLangObject?.typeWith()
|
||||
@@ -885,11 +889,7 @@ open class KotlinUsesExtractor(
|
||||
else -> null
|
||||
}
|
||||
|
||||
val javaUtilCollection by lazy {
|
||||
val result = pluginContext.referenceClass(FqName("java.util.Collection"))?.owner
|
||||
result?.let { extractExternalClassLater(it) }
|
||||
result
|
||||
}
|
||||
val javaUtilCollection by lazy { referenceExternalClass("java.util.Collection") }
|
||||
|
||||
val wildcardCollectionType by lazy {
|
||||
javaUtilCollection?.let {
|
||||
@@ -1152,11 +1152,7 @@ open class KotlinUsesExtractor(
|
||||
return "@\"$prefix;{$parentId}.$name($paramTypeIds){$returnTypeId}${typeArgSuffix}\""
|
||||
}
|
||||
|
||||
val javaLangClass by lazy {
|
||||
val result = pluginContext.referenceClass(FqName("java.lang.Class"))?.owner
|
||||
result?.let { extractExternalClassLater(it) }
|
||||
result
|
||||
}
|
||||
val javaLangClass by lazy { referenceExternalClass("java.lang.Class") }
|
||||
|
||||
fun kClassToJavaClass(t: IrType): IrType {
|
||||
when(t) {
|
||||
|
||||
396
java/kotlin-extractor/src/main/kotlin/MetaAnnotationSupport.kt
Normal file
396
java/kotlin-extractor/src/main/kotlin/MetaAnnotationSupport.kt
Normal file
@@ -0,0 +1,396 @@
|
||||
package com.github.codeql
|
||||
|
||||
import com.github.codeql.utils.versions.copyParameterToFunction
|
||||
import com.github.codeql.utils.versions.createImplicitParameterDeclarationWithWrappedDescriptor
|
||||
import com.github.codeql.utils.versions.getAnnotationType
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addConstructor
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addGetter
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addProperty
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildClass
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildField
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrEnumEntry
|
||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||
import org.jetbrains.kotlin.ir.expressions.IrClassReference
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrGetEnumValue
|
||||
import org.jetbrains.kotlin.ir.expressions.IrVararg
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetEnumValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.types.typeWith
|
||||
import org.jetbrains.kotlin.ir.util.constructedClass
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||
import org.jetbrains.kotlin.ir.util.getAnnotation
|
||||
import org.jetbrains.kotlin.ir.util.hasAnnotation
|
||||
import org.jetbrains.kotlin.ir.util.hasEqualFqName
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.ir.util.primaryConstructor
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import java.lang.annotation.ElementType
|
||||
import java.util.HashSet
|
||||
|
||||
class MetaAnnotationSupport(private val logger: FileLogger, private val pluginContext: IrPluginContext, private val extractor: KotlinFileExtractor) {
|
||||
|
||||
// Taken from AdditionalIrUtils.kt (not available in Kotlin < 1.6)
|
||||
private val IrConstructorCall.annotationClass
|
||||
get() = this.symbol.owner.constructedClass
|
||||
|
||||
// Taken from AdditionalIrUtils.kt (not available in Kotlin < 1.6)
|
||||
private fun IrConstructorCall.isAnnotationWithEqualFqName(fqName: FqName): Boolean =
|
||||
annotationClass.hasEqualFqName(fqName)
|
||||
|
||||
// Adapted from RepeatedAnnotationLowering.kt
|
||||
fun groupRepeatableAnnotations(annotations: List<IrConstructorCall>): List<IrConstructorCall> {
|
||||
if (annotations.size < 2) return annotations
|
||||
|
||||
val annotationsByClass = annotations.groupByTo(mutableMapOf()) { it.annotationClass }
|
||||
if (annotationsByClass.values.none { it.size > 1 }) return annotations
|
||||
|
||||
val result = mutableListOf<IrConstructorCall>()
|
||||
for (annotation in annotations) {
|
||||
val annotationClass = annotation.annotationClass
|
||||
val grouped = annotationsByClass.remove(annotationClass) ?: continue
|
||||
if (grouped.size < 2) {
|
||||
result.add(grouped.single())
|
||||
continue
|
||||
}
|
||||
|
||||
val containerClass = getOrCreateContainerClass(annotationClass)
|
||||
if (containerClass != null)
|
||||
wrapAnnotationEntriesInContainer(annotationClass, containerClass, grouped)?.let {
|
||||
result.add(it)
|
||||
}
|
||||
else
|
||||
logger.warnElement("Failed to find an annotation container class", annotationClass)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Adapted from RepeatedAnnotationLowering.kt
|
||||
private fun getOrCreateContainerClass(annotationClass: IrClass): IrClass? {
|
||||
val metaAnnotations = annotationClass.annotations
|
||||
val jvmRepeatable = metaAnnotations.find { it.symbol.owner.parentAsClass.fqNameWhenAvailable == JvmAnnotationNames.REPEATABLE_ANNOTATION }
|
||||
return if (jvmRepeatable != null) {
|
||||
((jvmRepeatable.getValueArgument(0) as? IrClassReference)?.symbol as? IrClassSymbol)?.owner
|
||||
} else {
|
||||
getOrCreateSyntheticRepeatableAnnotationContainer(annotationClass)
|
||||
}
|
||||
}
|
||||
|
||||
// Adapted from RepeatedAnnotationLowering.kt
|
||||
private fun wrapAnnotationEntriesInContainer(
|
||||
annotationClass: IrClass,
|
||||
containerClass: IrClass,
|
||||
entries: List<IrConstructorCall>
|
||||
): IrConstructorCall? {
|
||||
val annotationType = annotationClass.typeWith()
|
||||
val containerConstructor = containerClass.primaryConstructor
|
||||
if (containerConstructor == null) {
|
||||
logger.warnElement("Expected container class to have a primary constructor", containerClass)
|
||||
return null
|
||||
} else {
|
||||
return IrConstructorCallImpl.fromSymbolOwner(containerClass.defaultType, containerConstructor.symbol).apply {
|
||||
putValueArgument(
|
||||
0,
|
||||
IrVarargImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
pluginContext.irBuiltIns.arrayClass.typeWith(annotationType),
|
||||
annotationType,
|
||||
entries
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Taken from AdditionalClassAnnotationLowering.kt
|
||||
private fun getApplicableTargetSet(c: IrClass): Set<KotlinTarget>? {
|
||||
val targetEntry = c.getAnnotation(StandardNames.FqNames.target) ?: return null
|
||||
return loadAnnotationTargets(targetEntry)
|
||||
}
|
||||
|
||||
// Taken from AdditionalClassAnnotationLowering.kt
|
||||
private fun loadAnnotationTargets(targetEntry: IrConstructorCall): Set<KotlinTarget>? {
|
||||
val valueArgument = targetEntry.getValueArgument(0) as? IrVararg ?: return null
|
||||
return valueArgument.elements.filterIsInstance<IrGetEnumValue>().mapNotNull {
|
||||
KotlinTarget.valueOrNull(it.symbol.owner.name.asString())
|
||||
}.toSet()
|
||||
}
|
||||
|
||||
private val javaAnnotationTargetElementType by lazy { extractor.referenceExternalClass("java.lang.annotation.ElementType") }
|
||||
|
||||
private val javaAnnotationTarget by lazy { extractor.referenceExternalClass("java.lang.annotation.Target") }
|
||||
|
||||
private fun findEnumEntry(c: IrClass, name: String) =
|
||||
c.declarations.filterIsInstance<IrEnumEntry>().find { it.name.asString() == name }
|
||||
|
||||
// Adapted from JvmSymbols.kt
|
||||
private val jvm6TargetMap by lazy {
|
||||
javaAnnotationTargetElementType?.let {
|
||||
val etMethod = findEnumEntry(it, "METHOD")
|
||||
mapOf(
|
||||
KotlinTarget.CLASS to findEnumEntry(it, "TYPE"),
|
||||
KotlinTarget.ANNOTATION_CLASS to findEnumEntry(it, "ANNOTATION_TYPE"),
|
||||
KotlinTarget.CONSTRUCTOR to findEnumEntry(it, "CONSTRUCTOR"),
|
||||
KotlinTarget.LOCAL_VARIABLE to findEnumEntry(it, "LOCAL_VARIABLE"),
|
||||
KotlinTarget.FUNCTION to etMethod,
|
||||
KotlinTarget.PROPERTY_GETTER to etMethod,
|
||||
KotlinTarget.PROPERTY_SETTER to etMethod,
|
||||
KotlinTarget.FIELD to findEnumEntry(it, "FIELD"),
|
||||
KotlinTarget.VALUE_PARAMETER to findEnumEntry(it, "PARAMETER")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Adapted from JvmSymbols.kt
|
||||
private val jvm8TargetMap by lazy {
|
||||
javaAnnotationTargetElementType?.let {
|
||||
jvm6TargetMap?.let { j6Map ->
|
||||
j6Map + mapOf(
|
||||
KotlinTarget.TYPE_PARAMETER to findEnumEntry(it, "TYPE_PARAMETER"),
|
||||
KotlinTarget.TYPE to findEnumEntry(it, "TYPE_USE")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAnnotationTargetMap() =
|
||||
if (pluginContext.platform?.any { it.targetPlatformVersion == JvmTarget.JVM_1_6 } == true)
|
||||
jvm6TargetMap
|
||||
else
|
||||
jvm8TargetMap
|
||||
|
||||
// Adapted from AdditionalClassAnnotationLowering.kt
|
||||
private fun generateTargetAnnotation(c: IrClass): IrConstructorCall? {
|
||||
if (c.hasAnnotation(JvmAnnotationNames.TARGET_ANNOTATION))
|
||||
return null
|
||||
val elementType = javaAnnotationTargetElementType ?: return null
|
||||
val targetType = javaAnnotationTarget ?: return null
|
||||
val targetConstructor = targetType.declarations.firstIsInstanceOrNull<IrConstructor>() ?: return null
|
||||
val targets = getApplicableTargetSet(c) ?: return null
|
||||
val annotationTargetMap = getAnnotationTargetMap() ?: return null
|
||||
|
||||
val javaTargets = targets.mapNotNullTo(HashSet()) { annotationTargetMap[it] }.sortedBy {
|
||||
ElementType.valueOf(it.symbol.owner.name.asString())
|
||||
}
|
||||
val vararg = IrVarargImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
type = pluginContext.irBuiltIns.arrayClass.typeWith(elementType.defaultType),
|
||||
varargElementType = elementType.defaultType
|
||||
)
|
||||
for (target in javaTargets) {
|
||||
vararg.elements.add(
|
||||
IrGetEnumValueImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, elementType.defaultType, target.symbol
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return IrConstructorCallImpl.fromSymbolOwner(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, targetConstructor.returnType, targetConstructor.symbol, 0
|
||||
).apply {
|
||||
putValueArgument(0, vararg)
|
||||
}
|
||||
}
|
||||
|
||||
private val javaAnnotationRetention by lazy { extractor.referenceExternalClass("java.lang.annotation.Retention") }
|
||||
private val javaAnnotationRetentionPolicy by lazy { extractor.referenceExternalClass("java.lang.annotation.RetentionPolicy") }
|
||||
private val javaAnnotationRetentionPolicyRuntime by lazy { javaAnnotationRetentionPolicy?.let { findEnumEntry(it, "RUNTIME") } }
|
||||
|
||||
private val annotationRetentionMap by lazy {
|
||||
javaAnnotationRetentionPolicy?.let {
|
||||
mapOf(
|
||||
KotlinRetention.SOURCE to findEnumEntry(it, "SOURCE"),
|
||||
KotlinRetention.BINARY to findEnumEntry(it, "CLASS"),
|
||||
KotlinRetention.RUNTIME to javaAnnotationRetentionPolicyRuntime
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Taken from AnnotationCodegen.kt (not available in Kotlin < 1.6.20)
|
||||
private fun IrClass.getAnnotationRetention(): KotlinRetention? {
|
||||
val retentionArgument =
|
||||
getAnnotation(StandardNames.FqNames.retention)?.getValueArgument(0)
|
||||
as? IrGetEnumValue ?: return null
|
||||
val retentionArgumentValue = retentionArgument.symbol.owner
|
||||
return KotlinRetention.valueOf(retentionArgumentValue.name.asString())
|
||||
}
|
||||
|
||||
// Taken from AdditionalClassAnnotationLowering.kt
|
||||
private fun generateRetentionAnnotation(irClass: IrClass): IrConstructorCall? {
|
||||
if (irClass.hasAnnotation(JvmAnnotationNames.RETENTION_ANNOTATION))
|
||||
return null
|
||||
val retentionMap = annotationRetentionMap ?: return null
|
||||
val kotlinRetentionPolicy = irClass.getAnnotationRetention()
|
||||
val javaRetentionPolicy = kotlinRetentionPolicy?.let { retentionMap[it] } ?: javaAnnotationRetentionPolicyRuntime ?: return null
|
||||
val retentionPolicyType = javaAnnotationRetentionPolicy ?: return null
|
||||
val retentionType = javaAnnotationRetention ?: return null
|
||||
val targetConstructor = retentionType.declarations.firstIsInstanceOrNull<IrConstructor>() ?: return null
|
||||
|
||||
return IrConstructorCallImpl.fromSymbolOwner(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, targetConstructor.returnType, targetConstructor.symbol, 0
|
||||
).apply {
|
||||
putValueArgument(
|
||||
0,
|
||||
IrGetEnumValueImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, retentionPolicyType.defaultType, javaRetentionPolicy.symbol
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private val javaAnnotationRepeatable by lazy { extractor.referenceExternalClass("java.lang.annotation.Repeatable") }
|
||||
private val kotlinAnnotationRepeatableContainer by lazy { extractor.referenceExternalClass("kotlin.jvm.internal.RepeatableContainer") }
|
||||
|
||||
// Taken from declarationBuilders.kt (not available in Kotlin < 1.6):
|
||||
private fun addDefaultGetter(p: IrProperty, parentClass: IrClass) {
|
||||
val field = p.backingField ?:
|
||||
run { logger.warnElement("Expected property to have a backing field", p); return }
|
||||
p.addGetter {
|
||||
origin = IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
|
||||
returnType = field.type
|
||||
}.apply {
|
||||
val thisReceiever = parentClass.thisReceiver ?:
|
||||
run { logger.warnElement("Expected property's parent class to have a receiver parameter", parentClass); return }
|
||||
val newParam = copyParameterToFunction(thisReceiever, this)
|
||||
dispatchReceiverParameter = newParam
|
||||
body = factory.createBlockBody(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf(
|
||||
IrReturnImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
pluginContext.irBuiltIns.nothingType,
|
||||
symbol,
|
||||
IrGetFieldImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
field.symbol,
|
||||
field.type,
|
||||
IrGetValueImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
newParam.type,
|
||||
newParam.symbol
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Taken from JvmCachedDeclarations.kt
|
||||
private fun getOrCreateSyntheticRepeatableAnnotationContainer(annotationClass: IrClass) =
|
||||
extractor.globalExtensionState.syntheticRepeatableAnnotationContainers.getOrPut(annotationClass) {
|
||||
val containerClass = pluginContext.irFactory.buildClass {
|
||||
kind = ClassKind.ANNOTATION_CLASS
|
||||
name = Name.identifier("Container")
|
||||
}.apply {
|
||||
createImplicitParameterDeclarationWithWrappedDescriptor()
|
||||
parent = annotationClass
|
||||
superTypes = listOf(getAnnotationType(pluginContext))
|
||||
}
|
||||
|
||||
val propertyName = Name.identifier("value")
|
||||
val propertyType = pluginContext.irBuiltIns.arrayClass.typeWith(annotationClass.typeWith())
|
||||
|
||||
containerClass.addConstructor {
|
||||
isPrimary = true
|
||||
}.apply {
|
||||
addValueParameter(propertyName.identifier, propertyType)
|
||||
}
|
||||
|
||||
containerClass.addProperty {
|
||||
name = propertyName
|
||||
}.apply property@{
|
||||
backingField = pluginContext.irFactory.buildField {
|
||||
name = propertyName
|
||||
type = propertyType
|
||||
}.apply {
|
||||
parent = containerClass
|
||||
correspondingPropertySymbol = this@property.symbol
|
||||
}
|
||||
addDefaultGetter(this, containerClass)
|
||||
}
|
||||
|
||||
val repeatableContainerAnnotation = kotlinAnnotationRepeatableContainer?.constructors?.single()
|
||||
|
||||
containerClass.annotations = annotationClass.annotations
|
||||
.filter {
|
||||
it.isAnnotationWithEqualFqName(StandardNames.FqNames.retention) ||
|
||||
it.isAnnotationWithEqualFqName(StandardNames.FqNames.target)
|
||||
}
|
||||
.map { it.deepCopyWithSymbols(containerClass) } +
|
||||
listOfNotNull(
|
||||
repeatableContainerAnnotation?.let {
|
||||
IrConstructorCallImpl.fromSymbolOwner(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, it.returnType, it.symbol, 0
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
containerClass
|
||||
}
|
||||
|
||||
// Adapted from AdditionalClassAnnotationLowering.kt
|
||||
private fun generateRepeatableAnnotation(irClass: IrClass, extractAnnotationTypeAccesses: Boolean): IrConstructorCall? {
|
||||
if (!irClass.hasAnnotation(StandardNames.FqNames.repeatable) ||
|
||||
irClass.hasAnnotation(JvmAnnotationNames.REPEATABLE_ANNOTATION)
|
||||
) return null
|
||||
|
||||
val repeatableConstructor = javaAnnotationRepeatable?.declarations?.firstIsInstanceOrNull<IrConstructor>() ?: return null
|
||||
|
||||
val containerClass = getOrCreateSyntheticRepeatableAnnotationContainer(irClass)
|
||||
// Whenever a repeatable annotation with a Kotlin-synthesised container is extracted, extract the synthetic container to the same trap file.
|
||||
extractor.extractClassSource(containerClass, extractDeclarations = true, extractStaticInitializer = true, extractPrivateMembers = true, extractFunctionBodies = extractAnnotationTypeAccesses)
|
||||
|
||||
val containerReference = IrClassReferenceImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, pluginContext.irBuiltIns.kClassClass.typeWith(containerClass.defaultType),
|
||||
containerClass.symbol, containerClass.defaultType
|
||||
)
|
||||
return IrConstructorCallImpl.fromSymbolOwner(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, repeatableConstructor.returnType, repeatableConstructor.symbol, 0
|
||||
).apply {
|
||||
putValueArgument(0, containerReference)
|
||||
}
|
||||
}
|
||||
|
||||
private val javaAnnotationDocumented by lazy { extractor.referenceExternalClass("java.lang.annotation.Documented") }
|
||||
|
||||
// Taken from AdditionalClassAnnotationLowering.kt
|
||||
private fun generateDocumentedAnnotation(irClass: IrClass): IrConstructorCall? {
|
||||
if (!irClass.hasAnnotation(StandardNames.FqNames.mustBeDocumented) ||
|
||||
irClass.hasAnnotation(JvmAnnotationNames.DOCUMENTED_ANNOTATION)
|
||||
) return null
|
||||
|
||||
val documentedConstructor = javaAnnotationDocumented?.declarations?.firstIsInstanceOrNull<IrConstructor>() ?: return null
|
||||
|
||||
return IrConstructorCallImpl.fromSymbolOwner(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, documentedConstructor.returnType, documentedConstructor.symbol, 0
|
||||
)
|
||||
}
|
||||
|
||||
fun generateJavaMetaAnnotations(c: IrClass, extractAnnotationTypeAccesses: Boolean) =
|
||||
// This is essentially AdditionalClassAnnotationLowering adapted to run outside the backend.
|
||||
listOfNotNull(generateTargetAnnotation(c), generateRetentionAnnotation(c), generateRepeatableAnnotation(c, extractAnnotationTypeAccesses), generateDocumentedAnnotation(c))
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import java.util.Stack
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
|
||||
class LogCounter() {
|
||||
public val diagnosticCounts = mutableMapOf<String, Int>()
|
||||
public val diagnosticInfo = mutableMapOf<String, Pair<Severity, Int>>()
|
||||
public val diagnosticLimit: Int
|
||||
init {
|
||||
diagnosticLimit = System.getenv("CODEQL_EXTRACTOR_KOTLIN_DIAGNOSTIC_LIMIT")?.toIntOrNull() ?: 100
|
||||
@@ -114,12 +114,23 @@ open class LoggerBase(val logCounter: LogCounter) {
|
||||
if(diagnosticLoc == null) {
|
||||
" Missing caller information.\n"
|
||||
} else {
|
||||
val count = logCounter.diagnosticCounts.getOrDefault(diagnosticLoc, 0) + 1
|
||||
logCounter.diagnosticCounts[diagnosticLoc] = count
|
||||
val oldInfo = logCounter.diagnosticInfo.getOrDefault(diagnosticLoc, Pair(severity, 0))
|
||||
if(severity != oldInfo.first) {
|
||||
// We don't want to get in a loop, so just emit this
|
||||
// directly without going through the diagnostic
|
||||
// counting machinery
|
||||
if (verbosity >= 1) {
|
||||
val message = "Severity mismatch ($severity vs ${oldInfo.first}) at $diagnosticLoc"
|
||||
emitDiagnostic(tw, Severity.Error, "Inconsistency", message, message)
|
||||
}
|
||||
}
|
||||
val newCount = oldInfo.second + 1
|
||||
val newInfo = Pair(severity, newCount)
|
||||
logCounter.diagnosticInfo[diagnosticLoc] = newInfo
|
||||
when {
|
||||
logCounter.diagnosticLimit <= 0 -> ""
|
||||
count == logCounter.diagnosticLimit -> " Limit reached for diagnostics from $diagnosticLoc.\n"
|
||||
count > logCounter.diagnosticLimit -> return
|
||||
newCount == logCounter.diagnosticLimit -> " Limit reached for diagnostics from $diagnosticLoc.\n"
|
||||
newCount > logCounter.diagnosticLimit -> return
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
@@ -189,14 +200,16 @@ open class LoggerBase(val logCounter: LogCounter) {
|
||||
}
|
||||
|
||||
fun printLimitedDiagnosticCounts(tw: TrapWriter) {
|
||||
for((caller, count) in logCounter.diagnosticCounts) {
|
||||
for((caller, info) in logCounter.diagnosticInfo) {
|
||||
val severity = info.first
|
||||
val count = info.second
|
||||
if(count >= logCounter.diagnosticLimit) {
|
||||
// We don't know if this location relates to an error
|
||||
// or a warning, so we just declare hitting the limit
|
||||
// to be an error regardless.
|
||||
val message = "Total of $count diagnostics (reached limit of ${logCounter.diagnosticLimit}) from $caller."
|
||||
if (verbosity >= 1) {
|
||||
emitDiagnostic(tw, Severity.Error, "Limit", message, message)
|
||||
emitDiagnostic(tw, severity, "Limit", message, message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.github.codeql.utils.versions
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun getAnnotationType(context: IrPluginContext) =
|
||||
context.typeTranslator.translateType(context.builtIns.annotationType)
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.github.codeql.utils.versions
|
||||
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||
|
||||
fun copyParameterToFunction(p: IrValueParameter, f: IrFunction) = p.copyTo(f)
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.github.codeql.utils.versions
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||
|
||||
fun getAnnotationType(context: IrPluginContext) =
|
||||
context.irBuiltIns.annotationType
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.github.codeql.utils.versions
|
||||
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||
import org.jetbrains.kotlin.ir.util.copyTo
|
||||
|
||||
fun copyParameterToFunction(p: IrValueParameter, f: IrFunction) = p.copyTo(f)
|
||||
@@ -53,6 +53,8 @@ predicate shouldBeDeadEnd(ControlFlowNode n) {
|
||||
not exists(n.getFile().getRelativePath()) // TODO
|
||||
or
|
||||
n = any(ConstCase c).getValue(_) // TODO
|
||||
or
|
||||
n instanceof ErrorExpr // TODO
|
||||
}
|
||||
|
||||
from ControlFlowNode n, string s
|
||||
|
||||
@@ -41,7 +41,12 @@ predicate gapInChildren(Element e, int i) {
|
||||
// -1 can be skipped (type arguments from -2 down, no qualifier at -1,
|
||||
// then arguments from 0).
|
||||
// Can we also skip arguments, e.g. due to defaults for parameters?
|
||||
not (e instanceof MethodAccess and e.getFile().isKotlinSourceFile())
|
||||
not (e instanceof MethodAccess and e.getFile().isKotlinSourceFile()) and
|
||||
// Kotlin-extracted annotations can have missing children where a default
|
||||
// value should be, because kotlinc doesn't load annotation defaults and we
|
||||
// want to leave a space for another extractor to fill in the default if it
|
||||
// is able.
|
||||
not e instanceof Annotation
|
||||
}
|
||||
|
||||
predicate lateFirstChild(Element e, int i) {
|
||||
@@ -59,7 +64,12 @@ predicate lateFirstChild(Element e, int i) {
|
||||
not (e instanceof LocalVariableDeclStmt and i = 1 and not exists(nthChildOf(e, 2))) and
|
||||
// For statements may or may not declare a new variable (child 0), or
|
||||
// have a condition (child 1).
|
||||
not (e instanceof ForStmt and i = [1, 2])
|
||||
not (e instanceof ForStmt and i = [1, 2]) and
|
||||
// Kotlin-extracted annotations can have missing children where a default
|
||||
// value should be, because kotlinc doesn't load annotation defaults and we
|
||||
// want to leave a space for another extractor to fill in the default if it
|
||||
// is able.
|
||||
not e instanceof Annotation
|
||||
}
|
||||
|
||||
from Element e, int i, string problem
|
||||
|
||||
@@ -0,0 +1,301 @@
|
||||
User.java:
|
||||
# 0| [CompilationUnit] User
|
||||
# 1| 1: [Class] User
|
||||
# 3| 2: [Method] user
|
||||
# 3| 3: [TypeAccess] void
|
||||
#-----| 4: (Parameters)
|
||||
# 3| 0: [Parameter] a1
|
||||
# 3| 0: [TypeAccess] Ann1
|
||||
# 3| 1: [Parameter] a2
|
||||
# 3| 0: [TypeAccess] Ann2
|
||||
# 3| 5: [BlockStmt] { ... }
|
||||
# 4| 0: [ExprStmt] <Expr>;
|
||||
# 4| 0: [MethodAccess] x(...)
|
||||
# 4| -1: [VarAccess] a1
|
||||
# 4| 1: [ExprStmt] <Expr>;
|
||||
# 4| 0: [MethodAccess] z(...)
|
||||
# 4| -1: [VarAccess] a2
|
||||
# 4| 2: [ExprStmt] <Expr>;
|
||||
# 4| 0: [ClassInstanceExpr] new Annotated(...)
|
||||
# 4| -3: [TypeAccess] Annotated
|
||||
# 4| 3: [ExprStmt] <Expr>;
|
||||
# 4| 0: [ClassInstanceExpr] new HasJavaDeprecatedAnnotationUsedByJava(...)
|
||||
# 4| -3: [TypeAccess] HasJavaDeprecatedAnnotationUsedByJava
|
||||
# 4| 4: [ExprStmt] <Expr>;
|
||||
# 4| 0: [ClassInstanceExpr] new HasKotlinDeprecatedAnnotationUsedByJava(...)
|
||||
# 4| -3: [TypeAccess] HasKotlinDeprecatedAnnotationUsedByJava
|
||||
ktUser.kt:
|
||||
# 0| [CompilationUnit] ktUser
|
||||
# 1| 1: [Class] KtUser
|
||||
# 1| 1: [Constructor] KtUser
|
||||
# 1| 5: [BlockStmt] { ... }
|
||||
# 1| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 1| 1: [BlockStmt] { ... }
|
||||
# 3| 2: [Method] user
|
||||
# 3| 3: [TypeAccess] Unit
|
||||
# 3| 5: [BlockStmt] { ... }
|
||||
# 4| 0: [LocalVariableDeclStmt] var ...;
|
||||
# 4| 1: [LocalVariableDeclExpr] a
|
||||
# 4| 0: [ClassInstanceExpr] new AnnotatedUsedByKotlin(...)
|
||||
# 4| -3: [TypeAccess] AnnotatedUsedByKotlin
|
||||
# 5| 1: [LocalVariableDeclStmt] var ...;
|
||||
# 5| 1: [LocalVariableDeclExpr] b
|
||||
# 5| 0: [ClassInstanceExpr] new HasJavaDeprecatedAnnotationUsedByKotlin(...)
|
||||
# 5| -3: [TypeAccess] HasJavaDeprecatedAnnotationUsedByKotlin
|
||||
# 6| 2: [LocalVariableDeclStmt] var ...;
|
||||
# 6| 1: [LocalVariableDeclExpr] c
|
||||
# 6| 0: [ClassInstanceExpr] new HasKotlinDeprecatedAnnotationUsedByKotlin(...)
|
||||
# 6| -3: [TypeAccess] HasKotlinDeprecatedAnnotationUsedByKotlin
|
||||
# 8| 3: [ExprStmt] <Expr>;
|
||||
# 8| 0: [ImplicitCoercionToUnitExpr] <implicit coercion to unit>
|
||||
# 8| 0: [TypeAccess] Unit
|
||||
# 8| 1: [MethodAccess] isJavaLetter(...)
|
||||
# 8| -1: [TypeAccess] Character
|
||||
# 8| 0: [CharacterLiteral] a
|
||||
test.kt:
|
||||
# 0| [CompilationUnit] test
|
||||
# 4| 1: [Interface] Ann1
|
||||
#-----| -3: (Annotations)
|
||||
# 0| 1: [Annotation] Retention
|
||||
# 0| 1: [VarAccess] RetentionPolicy.RUNTIME
|
||||
# 0| -1: [TypeAccess] RetentionPolicy
|
||||
# 4| 1: [Method] x
|
||||
# 4| 3: [TypeAccess] int
|
||||
# 4| 2: [Method] y
|
||||
# 4| 3: [TypeAccess] Ann2
|
||||
# 4| 3: [Method] z
|
||||
# 4| 3: [TypeAccess] DayOfWeek
|
||||
# 6| 2: [Interface] Ann2
|
||||
#-----| -3: (Annotations)
|
||||
# 0| 1: [Annotation] Retention
|
||||
# 0| 1: [VarAccess] RetentionPolicy.RUNTIME
|
||||
# 0| -1: [TypeAccess] RetentionPolicy
|
||||
# 6| 1: [Method] z
|
||||
# 6| 3: [TypeAccess] String
|
||||
# 6| 2: [Method] w
|
||||
# 6| 3: [TypeAccess] Class<?>
|
||||
# 6| 0: [WildcardTypeAccess] ? ...
|
||||
# 6| 3: [Method] v
|
||||
# 6| 3: [TypeAccess] int[]
|
||||
# 6| 4: [Method] u
|
||||
# 6| 3: [TypeAccess] Ann3[]
|
||||
# 6| 0: [TypeAccess] Ann3
|
||||
# 6| 5: [Method] t
|
||||
# 6| 3: [TypeAccess] Class<?>[]
|
||||
# 6| 0: [TypeAccess] Class<?>
|
||||
# 6| 0: [WildcardTypeAccess] ? ...
|
||||
# 8| 3: [Interface] Ann3
|
||||
#-----| -3: (Annotations)
|
||||
# 0| 1: [Annotation] Retention
|
||||
# 0| 1: [VarAccess] RetentionPolicy.RUNTIME
|
||||
# 0| -1: [TypeAccess] RetentionPolicy
|
||||
# 8| 1: [Method] a
|
||||
# 8| 3: [TypeAccess] int
|
||||
# 10| 4: [GenericType,Interface,ParameterizedType] GenericAnnotation
|
||||
#-----| -3: (Annotations)
|
||||
# 0| 1: [Annotation] Retention
|
||||
# 0| 1: [VarAccess] RetentionPolicy.RUNTIME
|
||||
# 0| -1: [TypeAccess] RetentionPolicy
|
||||
#-----| -2: (Generic Parameters)
|
||||
# 10| 0: [TypeVariable] T
|
||||
# 10| 1: [Method] x
|
||||
# 10| 3: [TypeAccess] Class<T>
|
||||
# 10| 0: [TypeAccess] T
|
||||
# 10| 2: [Method] y
|
||||
# 10| 3: [TypeAccess] Class<T>[]
|
||||
# 10| 0: [TypeAccess] Class<T>
|
||||
# 10| 0: [TypeAccess] T
|
||||
# 12| 6: [Interface] VarargAnnotation
|
||||
#-----| -3: (Annotations)
|
||||
# 0| 1: [Annotation] Repeatable
|
||||
# 0| 1: [TypeLiteral] Container.class
|
||||
# 0| 0: [TypeAccess] Container
|
||||
# 0| 2: [Annotation] Retention
|
||||
# 0| 1: [VarAccess] RetentionPolicy.RUNTIME
|
||||
# 0| -1: [TypeAccess] RetentionPolicy
|
||||
# 12| 3: [Annotation] Repeatable
|
||||
# 0| 1: [Interface] Container
|
||||
#-----| -3: (Annotations)
|
||||
# 0| 1: [Annotation] RepeatableContainer
|
||||
# 0| 2: [Annotation] Retention
|
||||
# 0| 1: [VarAccess] RetentionPolicy.RUNTIME
|
||||
# 0| -1: [TypeAccess] RetentionPolicy
|
||||
# 0| 1: [Method] value
|
||||
# 0| 3: [TypeAccess] VarargAnnotation[]
|
||||
# 0| 0: [TypeAccess] VarargAnnotation
|
||||
# 13| 2: [Method] x
|
||||
# 13| 3: [TypeAccess] int[]
|
||||
# 15| 7: [Interface] AnnWithDefaults
|
||||
#-----| -3: (Annotations)
|
||||
# 0| 1: [Annotation] Retention
|
||||
# 0| 1: [VarAccess] RetentionPolicy.RUNTIME
|
||||
# 0| -1: [TypeAccess] RetentionPolicy
|
||||
# 15| 1: [Method] x
|
||||
# 15| 3: [TypeAccess] int
|
||||
# 15| 2: [Method] y
|
||||
# 15| 3: [TypeAccess] String
|
||||
# 15| 3: [Method] z
|
||||
# 15| 3: [TypeAccess] DayOfWeek
|
||||
# 15| 4: [Method] w
|
||||
# 15| 3: [TypeAccess] Ann3[]
|
||||
# 15| 0: [TypeAccess] Ann3
|
||||
# 17| 8: [Class] Annotated
|
||||
#-----| -3: (Annotations)
|
||||
# 0| 1: [Annotation] Container
|
||||
# 0| 1: [ArrayInit] {...}
|
||||
# 19| 1: [Annotation] VarargAnnotation
|
||||
# 0| 1: [ArrayInit] {...}
|
||||
# 20| 2: [Annotation] VarargAnnotation
|
||||
# 0| 1: [ArrayInit] {...}
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 21| 3: [Annotation] VarargAnnotation
|
||||
# 0| 1: [ArrayInit] {...}
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 0| 2: [IntegerLiteral] 2
|
||||
# 22| 4: [Annotation] VarargAnnotation
|
||||
# 0| 1: [ArrayInit] {...}
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 0| 2: [IntegerLiteral] 2
|
||||
# 0| 3: [IntegerLiteral] 3
|
||||
# 23| 5: [Annotation] VarargAnnotation
|
||||
# 0| 1: [ArrayInit] {...}
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 0| 2: [IntegerLiteral] 2
|
||||
# 0| 3: [IntegerLiteral] 3
|
||||
# 17| 2: [Annotation] Ann1
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 0| 2: [Annotation] Ann2
|
||||
# 0| 1: [StringLiteral] "Hello"
|
||||
# 0| 2: [TypeLiteral] String.class
|
||||
# 0| 0: [TypeAccess] String
|
||||
# 0| 3: [ArrayInit] {...}
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 0| 2: [IntegerLiteral] 2
|
||||
# 0| 3: [IntegerLiteral] 3
|
||||
# 0| 4: [ArrayInit] {...}
|
||||
# 0| 1: [Annotation] Ann3
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 0| 2: [Annotation] Ann3
|
||||
# 0| 1: [IntegerLiteral] 2
|
||||
# 0| 5: [ArrayInit] {...}
|
||||
# 0| 1: [TypeLiteral] String.class
|
||||
# 0| 0: [TypeAccess] String
|
||||
# 0| 2: [TypeLiteral] int.class
|
||||
# 0| 0: [TypeAccess] int
|
||||
# 0| 3: [VarAccess] DayOfWeek.MONDAY
|
||||
# 0| -1: [TypeAccess] DayOfWeek
|
||||
# 18| 3: [Annotation] GenericAnnotation
|
||||
# 0| 1: [TypeLiteral] String.class
|
||||
# 0| 0: [TypeAccess] String
|
||||
# 0| 2: [ArrayInit] {...}
|
||||
# 0| 1: [TypeLiteral] String.class
|
||||
# 0| 0: [TypeAccess] String
|
||||
# 0| 2: [TypeLiteral] String.class
|
||||
# 0| 0: [TypeAccess] String
|
||||
# 24| 4: [Annotation] AnnWithDefaults
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 0| 2: [StringLiteral] "hello"
|
||||
# 0| 3: [VarAccess] DayOfWeek.TUESDAY
|
||||
# 0| -1: [TypeAccess] DayOfWeek
|
||||
# 0| 4: [ArrayInit] {...}
|
||||
# 0| 1: [Annotation] Ann3
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 25| 1: [Constructor] Annotated
|
||||
# 17| 5: [BlockStmt] { ... }
|
||||
# 17| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 25| 1: [BlockStmt] { ... }
|
||||
# 27| 9: [Class] AnnotatedUsedByKotlin
|
||||
#-----| -3: (Annotations)
|
||||
# 0| 1: [Annotation] Container
|
||||
# 0| 1: [ArrayInit] {...}
|
||||
# 29| 1: [Annotation] VarargAnnotation
|
||||
# 0| 1: [ArrayInit] {...}
|
||||
# 30| 2: [Annotation] VarargAnnotation
|
||||
# 0| 1: [ArrayInit] {...}
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 31| 3: [Annotation] VarargAnnotation
|
||||
# 0| 1: [ArrayInit] {...}
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 0| 2: [IntegerLiteral] 2
|
||||
# 32| 4: [Annotation] VarargAnnotation
|
||||
# 0| 1: [ArrayInit] {...}
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 0| 2: [IntegerLiteral] 2
|
||||
# 0| 3: [IntegerLiteral] 3
|
||||
# 33| 5: [Annotation] VarargAnnotation
|
||||
# 0| 1: [ArrayInit] {...}
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 0| 2: [IntegerLiteral] 2
|
||||
# 0| 3: [IntegerLiteral] 3
|
||||
# 27| 2: [Annotation] Ann1
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 0| 2: [Annotation] Ann2
|
||||
# 0| 1: [StringLiteral] "Hello"
|
||||
# 0| 2: [TypeLiteral] String.class
|
||||
# 0| 0: [TypeAccess] String
|
||||
# 0| 3: [ArrayInit] {...}
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 0| 2: [IntegerLiteral] 2
|
||||
# 0| 3: [IntegerLiteral] 3
|
||||
# 0| 4: [ArrayInit] {...}
|
||||
# 0| 1: [Annotation] Ann3
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 0| 2: [Annotation] Ann3
|
||||
# 0| 1: [IntegerLiteral] 2
|
||||
# 0| 5: [ArrayInit] {...}
|
||||
# 0| 1: [TypeLiteral] String.class
|
||||
# 0| 0: [TypeAccess] String
|
||||
# 0| 2: [TypeLiteral] int.class
|
||||
# 0| 0: [TypeAccess] int
|
||||
# 0| 3: [VarAccess] DayOfWeek.MONDAY
|
||||
# 0| -1: [TypeAccess] DayOfWeek
|
||||
# 28| 3: [Annotation] GenericAnnotation
|
||||
# 0| 1: [TypeLiteral] String.class
|
||||
# 0| 0: [TypeAccess] String
|
||||
# 0| 2: [ArrayInit] {...}
|
||||
# 0| 1: [TypeLiteral] String.class
|
||||
# 0| 0: [TypeAccess] String
|
||||
# 0| 2: [TypeLiteral] String.class
|
||||
# 0| 0: [TypeAccess] String
|
||||
# 34| 4: [Annotation] AnnWithDefaults
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 0| 2: [StringLiteral] "hello"
|
||||
# 0| 3: [VarAccess] DayOfWeek.TUESDAY
|
||||
# 0| -1: [TypeAccess] DayOfWeek
|
||||
# 0| 4: [ArrayInit] {...}
|
||||
# 0| 1: [Annotation] Ann3
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 35| 1: [Constructor] AnnotatedUsedByKotlin
|
||||
# 27| 5: [BlockStmt] { ... }
|
||||
# 27| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 35| 1: [BlockStmt] { ... }
|
||||
# 37| 10: [Class] HasJavaDeprecatedAnnotationUsedByJava
|
||||
#-----| -3: (Annotations)
|
||||
# 37| 1: [Annotation] Deprecated
|
||||
# 38| 1: [Constructor] HasJavaDeprecatedAnnotationUsedByJava
|
||||
# 37| 5: [BlockStmt] { ... }
|
||||
# 37| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 38| 1: [BlockStmt] { ... }
|
||||
# 40| 11: [Class] HasKotlinDeprecatedAnnotationUsedByJava
|
||||
#-----| -3: (Annotations)
|
||||
# 40| 1: [Annotation] Deprecated
|
||||
# 0| 1: [StringLiteral] "Kotlin deprecation message 1"
|
||||
# 41| 1: [Constructor] HasKotlinDeprecatedAnnotationUsedByJava
|
||||
# 40| 5: [BlockStmt] { ... }
|
||||
# 40| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 41| 1: [BlockStmt] { ... }
|
||||
# 43| 12: [Class] HasJavaDeprecatedAnnotationUsedByKotlin
|
||||
#-----| -3: (Annotations)
|
||||
# 43| 1: [Annotation] Deprecated
|
||||
# 44| 1: [Constructor] HasJavaDeprecatedAnnotationUsedByKotlin
|
||||
# 43| 5: [BlockStmt] { ... }
|
||||
# 43| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 44| 1: [BlockStmt] { ... }
|
||||
# 46| 13: [Class] HasKotlinDeprecatedAnnotationUsedByKotlin
|
||||
#-----| -3: (Annotations)
|
||||
# 46| 1: [Annotation] Deprecated
|
||||
# 0| 1: [StringLiteral] "Kotlin deprecation message 2"
|
||||
# 47| 1: [Constructor] HasKotlinDeprecatedAnnotationUsedByKotlin
|
||||
# 46| 5: [BlockStmt] { ... }
|
||||
# 46| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 47| 1: [BlockStmt] { ... }
|
||||
@@ -0,0 +1 @@
|
||||
semmle/code/java/PrintAst.ql
|
||||
@@ -0,0 +1,7 @@
|
||||
public class User {
|
||||
|
||||
public static void user(Ann1 a1, Ann2 a2) {
|
||||
a1.x(); a2.z(); new Annotated(); new HasJavaDeprecatedAnnotationUsedByJava(); new HasKotlinDeprecatedAnnotationUsedByJava();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
| HasJavaDeprecatedAnnotationUsedByJava | java.lang.Deprecated |
|
||||
| HasJavaDeprecatedAnnotationUsedByKotlin | java.lang.Deprecated |
|
||||
| HasKotlinDeprecatedAnnotationUsedByJava | kotlin.Deprecated |
|
||||
| HasKotlinDeprecatedAnnotationUsedByKotlin | kotlin.Deprecated |
|
||||
| isJavaLetter | java.lang.Deprecated |
|
||||
@@ -0,0 +1,11 @@
|
||||
import java
|
||||
|
||||
from Annotatable a, Annotation ann
|
||||
where
|
||||
(
|
||||
a.(Method).hasQualifiedName("java.lang", "Character", "isJavaLetter") or
|
||||
a.(ClassOrInterface).fromSource()
|
||||
) and
|
||||
ann = a.getAnAnnotation() and
|
||||
ann.getType().getName() = "Deprecated"
|
||||
select a.toString(), a.getAnAnnotation().getType().getQualifiedName()
|
||||
@@ -0,0 +1,5 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: integrationtest-annotation-id-consistency
|
||||
extensible: extNegativeSummaryModel
|
||||
data: []
|
||||
@@ -0,0 +1,11 @@
|
||||
public class KtUser {
|
||||
|
||||
fun user() {
|
||||
val a = AnnotatedUsedByKotlin()
|
||||
val b = HasJavaDeprecatedAnnotationUsedByKotlin()
|
||||
val c = HasKotlinDeprecatedAnnotationUsedByKotlin()
|
||||
// Use a Java-defined function carrying a java.lang.Deprecated annotation:
|
||||
java.lang.Character.isJavaLetter('a')
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
name: integrationtest-annotation-id-consistency
|
||||
dependencies:
|
||||
codeql/java-all: '*'
|
||||
codeql/java-tests: '*'
|
||||
codeql/java-queries: '*'
|
||||
dataExtensions:
|
||||
ext/*.model.yml
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import kotlin.reflect.KClass
|
||||
import java.time.DayOfWeek
|
||||
|
||||
annotation class Ann1(val x: Int, val y: Ann2, val z: DayOfWeek) { }
|
||||
|
||||
annotation class Ann2(val z: String, val w: KClass<*>, val v: IntArray, val u: Array<Ann3>, val t: Array<KClass<*>>) { }
|
||||
|
||||
annotation class Ann3(val a: Int) { }
|
||||
|
||||
annotation class GenericAnnotation<T : Any>(val x: KClass<T>, val y: Array<KClass<T>>) { }
|
||||
|
||||
@Repeatable
|
||||
annotation class VarargAnnotation(vararg val x: Int) { }
|
||||
|
||||
annotation class AnnWithDefaults(val x: Int = 1, val y: String = "hello", val z: DayOfWeek = DayOfWeek.TUESDAY, val w: Array<Ann3> = [Ann3(1)]) { }
|
||||
|
||||
@Ann1(1, Ann2("Hello", String::class, intArrayOf(1, 2, 3), arrayOf(Ann3(1), Ann3(2)), arrayOf(String::class, Int::class)), DayOfWeek.MONDAY)
|
||||
@GenericAnnotation<String>(String::class, arrayOf(String::class, String::class))
|
||||
@VarargAnnotation
|
||||
@VarargAnnotation(1)
|
||||
@VarargAnnotation(1, 2)
|
||||
@VarargAnnotation(*[1, 2, 3])
|
||||
@VarargAnnotation(*intArrayOf(1, 2, 3))
|
||||
@AnnWithDefaults
|
||||
class Annotated { }
|
||||
|
||||
@Ann1(1, Ann2("Hello", String::class, intArrayOf(1, 2, 3), arrayOf(Ann3(1), Ann3(2)), arrayOf(String::class, Int::class)), DayOfWeek.MONDAY)
|
||||
@GenericAnnotation<String>(String::class, arrayOf(String::class, String::class))
|
||||
@VarargAnnotation
|
||||
@VarargAnnotation(1)
|
||||
@VarargAnnotation(1, 2)
|
||||
@VarargAnnotation(*[1, 2, 3])
|
||||
@VarargAnnotation(*intArrayOf(1, 2, 3))
|
||||
@AnnWithDefaults
|
||||
class AnnotatedUsedByKotlin { }
|
||||
|
||||
@java.lang.Deprecated
|
||||
class HasJavaDeprecatedAnnotationUsedByJava
|
||||
|
||||
@kotlin.Deprecated("Kotlin deprecation message 1")
|
||||
class HasKotlinDeprecatedAnnotationUsedByJava
|
||||
|
||||
@java.lang.Deprecated
|
||||
class HasJavaDeprecatedAnnotationUsedByKotlin
|
||||
|
||||
@kotlin.Deprecated("Kotlin deprecation message 2")
|
||||
class HasKotlinDeprecatedAnnotationUsedByKotlin
|
||||
@@ -0,0 +1,5 @@
|
||||
from create_database_utils import *
|
||||
|
||||
os.mkdir('out')
|
||||
os.mkdir('out2')
|
||||
run_codeql_database_create(["kotlinc test.kt -d out", "javac User.java -cp out -d out2", "kotlinc ktUser.kt -cp out -d out2"], lang="java")
|
||||
@@ -1,7 +1,17 @@
|
||||
app/src/main/kotlin/testProject/App.kt:
|
||||
# 0| [CompilationUnit] App
|
||||
# 7| 1: [Class] Project
|
||||
#-----| -3: (Annotations)
|
||||
# 7| 1: [Annotation] Serializable
|
||||
# 0| 1: [Constructor] Project
|
||||
#-----| 1: (Annotations)
|
||||
# 0| 1: [Annotation] Deprecated
|
||||
# 0| 1: [StringLiteral] "This synthesized declaration should not be used directly"
|
||||
# 0| 2: [Annotation] ReplaceWith
|
||||
# 0| 1: [StringLiteral] ""
|
||||
# 0| 2: [ArrayInit] {...}
|
||||
# 0| 3: [VarAccess] DeprecationLevel.HIDDEN
|
||||
# 0| -1: [TypeAccess] DeprecationLevel
|
||||
#-----| 4: (Parameters)
|
||||
# 0| 0: [Parameter] seen1
|
||||
# 0| 0: [TypeAccess] int
|
||||
@@ -41,6 +51,8 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 7| 0: [TypeAccess] Project
|
||||
# 7| 1: [VarAccess] language
|
||||
# 0| 2: [Method] component1
|
||||
#-----| 1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 3: [TypeAccess] String
|
||||
# 0| 5: [BlockStmt] { ... }
|
||||
# 0| 0: [ReturnStmt] return ...
|
||||
@@ -53,9 +65,13 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 0| 0: [VarAccess] this.language
|
||||
# 0| -1: [ThisAccess] this
|
||||
# 0| 4: [Method] copy
|
||||
#-----| 1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 3: [TypeAccess] Project
|
||||
#-----| 4: (Parameters)
|
||||
# 8| 0: [Parameter] name
|
||||
#-----| -1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 8| 0: [TypeAccess] String
|
||||
# 8| 1: [Parameter] language
|
||||
# 8| 0: [TypeAccess] int
|
||||
@@ -176,6 +192,8 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 0| 2: [ReturnStmt] return ...
|
||||
# 0| 0: [VarAccess] result
|
||||
# 0| 8: [Method] toString
|
||||
#-----| 1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 3: [TypeAccess] String
|
||||
# 0| 5: [BlockStmt] { ... }
|
||||
# 0| 0: [ReturnStmt] return ...
|
||||
@@ -190,13 +208,21 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 0| -1: [ThisAccess] this
|
||||
# 0| 6: [StringLiteral] ")"
|
||||
# 0| 9: [Method] write$Self
|
||||
#-----| 1: (Annotations)
|
||||
# 0| 1: [Annotation] JvmStatic
|
||||
# 0| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 0| 0: [Parameter] self
|
||||
#-----| -1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 0: [TypeAccess] Project
|
||||
# 0| 1: [Parameter] output
|
||||
#-----| -1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 0: [TypeAccess] CompositeEncoder
|
||||
# 0| 2: [Parameter] serialDesc
|
||||
#-----| -1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 0: [TypeAccess] SerialDescriptor
|
||||
# 7| 5: [BlockStmt] { ... }
|
||||
# 7| 0: [ExprStmt] <Expr>;
|
||||
@@ -214,9 +240,19 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 7| 2: [MethodAccess] getLanguage(...)
|
||||
# 7| -1: [VarAccess] self
|
||||
# 7| 10: [Class] $serializer
|
||||
#-----| -3: (Annotations)
|
||||
# 0| 1: [Annotation] Deprecated
|
||||
# 0| 1: [StringLiteral] "This synthesized declaration should not be used directly"
|
||||
# 0| 2: [Annotation] ReplaceWith
|
||||
# 0| 1: [StringLiteral] ""
|
||||
# 0| 2: [ArrayInit] {...}
|
||||
# 0| 3: [VarAccess] DeprecationLevel.HIDDEN
|
||||
# 0| -1: [TypeAccess] DeprecationLevel
|
||||
# 0| 1: [FieldDeclaration] SerialDescriptor descriptor;
|
||||
# 0| -1: [TypeAccess] SerialDescriptor
|
||||
# 0| 2: [Method] childSerializers
|
||||
#-----| 1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 3: [TypeAccess] KSerializer<?>[]
|
||||
# 0| 0: [TypeAccess] KSerializer<?>
|
||||
# 0| 0: [WildcardTypeAccess] ? ...
|
||||
@@ -227,9 +263,13 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 7| -1: [TypeAccess] KSerializer<?>
|
||||
# 7| 0: [IntegerLiteral] 2
|
||||
# 0| 3: [Method] deserialize
|
||||
#-----| 1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 3: [TypeAccess] Project
|
||||
#-----| 4: (Parameters)
|
||||
# 0| 0: [Parameter] decoder
|
||||
#-----| -1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 0: [TypeAccess] Decoder
|
||||
# 7| 5: [BlockStmt] { ... }
|
||||
# 7| 0: [LocalVariableDeclStmt] var ...;
|
||||
@@ -365,6 +405,8 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 7| 2: [VarAccess] tmp5_local1
|
||||
# 7| 3: [NullLiteral] null
|
||||
# 0| 4: [Method] getDescriptor
|
||||
#-----| 1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 3: [TypeAccess] SerialDescriptor
|
||||
# 0| 5: [BlockStmt] { ... }
|
||||
# 0| 0: [ReturnStmt] return ...
|
||||
@@ -374,8 +416,12 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 0| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 0| 0: [Parameter] encoder
|
||||
#-----| -1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 0: [TypeAccess] Encoder
|
||||
# 0| 1: [Parameter] value
|
||||
#-----| -1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 0: [TypeAccess] Project
|
||||
# 7| 5: [BlockStmt] { ... }
|
||||
# 7| 0: [LocalVariableDeclStmt] var ...;
|
||||
@@ -436,6 +482,8 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 7| 0: [TypeAccess] GeneratedSerializer
|
||||
# 7| 11: [Class] Companion
|
||||
# 0| 1: [Method] serializer
|
||||
#-----| 1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 3: [TypeAccess] KSerializer<Project>
|
||||
# 0| 0: [TypeAccess] Project
|
||||
# 7| 5: [BlockStmt] { ... }
|
||||
@@ -448,6 +496,8 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 8| 12: [Constructor] Project
|
||||
#-----| 4: (Parameters)
|
||||
# 8| 0: [Parameter] name
|
||||
#-----| -1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 8| 0: [TypeAccess] String
|
||||
# 8| 1: [Parameter] language
|
||||
# 8| 0: [TypeAccess] int
|
||||
@@ -464,6 +514,8 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 8| -1: [TypeAccess] String
|
||||
# 8| 0: [VarAccess] name
|
||||
# 8| 14: [Method] getName
|
||||
#-----| 1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 8| 3: [TypeAccess] String
|
||||
# 8| 5: [BlockStmt] { ... }
|
||||
# 8| 0: [ReturnStmt] return ...
|
||||
@@ -480,9 +532,21 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 8| 0: [VarAccess] language
|
||||
# 10| 2: [Interface] Base
|
||||
# 11| 1: [Method] getId
|
||||
#-----| 1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 11| 3: [TypeAccess] String
|
||||
# 14| 3: [Class] X
|
||||
#-----| -3: (Annotations)
|
||||
# 14| 1: [Annotation] Serializable
|
||||
# 0| 1: [Constructor] X
|
||||
#-----| 1: (Annotations)
|
||||
# 0| 1: [Annotation] Deprecated
|
||||
# 0| 1: [StringLiteral] "This synthesized declaration should not be used directly"
|
||||
# 0| 2: [Annotation] ReplaceWith
|
||||
# 0| 1: [StringLiteral] ""
|
||||
# 0| 2: [ArrayInit] {...}
|
||||
# 0| 3: [VarAccess] DeprecationLevel.HIDDEN
|
||||
# 0| -1: [TypeAccess] DeprecationLevel
|
||||
#-----| 4: (Parameters)
|
||||
# 0| 0: [Parameter] seen1
|
||||
# 0| 0: [TypeAccess] int
|
||||
@@ -530,13 +594,21 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 14| 0: [TypeAccess] X
|
||||
# 14| 1: [VarAccess] id
|
||||
# 0| 2: [Method] write$Self
|
||||
#-----| 1: (Annotations)
|
||||
# 0| 1: [Annotation] JvmStatic
|
||||
# 0| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 0| 0: [Parameter] self
|
||||
#-----| -1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 0: [TypeAccess] X
|
||||
# 0| 1: [Parameter] output
|
||||
#-----| -1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 0: [TypeAccess] CompositeEncoder
|
||||
# 0| 2: [Parameter] serialDesc
|
||||
#-----| -1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 0: [TypeAccess] SerialDescriptor
|
||||
# 14| 5: [BlockStmt] { ... }
|
||||
# 14| 0: [ExprStmt] <Expr>;
|
||||
@@ -565,9 +637,19 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 14| 2: [MethodAccess] getId(...)
|
||||
# 14| -1: [VarAccess] self
|
||||
# 14| 3: [Class] $serializer
|
||||
#-----| -3: (Annotations)
|
||||
# 0| 1: [Annotation] Deprecated
|
||||
# 0| 1: [StringLiteral] "This synthesized declaration should not be used directly"
|
||||
# 0| 2: [Annotation] ReplaceWith
|
||||
# 0| 1: [StringLiteral] ""
|
||||
# 0| 2: [ArrayInit] {...}
|
||||
# 0| 3: [VarAccess] DeprecationLevel.HIDDEN
|
||||
# 0| -1: [TypeAccess] DeprecationLevel
|
||||
# 0| 1: [FieldDeclaration] SerialDescriptor descriptor;
|
||||
# 0| -1: [TypeAccess] SerialDescriptor
|
||||
# 0| 2: [Method] childSerializers
|
||||
#-----| 1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 3: [TypeAccess] KSerializer<?>[]
|
||||
# 0| 0: [TypeAccess] KSerializer<?>
|
||||
# 0| 0: [WildcardTypeAccess] ? ...
|
||||
@@ -578,9 +660,13 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 14| -1: [TypeAccess] KSerializer<?>
|
||||
# 14| 0: [IntegerLiteral] 1
|
||||
# 0| 3: [Method] deserialize
|
||||
#-----| 1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 3: [TypeAccess] X
|
||||
#-----| 4: (Parameters)
|
||||
# 0| 0: [Parameter] decoder
|
||||
#-----| -1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 0: [TypeAccess] Decoder
|
||||
# 14| 5: [BlockStmt] { ... }
|
||||
# 14| 0: [LocalVariableDeclStmt] var ...;
|
||||
@@ -680,6 +766,8 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 14| 1: [VarAccess] tmp4_local0
|
||||
# 14| 2: [NullLiteral] null
|
||||
# 0| 4: [Method] getDescriptor
|
||||
#-----| 1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 3: [TypeAccess] SerialDescriptor
|
||||
# 0| 5: [BlockStmt] { ... }
|
||||
# 0| 0: [ReturnStmt] return ...
|
||||
@@ -689,8 +777,12 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 0| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 0| 0: [Parameter] encoder
|
||||
#-----| -1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 0: [TypeAccess] Encoder
|
||||
# 0| 1: [Parameter] value
|
||||
#-----| -1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 0: [TypeAccess] X
|
||||
# 14| 5: [BlockStmt] { ... }
|
||||
# 14| 0: [LocalVariableDeclStmt] var ...;
|
||||
@@ -746,6 +838,8 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 14| 0: [TypeAccess] GeneratedSerializer
|
||||
# 14| 4: [Class] Companion
|
||||
# 0| 1: [Method] serializer
|
||||
#-----| 1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 0| 3: [TypeAccess] KSerializer<X>
|
||||
# 0| 0: [TypeAccess] X
|
||||
# 14| 5: [BlockStmt] { ... }
|
||||
@@ -766,6 +860,8 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 16| -1: [TypeAccess] String
|
||||
# 16| 0: [StringLiteral] "X"
|
||||
# 16| 7: [Method] getId
|
||||
#-----| 1: (Annotations)
|
||||
# 0| 1: [Annotation] NotNull
|
||||
# 16| 3: [TypeAccess] String
|
||||
# 16| 5: [BlockStmt] { ... }
|
||||
# 16| 0: [ReturnStmt] return ...
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import org.jetbrains.annotations.*;
|
||||
import zpkg.A;
|
||||
|
||||
public interface AnnotatedInterface {
|
||||
|
||||
public @A @NotNull String notNullAnnotated(@A @NotNull String param);
|
||||
|
||||
public @A @Nullable String nullableAnnotated(@A @Nullable String param);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import org.jetbrains.annotations.*;
|
||||
import zpkg.A;
|
||||
|
||||
public class AnnotatedMethods implements AnnotatedInterface {
|
||||
|
||||
public @A @NotNull String notNullAnnotated(@A @NotNull String param) { return param; }
|
||||
|
||||
public @A @Nullable String nullableAnnotated(@A @Nullable String param) { return param; }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
public class JavaUser {
|
||||
|
||||
public static void test(KotlinAnnotatedMethods km, KotlinDelegate kd) {
|
||||
km.f(null);
|
||||
kd.notNullAnnotated("Hello world");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import zpkg.A
|
||||
|
||||
class KotlinAnnotatedMethods {
|
||||
|
||||
@A fun f(@A m: AnnotatedMethods): String = m.notNullAnnotated("hello") + m.nullableAnnotated("world")!!
|
||||
|
||||
}
|
||||
|
||||
class KotlinDelegate(c: AnnotatedMethods) : AnnotatedInterface by c { }
|
||||
@@ -0,0 +1,6 @@
|
||||
package org.jetbrains.annotations;
|
||||
|
||||
public @interface NotNull {
|
||||
String value() default "";
|
||||
Class<? extends Exception> exception() default Exception.class;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.jetbrains.annotations;
|
||||
|
||||
public @interface Nullable {
|
||||
String value() default "";
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
| AnnotatedInterface.java:6:29:6:44 | notNullAnnotated | parameter | AnnotatedInterface.java:6:46:6:47 | A |
|
||||
| AnnotatedInterface.java:6:29:6:44 | notNullAnnotated | parameter | AnnotatedInterface.java:6:49:6:56 | NotNull |
|
||||
| AnnotatedInterface.java:6:29:6:44 | notNullAnnotated | return value | AnnotatedInterface.java:6:10:6:11 | A |
|
||||
| AnnotatedInterface.java:6:29:6:44 | notNullAnnotated | return value | AnnotatedInterface.java:6:13:6:20 | NotNull |
|
||||
| AnnotatedInterface.java:8:30:8:46 | nullableAnnotated | parameter | AnnotatedInterface.java:8:48:8:49 | A |
|
||||
| AnnotatedInterface.java:8:30:8:46 | nullableAnnotated | parameter | AnnotatedInterface.java:8:51:8:59 | Nullable |
|
||||
| AnnotatedInterface.java:8:30:8:46 | nullableAnnotated | return value | AnnotatedInterface.java:8:10:8:11 | A |
|
||||
| AnnotatedInterface.java:8:30:8:46 | nullableAnnotated | return value | AnnotatedInterface.java:8:13:8:21 | Nullable |
|
||||
| AnnotatedMethods.java:6:29:6:44 | notNullAnnotated | parameter | AnnotatedMethods.java:6:46:6:47 | A |
|
||||
| AnnotatedMethods.java:6:29:6:44 | notNullAnnotated | parameter | AnnotatedMethods.java:6:49:6:56 | NotNull |
|
||||
| AnnotatedMethods.java:6:29:6:44 | notNullAnnotated | return value | AnnotatedMethods.java:6:10:6:11 | A |
|
||||
| AnnotatedMethods.java:6:29:6:44 | notNullAnnotated | return value | AnnotatedMethods.java:6:13:6:20 | NotNull |
|
||||
| AnnotatedMethods.java:8:30:8:46 | nullableAnnotated | parameter | AnnotatedMethods.java:8:48:8:49 | A |
|
||||
| AnnotatedMethods.java:8:30:8:46 | nullableAnnotated | parameter | AnnotatedMethods.java:8:51:8:59 | Nullable |
|
||||
| AnnotatedMethods.java:8:30:8:46 | nullableAnnotated | return value | AnnotatedMethods.java:8:10:8:11 | A |
|
||||
| AnnotatedMethods.java:8:30:8:46 | nullableAnnotated | return value | AnnotatedMethods.java:8:13:8:21 | Nullable |
|
||||
| ktUser.kt:0:0:0:0 | notNullAnnotated | parameter | ktUser.kt:0:0:0:0 | A |
|
||||
| ktUser.kt:0:0:0:0 | notNullAnnotated | parameter | ktUser.kt:0:0:0:0 | NotNull |
|
||||
| ktUser.kt:0:0:0:0 | notNullAnnotated | return value | ktUser.kt:0:0:0:0 | A |
|
||||
| ktUser.kt:0:0:0:0 | notNullAnnotated | return value | ktUser.kt:0:0:0:0 | NotNull |
|
||||
| ktUser.kt:0:0:0:0 | nullableAnnotated | parameter | ktUser.kt:0:0:0:0 | A |
|
||||
| ktUser.kt:0:0:0:0 | nullableAnnotated | parameter | ktUser.kt:0:0:0:0 | Nullable |
|
||||
| ktUser.kt:0:0:0:0 | nullableAnnotated | return value | ktUser.kt:0:0:0:0 | A |
|
||||
| ktUser.kt:0:0:0:0 | nullableAnnotated | return value | ktUser.kt:0:0:0:0 | Nullable |
|
||||
| ktUser.kt:5:6:5:105 | f | parameter | ktUser.kt:0:0:0:0 | NotNull |
|
||||
| ktUser.kt:5:6:5:105 | f | parameter | ktUser.kt:5:12:5:13 | A |
|
||||
| ktUser.kt:5:6:5:105 | f | return value | ktUser.kt:0:0:0:0 | NotNull |
|
||||
| ktUser.kt:5:6:5:105 | f | return value | ktUser.kt:5:3:5:4 | A |
|
||||
@@ -0,0 +1,7 @@
|
||||
from create_database_utils import *
|
||||
import os
|
||||
|
||||
os.mkdir('out')
|
||||
os.mkdir('out2')
|
||||
os.mkdir('out3')
|
||||
run_codeql_database_create(["javac AnnotatedInterface.java AnnotatedMethods.java zpkg/A.java org/jetbrains/annotations/NotNull.java org/jetbrains/annotations/Nullable.java -d out", "kotlinc ktUser.kt -cp out -d out2", "javac JavaUser.java -cp out" + os.pathsep + "out2 -d out3"], lang="java")
|
||||
@@ -0,0 +1,11 @@
|
||||
import java
|
||||
|
||||
from Method m, string origin, Annotation a
|
||||
where
|
||||
m.fromSource() and
|
||||
(
|
||||
origin = "return value" and a = m.getAnAnnotation()
|
||||
or
|
||||
origin = "parameter" and a = m.getAParameter().getAnAnnotation()
|
||||
)
|
||||
select m, origin, a
|
||||
@@ -0,0 +1,3 @@
|
||||
package zpkg;
|
||||
|
||||
public @interface A { }
|
||||
@@ -0,0 +1,5 @@
|
||||
public @interface JavaDefinedContainer {
|
||||
|
||||
public JavaDefinedRepeatable[] value();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
@java.lang.annotation.Repeatable(JavaDefinedContainer.class)
|
||||
public @interface JavaDefinedRepeatable { }
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
@LocalRepeatable
|
||||
@LocalRepeatable
|
||||
@LibRepeatable
|
||||
@LibRepeatable
|
||||
@ExplicitContainerRepeatable
|
||||
@ExplicitContainerRepeatable
|
||||
@JavaDefinedRepeatable
|
||||
@JavaDefinedRepeatable
|
||||
public class JavaUser { }
|
||||
@@ -0,0 +1,7 @@
|
||||
@Repeatable
|
||||
public annotation class LibRepeatable { }
|
||||
|
||||
annotation class KtDefinedContainer(val value: Array<ExplicitContainerRepeatable>) { }
|
||||
|
||||
@java.lang.annotation.Repeatable(KtDefinedContainer::class)
|
||||
annotation class ExplicitContainerRepeatable() { }
|
||||
@@ -0,0 +1,16 @@
|
||||
| JavaUser.java:9:14:9:21 | JavaUser | out2/JavaUser.class:0:0:0:0 | Container | value | out2/JavaUser.class:0:0:0:0 | {...} |
|
||||
| JavaUser.java:9:14:9:21 | JavaUser | out2/JavaUser.class:0:0:0:0 | Container | value | out2/JavaUser.class:0:0:0:0 | {...} |
|
||||
| JavaUser.java:9:14:9:21 | JavaUser | out2/JavaUser.class:0:0:0:0 | JavaDefinedContainer | value | out2/JavaUser.class:0:0:0:0 | {...} |
|
||||
| JavaUser.java:9:14:9:21 | JavaUser | out2/JavaUser.class:0:0:0:0 | KtDefinedContainer | value | out2/JavaUser.class:0:0:0:0 | {...} |
|
||||
| out/ExplicitContainerRepeatable.class:0:0:0:0 | ExplicitContainerRepeatable | out/ExplicitContainerRepeatable.class:0:0:0:0 | Repeatable | value | out/ExplicitContainerRepeatable.class:0:0:0:0 | KtDefinedContainer.class |
|
||||
| out/ExplicitContainerRepeatable.class:0:0:0:0 | ExplicitContainerRepeatable | out/ExplicitContainerRepeatable.class:0:0:0:0 | Retention | value | out/ExplicitContainerRepeatable.class:0:0:0:0 | RUNTIME |
|
||||
| out/JavaDefinedRepeatable.class:0:0:0:0 | JavaDefinedRepeatable | out/JavaDefinedRepeatable.class:0:0:0:0 | Repeatable | value | out/JavaDefinedRepeatable.class:0:0:0:0 | JavaDefinedContainer.class |
|
||||
| out/KtDefinedContainer.class:0:0:0:0 | KtDefinedContainer | out/KtDefinedContainer.class:0:0:0:0 | Retention | value | out/KtDefinedContainer.class:0:0:0:0 | RUNTIME |
|
||||
| out/LibRepeatable.class:0:0:0:0 | LibRepeatable | out/LibRepeatable.class:0:0:0:0 | Repeatable | value | out/LibRepeatable.class:0:0:0:0 | Container.class |
|
||||
| out/LibRepeatable.class:0:0:0:0 | LibRepeatable | out/LibRepeatable.class:0:0:0:0 | Retention | value | out/LibRepeatable.class:0:0:0:0 | RUNTIME |
|
||||
| test.kt:1:1:2:43 | LocalRepeatable | test.kt:0:0:0:0 | Repeatable | value | test.kt:0:0:0:0 | Container.class |
|
||||
| test.kt:1:1:2:43 | LocalRepeatable | test.kt:0:0:0:0 | Retention | value | test.kt:0:0:0:0 | RetentionPolicy.RUNTIME |
|
||||
| test.kt:4:1:12:21 | User | test.kt:0:0:0:0 | Container | value | test.kt:0:0:0:0 | {...} |
|
||||
| test.kt:4:1:12:21 | User | test.kt:0:0:0:0 | Container | value | test.kt:0:0:0:0 | {...} |
|
||||
| test.kt:4:1:12:21 | User | test.kt:0:0:0:0 | JavaDefinedContainer | value | test.kt:0:0:0:0 | {...} |
|
||||
| test.kt:4:1:12:21 | User | test.kt:0:0:0:0 | KtDefinedContainer | value | test.kt:0:0:0:0 | {...} |
|
||||
@@ -0,0 +1,12 @@
|
||||
@Repeatable
|
||||
public annotation class LocalRepeatable { }
|
||||
|
||||
@LocalRepeatable
|
||||
@LocalRepeatable
|
||||
@LibRepeatable
|
||||
@LibRepeatable
|
||||
@ExplicitContainerRepeatable
|
||||
@ExplicitContainerRepeatable
|
||||
@JavaDefinedRepeatable
|
||||
@JavaDefinedRepeatable
|
||||
public class User { }
|
||||
@@ -0,0 +1,7 @@
|
||||
from create_database_utils import *
|
||||
|
||||
os.mkdir('out')
|
||||
os.mkdir('out2')
|
||||
runSuccessfully([get_cmd("kotlinc"), "lib.kt", "-d", "out"])
|
||||
runSuccessfully([get_cmd("javac"), "JavaDefinedContainer.java", "JavaDefinedRepeatable.java", "-d", "out"])
|
||||
run_codeql_database_create(["kotlinc test.kt -cp out -d out", "javac JavaUser.java -cp out -d out2"], lang="java")
|
||||
@@ -0,0 +1,11 @@
|
||||
import java
|
||||
|
||||
from ClassOrInterface annotated, Annotation a, string valName, Expr val
|
||||
where
|
||||
a.getValue(valName) = val and
|
||||
annotated = a.getAnnotatedElement() and
|
||||
annotated.getName() in [
|
||||
"JavaDefinedRepeatable", "JavaDefinedContainer", "KtDefinedContainer", "LibRepeatable",
|
||||
"ExplicitContainerRepeatable", "LocalRepeatable", "User", "JavaUser"
|
||||
]
|
||||
select a.getAnnotatedElement(), a, valName, val
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The extraction of Kotlin extension methods has been improved when default parameter values are present. The dispatch and extension receiver parameters are extracted in the correct order. The `ExtensionMethod::getExtensionReceiverParameterIndex` predicate has been introduced to facilitate getting the correct extension parameter index.
|
||||
@@ -14,5 +14,5 @@ extensions:
|
||||
data: []
|
||||
- addsTo:
|
||||
pack: codeql/java-all
|
||||
extensible: extNegativeSummaryModel
|
||||
extensible: extNeutralModel
|
||||
data: []
|
||||
@@ -1861,7 +1861,7 @@ extensions:
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/java-all
|
||||
extensible: extNegativeSummaryModel
|
||||
extensible: extNeutralModel
|
||||
data:
|
||||
- ["kotlin.annotation", "AnnotationRetention", "valueOf", "(String)", "generated"]
|
||||
- ["kotlin.annotation", "AnnotationRetention", "values", "()", "generated"]
|
||||
|
||||
@@ -676,7 +676,7 @@ extensions:
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/java-all
|
||||
extensible: extNegativeSummaryModel
|
||||
extensible: extNeutralModel
|
||||
data:
|
||||
- ["org.apache.commons.io.charset", "CharsetDecoders", "CharsetDecoders", "()", "generated"]
|
||||
- ["org.apache.commons.io.charset", "CharsetEncoders", "CharsetEncoders", "()", "generated"]
|
||||
|
||||
@@ -37,7 +37,9 @@ class Annotation extends @annotation, Expr {
|
||||
}
|
||||
|
||||
/** Gets the annotation type declaration for this annotation. */
|
||||
override AnnotationType getType() { result = Expr.super.getType() }
|
||||
override AnnotationType getType() {
|
||||
result = Expr.super.getType().(Interface).getSourceDeclaration()
|
||||
}
|
||||
|
||||
/** Gets the annotation element with the specified `name`. */
|
||||
AnnotationElement getAnnotationElement(string name) {
|
||||
@@ -249,7 +251,7 @@ private predicate filteredAnnotValue(Annotation a, Method m, Expr val) {
|
||||
|
||||
private predicate sourceAnnotValue(Annotation a, Method m, Expr val) {
|
||||
annotValue(a, m, val) and
|
||||
val.getFile().getExtension() = "java"
|
||||
val.getFile().isSourceFile()
|
||||
}
|
||||
|
||||
/** An abstract representation of language elements that can be annotated. */
|
||||
|
||||
@@ -91,7 +91,7 @@ predicate numDepends(RefType t, RefType dep, int value) {
|
||||
elem = a and usesType(a.getType(), dep)
|
||||
or
|
||||
elem = [a.getValue(_), a.getAnArrayValue(_)] and
|
||||
elem.getFile().getExtension() = "java" and
|
||||
elem.getFile().isSourceFile() and
|
||||
usesType(elem.(Expr).getType(), dep)
|
||||
)
|
||||
or
|
||||
|
||||
@@ -1896,7 +1896,8 @@ class VarAccess extends Expr, @varaccess {
|
||||
class ExtensionReceiverAccess extends VarAccess {
|
||||
ExtensionReceiverAccess() {
|
||||
exists(Parameter p |
|
||||
this.getVariable() = p and p.getPosition() = 0 and p.getCallable() instanceof ExtensionMethod
|
||||
this.getVariable() = p and
|
||||
p.isExtensionParameter()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -327,18 +327,8 @@ class Callable extends StmtParent, Member, @callable {
|
||||
this instanceof Method and
|
||||
result instanceof Method and
|
||||
this.getName() + "$default" = result.getName() and
|
||||
extraLeadingParams <= 1 and
|
||||
(
|
||||
if ktExtensionFunctions(this, _, _)
|
||||
then
|
||||
// Both extension receivers are expected to occur at arg0, with any
|
||||
// dispatch receiver inserted afterwards in the $default proxy's parameter list.
|
||||
// Check the extension receiver matches here, and note regular args
|
||||
// are bumped one position to the right.
|
||||
regularParamsStartIdx = extraLeadingParams + 1 and
|
||||
this.getParameterType(0).getErasure() = eraseRaw(result.getParameterType(0))
|
||||
else regularParamsStartIdx = extraLeadingParams
|
||||
) and
|
||||
extraLeadingParams <= 1 and // 0 for static methods, 1 for instance methods
|
||||
regularParamsStartIdx = extraLeadingParams and
|
||||
lastParamType instanceof TypeObject
|
||||
)
|
||||
|
|
||||
@@ -827,4 +817,19 @@ class ExtensionMethod extends Method {
|
||||
KotlinType getExtendedKotlinType() { result = extendedKotlinType }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ExtensionMethod" }
|
||||
|
||||
/**
|
||||
* Gets the index of the parameter that is the extension receiver. This is typically index 0. In case of `$default`
|
||||
* extension methods that are defined as members, the index is 1. Index 0 is the dispatch receiver of the `$default`
|
||||
* method.
|
||||
*/
|
||||
int getExtensionReceiverParameterIndex() {
|
||||
if
|
||||
exists(Method src |
|
||||
this = src.getKotlinParameterDefaultsProxy() and
|
||||
src.getNumberOfParameters() = this.getNumberOfParameters() - 3 // 2 extra parameters + 1 dispatch receiver
|
||||
)
|
||||
then result = 1
|
||||
else result = 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +120,12 @@ private newtype TPrintAstNode =
|
||||
shouldPrint(lvde, _) and lvde.getParent() instanceof SingleLocalVarDeclParent
|
||||
} or
|
||||
TAnnotationsNode(Annotatable ann) {
|
||||
shouldPrint(ann, _) and ann.hasDeclaredAnnotation() and not partOfAnnotation(ann)
|
||||
shouldPrint(ann, _) and
|
||||
ann.hasDeclaredAnnotation() and
|
||||
not partOfAnnotation(ann) and
|
||||
// The Kotlin compiler might add annotations that are only present in byte code, although the annotatable element is
|
||||
// present in source code.
|
||||
exists(Annotation a | a.getAnnotatedElement() = ann and shouldPrint(a, _))
|
||||
} or
|
||||
TParametersNode(Callable c) { shouldPrint(c, _) and not c.hasNoParameters() } or
|
||||
TBaseTypesNode(ClassOrInterface ty) { shouldPrint(ty, _) } or
|
||||
@@ -293,19 +298,21 @@ final class AnnotationPartNode extends ExprStmtNode {
|
||||
|
||||
override ElementNode getChild(int childIndex) {
|
||||
result.getElement() =
|
||||
rank[childIndex](Element ch, string file, int line, int column |
|
||||
ch = this.getAnAnnotationChild() and locationSortKeys(ch, file, line, column)
|
||||
rank[childIndex](Element ch, string file, int line, int column, int idx |
|
||||
ch = this.getAnnotationChild(idx) and locationSortKeys(ch, file, line, column)
|
||||
|
|
||||
ch order by file, line, column
|
||||
ch order by file, line, column, idx
|
||||
)
|
||||
}
|
||||
|
||||
private Expr getAnAnnotationChild() {
|
||||
result = element.(Annotation).getValue(_)
|
||||
private Expr getAnnotationChild(int index) {
|
||||
result = element.(Annotation).getValue(_) and
|
||||
index >= 0 and
|
||||
if exists(int x | x >= 0 | result.isNthChildOf(element, x))
|
||||
then result.isNthChildOf(element, index)
|
||||
else result.isNthChildOf(element, -(index + 1))
|
||||
or
|
||||
result = element.(ArrayInit).getAnInit()
|
||||
or
|
||||
result = element.(ArrayInit).(Annotatable).getAnAnnotation()
|
||||
result = element.(ArrayInit).getInit(index)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -672,10 +679,10 @@ final class AnnotationsNode extends PrintAstNode, TAnnotationsNode {
|
||||
|
||||
override ElementNode getChild(int childIndex) {
|
||||
result.getElement() =
|
||||
rank[childIndex](Element e, string file, int line, int column |
|
||||
e = ann.getAnAnnotation() and locationSortKeys(e, file, line, column)
|
||||
rank[childIndex](Element e, string file, int line, int column, string s |
|
||||
e = ann.getAnAnnotation() and locationSortKeys(e, file, line, column) and s = e.toString()
|
||||
|
|
||||
e order by file, line, column
|
||||
e order by file, line, column, s
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ class Parameter extends Element, @param, LocalScopeVariable {
|
||||
|
||||
/** Holds if this formal parameter is a parameter representing the dispatch receiver in an extension method. */
|
||||
predicate isExtensionParameter() {
|
||||
this.getPosition() = 0 and this.getCallable() instanceof ExtensionMethod
|
||||
this.getPosition() = this.getCallable().(ExtensionMethod).getExtensionReceiverParameterIndex()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
* `package; type; subtypes; name; signature; ext; input; kind; provenance`
|
||||
* - Summaries:
|
||||
* `package; type; subtypes; name; signature; ext; input; output; kind; provenance`
|
||||
* - Negative Summaries:
|
||||
* - Neutrals:
|
||||
* `package; type; name; signature; provenance`
|
||||
* A negative summary is used to indicate that there is no flow via a callable.
|
||||
* A neutral is used to indicate that there is no flow via a callable.
|
||||
*
|
||||
* The interpretation of a row is similar to API-graphs with a left-to-right
|
||||
* reading.
|
||||
@@ -122,30 +122,12 @@ private class SummaryModelCsvInternal extends Unit {
|
||||
abstract predicate row(string row);
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Define negative summary models as data extensions instead.
|
||||
*
|
||||
* A unit class for adding additional negative summary model rows.
|
||||
*
|
||||
* Extend this class to add additional negative summary definitions.
|
||||
*/
|
||||
deprecated class NegativeSummaryModelCsv = NegativeSummaryModelCsvInternal;
|
||||
|
||||
private class NegativeSummaryModelCsvInternal extends Unit {
|
||||
/** Holds if `row` specifies a negative summary definition. */
|
||||
abstract predicate row(string row);
|
||||
}
|
||||
|
||||
private predicate sourceModelInternal(string row) { any(SourceModelCsvInternal s).row(row) }
|
||||
|
||||
private predicate summaryModelInternal(string row) { any(SummaryModelCsvInternal s).row(row) }
|
||||
|
||||
private predicate sinkModelInternal(string row) { any(SinkModelCsvInternal s).row(row) }
|
||||
|
||||
private predicate negativeSummaryModelInternal(string row) {
|
||||
any(NegativeSummaryModelCsvInternal s).row(row)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if an experimental source model exists for the given parameters.
|
||||
* This is only for experimental queries.
|
||||
@@ -313,25 +295,14 @@ predicate summaryModel(
|
||||
.summaryModel(package, type, subtypes, name, signature, ext, input, output, kind, provenance)
|
||||
}
|
||||
|
||||
/** Holds if a summary model exists indicating there is no flow for the given parameters. */
|
||||
extensible predicate extNegativeSummaryModel(
|
||||
/** Holds if a neutral model exists indicating there is no flow for the given parameters. */
|
||||
extensible predicate extNeutralModel(
|
||||
string package, string type, string name, string signature, string provenance
|
||||
);
|
||||
|
||||
/** Holds if a summary model exists indicating there is no flow for the given parameters. */
|
||||
predicate negativeSummaryModel(
|
||||
string package, string type, string name, string signature, string provenance
|
||||
) {
|
||||
exists(string row |
|
||||
negativeSummaryModelInternal(row) and
|
||||
row.splitAt(";", 0) = package and
|
||||
row.splitAt(";", 1) = type and
|
||||
row.splitAt(";", 2) = name and
|
||||
row.splitAt(";", 3) = signature and
|
||||
row.splitAt(";", 4) = provenance
|
||||
)
|
||||
or
|
||||
extNegativeSummaryModel(package, type, name, signature, provenance)
|
||||
/** Holds if a neutral model exists indicating there is no flow for the given parameters. */
|
||||
predicate neutralModel(string package, string type, string name, string signature, string provenance) {
|
||||
extNeutralModel(package, type, name, signature, provenance)
|
||||
}
|
||||
|
||||
private predicate relevantPackage(string package) {
|
||||
@@ -472,8 +443,6 @@ module ModelValidation {
|
||||
sinkModelInternal(row) and expect = 9 and pred = "sink"
|
||||
or
|
||||
summaryModelInternal(row) and expect = 10 and pred = "summary"
|
||||
or
|
||||
negativeSummaryModelInternal(row) and expect = 5 and pred = "negative summary"
|
||||
|
|
||||
exists(int cols |
|
||||
cols = 1 + max(int n | exists(row.splitAt(";", n))) and
|
||||
@@ -497,9 +466,9 @@ module ModelValidation {
|
||||
summaryModel(package, type, _, name, signature, ext, _, _, _, provenance) and
|
||||
pred = "summary"
|
||||
or
|
||||
negativeSummaryModel(package, type, name, signature, provenance) and
|
||||
neutralModel(package, type, name, signature, provenance) and
|
||||
ext = "" and
|
||||
pred = "negative summary"
|
||||
pred = "neutral"
|
||||
|
|
||||
not package.regexpMatch("[a-zA-Z0-9_\\.]*") and
|
||||
result = "Dubious package \"" + package + "\" in " + pred + " model."
|
||||
@@ -541,7 +510,7 @@ private predicate elementSpec(
|
||||
or
|
||||
summaryModel(package, type, subtypes, name, signature, ext, _, _, _, _)
|
||||
or
|
||||
negativeSummaryModel(package, type, name, signature, _) and ext = "" and subtypes = false
|
||||
neutralModel(package, type, name, signature, _) and ext = "" and subtypes = false
|
||||
}
|
||||
|
||||
private string paramsStringPart(Callable c, int i) {
|
||||
@@ -590,7 +559,7 @@ private Element interpretElement0(
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the source/sink/summary/negativesummary element corresponding to the supplied parameters. */
|
||||
/** Gets the source/sink/summary/neutral element corresponding to the supplied parameters. */
|
||||
Element interpretElement(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext
|
||||
) {
|
||||
|
||||
@@ -172,9 +172,7 @@ abstract class UserInput extends DataFlow::Node { }
|
||||
/**
|
||||
* Input that may be controlled by a remote user.
|
||||
*/
|
||||
private class RemoteUserInput extends UserInput {
|
||||
RemoteUserInput() { this instanceof RemoteFlowSource }
|
||||
}
|
||||
private class RemoteUserInput extends UserInput instanceof RemoteFlowSource { }
|
||||
|
||||
/** A node with input that may be controlled by a local user. */
|
||||
abstract class LocalUserInput extends UserInput { }
|
||||
|
||||
@@ -246,14 +246,14 @@ module Public {
|
||||
predicate isAutoGenerated() { none() }
|
||||
}
|
||||
|
||||
/** A callable with a flow summary stating there is no flow via the callable. */
|
||||
class NegativeSummarizedCallable extends SummarizedCallableBase {
|
||||
NegativeSummarizedCallable() { negativeSummaryElement(this, _) }
|
||||
/** A callable where there is no flow via the callable. */
|
||||
class NeutralCallable extends SummarizedCallableBase {
|
||||
NeutralCallable() { neutralElement(this, _) }
|
||||
|
||||
/**
|
||||
* Holds if the negative summary is auto generated.
|
||||
* Holds if the neutral is auto generated.
|
||||
*/
|
||||
predicate isAutoGenerated() { negativeSummaryElement(this, true) }
|
||||
predicate isAutoGenerated() { neutralElement(this, true) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1161,9 +1161,9 @@ module Private {
|
||||
string toString() { result = super.toString() }
|
||||
}
|
||||
|
||||
/** A flow summary to include in the `negativeSummary/1` query predicate. */
|
||||
abstract class RelevantNegativeSummarizedCallable instanceof NegativeSummarizedCallable {
|
||||
/** Gets the string representation of this callable used by `summary/1`. */
|
||||
/** A model to include in the `neutral/1` query predicate. */
|
||||
abstract class RelevantNeutralCallable instanceof NeutralCallable {
|
||||
/** Gets the string representation of this callable used by `neutral/1`. */
|
||||
abstract string getCallableCsv();
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
@@ -1180,13 +1180,13 @@ module Private {
|
||||
if c.isAutoGenerated() then result = "generated" else result = "manual"
|
||||
}
|
||||
|
||||
private string renderProvenanceNegative(NegativeSummarizedCallable c) {
|
||||
private string renderProvenanceNeutral(NeutralCallable c) {
|
||||
if c.isAutoGenerated() then result = "generated" else result = "manual"
|
||||
}
|
||||
|
||||
/**
|
||||
* A query predicate for outputting flow summaries in semi-colon separated format in QL tests.
|
||||
* The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind;provenance"",
|
||||
* The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind;provenance",
|
||||
* ext is hardcoded to empty.
|
||||
*/
|
||||
query predicate summary(string csv) {
|
||||
@@ -1205,14 +1205,14 @@ module Private {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a negative flow summary `csv` exists (semi-colon separated format). Used for testing purposes.
|
||||
* Holds if a neutral model `csv` exists (semi-colon separated format). Used for testing purposes.
|
||||
* The syntax is: "namespace;type;name;signature;provenance"",
|
||||
*/
|
||||
query predicate negativeSummary(string csv) {
|
||||
exists(RelevantNegativeSummarizedCallable c |
|
||||
query predicate neutral(string csv) {
|
||||
exists(RelevantNeutralCallable c |
|
||||
csv =
|
||||
c.getCallableCsv() // Callable information
|
||||
+ renderProvenanceNegative(c) // provenance
|
||||
+ renderProvenanceNeutral(c) // provenance
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,8 +120,11 @@ private predicate correspondingKotlinParameterDefaultsArgSpec(
|
||||
exists(int oldArgParsed |
|
||||
oldArgParsed = AccessPathSyntax::AccessPath::parseInt(oldArgNumber.splitAt(",").trim())
|
||||
|
|
||||
if ktExtensionFunctions(originalCallable, _, _) and oldArgParsed = 0
|
||||
then defaultsArgSpec = "Argument[0]"
|
||||
if
|
||||
ktExtensionFunctions(originalCallable, _, _) and
|
||||
ktExtensionFunctions(defaultsCallable, _, _) and
|
||||
oldArgParsed = 0
|
||||
then defaultsArgSpec = "Argument[" + paramOffset + "]" // 1 if dispatch receiver is present, 0 otherwise.
|
||||
else defaultsArgSpec = "Argument[" + (oldArgParsed + paramOffset) + "]" + rest
|
||||
)
|
||||
)
|
||||
@@ -160,12 +163,12 @@ predicate summaryElement(
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a negative flow summary exists for `c`, which means that there is no
|
||||
* flow through `c`. The flag `generated` states whether the summary is autogenerated.
|
||||
* Holds if a neutral model exists for `c`, which means that there is no
|
||||
* flow through `c`. The flag `generated` states whether the model is autogenerated.
|
||||
*/
|
||||
predicate negativeSummaryElement(SummarizedCallableBase c, boolean generated) {
|
||||
predicate neutralElement(SummarizedCallableBase c, boolean generated) {
|
||||
exists(string namespace, string type, string name, string signature, string provenance |
|
||||
negativeSummaryModel(namespace, type, name, signature, provenance) and
|
||||
neutralModel(namespace, type, name, signature, provenance) and
|
||||
generated = isGenerated(provenance) and
|
||||
c.asCallable() = interpretElement(namespace, type, false, name, signature, "")
|
||||
)
|
||||
|
||||
@@ -58,9 +58,7 @@ abstract class WhitelistedLiveCallable extends CallableEntryPoint { }
|
||||
/**
|
||||
* A `public static void main(String[] args)` method.
|
||||
*/
|
||||
class MainMethodEntry extends CallableEntryPoint {
|
||||
MainMethodEntry() { this instanceof MainMethod }
|
||||
}
|
||||
class MainMethodEntry extends CallableEntryPoint instanceof MainMethod { }
|
||||
|
||||
/**
|
||||
* A method that overrides a library method -- the result is
|
||||
@@ -96,9 +94,7 @@ abstract class ReflectivelyConstructedClass extends EntryPoint, Class {
|
||||
/**
|
||||
* Classes that are deserialized by Jackson are reflectively constructed.
|
||||
*/
|
||||
library class JacksonReflectivelyConstructedClass extends ReflectivelyConstructedClass {
|
||||
JacksonReflectivelyConstructedClass() { this instanceof JacksonDeserializableType }
|
||||
|
||||
library class JacksonReflectivelyConstructedClass extends ReflectivelyConstructedClass instanceof JacksonDeserializableType {
|
||||
override Callable getALiveCallable() {
|
||||
// Constructors may be called by Jackson, if they are a no-arg, they have a suitable annotation,
|
||||
// or inherit a suitable annotation through a mixin.
|
||||
@@ -312,8 +308,7 @@ class FacesAccessibleMethodEntryPoint extends CallableEntryPoint {
|
||||
* A Java Server Faces custom component, that is reflectively constructed by the framework when
|
||||
* used in a view (JSP or facelet).
|
||||
*/
|
||||
class FacesComponentReflectivelyConstructedClass extends ReflectivelyConstructedClass {
|
||||
FacesComponentReflectivelyConstructedClass() { this instanceof FacesComponent }
|
||||
class FacesComponentReflectivelyConstructedClass extends ReflectivelyConstructedClass instanceof FacesComponent {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -400,8 +395,7 @@ class JavaxManagedBeanReflectivelyConstructed extends ReflectivelyConstructedCla
|
||||
* Classes marked as Java persistence entities can be reflectively constructed when the data is
|
||||
* loaded.
|
||||
*/
|
||||
class PersistentEntityEntryPoint extends ReflectivelyConstructedClass {
|
||||
PersistentEntityEntryPoint() { this instanceof PersistentEntity }
|
||||
class PersistentEntityEntryPoint extends ReflectivelyConstructedClass instanceof PersistentEntity {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -465,6 +459,5 @@ class ArbitraryXmlEntryPoint extends ReflectivelyConstructedClass {
|
||||
deprecated class ArbitraryXMLEntryPoint = ArbitraryXmlEntryPoint;
|
||||
|
||||
/** A Selenium PageObject, created by a call to PageFactory.initElements(..). */
|
||||
class SeleniumPageObjectEntryPoint extends ReflectivelyConstructedClass {
|
||||
SeleniumPageObjectEntryPoint() { this instanceof SeleniumPageObject }
|
||||
class SeleniumPageObjectEntryPoint extends ReflectivelyConstructedClass instanceof SeleniumPageObject {
|
||||
}
|
||||
|
||||
@@ -50,9 +50,7 @@ class SpringBeanAnnotatedMethod extends CallableEntryPoint {
|
||||
/**
|
||||
* A live entry point within a Spring controller.
|
||||
*/
|
||||
class SpringControllerEntryPoint extends CallableEntryPoint {
|
||||
SpringControllerEntryPoint() { this instanceof SpringControllerMethod }
|
||||
}
|
||||
class SpringControllerEntryPoint extends CallableEntryPoint instanceof SpringControllerMethod { }
|
||||
|
||||
/**
|
||||
* A method that is accessible in a response, because it is part of the returned model,
|
||||
|
||||
@@ -33,23 +33,18 @@ class Struts1ActionEntryPoint extends EntryPoint, Class {
|
||||
/**
|
||||
* A struts 2 action class that is reflectively constructed.
|
||||
*/
|
||||
class Struts2ReflectivelyConstructedAction extends ReflectivelyConstructedClass {
|
||||
Struts2ReflectivelyConstructedAction() { this instanceof Struts2ActionClass }
|
||||
class Struts2ReflectivelyConstructedAction extends ReflectivelyConstructedClass instanceof Struts2ActionClass {
|
||||
}
|
||||
|
||||
/**
|
||||
* A method called on a struts 2 action class when the action is activated.
|
||||
*/
|
||||
class Struts2ActionMethodEntryPoint extends CallableEntryPoint {
|
||||
Struts2ActionMethodEntryPoint() { this instanceof Struts2ActionMethod }
|
||||
}
|
||||
class Struts2ActionMethodEntryPoint extends CallableEntryPoint instanceof Struts2ActionMethod { }
|
||||
|
||||
/**
|
||||
* A method called on a struts 2 action class before an action is activated.
|
||||
*/
|
||||
class Struts2PrepareMethodEntryPoint extends CallableEntryPoint {
|
||||
Struts2PrepareMethodEntryPoint() { this instanceof Struts2PrepareMethod }
|
||||
}
|
||||
class Struts2PrepareMethodEntryPoint extends CallableEntryPoint instanceof Struts2PrepareMethod { }
|
||||
|
||||
/**
|
||||
* A class which is accessible - directly or indirectly - from a struts action.
|
||||
|
||||
@@ -78,13 +78,10 @@ class JUnitCategory extends WhitelistedLiveClass {
|
||||
/**
|
||||
* A listener that will be reflectively constructed by TestNG.
|
||||
*/
|
||||
class TestNGReflectivelyConstructedListener extends ReflectivelyConstructedClass {
|
||||
TestNGReflectivelyConstructedListener() {
|
||||
// Consider any class that implements a TestNG listener interface to be live. Listeners can be
|
||||
// specified on the command line, in `testng.xml` files and in Ant build files, so it is safest
|
||||
// to assume that all such listeners are live.
|
||||
this instanceof TestNGListenerImpl
|
||||
}
|
||||
class TestNGReflectivelyConstructedListener extends ReflectivelyConstructedClass instanceof TestNGListenerImpl {
|
||||
// Consider any class that implements a TestNG listener interface to be live. Listeners can be
|
||||
// specified on the command line, in `testng.xml` files and in Ant build files, so it is safest
|
||||
// to assume that all such listeners are live.
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,9 +96,7 @@ class TestNGDataProvidersEntryPoint extends CallableEntryPoint {
|
||||
/**
|
||||
* A `@Factory` TestNG method or constructor which is live.
|
||||
*/
|
||||
class TestNGFactoryEntryPoint extends CallableEntryPoint {
|
||||
TestNGFactoryEntryPoint() { this instanceof TestNGFactoryCallable }
|
||||
}
|
||||
class TestNGFactoryEntryPoint extends CallableEntryPoint instanceof TestNGFactoryCallable { }
|
||||
|
||||
class TestRefectivelyConstructedClass extends ReflectivelyConstructedClass {
|
||||
TestRefectivelyConstructedClass() {
|
||||
@@ -159,6 +154,5 @@ class CucumberConstructedClass extends ReflectivelyConstructedClass {
|
||||
/**
|
||||
* A "step definition" that may be called by Cucumber when executing an acceptance test.
|
||||
*/
|
||||
class CucumberStepDefinitionEntryPoint extends CallableEntryPoint {
|
||||
CucumberStepDefinitionEntryPoint() { this instanceof CucumberStepDefinition }
|
||||
class CucumberStepDefinitionEntryPoint extends CallableEntryPoint instanceof CucumberStepDefinition {
|
||||
}
|
||||
|
||||
@@ -7,17 +7,12 @@ import semmle.code.java.frameworks.Servlets
|
||||
* Any class which extends the `Servlet` interface is intended to be constructed reflectively by a
|
||||
* servlet container.
|
||||
*/
|
||||
class ServletConstructedClass extends ReflectivelyConstructedClass {
|
||||
class ServletConstructedClass extends ReflectivelyConstructedClass instanceof ServletClass {
|
||||
ServletConstructedClass() {
|
||||
this instanceof ServletClass and
|
||||
// If we have seen any `web.xml` files, this servlet will be considered to be live only if it is
|
||||
// referred to as a servlet-class in at least one. If no `web.xml` files are found, we assume
|
||||
// that XML extraction was not enabled, and therefore consider all `Servlet` classes as live.
|
||||
(
|
||||
isWebXmlIncluded()
|
||||
implies
|
||||
exists(WebServletClass servletClass | this = servletClass.getClass())
|
||||
)
|
||||
isWebXmlIncluded() implies exists(WebServletClass servletClass | this = servletClass.getClass())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +107,4 @@ class GwtUiBinderEntryPoint extends CallableEntryPoint {
|
||||
/**
|
||||
* Fields that may be reflectively read or written to by the UiBinder framework.
|
||||
*/
|
||||
class GwtUiBinderReflectivelyReadField extends ReflectivelyReadField {
|
||||
GwtUiBinderReflectivelyReadField() { this instanceof GwtUiField }
|
||||
}
|
||||
class GwtUiBinderReflectivelyReadField extends ReflectivelyReadField instanceof GwtUiField { }
|
||||
|
||||
@@ -45,7 +45,10 @@ class WebViewGetUrlMethod extends Method {
|
||||
class CrossOriginAccessMethod extends Method {
|
||||
CrossOriginAccessMethod() {
|
||||
this.getDeclaringType() instanceof TypeWebSettings and
|
||||
this.hasName(["setAllowUniversalAccessFromFileURLs", "setAllowFileAccessFromFileURLs"])
|
||||
this.hasName([
|
||||
"setAllowFileAccess", "setAllowUniversalAccessFromFileURLs",
|
||||
"setAllowFileAccessFromFileURLs"
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -75,14 +75,11 @@ class ForbiddenSecurityConfigurationCallable extends ForbiddenCallable {
|
||||
}
|
||||
|
||||
/** A method or constructor involving serialization that may not be called by an EJB. */
|
||||
class ForbiddenSerializationCallable extends ForbiddenCallable {
|
||||
ForbiddenSerializationCallable() { this instanceof ForbiddenSerializationMethod }
|
||||
class ForbiddenSerializationCallable extends ForbiddenCallable instanceof ForbiddenSerializationMethod {
|
||||
}
|
||||
|
||||
/** A method or constructor involving network factory operations that may not be called by an EJB. */
|
||||
class ForbiddenSetFactoryCallable extends ForbiddenCallable {
|
||||
ForbiddenSetFactoryCallable() { this instanceof ForbiddenSetFactoryMethod }
|
||||
}
|
||||
class ForbiddenSetFactoryCallable extends ForbiddenCallable instanceof ForbiddenSetFactoryMethod { }
|
||||
|
||||
/** A method or constructor involving server socket operations that may not be called by an EJB. */
|
||||
class ForbiddenServerSocketCallable extends ForbiddenCallable {
|
||||
|
||||
@@ -73,9 +73,8 @@ abstract class AlwaysEnabledSpringProfile extends string {
|
||||
*
|
||||
* Includes all `SpringProfile`s that are not specified as always enabled or never enabled.
|
||||
*/
|
||||
class SometimesEnabledSpringProfile extends string {
|
||||
class SometimesEnabledSpringProfile extends string instanceof SpringProfile {
|
||||
SometimesEnabledSpringProfile() {
|
||||
this instanceof SpringProfile and
|
||||
not (
|
||||
this instanceof AlwaysEnabledSpringProfile or
|
||||
this instanceof NeverEnabledSpringProfile
|
||||
|
||||
@@ -290,9 +290,7 @@ string getSecureAlgorithmRegex() {
|
||||
* algorithm. For example, methods returning ciphers, decryption methods,
|
||||
* constructors of cipher classes, etc.
|
||||
*/
|
||||
abstract class CryptoAlgoSpec extends Top {
|
||||
CryptoAlgoSpec() { this instanceof Call }
|
||||
|
||||
abstract class CryptoAlgoSpec extends Top instanceof Call {
|
||||
abstract Expr getAlgoSpec();
|
||||
}
|
||||
|
||||
|
||||
@@ -298,8 +298,9 @@ private class PathNormalizeSanitizer extends MethodAccess {
|
||||
* what `getQualifier` actually gets in Java and Kotlin.
|
||||
*/
|
||||
private Expr getVisualQualifier(MethodAccess ma) {
|
||||
if getSourceMethod(ma.getMethod()) instanceof ExtensionMethod
|
||||
then result = ma.getArgument(0)
|
||||
if ma.getMethod() instanceof ExtensionMethod
|
||||
then
|
||||
result = ma.getArgument(ma.getMethod().(ExtensionMethod).getExtensionReceiverParameterIndex())
|
||||
else result = ma.getQualifier()
|
||||
}
|
||||
|
||||
@@ -310,8 +311,11 @@ private Expr getVisualQualifier(MethodAccess ma) {
|
||||
*/
|
||||
bindingset[argPos]
|
||||
private Argument getVisualArgument(MethodAccess ma, int argPos) {
|
||||
if getSourceMethod(ma.getMethod()) instanceof ExtensionMethod
|
||||
then result = ma.getArgument(argPos + 1)
|
||||
if ma.getMethod() instanceof ExtensionMethod
|
||||
then
|
||||
result =
|
||||
ma.getArgument(argPos + ma.getMethod().(ExtensionMethod).getExtensionReceiverParameterIndex() +
|
||||
1)
|
||||
else result = ma.getArgument(argPos)
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,7 @@ private class DefaultHeaderSplittingSink extends HeaderSplittingSink {
|
||||
}
|
||||
|
||||
/** A source that introduces data considered safe to use by a header splitting source. */
|
||||
abstract class SafeHeaderSplittingSource extends DataFlow::Node {
|
||||
SafeHeaderSplittingSource() { this instanceof RemoteFlowSource }
|
||||
}
|
||||
abstract class SafeHeaderSplittingSource extends DataFlow::Node instanceof RemoteFlowSource { }
|
||||
|
||||
/** A default source that introduces data considered safe to use by a header splitting source. */
|
||||
private class DefaultSafeHeaderSplittingSource extends SafeHeaderSplittingSource {
|
||||
|
||||
@@ -53,9 +53,7 @@ class SuppressionComment extends Javadoc {
|
||||
/**
|
||||
* The scope of an alert suppression comment.
|
||||
*/
|
||||
class SuppressionScope extends @javadoc {
|
||||
SuppressionScope() { this instanceof SuppressionComment }
|
||||
|
||||
class SuppressionScope extends @javadoc instanceof SuppressionComment {
|
||||
/** Gets a suppression comment with this scope. */
|
||||
SuppressionComment getSuppressionComment() { result = this }
|
||||
|
||||
@@ -69,7 +67,7 @@ class SuppressionScope extends @javadoc {
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.(SuppressionComment).covers(filepath, startline, startcolumn, endline, endcolumn)
|
||||
super.covers(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
|
||||
@@ -69,9 +69,7 @@ class SuppressionAnnotation extends SuppressWarningsAnnotation {
|
||||
/**
|
||||
* The scope of an alert suppression annotation.
|
||||
*/
|
||||
class SuppressionScope extends @annotation {
|
||||
SuppressionScope() { this instanceof SuppressionAnnotation }
|
||||
|
||||
class SuppressionScope extends @annotation instanceof SuppressionAnnotation {
|
||||
/** Gets a suppression annotation with this scope. */
|
||||
SuppressionAnnotation getSuppressionAnnotation() { result = this }
|
||||
|
||||
@@ -85,7 +83,7 @@ class SuppressionScope extends @annotation {
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.(SuppressionAnnotation).covers(filepath, startline, startcolumn, endline, endcolumn)
|
||||
super.covers(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
|
||||
@@ -20,9 +20,7 @@ int leftWidth(ComparisonExpr e) { result = e.getLeftOperand().getType().(NumType
|
||||
|
||||
int rightWidth(ComparisonExpr e) { result = e.getRightOperand().getType().(NumType).getWidthRank() }
|
||||
|
||||
abstract class WideningComparison extends BinaryExpr {
|
||||
WideningComparison() { this instanceof ComparisonExpr }
|
||||
|
||||
abstract class WideningComparison extends BinaryExpr instanceof ComparisonExpr {
|
||||
abstract Expr getNarrower();
|
||||
|
||||
abstract Expr getWider();
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
Allowing file access in an Android WebView can expose a device's file system to
|
||||
the JavaScript running in that WebView. If the JavaScript contains
|
||||
vulnerabilities or the WebView loads untrusted content, file access
|
||||
allows an attacker to steal the user's data.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>When possible, do not allow file access. The file access settings
|
||||
are disabled by default. You can explicitly disable file access by setting the
|
||||
following settings to <code>false</code>:</p>
|
||||
|
||||
<ul>
|
||||
<li><code>setAllowFileAccess</code></li>
|
||||
<li><code>setAllowFileAccessFromFileURLs</code></li>
|
||||
<li><code>setAllowUniversalAccessFromFileURLs</code></li>
|
||||
</ul>
|
||||
|
||||
<p>If your application requires access to the file system, it is best to
|
||||
avoid using <code>file://</code> URLs. Instead, use an alternative that
|
||||
loads files via HTTPS, such
|
||||
as <code>androidx.webkit.WebViewAssetLoader</code>.</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>In the following (bad) example, the WebView is configured with settings
|
||||
that allow local file access.</p>
|
||||
|
||||
<sample src="WebViewFileAccessUnsafe.java"/>
|
||||
|
||||
<p>In the following (good) example, the WebView is configured to disallow file access.</p>
|
||||
|
||||
<sample src="WebViewFileAccessSafe.java"/>
|
||||
|
||||
<p>
|
||||
As mentioned previously, asset loaders can load files without file system
|
||||
access. In the following (good) example, an asset loader is configured to
|
||||
load assets over HTTPS.
|
||||
</p>
|
||||
|
||||
<sample src="AssetLoaderExample.java"/>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
Android documentation: <a href="https://developer.android.com/reference/android/webkit/WebSettings#setAllowFileAccess(boolean)">WebSettings.setAllowFileAccess</a>.
|
||||
</li>
|
||||
<li>
|
||||
Android documentation: <a href="https://developer.android.com/reference/android/webkit/WebSettings#setAllowFileAccessFromFileURLs(boolean)">WebSettings.setAllowFileAccessFromFileURLs</a>.
|
||||
</li>
|
||||
<li>
|
||||
Android documentation: <a href="https://developer.android.com/reference/android/webkit/WebSettings#setAllowUniversalAccessFromFileURLs(boolean)">WebSettings.setAllowUniversalAccessFromFileURLs</a>.
|
||||
</li>
|
||||
<li>
|
||||
Android documentation: <a href="https://developer.android.com/reference/androidx/webkit/WebViewAssetLoader">WebViewAssetLoader</a>.
|
||||
</li>
|
||||
</references>
|
||||
|
||||
</qhelp>
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @name Android WebSettings file access
|
||||
* @kind problem
|
||||
* @description Enabling access to the file system in a WebView allows attackers to view sensitive information.
|
||||
* @id java/android-websettings-file-access
|
||||
* @problem.severity warning
|
||||
* @security-severity 6.5
|
||||
* @precision medium
|
||||
* @tags security
|
||||
* external/cwe/cwe-200
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.frameworks.android.WebView
|
||||
|
||||
from MethodAccess ma
|
||||
where
|
||||
ma.getMethod() instanceof CrossOriginAccessMethod and
|
||||
ma.getArgument(0).(CompileTimeConstantExpr).getBooleanValue() = true
|
||||
select ma,
|
||||
"WebView setting " + ma.getMethod().getName() +
|
||||
" may allow for unauthorized access of sensitive information."
|
||||
15
java/ql/src/Security/CWE/CWE-200/AssetLoaderExample.java
Normal file
15
java/ql/src/Security/CWE/CWE-200/AssetLoaderExample.java
Normal file
@@ -0,0 +1,15 @@
|
||||
WebViewAssetLoader loader = new WebViewAssetLoader.Builder()
|
||||
// Replace the domain with a domain you control, or use the default
|
||||
// appassets.androidplatform.com
|
||||
.setDomain("appassets.example.com")
|
||||
.addPathHandler("/resources", new AssetsPathHandler(this))
|
||||
.build();
|
||||
|
||||
webView.setWebViewClient(new WebViewClientCompat() {
|
||||
@Override
|
||||
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
|
||||
return assetLoader.shouldInterceptRequest(request.getUrl());
|
||||
}
|
||||
});
|
||||
|
||||
webView.loadUrl("https://appassets.example.com/resources/www/index.html");
|
||||
@@ -0,0 +1,5 @@
|
||||
WebSettings settings = view.getSettings();
|
||||
|
||||
settings.setAllowFileAccess(false);
|
||||
settings.setAllowFileAccessFromURLs(false);
|
||||
settings.setAllowUniversalAccessFromURLs(false);
|
||||
@@ -0,0 +1,5 @@
|
||||
WebSettings settings = view.getSettings();
|
||||
|
||||
settings.setAllowFileAccess(true);
|
||||
settings.setAllowFileAccessFromURLs(true);
|
||||
settings.setAllowUniversalAccessFromURLs(true);
|
||||
@@ -11,8 +11,8 @@ import semmle.code.java.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
|
||||
import ExternalApi
|
||||
|
||||
private predicate relevant(ExternalApi api) {
|
||||
api.isSupported() or
|
||||
api = any(FlowSummaryImpl::Public::NegativeSummarizedCallable nsc).asCallable()
|
||||
api.isSupported() or
|
||||
api = any(FlowSummaryImpl::Public::NeutralCallable nsc).asCallable()
|
||||
}
|
||||
|
||||
from string apiName, int usages
|
||||
|
||||
@@ -12,7 +12,7 @@ import ExternalApi
|
||||
|
||||
private predicate relevant(ExternalApi api) {
|
||||
not api.isSupported() and
|
||||
not api = any(FlowSummaryImpl::Public::NegativeSummarizedCallable nsc).asCallable()
|
||||
not api = any(FlowSummaryImpl::Public::NeutralCallable nsc).asCallable()
|
||||
}
|
||||
|
||||
from string apiName, int usages
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
* Added a new query `java/android-websettings-file-access` to detect configurations that enable file system access in Android WebViews.
|
||||
|
||||
@@ -81,8 +81,7 @@ private class CompareSink extends ClientSuppliedIpUsedInSecurityCheckSink {
|
||||
}
|
||||
|
||||
/** A data flow sink for sql operation. */
|
||||
private class SqlOperationSink extends ClientSuppliedIpUsedInSecurityCheckSink {
|
||||
SqlOperationSink() { this instanceof QueryInjectionSink }
|
||||
private class SqlOperationSink extends ClientSuppliedIpUsedInSecurityCheckSink instanceof QueryInjectionSink {
|
||||
}
|
||||
|
||||
/** A method that split string. */
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
|
||||
<overview>
|
||||
<p>The <code>Thread.sleep</code> method is used to pause the execution of current thread for
|
||||
specified time. When the sleep time is user-controlled, especially in the web application context,
|
||||
it can be abused to cause all of a server's threads to sleep, leading to denial of service.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>To guard against this attack, consider specifying an upper range of allowed sleep time or adopting
|
||||
the producer/consumer design pattern with <code>Object.wait</code> method to avoid performance
|
||||
problems or even resource exhaustion. For more information, refer to the concurrency tutorial of Oracle
|
||||
listed below or <code>java/ql/src/Likely Bugs/Concurrency</code> queries of CodeQL.</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>The following example shows a bad situation and a good situation respectively. In the bad situation,
|
||||
a thread sleep time comes directly from user input. In the good situation, an upper
|
||||
range check on the maximum sleep time allowed is enforced.</p>
|
||||
<sample src="ThreadResourceAbuse.java" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
Snyk:
|
||||
<a href="https://snyk.io/vuln/SNYK-JAVA-COMGOOGLECODEGWTUPLOAD-569506">Denial of Service (DoS)
|
||||
in com.googlecode.gwtupload:gwtupload</a>.
|
||||
</li>
|
||||
<li>
|
||||
gwtupload:
|
||||
<a href="https://github.com/manolo/gwtupload/issues/33">[Fix DOS issue] Updating the
|
||||
AbstractUploadListener.java file</a>.
|
||||
</li>
|
||||
<li>
|
||||
The blog of a gypsy engineer:
|
||||
<a href="https://blog.gypsyengineer.com/en/security/cve-2019-17555-dos-via-retry-after-header-in-apache-olingo.html">
|
||||
CVE-2019-17555: DoS via Retry-After header in Apache Olingo</a>.
|
||||
</li>
|
||||
<li>
|
||||
Oracle:
|
||||
<a href="https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html">The Java Concurrency Tutorials</a>
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -3,7 +3,7 @@
|
||||
* @description Using user input directly to control a thread's sleep time could lead to
|
||||
* performance problems or even resource exhaustion.
|
||||
* @kind path-problem
|
||||
* @id java/thread-resource-abuse
|
||||
* @id java/local-thread-resource-abuse
|
||||
* @problem.severity recommendation
|
||||
* @tags security
|
||||
* external/cwe/cwe-400
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* @name Capture negative summary models.
|
||||
* @description Finds negative summary models to be used by other queries.
|
||||
* @name Capture neutral models.
|
||||
* @description Finds neutral models to be used by other queries.
|
||||
* @kind diagnostic
|
||||
* @id java/utils/model-generator/negative-summary-models
|
||||
* @id java/utils/model-generator/neutral-models
|
||||
* @tags model-generator
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
# Tool to regenerate existing framework CSV models.
|
||||
|
||||
from pathlib import Path
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
@@ -37,7 +36,7 @@ def regenerateModel(lgtmSlug, extractedDb):
|
||||
modelFile = lgtmSlugToModelFile[lgtmSlug]
|
||||
codeQlRoot = findGitRoot()
|
||||
subprocess.check_call([codeQlRoot + "/java/ql/src/utils/model-generator/GenerateFlowModel.py",
|
||||
"--with-summaries", "--with-sinks", "--with-negative-summaries",
|
||||
"--with-summaries", "--with-sinks", "--with-neutrals",
|
||||
extractedDb, modelFile])
|
||||
print("Regenerated " + modelFile)
|
||||
shutil.rmtree(tmpDir)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @name Extract MaD negative summary model rows.
|
||||
* @description This extracts the Models as data negative summary model rows.
|
||||
* @id java/utils/modelconverter/generate-data-extensions-negative-summary
|
||||
* @name Extract MaD neutral model rows.
|
||||
* @description This extracts the Models as data neutral model rows.
|
||||
* @id java/utils/modelconverter/generate-data-extensions-neutral
|
||||
*/
|
||||
|
||||
import java
|
||||
@@ -9,6 +9,6 @@ import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
from string package, string type, string name, string signature, string provenance
|
||||
where
|
||||
negativeSummaryModel(package, type, name, signature, provenance) and
|
||||
neutralModel(package, type, name, signature, provenance) and
|
||||
provenance != "generated"
|
||||
select package, type, name, signature, provenance order by package, type, name, signature
|
||||
@@ -58,9 +58,7 @@ private string asSummaryModel(TargetApiSpecific api, string input, string output
|
||||
+ "generated"
|
||||
}
|
||||
|
||||
string asNegativeSummaryModel(TargetApiSpecific api) {
|
||||
result = asPartialNegativeModel(api) + "generated"
|
||||
}
|
||||
string asNeutralModel(TargetApiSpecific api) { result = asPartialNeutralModel(api) + "generated" }
|
||||
|
||||
/**
|
||||
* Gets the value summary model for `api` with `input` and `output`.
|
||||
|
||||
@@ -131,9 +131,9 @@ string asPartialModel(TargetApiSpecific api) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the first 4 columns for negative CSV rows.
|
||||
* Computes the first 4 columns for neutral CSV rows.
|
||||
*/
|
||||
string asPartialNegativeModel(TargetApiSpecific api) {
|
||||
string asPartialNeutralModel(TargetApiSpecific api) {
|
||||
exists(string type, string name, string parameters |
|
||||
partialModel(api, type, name, parameters) and
|
||||
result =
|
||||
|
||||
@@ -77,10 +77,10 @@ string captureFlow(DataFlowTargetApi api) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the negative summary for `api`, if any.
|
||||
* A negative summary is generated, if there does not exist any positive flow.
|
||||
* Gets the neutral summary for `api`, if any.
|
||||
* A neutral model is generated, if there does not exist any summary model.
|
||||
*/
|
||||
string captureNoFlow(DataFlowTargetApi api) {
|
||||
not exists(captureFlow(api)) and
|
||||
result = asNegativeSummaryModel(api)
|
||||
result = asNeutralModel(api)
|
||||
}
|
||||
|
||||
@@ -499,11 +499,8 @@ private RefType getAReferencedType(RefType t) {
|
||||
}
|
||||
|
||||
/** A top level type whose file should be stubbed */
|
||||
class GeneratedTopLevel extends TopLevelType {
|
||||
GeneratedTopLevel() {
|
||||
this = this.getSourceDeclaration() and
|
||||
this instanceof GeneratedType
|
||||
}
|
||||
class GeneratedTopLevel extends TopLevelType instanceof GeneratedType {
|
||||
GeneratedTopLevel() { this = this.getSourceDeclaration() }
|
||||
|
||||
private TopLevelType getAnImportedType() {
|
||||
result = getAReferencedType(this).getSourceDeclaration()
|
||||
@@ -536,8 +533,6 @@ class GeneratedTopLevel extends TopLevelType {
|
||||
|
||||
/** Creates a full stub for the file containing this type. */
|
||||
string stubFile() {
|
||||
result =
|
||||
this.stubComment() + this.stubPackage() + this.stubImports() + this.(GeneratedType).getStub() +
|
||||
"\n"
|
||||
result = this.stubComment() + this.stubPackage() + this.stubImports() + super.getStub() + "\n"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,82 +1,21 @@
|
||||
test.kt:
|
||||
# 0| [CompilationUnit] test
|
||||
# 3| 1: [Interface] A
|
||||
# 3| 1: [Constructor] A
|
||||
#-----| 4: (Parameters)
|
||||
# 3| 0: [Parameter] c1
|
||||
# 3| 0: [TypeAccess] Class<?>
|
||||
# 3| 0: [WildcardTypeAccess] ? ...
|
||||
# 3| 1: [Parameter] c2
|
||||
# 3| 0: [TypeAccess] Class<? extends CharSequence>
|
||||
# 3| 0: [WildcardTypeAccess] ? ...
|
||||
# 3| 0: [TypeAccess] CharSequence
|
||||
# 3| 2: [Parameter] c3
|
||||
# 3| 0: [TypeAccess] Class<String>
|
||||
# 3| 0: [TypeAccess] String
|
||||
# 3| 3: [Parameter] c4
|
||||
# 3| 0: [TypeAccess] Class<?>[]
|
||||
# 3| 0: [TypeAccess] Class<?>
|
||||
# 3| 0: [WildcardTypeAccess] ? ...
|
||||
# 3| 5: [BlockStmt] { ... }
|
||||
# 3| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 3| 1: [BlockStmt] { ... }
|
||||
# 3| 0: [ExprStmt] <Expr>;
|
||||
# 3| 0: [KtInitializerAssignExpr] ...=...
|
||||
# 3| 0: [VarAccess] c1
|
||||
# 3| 1: [ExprStmt] <Expr>;
|
||||
# 3| 0: [KtInitializerAssignExpr] ...=...
|
||||
# 3| 0: [VarAccess] c2
|
||||
# 3| 2: [ExprStmt] <Expr>;
|
||||
# 3| 0: [KtInitializerAssignExpr] ...=...
|
||||
# 3| 0: [VarAccess] c3
|
||||
# 3| 3: [ExprStmt] <Expr>;
|
||||
# 3| 0: [KtInitializerAssignExpr] ...=...
|
||||
# 3| 0: [VarAccess] c4
|
||||
# 3| 2: [FieldDeclaration] Class<?> c1;
|
||||
# 3| -1: [TypeAccess] Class<?>
|
||||
# 3| 0: [WildcardTypeAccess] ? ...
|
||||
# 3| 0: [VarAccess] c1
|
||||
# 3| 3: [Method] c1
|
||||
#-----| -3: (Annotations)
|
||||
# 0| 1: [Annotation] Retention
|
||||
# 0| 1: [VarAccess] RetentionPolicy.RUNTIME
|
||||
# 0| -1: [TypeAccess] RetentionPolicy
|
||||
# 3| 1: [Method] c1
|
||||
# 3| 3: [TypeAccess] Class<?>
|
||||
# 3| 0: [WildcardTypeAccess] ? ...
|
||||
# 3| 5: [BlockStmt] { ... }
|
||||
# 3| 0: [ReturnStmt] return ...
|
||||
# 3| 0: [VarAccess] this.c1
|
||||
# 3| -1: [ThisAccess] this
|
||||
# 3| 4: [FieldDeclaration] Class<? extends CharSequence> c2;
|
||||
# 3| -1: [TypeAccess] Class<? extends CharSequence>
|
||||
# 3| 0: [WildcardTypeAccess] ? ...
|
||||
# 3| 0: [TypeAccess] CharSequence
|
||||
# 3| 0: [VarAccess] c2
|
||||
# 3| 5: [Method] c2
|
||||
# 3| 2: [Method] c2
|
||||
# 3| 3: [TypeAccess] Class<? extends CharSequence>
|
||||
# 3| 0: [WildcardTypeAccess] ? ...
|
||||
# 3| 0: [TypeAccess] CharSequence
|
||||
# 3| 5: [BlockStmt] { ... }
|
||||
# 3| 0: [ReturnStmt] return ...
|
||||
# 3| 0: [VarAccess] this.c2
|
||||
# 3| -1: [ThisAccess] this
|
||||
# 3| 6: [FieldDeclaration] Class<String> c3;
|
||||
# 3| -1: [TypeAccess] Class<String>
|
||||
# 3| 0: [TypeAccess] String
|
||||
# 3| 0: [VarAccess] c3
|
||||
# 3| 7: [Method] c3
|
||||
# 3| 3: [Method] c3
|
||||
# 3| 3: [TypeAccess] Class<String>
|
||||
# 3| 0: [TypeAccess] String
|
||||
# 3| 5: [BlockStmt] { ... }
|
||||
# 3| 0: [ReturnStmt] return ...
|
||||
# 3| 0: [VarAccess] this.c3
|
||||
# 3| -1: [ThisAccess] this
|
||||
# 3| 8: [FieldDeclaration] Class<?>[] c4;
|
||||
# 3| -1: [TypeAccess] Class<?>[]
|
||||
# 3| 0: [TypeAccess] Class<?>
|
||||
# 3| 0: [WildcardTypeAccess] ? ...
|
||||
# 3| 0: [VarAccess] c4
|
||||
# 3| 9: [Method] c4
|
||||
# 3| 4: [Method] c4
|
||||
# 3| 3: [TypeAccess] Class<?>[]
|
||||
# 3| 0: [TypeAccess] Class<?>
|
||||
# 3| 0: [WildcardTypeAccess] ? ...
|
||||
# 3| 5: [BlockStmt] { ... }
|
||||
# 3| 0: [ReturnStmt] return ...
|
||||
# 3| 0: [VarAccess] this.c4
|
||||
# 3| -1: [ThisAccess] this
|
||||
|
||||
@@ -1,35 +1,9 @@
|
||||
classExprs
|
||||
| test.kt:3:20:3:36 | ...=... | Class<?> |
|
||||
| test.kt:3:20:3:36 | Class<?> | Class<?> |
|
||||
| test.kt:3:20:3:36 | Class<?> | Class<?> |
|
||||
| test.kt:3:20:3:36 | Class<?> | Class<?> |
|
||||
| test.kt:3:20:3:36 | c1 | Class<?> |
|
||||
| test.kt:3:20:3:36 | c1 | Class<?> |
|
||||
| test.kt:3:20:3:36 | this.c1 | Class<?> |
|
||||
| test.kt:3:39:3:70 | ...=... | Class<? extends CharSequence> |
|
||||
| test.kt:3:39:3:70 | Class<? extends CharSequence> | Class<? extends CharSequence> |
|
||||
| test.kt:3:39:3:70 | Class<? extends CharSequence> | Class<? extends CharSequence> |
|
||||
| test.kt:3:39:3:70 | Class<? extends CharSequence> | Class<? extends CharSequence> |
|
||||
| test.kt:3:39:3:70 | c2 | Class<? extends CharSequence> |
|
||||
| test.kt:3:39:3:70 | c2 | Class<? extends CharSequence> |
|
||||
| test.kt:3:39:3:70 | this.c2 | Class<? extends CharSequence> |
|
||||
| test.kt:3:73:3:94 | ...=... | Class<String> |
|
||||
| test.kt:3:73:3:94 | Class<String> | Class<String> |
|
||||
| test.kt:3:73:3:94 | Class<String> | Class<String> |
|
||||
| test.kt:3:73:3:94 | Class<String> | Class<String> |
|
||||
| test.kt:3:73:3:94 | c3 | Class<String> |
|
||||
| test.kt:3:73:3:94 | c3 | Class<String> |
|
||||
| test.kt:3:73:3:94 | this.c3 | Class<String> |
|
||||
| test.kt:3:97:3:120 | ...=... | Class<?>[] |
|
||||
| test.kt:3:97:3:120 | Class<?> | Class<?> |
|
||||
| test.kt:3:97:3:120 | Class<?> | Class<?> |
|
||||
| test.kt:3:97:3:120 | Class<?> | Class<?> |
|
||||
| test.kt:3:97:3:120 | Class<?>[] | Class<?>[] |
|
||||
| test.kt:3:97:3:120 | Class<?>[] | Class<?>[] |
|
||||
| test.kt:3:97:3:120 | Class<?>[] | Class<?>[] |
|
||||
| test.kt:3:97:3:120 | c4 | Class<?>[] |
|
||||
| test.kt:3:97:3:120 | c4 | Class<?>[] |
|
||||
| test.kt:3:97:3:120 | this.c4 | Class<?>[] |
|
||||
#select
|
||||
| test.kt:3:20:3:36 | c1 | Class<?> |
|
||||
| test.kt:3:39:3:70 | c2 | Class<? extends CharSequence> |
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
public @interface Annot0j {
|
||||
int abc() default 0;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
public @interface Annot1j {
|
||||
int a() default 2;
|
||||
|
||||
String b() default "ab";
|
||||
|
||||
Class c() default X.class;
|
||||
|
||||
Y d() default Y.A;
|
||||
|
||||
Y[] e() default { Y.A, Y.B };
|
||||
|
||||
Annot0j f() default @Annot0j(
|
||||
abc = 1
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
Annot0j.java:
|
||||
# 0| [CompilationUnit] Annot0j
|
||||
# 1| 1: [Interface] Annot0j
|
||||
# 2| 1: [Method] abc
|
||||
# 2| 3: [TypeAccess] int
|
||||
Annot1j.java:
|
||||
# 0| [CompilationUnit] Annot1j
|
||||
# 1| 1: [Interface] Annot1j
|
||||
# 2| 1: [Method] a
|
||||
# 2| 3: [TypeAccess] int
|
||||
# 4| 2: [Method] b
|
||||
# 4| 3: [TypeAccess] String
|
||||
# 6| 3: [Method] c
|
||||
# 6| 3: [TypeAccess] Class<>
|
||||
# 8| 4: [Method] d
|
||||
# 8| 3: [TypeAccess] Y
|
||||
# 10| 5: [Method] e
|
||||
# 10| 3: [ArrayTypeAccess] ...[]
|
||||
# 10| 0: [TypeAccess] Y
|
||||
# 12| 6: [Method] f
|
||||
# 12| 3: [TypeAccess] Annot0j
|
||||
def.kt:
|
||||
# 0| [CompilationUnit] def
|
||||
# 0| 1: [Class] DefKt
|
||||
# 46| 2: [Method] fn
|
||||
#-----| 1: (Annotations)
|
||||
# 45| 1: [Annotation] Annot0k
|
||||
# 0| 1: [IntegerLiteral] 0
|
||||
#-----| 2: (Generic Parameters)
|
||||
# 46| 0: [TypeVariable] T
|
||||
# 46| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 46| 0: [Parameter] a
|
||||
#-----| -1: (Annotations)
|
||||
# 46| 1: [Annotation] Annot0k
|
||||
# 0| 1: [IntegerLiteral] 0
|
||||
# 46| 0: [TypeAccess] Annot0k
|
||||
# 46| 5: [BlockStmt] { ... }
|
||||
# 47| 0: [ExprStmt] <Expr>;
|
||||
# 47| 0: [MethodAccess] println(...)
|
||||
# 47| -1: [TypeAccess] ConsoleKt
|
||||
# 47| 0: [MethodAccess] a(...)
|
||||
# 47| -1: [VarAccess] a
|
||||
# 50| 1: [LocalVariableDeclStmt] var ...;
|
||||
# 50| 1: [LocalVariableDeclExpr] x
|
||||
# 50| 0: [IntegerLiteral] 10
|
||||
# 53| 3: [FieldDeclaration] int p;
|
||||
#-----| -2: (Annotations)
|
||||
# 56| 1: [Annotation] Annot0k
|
||||
# 0| 1: [IntegerLiteral] 0
|
||||
# 53| -1: [TypeAccess] int
|
||||
# 57| 0: [IntegerLiteral] 5
|
||||
# 57| 4: [Method] getP
|
||||
#-----| 1: (Annotations)
|
||||
# 54| 1: [Annotation] Annot0k
|
||||
# 0| 1: [IntegerLiteral] 0
|
||||
# 57| 3: [TypeAccess] int
|
||||
# 57| 5: [BlockStmt] { ... }
|
||||
# 57| 0: [ReturnStmt] return ...
|
||||
# 57| 0: [VarAccess] DefKt.p
|
||||
# 57| -1: [TypeAccess] DefKt
|
||||
# 57| 5: [Method] setP
|
||||
#-----| 1: (Annotations)
|
||||
# 55| 1: [Annotation] Annot0k
|
||||
# 0| 1: [IntegerLiteral] 0
|
||||
# 57| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 57| 0: [Parameter] <set-?>
|
||||
# 57| 0: [TypeAccess] int
|
||||
# 57| 5: [BlockStmt] { ... }
|
||||
# 57| 0: [ExprStmt] <Expr>;
|
||||
# 57| 0: [AssignExpr] ...=...
|
||||
# 57| 0: [VarAccess] DefKt.p
|
||||
# 57| -1: [TypeAccess] DefKt
|
||||
# 57| 1: [VarAccess] <set-?>
|
||||
# 59| 6: [ExtensionMethod] myExtension
|
||||
# 59| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 59| 0: [Parameter] <this>
|
||||
#-----| -1: (Annotations)
|
||||
# 59| 1: [Annotation] Annot0k
|
||||
# 0| 1: [IntegerLiteral] 0
|
||||
# 59| 0: [TypeAccess] String
|
||||
# 59| 5: [BlockStmt] { ... }
|
||||
# 5| 2: [Interface] Annot0k
|
||||
#-----| -3: (Annotations)
|
||||
# 0| 1: [Annotation] Retention
|
||||
# 0| 1: [VarAccess] RetentionPolicy.RUNTIME
|
||||
# 0| -1: [TypeAccess] RetentionPolicy
|
||||
# 0| 2: [Annotation] Target
|
||||
# 0| 1: [ArrayInit] {...}
|
||||
# 0| 1: [VarAccess] ElementType.TYPE
|
||||
# 0| -1: [TypeAccess] ElementType
|
||||
# 0| 2: [VarAccess] ElementType.FIELD
|
||||
# 0| -1: [TypeAccess] ElementType
|
||||
# 0| 3: [VarAccess] ElementType.METHOD
|
||||
# 0| -1: [TypeAccess] ElementType
|
||||
# 0| 4: [VarAccess] ElementType.PARAMETER
|
||||
# 0| -1: [TypeAccess] ElementType
|
||||
# 0| 5: [VarAccess] ElementType.CONSTRUCTOR
|
||||
# 0| -1: [TypeAccess] ElementType
|
||||
# 0| 6: [VarAccess] ElementType.LOCAL_VARIABLE
|
||||
# 0| -1: [TypeAccess] ElementType
|
||||
# 0| 7: [VarAccess] ElementType.ANNOTATION_TYPE
|
||||
# 0| -1: [TypeAccess] ElementType
|
||||
# 0| 8: [VarAccess] ElementType.TYPE_PARAMETER
|
||||
# 0| -1: [TypeAccess] ElementType
|
||||
# 0| 9: [VarAccess] ElementType.TYPE_USE
|
||||
# 0| -1: [TypeAccess] ElementType
|
||||
# 5| 3: [Annotation] Target
|
||||
# 0| 1: [ArrayInit] {...}
|
||||
# 0| 1: [VarAccess] AnnotationTarget.CLASS
|
||||
# 0| -1: [TypeAccess] AnnotationTarget
|
||||
# 0| 2: [VarAccess] AnnotationTarget.ANNOTATION_CLASS
|
||||
# 0| -1: [TypeAccess] AnnotationTarget
|
||||
# 0| 3: [VarAccess] AnnotationTarget.TYPE_PARAMETER
|
||||
# 0| -1: [TypeAccess] AnnotationTarget
|
||||
# 0| 4: [VarAccess] AnnotationTarget.PROPERTY
|
||||
# 0| -1: [TypeAccess] AnnotationTarget
|
||||
# 0| 5: [VarAccess] AnnotationTarget.FIELD
|
||||
# 0| -1: [TypeAccess] AnnotationTarget
|
||||
# 0| 6: [VarAccess] AnnotationTarget.LOCAL_VARIABLE
|
||||
# 0| -1: [TypeAccess] AnnotationTarget
|
||||
# 0| 7: [VarAccess] AnnotationTarget.VALUE_PARAMETER
|
||||
# 0| -1: [TypeAccess] AnnotationTarget
|
||||
# 0| 8: [VarAccess] AnnotationTarget.CONSTRUCTOR
|
||||
# 0| -1: [TypeAccess] AnnotationTarget
|
||||
# 0| 9: [VarAccess] AnnotationTarget.FUNCTION
|
||||
# 0| -1: [TypeAccess] AnnotationTarget
|
||||
# 0| 10: [VarAccess] AnnotationTarget.PROPERTY_GETTER
|
||||
# 0| -1: [TypeAccess] AnnotationTarget
|
||||
# 0| 11: [VarAccess] AnnotationTarget.PROPERTY_SETTER
|
||||
# 0| -1: [TypeAccess] AnnotationTarget
|
||||
# 0| 12: [VarAccess] AnnotationTarget.TYPE
|
||||
# 0| -1: [TypeAccess] AnnotationTarget
|
||||
# 0| 13: [VarAccess] AnnotationTarget.FILE
|
||||
# 0| -1: [TypeAccess] AnnotationTarget
|
||||
# 0| 14: [VarAccess] AnnotationTarget.TYPEALIAS
|
||||
# 0| -1: [TypeAccess] AnnotationTarget
|
||||
# 21| 1: [Method] a
|
||||
#-----| 1: (Annotations)
|
||||
# 21| 1: [Annotation] JvmName
|
||||
# 0| 1: [StringLiteral] "a"
|
||||
# 21| 3: [TypeAccess] int
|
||||
# 23| 3: [Interface] Annot1k
|
||||
#-----| -3: (Annotations)
|
||||
# 0| 1: [Annotation] Retention
|
||||
# 0| 1: [VarAccess] RetentionPolicy.RUNTIME
|
||||
# 0| -1: [TypeAccess] RetentionPolicy
|
||||
# 23| 2: [Annotation] Annot0k
|
||||
# 0| 1: [IntegerLiteral] 0
|
||||
# 25| 1: [Method] a
|
||||
# 25| 3: [TypeAccess] int
|
||||
# 26| 2: [Method] b
|
||||
# 26| 3: [TypeAccess] String
|
||||
# 27| 3: [Method] c
|
||||
# 27| 3: [TypeAccess] Class<?>
|
||||
# 27| 0: [WildcardTypeAccess] ? ...
|
||||
# 28| 4: [Method] d
|
||||
# 28| 3: [TypeAccess] Y
|
||||
# 29| 5: [Method] e
|
||||
# 29| 3: [TypeAccess] Y[]
|
||||
# 29| 0: [TypeAccess] Y
|
||||
# 30| 6: [Method] f
|
||||
# 30| 3: [TypeAccess] Annot0k
|
||||
# 33| 4: [Class] X
|
||||
# 33| 1: [Constructor] X
|
||||
# 33| 5: [BlockStmt] { ... }
|
||||
# 33| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 33| 1: [BlockStmt] { ... }
|
||||
# 34| 5: [Class] Y
|
||||
# 0| 2: [Method] valueOf
|
||||
# 0| 3: [TypeAccess] Y
|
||||
#-----| 4: (Parameters)
|
||||
# 0| 0: [Parameter] value
|
||||
# 0| 0: [TypeAccess] String
|
||||
# 0| 3: [Method] values
|
||||
# 0| 3: [TypeAccess] Y[]
|
||||
# 0| 0: [TypeAccess] Y
|
||||
# 34| 4: [Constructor] Y
|
||||
# 34| 5: [BlockStmt] { ... }
|
||||
# 34| 0: [ExprStmt] <Expr>;
|
||||
# 34| 0: [ClassInstanceExpr] new Enum(...)
|
||||
# 34| -3: [TypeAccess] Enum<Y>
|
||||
# 34| 0: [TypeAccess] Y
|
||||
# 34| 0: [NullLiteral] null
|
||||
# 34| 1: [IntegerLiteral] 0
|
||||
# 34| 1: [BlockStmt] { ... }
|
||||
# 35| 5: [FieldDeclaration] Y A;
|
||||
# 35| -1: [TypeAccess] Y
|
||||
# 35| 0: [ClassInstanceExpr] new Y(...)
|
||||
# 35| -3: [TypeAccess] Y
|
||||
# 35| 6: [FieldDeclaration] Y B;
|
||||
# 35| -1: [TypeAccess] Y
|
||||
# 35| 0: [ClassInstanceExpr] new Y(...)
|
||||
# 35| -3: [TypeAccess] Y
|
||||
# 35| 7: [FieldDeclaration] Y C;
|
||||
# 35| -1: [TypeAccess] Y
|
||||
# 35| 0: [ClassInstanceExpr] new Y(...)
|
||||
# 35| -3: [TypeAccess] Y
|
||||
# 38| 6: [Class] Z
|
||||
#-----| -3: (Annotations)
|
||||
# 38| 1: [Annotation] Annot0k
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 39| 2: [Annotation] Annot1k
|
||||
# 0| 1: [IntegerLiteral] 2
|
||||
# 0| 2: [StringLiteral] "ab"
|
||||
# 0| 3: [TypeLiteral] X.class
|
||||
# 0| 0: [TypeAccess] X
|
||||
# 0| 4: [VarAccess] Y.B
|
||||
# 0| -1: [TypeAccess] Y
|
||||
# 0| 5: [ArrayInit] {...}
|
||||
# 0| 1: [VarAccess] Y.C
|
||||
# 0| -1: [TypeAccess] Y
|
||||
# 0| 2: [VarAccess] Y.A
|
||||
# 0| -1: [TypeAccess] Y
|
||||
# 0| 6: [Annotation] Annot0k
|
||||
# 0| 1: [IntegerLiteral] 1
|
||||
# 42| 1: [Constructor] Z
|
||||
#-----| 1: (Annotations)
|
||||
# 41| 1: [Annotation] Annot0k
|
||||
# 0| 1: [IntegerLiteral] 0
|
||||
# 41| 5: [BlockStmt] { ... }
|
||||
# 42| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 42| 1: [BlockStmt] { ... }
|
||||
use.java:
|
||||
# 0| [CompilationUnit] use
|
||||
# 1| 1: [Class] use
|
||||
#-----| -1: (Base Types)
|
||||
# 1| 0: [TypeAccess] Annot0k
|
||||
# 3| 2: [Method] a
|
||||
#-----| 1: (Annotations)
|
||||
# 2| 1: [Annotation] Override
|
||||
# 3| 3: [TypeAccess] int
|
||||
# 3| 5: [BlockStmt] { ... }
|
||||
# 3| 0: [ReturnStmt] return ...
|
||||
# 3| 0: [IntegerLiteral] 1
|
||||
# 6| 3: [Method] annotationType
|
||||
#-----| 1: (Annotations)
|
||||
# 5| 1: [Annotation] Override
|
||||
# 6| 3: [TypeAccess] Class<? extends Annotation>
|
||||
# 6| 0: [WildcardTypeAccess] ? ...
|
||||
# 6| 0: [TypeAccess] Annotation
|
||||
# 6| 5: [BlockStmt] { ... }
|
||||
# 7| 0: [ReturnStmt] return ...
|
||||
# 7| 0: [NullLiteral] null
|
||||
# 14| 4: [Class] Z
|
||||
#-----| -3: (Annotations)
|
||||
# 10| 1: [Annotation] Annot0j
|
||||
# 10| 1: [IntegerLiteral] 1
|
||||
# 11| 2: [Annotation] Annot1j
|
||||
# 11| 1: [IntegerLiteral] 1
|
||||
# 11| 2: [StringLiteral] "ac"
|
||||
# 11| 3: [TypeLiteral] X.class
|
||||
# 11| 0: [TypeAccess] X
|
||||
# 11| 4: [VarAccess] Y.B
|
||||
# 11| -1: [TypeAccess] Y
|
||||
# 11| 5: [ArrayInit] {...}
|
||||
# 11| 3: [VarAccess] Y.C
|
||||
# 11| -1: [TypeAccess] Y
|
||||
# 11| 4: [VarAccess] Y.A
|
||||
# 11| -1: [TypeAccess] Y
|
||||
# 11| 6: [Annotation] Annot0j
|
||||
# 11| 1: [IntegerLiteral] 2
|
||||
# 12| 3: [Annotation] Annot0k
|
||||
# 12| 1: [IntegerLiteral] 1
|
||||
# 13| 4: [Annotation] Annot1k
|
||||
# 13| 1: [IntegerLiteral] 1
|
||||
# 13| 2: [StringLiteral] "ac"
|
||||
# 13| 3: [TypeLiteral] X.class
|
||||
# 13| 0: [TypeAccess] X
|
||||
# 13| 4: [VarAccess] Y.B
|
||||
# 13| -1: [TypeAccess] Y
|
||||
# 13| 5: [ArrayInit] {...}
|
||||
# 13| 3: [VarAccess] Y.C
|
||||
# 13| -1: [TypeAccess] Y
|
||||
# 13| 4: [VarAccess] Y.A
|
||||
# 13| -1: [TypeAccess] Y
|
||||
# 13| 6: [Annotation] Annot0k
|
||||
# 13| 1: [IntegerLiteral] 2
|
||||
@@ -0,0 +1 @@
|
||||
semmle/code/java/PrintAst.ql
|
||||
@@ -1,2 +1,82 @@
|
||||
| def.kt:2:1:2:31 | SomeAnnotation | Interface |
|
||||
| use.java:2:23:2:25 | use | Class |
|
||||
annotationDeclarations
|
||||
| Annot0j.java:1:19:1:25 | Annot0j | Annot0j.java:2:9:2:11 | abc |
|
||||
| Annot1j.java:1:19:1:25 | Annot1j | Annot1j.java:2:9:2:9 | a |
|
||||
| Annot1j.java:1:19:1:25 | Annot1j | Annot1j.java:4:12:4:12 | b |
|
||||
| Annot1j.java:1:19:1:25 | Annot1j | Annot1j.java:6:11:6:11 | c |
|
||||
| Annot1j.java:1:19:1:25 | Annot1j | Annot1j.java:8:7:8:7 | d |
|
||||
| Annot1j.java:1:19:1:25 | Annot1j | Annot1j.java:10:9:10:9 | e |
|
||||
| Annot1j.java:1:19:1:25 | Annot1j | Annot1j.java:12:13:12:13 | f |
|
||||
| def.kt:5:1:21:60 | Annot0k | def.kt:21:44:21:59 | a |
|
||||
| def.kt:23:1:31:1 | Annot1k | def.kt:25:5:25:18 | a |
|
||||
| def.kt:23:1:31:1 | Annot1k | def.kt:26:5:26:24 | b |
|
||||
| def.kt:23:1:31:1 | Annot1k | def.kt:27:5:27:31 | c |
|
||||
| def.kt:23:1:31:1 | Annot1k | def.kt:28:5:28:18 | d |
|
||||
| def.kt:23:1:31:1 | Annot1k | def.kt:29:5:29:32 | e |
|
||||
| def.kt:23:1:31:1 | Annot1k | def.kt:30:5:30:31 | f |
|
||||
annotations
|
||||
| def.kt:0:0:0:0 | Annot0k | def.kt:39:1:39:40 | Annot1k | def.kt:5:1:21:60 | Annot0k |
|
||||
| def.kt:23:1:23:8 | Annot0k | def.kt:23:1:31:1 | Annot1k | def.kt:5:1:21:60 | Annot0k |
|
||||
| def.kt:38:1:38:17 | Annot0k | def.kt:38:1:43:1 | Z | def.kt:5:1:21:60 | Annot0k |
|
||||
| def.kt:39:1:39:40 | Annot1k | def.kt:38:1:43:1 | Z | def.kt:23:1:31:1 | Annot1k |
|
||||
| def.kt:41:5:41:12 | Annot0k | def.kt:42:5:42:19 | Z | def.kt:5:1:21:60 | Annot0k |
|
||||
| def.kt:45:1:45:8 | Annot0k | def.kt:46:1:51:1 | fn | def.kt:5:1:21:60 | Annot0k |
|
||||
| def.kt:46:21:46:28 | Annot0k | def.kt:46:21:46:39 | a | def.kt:5:1:21:60 | Annot0k |
|
||||
| def.kt:54:1:54:12 | Annot0k | def.kt:57:1:57:23 | getP | def.kt:5:1:21:60 | Annot0k |
|
||||
| def.kt:55:1:55:12 | Annot0k | def.kt:57:1:57:23 | setP | def.kt:5:1:21:60 | Annot0k |
|
||||
| def.kt:56:1:56:14 | Annot0k | def.kt:53:1:57:23 | p | def.kt:5:1:21:60 | Annot0k |
|
||||
| def.kt:59:5:59:21 | Annot0k | def.kt:59:5:59:28 | <this> | def.kt:5:1:21:60 | Annot0k |
|
||||
| use.java:10:5:10:21 | Annot0j | use.java:14:18:14:18 | Z | Annot0j.java:1:19:1:25 | Annot0j |
|
||||
| use.java:11:5:11:90 | Annot1j | use.java:14:18:14:18 | Z | Annot1j.java:1:19:1:25 | Annot1j |
|
||||
| use.java:11:73:11:89 | Annot0j | use.java:11:5:11:90 | Annot1j | Annot0j.java:1:19:1:25 | Annot0j |
|
||||
| use.java:12:5:12:19 | Annot0k | use.java:14:18:14:18 | Z | def.kt:5:1:21:60 | Annot0k |
|
||||
| use.java:13:5:13:88 | Annot1k | use.java:14:18:14:18 | Z | def.kt:23:1:31:1 | Annot1k |
|
||||
| use.java:13:73:13:87 | Annot0k | use.java:13:5:13:88 | Annot1k | def.kt:5:1:21:60 | Annot0k |
|
||||
annotationValues
|
||||
| def.kt:0:0:0:0 | Annot0k | def.kt:0:0:0:0 | 1 |
|
||||
| def.kt:0:0:0:0 | Retention | def.kt:0:0:0:0 | RetentionPolicy.RUNTIME |
|
||||
| def.kt:0:0:0:0 | Retention | def.kt:0:0:0:0 | RetentionPolicy.RUNTIME |
|
||||
| def.kt:0:0:0:0 | Target | def.kt:0:0:0:0 | {...} |
|
||||
| def.kt:5:1:20:1 | Target | def.kt:0:0:0:0 | {...} |
|
||||
| def.kt:21:26:21:42 | JvmName | def.kt:0:0:0:0 | "a" |
|
||||
| def.kt:23:1:23:8 | Annot0k | def.kt:0:0:0:0 | 0 |
|
||||
| def.kt:38:1:38:17 | Annot0k | def.kt:0:0:0:0 | 1 |
|
||||
| def.kt:39:1:39:40 | Annot1k | def.kt:0:0:0:0 | 2 |
|
||||
| def.kt:39:1:39:40 | Annot1k | def.kt:0:0:0:0 | "ab" |
|
||||
| def.kt:39:1:39:40 | Annot1k | def.kt:0:0:0:0 | Annot0k |
|
||||
| def.kt:39:1:39:40 | Annot1k | def.kt:0:0:0:0 | X.class |
|
||||
| def.kt:39:1:39:40 | Annot1k | def.kt:0:0:0:0 | Y.B |
|
||||
| def.kt:39:1:39:40 | Annot1k | def.kt:0:0:0:0 | {...} |
|
||||
| def.kt:41:5:41:12 | Annot0k | def.kt:0:0:0:0 | 0 |
|
||||
| def.kt:45:1:45:8 | Annot0k | def.kt:0:0:0:0 | 0 |
|
||||
| def.kt:46:21:46:28 | Annot0k | def.kt:0:0:0:0 | 0 |
|
||||
| def.kt:54:1:54:12 | Annot0k | def.kt:0:0:0:0 | 0 |
|
||||
| def.kt:55:1:55:12 | Annot0k | def.kt:0:0:0:0 | 0 |
|
||||
| def.kt:56:1:56:14 | Annot0k | def.kt:0:0:0:0 | 0 |
|
||||
| def.kt:59:5:59:21 | Annot0k | def.kt:0:0:0:0 | 0 |
|
||||
| use.java:10:5:10:21 | Annot0j | use.java:10:20:10:20 | 1 |
|
||||
| use.java:11:5:11:90 | Annot1j | use.java:11:18:11:18 | 1 |
|
||||
| use.java:11:5:11:90 | Annot1j | use.java:11:25:11:28 | "ac" |
|
||||
| use.java:11:5:11:90 | Annot1j | use.java:11:35:11:41 | X.class |
|
||||
| use.java:11:5:11:90 | Annot1j | use.java:11:48:11:50 | Y.B |
|
||||
| use.java:11:5:11:90 | Annot1j | use.java:11:57:11:66 | {...} |
|
||||
| use.java:11:5:11:90 | Annot1j | use.java:11:73:11:89 | Annot0j |
|
||||
| use.java:11:73:11:89 | Annot0j | use.java:11:88:11:88 | 2 |
|
||||
| use.java:12:5:12:19 | Annot0k | use.java:12:18:12:18 | 1 |
|
||||
| use.java:13:5:13:88 | Annot1k | use.java:13:18:13:18 | 1 |
|
||||
| use.java:13:5:13:88 | Annot1k | use.java:13:25:13:28 | "ac" |
|
||||
| use.java:13:5:13:88 | Annot1k | use.java:13:35:13:41 | X.class |
|
||||
| use.java:13:5:13:88 | Annot1k | use.java:13:48:13:50 | Y.B |
|
||||
| use.java:13:5:13:88 | Annot1k | use.java:13:57:13:66 | {...} |
|
||||
| use.java:13:5:13:88 | Annot1k | use.java:13:73:13:87 | Annot0k |
|
||||
| use.java:13:73:13:87 | Annot0k | use.java:13:86:13:86 | 2 |
|
||||
#select
|
||||
| Annot0j.java:1:19:1:25 | Annot0j | Interface |
|
||||
| Annot1j.java:1:19:1:25 | Annot1j | Interface |
|
||||
| def.kt:0:0:0:0 | DefKt | Class |
|
||||
| def.kt:5:1:21:60 | Annot0k | Interface |
|
||||
| def.kt:23:1:31:1 | Annot1k | Interface |
|
||||
| def.kt:33:1:33:10 | X | Class |
|
||||
| def.kt:34:1:36:1 | Y | Class |
|
||||
| def.kt:38:1:43:1 | Z | Class |
|
||||
| use.java:1:14:1:16 | use | Class |
|
||||
| use.java:14:18:14:18 | Z | Class |
|
||||
|
||||
@@ -3,3 +3,18 @@ import java
|
||||
from ClassOrInterface x
|
||||
where x.fromSource()
|
||||
select x, x.getPrimaryQlClasses()
|
||||
|
||||
query predicate annotationDeclarations(AnnotationType at, AnnotationElement ae) {
|
||||
at.fromSource() and
|
||||
at.getAnAnnotationElement() = ae
|
||||
}
|
||||
|
||||
query predicate annotations(Annotation a, Element e, AnnotationType at) {
|
||||
at.fromSource() and
|
||||
a.getAnnotatedElement() = e and
|
||||
at = a.getType()
|
||||
}
|
||||
|
||||
query predicate annotationValues(Annotation a, Expr v) {
|
||||
a.getValue(_) = v and v.getFile().isSourceFile()
|
||||
}
|
||||
|
||||
@@ -1,3 +1,62 @@
|
||||
@file:Annot0k
|
||||
|
||||
annotation class SomeAnnotation
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
@Target(AnnotationTarget.CLASS,
|
||||
AnnotationTarget.ANNOTATION_CLASS,
|
||||
AnnotationTarget.TYPE_PARAMETER,
|
||||
AnnotationTarget.PROPERTY,
|
||||
AnnotationTarget.FIELD,
|
||||
AnnotationTarget.LOCAL_VARIABLE, // TODO
|
||||
AnnotationTarget.VALUE_PARAMETER,
|
||||
AnnotationTarget.CONSTRUCTOR,
|
||||
AnnotationTarget.FUNCTION,
|
||||
AnnotationTarget.PROPERTY_GETTER,
|
||||
AnnotationTarget.PROPERTY_SETTER,
|
||||
AnnotationTarget.TYPE, // TODO
|
||||
//AnnotationTarget.EXPRESSION, // TODO
|
||||
AnnotationTarget.FILE, // TODO
|
||||
AnnotationTarget.TYPEALIAS // TODO
|
||||
)
|
||||
annotation class Annot0k(@get:JvmName("a") val abc: Int = 0)
|
||||
|
||||
@Annot0k
|
||||
annotation class Annot1k(
|
||||
val a: Int = 2,
|
||||
val b: String = "ab",
|
||||
val c: KClass<*> = X::class,
|
||||
val d: Y = Y.A,
|
||||
val e: Array<Y> = [Y.A, Y.B],
|
||||
val f: Annot0k = Annot0k(1)
|
||||
)
|
||||
|
||||
class X {}
|
||||
enum class Y {
|
||||
A,B,C
|
||||
}
|
||||
|
||||
@Annot0k(abc = 1)
|
||||
@Annot1k(d = Y.B, e = arrayOf(Y.C, Y.A))
|
||||
class Z {
|
||||
@Annot0k
|
||||
constructor(){}
|
||||
}
|
||||
|
||||
@Annot0k
|
||||
fun <@Annot0k T> fn(@Annot0k a: Annot0k) {
|
||||
println(a.abc)
|
||||
|
||||
@Annot0k
|
||||
var x = 10
|
||||
}
|
||||
|
||||
@Annot0k
|
||||
@get:Annot0k
|
||||
@set:Annot0k
|
||||
@field:Annot0k
|
||||
var p: @Annot0k Int = 5
|
||||
|
||||
fun @receiver:Annot0k String.myExtension() { }
|
||||
|
||||
@Annot0k
|
||||
typealias AAA = Z
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
public class use implements Annot0k {
|
||||
@Override
|
||||
public int a() { return 1; }
|
||||
|
||||
public abstract class use implements SomeAnnotation {}
|
||||
@Override
|
||||
public Class<? extends java.lang.annotation.Annotation> annotationType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Annot0j(abc = 1)
|
||||
@Annot1j(a = 1, b = "ac", c = X.class, d = Y.B, e = {Y.C, Y.A}, f = @Annot0j(abc = 2))
|
||||
@Annot0k(a = 1)
|
||||
@Annot1k(a = 1, b = "ac", c = X.class, d = Y.B, e = {Y.C, Y.A}, f = @Annot0k(a = 2))
|
||||
public class Z { }
|
||||
}
|
||||
|
||||
@@ -1,84 +1,12 @@
|
||||
test.kt:
|
||||
# 0| [CompilationUnit] test
|
||||
# 1| 1: [Interface] Ann
|
||||
# 1| 1: [Constructor] Ann
|
||||
#-----| 4: (Parameters)
|
||||
# 1| 0: [Parameter] arr1
|
||||
# 1| 0: [TypeAccess] String[]
|
||||
# 1| 0: [TypeAccess] String
|
||||
# 1| 1: [Parameter] arr2
|
||||
# 1| 0: [TypeAccess] int[]
|
||||
# 1| 5: [BlockStmt] { ... }
|
||||
# 1| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 1| 1: [BlockStmt] { ... }
|
||||
# 1| 0: [ExprStmt] <Expr>;
|
||||
# 1| 0: [KtInitializerAssignExpr] ...=...
|
||||
# 1| 0: [VarAccess] arr1
|
||||
# 1| 1: [ExprStmt] <Expr>;
|
||||
# 1| 0: [KtInitializerAssignExpr] ...=...
|
||||
# 1| 0: [VarAccess] arr2
|
||||
# 1| 2: [Constructor] Ann
|
||||
#-----| 4: (Parameters)
|
||||
# 1| 0: [Parameter] p0
|
||||
# 1| 0: [TypeAccess] String[]
|
||||
# 1| 1: [Parameter] p1
|
||||
# 1| 0: [TypeAccess] int[]
|
||||
# 1| 2: [Parameter] p2
|
||||
# 1| 0: [TypeAccess] int
|
||||
# 1| 3: [Parameter] p3
|
||||
# 1| 0: [TypeAccess] DefaultConstructorMarker
|
||||
# 1| 5: [BlockStmt] { ... }
|
||||
# 1| 0: [IfStmt] if (...)
|
||||
# 1| 0: [EQExpr] ... == ...
|
||||
# 1| 0: [AndBitwiseExpr] ... & ...
|
||||
# 1| 0: [IntegerLiteral] 1
|
||||
# 1| 1: [VarAccess] p2
|
||||
# 1| 1: [IntegerLiteral] 0
|
||||
# 1| 1: [ExprStmt] <Expr>;
|
||||
# 1| 0: [AssignExpr] ...=...
|
||||
# 1| 0: [VarAccess] p0
|
||||
# 0| 1: [ArrayCreationExpr] new String[]
|
||||
# 0| -2: [ArrayInit] {...}
|
||||
# 0| 0: [StringLiteral] "hello"
|
||||
# 0| 1: [StringLiteral] "world"
|
||||
# 0| -1: [TypeAccess] String
|
||||
# 0| 0: [IntegerLiteral] 2
|
||||
# 1| 1: [IfStmt] if (...)
|
||||
# 1| 0: [EQExpr] ... == ...
|
||||
# 1| 0: [AndBitwiseExpr] ... & ...
|
||||
# 1| 0: [IntegerLiteral] 2
|
||||
# 1| 1: [VarAccess] p2
|
||||
# 1| 1: [IntegerLiteral] 0
|
||||
# 1| 1: [ExprStmt] <Expr>;
|
||||
# 1| 0: [AssignExpr] ...=...
|
||||
# 1| 0: [VarAccess] p1
|
||||
# 0| 1: [ArrayCreationExpr] new int[]
|
||||
# 0| -2: [ArrayInit] {...}
|
||||
# 0| 0: [IntegerLiteral] 1
|
||||
# 0| 1: [IntegerLiteral] 2
|
||||
# 0| 2: [IntegerLiteral] 3
|
||||
# 0| -1: [TypeAccess] int
|
||||
# 0| 0: [IntegerLiteral] 3
|
||||
# 1| 2: [ThisConstructorInvocationStmt] this(...)
|
||||
# 1| 0: [VarAccess] p0
|
||||
# 1| 1: [VarAccess] p1
|
||||
# 1| 3: [FieldDeclaration] String[] arr1;
|
||||
# 1| -1: [TypeAccess] String[]
|
||||
# 1| 0: [TypeAccess] String
|
||||
# 1| 0: [VarAccess] arr1
|
||||
# 1| 4: [Method] arr1
|
||||
#-----| -3: (Annotations)
|
||||
# 0| 1: [Annotation] Retention
|
||||
# 0| 1: [VarAccess] RetentionPolicy.RUNTIME
|
||||
# 0| -1: [TypeAccess] RetentionPolicy
|
||||
# 1| 1: [Method] arr1
|
||||
# 1| 3: [TypeAccess] String[]
|
||||
# 1| 0: [TypeAccess] String
|
||||
# 1| 5: [BlockStmt] { ... }
|
||||
# 1| 0: [ReturnStmt] return ...
|
||||
# 1| 0: [VarAccess] this.arr1
|
||||
# 1| -1: [ThisAccess] this
|
||||
# 1| 5: [Method] arr2
|
||||
# 1| 2: [Method] arr2
|
||||
# 1| 3: [TypeAccess] int[]
|
||||
# 1| 5: [BlockStmt] { ... }
|
||||
# 1| 0: [ReturnStmt] return ...
|
||||
# 1| 0: [VarAccess] this.arr2
|
||||
# 1| -1: [ThisAccess] this
|
||||
# 1| 6: [FieldDeclaration] int[] arr2;
|
||||
# 1| -1: [TypeAccess] int[]
|
||||
# 1| 0: [VarAccess] arr2
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
| exprs.kt:278:52:278:66 | <error expr> | ErrorExpr | unexpected dead end |
|
||||
| exprs.kt:278:52:278:66 | { ... } | BlockStmt | unexpected dead end |
|
||||
|
||||
@@ -35,4 +35,5 @@ MaybeElement enclosingCallable(Expr e) {
|
||||
}
|
||||
|
||||
from Expr e
|
||||
where e.getFile().isSourceFile()
|
||||
select e, enclosingCallable(e), e.getPrimaryQlClasses()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user