Kotlin: Add a Kotlin 2 copy of the testsuite

This commit is contained in:
Ian Lynagh
2023-10-26 13:13:28 +01:00
parent e6f31c965e
commit 905583e00a
625 changed files with 32808 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
import kotlinx.coroutines.*
suspend fun fn() {
GlobalScope.launch {
val x: Deferred<String> = async { Helper.taint() }
Helper.sink(x.await()) // TODO: not found
}
}

View File

@@ -0,0 +1,22 @@
class FunctionReference {
fun fn1(s: String) = s
suspend fun test() {
fun fn2(s: String) = s
Helper.sink(Processor().process(this::fn1, Helper.taint()))
Helper.sink(Processor().processSusp(this::fn1Susp, Helper.taint()))
Helper.sink(Processor().process(FunctionReference::fn1, this, Helper.taint()))
Helper.sink(Processor().process(this::fn1, Helper.notaint()))
Helper.sink(Processor().process(::fn2, Helper.taint()))
Helper.sink(Processor().process(::fn2, Helper.notaint()))
Helper.sink(Processor().process(this::prop))
}
val prop: String
get() = Helper.taint()
suspend fun fn1Susp(s: String) = s
}

View File

@@ -0,0 +1,35 @@
/**
* Stubs for `kotlinx.coroutines`
*/
@file:JvmName("BuildersKt") // Required for `async`
package kotlinx.coroutines
public interface CoroutineScope
public interface CoroutineContext
public enum class CoroutineStart { DEFAULT }
public interface Job
public interface Deferred<out T> : Job {
public suspend fun await(): T
}
public object GlobalScope : CoroutineScope
public fun CoroutineScope.launch(
context: CoroutineContext = null!!,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job {
return null!!
}
public fun <T> CoroutineScope.async(
context: CoroutineContext = null!!,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T
): Deferred<T> {
return null!!
}
// Diagnostic Matches: % Couldn't get owner of KDoc. The comment is extracted without an owner. ...while extracting a file (kotlinx_coroutines_stubs.kt) at %kotlinx_coroutines_stubs.kt:1:1:36:0%

View File

@@ -0,0 +1,33 @@
class Lambda {
suspend fun test() {
Helper.sink(Processor().process({ it: String -> Helper.notaint() }, ""))
Helper.sink(Processor().process({ it: String -> Helper.taint() }, ""))
Helper.sink(Processor().processSusp({ it: String -> Helper.taint() }, ""))
Helper.sink(Processor().process({ i -> i }, Helper.taint()))
Helper.sink(Processor().process(fun (i: String) = i, Helper.taint()))
Helper.sink(Processor().processExt({ i -> i }, Helper.taint(), Helper.notaint()))
Helper.sink(Processor().processExt({ i -> i }, Helper.notaint(), Helper.taint()))
Helper.sink(Processor().processExt({ i -> this }, Helper.taint(), Helper.notaint()))
Helper.sink(Processor().processExt({ i -> this }, Helper.notaint(), Helper.taint()))
Helper.sink(Processor().process({ i0,i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15,i16,i17,i18,i19,i20,i21,i22,i23 -> i0 }, Helper.taint(), Helper.notaint()))
Helper.sink(Processor().process({ i0,i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15,i16,i17,i18,i19,i20,i21,i22,i23 -> i0 }, Helper.notaint(), Helper.taint())) // False positive
}
}
class ManualBigLambda {
fun invoke(s0: String, s1: String): String {
return s0
}
fun invoke(a: Array<Any?>): String {
return invoke(a[0] as String, a[1] as String)
}
fun call() {
Helper.sink(invoke(Helper.taint(), Helper.notaint()))
Helper.sink(invoke(Helper.notaint(), Helper.taint()))
Helper.sink(invoke(arrayOf(Helper.taint(), Helper.notaint())))
Helper.sink(invoke(arrayOf(Helper.notaint(), Helper.taint()))) // False positive
}
}

View File

@@ -0,0 +1,15 @@
class LocalFunction {
suspend fun test() {
fun fn1() = Helper.taint()
fun fn2(s: String) = s
Helper.sink(fn1())
Helper.sink(fn2(Helper.taint()))
suspend fun fn3() = Helper.taint()
suspend fun fn4(s: String) = s
Helper.sink(fn3())
Helper.sink(fn4(Helper.taint()))
}
}

View File

@@ -0,0 +1,23 @@
fun interface Predicate {
fun go(s: String): String
}
fun interface PredicateSusp {
suspend fun go(s: String): String
}
class SamConversion {
suspend fun test() {
val p1 = Predicate { Helper.taint() }
val p2 = Predicate { it -> it }
Helper.sink(p1.go(""))
Helper.sink(p2.go(Helper.taint()))
val p3 = PredicateSusp { Helper.taint() }
val p4 = PredicateSusp { it -> it }
Helper.sink(p3.go(""))
Helper.sink(p4.go(Helper.taint()))
}
}

View File

@@ -0,0 +1,22 @@
| functionReference.kt:8:52:8:65 | taint(...) | functionReference.kt:8:21:8:66 | process(...) |
| functionReference.kt:10:71:10:84 | taint(...) | functionReference.kt:10:21:10:85 | process(...) |
| functionReference.kt:12:48:12:61 | taint(...) | functionReference.kt:12:21:12:62 | process(...) |
| functionReference.kt:19:17:19:30 | taint(...) | functionReference.kt:15:21:15:51 | process(...) |
| lambda.kt:4:57:4:70 | taint(...) | lambda.kt:4:21:4:77 | process(...) |
| lambda.kt:6:53:6:66 | taint(...) | lambda.kt:6:21:6:67 | process(...) |
| lambda.kt:7:62:7:75 | taint(...) | lambda.kt:7:21:7:76 | process(...) |
| lambda.kt:10:74:10:87 | taint(...) | lambda.kt:10:21:10:88 | processExt(...) |
| lambda.kt:11:59:11:72 | taint(...) | lambda.kt:11:21:11:91 | processExt(...) |
| lambda.kt:14:138:14:151 | taint(...) | lambda.kt:14:21:14:170 | process(...) |
| lambda.kt:15:156:15:169 | taint(...) | lambda.kt:15:21:15:170 | process(...) |
| lambda.kt:28:28:28:41 | taint(...) | lambda.kt:28:21:28:60 | invoke(...) |
| lambda.kt:30:36:30:49 | taint(...) | lambda.kt:30:21:30:69 | invoke(...) |
| lambda.kt:31:54:31:67 | taint(...) | lambda.kt:31:21:31:69 | invoke(...) |
| localFunction.kt:3:21:3:34 | taint(...) | localFunction.kt:6:21:6:25 | fn1(...) |
| localFunction.kt:7:25:7:38 | taint(...) | localFunction.kt:7:21:7:39 | fn2(...) |
| localFunction.kt:9:29:9:42 | taint(...) | localFunction.kt:12:21:12:25 | fn3(...) |
| localFunction.kt:13:25:13:38 | taint(...) | localFunction.kt:13:21:13:39 | fn4(...) |
| samConversion.kt:11:30:11:43 | taint(...) | samConversion.kt:14:21:14:29 | go(...) |
| samConversion.kt:15:27:15:40 | taint(...) | samConversion.kt:15:21:15:41 | go(...) |
| samConversion.kt:17:34:17:47 | taint(...) | samConversion.kt:20:21:20:29 | go(...) |
| samConversion.kt:21:27:21:40 | taint(...) | samConversion.kt:21:21:21:41 | go(...) |

View File

@@ -0,0 +1,14 @@
import java
import semmle.code.java.dataflow.TaintTracking
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node n) { n.asExpr().(MethodCall).getMethod().hasName("taint") }
predicate isSink(DataFlow::Node n) { n.asExpr().(Argument).getCall().getCallee().hasName("sink") }
}
module Flow = TaintTracking::Global<Config>;
from DataFlow::Node src, DataFlow::Node sink
where Flow::flow(src, sink)
select src, sink

View File

@@ -0,0 +1,35 @@
class Processor {
fun <R1> process(f: () -> R1) : R1 {
return f()
}
fun <T, R2> process(f: (T) -> R2, arg: T) : R2 {
return f(arg)
}
suspend fun <T, R2> processSusp(f: suspend (T) -> R2, arg: T) : R2 {
return f(arg)
}
fun <T0, T1, R3> process(f: (T0, T1) -> R3, arg0: T0, arg1: T1) : R3 {
return f(arg0, arg1)
}
fun <T, R4> process(
f: (T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T) -> R4,
a: T, b: T) : R4 {
return f(a,b,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a)
}
fun <T, R5> processExt(f: T.(T) -> R5, ext: T, arg: T) : R5 {
return ext.f(arg)
}
}
class Helper {
companion object {
fun taint(): String = "taint"
fun notaint(): String = "notaint"
fun sink(a: Any?) { }
}
}