Skip to content

Commit

Permalink
[GO] - Fix for ticket #3678 (#3680)
Browse files Browse the repository at this point in the history
Fix for issue #3678.

For now, this PR fixes the issue related to the breaking error for the Local node being pushed to as a condition AST node for switch AST. 
Fixed the issue and resolved the breaking error.

This will still require a proper fix to push the Assign AST as the first child of which block AST. We will handle this issue at a later stage.
  • Loading branch information
pandurangpatil authored Sep 20, 2023
1 parent 1b9d738 commit c7ffcd2
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ package io.joern.gosrc2cpg.astcreation
import io.joern.gosrc2cpg.parser.ParserAst.*
import io.joern.gosrc2cpg.parser.{ParserKeys, ParserNodeInfo}
import io.joern.gosrc2cpg.utils.Operator
import io.joern.x2cpg.utils.NodeBuilders.{newCallNode, newOperatorCallNode}
import io.joern.x2cpg.{Ast, ValidationMode}
import io.shiftleft.codepropertygraph.generated.nodes.{ExpressionNew, NewCall, NewIdentifier, NewLiteral, NewLocal}
import io.shiftleft.codepropertygraph.generated.nodes.{ExpressionNew, NewIdentifier, NewLocal}
import io.shiftleft.codepropertygraph.generated.{ControlStructureTypes, DispatchTypes, Operators}
import ujson.Value

import scala.annotation.tailrec
import scala.util.Try

trait AstForStatementsCreator(implicit withSchemaValidation: ValidationMode) { this: AstCreator =>
Expand Down Expand Up @@ -185,12 +183,25 @@ trait AstForStatementsCreator(implicit withSchemaValidation: ValidationMode) { t

val conditionParserNode = Try(createParserNodeInfo(typeSwitchStmt.json(ParserKeys.Assign)))
val (code, conditionAst) = conditionParserNode.toOption match {
case Some(node) => (node.code, Some(astForConditionExpression(node)))
case _ => ("", None)
case Some(node) => (node.code, astForNode(node))
case _ => ("", Seq.empty)
}
val switchNode = controlStructureNode(typeSwitchStmt, ControlStructureTypes.SWITCH, s"switch $code")
val stmtAsts = astsForStatement(createParserNodeInfo(typeSwitchStmt.json(ParserKeys.Body)))
controlStructureAst(switchNode, conditionAst, stmtAsts)
val id = conditionAst
.flatMap(_.root)
.collectFirst {
case x: NewIdentifier => identifierNode(conditionParserNode.get, x.name, x.code, x.typeFullName)
case x: NewLocal => identifierNode(conditionParserNode.get, x.name, x.code, x.typeFullName)
}
.get
val identifier = Ast(id)
val isOp =
callNode(conditionParserNode.get, s"${id.name}.(type)", Operators.is, Operators.is, DispatchTypes.STATIC_DISPATCH)
val condition = Option(callAst(isOp, Seq(identifier)))

val newStmtAst = stmtAsts // TODO: Push conditionAst to the front of the block
controlStructureAst(switchNode, condition, newStmtAst)
}

private def astForCaseClause(caseStmt: ParserNodeInfo): Seq[Ast] = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package io.joern.go2cpg.passes.ast

import io.joern.go2cpg.testfixtures.GoCodeToCpgSuite
import io.shiftleft.codepropertygraph.generated.ControlStructureTypes
import io.shiftleft.codepropertygraph.generated.nodes.*
import io.shiftleft.codepropertygraph.generated.{ControlStructureTypes, Operators}
import io.shiftleft.semanticcpg.language.*
import io.shiftleft.semanticcpg.language.operatorextension.OpNodes

class SwitchTests extends GoCodeToCpgSuite {
"AST Creation for switch case" should {
Expand Down Expand Up @@ -78,7 +77,7 @@ class SwitchTests extends GoCodeToCpgSuite {
}
}

"be correct for switch case 3" ignore {
"be correct for switch case 3" in {

val cpg = code("""
|package main
Expand All @@ -91,28 +90,26 @@ class SwitchTests extends GoCodeToCpgSuite {
| case int:
| y = 8
| case float64:
| y= 12
| y = 12
| }
|}
""".stripMargin)
inside(cpg.method.name("method").controlStructure.l) { case List(controlStruct: ControlStructure) =>
controlStruct.code shouldBe "switch i := x.(type)"
controlStruct.controlStructureType shouldBe ControlStructureTypes.SWITCH
inside(controlStruct.astChildren.l) { case List(assignment: Call, switchBlock: Block) =>
switchBlock.astChildren.size shouldBe 9
switchBlock.astChildren.code.l shouldBe List(
"case nil",
"nil",
"y = 5",
"case int",
"int",
"y = 8",
"case float64",
"float64",
"y = 12"
)
}
}
val List(controlStruct: ControlStructure) = cpg.method.name("method").controlStructure.l
controlStruct.code shouldBe "switch i := x.(type)"
controlStruct.controlStructureType shouldBe ControlStructureTypes.SWITCH
val List(assignment: Call, switchBlock: Block) = controlStruct.astChildren.l
switchBlock.astChildren.size shouldBe 9
switchBlock.astChildren.code.l shouldBe List(
"case nil",
"nil",
"y = 5",
"case int",
"int",
"y = 8",
"case float64",
"float64",
"y = 12"
)
}

"be correct for switch case 4" in {
Expand All @@ -135,8 +132,7 @@ class SwitchTests extends GoCodeToCpgSuite {
val List(controlStruct: ControlStructure) = cpg.method.name("method").controlStructure.l
controlStruct.code shouldBe "switch x.(type)"
controlStruct.controlStructureType shouldBe ControlStructureTypes.SWITCH
val List(identifier: Identifier, switchBlock: Block) = controlStruct.astChildren.l
identifier.code shouldBe "x"
val List(identifier: Call, switchBlock: Block) = controlStruct.astChildren.l
switchBlock.astChildren.size shouldBe 9
// TODO: something is wrong here. Identifier is being created for int, nil and float64
switchBlock.astChildren.code.l shouldBe List(
Expand Down

0 comments on commit c7ffcd2

Please sign in to comment.