Skip to content

Commit 3410dd5

Browse files
authored
Merge pull request #9783 from tamasvajk/feature/kotlin-stdlib-mad
Kotlin: Add MaD for stdlib
2 parents 5c37430 + 7daf53f commit 3410dd5

File tree

12 files changed

+6406
-50
lines changed

12 files changed

+6406
-50
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Added flow sinks, sources and summaries for the Kotlin standard library.

java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ private module Frameworks {
153153
private import semmle.code.java.frameworks.JMS
154154
private import semmle.code.java.frameworks.RabbitMQ
155155
private import semmle.code.java.regex.RegexFlowModels
156-
private import semmle.code.java.frameworks.KotlinStdLib
156+
private import semmle.code.java.frameworks.kotlin.StdLib
157157
}
158158

159159
/**

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

Lines changed: 0 additions & 11 deletions
This file was deleted.

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
}

java/ql/lib/semmle/code/java/frameworks/kotlin/NegativeStdLibGenerated.qll

Lines changed: 4414 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/** Definitions of taint steps in the KotlinStdLib framework */
2+
3+
import java
4+
private import semmle.code.java.dataflow.ExternalFlow
5+
6+
private class KotlinStdLibSummaryCsv extends SummaryModelCsv {
7+
override predicate row(string row) {
8+
row =
9+
[
10+
"kotlin.jvm.internal;ArrayIteratorKt;false;iterator;(Object[]);;Argument[0].ArrayElement;ReturnValue.Element;value;manual",
11+
"kotlin.collections;ArraysKt;false;withIndex;(Object[]);;Argument[0].ArrayElement;ReturnValue;taint;manual"
12+
]
13+
}
14+
}

java/ql/lib/semmle/code/java/frameworks/kotlin/StdLibGenerated.qll

Lines changed: 1868 additions & 0 deletions
Large diffs are not rendered by default.

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: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
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:28:16:28:21 | getSecond(...) | Unexpected result: hasTaintFlow=a |
2+
| test.kt:35:16:35:27 | component1(...) | Unexpected result: hasTaintFlow=d |
3+
| test.kt:41:17:41:22 | getSecond(...) | Unexpected result: hasTaintFlow=e |
4+
| test.kt:53:17:53:24 | getDuration(...) | Unexpected result: hasTaintFlow=f |
5+
| test.kt:58:18:58:29 | component2(...) | Unexpected result: hasTaintFlow=g |
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+
}

0 commit comments

Comments
 (0)