Skip to content

Commit bb6353b

Browse files
[kotlin2cpg] Emit control structure for throw statement (#5833)
1 parent 7a72f0f commit bb6353b

File tree

3 files changed

+46
-1
lines changed

3 files changed

+46
-1
lines changed

joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstCreator.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,8 @@ class AstCreator(
317317
Seq(astForStringTemplate(typedExpr, argIdxMaybe, argNameMaybe, annotations))
318318
case typedExpr: KtSuperExpression => Seq(astForSuperExpression(typedExpr, argIdxMaybe, argNameMaybe, annotations))
319319
case typedExpr: KtThisExpression => Seq(astForThisExpression(typedExpr, argIdxMaybe, argNameMaybe, annotations))
320-
case typedExpr: KtThrowExpression => Seq(astForUnknown(typedExpr, argIdxMaybe, argNameMaybe, annotations))
320+
case typedExpr: KtThrowExpression =>
321+
Seq(astForThrowExpression(typedExpr, argIdxMaybe, argNameMaybe, annotations))
321322
case typedExpr: KtTryExpression => Seq(astForTry(typedExpr, argIdxMaybe, argNameMaybe, annotations))
322323
case typedExpr: KtWhenExpression => Seq(astForWhen(typedExpr, argIdxMaybe, argNameMaybe, annotations))
323324
case typedExpr: KtWhileExpression => Seq(astForWhile(typedExpr, annotations))

joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstForStatementsCreator.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.psi.KtIfExpression
2121
import org.jetbrains.kotlin.psi.KtNamedFunction
2222
import org.jetbrains.kotlin.psi.KtProperty
2323
import org.jetbrains.kotlin.psi.KtPsiUtil
24+
import org.jetbrains.kotlin.psi.KtThrowExpression
2425
import org.jetbrains.kotlin.psi.KtTryExpression
2526
import org.jetbrains.kotlin.psi.KtWhenConditionWithExpression
2627
import org.jetbrains.kotlin.psi.KtWhenEntry
@@ -522,6 +523,17 @@ trait AstForStatementsCreator(implicit withSchemaValidation: ValidationMode) {
522523
Ast(node)
523524
}
524525

526+
def astForThrowExpression(
527+
expr: KtThrowExpression,
528+
argIdxMaybe: Option[Int],
529+
argNameMaybe: Option[String],
530+
annotations: Seq[KtAnnotationEntry] = Seq()
531+
): Ast = {
532+
val thrownValue = astsForExpression(expr.getThrownExpression, None)
533+
val node = controlStructureNode(expr, ControlStructureTypes.THROW, expr.getText)
534+
Ast(node).withChildren(thrownValue)
535+
}
536+
525537
def astForBlock(
526538
expr: KtBlockExpression,
527539
argIdxMaybe: Option[Int],

joern-cli/frontends/kotlin2cpg/src/test/scala/io/joern/kotlin2cpg/querying/ControlStructureTests.scala

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import io.joern.kotlin2cpg.testfixtures.KotlinCode2CpgFixture
44
import io.shiftleft.codepropertygraph.generated.nodes.{Block, Call, ControlStructure, Identifier, Local}
55
import io.shiftleft.codepropertygraph.generated.{ControlStructureTypes, DispatchTypes, Operators}
66
import io.shiftleft.semanticcpg.language.*
7+
import io.shiftleft.codepropertygraph.generated.nodes.Literal
78

89
class ControlStructureTests extends KotlinCode2CpgFixture(withOssDataflow = false) {
910
"CPG for code with simple if-else" should {
@@ -212,6 +213,37 @@ class ControlStructureTests extends KotlinCode2CpgFixture(withOssDataflow = fals
212213
}
213214
}
214215

216+
"CPG for code with throw statement" should {
217+
val cpg = code("""
218+
|package mypkg
219+
|
220+
|fun main() {
221+
| throw RuntimeException("boom")
222+
|}
223+
|""".stripMargin)
224+
225+
"should contain a THROW control structure with the thrown expression as its child" in {
226+
val List(throwNode: ControlStructure) = cpg.controlStructure.controlStructureType(ControlStructureTypes.THROW).l
227+
throwNode.code shouldBe "throw RuntimeException(\"boom\")"
228+
229+
// Ctor calls cause the following structure to be emitted for the call to RuntimeException
230+
// throw Block {
231+
// var tmp = operator.<alloc>(...)
232+
// RuntimeException.<init>(tmp, "boom")
233+
// }
234+
val List(throwBlock: Block) = throwNode.astChildren.l
235+
inside(throwBlock.astChildren.isCall.sortBy(_.name).l) { case List(init: Call, assignment: Call) =>
236+
// Not really testing ctor generation, just a simple check that it does exist and has expected values
237+
assignment.name shouldBe "<operator>.assignment"
238+
239+
init.code shouldBe "RuntimeException(\"boom\")"
240+
init.name shouldBe "<init>"
241+
init.methodFullName shouldBe "java.lang.RuntimeException.<init>:void(java.lang.String)"
242+
}
243+
244+
}
245+
}
246+
215247
"CPG for code with `for-in` loop which has a simple variable loop parameter" should {
216248
val cpg = code("""
217249
|package mypkg

0 commit comments

Comments
 (0)