Kotlin: Add dataflow tests for stdlib calls

This commit is contained in:
Tamas Vajk
2022-08-23 11:16:23 +02:00
parent 6d5d78e975
commit 57d861337b
6 changed files with 117 additions and 31 deletions

View File

@@ -6,4 +6,5 @@ import java
private module GeneratedFrameworks {
private import apache.IOGenerated
private import kotlin.StdLibGenerated
}

View File

@@ -0,0 +1,7 @@
/**
* THIS FILE IS AN AUTO-GENERATED MODELS AS DATA FILE. DO NOT EDIT.
* Definitions of taint steps in the StdLibGenerated framework.
*/
import java
private import semmle.code.java.dataflow.ExternalFlow

View File

@@ -4,17 +4,17 @@ class ListFlowTest {
fun test(l: MutableList<String>) {
l[0] = taint("a")
sink(l)
sink(l[0])
sink(l) // $ hasTaintFlow=a
sink(l[0]) // $ hasValueFlow=a
for (s in l) {
sink(s)
sink(s) // $ hasValueFlow=a
}
val a = arrayOf(taint("a"), "b")
sink(a)
sink(a[0])
val a = arrayOf(taint("b"), "c")
sink(a) // $ hasTaintFlow=b
sink(a[0]) // $ hasValueFlow=b
for (s in a) {
sink(s)
sink(s) // $ hasValueFlow=b
}
}
}

View File

@@ -1,6 +1,26 @@
| list.kt:6:23:6:23 | a | list.kt:7:14:7:14 | l |
| list.kt:6:23:6:23 | a | list.kt:8:14:8:17 | get(...) |
| list.kt:6:23:6:23 | a | list.kt:10:18:10:18 | s |
| list.kt:13:32:13:32 | a | list.kt:14:14:14:14 | a |
| list.kt:13:32:13:32 | a | list.kt:15:14:15:17 | ...[...] |
| list.kt:13:32:13:32 | a | list.kt:17:18:17:18 | s |
| test.kt:16:53:16:69 | // $ hasTaintFlow | Missing result:hasTaintFlow= |
| test.kt:17:53:17:69 | // $ hasTaintFlow | Missing result:hasTaintFlow= |
| test.kt:20:53:20:69 | // $ hasTaintFlow | Missing result:hasTaintFlow= |
| test.kt:21:53:21:69 | // $ hasTaintFlow | Missing result:hasTaintFlow= |
| test.kt:23:53:23:69 | // $ hasTaintFlow | Missing result:hasTaintFlow= |
| test.kt:26:53:26:71 | // $ hasTaintFlow=a | Missing result:hasTaintFlow=a |
| test.kt:27:53:27:71 | // $ hasTaintFlow=a | Missing result:hasTaintFlow=a |
| test.kt:30:57:30:75 | // $ hasTaintFlow=b | Missing result:hasTaintFlow=b |
| test.kt:31:57:31:75 | // $ hasTaintFlow=c | Missing result:hasTaintFlow=c |
| test.kt:34:53:34:71 | // $ hasTaintFlow=d | Missing result:hasTaintFlow=d |
| test.kt:36:53:36:71 | // $ hasTaintFlow=d | Missing result:hasTaintFlow=d |
| test.kt:39:53:39:71 | // $ hasTaintFlow=e | Missing result:hasTaintFlow=e |
| test.kt:40:53:40:71 | // $ hasTaintFlow=e | Missing result:hasTaintFlow=e |
| test.kt:44:53:44:71 | // $ hasTaintFlow=a | Missing result:hasTaintFlow=a |
| test.kt:45:53:45:71 | // $ hasTaintFlow=a | Missing result:hasTaintFlow=a |
| test.kt:47:53:47:71 | // $ hasTaintFlow=a | Missing result:hasTaintFlow=a |
| test.kt:51:53:51:71 | // $ hasTaintFlow=f | Missing result:hasTaintFlow=f |
| test.kt:52:53:52:71 | // $ hasTaintFlow=f | Missing result:hasTaintFlow=f |
| test.kt:56:53:56:71 | // $ hasTaintFlow=g | Missing result:hasTaintFlow=g |
| test.kt:57:53:57:71 | // $ hasTaintFlow=g | Missing result:hasTaintFlow=g |
| test.kt:61:53:61:71 | // $ hasTaintFlow=h | Missing result:hasTaintFlow=h |
| test.kt:63:53:63:71 | // $ hasTaintFlow=h | Missing result:hasTaintFlow=h |
| test.kt:66:53:66:71 | // $ hasTaintFlow=i | Missing result:hasTaintFlow=i |
| test.kt:67:53:67:71 | // $ hasTaintFlow=i | Missing result:hasTaintFlow=i |
| test.kt:68:53:68:71 | // $ hasTaintFlow=i | Missing result:hasTaintFlow=i |
| test.kt:71:53:71:71 | // $ hasTaintFlow=i | Missing result:hasTaintFlow=i |

