Skip to content

Commit 57d8613

Browse files
committed
Kotlin: Add dataflow tests for stdlib calls
1 parent 6d5d78e commit 57d8613

File tree

6 files changed

+117
-31
lines changed

6 files changed

+117
-31
lines changed

java/ql/lib/semmle/code/java/frameworks/generated.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ import java
66

77
private module GeneratedFrameworks {
88
private import apache.IOGenerated
9+
private import kotlin.StdLibGenerated
910
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/**
2+
* THIS FILE IS AN AUTO-GENERATED MODELS AS DATA FILE. DO NOT EDIT.
3+
* Definitions of taint steps in the StdLibGenerated framework.
4+
*/
5+
6+
import java
7+
private import semmle.code.java.dataflow.ExternalFlow

java/ql/test/kotlin/library-tests/dataflow/summaries/list.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@ class ListFlowTest {
44

55
fun test(l: MutableList<String>) {
66
l[0] = taint("a")
7-
sink(l)
8-
sink(l[0])
7+
sink(l) // $ hasTaintFlow=a
8+
sink(l[0]) // $ hasValueFlow=a
99
for (s in l) {
10-
sink(s)
10+
sink(s) // $ hasValueFlow=a
1111
}
1212

13-
val a = arrayOf(taint("a"), "b")
14-
sink(a)
15-
sink(a[0])
13+
val a = arrayOf(taint("b"), "c")
14+
sink(a) // $ hasTaintFlow=b
15+
sink(a[0]) // $ hasValueFlow=b
1616
for (s in a) {
17-
sink(s)
17+
sink(s) // $ hasValueFlow=b
1818
}
1919
}
2020
}
Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,26 @@
1-
| list.kt:6:23:6:23 | a | list.kt:7:14:7:14 | l |
2-
| list.kt:6:23:6:23 | a | list.kt:8:14:8:17 | get(...) |
3-
| list.kt:6:23:6:23 | a | list.kt:10:18:10:18 | s |
4-
| list.kt:13:32:13:32 | a | list.kt:14:14:14:14 | a |
5-
| list.kt:13:32:13:32 | a | list.kt:15:14:15:17 | ...[...] |
6-
| list.kt:13:32:13:32 | a | list.kt:17:18:17:18 | s |
1+
| test.kt:16:53:16:69 | // $ hasTaintFlow | Missing result:hasTaintFlow= |
2+
| test.kt:17:53:17:69 | // $ hasTaintFlow | Missing result:hasTaintFlow= |
3+
| test.kt:20:53:20:69 | // $ hasTaintFlow | Missing result:hasTaintFlow= |
4+
| test.kt:21:53:21:69 | // $ hasTaintFlow | Missing result:hasTaintFlow= |
5+
| test.kt:23:53:23:69 | // $ hasTaintFlow | Missing result:hasTaintFlow= |
6+
| test.kt:26:53:26:71 | // $ hasTaintFlow=a | Missing result:hasTaintFlow=a |
7+
| test.kt:27:53:27:71 | // $ hasTaintFlow=a | Missing result:hasTaintFlow=a |
8+
| test.kt:30:57:30:75 | // $ hasTaintFlow=b | Missing result:hasTaintFlow=b |
9+
| test.kt:31:57:31:75 | // $ hasTaintFlow=c | Missing result:hasTaintFlow=c |
10+
| test.kt:34:53:34:71 | // $ hasTaintFlow=d | Missing result:hasTaintFlow=d |
11+
| test.kt:36:53:36:71 | // $ hasTaintFlow=d | Missing result:hasTaintFlow=d |
12+
| test.kt:39:53:39:71 | // $ hasTaintFlow=e | Missing result:hasTaintFlow=e |
13+
| test.kt:40:53:40:71 | // $ hasTaintFlow=e | Missing result:hasTaintFlow=e |
14+
| test.kt:44:53:44:71 | // $ hasTaintFlow=a | Missing result:hasTaintFlow=a |
15+
| test.kt:45:53:45:71 | // $ hasTaintFlow=a | Missing result:hasTaintFlow=a |
16+
| test.kt:47:53:47:71 | // $ hasTaintFlow=a | Missing result:hasTaintFlow=a |
17+
| test.kt:51:53:51:71 | // $ hasTaintFlow=f | Missing result:hasTaintFlow=f |
18+
| test.kt:52:53:52:71 | // $ hasTaintFlow=f | Missing result:hasTaintFlow=f |
19+
| test.kt:56:53:56:71 | // $ hasTaintFlow=g | Missing result:hasTaintFlow=g |
20+
| test.kt:57:53:57:71 | // $ hasTaintFlow=g | Missing result:hasTaintFlow=g |
21+
| test.kt:61:53:61:71 | // $ hasTaintFlow=h | Missing result:hasTaintFlow=h |
22+
| test.kt:63:53:63:71 | // $ hasTaintFlow=h | Missing result:hasTaintFlow=h |
23+
| test.kt:66:53:66:71 | // $ hasTaintFlow=i | Missing result:hasTaintFlow=i |
24+
| test.kt:67:53:67:71 | // $ hasTaintFlow=i | Missing result:hasTaintFlow=i |
25+
| test.kt:68:53:68:71 | // $ hasTaintFlow=i | Missing result:hasTaintFlow=i |
26+
| test.kt:71:53:71:71 | // $ hasTaintFlow=i | Missing result:hasTaintFlow=i |
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import kotlin.time.Duration
2+
import kotlin.time.ExperimentalTime
3+
import kotlin.time.TimedValue
4+
5+
class Test {
6+
fun <T> taint(t: T) = t
7+
fun sink(a: Any) {}
8+
9+
@OptIn(ExperimentalTime::class)
10+
fun test(b: ByteArray,
11+
f: kotlin.io.FileTreeWalk,
12+
c1: CharArray,
13+
c2: CharArray,
14+
c3: CharArray,) {
15+
16+
sink(taint(b).copyOf()) // $ hasTaintFlow
17+
sink(taint(f).maxDepth(1)) // $ hasTaintFlow
18+
19+
val sb = StringBuilder()
20+
sink(sb.insertRange(0, taint(c1), 0, 0)) // $ hasTaintFlow
21+
sink(sb) // $ hasTaintFlow
22+
23+
sink(taint(c2) + c3) // $ hasTaintFlow
24+
25+
val p = Pair(taint("a"), "")
26+
sink(p) // $ hasTaintFlow=a
27+
sink(p.component1()) // $ hasTaintFlow=a
28+
sink(p.second)
29+
30+
sink(taint("b").capitalize()) // $ hasTaintFlow=b
31+
sink(taint("c").replaceFirstChar { _ -> 'x' }) // $ hasTaintFlow=c
32+
33+
val t = Triple("", taint("d"), "")
34+
sink(t) // $ hasTaintFlow=d
35+
sink(t.component1())
36+
sink(t.second) // $ hasTaintFlow=d
37+
38+
val p1 = taint("e") to ""
39+
sink(p1) // $ hasTaintFlow=e
40+
sink(p1.component1()) // $ hasTaintFlow=e
41+
sink(p1.second)
42+
43+
val l = p.toList()
44+
sink(l) // $ hasTaintFlow=a
45+
sink(l[0]) // $ hasTaintFlow=a
46+
for (s in l) {
47+
sink(s) // $ hasTaintFlow=a
48+
}
49+
50+
val tv = TimedValue(taint("f"), Duration.parse(""))
51+
sink(tv) // $ hasTaintFlow=f
52+
sink(tv.component1()) // $ hasTaintFlow=f
53+
sink(tv.duration)
54+
55+
val mg0 = MatchGroup(taint("g"), IntRange(0, 10))
56+
sink(mg0) // $ hasTaintFlow=g
57+
sink(mg0.value) // $ hasTaintFlow=g
58+
sink(mg0.component2())
59+
60+
val iv = IndexedValue<String>(5, taint("h"))
61+
sink(iv) // $ hasTaintFlow=h
62+
sink(iv.index)
63+
sink(iv.component2()) // $ hasTaintFlow=h
64+
65+
val strings = arrayOf("", taint("i"))
66+
sink(strings.withIndex()) // $ hasTaintFlow=i
67+
sink(strings.withIndex().toList()) // $ hasTaintFlow=i
68+
sink(strings.withIndex().toList()[0].value) // $ hasTaintFlow=i
69+
sink(strings.withIndex().toList()[0].index)
70+
for (x in strings.withIndex()) {
71+
sink(x.value) // $ hasTaintFlow=i
72+
sink(x.index)
73+
}
74+
}
75+
}
Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,2 @@
11
import java
2-
import semmle.code.java.dataflow.TaintTracking
3-
import semmle.code.java.dataflow.ExternalFlow
4-
5-
class Conf extends TaintTracking::Configuration {
6-
Conf() { this = "qltest:mad-summaries" }
7-
8-
override predicate isSource(DataFlow::Node n) {
9-
n.asExpr().(Argument).getCall().getCallee().hasName("taint")
10-
}
11-
12-
override predicate isSink(DataFlow::Node n) {
13-
n.asExpr().(Argument).getCall().getCallee().hasName("sink")
14-
}
15-
}
16-
17-
from DataFlow::Node src, DataFlow::Node sink, Conf conf
18-
where conf.hasFlow(src, sink)
19-
select src, sink
2+
import TestUtilities.InlineFlowTest

0 commit comments

Comments
 (0)