Skip to content

Commit 9e7fc17

Browse files
authored
Merge pull request #9898 from smowton/smowton/fix/kotlin-super-calls
Kotlin: implement super-method calls
2 parents e179126 + 5086841 commit 9e7fc17

File tree

4 files changed

+84
-8
lines changed

4 files changed

+84
-8
lines changed

java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,10 @@ open class KotlinFileExtractor(
888888
if (shortName.nameInDB != shortName.kotlinName) {
889889
tw.writeKtFunctionOriginalNames(methodId, shortName.kotlinName)
890890
}
891+
892+
if (f.hasInterfaceParent() && f.body != null) {
893+
addModifiers(id, "default") // The actual output class file may or may not have this modifier, depending on the -Xjvm-default setting.
894+
}
891895
}
892896

893897
tw.writeHasLocation(id, locId)
@@ -1386,7 +1390,8 @@ open class KotlinFileExtractor(
13861390
dispatchReceiver: IrExpression?,
13871391
extensionReceiver: IrExpression?,
13881392
typeArguments: List<IrType> = listOf(),
1389-
extractClassTypeArguments: Boolean = false) {
1393+
extractClassTypeArguments: Boolean = false,
1394+
superQualifierSymbol: IrClassSymbol? = null) {
13901395

13911396
val locId = tw.getLocation(callsite)
13921397

@@ -1404,7 +1409,8 @@ open class KotlinFileExtractor(
14041409
dispatchReceiver?.let { { callId -> extractExpressionExpr(dispatchReceiver, enclosingCallable, callId, -1, enclosingStmt) } },
14051410
extensionReceiver?.let { { argParent -> extractExpressionExpr(extensionReceiver, enclosingCallable, argParent, 0, enclosingStmt) } },
14061411
typeArguments,
1407-
extractClassTypeArguments
1412+
extractClassTypeArguments,
1413+
superQualifierSymbol
14081414
)
14091415

14101416
}
@@ -1424,7 +1430,8 @@ open class KotlinFileExtractor(
14241430
extractDispatchReceiver: ((Label<out DbExpr>) -> Unit)?,
14251431
extractExtensionReceiver: ((Label<out DbExpr>) -> Unit)?,
14261432
typeArguments: List<IrType> = listOf(),
1427-
extractClassTypeArguments: Boolean = false) {
1433+
extractClassTypeArguments: Boolean = false,
1434+
superQualifierSymbol: IrClassSymbol? = null) {
14281435

14291436
val callTarget = syntacticCallTarget.target.realOverrideTarget
14301437
val id = tw.getFreshIdLabel<DbMethodaccess>()
@@ -1483,6 +1490,8 @@ open class KotlinFileExtractor(
14831490

14841491
if (callTarget.shouldExtractAsStatic) {
14851492
extractStaticTypeAccessQualifier(callTarget, id, locId, enclosingCallable, enclosingStmt)
1493+
} else if (superQualifierSymbol != null) {
1494+
extractSuperAccess(superQualifierSymbol.typeWith(), enclosingCallable, id, -1, enclosingStmt, locId)
14861495
} else if (extractDispatchReceiver != null) {
14871496
extractDispatchReceiver(id)
14881497
}
@@ -1744,7 +1753,7 @@ open class KotlinFileExtractor(
17441753
else
17451754
listOf()
17461755

1747-
extractRawMethodAccess(syntacticCallTarget, c, callable, parent, idx, enclosingStmt, (0 until c.valueArgumentsCount).map { c.getValueArgument(it) }, c.dispatchReceiver, c.extensionReceiver, typeArgs, extractClassTypeArguments)
1756+
extractRawMethodAccess(syntacticCallTarget, c, callable, parent, idx, enclosingStmt, (0 until c.valueArgumentsCount).map { c.getValueArgument(it) }, c.dispatchReceiver, c.extensionReceiver, typeArgs, extractClassTypeArguments, c.superQualifierSymbol)
17481757
}
17491758

17501759
fun extractSpecialEnumFunction(fnName: String){
@@ -3066,6 +3075,17 @@ open class KotlinFileExtractor(
30663075
}
30673076
}
30683077

3078+
private fun extractSuperAccess(irType: IrType, callable: Label<out DbCallable>, parent: Label<out DbExprparent>, idx: Int, enclosingStmt: Label<out DbStmt>, locId: Label<out DbLocation>) =
3079+
tw.getFreshIdLabel<DbSuperaccess>().also {
3080+
val type = useType(irType)
3081+
tw.writeExprs_superaccess(it, type.javaResult.id, parent, idx)
3082+
tw.writeExprsKotlinType(it, type.kotlinResult.id)
3083+
tw.writeHasLocation(it, locId)
3084+
tw.writeCallableEnclosingExpr(it, callable)
3085+
tw.writeStatementEnclosingExpr(it, enclosingStmt)
3086+
extractTypeAccessRecursive(irType, locId, it, 0)
3087+
}
3088+
30693089
private fun extractThisAccess(e: IrGetValue, exprParent: ExprParent, callable: Label<out DbCallable>) {
30703090
val containingDeclaration = declarationStack.peek()
30713091
val locId = tw.getLocation(e)
@@ -4020,7 +4040,7 @@ open class KotlinFileExtractor(
40204040
/**
40214041
* Extracts a single wildcard type access expression with no enclosing callable and statement.
40224042
*/
4023-
private fun extractWildcardTypeAccess(type: TypeResults, location: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int): Label<out DbExpr> {
4043+
private fun extractWildcardTypeAccess(type: TypeResults, location: Label<out DbLocation>, parent: Label<out DbExprparent>, idx: Int): Label<out DbExpr> {
40244044
val id = tw.getFreshIdLabel<DbWildcardtypeaccess>()
40254045
tw.writeExprs_wildcardtypeaccess(id, type.javaResult.id, parent, idx)
40264046
tw.writeExprsKotlinType(id, type.kotlinResult.id)
@@ -4031,7 +4051,7 @@ open class KotlinFileExtractor(
40314051
/**
40324052
* Extracts a single type access expression with no enclosing callable and statement.
40334053
*/
4034-
private fun extractTypeAccess(type: TypeResults, location: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int): Label<out DbExpr> {
4054+
private fun extractTypeAccess(type: TypeResults, location: Label<out DbLocation>, parent: Label<out DbExprparent>, idx: Int): Label<out DbExpr> {
40354055
// TODO: elementForLocation allows us to give some sort of
40364056
// location, but a proper location for the type access will
40374057
// require upstream changes
@@ -4057,7 +4077,7 @@ open class KotlinFileExtractor(
40574077
* `extractTypeAccessRecursive` if the argument is invariant.
40584078
* No enclosing callable and statement is extracted, this is useful for type access extraction in field declarations.
40594079
*/
4060-
private fun extractWildcardTypeAccessRecursive(t: IrTypeArgument, location: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int) {
4080+
private fun extractWildcardTypeAccessRecursive(t: IrTypeArgument, location: Label<out DbLocation>, parent: Label<out DbExprparent>, idx: Int) {
40614081
val typeLabels by lazy { TypeResults(getTypeArgumentLabel(t), TypeResult(fakeKotlinType(), "TODO", "TODO")) }
40624082
when (t) {
40634083
is IrStarProjection -> extractWildcardTypeAccess(typeLabels, location, parent, idx)
@@ -4077,7 +4097,7 @@ open class KotlinFileExtractor(
40774097
* Extracts a type access expression and its child type access expressions in case of a generic type. Nested generics are also handled.
40784098
* No enclosing callable and statement is extracted, this is useful for type access extraction in field declarations.
40794099
*/
4080-
private fun extractTypeAccessRecursive(t: IrType, location: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int, typeContext: TypeContext = TypeContext.OTHER): Label<out DbExpr> {
4100+
private fun extractTypeAccessRecursive(t: IrType, location: Label<out DbLocation>, parent: Label<out DbExprparent>, idx: Int, typeContext: TypeContext = TypeContext.OTHER): Label<out DbExpr> {
40814101
val typeAccessId = extractTypeAccess(useType(t, typeContext), location, parent, idx)
40824102
if (t is IrSimpleType) {
40834103
t.arguments.forEachIndexed { argIdx, arg ->
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| test.kt:31:17:31:24 | source(...) | test.kt:31:15:31:25 | f(...) |
2+
| test.kt:32:17:32:24 | source(...) | test.kt:32:15:32:25 | g(...) |
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
open class A {
2+
3+
open fun f(x: String) = x
4+
5+
}
6+
7+
interface B {
8+
9+
fun g(x: String) = x
10+
11+
}
12+
13+
interface C {
14+
15+
fun g(x: String) = x
16+
17+
}
18+
19+
class User : A(), B, C {
20+
21+
override fun f(x: String) = super.f(x)
22+
23+
override fun g(x: String) = super<B>.g(x)
24+
25+
fun source() = "tainted"
26+
27+
fun sink(s: String) { }
28+
29+
fun test() {
30+
31+
sink(this.f(source()))
32+
sink(this.g(source()))
33+
34+
}
35+
36+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import java
2+
import semmle.code.java.dataflow.DataFlow
3+
4+
class Config extends DataFlow::Configuration {
5+
Config() { this = "abc" }
6+
7+
override predicate isSource(DataFlow::Node n) {
8+
n.asExpr().(MethodAccess).getMethod().getName() = "source"
9+
}
10+
11+
override predicate isSink(DataFlow::Node n) {
12+
n.asExpr().(Argument).getCall().getCallee().getName() = "sink"
13+
}
14+
}
15+
16+
from Config c, DataFlow::Node n1, DataFlow::Node n2
17+
where c.hasFlow(n1, n2)
18+
select n1, n2

0 commit comments

Comments
 (0)