View File

@@ -0,0 +1,75 @@
import kotlin.time.Duration
import kotlin.time.ExperimentalTime
import kotlin.time.TimedValue
class Test {
fun <T> taint(t: T) = t
fun sink(a: Any) {}
@OptIn(ExperimentalTime::class)
fun test(b: ByteArray,
f: kotlin.io.FileTreeWalk,
c1: CharArray,
c2: CharArray,
c3: CharArray,) {
sink(taint(b).copyOf()) // $ hasTaintFlow
sink(taint(f).maxDepth(1)) // $ hasTaintFlow
val sb = StringBuilder()
sink(sb.insertRange(0, taint(c1), 0, 0)) // $ hasTaintFlow
sink(sb) // $ hasTaintFlow
sink(taint(c2) + c3) // $ hasTaintFlow
val p = Pair(taint("a"), "")
sink(p) // $ hasTaintFlow=a
sink(p.component1()) // $ hasTaintFlow=a
sink(p.second)
sink(taint("b").capitalize()) // $ hasTaintFlow=b
sink(taint("c").replaceFirstChar { _ -> 'x' }) // $ hasTaintFlow=c
val t = Triple("", taint("d"), "")
sink(t) // $ hasTaintFlow=d
sink(t.component1())
sink(t.second) // $ hasTaintFlow=d
val p1 = taint("e") to ""
sink(p1) // $ hasTaintFlow=e
sink(p1.component1()) // $ hasTaintFlow=e
sink(p1.second)
val l = p.toList()
sink(l) // $ hasTaintFlow=a
sink(l[0]) // $ hasTaintFlow=a
for (s in l) {
sink(s) // $ hasTaintFlow=a
}
val tv = TimedValue(taint("f"), Duration.parse(""))
sink(tv) // $ hasTaintFlow=f
sink(tv.component1()) // $ hasTaintFlow=f
sink(tv.duration)
val mg0 = MatchGroup(taint("g"), IntRange(0, 10))
sink(mg0) // $ hasTaintFlow=g
sink(mg0.value) // $ hasTaintFlow=g
sink(mg0.component2())
val iv = IndexedValue<String>(5, taint("h"))
sink(iv) // $ hasTaintFlow=h
sink(iv.index)
sink(iv.component2()) // $ hasTaintFlow=h
val strings = arrayOf("", taint("i"))
sink(strings.withIndex()) // $ hasTaintFlow=i
sink(strings.withIndex().toList()) // $ hasTaintFlow=i
sink(strings.withIndex().toList()[0].value) // $ hasTaintFlow=i
sink(strings.withIndex().toList()[0].index)
for (x in strings.withIndex()) {
sink(x.value) // $ hasTaintFlow=i
sink(x.index)
}
}
}

View File

@@ -1,19 +1,2 @@
import java
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.ExternalFlow
class Conf extends TaintTracking::Configuration {
Conf() { this = "qltest:mad-summaries" }
override predicate isSource(DataFlow::Node n) {
n.asExpr().(Argument).getCall().getCallee().hasName("taint")
}
override predicate isSink(DataFlow::Node n) {
n.asExpr().(Argument).getCall().getCallee().hasName("sink")
}
}
from DataFlow::Node src, DataFlow::Node sink, Conf conf
where conf.hasFlow(src, sink)
select src, sink
import TestUtilities.InlineFlowTest