Skip to content

Commit

Permalink
Joern Upgrades and Stripping of Old Functionality (#253)
Browse files Browse the repository at this point in the history
* Removed incremental/hash functionality
* Upgraded Joern
* Removed source file support via Jimple
* Handling new docker compose command
* Commented out TG testing since licensing is an issue now
  • Loading branch information
DavidBakerEffendi authored May 23, 2024
1 parent 9334c27 commit 70367d1
Show file tree
Hide file tree
Showing 31 changed files with 289 additions and 968 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
run: sbt "project neo4j" test
# - name: Run TigerGraph tests
# run: |
# curl https://dl.tigergraph.com/enterprise-edition/gsql_client/tigergraph-3.9.3-1-gsql_client.jar \
# curl https://dl.tigergraph.com/enterprise-edition/gsql_client/tigergraph-3.10.1-gsql_client.jar \
# --output gsql_client.jar &&
# export GSQL_HOME=`pwd`/gsql_client.jar
# sbt "project tigergraph" test
Expand Down
3 changes: 2 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ inThisBuild(
List(
organization := "com.github.plume-oss",
version := "2.0.0",
scalaVersion := "3.3.1",
scalaVersion := "3.4.1",
resolvers ++= Seq(
Resolver.mavenLocal,
Resolver.mavenCentral,
Expand Down Expand Up @@ -36,6 +36,7 @@ libraryDependencies ++= Seq(
"io.joern" %% "semanticcpg" % Versions.joern,
"io.joern" %% "x2cpg" % Versions.joern,
"io.joern" %% "jimple2cpg" % Versions.joern,
"io.joern" %% "jimple2cpg" % Versions.joern % Test classifier "tests",
"io.joern" %% "x2cpg" % Versions.joern % Test classifier "tests",
"org.slf4j" % "slf4j-api" % Versions.slf4j,
"org.apache.logging.log4j" % "log4j-core" % Versions.log4j % Test,
Expand Down
3 changes: 1 addition & 2 deletions commons/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@ name := "commons"

libraryDependencies ++= Seq(
"io.shiftleft" %% "overflowdb-traversal" % Versions.overflowDb,
"io.shiftleft" %% "codepropertygraph" % Versions.codePropertyGraph,
"org.lz4" % "lz4-java" % Versions.lz4
"io.shiftleft" %% "codepropertygraph" % Versions.codePropertyGraph
)
44 changes: 0 additions & 44 deletions commons/src/main/scala/com/github/plume/oss/util/HashUtil.scala

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import scala.collection.mutable.ListBuffer
*/
trait IDriver extends AutoCloseable {

private val logger = LoggerFactory.getLogger(IDriver.getClass)
// ID Tracking
protected val currId = new AtomicLong(1)
private val nodeId = TrieMap.empty[overflowdb.NodeOrDetachedNode, Long]
Expand All @@ -41,10 +40,6 @@ trait IDriver extends AutoCloseable {
*/
def bulkTx(dg: DiffOrBuilder): Int

/** Given filenames, will remove related TYPE, TYPE_DECL, METHOD (with AST children), and NAMESPACE_BLOCK.
*/
def removeSourceFiles(filenames: String*): Unit

/** Obtains properties from the specified node type and key(s). By default will return the ID property as one of the
* keys as "id".
*/
Expand Down Expand Up @@ -148,38 +143,3 @@ trait ISchemaSafeDriver extends IDriver {
def buildSchemaPayload(): String

}

object IDriver {
val STRING_DEFAULT: String = "<empty>"
val INT_DEFAULT: Int = -1
val LONG_DEFAULT: Long = -1L
val BOOL_DEFAULT: Boolean = false
val LIST_DEFAULT: Seq[String] = Seq.empty[String]

/** Given a property, returns its known default.
*/
def getPropertyDefault(prop: String): Any = {
import PropertyNames.*
prop match {
case AST_PARENT_TYPE => STRING_DEFAULT
case AST_PARENT_FULL_NAME => STRING_DEFAULT
case NAME => STRING_DEFAULT
case CODE => STRING_DEFAULT
case ORDER => INT_DEFAULT
case SIGNATURE => ""
case ARGUMENT_INDEX => INT_DEFAULT
case FULL_NAME => STRING_DEFAULT
case TYPE_FULL_NAME => STRING_DEFAULT
case TYPE_DECL_FULL_NAME => STRING_DEFAULT
case IS_EXTERNAL => BOOL_DEFAULT
case DISPATCH_TYPE => STRING_DEFAULT
case LINE_NUMBER => INT_DEFAULT
case COLUMN_NUMBER => INT_DEFAULT
case LINE_NUMBER_END => INT_DEFAULT
case COLUMN_NUMBER_END => INT_DEFAULT
case OVERLAYS => LIST_DEFAULT
case INHERITS_FROM_TYPE_FULL_NAME => LIST_DEFAULT
case _ => STRING_DEFAULT
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package com.github.plume.oss.drivers

import io.shiftleft.codepropertygraph.generated.EdgeTypes
import io.shiftleft.codepropertygraph.generated.nodes.*
import org.slf4j.LoggerFactory

/** A single utility to build out the CPG schema in other databases.
*/
object SchemaBuilder {

private val logger = LoggerFactory.getLogger(getClass)

val STRING_DEFAULT: String = "<empty>"
val INT_DEFAULT: Int = -1
val LONG_DEFAULT: Long = -1L
val BOOL_DEFAULT: Boolean = false
val LIST_DEFAULT: Seq[String] = Seq.empty[String]

/** Given a property, returns its known default.
*/
def getPropertyDefault(prop: String): Any = {
import io.shiftleft.codepropertygraph.generated.PropertyNames.*
prop match {
case AST_PARENT_TYPE => STRING_DEFAULT
case AST_PARENT_FULL_NAME => STRING_DEFAULT
case NAME => STRING_DEFAULT
case CODE => STRING_DEFAULT
case ORDER => INT_DEFAULT
case SIGNATURE => ""
case ARGUMENT_INDEX => INT_DEFAULT
case FULL_NAME => STRING_DEFAULT
case TYPE_FULL_NAME => STRING_DEFAULT
case TYPE_DECL_FULL_NAME => STRING_DEFAULT
case IS_EXTERNAL => BOOL_DEFAULT
case DISPATCH_TYPE => STRING_DEFAULT
case LINE_NUMBER => INT_DEFAULT
case COLUMN_NUMBER => INT_DEFAULT
case LINE_NUMBER_END => INT_DEFAULT
case COLUMN_NUMBER_END => INT_DEFAULT
case OVERLAYS => LIST_DEFAULT
case INHERITS_FROM_TYPE_FULL_NAME => LIST_DEFAULT
case POSSIBLE_TYPES => LIST_DEFAULT
case _ => STRING_DEFAULT
}
}

/** Edges that should be specified as being between any kind of vertex.
*/
val WILDCARD_EDGE_LABELS: Set[String] =
Set(EdgeTypes.EVAL_TYPE, EdgeTypes.REF, EdgeTypes.INHERITS_FROM, EdgeTypes.ALIAS_OF)

/** Determines if an edge type between two node types is valid.
*/
def checkEdgeConstraint(from: String, to: String, edge: String): Boolean = {
val fromCheck = from match {
case MetaData.Label => MetaData.Edges.Out.contains(edge)
case File.Label => File.Edges.Out.contains(edge)
case Method.Label => Method.Edges.Out.contains(edge)
case MethodParameterIn.Label => MethodParameterIn.Edges.Out.contains(edge)
case MethodParameterOut.Label => MethodParameterOut.Edges.Out.contains(edge)
case MethodReturn.Label => MethodReturn.Edges.Out.contains(edge)
case Modifier.Label => Modifier.Edges.Out.contains(edge)
case Type.Label => Type.Edges.Out.contains(edge)
case TypeDecl.Label => TypeDecl.Edges.Out.contains(edge)
case TypeParameter.Label => TypeParameter.Edges.Out.contains(edge)
case TypeArgument.Label => TypeArgument.Edges.Out.contains(edge)
case Member.Label => Member.Edges.Out.contains(edge)
case Namespace.Label => Namespace.Edges.Out.contains(edge)
case NamespaceBlock.Label => NamespaceBlock.Edges.Out.contains(edge)
case Literal.Label => Literal.Edges.Out.contains(edge)
case Call.Label => Call.Edges.Out.contains(edge)
case ClosureBinding.Label => ClosureBinding.Edges.Out.contains(edge)
case Local.Label => Local.Edges.Out.contains(edge)
case Identifier.Label => Identifier.Edges.Out.contains(edge)
case FieldIdentifier.Label => FieldIdentifier.Edges.Out.contains(edge)
case Return.Label => Return.Edges.Out.contains(edge)
case Block.Label => Block.Edges.Out.contains(edge)
case MethodRef.Label => MethodRef.Edges.Out.contains(edge)
case TypeRef.Label => TypeRef.Edges.Out.contains(edge)
case JumpTarget.Label => JumpTarget.Edges.Out.contains(edge)
case ControlStructure.Label => ControlStructure.Edges.Out.contains(edge)
case Annotation.Label => Annotation.Edges.Out.contains(edge)
case AnnotationLiteral.Label => AnnotationLiteral.Edges.Out.contains(edge)
case AnnotationParameter.Label => AnnotationParameter.Edges.Out.contains(edge)
case AnnotationParameterAssign.Label => AnnotationParameterAssign.Edges.Out.contains(edge)
case Unknown.Label => Unknown.Edges.Out.contains(edge)
case x =>
logger.warn(s"Unhandled node type '$x'")
false
}
val toCheck = to match {
case MetaData.Label => MetaData.Edges.In.contains(edge)
case File.Label => File.Edges.In.contains(edge)
case Method.Label => Method.Edges.In.contains(edge)
case MethodParameterIn.Label => MethodParameterIn.Edges.In.contains(edge)
case MethodParameterOut.Label => MethodParameterOut.Edges.In.contains(edge)
case MethodReturn.Label => MethodReturn.Edges.In.contains(edge)
case Modifier.Label => Modifier.Edges.In.contains(edge)
case Type.Label => Type.Edges.In.contains(edge)
case TypeDecl.Label => TypeDecl.Edges.In.contains(edge)
case TypeParameter.Label => TypeParameter.Edges.In.contains(edge)
case TypeArgument.Label => TypeArgument.Edges.In.contains(edge)
case Member.Label => Member.Edges.In.contains(edge)
case Namespace.Label => Namespace.Edges.In.contains(edge)
case NamespaceBlock.Label => NamespaceBlock.Edges.In.contains(edge)
case Literal.Label => Literal.Edges.In.contains(edge)
case Call.Label => Call.Edges.In.contains(edge)
case ClosureBinding.Label => ClosureBinding.Edges.Out.contains(edge)
case Local.Label => Local.Edges.In.contains(edge)
case Identifier.Label => Identifier.Edges.In.contains(edge)
case FieldIdentifier.Label => FieldIdentifier.Edges.In.contains(edge)
case Return.Label => Return.Edges.In.contains(edge)
case Block.Label => Block.Edges.In.contains(edge)
case MethodRef.Label => MethodRef.Edges.In.contains(edge)
case TypeRef.Label => TypeRef.Edges.In.contains(edge)
case JumpTarget.Label => JumpTarget.Edges.In.contains(edge)
case ControlStructure.Label => ControlStructure.Edges.In.contains(edge)
case Annotation.Label => Annotation.Edges.In.contains(edge)
case AnnotationLiteral.Label => AnnotationLiteral.Edges.In.contains(edge)
case AnnotationParameter.Label => AnnotationParameter.Edges.In.contains(edge)
case AnnotationParameterAssign.Label => AnnotationParameterAssign.Edges.In.contains(edge)
case Unknown.Label => Unknown.Edges.In.contains(edge)
case x =>
logger.warn(s"Unhandled node type '$x'")
false
}

fromCheck && toCheck
}

def allProperties: Set[String] = NodeToProperties.flatMap(_._2).toSet

val NodeToProperties: Map[String, Set[String]] = Map(
MetaData.Label -> MetaData.PropertyNames.all,
File.Label -> File.PropertyNames.all,
Method.Label -> Method.PropertyNames.all,
MethodParameterIn.Label -> MethodParameterIn.PropertyNames.all,
MethodParameterOut.Label -> MethodParameterOut.PropertyNames.all,
MethodReturn.Label -> MethodReturn.PropertyNames.all,
Modifier.Label -> Modifier.PropertyNames.all,
Type.Label -> Type.PropertyNames.all,
TypeDecl.Label -> TypeDecl.PropertyNames.all,
TypeParameter.Label -> TypeParameter.PropertyNames.all,
TypeArgument.Label -> TypeArgument.PropertyNames.all,
Member.Label -> Member.PropertyNames.all,
Namespace.Label -> Namespace.PropertyNames.all,
NamespaceBlock.Label -> NamespaceBlock.PropertyNames.all,
Literal.Label -> Literal.PropertyNames.all,
Call.Label -> Call.PropertyNames.all,
Local.Label -> Local.PropertyNames.all,
Identifier.Label -> Identifier.PropertyNames.all,
FieldIdentifier.Label -> FieldIdentifier.PropertyNames.all,
Return.Label -> Return.PropertyNames.all,
Block.Label -> Block.PropertyNames.all,
MethodRef.Label -> MethodRef.PropertyNames.all,
TypeRef.Label -> TypeRef.PropertyNames.all,
JumpTarget.Label -> JumpTarget.PropertyNames.all,
ControlStructure.Label -> ControlStructure.PropertyNames.all,
Annotation.Label -> Annotation.PropertyNames.all,
AnnotationLiteral.Label -> AnnotationLiteral.PropertyNames.all,
AnnotationParameter.Label -> AnnotationParameter.PropertyNames.all,
AnnotationParameterAssign.Label -> AnnotationParameterAssign.PropertyNames.all,
Unknown.Label -> Unknown.PropertyNames.all
)

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,33 @@ package com.github.plume.oss
import io.circe.Json
import org.slf4j.LoggerFactory

import java.io.{File => JavaFile}
import better.files.File
import scala.collection.mutable.ListBuffer
import scala.sys.process.{Process, ProcessLogger, stringSeqToProcess}

object DockerManager {

private val logger = LoggerFactory.getLogger(getClass)

def toDockerComposeFile(dbName: String): JavaFile =
new JavaFile(getClass.getResource(s"/docker/$dbName.yml").toURI)
def toDockerComposeFile(dbName: String)(implicit classLoader: ClassLoader): File =
File(classLoader.getResource(s"docker/$dbName.yml").toURI)

def closeAnyDockerContainers(dbName: String): Unit = {
def closeAnyDockerContainers(dbName: String)(implicit classLoader: ClassLoader): Unit = {
logger.info(s"Stopping Docker services for $dbName...")
val dockerComposeUp = Process(Seq("docker-compose", "-f", toDockerComposeFile(dbName).getAbsolutePath, "down"))
dockerComposeUp.run(ProcessLogger(_ => ()))
val dockerComposeDown = Process(Seq("docker", "compose", "-f", toDockerComposeFile(dbName).pathAsString, "down"))
dockerComposeDown.run(ProcessLogger(_ => ()))
}

def startDockerFile(dbName: String, containers: List[String] = List.empty[String]): Unit = {
def startDockerFile(dbName: String, containers: List[String] = List.empty[String])(implicit
classLoader: ClassLoader
): Unit = {
val healthChecks = ListBuffer.empty[String]
if (containers.isEmpty) healthChecks += dbName else healthChecks ++= containers
logger.info(s"Docker Compose file found for $dbName, starting...")
closeAnyDockerContainers(dbName) // Easiest way to clear the db
Thread.sleep(3000)
val dockerComposeUp = Process(
Seq("docker-compose", "-f", toDockerComposeFile(dbName).getAbsolutePath, "up", "--remove-orphans")
Seq("docker", "compose", "-f", toDockerComposeFile(dbName).pathAsString, "up", "--remove-orphans")
)
logger.info(s"Starting process $dockerComposeUp")
dockerComposeUp.run(ProcessLogger(_ => ()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class PlumeDriverFixture(val driver: IDriver)
val props: Array[Object] = n.properties.flatMap { case (k, v) =>
Iterable(k.asInstanceOf[Object], v.asInstanceOf[Object])
}.toArray
new DetachedNodeGeneric(n.label(), props: _*)
new DetachedNodeGeneric(n.label(), props*)
}

"overflowdb.BatchedUpdate.DiffGraph based changes" should {
Expand Down Expand Up @@ -97,23 +97,6 @@ class PlumeDriverFixture(val driver: IDriver)
}
}

"should delete a source file's nodes precisely" in {
val diffGraph = new DiffGraphBuilder
// Create some basic method
createSimpleGraph(diffGraph)
driver.bulkTx(diffGraph.build())

// remove f1 nodes
driver.removeSourceFiles(f1.name)

val List(m: Map[String, Any]) = driver.propertyFromNodes(METHOD, NAME)
val List(td: Map[String, Any]) = driver.propertyFromNodes(TYPE_DECL, NAME)
val List(n: Map[String, Any]) = driver.propertyFromNodes(NAMESPACE_BLOCK, NAME)
m.getOrElse(NAME, -1L).asInstanceOf[String] shouldBe m2.name
td.getOrElse(NAME, -1L).asInstanceOf[String] shouldBe td2.name
n.getOrElse(NAME, -1L).asInstanceOf[String] shouldBe n2.name
}

override def afterAll(): Unit = {
if (driver.isConnected) driver.close()
}
Expand Down
Loading

0 comments on commit 70367d1

Please sign in to comment.