All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.joern.joerncli.CpgBasedTool.scala Maven / Gradle / Ivy

package io.joern.joerncli

import better.files.File
import io.joern.dataflowengineoss.layers.dataflows.{OssDataFlow, OssDataFlowOptions}
import io.joern.dataflowengineoss.semanticsloader.Semantics
import io.shiftleft.codepropertygraph.Cpg
import io.shiftleft.codepropertygraph.cpgloading.CpgLoaderConfig
import io.shiftleft.semanticcpg.layers.LayerCreatorContext
import io.shiftleft.semanticcpg.language._

object CpgBasedTool {

  /** Load code property graph from overflowDB
    *
    * @param filename
    *   name of the file that stores the CPG
    */
  def loadFromOdb(filename: String): Cpg = {
    val odbConfig = overflowdb.Config.withDefaults().withStorageLocation(filename)
    val config    = CpgLoaderConfig().withOverflowConfig(odbConfig).doNotCreateIndexesOnLoad
    io.shiftleft.codepropertygraph.cpgloading.CpgLoader.loadFromOverflowDb(config)
  }

  /** Add the data flow layer to the CPG if it does not exist yet.
    */
  def addDataFlowOverlayIfNonExistent(cpg: Cpg)(implicit s: Semantics): Unit = {
    if (!cpg.metaData.overlays.exists(_ == OssDataFlow.overlayName)) {
      System.err.println("CPG does not have dataflow overlay. Calculating.")
      val opts    = new OssDataFlowOptions()
      val context = new LayerCreatorContext(cpg)
      new OssDataFlow(opts).run(context)
    }
  }

  /** Create an informational string for the user that informs of a successfully generated CPG.
    */
  def newCpgCreatedString(path: String): String = {
    val absolutePath = File(path).path.toAbsolutePath
    s"Successfully wrote graph to: $absolutePath\n" +
      s"To load the graph, type `joern $absolutePath`"
  }

  val ARGS_DELIMITER = "--frontend-args"

  /** Splits arguments at the ARGS_DELIMITER into arguments for the tool and arguments for the language frontend.
    */
  def splitArgs(args: Array[String]): (List[String], List[String]) = {
    args.indexOf(ARGS_DELIMITER) match {
      case -1 => (args.toList, Nil)
      case splitIdx =>
        val (parseOpts, frontendOpts) = args.toList.splitAt(splitIdx)
        (parseOpts, frontendOpts.tail) // Take the tail to ignore the delimiter
    }
  }

  def exitIfInvalid(outDir: String, cpgFileName: String): Unit = {
    if (File(outDir).exists)
      exitWithError(s"Output directory `$outDir` already exists.")
    if (File(cpgFileName).notExists)
      exitWithError(s"CPG at $cpgFileName does not exist.")
  }

  def exitWithError(msg: String): Unit = {
    System.err.println(s"error: $msg")
    System.exit(1)
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy