From 860f3987cc78819f2287c62f8de9185fd4767915 Mon Sep 17 00:00:00 2001 From: Pandurang Patil Date: Wed, 25 Oct 2023 12:33:57 +0530 Subject: [PATCH] [gosrc2cpg] - Global variable as member nodes of package level TypeDecl (#3756) Follow up PR to the PR #3734 to model global variables as member nodes of Package level TypeDecl, and its access is converted to `field access` call. --- .../gosrc2cpg/astcreation/AstCreator.scala | 13 +++- .../AstForGenDeclarationCreator.scala | 76 ++++++++++++++----- .../astcreation/AstForPrimitivesCreator.scala | 32 +++++++- .../astcreation/AstForTypeDeclCreator.scala | 14 ++-- .../gosrc2cpg/astcreation/CacheBuilder.scala | 5 +- .../gosrc2cpg/datastructures/GoGlobal.scala | 1 - .../MethodAndTypeCacheBuilderPass.scala | 8 +- .../go2cpg/passes/ast/ArraysAndMapTests.scala | 35 ++++----- .../ast/GlobalVariableAndConstantTests.scala | 17 ++++- .../joern/go2cpg/passes/ast/MethodTests.scala | 18 +++-- .../passes/ast/VariableReferencingTests.scala | 25 +++--- 11 files changed, 156 insertions(+), 88 deletions(-) diff --git a/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/astcreation/AstCreator.scala b/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/astcreation/AstCreator.scala index bd10d3fa39f6..d8923e1821c4 100644 --- a/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/astcreation/AstCreator.scala +++ b/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/astcreation/AstCreator.scala @@ -63,15 +63,22 @@ class AstCreator(val relPathFileName: String, val parserResult: ParserResult, go scope.pushNewScope(fakeGlobalMethodForFile) val blockNode_ = blockNode(rootNode, Defines.empty, Defines.anyTypeName) val methodReturn = methodReturnNode(rootNode, Defines.anyTypeName) - val declsAsts = rootNode.json(ParserKeys.Decls).arr.flatMap(item => astForNode(item)).toList + val declsAsts = rootNode + .json(ParserKeys.Decls) + .arr + .flatMap { item => + val node = createParserNodeInfo(item) + astForNode(node, true) + } + .toList methodAstParentStack.pop() scope.popScope() methodAst(fakeGlobalMethodForFile, Seq.empty, blockAst(blockNode_, declsAsts), methodReturn) } - protected def astForNode(nodeInfo: ParserNodeInfo): Seq[Ast] = { + protected def astForNode(nodeInfo: ParserNodeInfo, globalStatements: Boolean = false): Seq[Ast] = { nodeInfo.node match { - case GenDecl => astForGenDecl(nodeInfo) + case GenDecl => astForGenDecl(nodeInfo, globalStatements) case FuncDecl => astForFuncDecl(nodeInfo) case _: BasePrimitive => astForPrimitive(nodeInfo) case _: BaseExpr => astsForExpression(nodeInfo) diff --git a/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/astcreation/AstForGenDeclarationCreator.scala b/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/astcreation/AstForGenDeclarationCreator.scala index 603e3690aa24..a466b1021bc1 100644 --- a/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/astcreation/AstForGenDeclarationCreator.scala +++ b/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/astcreation/AstForGenDeclarationCreator.scala @@ -5,13 +5,13 @@ import io.joern.gosrc2cpg.parser.ParserAst.* import io.joern.gosrc2cpg.parser.{ParserKeys, ParserNodeInfo} import io.joern.x2cpg import io.joern.x2cpg.{Ast, ValidationMode} -import io.shiftleft.codepropertygraph.generated.{DispatchTypes, Operators} +import io.shiftleft.codepropertygraph.generated.{DispatchTypes, NodeTypes, Operators} import ujson.Value import scala.util.{Success, Try} trait AstForGenDeclarationCreator(implicit withSchemaValidation: ValidationMode) { this: AstCreator => - def astForGenDecl(genDecl: ParserNodeInfo): Seq[Ast] = { + def astForGenDecl(genDecl: ParserNodeInfo, globalStatements: Boolean = false): Seq[Ast] = { Try( genDecl .json(ParserKeys.Specs) @@ -24,7 +24,7 @@ trait AstForGenDeclarationCreator(implicit withSchemaValidation: ValidationMode) genDeclNode.node match case ImportSpec => astForImport(genDeclNode) case TypeSpec => astForTypeSpec(genDeclNode) - case ValueSpec => astForValueSpec(genDeclNode) + case ValueSpec => astForValueSpec(genDeclNode, globalStatements = globalStatements) case _ => Seq[Ast]() } .toSeq @@ -41,7 +41,11 @@ trait AstForGenDeclarationCreator(implicit withSchemaValidation: ValidationMode) Seq(Ast(newImportNode(s"import $importedAsReplacement$importedEntity", importedEntity, importedAs, basicLit))) } - protected def astForValueSpec(valueSpec: ParserNodeInfo, recordVar: Boolean = false): Seq[Ast] = { + protected def astForValueSpec( + valueSpec: ParserNodeInfo, + recordVar: Boolean = false, + globalStatements: Boolean = false + ): Seq[Ast] = { val typeFullName = Try(valueSpec.json(ParserKeys.Type)) match case Success(typeJson) => val (typeFullName, _, _, _) = processTypeInfo(createParserNodeInfo(typeJson)) @@ -54,17 +58,29 @@ trait AstForGenDeclarationCreator(implicit withSchemaValidation: ValidationMode) (valueSpec.json(ParserKeys.Names).arr.toList zip valueSpec.json(ParserKeys.Values).arr.toList) .map { case (lhs, rhs) => (createParserNodeInfo(lhs), createParserNodeInfo(rhs)) } .map { case (lhsParserNode, rhsParserNode) => - astForAssignmentCallNode(lhsParserNode, rhsParserNode, typeFullName, valueSpec.code, recordVar) + astForAssignmentCallNode( + lhsParserNode, + rhsParserNode, + typeFullName, + valueSpec.code, + recordVar, + globalStatements + ) } .unzip - localAsts ++: assCallAsts + if globalStatements then Seq.empty else localAsts ++: assCallAsts case _ => valueSpec .json(ParserKeys.Names) .arr .flatMap { parserNode => val localParserNode = createParserNodeInfo(parserNode) - Seq(astForLocalNode(localParserNode, typeFullName, recordVar)) ++: astForNode(localParserNode) + if globalStatements then { + astForGlobalVarAndConstants(typeFullName.getOrElse(Defines.anyTypeName), localParserNode) + Seq.empty + } else { + Seq(astForLocalNode(localParserNode, typeFullName, recordVar)) ++: astForNode(localParserNode) + } } .toSeq @@ -75,23 +91,43 @@ trait AstForGenDeclarationCreator(implicit withSchemaValidation: ValidationMode) rhsParserNode: ParserNodeInfo, typeFullName: Option[String], code: String, - recordVar: Boolean = false + recordVar: Boolean = false, + globalStatements: Boolean = false ): (Ast, Ast) = { val rhsAst = astForBooleanLiteral(rhsParserNode) val rhsTypeFullName = typeFullName.getOrElse(getTypeFullNameFromAstNode(rhsAst)) - val localAst = astForLocalNode(lhsParserNode, Some(rhsTypeFullName), recordVar) - val lhsAst = astForNode(lhsParserNode) - val arguments = lhsAst ++: rhsAst - val cNode = callNode( - rhsParserNode, - code, - Operators.assignment, - Operators.assignment, - DispatchTypes.STATIC_DISPATCH, - None, - Some(rhsTypeFullName) + if (globalStatements) { + astForGlobalVarAndConstants(rhsTypeFullName, lhsParserNode, Some(rhsAst)) + (Ast(), Ast()) + } else { + val localAst = astForLocalNode(lhsParserNode, Some(rhsTypeFullName), recordVar) + val lhsAst = astForNode(lhsParserNode) + val arguments = lhsAst ++: rhsAst + val cNode = callNode( + rhsParserNode, + code, + Operators.assignment, + Operators.assignment, + DispatchTypes.STATIC_DISPATCH, + None, + Some(rhsTypeFullName) + ) + (callAst(cNode, arguments), localAst) + } + } + + private def astForGlobalVarAndConstants( + typeFullName: String, + lhsParserNode: ParserNodeInfo, + rhsAst: Option[Seq[Ast]] = None + ): Unit = { + val name = lhsParserNode.json(ParserKeys.Name).str + val memberAst = Ast( + memberNode(lhsParserNode, name, lhsParserNode.code, typeFullName) + .astParentType(NodeTypes.TYPE_DECL) + .astParentFullName(fullyQualifiedPackage) ) - (callAst(cNode, arguments), localAst) + Ast.storeInDiffGraph(memberAst, diffGraph) } protected def astForLocalNode( diff --git a/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/astcreation/AstForPrimitivesCreator.scala b/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/astcreation/AstForPrimitivesCreator.scala index 67c81ee33c21..a372e2b674f9 100644 --- a/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/astcreation/AstForPrimitivesCreator.scala +++ b/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/astcreation/AstForPrimitivesCreator.scala @@ -1,9 +1,11 @@ package io.joern.gosrc2cpg.astcreation +import io.joern.gosrc2cpg.datastructures.GoGlobal import io.joern.gosrc2cpg.parser.ParserAst.* import io.joern.gosrc2cpg.parser.{ParserKeys, ParserNodeInfo} +import io.joern.x2cpg.utils.NodeBuilders.newOperatorCallNode import io.joern.x2cpg.{Ast, ValidationMode} -import io.shiftleft.codepropertygraph.generated.nodes.NewCall +import io.shiftleft.codepropertygraph.generated.nodes.{NewCall, NewFieldIdentifier} import io.shiftleft.codepropertygraph.generated.{DispatchTypes, Operators} import scala.util.{Success, Try} @@ -68,14 +70,38 @@ trait AstForPrimitivesCreator(implicit withSchemaValidation: ValidationMode) { t val node = identifierNode(ident, identifierName, ident.code, variableTypeName) Ast(node).withRefEdge(node, variable) case _ => - // TODO: something is wrong here. Refer to SwitchTests -> "be correct for switch case 4" - Ast(identifierNode(ident, identifierName, ident.json(ParserKeys.Name).str, Defines.anyTypeName)) + // If its not local node then check if its global member variable of package TypeDecl + Option(GoGlobal.structTypeMemberTypeMapping.get(s"$fullyQualifiedPackage${Defines.dot}$identifierName")) match + case Some(fieldTypeFullName) => astForPackageGlobalFieldAccess(fieldTypeFullName, identifierName, ident) + case _ => + // TODO: something is wrong here. Refer to SwitchTests -> "be correct for switch case 4" + Ast(identifierNode(ident, identifierName, ident.json(ParserKeys.Name).str, Defines.anyTypeName)) } } else { Ast() } } + private def astForPackageGlobalFieldAccess( + fieldTypeFullName: String, + identifierName: String, + ident: ParserNodeInfo + ): Ast = { + val identifierAsts = Seq(Ast(identifierNode(ident, declaredPackageName, ident.code, fullyQualifiedPackage))) + callAst( + newOperatorCallNode(Operators.fieldAccess, ident.code, Some(fieldTypeFullName), line(ident), column(ident)), + identifierAsts ++: Seq( + Ast( + NewFieldIdentifier() + .canonicalName(identifierName) + .lineNumber(line(ident)) + .columnNumber(column(ident)) + .code(identifierName) + ) + ) + ) + } + protected def getTypeOfToken(basicLit: ParserNodeInfo): String = { // TODO need to add more primitive types Try(basicLit.json(ParserKeys.Kind).str match { diff --git a/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/astcreation/AstForTypeDeclCreator.scala b/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/astcreation/AstForTypeDeclCreator.scala index 26d6c8746388..c495b83904e4 100644 --- a/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/astcreation/AstForTypeDeclCreator.scala +++ b/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/astcreation/AstForTypeDeclCreator.scala @@ -3,7 +3,7 @@ import io.joern.gosrc2cpg.datastructures.GoGlobal import io.joern.gosrc2cpg.parser.ParserAst.* import io.joern.gosrc2cpg.parser.{ParserKeys, ParserNodeInfo} import io.joern.x2cpg -import io.joern.x2cpg.utils.NodeBuilders.newOperatorCallNode +import io.joern.x2cpg.utils.NodeBuilders.{newFieldIdentifierNode, newOperatorCallNode} import io.joern.x2cpg.{Ast, ValidationMode, Defines as XDefines} import io.shiftleft.codepropertygraph.generated.Operators import io.shiftleft.codepropertygraph.generated.nodes.NewFieldIdentifier @@ -35,7 +35,7 @@ trait AstForTypeDeclCreator(implicit withSchemaValidation: ValidationMode) { thi val fieldNodeInfo = createParserNodeInfo(fieldInfo) val fieldName = fieldNodeInfo.json(ParserKeys.Name).str GoGlobal.recordStructTypeMemberType(typeDeclFullName + Defines.dot + fieldName, typeFullName) - Ast(memberNode(typeInfo, fieldName, fieldNodeInfo.code, typeFullName, Seq())) + Ast(memberNode(typeInfo, fieldName, fieldNodeInfo.code, typeFullName)) }) }) .toSeq @@ -79,14 +79,10 @@ trait AstForTypeDeclCreator(implicit withSchemaValidation: ValidationMode) { thi protected def astForFieldAccess(info: ParserNodeInfo): Seq[Ast] = { val (identifierAsts, fieldTypeFullName) = processReceiver(info) val fieldIdentifier = info.json(ParserKeys.Sel)(ParserKeys.Name).str - val fieldIdentifierNode = NewFieldIdentifier() - .canonicalName(fieldIdentifier) - .lineNumber(line(info)) - .columnNumber(column(info)) - .code(fieldIdentifier) - val fieldIdAst = Ast(fieldIdentifierNode) val callNode = newOperatorCallNode(Operators.fieldAccess, info.code, Some(fieldTypeFullName), line(info), column(info)) - Seq(callAst(callNode, identifierAsts ++ Seq(fieldIdAst))) + Seq( + callAst(callNode, identifierAsts ++ Seq(Ast(newFieldIdentifierNode(fieldIdentifier, line(info), column(info))))) + ) } } diff --git a/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/astcreation/CacheBuilder.scala b/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/astcreation/CacheBuilder.scala index 22829e00e047..96f588900d03 100644 --- a/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/astcreation/CacheBuilder.scala +++ b/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/astcreation/CacheBuilder.scala @@ -19,7 +19,7 @@ trait CacheBuilder(implicit withSchemaValidation: ValidationMode) { this: AstCre val diffGraph = new DiffGraphBuilder try { - cpgOpt.map(_ => { + cpgOpt.map { _ => // We don't want to process this part when third party dependencies are being processed. val result = GoGlobal.recordAliasToNamespaceMapping(declaredPackageName, fullyQualifiedPackage) if (result == null) { @@ -28,8 +28,7 @@ trait CacheBuilder(implicit withSchemaValidation: ValidationMode) { this: AstCre val ast = astForPackage(rootNode) Ast.storeInDiffGraph(ast, diffGraph) } - }) - + } findAndProcess(parserResult.json) processPackageLevelGolbalVaraiblesAndConstants(parserResult.json) } catch { diff --git a/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/datastructures/GoGlobal.scala b/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/datastructures/GoGlobal.scala index 84987550cc15..9c2afb237693 100644 --- a/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/datastructures/GoGlobal.scala +++ b/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/datastructures/GoGlobal.scala @@ -3,7 +3,6 @@ package io.joern.gosrc2cpg.datastructures import io.joern.gosrc2cpg.astcreation.Defines import io.joern.x2cpg.datastructures.Global -import java.util.Map import java.util.concurrent.ConcurrentHashMap import scala.jdk.CollectionConverters.EnumerationHasAsScala diff --git a/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/passes/MethodAndTypeCacheBuilderPass.scala b/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/passes/MethodAndTypeCacheBuilderPass.scala index e088809d1843..9a7d44b16518 100644 --- a/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/passes/MethodAndTypeCacheBuilderPass.scala +++ b/joern-cli/frontends/gosrc2cpg/src/main/scala/io/joern/gosrc2cpg/passes/MethodAndTypeCacheBuilderPass.scala @@ -28,13 +28,13 @@ class MethodAndTypeCacheBuilderPass(cpgOpt: Option[Cpg], astFiles: List[String], val allResults: Future[List[(AstCreator, DiffGraphBuilder)]] = Future.sequence(futures) val results = Await.result(allResults, Duration.Inf) val (astCreators, diffGraphs) = results.unzip - cpgOpt.map(cpg => { - diffGraphs.foreach(diffGraph => { + cpgOpt.map { cpg => + diffGraphs.foreach { diffGraph => overflowdb.BatchedUpdate .applyDiff(cpg.graph, diffGraph, null, null) .transitiveModifications() - }) - }) + } + } astCreators } } diff --git a/joern-cli/frontends/gosrc2cpg/src/test/scala/io/joern/go2cpg/passes/ast/ArraysAndMapTests.scala b/joern-cli/frontends/gosrc2cpg/src/test/scala/io/joern/go2cpg/passes/ast/ArraysAndMapTests.scala index af29cb95cafc..7400c27e1ea1 100644 --- a/joern-cli/frontends/gosrc2cpg/src/test/scala/io/joern/go2cpg/passes/ast/ArraysAndMapTests.scala +++ b/joern-cli/frontends/gosrc2cpg/src/test/scala/io/joern/go2cpg/passes/ast/ArraysAndMapTests.scala @@ -55,16 +55,11 @@ class ArraysAndMapTests extends GoCodeToCpgSuite { |func main() { |} |""".stripMargin) - "check LOCAL node" in { - cpg.local("a").size shouldBe 1 - val List(x) = cpg.local("a").l - x.typeFullName shouldBe "[]int" - } - - "Check IDENTIFIER node" in { - cpg.identifier("a").size shouldBe 1 - val List(x) = cpg.identifier("a").l - x.typeFullName shouldBe "[]int" + "check Global member node" in { + val List(x) = cpg.typeDecl("main").l + val List(a) = x.member.l + a.name shouldBe "a" + a.typeFullName shouldBe "[]int" } } @@ -76,19 +71,15 @@ class ArraysAndMapTests extends GoCodeToCpgSuite { |} |""".stripMargin) - "check LOCAL node" in { - cpg.local("a").size shouldBe 1 - val List(x) = cpg.local("a").l - x.typeFullName shouldBe "[]int" - } - - "Check IDENTIFIER node" in { - cpg.identifier("a").size shouldBe 1 - val List(x) = cpg.identifier("a").l - x.typeFullName shouldBe "[]int" + "check Global Member node" in { + val List(x) = cpg.typeDecl("main").l + val List(a) = x.member.l + a.name shouldBe "a" + a.typeFullName shouldBe "[]int" } - "Check Array initializer CALL node" in { + // TODO need to be handled as part of initializer constructor implementation for package TypeDecl + "Check Array initializer CALL node" ignore { val List(x) = cpg.call(Operators.arrayInitializer).l x.typeFullName shouldBe "[]int" val List(arg1: Literal, arg2: Literal) = x.argument.l: @unchecked @@ -96,7 +87,7 @@ class ArraysAndMapTests extends GoCodeToCpgSuite { arg2.code shouldBe "2" } - "Check assignment call node" in { + "Check assignment call node" ignore { val List(assignmentCallNode) = cpg.call(Operators.assignment).l assignmentCallNode.typeFullName shouldBe "[]int" val List(arg1: Identifier, arg2: Call) = assignmentCallNode.argument.l: @unchecked diff --git a/joern-cli/frontends/gosrc2cpg/src/test/scala/io/joern/go2cpg/passes/ast/GlobalVariableAndConstantTests.scala b/joern-cli/frontends/gosrc2cpg/src/test/scala/io/joern/go2cpg/passes/ast/GlobalVariableAndConstantTests.scala index 33d3ce4bfd96..7f70c71c2c83 100644 --- a/joern-cli/frontends/gosrc2cpg/src/test/scala/io/joern/go2cpg/passes/ast/GlobalVariableAndConstantTests.scala +++ b/joern-cli/frontends/gosrc2cpg/src/test/scala/io/joern/go2cpg/passes/ast/GlobalVariableAndConstantTests.scala @@ -22,11 +22,24 @@ class GlobalVariableAndConstantTests extends GoCodeToCpgSuite { |} |""".stripMargin) - "Check LOCAL node" in { - val List(a, b) = cpg.local.l + "Check package Type Decl" in { + val List(x) = cpg.typeDecl("main").l + x.fullName shouldBe "main" + } + + "Traversal from package type decl to global variable member nodes" in { + val List(x) = cpg.typeDecl("main").l + val List(a, b) = x.member.l + a.name shouldBe "FooConst" a.typeFullName shouldBe "string" + b.name shouldBe "BarVar" b.typeFullName shouldBe "int" } + + "Be correct for Field Access CALL Node for Global variable access" in { + val List(x) = cpg.call(Operators.fieldAccess).l + x.typeFullName shouldBe "string" + } } "Var defined(with type mentioned) in one package used in another package" should { diff --git a/joern-cli/frontends/gosrc2cpg/src/test/scala/io/joern/go2cpg/passes/ast/MethodTests.scala b/joern-cli/frontends/gosrc2cpg/src/test/scala/io/joern/go2cpg/passes/ast/MethodTests.scala index 1e02a08f52c4..e6e8cbb72533 100644 --- a/joern-cli/frontends/gosrc2cpg/src/test/scala/io/joern/go2cpg/passes/ast/MethodTests.scala +++ b/joern-cli/frontends/gosrc2cpg/src/test/scala/io/joern/go2cpg/passes/ast/MethodTests.scala @@ -2,7 +2,7 @@ package io.joern.go2cpg.passes.ast import io.joern.go2cpg.testfixtures.GoCodeToCpgSuite import io.joern.gosrc2cpg.astcreation.Defines -import io.shiftleft.codepropertygraph.generated.{EvaluationStrategies, NodeTypes} +import io.shiftleft.codepropertygraph.generated.{EvaluationStrategies, NodeTypes, Operators} import io.shiftleft.semanticcpg.language.* import java.io.File @@ -1597,12 +1597,18 @@ class MethodTests extends GoCodeToCpgSuite { name.typeFullName shouldBe "string" } - "test basic ast structure for identifiers" in { + "check Global Member node" in { + val List(x) = cpg.typeDecl("main").l + val List(a, b) = x.member.l + a.name shouldBe "person" + a.typeFullName shouldBe "main.Name" + b.name shouldBe "personName" + b.typeFullName shouldBe "string" + } - val List(personName, person, _) = cpg.identifier.l - person.name shouldBe "person" - personName.name shouldBe "personName" - personName.typeFullName shouldBe "string" + "Check fieldAccess node for global variable access" in { + val List(x) = cpg.call(Operators.fieldAccess).l + x.typeFullName shouldBe "string" } } diff --git a/joern-cli/frontends/gosrc2cpg/src/test/scala/io/joern/go2cpg/passes/ast/VariableReferencingTests.scala b/joern-cli/frontends/gosrc2cpg/src/test/scala/io/joern/go2cpg/passes/ast/VariableReferencingTests.scala index 1b142bd4068c..82ea6aa042fa 100644 --- a/joern-cli/frontends/gosrc2cpg/src/test/scala/io/joern/go2cpg/passes/ast/VariableReferencingTests.scala +++ b/joern-cli/frontends/gosrc2cpg/src/test/scala/io/joern/go2cpg/passes/ast/VariableReferencingTests.scala @@ -43,26 +43,21 @@ class VariableReferencingTests extends GoCodeToCpgSuite { val cpg = code("""package main |var x = 1 |func main(){ - |y:=x + | y := x |} |""".stripMargin) - "test local variable exists" in { - val List(localNode) = cpg.method("main.Test0.go").local.nameExact("x").l - localNode.code shouldBe "x" - localNode.closureBindingId shouldBe None + "check Global Member node" in { + val List(x) = cpg.typeDecl("main").l + val List(a) = x.member.l + a.name shouldBe "x" + a.typeFullName shouldBe "int" } - "test identifier association to local" in { - val List(localNode) = cpg.method("main.Test0.go").local.nameExact("x").l - localNode.referencingIdentifiers.lineNumber(2).code.head shouldBe "x" - localNode.referencingIdentifiers.lineNumber(4).code.head shouldBe "x" - } - - "test global variable line and column numbers" in { - val List(localNode) = cpg.method("main.Test0.go").local.nameExact("x").l - localNode.lineNumber shouldBe Some(2) - localNode.columnNumber shouldBe Some(5) + "test local variable exists" in { + val List(localNode) = cpg.local.l + localNode.name shouldBe "y" + localNode.typeFullName shouldBe "int" } }