mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
Fix initializer field flow by extracting field finality
This commit is contained in:
@@ -778,19 +778,22 @@ open class KotlinFileExtractor(
|
||||
with("field", f) {
|
||||
DeclarationStackAdjuster(f).use {
|
||||
declarationStack.push(f)
|
||||
return extractField(useField(f), f.name.asString(), f.type, parentId, tw.getLocation(f), f.visibility, f, isExternalDeclaration(f))
|
||||
return extractField(useField(f), f.name.asString(), f.type, parentId, tw.getLocation(f), f.visibility, f, isExternalDeclaration(f), f.isFinal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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> {
|
||||
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> {
|
||||
val t = useType(type)
|
||||
tw.writeFields(id, name, t.javaResult.id, parentId, id)
|
||||
tw.writeFieldsKotlinType(id, t.kotlinResult.id)
|
||||
tw.writeHasLocation(id, locId)
|
||||
|
||||
extractVisibility(errorElement, id, visibility)
|
||||
if (isFinal) {
|
||||
addModifiers(id, "final")
|
||||
}
|
||||
|
||||
if (!isExternalDeclaration) {
|
||||
val fieldDeclarationId = tw.getFreshIdLabel<DbFielddecl>()
|
||||
@@ -2949,12 +2952,12 @@ open class KotlinFileExtractor(
|
||||
|
||||
// only one of the following can be non-null:
|
||||
if (dispatchReceiver != null) {
|
||||
extractField(dispatchFieldId!!, "<dispatchReceiver>", receiverType!!, classId, locId, DescriptorVisibilities.PRIVATE, callableReferenceExpr, false)
|
||||
extractField(dispatchFieldId!!, "<dispatchReceiver>", receiverType!!, classId, locId, DescriptorVisibilities.PRIVATE, callableReferenceExpr, isExternalDeclaration = false, isFinal = true)
|
||||
extractParameterToFieldAssignmentInConstructor("<dispatchReceiver>", dispatchReceiver.type, dispatchFieldId, 0, firstAssignmentStmtIdx)
|
||||
}
|
||||
|
||||
if (extensionReceiver != null) {
|
||||
extractField(extensionFieldId!!, "<extensionReceiver>", receiverType!!, classId, locId, DescriptorVisibilities.PRIVATE, callableReferenceExpr, false)
|
||||
extractField(extensionFieldId!!, "<extensionReceiver>", receiverType!!, classId, locId, DescriptorVisibilities.PRIVATE, callableReferenceExpr, isExternalDeclaration = false, isFinal = true)
|
||||
extractParameterToFieldAssignmentInConstructor( "<extensionReceiver>", extensionReceiver.type, extensionFieldId, 0 + extensionParameterIndex, firstAssignmentStmtIdx + extensionParameterIndex)
|
||||
}
|
||||
}
|
||||
@@ -4005,7 +4008,7 @@ open class KotlinFileExtractor(
|
||||
|
||||
// add field
|
||||
val fieldId = tw.getFreshIdLabel<DbField>()
|
||||
extractField(fieldId, "<fn>", functionType, classId, locId, DescriptorVisibilities.PRIVATE, e, false)
|
||||
extractField(fieldId, "<fn>", functionType, classId, locId, DescriptorVisibilities.PRIVATE, e, isExternalDeclaration = false, isFinal = true)
|
||||
|
||||
// adjust constructor
|
||||
helper.extractParameterToFieldAssignmentInConstructor("<fn>", functionType, fieldId, 0, 1)
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
isFinalField
|
||||
| test.kt:3:3:3:18 | x |
|
||||
#select
|
||||
| test.kt:3:3:3:18 | this.x | test.kt:6:10:6:10 | getX(...) |
|
||||
@@ -0,0 +1,11 @@
|
||||
class Test {
|
||||
|
||||
val x = "Source"
|
||||
|
||||
fun test() {
|
||||
sink(x)
|
||||
}
|
||||
|
||||
fun sink(s: String) { }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import java
|
||||
import semmle.code.java.dataflow.DataFlow
|
||||
|
||||
class Config extends DataFlow::Configuration {
|
||||
|
||||
Config() { this = "dlkjhfgsdjgfhd2" }
|
||||
|
||||
override predicate isSource(DataFlow::Node n) {
|
||||
n.asExpr().(CompileTimeConstantExpr).getStringValue() = "Source"
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node n) {
|
||||
n.asExpr().(Argument).getCall().getCallee().getName() = "sink"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
query predicate isFinalField(Field f) { exists(FieldDeclaration f2 | f = f2.getAField()) and f.isFinal() }
|
||||
|
||||
from DataFlow::Node source, DataFlow::Node sink
|
||||
where any(Config c).hasFlow(source, sink)
|
||||
select source, sink
|
||||
Reference in New Issue
Block a user