Skip to content

Commit b9116f3

Browse files
Kotlin: test companion extension extraction
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 7d65a2e commit b9116f3

4 files changed

Lines changed: 76 additions & 0 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
declarations
2+
| test.kt:5:9:5:29 | empty | test.kt:3:1:7:1 | Box | Method | empty() |
3+
| test.kt:9:11:9:52 | create | test.kt:0:0:0:0 | TestKt | Method | create(java.lang.String) |
4+
| test.kt:12:5:12:19 | getDefault | test.kt:0:0:0:0 | TestKt | Method | getDefault() |
5+
calls
6+
| test.kt:19:14:19:29 | create(...) | test.kt:18:1:21:1 | test | test.kt:9:11:9:52 | create | test.kt:19:14:19:29 | TestKt |
7+
| test.kt:20:14:20:20 | getDefault(...) | test.kt:18:1:21:1 | test | test.kt:12:5:12:19 | getDefault | test.kt:20:14:20:20 | TestKt |
8+
properties
9+
| test.kt:11:11:12:19 | default | test.kt:0:0:0:0 | TestKt | test.kt:12:5:12:19 | getDefault |
10+
#select
11+
| test.kt:19:21:19:28 | source(...) | test.kt:19:14:19:35 | getValue(...) |
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// codeql-extractor-kotlin-options: -language-version 2.4 -Xcompanion-blocks-and-extensions
2+
3+
class Box(val value: String) {
4+
companion {
5+
fun empty() = Box("")
6+
}
7+
}
8+
9+
companion fun Box.create(value: String) = Box(value)
10+
11+
companion val Box.default: Box
12+
get() = Box("")
13+
14+
fun source(): String = ""
15+
16+
fun sink(value: String) {}
17+
18+
fun test() {
19+
sink(Box.create(source()).value)
20+
sink(Box.default.value)
21+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import java
2+
import semmle.code.java.dataflow.TaintTracking
3+
4+
predicate isCompanionCallable(Callable callable) {
5+
callable.getName() = ["empty", "create", "getDefault"]
6+
}
7+
8+
query predicate declarations(
9+
Callable callable, RefType declaringType, string primaryClass, string signature
10+
) {
11+
isCompanionCallable(callable) and
12+
callable.fromSource() and
13+
declaringType = callable.getDeclaringType() and
14+
primaryClass = callable.getAPrimaryQlClass() and
15+
signature = callable.getSignature()
16+
}
17+
18+
query predicate calls(MethodCall call, Callable caller, Method target, Expr qualifier) {
19+
caller.fromSource() and
20+
call.getEnclosingCallable() = caller and
21+
target = call.getMethod() and
22+
isCompanionCallable(target) and
23+
qualifier = call.getQualifier()
24+
}
25+
26+
query predicate properties(Property property, RefType declaringType, Method getter) {
27+
property.hasName("default") and
28+
property.fromSource() and
29+
getter = property.getGetter() and
30+
declaringType = getter.getDeclaringType()
31+
}
32+
33+
module Config implements DataFlow::ConfigSig {
34+
predicate isSource(DataFlow::Node n) { n.asExpr().(MethodCall).getMethod().hasName("source") }
35+
36+
predicate isSink(DataFlow::Node n) { n.asExpr().(Argument).getCall().getCallee().hasName("sink") }
37+
}
38+
39+
module Flow = TaintTracking::Global<Config>;
40+
41+
from DataFlow::Node source, DataFlow::Node sink
42+
where Flow::flow(source, sink)
43+
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)