Skip to content

Commit 8595a36

Browse files
Kotlin: cover collection literal extraction
Add focused coverage for a collection literal resolved through a companion operator fun of. Check the call target, arguments, result type, locations, and element data flow through the resulting collection. The existing extractor handles the lowered call correctly. This commit adds coverage only and requires no extractor change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 05357c2 commit 8595a36

4 files changed

Lines changed: 54 additions & 0 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
literalCall
2+
| test.kt:14:24:14:40 | of(...) | test.kt:5:18:5:62 | of | Words | test.kt:14:24:14:40 | Companion | 2 |
3+
literalArguments
4+
| test.kt:14:24:14:40 | of(...) | 0 | test.kt:14:25:14:32 | source(...) |
5+
| test.kt:14:24:14:40 | of(...) | 1 | test.kt:14:35:14:39 | "two" |
6+
#select
7+
| test.kt:14:25:14:32 | source(...) | test.kt:15:10:15:24 | ...[...] |
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// codeql-extractor-kotlin-options: -language-version 2.4 -XXLanguage:+CollectionLiterals
2+
3+
class Words private constructor(val values: Array<out String>) {
4+
companion object {
5+
operator fun of(vararg values: String) = Words(values)
6+
}
7+
}
8+
9+
fun source(): String = ""
10+
11+
fun sink(value: String) {}
12+
13+
fun test() {
14+
val words: Words = [source(), "two"]
15+
sink(words.values[0])
16+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import java
2+
import semmle.code.java.dataflow.TaintTracking
3+
4+
query predicate literalCall(
5+
MethodCall call, Method target, string resultType, Expr qualifier, int argumentCount
6+
) {
7+
target = call.getMethod() and
8+
target.hasName("of") and
9+
call.getEnclosingCallable().fromSource() and
10+
resultType = call.getType().toString() and
11+
qualifier = call.getQualifier() and
12+
argumentCount = call.getNumArgument()
13+
}
14+
15+
query predicate literalArguments(MethodCall call, int index, Expr argument) {
16+
call.getMethod().hasName("of") and
17+
argument = call.getArgument(index)
18+
}
19+
20+
module Config implements DataFlow::ConfigSig {
21+
predicate isSource(DataFlow::Node n) { n.asExpr().(MethodCall).getMethod().hasName("source") }
22+
23+
predicate isSink(DataFlow::Node n) { n.asExpr().(Argument).getCall().getCallee().hasName("sink") }
24+
}
25+
26+
module Flow = TaintTracking::Global<Config>;
27+
28+
from DataFlow::Node source, DataFlow::Node sink
29+
where Flow::flow(source, sink)
30+
select source, sink
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
test.ql

0 commit comments

Comments
 (0)