Skip to content

Commit 81baca2

Browse files
committed
Fix initializer field flow by extracting field finality
1 parent eacb9f1 commit 81baca2

File tree

4 files changed

+45
-5
lines changed

4 files changed

+45
-5
lines changed

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -778,19 +778,22 @@ open class KotlinFileExtractor(
778778
with("field", f) {
779779
DeclarationStackAdjuster(f).use {
780780
declarationStack.push(f)
781-
return extractField(useField(f), f.name.asString(), f.type, parentId, tw.getLocation(f), f.visibility, f, isExternalDeclaration(f))
781+
return extractField(useField(f), f.name.asString(), f.type, parentId, tw.getLocation(f), f.visibility, f, isExternalDeclaration(f), f.isFinal)
782782
}
783783
}
784784
}
785785

786786

787-
private fun extractField(id: Label<out DbField>, name: String, type: IrType, parentId: Label<out DbReftype>, locId: Label<DbLocation>, visibility: DescriptorVisibility, errorElement: IrElement, isExternalDeclaration: Boolean): Label<out DbField> {
787+
private fun extractField(id: Label<out DbField>, name: String, type: IrType, parentId: Label<out DbReftype>, locId: Label<DbLocation>, visibility: DescriptorVisibility, errorElement: IrElement, isExternalDeclaration: Boolean, isFinal: Boolean): Label<out DbField> {
788788
val t = useType(type)
789789
tw.writeFields(id, name, t.javaResult.id, parentId, id)
790790
tw.writeFieldsKotlinType(id, t.kotlinResult.id)
791791
tw.writeHasLocation(id, locId)
792792

793793
extractVisibility(errorElement, id, visibility)
794+
if (isFinal) {
795+
addModifiers(id, "final")
796+
}
794797

795798
if (!isExternalDeclaration) {
796799
val fieldDeclarationId = tw.getFreshIdLabel<DbFielddecl>()
@@ -2949,12 +2952,12 @@ open class KotlinFileExtractor(
29492952

29502953
// only one of the following can be non-null:
29512954
if (dispatchReceiver != null) {
2952-
extractField(dispatchFieldId!!, "<dispatchReceiver>", receiverType!!, classId, locId, DescriptorVisibilities.PRIVATE, callableReferenceExpr, false)
2955+
extractField(dispatchFieldId!!, "<dispatchReceiver>", receiverType!!, classId, locId, DescriptorVisibilities.PRIVATE, callableReferenceExpr, isExternalDeclaration = false, isFinal = true)
29532956
extractParameterToFieldAssignmentInConstructor("<dispatchReceiver>", dispatchReceiver.type, dispatchFieldId, 0, firstAssignmentStmtIdx)
29542957
}
29552958

29562959
if (extensionReceiver != null) {
2957-
extractField(extensionFieldId!!, "<extensionReceiver>", receiverType!!, classId, locId, DescriptorVisibilities.PRIVATE, callableReferenceExpr, false)
2960+
extractField(extensionFieldId!!, "<extensionReceiver>", receiverType!!, classId, locId, DescriptorVisibilities.PRIVATE, callableReferenceExpr, isExternalDeclaration = false, isFinal = true)
29582961
extractParameterToFieldAssignmentInConstructor( "<extensionReceiver>", extensionReceiver.type, extensionFieldId, 0 + extensionParameterIndex, firstAssignmentStmtIdx + extensionParameterIndex)
29592962
}
29602963
}
@@ -4005,7 +4008,7 @@ open class KotlinFileExtractor(
40054008

40064009
// add field
40074010
val fieldId = tw.getFreshIdLabel<DbField>()
4008-
extractField(fieldId, "<fn>", functionType, classId, locId, DescriptorVisibilities.PRIVATE, e, false)
4011+
extractField(fieldId, "<fn>", functionType, classId, locId, DescriptorVisibilities.PRIVATE, e, isExternalDeclaration = false, isFinal = true)
40094012

40104013
// adjust constructor
40114014
helper.extractParameterToFieldAssignmentInConstructor("<fn>", functionType, fieldId, 0, 1)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
isFinalField
2+
| test.kt:3:3:3:18 | x |
3+
#select
4+
| test.kt:3:3:3:18 | this.x | test.kt:6:10:6:10 | getX(...) |
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class Test {
2+
3+
val x = "Source"
4+
5+
fun test() {
6+
sink(x)
7+
}
8+
9+
fun sink(s: String) { }
10+
11+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import java
2+
import semmle.code.java.dataflow.DataFlow
3+
4+
class Config extends DataFlow::Configuration {
5+
6+
Config() { this = "dlkjhfgsdjgfhd2" }
7+
8+
override predicate isSource(DataFlow::Node n) {
9+
n.asExpr().(CompileTimeConstantExpr).getStringValue() = "Source"
10+
}
11+
12+
override predicate isSink(DataFlow::Node n) {
13+
n.asExpr().(Argument).getCall().getCallee().getName() = "sink"
14+
}
15+
16+
}
17+
18+
query predicate isFinalField(Field f) { exists(FieldDeclaration f2 | f = f2.getAField()) and f.isFinal() }
19+
20+
from DataFlow::Node source, DataFlow::Node sink
21+
where any(Config c).hasFlow(source, sink)
22+
select source, sink

0 commit comments

Comments
 (0)