Repository: joernio/joern
Pull request #728 (2021-11-12 22:14:50)

Remove ghidra2cpg's log4j file
Note quite sure how this file popped up again but ghidra2cpg actually uses the same log4j config as all other joern components, so, this one should be removed to avoid confusion.


Patch:
diff --git a/joern-cli/frontends/ghidra2cpg/config/log4j-ghidra.xml b/joern-cli/frontends/ghidra2cpg/config/log4j-ghidra.xml
deleted file mode 100644
index cec74197d..000000000
--- a/joern-cli/frontends/ghidra2cpg/config/log4j-ghidra.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Configuration>
-  <Appenders>
-    <Console name="Console">
-      <PatternLayout pattern="%-5level %logger{36} - %msg%n"/>
-    </Console>
-  </Appenders>
-  <Loggers>
-    <Logger name="ghidra.app.plugin.core.analysis" additivity="false" level="error">
-      <AppenderRef ref="Console" />
-    </Logger>
-    <Root level="error">
-      <AppenderRef ref="Console"/>
-    </Root>
-  </Loggers>
-</Configuration>
diff --git a/joern-cli/frontends/ghidra2cpg/src/main/scala/io/joern/ghidra2cpg/Ghidra2Cpg.scala b/joern-cli/frontends/ghidra2cpg/src/main/scala/io/joern/ghidra2cpg/Ghidra2Cpg.scala
index 6d7baf3d9..3a247a0b9 100644
--- a/joern-cli/frontends/ghidra2cpg/src/main/scala/io/joern/ghidra2cpg/Ghidra2Cpg.scala
+++ b/joern-cli/frontends/ghidra2cpg/src/main/scala/io/joern/ghidra2cpg/Ghidra2Cpg.scala
@@ -17,6 +17,7 @@ import io.joern.ghidra2cpg.passes._
 import io.joern.ghidra2cpg.passes.arm.ArmFunctionPass
 import io.joern.ghidra2cpg.passes.mips.{LoHiPass, MipsFunctionPass}
 import io.joern.ghidra2cpg.passes.x86.X86FunctionPass
+import io.shiftleft.codepropertygraph.Cpg
 import io.shiftleft.passes.KeyPoolCreator
 import io.shiftleft.x2cpg.X2Cpg
 import utilities.util.FileUtilities
