From 8db5d70a59c4e42dedaf0793d6de3fb156061131 Mon Sep 17 00:00:00 2001 From: Fabian Yamaguchi Date: Mon, 13 Feb 2023 18:05:11 +0200 Subject: [PATCH] Consistent callAST creation across frontends (#2265) * Replace `receiver` with `base` in `callAst` * Adapt `callAst` to that used in jssrc2cpg * Do not use `receiver` outside jssrc2cpg * Use `callAst` in `jssrc2cpg` * Fix build * Add comment --------- Co-authored-by: Fabian Yamaguchi --- .../passes/ast/AstCreationPassTests.scala | 7 +-- .../joern/javasrc2cpg/passes/AstCreator.scala | 14 ++--- .../javasrc2cpg/querying/CallTests.scala | 10 ++-- .../querying/ControlStructureTests.scala | 6 +- .../javasrc2cpg/querying/TypeTests.scala | 2 +- .../jssrc2cpg/astcreation/AstCreator.scala | 2 +- .../AstForDeclarationsCreator.scala | 20 +++---- .../AstForExpressionsCreator.scala | 35 +++++------- .../astcreation/AstForFunctionsCreator.scala | 4 +- .../astcreation/AstForPrimitivesCreator.scala | 2 +- .../astcreation/AstForStatementsCreator.scala | 26 ++++----- .../AstForTemplateDomCreator.scala | 12 ++-- .../astcreation/AstForTypesCreator.scala | 4 +- .../astcreation/AstNodeBuilder.scala | 55 +++---------------- .../joern/kotlin2cpg/passes/KtPsiToAst.scala | 22 ++++---- .../querying/ControlStructureTests.scala | 6 -- .../php2cpg/astcreation/AstCreator.scala | 10 ++-- .../io/joern/php2cpg/querying/CallTests.scala | 9 +-- .../querying/ControlStructureTests.scala | 8 +-- .../php2cpg/querying/TypeDeclTests.scala | 6 +- .../scala/io/joern/x2cpg/AstCreatorBase.scala | 54 +++++++++++++----- 21 files changed, 142 insertions(+), 172 deletions(-) diff --git a/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/ast/AstCreationPassTests.scala b/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/ast/AstCreationPassTests.scala index 2176c23ee2ea..8ca2c7ecbba7 100644 --- a/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/ast/AstCreationPassTests.scala +++ b/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/ast/AstCreationPassTests.scala @@ -320,12 +320,10 @@ class AstCreationPassTests extends AbstractPassTest { lit.code shouldBe "10" } - inside(lambda2call.argument.l) { case List(lit: Literal) => - lit.code shouldBe "10" - } - inside(lambda2call.receiver.l) { case List(ref: MethodRef) => + inside(lambda2call.argument.l) { case List(ref: MethodRef, lit: Literal) => ref.methodFullName shouldBe lambda2Name ref.code shouldBe "int anonymous_lambda_1 (int n)" + lit.code shouldBe "10" } } } @@ -1103,6 +1101,7 @@ class AstCreationPassTests extends AbstractPassTest { .name("Foo") .l .size shouldBe 1 + inside(cpg.call.code("f.method()").l) { case List(call: Call) => call.methodFullName shouldBe Operators.fieldAccess call.argument(1).code shouldBe "f" diff --git a/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/passes/AstCreator.scala b/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/passes/AstCreator.scala index bd6395599afe..885bf5a5566b 100644 --- a/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/passes/AstCreator.scala +++ b/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/passes/AstCreator.scala @@ -1605,7 +1605,7 @@ class AstCreator(filename: String, javaParserAst: CompilationUnit, global: Globa } val iteratorCallAst = - callAst(iteratorCallNode, receiver = actualIteratorAst, withRecvArgEdge = true) + callAst(iteratorCallNode, base = actualIteratorAst) callAst(iteratorAssignNode, List(Ast(iteratorAssignIdentifier), iteratorCallAst)) .withRefEdge(iteratorAssignIdentifier, iteratorLocalNode) @@ -1623,7 +1623,7 @@ class AstCreator(filename: String, javaParserAst: CompilationUnit, global: Globa val iteratorHasNextCallReceiver = identifierNode(iteratorLocalNode.name, Some(iteratorLocalNode.typeFullName), lineNo) - callAst(iteratorHasNextCallNode, receiver = Some(Ast(iteratorHasNextCallReceiver)), withRecvArgEdge = true) + callAst(iteratorHasNextCallNode, base = Some(Ast(iteratorHasNextCallReceiver))) .withRefEdge(iteratorHasNextCallReceiver, iteratorLocalNode) } @@ -1644,7 +1644,7 @@ class AstCreator(filename: String, javaParserAst: CompilationUnit, global: Globa ) val iterNextCallReceiver = identifierNode(iteratorLocalNode.name, Some(iteratorLocalNode.typeFullName), lineNo) val iterNextCallAst = - callAst(iterNextCallNode, receiver = Some(Ast(iterNextCallReceiver)), withRecvArgEdge = true) + callAst(iterNextCallNode, base = Some(Ast(iterNextCallReceiver))) .withRefEdge(iterNextCallReceiver, iteratorLocalNode) callAst(varLocalAssignNode, List(Ast(varLocalAssignIdentifier), iterNextCallAst)) @@ -2172,7 +2172,7 @@ class AstCreator(filename: String, javaParserAst: CompilationUnit, global: Globa case _ => // Nothing to do in this case } - callAst(initNode, args.toList, Some(targetAst), withRecvArgEdge = true) + callAst(initNode, args.toList, Some(targetAst)) } def astsForVariableDecl(varDecl: VariableDeclarationExpr): Seq[Ast] = { @@ -2468,7 +2468,7 @@ class AstCreator(filename: String, javaParserAst: CompilationUnit, global: Globa val identifierWithDefaultOrder = identifier.copy.order(PropertyDefaults.Order) val identifierForInit = identifierWithDefaultOrder.copy val initWithDefaultOrder = initNode.order(PropertyDefaults.Order) - val initAst = callAst(initWithDefaultOrder, args, Some(Ast(identifierForInit)), withRecvArgEdge = true) + val initAst = callAst(initWithDefaultOrder, args, Some(Ast(identifierForInit))) val returnAst = Ast(identifierWithDefaultOrder.copy) @@ -2517,7 +2517,7 @@ class AstCreator(filename: String, javaParserAst: CompilationUnit, global: Globa } val thisAst = Ast(thisNode) - callAst(callRoot, args, Some(thisAst), withRecvArgEdge = true) + callAst(callRoot, args, Some(thisAst)) } private def astsForExpression(expression: Expression, expectedType: ExpectedType): Seq[Ast] = { @@ -3147,7 +3147,7 @@ class AstCreator(filename: String, javaParserAst: CompilationUnit, global: Globa .columnNumber(column(call)) .typeFullName(expressionTypeFullName.getOrElse(TypeConstants.Any)) - callAst(callRoot, argumentAsts, scopeAsts.headOption, withRecvArgEdge = true) + callAst(callRoot, argumentAsts, scopeAsts.headOption) } def astForSuperExpr(superExpr: SuperExpr, expectedType: ExpectedType): Ast = { diff --git a/joern-cli/frontends/javasrc2cpg/src/test/scala/io/joern/javasrc2cpg/querying/CallTests.scala b/joern-cli/frontends/javasrc2cpg/src/test/scala/io/joern/javasrc2cpg/querying/CallTests.scala index 6982cfadaa7e..c5d66ea785dc 100644 --- a/joern-cli/frontends/javasrc2cpg/src/test/scala/io/joern/javasrc2cpg/querying/CallTests.scala +++ b/joern-cli/frontends/javasrc2cpg/src/test/scala/io/joern/javasrc2cpg/querying/CallTests.scala @@ -96,7 +96,7 @@ class NewCallTests extends JavaSrcCode2CpgFixture { .fullNameExact(s"Foo.${io.joern.x2cpg.Defines.ConstructorMethodName}:void()") .call .nameExact(io.joern.x2cpg.Defines.ConstructorMethodName) - .receiver + .argument(0) .l match { case List(thisNode: Identifier) => thisNode.outE.collectAll[Ref].map(_.inNode).l match { @@ -120,7 +120,7 @@ class NewCallTests extends JavaSrcCode2CpgFixture { | public void foo(int x) {} |}""".stripMargin) - cpg.method.name("test").call.name("foo").receiver.outE.collectAll[Ref].l match { + cpg.method.name("test").call.name("foo").argument(0).outE.collectAll[Ref].l match { case List(ref) => ref.inNode match { case param: MethodParameterIn => @@ -145,7 +145,7 @@ class NewCallTests extends JavaSrcCode2CpgFixture { | public void foo(int x) {} |}""".stripMargin) - cpg.method.name("test").call.name("foo").receiver.outE.collectAll[Ref].l match { + cpg.method.name("test").call.name("foo").argument(0).outE.collectAll[Ref].l match { case List(ref) => ref.inNode match { case param: MethodParameterIn => @@ -320,7 +320,7 @@ class NewCallTests extends JavaSrcCode2CpgFixture { |""".stripMargin) "create a `super` receiver with fields correctly set" in { - val superReceiver = cpg.call.name("toString").receiver.collectAll[Identifier].head + val superReceiver = cpg.call.name("toString").argument(0).collectAll[Identifier].head superReceiver.name shouldBe "this" superReceiver.code shouldBe "super" superReceiver.typeFullName shouldBe "java.lang.Object" @@ -400,7 +400,7 @@ class CallTests extends JavaSrcCode2CpgFixture { "should allow traversing from call to arguments" in { cpg.call("add").argument.size shouldBe 3 - val List(arg0) = cpg.call("add").receiver.l + val List(arg0) = cpg.call("add").argument(0).l arg0.isInstanceOf[nodes.Identifier] shouldBe true arg0.asInstanceOf[nodes.Identifier].name shouldBe "this" arg0.code shouldBe "this" diff --git a/joern-cli/frontends/javasrc2cpg/src/test/scala/io/joern/javasrc2cpg/querying/ControlStructureTests.scala b/joern-cli/frontends/javasrc2cpg/src/test/scala/io/joern/javasrc2cpg/querying/ControlStructureTests.scala index a0e107ff3b03..46f8b28f108c 100644 --- a/joern-cli/frontends/javasrc2cpg/src/test/scala/io/joern/javasrc2cpg/querying/ControlStructureTests.scala +++ b/joern-cli/frontends/javasrc2cpg/src/test/scala/io/joern/javasrc2cpg/querying/ControlStructureTests.scala @@ -602,7 +602,7 @@ class NewControlStructureTests extends JavaSrcCode2CpgFixture { iteratorCall.order shouldBe 2 iteratorCall.argumentIndex shouldBe 2 - iteratorCall.receiver.l match { + iteratorCall.argument(0).l match { case List(items: Identifier) => items.name shouldBe "items" items.typeFullName shouldBe "java.util.List" @@ -631,7 +631,7 @@ class NewControlStructureTests extends JavaSrcCode2CpgFixture { conditionCall.dispatchType shouldBe DispatchTypes.DYNAMIC_DISPATCH conditionCall.order shouldBe 1 - conditionCall.receiver.l match { + conditionCall.argument(0).l match { case List(receiver: Identifier) => receiver.name shouldBe "$iterLocal0" receiver.typeFullName shouldBe "java.util.Iterator" @@ -688,7 +688,7 @@ class NewControlStructureTests extends JavaSrcCode2CpgFixture { assignSource.typeFullName shouldBe "java.lang.Object" assignSource.order shouldBe 2 assignSource.argumentIndex shouldBe 2 - assignSource.receiver.l match { + assignSource.argument(0).l match { case List(iterIdent: Identifier) => iterIdent.name shouldBe "$iterLocal0" iterIdent.typeFullName shouldBe "java.util.Iterator" diff --git a/joern-cli/frontends/javasrc2cpg/src/test/scala/io/joern/javasrc2cpg/querying/TypeTests.scala b/joern-cli/frontends/javasrc2cpg/src/test/scala/io/joern/javasrc2cpg/querying/TypeTests.scala index de581b5bb5cb..3eb972402325 100644 --- a/joern-cli/frontends/javasrc2cpg/src/test/scala/io/joern/javasrc2cpg/querying/TypeTests.scala +++ b/joern-cli/frontends/javasrc2cpg/src/test/scala/io/joern/javasrc2cpg/querying/TypeTests.scala @@ -276,7 +276,7 @@ class TypeTests extends JavaSrcCode2CpgFixture { call.typeFullName shouldBe "void" call.dispatchType shouldBe DispatchTypes.STATIC_DISPATCH.toString - call.receiver.collect { case identifier: Identifier => identifier }.l match { + call.argument(0).collect { case identifier: Identifier => identifier }.l match { case identifier :: Nil => identifier.name shouldBe "this" identifier.typeFullName shouldBe "java.lang.Object" diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstCreator.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstCreator.scala index 117150d7a9d7..c01e66548eeb 100644 --- a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstCreator.scala +++ b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstCreator.scala @@ -114,7 +114,7 @@ class AstCreator( createParameterInNode("this", "this", 0, isVariadic = false, line = lineNumber, column = columnNumber) val methodChildren = astsForFile(astNodeInfo) - setArgIndices(methodChildren) + setArgumentIndices(methodChildren) val methodReturn = methodReturnNode(Defines.Any, line = None, column = None) diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForDeclarationsCreator.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForDeclarationsCreator.scala index 1aa408d8fd91..6432755f9929 100644 --- a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForDeclarationsCreator.scala +++ b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForDeclarationsCreator.scala @@ -145,7 +145,7 @@ trait AstForDeclarationsCreator { this: AstCreator => declaration.columnNumber ) val sourceAst = - createCallAst(sourceCall, List(Ast(sourceCallArgNode))) + callAst(sourceCall, List(Ast(sourceCallArgNode))) val assignmentCallAst = createAssignmentCallAst( Ast(id), sourceAst, @@ -207,7 +207,7 @@ trait AstForDeclarationsCreator { this: AstCreator => } val asts = fromAst +: (specifierAsts ++ declAsts.flatten) - setArgIndices(asts) + setArgumentIndices(asts) blockAst(createBlockNode(declaration), asts) } @@ -221,7 +221,7 @@ trait AstForDeclarationsCreator { this: AstCreator => } val asts = declAsts.toList.flatten - setArgIndices(asts) + setArgumentIndices(asts) blockAst(createBlockNode(assignment), asts) } @@ -237,7 +237,7 @@ trait AstForDeclarationsCreator { this: AstCreator => } val asts = declAsts.toList.flatten - setArgIndices(asts) + setArgumentIndices(asts) blockAst(createBlockNode(declaration), asts) } @@ -254,7 +254,7 @@ trait AstForDeclarationsCreator { this: AstCreator => val assignmentCallAst = createExportAssignmentCallAst(s"_$name", exportCallAst, declaration, None) val asts = List(fromCallAst, assignmentCallAst) - setArgIndices(asts) + setArgumentIndices(asts) blockAst(createBlockNode(declaration), asts) } @@ -268,7 +268,7 @@ trait AstForDeclarationsCreator { this: AstCreator => val declAsts = declaration.json("declarations").arr.toList.map(astForVariableDeclarator(_, scopeType, kind)) declAsts match { case head :: tail => - setArgIndices(declAsts) + setArgumentIndices(declAsts) tail.foreach { declAst => declAst.root.foreach(diffGraph.addEdge(localAstParentStack.head, _, EdgeTypes.AST)) Ast.storeInDiffGraph(declAst, diffGraph) @@ -398,7 +398,7 @@ trait AstForDeclarationsCreator { this: AstCreator => val receiverNode = createIdentifierNode(RequireKeyword, nodeInfo) val thisNode = createIdentifierNode("this", nodeInfo) scope.addVariableReference(thisNode.name, thisNode) - val callAst = createCallAst( + val cAst = callAst( sourceCall, List(Ast(sourceCallArgNode)), receiver = Option(Ast(receiverNode)), @@ -406,14 +406,14 @@ trait AstForDeclarationsCreator { this: AstCreator => ) val sourceAst = if (isImportN) { val fieldAccessCall = createFieldAccessCallAst( - callAst, + cAst, createFieldIdentifierNode(name, nodeInfo.lineNumber, nodeInfo.columnNumber), nodeInfo.lineNumber, nodeInfo.columnNumber ) fieldAccessCall } else { - callAst + cAst } val assigmentCallAst = createAssignmentCallAst( @@ -724,7 +724,7 @@ trait AstForDeclarationsCreator { this: AstCreator => localAstParentStack.pop() val blockChildren = assignmentTmpCallAst +: subTreeAsts :+ Ast(returnTmpNode) - setArgIndices(blockChildren) + setArgumentIndices(blockChildren) Ast(blockNode).withChildren(blockChildren) } diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForExpressionsCreator.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForExpressionsCreator.scala index 836f03502021..80b6bbafb866 100644 --- a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForExpressionsCreator.scala +++ b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForExpressionsCreator.scala @@ -23,7 +23,7 @@ trait AstForExpressionsCreator { this: AstCreator => val callNode = createStaticCallNode(callExpr.code, callName, fullName, callee.lineNumber, callee.columnNumber) val argAsts = astForNodes(callExpr.json("arguments").arr.toList) - createCallAst(callNode, argAsts) + callAst(callNode, argAsts) } private def handleCallNodeArgs( @@ -41,7 +41,7 @@ trait AstForExpressionsCreator { this: AstCreator => callExpr.lineNumber, callExpr.columnNumber ) - createCallAst(callNode, args, Option(receiverAst), Option(Ast(baseNode))) + callAst(callNode, args, receiver = Option(receiverAst), base = Option(Ast(baseNode))) } protected def astForCallExpression(callExpr: BabelNodeInfo): Ast = { @@ -137,7 +137,7 @@ trait AstForExpressionsCreator { this: AstCreator => scope.popScope() localAstParentStack.pop() - setArgIndices(List(assignmentTmpAllocCallNode, callNode, tmpAllocReturnNode)) + setArgumentIndices(List(assignmentTmpAllocCallNode, callNode, tmpAllocReturnNode)) Ast(blockNode).withChild(assignmentTmpAllocCallNode).withChild(callNode).withChild(tmpAllocReturnNode) } @@ -207,7 +207,7 @@ trait AstForExpressionsCreator { this: AstCreator => assignment.columnNumber ) val argAsts = List(lhsAst, rhsAst) - createCallAst(callNode, argAsts) + callAst(callNode, argAsts) } } @@ -232,7 +232,7 @@ trait AstForExpressionsCreator { this: AstCreator => nonNullExpr.columnNumber ) val argAsts = List(astForNodeWithFunctionReference(nonNullExpr.json("expression"))) - createCallAst(callNode, argAsts) + callAst(callNode, argAsts) } protected def astForCastExpression(castExpr: BabelNodeInfo): Ast = { @@ -244,7 +244,7 @@ trait AstForExpressionsCreator { this: AstCreator => val callNode = createCallNode(castExpr.code, op, DispatchTypes.STATIC_DISPATCH, castExpr.lineNumber, castExpr.columnNumber) val argAsts = List(lhsAst, rhsAst) - createCallAst(callNode, argAsts) + callAst(callNode, argAsts) } protected def astForBinaryExpression(binExpr: BabelNodeInfo): Ast = { @@ -287,7 +287,7 @@ trait AstForExpressionsCreator { this: AstCreator => val callNode = createCallNode(binExpr.code, op, DispatchTypes.STATIC_DISPATCH, binExpr.lineNumber, binExpr.columnNumber) val argAsts = List(lhsAst, rhsAst) - createCallAst(callNode, argAsts) + callAst(callNode, argAsts) } protected def astForUpdateExpression(updateExpr: BabelNodeInfo): Ast = { @@ -307,7 +307,7 @@ trait AstForExpressionsCreator { this: AstCreator => val callNode = createCallNode(updateExpr.code, op, DispatchTypes.STATIC_DISPATCH, updateExpr.lineNumber, updateExpr.columnNumber) val argAsts = List(argumentAst) - createCallAst(callNode, argAsts) + callAst(callNode, argAsts) } protected def astForUnaryExpression(unaryExpr: BabelNodeInfo): Ast = { @@ -330,7 +330,7 @@ trait AstForExpressionsCreator { this: AstCreator => val callNode = createCallNode(unaryExpr.code, op, DispatchTypes.STATIC_DISPATCH, unaryExpr.lineNumber, unaryExpr.columnNumber) val argAsts = List(argumentAst) - createCallAst(callNode, argAsts) + callAst(callNode, argAsts) } protected def astForSequenceExpression(seq: BabelNodeInfo): Ast = { @@ -338,7 +338,7 @@ trait AstForExpressionsCreator { this: AstCreator => scope.pushNewBlockScope(blockNode) localAstParentStack.push(blockNode) val sequenceExpressionAsts = createBlockStatementAsts(seq.json("expressions")) - setArgIndices(sequenceExpressionAsts) + setArgumentIndices(sequenceExpressionAsts) localAstParentStack.pop() scope.popScope() Ast(blockNode).withChildren(sequenceExpressionAsts) @@ -353,7 +353,7 @@ trait AstForExpressionsCreator { this: AstCreator => awaitExpr.columnNumber ) val argAsts = List(astForNodeWithFunctionReference(awaitExpr.json("argument"))) - createCallAst(callNode, argAsts) + callAst(callNode, argAsts) } protected def astForArrayExpression(arrExpr: BabelNodeInfo): Ast = { @@ -421,12 +421,7 @@ trait AstForExpressionsCreator { this: AstCreator => val thisPushNode = createIdentifierNode(tmpName, elementNodeInfo) Option( - createCallAst( - pushCallNode, - List(elementNode), - receiver = Option(receiverNode), - base = Option(Ast(thisPushNode)) - ) + callAst(pushCallNode, List(elementNode), receiver = Option(receiverNode), base = Option(Ast(thisPushNode))) ) case _ => None // skip } @@ -437,7 +432,7 @@ trait AstForExpressionsCreator { this: AstCreator => localAstParentStack.pop() val blockChildrenAsts = List(assignmentTmpArrayCallNode) ++ elementAsts :+ Ast(tmpArrayReturnNode) - setArgIndices(blockChildrenAsts) + setArgumentIndices(blockChildrenAsts) Ast(blockNode).withChildren(blockChildrenAsts) } } @@ -455,7 +450,7 @@ trait AstForExpressionsCreator { this: AstCreator => templateExpr.columnNumber ) val argAsts = List(argumentAst) - createCallAst(templateExprCall, argAsts) + callAst(templateExprCall, argAsts) } protected def astForObjectExpression(objExpr: BabelNodeInfo): Ast = { @@ -520,7 +515,7 @@ trait AstForExpressionsCreator { this: AstCreator => localAstParentStack.pop() val allBlockChildren = propertiesAsts :+ Ast(tmpNode) - setArgIndices(propertiesAsts) + setArgumentIndices(propertiesAsts) Ast(blockNode).withChildren(allBlockChildren) } } diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForFunctionsCreator.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForFunctionsCreator.scala index c0f2eea81240..3c5643235fda 100644 --- a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForFunctionsCreator.scala +++ b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForFunctionsCreator.scala @@ -302,7 +302,7 @@ trait AstForFunctionsCreator { this: AstCreator => val mAst = if (methodBlockContent.isEmpty) { methodStubAst(methodNode, thisNode +: paramNodes, methodReturnNode, List(virtualModifierNode)) } else { - setArgIndices(methodBlockContent) + setArgumentIndices(methodBlockContent) val bodyAst = blockAst(NewBlock(), methodBlockContent) methodAst(methodNode, thisNode +: paramNodes, bodyAst, methodReturnNode) } @@ -375,7 +375,7 @@ trait AstForFunctionsCreator { this: AstCreator => } case _ => createBlockStatementAsts(bodyJson("body")) } - setArgIndices(methodBlockContent ++ additionalBlockStatements.toList ++ bodyStmtAsts) + setArgumentIndices(methodBlockContent ++ additionalBlockStatements.toList ++ bodyStmtAsts) val methodReturnNode = createMethodReturnNode(func) diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForPrimitivesCreator.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForPrimitivesCreator.scala index 2c912755c04b..ce32027c16ad 100644 --- a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForPrimitivesCreator.scala +++ b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForPrimitivesCreator.scala @@ -150,7 +150,7 @@ trait AstForPrimitivesCreator { this: AstCreator => List(astForNodeWithFunctionReference(quasi), astForNodeWithFunctionReference(expression)) } val argAsts = argumentAsts :+ astForNodeWithFunctionReference(quasisTail) - createCallAst(templateCall, argAsts) + callAst(templateCall, argAsts) } } } diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForStatementsCreator.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForStatementsCreator.scala index 83711ecccb30..4d153cec1d1f 100644 --- a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForStatementsCreator.scala +++ b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForStatementsCreator.scala @@ -42,7 +42,7 @@ trait AstForStatementsCreator { this: AstCreator => protected def createBlockStatementAsts(json: Value): List[Ast] = { val blockStmts = sortBlockStatements(json.arr.map(createBabelNodeInfo).toList) val blockAsts = blockStmts.map(stmt => astForNodeWithFunctionReferenceAndCall(stmt.json)) - setArgIndices(blockAsts) + setArgumentIndices(blockAsts) blockAsts } @@ -51,7 +51,7 @@ trait AstForStatementsCreator { this: AstCreator => scope.pushNewBlockScope(blockNode) localAstParentStack.push(blockNode) val blockStatementAsts = createBlockStatementAsts(block.json("body")) - setArgIndices(blockStatementAsts) + setArgumentIndices(blockStatementAsts) localAstParentStack.pop() scope.popScope() Ast(blockNode).withChildren(blockStatementAsts) @@ -173,7 +173,7 @@ trait AstForStatementsCreator { this: AstCreator => localAstParentStack.pop() val labelAsts = List(Ast(labeledNode), bodyAst) - setArgIndices(labelAsts) + setArgumentIndices(labelAsts) Ast(blockNode).withChildren(labelAsts) } @@ -222,7 +222,7 @@ trait AstForStatementsCreator { this: AstCreator => throwStmt.columnNumber ) val argAsts = List(argumentAst) - createCallAst(throwCallNode, argAsts) + callAst(throwCallNode, argAsts) } private def astsForSwitchCase(switchCase: BabelNodeInfo): List[Ast] = { @@ -243,7 +243,7 @@ trait AstForStatementsCreator { this: AstCreator => localAstParentStack.push(blockNode) val casesAsts = switchStmt.json("cases").arr.flatMap(c => astsForSwitchCase(createBabelNodeInfo(c))) - setArgIndices(casesAsts.toList) + setArgumentIndices(casesAsts.toList) scope.popScope() localAstParentStack.pop() @@ -311,7 +311,7 @@ trait AstForStatementsCreator { this: AstCreator => ) val objectKeysCallArgs = List(astForNodeWithFunctionReference(collection)) - val objectKeysCallAst = createCallAst(objectKeysCallNode, objectKeysCallArgs) + val objectKeysCallAst = callAst(objectKeysCallNode, objectKeysCallArgs) val indexBaseNode = createIdentifierNode("Symbol", forInOfStmt) @@ -321,10 +321,10 @@ trait AstForStatementsCreator { this: AstCreator => createFieldAccessCallAst(indexBaseNode, indexMemberNode, forInOfStmt.lineNumber, forInOfStmt.columnNumber) val indexCallArgs = List(objectKeysCallAst, indexAccessNode) - val indexCallAst = createCallAst(indexCallNode, indexCallArgs) + val indexCallAst = callAst(indexCallNode, indexCallArgs) val callNodeArgs = List(Ast(thisNode)) - val callNodeAst = createCallAst(callNode, callNodeArgs, receiver = Option(indexCallAst)) + val callNodeAst = callAst(callNode, callNodeArgs, receiver = Option(indexCallAst)) val iteratorAssignmentNode = createCallNode( @@ -336,7 +336,7 @@ trait AstForStatementsCreator { this: AstCreator => ) val iteratorAssignmentArgs = List(Ast(iteratorNode), callNodeAst) - val iteratorAssignmentAst = createCallAst(iteratorAssignmentNode, iteratorAssignmentArgs) + val iteratorAssignmentAst = callAst(iteratorAssignmentNode, iteratorAssignmentArgs) // _result: val resultName = generateUnusedVariableName(usedVariableNames, "_result") @@ -398,10 +398,10 @@ trait AstForStatementsCreator { this: AstCreator => val thisNextNode = createIdentifierNode(iteratorName, forInOfStmt) val rhsArgs = List(Ast(thisNextNode)) - val rhsAst = createCallAst(rhsNode, rhsArgs, receiver = Option(nextReceiverNode)) + val rhsAst = callAst(rhsNode, rhsArgs, receiver = Option(nextReceiverNode)) val doneBaseArgs = List(Ast(lhsNode), rhsAst) - val doneBaseAst = createCallAst(doneBaseNode, doneBaseArgs) + val doneBaseAst = callAst(doneBaseNode, doneBaseArgs) Ast.storeInDiffGraph(doneBaseAst, diffGraph) val doneMemberNode = createFieldIdentifierNode("done", forInOfStmt.lineNumber, forInOfStmt.columnNumber) @@ -410,7 +410,7 @@ trait AstForStatementsCreator { this: AstCreator => createFieldAccessCallAst(doneBaseNode, doneMemberNode, forInOfStmt.lineNumber, forInOfStmt.columnNumber) val testCallArgs = List(testNode) - val testCallAst = createCallAst(testCallNode, testCallArgs) + val testCallAst = callAst(testCallNode, testCallArgs) val whileLoopAst = Ast(whileLoopNode).withChild(testCallAst).withConditionEdge(whileLoopNode, testCallNode) @@ -432,7 +432,7 @@ trait AstForStatementsCreator { this: AstCreator => ) val loopVariableAssignmentArgs = List(Ast(whileLoopVariableNode), accessAst) - val loopVariableAssignmentAst = createCallAst(loopVariableAssignmentNode, loopVariableAssignmentArgs) + val loopVariableAssignmentAst = callAst(loopVariableAssignmentNode, loopVariableAssignmentArgs) val whileLoopBlockNode = createBlockNode(forInOfStmt) scope.pushNewBlockScope(whileLoopBlockNode) diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForTemplateDomCreator.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForTemplateDomCreator.scala index 8757a13bee99..0df5ecb5717d 100644 --- a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForTemplateDomCreator.scala +++ b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForTemplateDomCreator.scala @@ -16,7 +16,7 @@ trait AstForTemplateDomCreator { this: AstCreator => safeObj(jsxElem.json, "closingElement").fold(Ast())(e => astForNodeWithFunctionReference(Obj(e))) val allChildrenAsts = openingAst +: childrenAsts :+ closingAst - setArgIndices(allChildrenAsts) + setArgumentIndices(allChildrenAsts) Ast(domNode).withChildren(allChildrenAsts) } @@ -29,14 +29,14 @@ trait AstForTemplateDomCreator { this: AstCreator => jsxFragment.columnNumber ) val childrenAsts = astForNodes(jsxFragment.json("children").arr.toList) - setArgIndices(childrenAsts) + setArgumentIndices(childrenAsts) Ast(domNode).withChildren(childrenAsts) } protected def astForJsxAttribute(jsxAttr: BabelNodeInfo): Ast = { val domNode = createTemplateDomNode(jsxAttr.node.toString, jsxAttr.code, jsxAttr.lineNumber, jsxAttr.columnNumber) val valueAst = safeObj(jsxAttr.json, "value").fold(Ast())(e => astForNodeWithFunctionReference(Obj(e))) - setArgIndices(List(valueAst)) + setArgumentIndices(List(valueAst)) Ast(domNode).withChild(valueAst) } @@ -48,7 +48,7 @@ trait AstForTemplateDomCreator { this: AstCreator => jsxOpeningElem.columnNumber ) val childrenAsts = astForNodes(jsxOpeningElem.json("attributes").arr.toList) - setArgIndices(childrenAsts) + setArgumentIndices(childrenAsts) Ast(domNode).withChildren(childrenAsts) } @@ -77,7 +77,7 @@ trait AstForTemplateDomCreator { this: AstCreator => case JSXEmptyExpression => Ast() case _ => astForNodeWithFunctionReference(nodeInfo.json) } - setArgIndices(List(exprAst)) + setArgumentIndices(List(exprAst)) Ast(domNode).withChild(exprAst) } @@ -89,7 +89,7 @@ trait AstForTemplateDomCreator { this: AstCreator => jsxSpreadAttr.columnNumber ) val argAst = astForNodeWithFunctionReference(jsxSpreadAttr.json("argument")) - setArgIndices(List(argAst)) + setArgumentIndices(List(argAst)) Ast(domNode).withChild(argAst) } diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForTypesCreator.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForTypesCreator.scala index 65badf3b8886..5f91caa4f993 100644 --- a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForTypesCreator.scala +++ b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForTypesCreator.scala @@ -153,7 +153,7 @@ trait AstForTypesCreator { this: AstCreator => tsEnumMember.columnNumber ) val argAsts = List(lhsAst, rhsAst) - Seq(createCallAst(callNode, argAsts), Ast(memberNode)) + Seq(callAst(callNode, argAsts), Ast(memberNode)) } else { Seq(Ast(memberNode)) } @@ -191,7 +191,7 @@ trait AstForTypesCreator { this: AstCreator => nodeInfo.columnNumber ) val argAsts = List(lhsAst, rhsAst) - createCallAst(callNode, argAsts) + callAst(callNode, argAsts) } else { Ast() } diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstNodeBuilder.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstNodeBuilder.scala index 2c0dda8e5369..41d4721e50ca 100644 --- a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstNodeBuilder.scala +++ b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstNodeBuilder.scala @@ -72,45 +72,8 @@ trait AstNodeBuilder { this: AstCreator => ast.root.foreach { case expr: ExpressionNew => expr.order = order } } - protected def setArgIndices(asts: List[Ast], base: Option[Ast] = None): Unit = { - var currIndex = 1 - - asts.foreach { a => - a.root match { - case Some(x: ExpressionNew) => - x.argumentIndex = currIndex - currIndex = currIndex + 1 - case None => // do nothing - case _ => - currIndex = currIndex + 1 - } - } - base.flatMap(_.root).foreach { case expr: ExpressionNew => expr.argumentIndex = 0 } - } - - protected def createCallAst( - callNode: NewCall, - arguments: List[Ast], - receiver: Option[Ast] = None, - base: Option[Ast] = None - ): Ast = { - setArgIndices(arguments, base = base) - - val receiverRoot = receiver.flatMap(_.root).toList - val rcvAst = receiver.getOrElse(Ast()) - val baseRoot = base.flatMap(_.root).toList - val baseAst = base.getOrElse(Ast()) - Ast(callNode) - .withChild(rcvAst) - .withChild(baseAst) - .withChildren(arguments) - .withArgEdges(callNode, arguments.flatMap(_.root)) - .withArgEdges(callNode, baseRoot) - .withReceiverEdges(callNode, receiverRoot) - } - protected def createReturnAst(returnNode: NewReturn, arguments: List[Ast] = List()): Ast = { - setArgIndices(arguments) + setArgumentIndices(arguments) Ast(returnNode) .withChildren(arguments) .withArgEdges(returnNode, arguments.flatMap(_.root)) @@ -222,7 +185,7 @@ trait AstNodeBuilder { this: AstCreator => column ) val arguments = List(Ast(baseNode), Ast(partNode)) - createCallAst(callNode, arguments) + callAst(callNode, arguments) } protected def createIndexAccessCallAst( @@ -239,7 +202,7 @@ trait AstNodeBuilder { this: AstCreator => column ) val arguments = List(baseAst, partAst) - createCallAst(callNode, arguments) + callAst(callNode, arguments) } protected def createFieldAccessCallAst( @@ -256,7 +219,7 @@ trait AstNodeBuilder { this: AstCreator => column ) val arguments = List(Ast(baseNode), Ast(partNode)) - createCallAst(callNode, arguments) + callAst(callNode, arguments) } protected def createFieldAccessCallAst( @@ -273,7 +236,7 @@ trait AstNodeBuilder { this: AstCreator => column ) val arguments = List(baseAst, Ast(partNode)) - createCallAst(callNode, arguments) + callAst(callNode, arguments) } protected def createTernaryCallAst( @@ -286,7 +249,7 @@ trait AstNodeBuilder { this: AstCreator => val code = s"${codeOf(testAst.nodes.head)} ? ${codeOf(trueAst.nodes.head)} : ${codeOf(falseAst.nodes.head)}" val callNode = createCallNode(code, Operators.conditional, DispatchTypes.STATIC_DISPATCH, line, column) val arguments = List(testAst, trueAst, falseAst) - createCallAst(callNode, arguments) + callAst(callNode, arguments) } protected def createCallNode( @@ -344,7 +307,7 @@ trait AstNodeBuilder { this: AstCreator => val code = s"${codeOf(dest.nodes.head)} === ${codeOf(source.nodes.head)}" val callNode = createCallNode(code, Operators.equals, DispatchTypes.STATIC_DISPATCH, line, column) val arguments = List(dest, source) - createCallAst(callNode, arguments) + callAst(callNode, arguments) } protected def createAssignmentCallAst( @@ -356,7 +319,7 @@ trait AstNodeBuilder { this: AstCreator => ): Ast = { val callNode = createCallNode(code, Operators.assignment, DispatchTypes.STATIC_DISPATCH, line, column) val arguments = List(Ast(destId), Ast(sourceId)) - createCallAst(callNode, arguments) + callAst(callNode, arguments) } protected def createAssignmentCallAst( @@ -368,7 +331,7 @@ trait AstNodeBuilder { this: AstCreator => ): Ast = { val callNode = createCallNode(code, Operators.assignment, DispatchTypes.STATIC_DISPATCH, line, column) val arguments = List(dest, source) - createCallAst(callNode, arguments) + callAst(callNode, arguments) } protected def createIdentifierNode(name: String, node: BabelNodeInfo): NewIdentifier = { diff --git a/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/passes/KtPsiToAst.scala b/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/passes/KtPsiToAst.scala index 76bb77906dcb..62e858fa6272 100644 --- a/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/passes/KtPsiToAst.scala +++ b/joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/passes/KtPsiToAst.scala @@ -807,7 +807,7 @@ trait KtPsiToAst { val componentNIdentifierAst = astWithRefEdgeMaybe(componentNIdentifierNode.name, componentNIdentifierNode) val componentNAst = - callAst(componentNCallNode, Seq(), Some(componentNIdentifierAst), withRecvArgEdge = true) + callAst(componentNCallNode, Seq(), Some(componentNIdentifierAst)) val assignmentCallNode = operatorCallNode( Operators.assignment, @@ -945,7 +945,7 @@ trait KtPsiToAst { ), argIdx ) - callAst(node, argAsts, Some(receiverAst), withRecvArgEdge = true) + callAst(node, argAsts, Some(receiverAst)) } private def selectorExpressionArgAsts( @@ -989,7 +989,7 @@ trait KtPsiToAst { ), argIdx ) - callAst(node, argAsts, Some(receiverAst), withRecvArgEdge = true) + callAst(node, argAsts, Some(receiverAst)) } private def astForQualifiedExpressionWithNoAstForReceiver(expr: KtQualifiedExpression, argIdx: Option[Int])(implicit @@ -1215,7 +1215,7 @@ trait KtPsiToAst { ) val iteratorAssignmentRhsAst = - callAst(iteratorAssignmentRhs, Seq(), Some(Ast(iteratorAssignmentRhsIdentifier)), withRecvArgEdge = true) + callAst(iteratorAssignmentRhs, Seq(), Some(Ast(iteratorAssignmentRhsIdentifier))) val iteratorAssignment = operatorCallNode(Operators.assignment, s"$iteratorName = ${iteratorAssignmentRhs.code}", None) @@ -1235,7 +1235,7 @@ trait KtPsiToAst { DispatchTypes.DYNAMIC_DISPATCH ).argumentIndex(0) val controlStructureConditionAst = - callAst(controlStructureCondition, List(), Some(Ast(conditionIdentifier)), withRecvArgEdge = true) + callAst(controlStructureCondition, List(), Some(Ast(conditionIdentifier))) val loopParameterTypeFullName = registerType( typeInfoProvider.typeFullName(expr.getLoopParameter, TypeConstants.any) @@ -1259,7 +1259,7 @@ trait KtPsiToAst { DispatchTypes.DYNAMIC_DISPATCH ) val iteratorNextCallAst = - callAst(iteratorNextCall, Seq(), Some(iteratorNextIdentifierAst), withRecvArgEdge = true) + callAst(iteratorNextCall, Seq(), Some(iteratorNextIdentifierAst)) val loopParameterNextAssignment = operatorCallNode(Operators.assignment, s"$loopParameterName = ${iteratorNextCall.code}", None) val loopParameterNextAssignmentAst = @@ -1316,7 +1316,7 @@ trait KtPsiToAst { ) val iteratorAssignmentRhsAst = - callAst(iteratorAssignmentRhs, Seq(), Some(Ast(iteratorAssignmentRhsIdentifier)), withRecvArgEdge = true) + callAst(iteratorAssignmentRhs, Seq(), Some(Ast(iteratorAssignmentRhsIdentifier))) val iteratorAssignment = operatorCallNode(Operators.assignment, s"$iteratorName = ${iteratorAssignmentRhs.code}", None) @@ -1336,7 +1336,7 @@ trait KtPsiToAst { DispatchTypes.DYNAMIC_DISPATCH ).argumentIndex(0) val controlStructureConditionAst = - callAst(controlStructureCondition, List(), Some(Ast(conditionIdentifier)), withRecvArgEdge = true) + callAst(controlStructureCondition, List(), Some(Ast(conditionIdentifier))) val destructuringDeclEntries = expr.getDestructuringDeclaration.getEntries val localsForDestructuringVars = destructuringDeclEntries.asScala.map { entry => @@ -1367,7 +1367,7 @@ trait KtPsiToAst { ) val iteratorNextCallAst = - callAst(iteratorNextCall, Seq(), Some(iteratorNextIdentifierAst), withRecvArgEdge = true) + callAst(iteratorNextCall, Seq(), Some(iteratorNextIdentifierAst)) val tmpParameterNextAssignment = operatorCallNode(Operators.assignment, s"$tmpName = ${iteratorNextCall.code}") val tmpParameterNextAssignmentAst = callAst(tmpParameterNextAssignment, List(tmpIdentifierAst, iteratorNextCallAst)) @@ -1500,7 +1500,7 @@ trait KtPsiToAst { line(expr), column(expr) ) - val initCallAst = callAst(initCallNode, argAsts, Some(initReceiverAst), withRecvArgEdge = true) + val initCallAst = callAst(initCallNode, argAsts, Some(initReceiverAst)) val lastIdentifier = identifierNode(tmpName, typeFullName, line(expr), column(expr)) val lastIdentifierAst = Ast(lastIdentifier) @@ -1556,7 +1556,7 @@ trait KtPsiToAst { astsForExpression(arg.getArgumentExpression, Some(idx), argNameOpt) }.flatten - val initAst = callAst(initCallNode, argAsts, Some(initReceiverAst), withRecvArgEdge = true) + val initAst = callAst(initCallNode, argAsts, Some(initReceiverAst)) Seq(localAst, assignmentCallAst, initAst) } else { val rhsAsts = astsForExpression(expr.getDelegateExpressionOrInitializer, Some(2)) diff --git a/joern-cli/frontends/kotlin2cpg/src/test/scala/io/joern/kotlin2cpg/querying/ControlStructureTests.scala b/joern-cli/frontends/kotlin2cpg/src/test/scala/io/joern/kotlin2cpg/querying/ControlStructureTests.scala index 6d4e8f0de00c..6c2494a30103 100644 --- a/joern-cli/frontends/kotlin2cpg/src/test/scala/io/joern/kotlin2cpg/querying/ControlStructureTests.scala +++ b/joern-cli/frontends/kotlin2cpg/src/test/scala/io/joern/kotlin2cpg/querying/ControlStructureTests.scala @@ -268,7 +268,6 @@ class ControlStructureTests extends KotlinCode2CpgFixture(withOssDataflow = fals controlStructureFirstChild.order shouldBe 1 controlStructureFirstChild.dispatchType shouldBe DispatchTypes.DYNAMIC_DISPATCH controlStructureFirstChild.methodFullName shouldBe "kotlin.collections.Iterator.hasNext:boolean()" - controlStructureFirstChild.receiver.size shouldBe 1 controlStructureFirstChild.name shouldBe "hasNext" controlStructureFirstChild.signature shouldBe "boolean()" controlStructureSecondChild.order shouldBe 2 @@ -294,7 +293,6 @@ class ControlStructureTests extends KotlinCode2CpgFixture(withOssDataflow = fals getNextSecondArg.name shouldBe "next" getNextSecondArg.signature shouldBe "java.lang.Object()" getNextSecondArg.dispatchType shouldBe DispatchTypes.DYNAMIC_DISPATCH - getNextSecondArg.receiver.size shouldBe 1 val List(getNextSecondArgFirstArg: Identifier) = getNextSecondArg.argument.l getNextSecondArgFirstArg.order shouldBe 1 @@ -383,7 +381,6 @@ class ControlStructureTests extends KotlinCode2CpgFixture(withOssDataflow = fals controlStructureFirstChild.order shouldBe 1 controlStructureFirstChild.dispatchType shouldBe DispatchTypes.DYNAMIC_DISPATCH controlStructureFirstChild.methodFullName shouldBe "kotlin.collections.Iterator.hasNext:boolean()" - controlStructureFirstChild.receiver.size shouldBe 1 controlStructureFirstChild.name shouldBe "hasNext" controlStructureFirstChild.signature shouldBe "boolean()" controlStructureSecondChild.order shouldBe 2 @@ -436,7 +433,6 @@ class ControlStructureTests extends KotlinCode2CpgFixture(withOssDataflow = fals getNextSecondArg.name shouldBe "next" getNextSecondArg.signature shouldBe "java.lang.Object()" getNextSecondArg.dispatchType shouldBe DispatchTypes.DYNAMIC_DISPATCH - getNextSecondArg.receiver.size shouldBe 1 val List(getNextSecondArgFirstArg: Identifier) = getNextSecondArg.argument.l getNextSecondArgFirstArg.order shouldBe 1 @@ -458,7 +454,6 @@ class ControlStructureTests extends KotlinCode2CpgFixture(withOssDataflow = fals component1SecondArg.name shouldBe "component1" component1SecondArg.signature shouldBe "java.lang.String()" component1SecondArg.dispatchType shouldBe DispatchTypes.DYNAMIC_DISPATCH - component1SecondArg.receiver.size shouldBe 1 val List(tmpInComponent1Call: Identifier) = component1SecondArg.argument.l tmp.referencingIdentifiers.id.l.contains(tmpInComponent1Call.id) shouldBe true @@ -476,7 +471,6 @@ class ControlStructureTests extends KotlinCode2CpgFixture(withOssDataflow = fals component2SecondArg.name shouldBe "component2" component2SecondArg.signature shouldBe "int()" component2SecondArg.dispatchType shouldBe DispatchTypes.DYNAMIC_DISPATCH - component2SecondArg.receiver.size shouldBe 1 val List(tmpInComponent2Call: Identifier) = component2SecondArg.argument.l tmp.referencingIdentifiers.id.l.contains(tmpInComponent2Call.id) shouldBe true diff --git a/joern-cli/frontends/php2cpg/src/main/scala/io/joern/php2cpg/astcreation/AstCreator.scala b/joern-cli/frontends/php2cpg/src/main/scala/io/joern/php2cpg/astcreation/AstCreator.scala index 26a04197efc4..aa52d4a1a067 100644 --- a/joern-cli/frontends/php2cpg/src/main/scala/io/joern/php2cpg/astcreation/AstCreator.scala +++ b/joern-cli/frontends/php2cpg/src/main/scala/io/joern/php2cpg/astcreation/AstCreator.scala @@ -601,7 +601,7 @@ class AstCreator(filename: String, phpAst: PhpFile, global: Global) extends AstC .code(s"${nextIterIdent.rootCodeOrEmpty}->next()") .dispatchType(DispatchTypes.DYNAMIC_DISPATCH) .lineNumber(line(stmt)) - val nextCallAst = callAst(nextCallNode, receiver = Some(nextIterIdent)) + val nextCallAst = callAst(nextCallNode, base = Some(nextIterIdent)) val itemUpdateAst = itemInitAst.root match { case Some(initRoot: AstNodeNew) => itemInitAst.subTreeCopy(initRoot) case _ => @@ -636,7 +636,7 @@ class AstCreator(filename: String, phpAst: PhpFile, global: Global) extends AstC .code(s"${iteratorIdentifierAst.rootCodeOrEmpty}->current()") .dispatchType(DispatchTypes.DYNAMIC_DISPATCH) .lineNumber(line(stmt)) - val currentCallAst = callAst(currentCallNode, receiver = Some(iteratorIdentifierAst)) + val currentCallAst = callAst(currentCallNode, base = Some(iteratorIdentifierAst)) val valueAst = if (stmt.assignByRef) { val addressOfCode = s"&${currentCallAst.rootCodeOrEmpty}" @@ -1046,7 +1046,7 @@ class AstCreator(filename: String, phpAst: PhpFile, global: Global) extends AstC case (None, None) => None } - callAst(callNode, arguments, receiver = receiverAst) + callAst(callNode, arguments, base = receiverAst) } private def astForCallArg(arg: PhpArgument): Ast = { @@ -1533,7 +1533,7 @@ class AstCreator(filename: String, phpAst: PhpFile, global: Global) extends AstC // Alloc assign val allocCode = s"$className.()" val allocNode = operatorCallNode(Operators.alloc, allocCode, Some(className), line(expr)) - val allocAst = callAst(allocNode, receiver = maybeNameAst) + val allocAst = callAst(allocNode, base = maybeNameAst) val allocAssignCode = s"${tmpLocal.code} = ${allocAst.rootCodeOrEmpty}" val allocAssignNode = operatorCallNode(Operators.assignment, allocAssignCode, Some(className), line(expr)) val allocAssignIdentifier = identifierAstFromLocal(tmpLocal, line(expr)) @@ -1553,7 +1553,7 @@ class AstCreator(filename: String, phpAst: PhpFile, global: Global) extends AstC .dispatchType(DispatchTypes.DYNAMIC_DISPATCH) .lineNumber(line(expr)) val initReceiver = identifierAstFromLocal(tmpLocal, line(expr)) - val initCallAst = callAst(initCallNode, initArgs, receiver = Some(initReceiver)) + val initCallAst = callAst(initCallNode, initArgs, base = Some(initReceiver)) // Return identifier val returnIdentifierAst = identifierAstFromLocal(tmpLocal, line(expr)) diff --git a/joern-cli/frontends/php2cpg/src/test/scala/io/joern/php2cpg/querying/CallTests.scala b/joern-cli/frontends/php2cpg/src/test/scala/io/joern/php2cpg/querying/CallTests.scala index 72af82d7fb58..87229a25a121 100644 --- a/joern-cli/frontends/php2cpg/src/test/scala/io/joern/php2cpg/querying/CallTests.scala +++ b/joern-cli/frontends/php2cpg/src/test/scala/io/joern/php2cpg/querying/CallTests.scala @@ -76,13 +76,10 @@ class CallTests extends PhpCode2CpgFixture { fooCall.lineNumber shouldBe Some(2) fooCall.code shouldBe "$f->foo($x)" - inside(fooCall.receiver.l) { case List(fRecv: Identifier) => + inside(fooCall.argument.l) { case List(fRecv: Identifier, xArg: Identifier) => fRecv.name shouldBe "f" fRecv.code shouldBe "$f" fRecv.lineNumber shouldBe Some(2) - } - - inside(fooCall.argument.l) { case List(xArg: Identifier) => xArg.name shouldBe "x" xArg.code shouldBe "$x" } @@ -99,7 +96,7 @@ class CallTests extends PhpCode2CpgFixture { fooCall.lineNumber shouldBe Some(2) fooCall.code shouldBe "$$f->$foo($x)" - inside(fooCall.receiver.l) { case List(fRecv: Call) => + inside(fooCall.argument.l) { case List(fRecv: Call, xArg: Identifier) => fRecv.name shouldBe Operators.fieldAccess fRecv.code shouldBe "$$f->$foo" fRecv.lineNumber shouldBe Some(2) @@ -111,9 +108,7 @@ class CallTests extends PhpCode2CpgFixture { fooVar.name shouldBe "foo" fooVar.code shouldBe "$foo" } - } - inside(fooCall.argument.l) { case List(xArg: Identifier) => xArg.name shouldBe "x" xArg.code shouldBe "$x" } diff --git a/joern-cli/frontends/php2cpg/src/test/scala/io/joern/php2cpg/querying/ControlStructureTests.scala b/joern-cli/frontends/php2cpg/src/test/scala/io/joern/php2cpg/querying/ControlStructureTests.scala index f415a9f0ec31..cc4333ac3117 100644 --- a/joern-cli/frontends/php2cpg/src/test/scala/io/joern/php2cpg/querying/ControlStructureTests.scala +++ b/joern-cli/frontends/php2cpg/src/test/scala/io/joern/php2cpg/querying/ControlStructureTests.scala @@ -1071,7 +1071,7 @@ class ControlStructureTests extends PhpCode2CpgFixture { currentCall.name shouldBe "current" currentCall.methodFullName shouldBe s"Iterator.current:${Defines.UnresolvedSignature}(0)" currentCall.code shouldBe "$iter_tmp0->current()" - inside(currentCall.receiver.l) { case List(iterRecv: Identifier) => + inside(currentCall.argument(0).l) { case List(iterRecv: Identifier) => iterRecv.name shouldBe "iter_tmp0" iterRecv.argumentIndex shouldBe 0 } @@ -1089,7 +1089,7 @@ class ControlStructureTests extends PhpCode2CpgFixture { nextCall.name shouldBe "next" nextCall.methodFullName shouldBe "Iterator.next:void()" nextCall.code shouldBe "$iter_tmp0->next()" - inside(nextCall.receiver.l) { case List(iterTmp: Identifier) => + inside(nextCall.argument(0).l) { case List(iterTmp: Identifier) => iterTmp.name shouldBe "iter_tmp0" iterTmp.code shouldBe "$iter_tmp0" iterTmp.argumentIndex shouldBe 0 @@ -1143,7 +1143,7 @@ class ControlStructureTests extends PhpCode2CpgFixture { currentCall.name shouldBe "current" currentCall.methodFullName shouldBe s"Iterator.current:${Defines.UnresolvedSignature}(0)" currentCall.code shouldBe "$iter_tmp0->current()" - inside(currentCall.receiver.l) { case List(iterRecv: Identifier) => + inside(currentCall.argument(0).l) { case List(iterRecv: Identifier) => iterRecv.name shouldBe "iter_tmp0" iterRecv.argumentIndex shouldBe 0 } @@ -1200,7 +1200,7 @@ class ControlStructureTests extends PhpCode2CpgFixture { currentCall.name shouldBe "current" currentCall.methodFullName shouldBe s"Iterator.current:${Defines.UnresolvedSignature}(0)" currentCall.code shouldBe "$iter_tmp0->current()" - inside(currentCall.receiver.l) { case List(iterRecv: Identifier) => + inside(currentCall.argument(0).l) { case List(iterRecv: Identifier) => iterRecv.name shouldBe "iter_tmp0" iterRecv.argumentIndex shouldBe 0 } diff --git a/joern-cli/frontends/php2cpg/src/test/scala/io/joern/php2cpg/querying/TypeDeclTests.scala b/joern-cli/frontends/php2cpg/src/test/scala/io/joern/php2cpg/querying/TypeDeclTests.scala index da55359bc27f..4417e3470680 100644 --- a/joern-cli/frontends/php2cpg/src/test/scala/io/joern/php2cpg/querying/TypeDeclTests.scala +++ b/joern-cli/frontends/php2cpg/src/test/scala/io/joern/php2cpg/querying/TypeDeclTests.scala @@ -79,13 +79,11 @@ class TypeDeclTests extends PhpCode2CpgFixture { initCall.methodFullName shouldBe s"Foo.:${Defines.UnresolvedSignature}(1)" initCall.signature shouldBe s"${Defines.UnresolvedSignature}(1)" initCall.code shouldBe "Foo.(42)" - inside(initCall.receiver.l) { case List(tmpIdentifier: Identifier) => + inside(initCall.argument.l) { case List(tmpIdentifier: Identifier, literal: Literal) => tmpIdentifier.name shouldBe "tmp0" tmpIdentifier.code shouldBe "$tmp0" tmpIdentifier.argumentIndex shouldBe 0 tmpIdentifier._localViaRefOut should contain(tmpLocal) - } - inside(initCall.argument.l) { case List(literal: Literal) => literal.code shouldBe "42" literal.argumentIndex shouldBe 1 } @@ -104,7 +102,7 @@ class TypeDeclTests extends PhpCode2CpgFixture { alloc.name shouldBe Operators.alloc alloc.methodFullName shouldBe Operators.alloc alloc.code shouldBe "$x.()" - inside(alloc.receiver.l) { case List(xIdentifier: Identifier) => + inside(alloc.argument(0).l) { case List(xIdentifier: Identifier) => xIdentifier.name shouldBe "x" xIdentifier.code shouldBe "$x" } diff --git a/joern-cli/frontends/x2cpg/src/main/scala/io/joern/x2cpg/AstCreatorBase.scala b/joern-cli/frontends/x2cpg/src/main/scala/io/joern/x2cpg/AstCreatorBase.scala index 04df76336096..8c773d5afe81 100644 --- a/joern-cli/frontends/x2cpg/src/main/scala/io/joern/x2cpg/AstCreatorBase.scala +++ b/joern-cli/frontends/x2cpg/src/main/scala/io/joern/x2cpg/AstCreatorBase.scala @@ -197,38 +197,64 @@ abstract class AstCreatorBase(filename: String) { Ast(blockNode).withChildren(statements) } - /** For a given call node, arguments, and optionally, a receiver, create an AST that represents the call site. The - * main purpose of this method is to automatically assign the correct argument indices. + /** Create an abstract syntax tree for a call, including CPG-specific edges required for arguments and the receiver. + * + * Our call representation is inspired by ECMAScript, that is, in addition to arguments, a call has a base and a + * receiver. For languages other than Javascript, leave `receiver` empty for now. + * + * @param callNode + * the node that represents the entire call + * @param arguments + * arguments (without the base argument (instance)) + * @param base + * the value to use as `this` in the method call. + * @param receiver + * the object in which the property lookup is performed */ def callAst( callNode: NewCall, arguments: Seq[Ast] = List(), - receiver: Option[Ast] = None, - withRecvArgEdge: Boolean = false + base: Option[Ast] = None, + receiver: Option[Ast] = None ): Ast = { - val receiverRoot = receiver.flatMap(_.root).toList - val rcv = receiver.getOrElse(Ast()) - receiverRoot match { + + setArgumentIndices(arguments) + + val baseRoot = base.flatMap(_.root).toList + val bse = base.getOrElse(Ast()) + baseRoot match { case List(x: ExpressionNew) => x.argumentIndex = 0 case _ => } - val recvArgEdgeDest = if (withRecvArgEdge) receiverRoot else Nil + val receiverRoot = receiver.flatMap(_.root).toList + val rcvAst = receiver.getOrElse(Ast()) + receiverRoot match { + case List(x: ExpressionNew) => + x.argumentIndex = -1 + case _ => + } - setArgumentIndices(arguments) Ast(callNode) - .withChild(rcv) + .withChild(rcvAst) + .withChild(bse) .withChildren(arguments) - .withArgEdges(callNode, recvArgEdgeDest) + .withArgEdges(callNode, baseRoot) .withArgEdges(callNode, arguments.flatMap(_.root)) .withReceiverEdges(callNode, receiverRoot) } def setArgumentIndices(arguments: Seq[Ast]): Unit = { - withIndex(arguments) { case (a, i) => - a.root.collect { case x: ExpressionNew => - x.argumentIndex = i + var currIndex = 1 + arguments.foreach { a => + a.root match { + case Some(x: ExpressionNew) => + x.argumentIndex = currIndex + currIndex = currIndex + 1 + case None => // do nothing + case _ => + currIndex = currIndex + 1 } } }