From 2e8a8452a99d3722148e2b23658db2664a33004c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20Leuth=C3=A4user?= <1417198+max-leuthaeuser@users.noreply.github.com> Date: Mon, 11 Nov 2024 12:10:07 +0100 Subject: [PATCH 1/3] [kotlin2cpg] Implemented Lambda Parameter Destruction --- .../scala/io/joern/kotlin2cpg/Constants.scala | 2 +- .../io/joern/kotlin2cpg/ast/AstCreator.scala | 5 +- .../ast/AstForFunctionsCreator.scala | 107 ++++++++++++++++-- .../kotlin2cpg/dataflow/LambdaTests.scala | 22 ++-- .../kotlin2cpg/querying/LambdaTests.scala | 91 ++++++++++++--- .../src/main/scala/io/joern/x2cpg/Ast.scala | 15 +-- 6 files changed, 191 insertions(+), 51 deletions(-) diff --git a/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/Constants.scala b/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/Constants.scala index 6c7e69fe27c7..057216b61b36 100644 --- a/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/Constants.scala +++ b/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/Constants.scala @@ -22,7 +22,7 @@ object Constants { val nextIteratorMethodName = "next" val codePropUndefinedValue = "" val operatorSuffix = "" - val paramNameLambdaDestructureDecl = "DESTRUCTURE_PARAM" + val destructedParamNamePrefix = "" val parserTypeName = "KOTLIN_PSI_PARSER" val retCode = "RET" val ret = "RET" diff --git a/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstCreator.scala b/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstCreator.scala index b7b10b28a7c1..c51f39e97657 100644 --- a/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstCreator.scala +++ b/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstCreator.scala @@ -64,8 +64,9 @@ class AstCreator(fileWithMeta: KtFileWithMeta, bindingContext: BindingContext, g protected val lambdaBindingInfoQueue: mutable.ArrayBuffer[BindingInfo] = mutable.ArrayBuffer.empty protected val methodAstParentStack: Stack[NewNode] = new Stack() - protected val tmpKeyPool = new IntervalKeyPool(first = 1, last = Long.MaxValue) - protected val iteratorKeyPool = new IntervalKeyPool(first = 1, last = Long.MaxValue) + protected val tmpKeyPool = new IntervalKeyPool(first = 1, last = Long.MaxValue) + protected val destructedParamKeyPool = new IntervalKeyPool(first = 1, last = Long.MaxValue) + protected val iteratorKeyPool = new IntervalKeyPool(first = 1, last = Long.MaxValue) protected val relativizedPath: String = fileWithMeta.relativizedPath diff --git a/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstForFunctionsCreator.scala b/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstForFunctionsCreator.scala index ccad4bbd3f62..e0e8b929997f 100644 --- a/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstForFunctionsCreator.scala +++ b/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstForFunctionsCreator.scala @@ -9,11 +9,13 @@ import io.joern.x2cpg.datastructures.Stack.StackWrapper import io.joern.x2cpg.utils.NodeBuilders import io.joern.x2cpg.utils.NodeBuilders.newBindingNode import io.joern.x2cpg.utils.NodeBuilders.newClosureBindingNode +import io.joern.x2cpg.utils.NodeBuilders.newIdentifierNode import io.joern.x2cpg.utils.NodeBuilders.newMethodReturnNode import io.joern.x2cpg.utils.NodeBuilders.newModifierNode import io.shiftleft.codepropertygraph.generated.EvaluationStrategies import io.shiftleft.codepropertygraph.generated.ModifierTypes import io.shiftleft.codepropertygraph.generated.nodes.* +import io.shiftleft.codepropertygraph.generated.Operators import io.shiftleft.semanticcpg.language.types.structure.NamespaceTraversal import org.jetbrains.kotlin.com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.ClassDescriptor @@ -186,9 +188,93 @@ trait AstForFunctionsCreator(implicit withSchemaValidation: ValidationMode) { ) } + private def astsForDestructing(param: KtParameter): Seq[Ast] = { + val decl = param.getDestructuringDeclaration + val tmpName = s"${Constants.tmpLocalPrefix}${tmpKeyPool.next}" + var localForTmp = Option.empty[NewLocal] + val additionalLocals = mutable.ArrayBuffer.empty[Ast] + + val initCallAst = if (decl.hasInitializer) { + val init = decl.getInitializer + val asts = astsForExpression(init, Some(2)) + val initAst = + if (asts.size == 1) asts.head + else { + val block = blockNode(init, "", "").argumentIndex(2) + blockAst(block, asts.toList) + } + val local = localNode(decl, tmpName, tmpName, TypeConstants.any) + localForTmp = Some(local) + scope.addToScope(tmpName, local) + val tmpIdentifier = newIdentifierNode(tmpName, TypeConstants.any) + val tmpIdentifierAst = Ast(tmpIdentifier).withRefEdge(tmpIdentifier, local) + val assignmentCallNode = NodeBuilders.newOperatorCallNode( + Operators.assignment, + s"$tmpName = ${init.getText}", + None, + line(init), + column(init) + ) + callAst(assignmentCallNode, List(tmpIdentifierAst, initAst)) + } else { + val explicitTypeName = Option(param.getTypeReference) + .map(typeRef => fullNameByImportPath(typeRef, param.getContainingKtFile).getOrElse(typeRef.getText)) + .getOrElse(TypeConstants.any) + val typeFullName = registerType( + nameRenderer.typeFullName(bindingUtils.getVariableDesc(param).get.getType).getOrElse(explicitTypeName) + ) + val localForIt = localNode(decl, "it", "it", typeFullName) + additionalLocals.addOne(Ast(localForIt)) + val identifierForIt = newIdentifierNode("it", typeFullName) + val initAst = Ast(identifierForIt).withRefEdge(identifierForIt, localForIt) + val tmpIdentifier = newIdentifierNode(tmpName, typeFullName) + val local = localNode(decl, tmpName, tmpName, typeFullName) + localForTmp = Some(local) + scope.addToScope(tmpName, local) + val tmpIdentifierAst = Ast(tmpIdentifier).withRefEdge(tmpIdentifier, local) + val assignmentCallNode = + NodeBuilders.newOperatorCallNode(Operators.assignment, s"$tmpName = it", None, line(decl), column(decl)) + callAst(assignmentCallNode, List(tmpIdentifierAst, initAst)) + } + + val localsForDestructuringVars = localsForDestructuringEntries(decl) + val assignmentsForEntries = + decl.getEntries.asScala.filterNot(_.getText == Constants.unusedDestructuringEntryText).zipWithIndex.map { + case (entry, idx) => + val rhsBaseAst = astWithRefEdgeMaybe( + tmpName, + identifierNode(entry, tmpName, tmpName, localForTmp.map(_.typeFullName).getOrElse(TypeConstants.any)) + .argumentIndex(0) + ) + assignmentAstForDestructuringEntry(entry, rhsBaseAst, idx + 1) + } + + localForTmp + .map(l => Ast(l)) + .toSeq ++ additionalLocals ++ localsForDestructuringVars ++ (initCallAst +: assignmentsForEntries) + } + + private def astForDestructedParameter(param: KtParameter, order: Int): Ast = { + val name = s"${Constants.destructedParamNamePrefix}${destructedParamKeyPool.next}" + val explicitTypeName = Option(param.getTypeReference) + .map(typeRef => + fullNameByImportPath(typeRef, param.getContainingKtFile) + .getOrElse(typeRef.getText) + ) + .getOrElse(TypeConstants.any) + val typeFullName = registerType( + nameRenderer.typeFullName(bindingUtils.getVariableDesc(param).get.getType).getOrElse(explicitTypeName) + ) + val node = parameterInNode(param, name, name, order, false, EvaluationStrategies.BY_VALUE, typeFullName) + scope.addToScope(name, node) + + val annotations = param.getAnnotationEntries.asScala.map(astForAnnotationEntry).toSeq + Ast(node).withChildren(annotations) + } + def astForParameter(param: KtParameter, order: Int): Ast = { val name = if (param.getDestructuringDeclaration != null) { - Constants.paramNameLambdaDestructureDecl + Constants.destructedParamNamePrefix } else { param.getName } @@ -316,8 +402,6 @@ trait AstForFunctionsCreator(implicit withSchemaValidation: ValidationMode) { .withChildren(annotations.map(astForAnnotationEntry)) } - // TODO Handling for destructuring of lambda parameters is missing. - // More specifically the creation and initialisation of the thereby introduced variables. def astForLambda( expr: KtLambdaExpression, argIdxMaybe: Option[Int], @@ -363,7 +447,8 @@ trait AstForFunctionsCreator(implicit withSchemaValidation: ValidationMode) { node } - val paramAsts = mutable.ArrayBuffer.empty[Ast] + val paramAsts = mutable.ArrayBuffer.empty[Ast] + val destructedParamAsts = mutable.ArrayBuffer.empty[Ast] val valueParamStartIndex = if (funcDesc.getExtensionReceiverParameter != null) { // Lambdas which are arguments to function parameters defined @@ -382,13 +467,18 @@ trait AstForFunctionsCreator(implicit withSchemaValidation: ValidationMode) { case parameters => parameters.zipWithIndex.foreach { (paramDesc, idx) => val param = paramDesc.getSource.asInstanceOf[KotlinSourceElement].getPsi.asInstanceOf[KtParameter] - paramAsts.append(astForParameter(param, valueParamStartIndex + idx)) + if (param.getDestructuringDeclaration != null) { + paramAsts.append(astForDestructedParameter(param, valueParamStartIndex + idx)) + val destructAsts = astsForDestructing(param) + destructedParamAsts.appendAll(destructAsts) + } else { + paramAsts.append(astForParameter(param, valueParamStartIndex + idx)) + } } } val lastChildNotReturnExpression = !expr.getBodyExpression.getLastChild.isInstanceOf[KtReturnExpression] - val needsReturnExpression = - lastChildNotReturnExpression + val needsReturnExpression = lastChildNotReturnExpression val bodyAsts = Option(expr.getBodyExpression) .map( astsForBlock( @@ -397,7 +487,8 @@ trait AstForFunctionsCreator(implicit withSchemaValidation: ValidationMode) { None, pushToScope = false, localsForCaptured, - implicitReturnAroundLastStatement = needsReturnExpression + implicitReturnAroundLastStatement = needsReturnExpression, + Some(destructedParamAsts.toSeq) ) ) .getOrElse(Seq(Ast(NewBlock()))) diff --git a/joern-cli/frontends/kotlin2cpg/src/test/scala/io/joern/kotlin2cpg/dataflow/LambdaTests.scala b/joern-cli/frontends/kotlin2cpg/src/test/scala/io/joern/kotlin2cpg/dataflow/LambdaTests.scala index e150c85a5182..7151500a7d9b 100644 --- a/joern-cli/frontends/kotlin2cpg/src/test/scala/io/joern/kotlin2cpg/dataflow/LambdaTests.scala +++ b/joern-cli/frontends/kotlin2cpg/src/test/scala/io/joern/kotlin2cpg/dataflow/LambdaTests.scala @@ -8,7 +8,8 @@ class LambdaTests extends KotlinCode2CpgFixture(withOssDataflow = true) { implicit val resolver: ICallResolver = NoResolve "CPG for code containing a lambda with parameter destructuring" should { - val cpg = code("""|package mypkg + val cpg = code(""" + |package mypkg | |fun f1(p: String) { | val m = mapOf(p to 1, "two" to 2, "three" to 3) @@ -20,20 +21,15 @@ class LambdaTests extends KotlinCode2CpgFixture(withOssDataflow = true) { val source = cpg.method.name("f1").parameter val sink = cpg.call.methodFullName(".*println.*").argument val flows = sink.reachableByFlows(source) - // fixme: The nature of destructed parameters causes a loss in granularity here, what we see - // is the over-approximation of container `m` tainting called method-ref parameters flows.map(flowToResultPairs).toSet shouldBe Set( - List(("f1(p)", Some(3)), ("println(k)", Some(5))) -// List( -// ("f1(p)", Some(3)), -// ("p to 1", Some(4)), -// ("mapOf(p to 1, \"two\" to 2, \"three\" to 3)", Some(4)), -// ("val m = mapOf(p to 1, \"two\" to 2, \"three\" to 3)", Some(4)), -// ("m.forEach { (k, v) -> println(k) }", Some(5)), -// ("0(k, v)", Some(5)), -// ("println(k)", Some(5)) -// ) + List( + ("f1(p)", Some(4)), + ("tmp_1 = it", None), + ("tmp_1.component1()", Some(6)), + ("k = tmp_1.component1()", Some(6)), + ("println(k)", Some(6)) + ) ) } } diff --git a/joern-cli/frontends/kotlin2cpg/src/test/scala/io/joern/kotlin2cpg/querying/LambdaTests.scala b/joern-cli/frontends/kotlin2cpg/src/test/scala/io/joern/kotlin2cpg/querying/LambdaTests.scala index ab8e81b7e0c3..b8179f7d1542 100644 --- a/joern-cli/frontends/kotlin2cpg/src/test/scala/io/joern/kotlin2cpg/querying/LambdaTests.scala +++ b/joern-cli/frontends/kotlin2cpg/src/test/scala/io/joern/kotlin2cpg/querying/LambdaTests.scala @@ -186,11 +186,12 @@ class LambdaTests extends KotlinCode2CpgFixture(withOssDataflow = false, withDef "CPG for code with a scope function lambda with implicit parameter" should { val cpg = code(""" |package mypkg + | |fun f3(p: String): String { - | val out = p.apply { println(this) } - | return out + | val out = p.apply { println(this) } + | return out |} - ||""".stripMargin) + |""".stripMargin) "should contain a METHOD_PARAMETER_IN for the lambda with the correct properties set" in { val List(p) = cpg.method.fullName(".*lambda.*").parameter.l @@ -202,12 +203,14 @@ class LambdaTests extends KotlinCode2CpgFixture(withOssDataflow = false, withDef "lambda should contain METHOD_PARAMETER_IN for both implicit lambda parameters" in { val cpg = code(""" - |package mypkg - |public fun myFunc(block: String.(Int) -> Unit): Unit {} - |fun outer(param: String): Unit { - | myFunc { println(it); println(this)} - |} - ||""".stripMargin) + |package mypkg + | + |public fun myFunc(block: String.(Int) -> Unit): Unit {} + | fun outer(param: String): Unit { + | myFunc { println(it); println(this) + | } + |} + |""".stripMargin) val List(thisParam, itParam) = cpg.method.fullName(".*lambda.*").parameter.l thisParam.code shouldBe "this" @@ -219,13 +222,14 @@ class LambdaTests extends KotlinCode2CpgFixture(withOssDataflow = false, withDef } "CPG for code containing a lambda with parameter destructuring" should { - val cpg = code("""|package mypkg + val cpg = code(""" + |package mypkg | |fun f1(p: String) { - | val m = mapOf(p to 1, "two" to 2, "three" to 3) - | m.forEach { (k, v) -> - | println(k) - | } + | val m = mapOf(p to 1, "two" to 2, "three" to 3) + | m.forEach { (k, v) -> + | println(k) + | } |} |""".stripMargin) @@ -237,12 +241,41 @@ class LambdaTests extends KotlinCode2CpgFixture(withOssDataflow = false, withDef "should contain METHOD_PARAMETER_IN nodes for the lambda with the correct properties set" in { val List(p1) = cpg.method.fullName(".*lambda.*").parameter.l - p1.code shouldBe Constants.paramNameLambdaDestructureDecl + p1.code shouldBe s"${Constants.destructedParamNamePrefix}1" p1.index shouldBe 1 p1.typeFullName shouldBe "java.util.Map$Entry" } - // TODO add tests for initialisation of destructured parameter + "should contain the correct initialization" in { + val List(_, _, localTmp, localIt, localK, localV) = cpg.method.fullName(".*lambda.*").local.l + localTmp.name shouldBe "tmp_1" + localTmp.typeFullName shouldBe "java.util.Map$Entry" + localIt.name shouldBe "it" + localIt.typeFullName shouldBe "java.util.Map$Entry" + localK.name shouldBe "k" + localK.typeFullName shouldBe "java.lang.String" + localV.name shouldBe "v" + localV.typeFullName shouldBe "int" + + val List(tmpAssignment, kAssignment, vAssignment) = cpg.method.fullName(".*lambda.*").ast.isCall.isAssignment.l + tmpAssignment.code shouldBe "tmp_1 = it" + val List(tmp, it) = tmpAssignment.astChildren.isIdentifier.l + tmp.typeFullName shouldBe "java.util.Map$Entry" + it.typeFullName shouldBe "java.util.Map$Entry" + + kAssignment.code shouldBe "k = tmp_1.component1()" + val List(k) = kAssignment.astChildren.isIdentifier.l + k.typeFullName shouldBe "java.lang.String" + + vAssignment.code shouldBe "v = tmp_1.component2()" + val List(v) = vAssignment.astChildren.isIdentifier.l + v.typeFullName shouldBe "int" + + cpg.identifier.filter(_._astIn.isEmpty) shouldBe empty + cpg.identifier.filter(_.refsTo.isEmpty) shouldBe empty + cpg.local.filter(_._astIn.isEmpty) shouldBe empty + } + } "CPG for code containing a lambda with parameter destructuring and an `_` entry" should { @@ -265,10 +298,34 @@ class LambdaTests extends KotlinCode2CpgFixture(withOssDataflow = false, withDef "should contain one METHOD_PARAMETER_IN node for the lambda with the correct properties set" in { val List(p1) = cpg.method.fullName(".*lambda.*").parameter.l - p1.code shouldBe Constants.paramNameLambdaDestructureDecl + p1.code shouldBe s"${Constants.destructedParamNamePrefix}1" p1.index shouldBe 1 p1.typeFullName shouldBe "java.util.Map$Entry" } + + "should contain the correct initialization" in { + val List(_, _, localTmp, localIt, localK) = cpg.method.fullName(".*lambda.*").local.l + localTmp.name shouldBe "tmp_1" + localTmp.typeFullName shouldBe "java.util.Map$Entry" + localIt.name shouldBe "it" + localIt.typeFullName shouldBe "java.util.Map$Entry" + localK.name shouldBe "k" + localK.typeFullName shouldBe "java.lang.String" + + val List(tmpAssignment, kAssignment) = cpg.method.fullName(".*lambda.*").ast.isCall.isAssignment.l + tmpAssignment.code shouldBe "tmp_1 = it" + val List(tmp, it) = tmpAssignment.astChildren.isIdentifier.l + tmp.typeFullName shouldBe "java.util.Map$Entry" + it.typeFullName shouldBe "java.util.Map$Entry" + + kAssignment.code shouldBe "k = tmp_1.component1()" + val List(k) = kAssignment.astChildren.isIdentifier.l + k.typeFullName shouldBe "java.lang.String" + + cpg.identifier.filter(_._astIn.isEmpty) shouldBe empty + cpg.identifier.filter(_.refsTo.isEmpty) shouldBe empty + cpg.local.filter(_._astIn.isEmpty) shouldBe empty + } } "CPG for code with a scope function lambda" should { diff --git a/joern-cli/frontends/x2cpg/src/main/scala/io/joern/x2cpg/Ast.scala b/joern-cli/frontends/x2cpg/src/main/scala/io/joern/x2cpg/Ast.scala index b9f8bed7e67c..df185d8addcf 100644 --- a/joern-cli/frontends/x2cpg/src/main/scala/io/joern/x2cpg/Ast.scala +++ b/joern-cli/frontends/x2cpg/src/main/scala/io/joern/x2cpg/Ast.scala @@ -1,11 +1,10 @@ package io.joern.x2cpg -import io.shiftleft.codepropertygraph.generated.{DiffGraphBuilder, EdgeTypes} +import flatgraph.SchemaViolationException +import io.shiftleft.codepropertygraph.generated.DiffGraphBuilder +import io.shiftleft.codepropertygraph.generated.EdgeTypes import io.shiftleft.codepropertygraph.generated.nodes.* import io.shiftleft.codepropertygraph.generated.nodes.AstNode.PropertyDefaults -import org.slf4j.LoggerFactory -import io.shiftleft.codepropertygraph.generated.DiffGraphBuilder -import flatgraph.SchemaViolationException case class AstEdge(src: NewNode, dst: NewNode) @@ -15,8 +14,6 @@ enum ValidationMode { object Ast { - private val logger = LoggerFactory.getLogger(getClass) - def apply(node: NewNode)(implicit withSchemaValidation: ValidationMode): Ast = Ast(Vector.empty :+ node) def apply()(implicit withSchemaValidation: ValidationMode): Ast = new Ast(Vector.empty) @@ -244,11 +241,9 @@ case class Ast( case None => node.copy } if (argIndex != -1) { - // newNode.order = argIndex newNode match { - case expr: ExpressionNew => - expr.argumentIndex = argIndex - case _ => + case expr: ExpressionNew => expr.argumentIndex = argIndex + case _ => } } From 92548c015c8b684e9f5762ed333d2fe066915e16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20Leuth=C3=A4user?= <1417198+max-leuthaeuser@users.noreply.github.com> Date: Mon, 11 Nov 2024 13:36:20 +0100 Subject: [PATCH 2/3] format --- .../scala/io/joern/kotlin2cpg/Constants.scala | 63 +++++++++---------- .../ast/AstForDeclarationsCreator.scala | 2 +- .../ast/AstForFunctionsCreator.scala | 2 +- 3 files changed, 32 insertions(+), 35 deletions(-) diff --git a/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/Constants.scala b/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/Constants.scala index 057216b61b36..2f83d875ee74 100644 --- a/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/Constants.scala +++ b/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/Constants.scala @@ -1,37 +1,34 @@ package io.joern.kotlin2cpg object Constants { - val alloc = "alloc" - val caseNodeParserTypeName = "CaseNode" - val caseNodePrefix = "case" - val codeForLoweredForBlock = "FOR-BLOCK" // TODO: improve this - val collectionsIteratorName = "kotlin.collections.Iterator" - val companionObjectMemberName = "object" - val componentNPrefix = "component" - val defaultCaseNode = "default" - val empty = "" - val getIteratorMethodName = "iterator" - val hasNextIteratorMethodName = "hasNext" - val importKeyword = "import" - val init = io.joern.x2cpg.Defines.ConstructorMethodName - val iteratorPrefix = "iterator_" - val javaUtilIterator = "java.util.Iterator" - val unknownLambdaBindingName = "" - val unknownLambdaBaseClass = "" - val lambdaTypeDeclName = "LAMBDA_TYPE_DECL" - val nextIteratorMethodName = "next" - val codePropUndefinedValue = "" - val operatorSuffix = "" - val destructedParamNamePrefix = "" - val parserTypeName = "KOTLIN_PSI_PARSER" - val retCode = "RET" - val ret = "RET" - val root = "" - val this_ = "this" - val tmpLocalPrefix = "tmp_" - val tryCode = "try" - val unusedDestructuringEntryText = "_" - val unknownOperator = ".unknown" - val when = "when" - val wildcardImportName = "*" + val alloc = "alloc" + val caseNodeParserTypeName = "CaseNode" + val caseNodePrefix = "case" + val codeForLoweredForBlock = "FOR-BLOCK" // TODO: improve this + val collectionsIteratorName = "kotlin.collections.Iterator" + val companionObjectMemberName = "object" + val componentNPrefix = "component" + val defaultCaseNode = "default" + val empty = "" + val getIteratorMethodName = "iterator" + val hasNextIteratorMethodName = "hasNext" + val importKeyword = "import" + val init = io.joern.x2cpg.Defines.ConstructorMethodName + val iteratorPrefix = "iterator_" + val javaUtilIterator = "java.util.Iterator" + val unknownLambdaBindingName = "" + val unknownLambdaBaseClass = "" + val lambdaTypeDeclName = "LAMBDA_TYPE_DECL" + val nextIteratorMethodName = "next" + val codePropUndefinedValue = "" + val operatorSuffix = "" + val destructedParamNamePrefix = "" + val retCode = "RET" + val root = "" + val this_ = "this" + val tmpLocalPrefix = "tmp_" + val unusedDestructuringEntryText = "_" + val unknownOperator = ".unknown" + val when = "when" + val wildcardImportName = "*" } diff --git a/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstForDeclarationsCreator.scala b/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstForDeclarationsCreator.scala index 2cb0fb282211..64bf66931bf8 100644 --- a/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstForDeclarationsCreator.scala +++ b/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstForDeclarationsCreator.scala @@ -450,7 +450,7 @@ trait AstForDeclarationsCreator(implicit withSchemaValidation: ValidationMode) { val fieldAccessCallAst = callAst(fieldAccessCall, List(thisAst, Ast(fieldIdentifier))) val methodBlockAst = blockAst( blockNode(valueParam, fieldAccessCall.code, typeFullName), - List(returnAst(returnNode(valueParam, Constants.ret), List(fieldAccessCallAst))) + List(returnAst(returnNode(valueParam, Constants.retCode), List(fieldAccessCallAst))) ) val componentIdx = idx + 1 diff --git a/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstForFunctionsCreator.scala b/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstForFunctionsCreator.scala index e0e8b929997f..258959997e38 100644 --- a/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstForFunctionsCreator.scala +++ b/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstForFunctionsCreator.scala @@ -274,7 +274,7 @@ trait AstForFunctionsCreator(implicit withSchemaValidation: ValidationMode) { def astForParameter(param: KtParameter, order: Int): Ast = { val name = if (param.getDestructuringDeclaration != null) { - Constants.destructedParamNamePrefix + s"${Constants.destructedParamNamePrefix}${destructedParamKeyPool.next}" } else { param.getName } From bc1de1d0106a290733fb4572b220a26681ec458e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20Leuth=C3=A4user?= <1417198+max-leuthaeuser@users.noreply.github.com> Date: Tue, 12 Nov 2024 07:43:57 +0100 Subject: [PATCH 3/3] adjustments for review comment --- .../io/joern/kotlin2cpg/ast/AstForFunctionsCreator.scala | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstForFunctionsCreator.scala b/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstForFunctionsCreator.scala index 258959997e38..5387494d6d8b 100644 --- a/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstForFunctionsCreator.scala +++ b/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstForFunctionsCreator.scala @@ -188,7 +188,7 @@ trait AstForFunctionsCreator(implicit withSchemaValidation: ValidationMode) { ) } - private def astsForDestructing(param: KtParameter): Seq[Ast] = { + private def astsForDestructuring(param: KtParameter): Seq[Ast] = { val decl = param.getDestructuringDeclaration val tmpName = s"${Constants.tmpLocalPrefix}${tmpKeyPool.next}" var localForTmp = Option.empty[NewLocal] @@ -198,9 +198,9 @@ trait AstForFunctionsCreator(implicit withSchemaValidation: ValidationMode) { val init = decl.getInitializer val asts = astsForExpression(init, Some(2)) val initAst = - if (asts.size == 1) asts.head + if (asts.size == 1) { asts.head } else { - val block = blockNode(init, "", "").argumentIndex(2) + val block = blockNode(init, "", "") blockAst(block, asts.toList) } val local = localNode(decl, tmpName, tmpName, TypeConstants.any) @@ -244,7 +244,6 @@ trait AstForFunctionsCreator(implicit withSchemaValidation: ValidationMode) { val rhsBaseAst = astWithRefEdgeMaybe( tmpName, identifierNode(entry, tmpName, tmpName, localForTmp.map(_.typeFullName).getOrElse(TypeConstants.any)) - .argumentIndex(0) ) assignmentAstForDestructuringEntry(entry, rhsBaseAst, idx + 1) } @@ -469,7 +468,7 @@ trait AstForFunctionsCreator(implicit withSchemaValidation: ValidationMode) { val param = paramDesc.getSource.asInstanceOf[KotlinSourceElement].getPsi.asInstanceOf[KtParameter] if (param.getDestructuringDeclaration != null) { paramAsts.append(astForDestructedParameter(param, valueParamStartIndex + idx)) - val destructAsts = astsForDestructing(param) + val destructAsts = astsForDestructuring(param) destructedParamAsts.appendAll(destructAsts) } else { paramAsts.append(astForParameter(param, valueParamStartIndex + idx))