@@ -27,12 +28,20 @@ import scala.jdk.CollectionConverters._
 
 class Ghidra2Cpg() {
 
-  def createCpg(inputFile: File, outputFile: Option[String]): Unit = {
+  /**
+    * Create a CPG representing the given input file. The CPG
+    * is stored at the given output file. The caller must close
+    * the CPG.
+    * */
+  def createCpg(inputFile: File, outputFile: Option[String]): Cpg = {
 
-    if (!inputFile.isDirectory && !inputFile.isFile)
+    if (!inputFile.isDirectory && !inputFile.isFile) {
       throw new InvalidInputException(
         s"$inputFile is not a valid directory or file."
       )
+    }
+
+    val cpg = X2Cpg.newEmptyCpg(outputFile)
 
     better.files.File.usingTemporaryDirectory("ghidra2cpg_tmp") { tempWorkingDir =>
       initGhidra()
@@ -50,8 +59,7 @@ class Ghidra2Cpg() {
           new MessageLog,
           TaskMonitor.DUMMY
         )
-
-        analyzeProgram(inputFile.getAbsolutePath, program, outputFile)
+        addProgramToCpg(program, inputFile.getAbsolutePath, cpg)
       } catch {
         case e: Throwable =>
           e.printStackTrace()
@@ -65,7 +73,7 @@ class Ghidra2Cpg() {
         locator.getMarkerFile.delete
       }
     }
-
+    cpg
   }
 
   private def initGhidra(): Unit = {
@@ -80,7 +88,7 @@ class Ghidra2Cpg() {
     }
   }
 
-  private def analyzeProgram(fileAbsolutePath: String, program: Program, outputFile: Option[String]): Unit = {
+  private def addProgramToCpg(program: Program, fileAbsolutePath: String, cpg: Cpg): Unit = {
     val autoAnalysisManager: AutoAnalysisManager = AutoAnalysisManager.getAnalysisManager(program)
     val transactionId: Int = program.startTransaction("Analysis")
     try {
@@ -95,14 +103,14 @@ class Ghidra2Cpg() {
       program.endTransaction(transactionId, true)
     }
     try {
-      handleProgram(program, fileAbsolutePath, outputFile)
+      handleProgram(program, fileAbsolutePath, cpg)
     } catch {
       case e: Throwable =>
         e.printStackTrace()
     }
   }
 
-  def handleProgram(currentProgram: Program, fileAbsolutePath: String, outputFile: Option[String]): Unit = {
+  def handleProgram(currentProgram: Program, fileAbsolutePath: String, cpg: Cpg): Unit = {
 
     val flatProgramAPI: FlatProgramAPI = new FlatProgramAPI(currentProgram)
     val options = new DecompileOptions()
@@ -137,9 +145,6 @@ class Ghidra2Cpg() {
     val numOfKeypools = functions.size * 3 + 2
     val keyPoolIterator = KeyPoolCreator.obtain(numOfKeypools).iterator
 
-    // Actual CPG construction
-    val cpg = X2Cpg.newEmptyCpg(outputFile)
-
     new MetaDataPass(fileAbsolutePath, cpg, keyPoolIterator.next()).createAndApply()
     new NamespacePass(cpg, fileAbsolutePath, keyPoolIterator.next()).createAndApply()
 
@@ -184,7 +189,6 @@ class Ghidra2Cpg() {
     new TypesPass(cpg).createAndApply()
     new JumpPass(cpg, keyPoolIterator.next()).createAndApply()
     new LiteralPass(cpg, address2Literals, currentProgram, flatProgramAPI, keyPoolIterator.next()).createAndApply()
-    cpg.close()
   }
 
   private class HeadlessProjectConnection(
diff --git a/joern-cli/frontends/ghidra2cpg/src/main/scala/io/joern/ghidra2cpg/Main.scala b/joern-cli/frontends/ghidra2cpg/src/main/scala/io/joern/ghidra2cpg/Main.scala
index 9bb6ddebf..681af7006 100644
--- a/joern-cli/frontends/ghidra2cpg/src/main/scala/io/joern/ghidra2cpg/Main.scala
+++ b/joern-cli/frontends/ghidra2cpg/src/main/scala/io/joern/ghidra2cpg/Main.scala
@@ -28,7 +28,7 @@ object Main extends App {
     case Some(config) =>
       if (config.inputPaths.size == 1) {
         val inputFile = new File(config.inputPaths.head)
-        new Ghidra2Cpg().createCpg(inputFile, Some(config.outputPath))
+        new Ghidra2Cpg().createCpg(inputFile, Some(config.outputPath)).close()
       } else {
         println("This frontend requires exactly one input path")
         System.exit(1)


Test patch:
diff --git a/joern-cli/frontends/ghidra2cpg/src/test/scala/io/joern/ghidra2cpg/fixtures/GhidraBinToCpgSuite.scala b/joern-cli/frontends/ghidra2cpg/src/test/scala/io/joern/ghidra2cpg/fixtures/GhidraBinToCpgSuite.scala
index 7ab2a7ce4..1c7f4c608 100644
--- a/joern-cli/frontends/ghidra2cpg/src/test/scala/io/joern/ghidra2cpg/fixtures/GhidraBinToCpgSuite.scala
+++ b/joern-cli/frontends/ghidra2cpg/src/test/scala/io/joern/ghidra2cpg/fixtures/GhidraBinToCpgSuite.scala
@@ -27,10 +27,6 @@ class GhidraFrontend extends LanguageFrontend {
 
     val cpgBin = dir.getAbsolutePath
     new Ghidra2Cpg().createCpg(inputFile, Some(cpgBin))
-
-    val odbConfig = overflowdb.Config.withDefaults().withStorageLocation(cpgBin)
-    val config = CpgLoaderConfig.withDefaults.withOverflowConfig(odbConfig)
-    CpgLoader.loadFromOverflowDb(config)
   }
 
 }