Skip to content

Commit

Permalink
[swiftsrc2cpg | c2cpg] Proper handling of do expressions (#4417)
Browse files Browse the repository at this point in the history
swiftsrc2cpg uses the same try/catch lowering as c2cpg now (using `ControlStructureTypes.CATCH`).

Also: fixed order values for catch ASTs.
  • Loading branch information
max-leuthaeuser authored Apr 2, 2024
1 parent ce9ae68 commit cdcf180
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,9 @@ trait AstForStatementsCreator(implicit withSchemaValidation: ValidationMode) { t

private def astForTryStatement(tryStmt: ICPPASTTryBlockStatement): Ast = {
val tryNode = controlStructureNode(tryStmt, ControlStructureTypes.TRY, "try")
val body = nullSafeAst(tryStmt.getTryBody)
val body = nullSafeAst(tryStmt.getTryBody, 1)
val catches = tryStmt.getCatchHandlers.zipWithIndex.map { case (h, index) =>
astForCatchHandler(h, index + 1)
astForCatchHandler(h, index + 2)
}.toIndexedSeq
Ast(tryNode).withChildren(body).withChildren(catches)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1220,9 +1220,10 @@ class AstCreationPassTests extends AstC2CpgSuite {
)
inside(cpg.controlStructure.isTry.l) { case List(t) =>
val List(tryBlock) = t.astChildren.isBlock.l
tryBlock.order shouldBe 1
tryBlock.astChildren.isCall.order(1).code.l shouldBe List("bar()")
val List(catchX) = t.astChildren.isControlStructure.isCatch.l
catchX.order shouldBe 1
catchX.order shouldBe 2
catchX.ast.isReturn.code.l shouldBe List("return 0;")
catchX.ast.isLocal.code.l shouldBe List("Foo x")
}
Expand All @@ -1247,15 +1248,16 @@ class AstCreationPassTests extends AstC2CpgSuite {
)
inside(cpg.controlStructure.isTry.l) { case List(t) =>
val List(tryBlock) = t.astChildren.isBlock.l
tryBlock.order shouldBe 1
tryBlock.astChildren.isIdentifier.order(1).code.l shouldBe List("a")
val List(catchX, catchY, catchZ) = t.astChildren.isControlStructure.isCatch.l
catchX.order shouldBe 1
catchX.order shouldBe 2
catchX.ast.isIdentifier.code.l shouldBe List("b")
catchX.ast.isLocal.code.l shouldBe List("short x")
catchY.order shouldBe 2
catchY.order shouldBe 3
catchY.ast.isIdentifier.code.l shouldBe List("c")
catchY.ast.isLocal.code.l shouldBe List("int y")
catchZ.order shouldBe 3
catchZ.order shouldBe 4
catchZ.ast.isIdentifier.code.l shouldBe List("d")
catchZ.ast.isLocal.code.l shouldBe List("long z")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,23 @@ trait AstForStmtSyntaxCreator(implicit withSchemaValidation: ValidationMode) {
private def astForDiscardStmtSyntax(node: DiscardStmtSyntax): Ast = notHandledYet(node)

private def astForDoStmtSyntax(node: DoStmtSyntax): Ast = {
val tryNode = controlStructureNode(node, ControlStructureTypes.TRY, code(node))
val bodyAst = astForNode(node.body)
val catchAst = astForNode(node.catchClauses)
// The semantics of try statement children is defined by their order value.
// Thus we set the here explicitly and do not rely on the usual consecutive
// ordering.
val tryNode = controlStructureNode(node, ControlStructureTypes.TRY, code(node))
val bodyAst = astForNode(node.body)
setOrderExplicitly(bodyAst, 1)
setOrderExplicitly(catchAst, 2)
Ast(tryNode).withChildren(List(bodyAst, catchAst))
val catchAsts = node.catchClauses.children.zipWithIndex.map { case (h, index) =>
astForCatchHandler(h, index + 2)
}.toIndexedSeq
Ast(tryNode).withChild(bodyAst).withChildren(catchAsts)
}

private def astForCatchHandler(catchClause: CatchClauseSyntax, argIndex: Int): Ast = {
val catchNode =
controlStructureNode(catchClause, ControlStructureTypes.CATCH, code(catchClause))
.order(argIndex)
.argumentIndex(argIndex)
val declAst = astForNode(catchClause.catchItems)
val bodyAst = astForNode(catchClause.body)
Ast(catchNode).withChild(declAst).withChild(bodyAst)
}

private def astForExpressionStmtSyntax(node: ExpressionStmtSyntax): Ast = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,66 +1,105 @@
package io.joern.swiftsrc2cpg.passes.ast

import io.joern.swiftsrc2cpg.testfixtures.AstSwiftSrc2CpgSuite
import io.shiftleft.semanticcpg.language.*

class DoExpressionTests extends AstSwiftSrc2CpgSuite {

"DoExpressionTests" should {

"testDoExpr1" ignore {
"testDoExpr1" in {
val cpg = code("let x = do { 5 }")
???
inside(cpg.controlStructure.isTry.l) { case List(t) =>
t.astChildren.isLiteral.order(1).code.l shouldBe List("5")
t.astChildren.isControlStructure.isCatch shouldBe empty
}
}

"testDoExpr2" ignore {
"testDoExpr2" in {
val cpg = code("let x = do { 5 } catch { 0 }")
???
inside(cpg.controlStructure.isTry.l) { case List(t) =>
t.astChildren.isLiteral.order(1).code.l shouldBe List("5")
val List(catchX) = t.astChildren.isControlStructure.isCatch.l
catchX.order shouldBe 2
catchX.ast.isLiteral.code.l shouldBe List("0")
}
}

"testDoExpr3" ignore {
"testDoExpr3" in {
val cpg = code("func foo() { do { 5 } }")
???
inside(cpg.controlStructure.isTry.l) { case List(t) =>
t.astChildren.isLiteral.order(1).code.l shouldBe List("5")
t.astChildren.isControlStructure.isCatch shouldBe empty
}
}

"testDoExpr4" ignore {
"testDoExpr4" in {
val cpg = code("func foo() { do { 5 } as Int }")
???
inside(cpg.controlStructure.isTry.l) { case List(t) =>
t.astChildren.isLiteral.order(1).code.l shouldBe List("5")
t.astChildren.isControlStructure.isCatch shouldBe empty
}
}

"testDoExpr5" ignore {
"testDoExpr5" in {
val cpg = code("do { 5 } as Int")
???
inside(cpg.controlStructure.isTry.l) { case List(t) =>
t.astChildren.isLiteral.order(1).code.l shouldBe List("5")
t.astChildren.isControlStructure.isCatch shouldBe empty
}
}

"testDoExpr6" ignore {
"testDoExpr6" in {
val cpg = code("""
|func foo() {
| do { 5 } catch { 0 } as Int
|}
|""".stripMargin)
???
inside(cpg.controlStructure.isTry.l) { case List(t) =>
t.astChildren.isLiteral.order(1).code.l shouldBe List("5")
val List(catchX) = t.astChildren.isControlStructure.isCatch.l
catchX.order shouldBe 2
catchX.ast.isLiteral.code.l shouldBe List("0")
}
}

"testDoExpr7" ignore {
"testDoExpr7" in {
val cpg = code("y = do { 5 } catch { 0 } as Int")
???
inside(cpg.controlStructure.isTry.l) { case List(t) =>
t.astChildren.isLiteral.order(1).code.l shouldBe List("5")
val List(catchX) = t.astChildren.isControlStructure.isCatch.l
catchX.order shouldBe 2
catchX.ast.isLiteral.code.l shouldBe List("0")
}
}

"testDoExpr8" ignore {
"testDoExpr8" in {
val cpg = code("{ do { 5 } catch { 0 } }")
???
inside(cpg.controlStructure.isTry.l) { case List(t) =>
t.astChildren.isLiteral.order(1).code.l shouldBe List("5")
val List(catchX) = t.astChildren.isControlStructure.isCatch.l
catchX.order shouldBe 2
catchX.ast.isLiteral.code.l shouldBe List("0")
}
}

"testDoExpr11" ignore {
"testDoExpr11" in {
val cpg = code("return do { 5 }")
???
inside(cpg.controlStructure.isTry.l) { case List(t) =>
t.astChildren.isLiteral.order(1).code.l shouldBe List("5")
t.astChildren.isControlStructure.isCatch shouldBe empty
}
}

"testDoExpr12" ignore {
"testDoExpr12" in {
val cpg = code("""
|return
|do { 5 }
|""".stripMargin)
???
inside(cpg.controlStructure.isTry.l) { case List(t) =>
t.astChildren.isLiteral.order(1).code.l shouldBe List("5")
t.astChildren.isControlStructure.isCatch shouldBe empty
}
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@ class StatementTests extends AstSwiftSrc2CpgSuite {

val List(tryBlock1) = doStructure1.astChildren.order(1).l
tryBlock1.astChildren.isCall.codeExact("foo()").size shouldBe 1
val List(catchBlock1) = doStructure1.astChildren.order(2).l
val List(catchBlock1) = doStructure1.astChildren.isControlStructure.isCatch.l
catchBlock1.order shouldBe 2
catchBlock1.astChildren.isCall.codeExact("bar()").size shouldBe 1

val List(tryBlock2) = doStructure2.astChildren.order(1).l
tryBlock2.astChildren.isCall.codeExact("foo()").size shouldBe 1
val List(catchBlock2) = doStructure2.astChildren.order(2).l
val List(catchBlock2) = doStructure2.astChildren.isControlStructure.isCatch.l
catchBlock2.order shouldBe 2
catchBlock2.astChildren.isCall.code.l shouldBe List("(error as NSError) == NSError()")
}

Expand Down

0 comments on commit cdcf180

Please sign in to comment.