From af2614be84028173761dd5dc3342a7059082a5ba Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Thu, 25 Aug 2022 09:17:50 +0200 Subject: [PATCH 1/3] Kotlin: Add array iterator tests --- .../library-tests/arrays/arrayIterators.expected | 6 ++++++ .../kotlin/library-tests/arrays/arrayIterators.kt | 13 +++++++++++++ .../kotlin/library-tests/arrays/arrayIterators.ql | 10 ++++++++++ .../test/kotlin/library-tests/arrays/test.expected | 1 + 4 files changed, 30 insertions(+) create mode 100644 java/ql/test/kotlin/library-tests/arrays/arrayIterators.expected create mode 100644 java/ql/test/kotlin/library-tests/arrays/arrayIterators.kt create mode 100644 java/ql/test/kotlin/library-tests/arrays/arrayIterators.ql diff --git a/java/ql/test/kotlin/library-tests/arrays/arrayIterators.expected b/java/ql/test/kotlin/library-tests/arrays/arrayIterators.expected new file mode 100644 index 000000000000..8617bba3a39f --- /dev/null +++ b/java/ql/test/kotlin/library-tests/arrays/arrayIterators.expected @@ -0,0 +1,6 @@ +| arrayIterators.kt:6:15:6:15 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt | +| arrayIterators.kt:7:15:7:15 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt | +| arrayIterators.kt:8:15:8:15 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt | +| arrayIterators.kt:10:16:10:25 | iterator(...) | iterator() | kotlin.Array | +| arrayIterators.kt:11:16:11:25 | iterator(...) | iterator() | kotlin.IntArray | +| arrayIterators.kt:12:16:12:25 | iterator(...) | iterator() | kotlin.BooleanArray | diff --git a/java/ql/test/kotlin/library-tests/arrays/arrayIterators.kt b/java/ql/test/kotlin/library-tests/arrays/arrayIterators.kt new file mode 100644 index 000000000000..45a49b800972 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/arrays/arrayIterators.kt @@ -0,0 +1,13 @@ +fun test( + a: Array, + b: IntArray, + c: BooleanArray) { + + for (i in a) { } + for (i in b) { } + for (i in c) { } + + val i1 = a.iterator() + val i2 = b.iterator() + val i3 = c.iterator() +} diff --git a/java/ql/test/kotlin/library-tests/arrays/arrayIterators.ql b/java/ql/test/kotlin/library-tests/arrays/arrayIterators.ql new file mode 100644 index 000000000000..442e454424ab --- /dev/null +++ b/java/ql/test/kotlin/library-tests/arrays/arrayIterators.ql @@ -0,0 +1,10 @@ +import java + +query predicate iterator(MethodAccess ma, string mn, string t) { + exists(Method m | + ma.getMethod() = m and + m.getName() = "iterator" and + mn = m.getSignature() and + t = ma.getMethod().getDeclaringType().getQualifiedName() + ) +} diff --git a/java/ql/test/kotlin/library-tests/arrays/test.expected b/java/ql/test/kotlin/library-tests/arrays/test.expected index 8ef00e41d6f8..7693b3acd6b3 100644 --- a/java/ql/test/kotlin/library-tests/arrays/test.expected +++ b/java/ql/test/kotlin/library-tests/arrays/test.expected @@ -18,6 +18,7 @@ sourceSignatures | arrayCreations.kt:27:24:27:38 | invoke | invoke(int) | | arrayGetsSets.kt:1:1:22:1 | arrayGetSet | arrayGetSet(int[],short[],byte[],long[],float[],double[],boolean[],char[],java.lang.Object[]) | | arrayGetsSets.kt:24:1:41:1 | arrayGetSetInPlace | arrayGetSetInPlace(int[],long[],float[],double[]) | +| arrayIterators.kt:1:1:13:1 | test | test(java.lang.Integer[],int[],boolean[]) | | primitiveArrays.kt:3:1:7:1 | Test | Test() | | primitiveArrays.kt:5:3:5:123 | test | test(java.lang.Integer[],java.lang.Integer[],int[],java.lang.Integer[][],java.lang.Integer[][],int[][]) | #select From 7196fdd4753266a0fcd8b9d0f8c72f9cb41aa74a Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Thu, 25 Aug 2022 09:23:31 +0200 Subject: [PATCH 2/3] Kotlin: fix array iterator extraction to work outside of `for` loops --- .../kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt | 2 +- .../kotlin/library-tests/arrays/arrayIterators.expected | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index f7932c7327f2..7e297c68feb4 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -2177,7 +2177,7 @@ open class KotlinFileExtractor( extractRawMethodAccess(getter, c, callable, parent, idx, enclosingStmt, listOf(), null, ext, typeArguments) } } - isFunction(target, "kotlin", "(some array type)", { isArrayType(it) }, "iterator") && c.origin == IrStatementOrigin.FOR_LOOP_ITERATOR -> { + isFunction(target, "kotlin", "(some array type)", { isArrayType(it) }, "iterator") -> { findTopLevelFunctionOrWarn("kotlin.jvm.internal.iterator", "kotlin.jvm.internal.ArrayIteratorKt", c)?.let { iteratorFn -> val dispatchReceiver = c.dispatchReceiver if (dispatchReceiver == null) { diff --git a/java/ql/test/kotlin/library-tests/arrays/arrayIterators.expected b/java/ql/test/kotlin/library-tests/arrays/arrayIterators.expected index 8617bba3a39f..56127db1d7d5 100644 --- a/java/ql/test/kotlin/library-tests/arrays/arrayIterators.expected +++ b/java/ql/test/kotlin/library-tests/arrays/arrayIterators.expected @@ -1,6 +1,6 @@ | arrayIterators.kt:6:15:6:15 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt | | arrayIterators.kt:7:15:7:15 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt | | arrayIterators.kt:8:15:8:15 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt | -| arrayIterators.kt:10:16:10:25 | iterator(...) | iterator() | kotlin.Array | -| arrayIterators.kt:11:16:11:25 | iterator(...) | iterator() | kotlin.IntArray | -| arrayIterators.kt:12:16:12:25 | iterator(...) | iterator() | kotlin.BooleanArray | +| arrayIterators.kt:10:16:10:25 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt | +| arrayIterators.kt:11:16:11:25 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt | +| arrayIterators.kt:12:16:12:25 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt | From 15305fd9bbf0c1b534666c967ef56b536ec7c768 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Thu, 25 Aug 2022 11:05:13 +0200 Subject: [PATCH 3/3] Kotlin: Fix iterator extraction of `IntArray`, `BooleanArray`, ... --- .../src/main/kotlin/KotlinFileExtractor.kt | 28 ++++++++++++++++--- .../arrays/arrayIterators.expected | 8 +++--- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 7e297c68feb4..1c15e70fe50b 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -1600,11 +1600,13 @@ open class KotlinFileExtractor( return result } - private fun findTopLevelFunctionOrWarn(functionFilter: String, type: String, warnAgainstElement: IrElement): IrFunction? { + private fun findTopLevelFunctionOrWarn(functionFilter: String, type: String, parameterTypes: Array, warnAgainstElement: IrElement): IrFunction? { val fn = pluginContext.referenceFunctions(FqName(functionFilter)) - .firstOrNull { it.owner.parentClassOrNull?.fqNameWhenAvailable?.asString() == type } - ?.owner + .firstOrNull { fnSymbol -> + fnSymbol.owner.parentClassOrNull?.fqNameWhenAvailable?.asString() == type && + fnSymbol.owner.valueParameters.map { it.type.classFqName?.asString() }.toTypedArray() contentEquals parameterTypes + }?.owner if (fn != null) { if (fn.parentClassOrNull != null) { @@ -1756,6 +1758,12 @@ open class KotlinFileExtractor( else -> false } + private fun isGenericArrayType(typeName: String) = + when(typeName) { + "Array" -> true + else -> false + } + private fun extractCall(c: IrCall, callable: Label, stmtExprParent: StmtExprParent) { with("call", c) { val target = tryReplaceSyntheticFunction(c.symbol.owner) @@ -2178,7 +2186,19 @@ open class KotlinFileExtractor( } } isFunction(target, "kotlin", "(some array type)", { isArrayType(it) }, "iterator") -> { - findTopLevelFunctionOrWarn("kotlin.jvm.internal.iterator", "kotlin.jvm.internal.ArrayIteratorKt", c)?.let { iteratorFn -> + val parentClass = target.parent + if (parentClass !is IrClass) { + logger.errorElement("Iterator parent is not a class", c) + return + } + + var typeFilter = if (isGenericArrayType(parentClass.name.asString())) { + "kotlin.jvm.internal.ArrayIteratorKt" + } else { + "kotlin.jvm.internal.ArrayIteratorsKt" + } + + findTopLevelFunctionOrWarn("kotlin.jvm.internal.iterator", typeFilter, arrayOf(parentClass.kotlinFqName.asString()), c)?.let { iteratorFn -> val dispatchReceiver = c.dispatchReceiver if (dispatchReceiver == null) { logger.errorElement("No dispatch receiver found for array iterator call", c) diff --git a/java/ql/test/kotlin/library-tests/arrays/arrayIterators.expected b/java/ql/test/kotlin/library-tests/arrays/arrayIterators.expected index 56127db1d7d5..cd1884eb00e8 100644 --- a/java/ql/test/kotlin/library-tests/arrays/arrayIterators.expected +++ b/java/ql/test/kotlin/library-tests/arrays/arrayIterators.expected @@ -1,6 +1,6 @@ | arrayIterators.kt:6:15:6:15 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt | -| arrayIterators.kt:7:15:7:15 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt | -| arrayIterators.kt:8:15:8:15 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt | +| arrayIterators.kt:7:15:7:15 | iterator(...) | iterator(int[]) | kotlin.jvm.internal.ArrayIteratorsKt | +| arrayIterators.kt:8:15:8:15 | iterator(...) | iterator(boolean[]) | kotlin.jvm.internal.ArrayIteratorsKt | | arrayIterators.kt:10:16:10:25 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt | -| arrayIterators.kt:11:16:11:25 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt | -| arrayIterators.kt:12:16:12:25 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt | +| arrayIterators.kt:11:16:11:25 | iterator(...) | iterator(int[]) | kotlin.jvm.internal.ArrayIteratorsKt | +| arrayIterators.kt:12:16:12:25 | iterator(...) | iterator(boolean[]) | kotlin.jvm.internal.ArrayIteratorsKt |