Skip to content

Commit 2c625e3

Browse files
authored
Merge pull request #15008 from igfoo/igfoo/kot-arr-taint
Kotlin: Track taint through Array.get/set
2 parents a09078a + 8ea155e commit 2c625e3

File tree

4 files changed

+43
-2
lines changed

4 files changed

+43
-2
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+
* Taint tracking now understands Kotlin's `Array.get` and `Array.set` methods.

java/ql/lib/semmle/code/java/dataflow/internal/ContainerFlow.qll

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ import semmle.code.java.Maps
44
private import semmle.code.java.dataflow.SSA
55
private import DataFlowUtil
66

7+
private class ArrayType extends RefType {
8+
ArrayType() { this.getSourceDeclaration().getASourceSupertype*() instanceof Array }
9+
}
10+
711
private class EntryType extends RefType {
812
EntryType() {
913
this.getSourceDeclaration().getASourceSupertype*().hasQualifiedName("java.util", "Map$Entry")
@@ -446,6 +450,14 @@ predicate arrayStoreStep(Node node1, Node node2) {
446450
exists(Assignment assign | assign.getSource() = node1.asExpr() |
447451
node2.(PostUpdateNode).getPreUpdateNode().asExpr() = assign.getDest().(ArrayAccess).getArray()
448452
)
453+
or
454+
exists(Expr arr, Call call |
455+
arr = node2.asExpr() and
456+
call.getArgument(1) = node1.asExpr() and
457+
call.getQualifier() = arr and
458+
arr.getType() instanceof ArrayType and
459+
call.getCallee().getName() = "set"
460+
)
449461
}
450462

451463
private predicate enhancedForStmtStep(Node node1, Node node2, Type containerType) {
@@ -470,6 +482,14 @@ predicate arrayReadStep(Node node1, Node node2, Type elemType) {
470482
node2.asExpr() = aa
471483
)
472484
or
485+
exists(Expr arr, Call call |
486+
arr = node1.asExpr() and
487+
call = node2.asExpr() and
488+
arr.getType() instanceof ArrayType and
489+
call.getCallee().getName() = "get" and
490+
call.getQualifier() = arr
491+
)
492+
or
473493
exists(Array arr |
474494
enhancedForStmtStep(node1, node2, arr) and
475495
arr.getComponentType() = elemType

java/ql/test-kotlin1/library-tests/dataflow/foreach/C2.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,23 @@ class C2 {
88
val l = arrayOf(taint("a"), "")
99
sink(l)
1010
sink(l[0])
11+
sink(l.get(0))
1112
for (i in l.indices) {
1213
sink(l[i])
1314
}
1415
for (s in l) {
1516
sink(s)
1617
}
1718
}
19+
20+
fun test2() {
21+
val l1 = arrayOf("")
22+
val l2 = arrayOf("")
23+
l1[0] = taint("a")
24+
l2.set(0, taint("a"))
25+
sink(l1[0])
26+
sink(l2[0])
27+
sink(l1.get(0))
28+
sink(l2.get(0))
29+
}
1830
}

java/ql/test-kotlin1/library-tests/dataflow/foreach/test.expected

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,10 @@
44
| C1.java:10:44:10:46 | "a" | C1.java:19:20:19:20 | s |
55
| C2.kt:8:32:8:32 | "a" | C2.kt:9:14:9:14 | l |
66
| C2.kt:8:32:8:32 | "a" | C2.kt:10:14:10:17 | ...[...] |
7-
| C2.kt:8:32:8:32 | "a" | C2.kt:12:18:12:21 | ...[...] |
8-
| C2.kt:8:32:8:32 | "a" | C2.kt:15:18:15:18 | s |
7+
| C2.kt:8:32:8:32 | "a" | C2.kt:11:14:11:21 | get(...) |
8+
| C2.kt:8:32:8:32 | "a" | C2.kt:13:18:13:21 | ...[...] |
9+
| C2.kt:8:32:8:32 | "a" | C2.kt:16:18:16:18 | s |
10+
| C2.kt:23:24:23:24 | "a" | C2.kt:25:14:25:18 | ...[...] |
11+
| C2.kt:23:24:23:24 | "a" | C2.kt:27:14:27:22 | get(...) |
12+
| C2.kt:24:26:24:26 | "a" | C2.kt:26:14:26:18 | ...[...] |
13+
| C2.kt:24:26:24:26 | "a" | C2.kt:28:14:28:22 | get(...) |

0 commit comments

Comments
 (0)