Skip to content

Commit

Permalink
[swiftsrc2cpg] Implemented if and conditional expressions (#3960)
Browse files Browse the repository at this point in the history
  • Loading branch information
max-leuthaeuser authored Dec 14, 2023
1 parent c9388dc commit 8ebdb08
Show file tree
Hide file tree
Showing 22 changed files with 162 additions and 102 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.joern.c2cpg

import io.joern.c2cpg.datastructures.CGlobal
import io.joern.c2cpg.passes.{AstCreationPass, PreprocessorPass, TypeDeclNodePass}
import io.joern.c2cpg.utils.Report
import io.shiftleft.codepropertygraph.Cpg
Expand All @@ -20,8 +19,9 @@ class C2Cpg extends X2CpgFrontend[Config] {
def createCpg(config: Config): Try[Cpg] = {
withNewEmptyCpg(config.outputPath, config) { (cpg, config) =>
new MetaDataPass(cpg, Languages.NEWC, config.inputPath).createAndApply()
new AstCreationPass(cpg, config, report).createAndApply()
TypeNodePass.withRegisteredTypes(CGlobal.typesSeen(), cpg).createAndApply()
val astCreationPass = new AstCreationPass(cpg, config, report)
astCreationPass.createAndApply()
TypeNodePass.withRegisteredTypes(astCreationPass.typesSeen(), cpg).createAndApply()
new TypeDeclNodePass(cpg)(config.schemaValidation).createAndApply()
report.print()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import io.joern.c2cpg.Config
import io.joern.x2cpg.datastructures.Scope
import io.joern.x2cpg.datastructures.Stack.*
import io.joern.x2cpg.{Ast, AstCreatorBase, ValidationMode, AstNodeBuilder as X2CpgAstNodeBuilder}
import io.joern.x2cpg.datastructures.Global
import io.shiftleft.codepropertygraph.generated.NodeTypes
import io.shiftleft.codepropertygraph.generated.nodes.*
import io.shiftleft.semanticcpg.language.types.structure.NamespaceTraversal
Expand All @@ -18,6 +19,7 @@ import scala.collection.mutable
*/
class AstCreator(
val filename: String,
val global: Global,
val config: Config,
val cdtAst: IASTTranslationUnit,
val file2OffsetTable: ConcurrentHashMap[String, Array[Int]]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.joern.c2cpg.astcreation

import io.joern.c2cpg.datastructures.CGlobal
import io.shiftleft.codepropertygraph.generated.nodes.{ExpressionNew, NewNode}
import io.shiftleft.codepropertygraph.generated.{DispatchTypes, Operators}
import io.joern.x2cpg.{Ast, SourceFiles, ValidationMode}
Expand All @@ -10,7 +9,6 @@ import io.shiftleft.utils.IOUtils
import org.apache.commons.lang.StringUtils
import org.eclipse.cdt.core.dom.ast.*
import org.eclipse.cdt.core.dom.ast.c.{ICASTArrayDesignator, ICASTDesignatedInitializer, ICASTFieldDesignator}
import org.eclipse.cdt.core.dom.ast.c.ICASTTypedefNameSpecifier
import org.eclipse.cdt.core.dom.ast.cpp.*
import org.eclipse.cdt.core.dom.ast.gnu.c.ICASTKnRFunctionDeclarator
import org.eclipse.cdt.internal.core.dom.parser.c.CASTArrayRangeDesignator
Expand Down Expand Up @@ -124,7 +122,7 @@ trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: As

protected def registerType(typeName: String): String = {
val fixedTypeName = fixQualifiedName(StringUtils.normalizeSpace(typeName))
CGlobal.usedTypes.putIfAbsent(fixedTypeName, true)
global.usedTypes.putIfAbsent(fixedTypeName, true)
fixedTypeName
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,29 @@ package io.joern.c2cpg.passes
import io.joern.c2cpg.C2Cpg.DefaultIgnoredFolders
import io.joern.c2cpg.Config
import io.joern.c2cpg.astcreation.AstCreator
import io.joern.c2cpg.astcreation.Defines
import io.joern.c2cpg.parser.{CdtParser, FileDefaults}
import io.joern.c2cpg.utils.{Report, TimeUtils}
import io.shiftleft.codepropertygraph.Cpg
import io.shiftleft.passes.ConcurrentWriterCpgPass
import io.joern.x2cpg.SourceFiles
import io.joern.x2cpg.datastructures.Global

import java.nio.file.Paths
import java.util.concurrent.ConcurrentHashMap
import java.util.regex.Pattern
import scala.util.matching.Regex
import scala.jdk.CollectionConverters.*

class AstCreationPass(cpg: Cpg, config: Config, report: Report = new Report())
extends ConcurrentWriterCpgPass[String](cpg) {

private val file2OffsetTable: ConcurrentHashMap[String, Array[Int]] = new ConcurrentHashMap()
private val parser: CdtParser = new CdtParser(config)

private val global = new Global()

def typesSeen(): List[String] = global.usedTypes.keys().asScala.filterNot(_ == Defines.anyTypeName).toList

override def generateParts(): Array[String] = SourceFiles
.determine(
config.inputPath,
Expand All @@ -39,8 +45,9 @@ class AstCreationPass(cpg: Cpg, config: Config, report: Report = new Report())
parseResult match {
case Some(translationUnit) =>
report.addReportInfo(relPath, fileLOC, parsed = true)
val localDiff =
new AstCreator(relPath, config, translationUnit, file2OffsetTable)(config.schemaValidation).createAst()
val localDiff = new AstCreator(relPath, global, config, translationUnit, file2OffsetTable)(
config.schemaValidation
).createAst()
diffGraph.absorb(localDiff)
true
case None =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package io.joern.jssrc2cpg
import better.files.File
import io.joern.dataflowengineoss.layers.dataflows.{OssDataFlow, OssDataFlowOptions}
import io.joern.jssrc2cpg.JsSrc2Cpg.postProcessingPasses
import io.joern.jssrc2cpg.datastructures.JsGlobal
import io.joern.jssrc2cpg.passes.*
import io.joern.jssrc2cpg.utils.AstGenRunner
import io.joern.x2cpg.X2Cpg.withNewEmptyCpg
Expand All @@ -30,7 +29,7 @@ class JsSrc2Cpg extends X2CpgFrontend[Config] {
val astCreationPass = new AstCreationPass(cpg, astGenResult, config, report)(config.schemaValidation)
astCreationPass.createAndApply()

JavaScriptTypeNodePass.withRegisteredTypes(JsGlobal.typesSeen(), cpg).createAndApply()
JavaScriptTypeNodePass.withRegisteredTypes(astCreationPass.typesSeen(), cpg).createAndApply()
new JavaScriptMetaDataPass(cpg, hash, config.inputPath).createAndApply()
new DependenciesPass(cpg, config).createAndApply()
new ConfigPass(cpg, config, report).createAndApply()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import io.joern.jssrc2cpg.passes.Defines
import io.joern.x2cpg.datastructures.Stack.*
import io.joern.x2cpg.utils.NodeBuilders.{newMethodReturnNode, newModifierNode}
import io.joern.x2cpg.{Ast, AstCreatorBase, ValidationMode, AstNodeBuilder as X2CpgAstNodeBuilder}
import io.joern.x2cpg.datastructures.Global
import io.shiftleft.codepropertygraph.generated.{EvaluationStrategies, ModifierTypes, NodeTypes}
import io.shiftleft.codepropertygraph.generated.nodes.NewBlock
import io.shiftleft.codepropertygraph.generated.nodes.NewFile
Expand All @@ -22,8 +23,9 @@ import ujson.Value

import scala.collection.mutable

class AstCreator(val config: Config, val parserResult: ParseResult)(implicit withSchemaValidation: ValidationMode)
extends AstCreatorBase(parserResult.filename)
class AstCreator(val config: Config, val global: Global, val parserResult: ParseResult)(implicit
withSchemaValidation: ValidationMode
) extends AstCreatorBase(parserResult.filename)
with AstForExpressionsCreator
with AstForPrimitivesCreator
with AstForTypesCreator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: As
}

protected def registerType(typeFullName: String): Unit = {
JsGlobal.usedTypes.putIfAbsent(typeFullName, true)
global.usedTypes.putIfAbsent(typeFullName, true)
}

private def nodeType(node: Value): BabelNode = fromString(node("type").str)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import io.joern.jssrc2cpg.astcreation.AstCreator
import io.joern.jssrc2cpg.parser.BabelJsonParser
import io.joern.jssrc2cpg.utils.AstGenRunner.AstGenRunnerResult
import io.joern.x2cpg.ValidationMode
import io.joern.x2cpg.datastructures.Global
import io.joern.x2cpg.utils.{Report, TimeUtils}
import io.shiftleft.codepropertygraph.Cpg
import io.shiftleft.passes.ConcurrentWriterCpgPass
Expand All @@ -13,13 +14,18 @@ import org.slf4j.{Logger, LoggerFactory}

import java.nio.file.Paths
import scala.util.{Failure, Success, Try}
import scala.jdk.CollectionConverters._

class AstCreationPass(cpg: Cpg, astGenRunnerResult: AstGenRunnerResult, config: Config, report: Report = new Report())(
implicit withSchemaValidation: ValidationMode
) extends ConcurrentWriterCpgPass[(String, String)](cpg) {

private val logger: Logger = LoggerFactory.getLogger(classOf[AstCreationPass])

private val global = new Global()

def typesSeen(): List[String] = global.usedTypes.keys().asScala.filterNot(_ == Defines.Any).toList

override def generateParts(): Array[(String, String)] = astGenRunnerResult.parsedFiles.toArray

override def finish(): Unit = {
Expand All @@ -43,7 +49,7 @@ class AstCreationPass(cpg: Cpg, astGenRunnerResult: AstGenRunnerResult, config:
val fileLOC = IOUtils.readLinesInFile(Paths.get(parseResult.fullPath)).size
report.addReportInfo(parseResult.filename, fileLOC, parsed = true)
Try {
val localDiff = new AstCreator(config, parseResult).createAst()
val localDiff = new AstCreator(config, global, parseResult).createAst()
diffGraph.absorb(localDiff)
} match {
case Failure(exception) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package io.joern.jssrc2cpg.passes
import better.files.File
import io.joern.jssrc2cpg.utils.AstGenRunner
import io.joern.jssrc2cpg.Config
import io.joern.jssrc2cpg.datastructures.JsGlobal
import io.joern.x2cpg.ValidationMode
import io.joern.x2cpg.X2Cpg.newEmptyCpg
import io.shiftleft.codepropertygraph.Cpg
Expand All @@ -23,10 +22,11 @@ abstract class AbstractPassTest extends AnyWordSpec with Matchers with Inside {
val cpg = newEmptyCpg()
val file = dir / filename
file.write(code)
val config = Config(tsTypes = tsTypes).withInputPath(dir.toString).withOutputPath(dir.toString)
val astGenResult = new AstGenRunner(config).execute(dir)
new AstCreationPass(cpg, astGenResult, config).createAndApply()
JavaScriptTypeNodePass.withRegisteredTypes(JsGlobal.typesSeen(), cpg).createAndApply()
val config = Config(tsTypes = tsTypes).withInputPath(dir.toString).withOutputPath(dir.toString)
val astGenResult = new AstGenRunner(config).execute(dir)
val astCreationPass = new AstCreationPass(cpg, astGenResult, config)
astCreationPass.createAndApply()
JavaScriptTypeNodePass.withRegisteredTypes(astCreationPass.typesSeen(), cpg).createAndApply()
f(cpg)
file.delete()
}
Expand All @@ -43,7 +43,7 @@ abstract class AbstractPassTest extends AnyWordSpec with Matchers with Inside {
val astGenResult = new AstGenRunner(config).execute(dir)
val astCreationPass = new AstCreationPass(cpg, astGenResult, config)
astCreationPass.createAndApply()
JavaScriptTypeNodePass.withRegisteredTypes(JsGlobal.typesSeen(), cpg).createAndApply()
JavaScriptTypeNodePass.withRegisteredTypes(astCreationPass.typesSeen(), cpg).createAndApply()
f(cpg)
file.delete()
}
Expand All @@ -62,7 +62,7 @@ abstract class AbstractPassTest extends AnyWordSpec with Matchers with Inside {
val astGenResult = new AstGenRunner(config).execute(dir)
val astCreationPass = new AstCreationPass(cpg, astGenResult, config)
astCreationPass.createAndApply()
JavaScriptTypeNodePass.withRegisteredTypes(JsGlobal.typesSeen(), cpg).createAndApply()
JavaScriptTypeNodePass.withRegisteredTypes(astCreationPass.typesSeen(), cpg).createAndApply()
f(cpg)
file1.delete()
file2.delete()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package io.joern.swiftsrc2cpg

import better.files.File
import io.joern.dataflowengineoss.layers.dataflows.{OssDataFlow, OssDataFlowOptions}
import io.joern.swiftsrc2cpg.datastructures.SwiftGlobal
import io.joern.swiftsrc2cpg.passes.*
import io.joern.swiftsrc2cpg.utils.AstGenRunner
import io.joern.x2cpg.X2Cpg.withNewEmptyCpg
Expand All @@ -29,7 +28,7 @@ class SwiftSrc2Cpg extends X2CpgFrontend[Config] {
val astCreationPass = new AstCreationPass(cpg, astGenResult, config, report)(config.schemaValidation)
astCreationPass.createAndApply()

SwiftTypeNodePass.withRegisteredTypes(SwiftGlobal.typesSeen(), cpg).createAndApply()
SwiftTypeNodePass.withRegisteredTypes(astCreationPass.typesSeen(), cpg).createAndApply()
new SwiftMetaDataPass(cpg, hash, config.inputPath).createAndApply()
new BuiltinTypesPass(cpg).createAndApply()
new DependenciesPass(cpg, config).createAndApply()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import io.joern.swiftsrc2cpg.passes.Defines
import io.joern.x2cpg.datastructures.Stack.*
import io.joern.x2cpg.utils.NodeBuilders.newMethodReturnNode
import io.joern.x2cpg.{Ast, AstCreatorBase, ValidationMode, AstNodeBuilder as X2CpgAstNodeBuilder}
import io.joern.x2cpg.datastructures.Global
import io.joern.x2cpg.utils.NodeBuilders.newModifierNode
import io.shiftleft.semanticcpg.language.types.structure.NamespaceTraversal
import io.shiftleft.codepropertygraph.generated.NodeTypes
Expand All @@ -22,8 +23,9 @@ import overflowdb.BatchedUpdate.DiffGraphBuilder

import scala.collection.mutable

class AstCreator(val config: Config, val parserResult: ParseResult)(implicit withSchemaValidation: ValidationMode)
extends AstCreatorBase(parserResult.filename)
class AstCreator(val config: Config, val global: Global, val parserResult: ParseResult)(implicit
withSchemaValidation: ValidationMode
) extends AstCreatorBase(parserResult.filename)
with AstForSwiftTokenCreator
with AstForSyntaxCreator
with AstForExprSyntaxCreator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@ import io.shiftleft.codepropertygraph.generated.nodes.NewTypeDecl

import scala.collection.mutable

object AstCreatorHelper {

implicit class OptionSafeAst(val ast: Ast) extends AnyVal {
def withArgEdge(src: NewNode, dst: Option[NewNode]): Ast = dst match {
case Some(value) => ast.withArgEdge(src, value)
case None => ast
}
}

}

trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: AstCreator =>

protected def notHandledYet(node: SwiftNode): Ast = {
Expand All @@ -28,7 +39,7 @@ trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: As
}

protected def registerType(typeFullName: String): Unit = {
SwiftGlobal.usedTypes.putIfAbsent((typeFullName), true)
global.usedTypes.putIfAbsent(typeFullName, true)
}

protected def generateUnusedVariableName(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package io.joern.swiftsrc2cpg.astcreation
import io.joern.swiftsrc2cpg.parser.SwiftNodeSyntax.*
import io.joern.x2cpg.Ast
import io.joern.x2cpg.ValidationMode
import io.shiftleft.codepropertygraph.generated.ControlStructureTypes
import io.shiftleft.codepropertygraph.generated.DispatchTypes
import io.shiftleft.codepropertygraph.generated.Operators

Expand Down Expand Up @@ -40,8 +41,20 @@ trait AstForExprSyntaxCreator(implicit withSchemaValidation: ValidationMode) {
private def astForForceUnwrapExprSyntax(node: ForceUnwrapExprSyntax): Ast = notHandledYet(node)
private def astForFunctionCallExprSyntax(node: FunctionCallExprSyntax): Ast = notHandledYet(node)
private def astForGenericSpecializationExprSyntax(node: GenericSpecializationExprSyntax): Ast = notHandledYet(node)
private def astForIfExprSyntax(node: IfExprSyntax): Ast = notHandledYet(node)
private def astForInOutExprSyntax(node: InOutExprSyntax): Ast = notHandledYet(node)

private def astForIfExprSyntax(node: IfExprSyntax): Ast = {
val code = this.code(node)
val ifNode = controlStructureNode(node, ControlStructureTypes.IF, code)
val conditionAst = astForNode(node.conditions)
val thenAst = astForNode(node.body)
val elseAst = node.elseBody match {
case Some(value) => astForNode(value)
case None => Ast()
}
controlStructureAst(ifNode, Some(conditionAst), Seq(thenAst, elseAst))
}

private def astForInOutExprSyntax(node: InOutExprSyntax): Ast = notHandledYet(node)
private def astForInfixOperatorExprSyntax(node: InfixOperatorExprSyntax): Ast = {
val op = code(node.operator) match {
case "=" => Operators.assignment
Expand Down Expand Up @@ -105,8 +118,20 @@ trait AstForExprSyntaxCreator(implicit withSchemaValidation: ValidationMode) {
private def astForSubscriptCallExprSyntax(node: SubscriptCallExprSyntax): Ast = notHandledYet(node)
private def astForSuperExprSyntax(node: SuperExprSyntax): Ast = notHandledYet(node)
private def astForSwitchExprSyntax(node: SwitchExprSyntax): Ast = notHandledYet(node)
private def astForTernaryExprSyntax(node: TernaryExprSyntax): Ast = notHandledYet(node)
private def astForTryExprSyntax(node: TryExprSyntax): Ast = notHandledYet(node)

private def astForTernaryExprSyntax(node: TernaryExprSyntax): Ast = {
val name = Operators.conditional
val call = callNode(node, code(node), name, name, DispatchTypes.STATIC_DISPATCH)

val condAst = astForNodeWithFunctionReference(node.condition)
val posAst = astForNodeWithFunctionReference(node.thenExpression)
val negAst = astForNodeWithFunctionReference(node.elseExpression)

val children = List(condAst, posAst, negAst)
callAst(call, children)
}

private def astForTryExprSyntax(node: TryExprSyntax): Ast = notHandledYet(node)

private def astForTupleExprSyntax(node: TupleExprSyntax): Ast = {
astForNode(node.elements)
Expand Down
Loading

0 comments on commit 8ebdb08

Please sign in to comment.