Skip to content

Commit

Permalink
Update chen to bring c fullname improvements (#150)
Browse files Browse the repository at this point in the history
Signed-off-by: Prabhu Subramanian <prabhu@appthreat.com>
  • Loading branch information
prabhu authored Jul 9, 2024
1 parent 590489d commit 73efd23
Show file tree
Hide file tree
Showing 20 changed files with 2,771 additions and 2,769 deletions.
3 changes: 2 additions & 1 deletion .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
version = 3.8.1
version = 3.8.2
runner.dialect = scala3
preset = IntelliJ
maxColumn = 100
align.preset = true

indent.main = 4
indent.significant = 2

newlines.source = keep
rewrite.scala3.convertToNewSyntax = true
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,10 @@ docker run --rm -v /tmp:/tmp -v $HOME:$HOME -v $(pwd):/app:rw -it ghcr.io/appthr
## Languages supported

- C/C++
- H (C/C++ Header files alone)
- H (C/C++ Header and pre-processed .i files alone)
- Java (Requires compilation)
- Jar
- Android APK (Requires Android SDK. Set the environment variable `ANDROID_HOME`)
- Android APK (Requires Android SDK. Set the environment variable `ANDROID_HOME` or use the container image.)
- JavaScript
- TypeScript
- Python
Expand Down
4 changes: 2 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name := "atom"
ThisBuild / organization := "io.appthreat"
ThisBuild / version := "2.0.16"
ThisBuild / version := "2.0.17"
ThisBuild / scalaVersion := "3.4.2"

val chenVersion = "2.1.2"
val chenVersion = "2.1.4"

lazy val atom = Projects.atom

Expand Down
2 changes: 1 addition & 1 deletion codemeta.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"downloadUrl": "https://github.com/AppThreat/atom",
"issueTracker": "https://github.com/AppThreat/atom/issues",
"name": "atom",
"version": "2.0.16",
"version": "2.0.17",
"description": "Atom is a novel intermediate representation for next-generation code analysis.",
"applicationCategory": "code-analysis",
"keywords": [
Expand Down
1,125 changes: 563 additions & 562 deletions src/main/scala/io/appthreat/atom/Atom.scala

Large diffs are not rendered by default.

126 changes: 63 additions & 63 deletions src/main/scala/io/appthreat/atom/dataflows/DataFlowGraph.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,48 +8,48 @@ import scala.collection.mutable

private class DataFlowGraph(nodes: Set[Option[DFNode]]):

private type Path = List[Long]
// Maximum number of data-flow paths to compute
private val MAX_PATHS = 100
private type Path = List[Long]
// Maximum number of data-flow paths to compute
private val MAX_PATHS = 100

def paths: Set[Path] =
implicit val finalSet: mutable.Set[Path] = mutable.Set.empty
implicit val nMap: Map[Long, DFNode] = nodes.map(x => x.get.id -> x.get).toMap
nodes.foreach { n =>
val currPath = List(n.get.id)
follow(currPath, n.get.out.flatMap(nMap.get))
}
finalSet.toSet
def paths: Set[Path] =
implicit val finalSet: mutable.Set[Path] = mutable.Set.empty
implicit val nMap: Map[Long, DFNode] = nodes.map(x => x.get.id -> x.get).toMap
nodes.foreach { n =>
val currPath = List(n.get.id)
follow(currPath, n.get.out.flatMap(nMap.get))
}
finalSet.toSet

private def isSubList[A](short: List[A], long: List[A]): Boolean =
val sLong = long.to(LazyList)
val sShort = short.to(LazyList)
sLong.tails.exists(_.startsWith(sShort))
private def isSubList[A](short: List[A], long: List[A]): Boolean =
val sLong = long.to(LazyList)
val sShort = short.to(LazyList)
sLong.tails.exists(_.startsWith(sShort))

private def isSubList[A](lst: List[A])(implicit finalSet: mutable.Set[Path]): Boolean =
finalSet.filterNot(_.size < lst.size).exists(xs => isSubList(lst, xs))
private def isSubList[A](lst: List[A])(implicit finalSet: mutable.Set[Path]): Boolean =
finalSet.filterNot(_.size < lst.size).exists(xs => isSubList(lst, xs))

/** Is there an existing path that starts and ends with the same node
*/
private def isDuplicate(finalSet: mutable.Set[Path], path: Path): Boolean =
finalSet.exists(apath =>
apath.headOption == path.headOption && apath.lastOption == path.lastOption
)
/** Is there an existing path that starts and ends with the same node
*/
private def isDuplicate(finalSet: mutable.Set[Path], path: Path): Boolean =
finalSet.exists(apath =>
apath.headOption == path.headOption && apath.lastOption == path.lastOption
)

private def follow(currPath: List[Long], outNodes: Set[DFNode])(
implicit
nMap: Map[Long, DFNode],
finalSet: mutable.Set[Path]
): Unit =
outNodes.foreach { x =>
val path = currPath :+ x.id
val queue = x.out.filterNot(currPath.contains)
if queue.isEmpty then
if !isDuplicate(finalSet, path) && !isSubList(path) then
finalSet.add(path)
else if finalSet.size < MAX_PATHS then
follow(path, queue.flatMap(nMap.get))
}
private def follow(currPath: List[Long], outNodes: Set[DFNode])(
implicit
nMap: Map[Long, DFNode],
finalSet: mutable.Set[Path]
): Unit =
outNodes.foreach { x =>
val path = currPath :+ x.id
val queue = x.out.filterNot(currPath.contains)
if queue.isEmpty then
if !isDuplicate(finalSet, path) && !isSubList(path) then
finalSet.add(path)
else if finalSet.size < MAX_PATHS then
follow(path, queue.flatMap(nMap.get))
}
end DataFlowGraph

private final case class DFNode(
Expand All @@ -62,33 +62,33 @@ private final case class DFNode(

object DataFlowGraph:

private def DF_EDGES =
Set(EdgeTypes.REACHING_DEF, EdgeTypes.CALL, EdgeTypes.REF)
val exec: ExecutorService =
Executors.newVirtualThreadPerTaskExecutor()
private def DF_EDGES =
Set(EdgeTypes.REACHING_DEF, EdgeTypes.CALL, EdgeTypes.REF)
val exec: ExecutorService =
Executors.newVirtualThreadPerTaskExecutor()

def buildFromSlice(slice: DataFlowSlice): DataFlowGraph =
val dfNodes = slice.nodes
.flatMap {
case n if n.fullName.startsWith("<operator") || n.name.equals("this") => None
case n => Some(n)
}
.map(n => exec.submit(new DFNodeTask(slice, n)))
.map(TimedGet)
.filter(_.isDefined)
new DataFlowGraph(dfNodes)
def buildFromSlice(slice: DataFlowSlice): DataFlowGraph =
val dfNodes = slice.nodes
.flatMap {
case n if n.fullName.startsWith("<operator") || n.name.equals("this") => None
case n => Some(n)
}
.map(n => exec.submit(new DFNodeTask(slice, n)))
.map(TimedGet)
.filter(_.isDefined)
new DataFlowGraph(dfNodes)

private def TimedGet(dfn: Future[DFNode]) =
try
Option(dfn.get(5, TimeUnit.SECONDS))
catch
case _: Throwable => None
private def TimedGet(dfn: Future[DFNode]) =
try
Option(dfn.get(5, TimeUnit.SECONDS))
catch
case _: Throwable => None

private class DFNodeTask(slice: DataFlowSlice, n: SliceNode) extends Callable[DFNode]:
override def call(): DFNode =
val inEs =
slice.edges.filter(e => DF_EDGES.contains(e.label) && e.dst == n.id).map(_.src)
val outEs =
slice.edges.filter(e => DF_EDGES.contains(e.label) && e.src == n.id).map(_.dst)
DFNode(n.id, n.isExternal, n.label, inEs, outEs)
private class DFNodeTask(slice: DataFlowSlice, n: SliceNode) extends Callable[DFNode]:
override def call(): DFNode =
val inEs =
slice.edges.filter(e => DF_EDGES.contains(e.label) && e.dst == n.id).map(_.src)
val outEs =
slice.edges.filter(e => DF_EDGES.contains(e.label) && e.src == n.id).map(_.dst)
DFNode(n.id, n.isExternal, n.label, inEs, outEs)
end DataFlowGraph
22 changes: 11 additions & 11 deletions src/main/scala/io/appthreat/atom/dataflows/OssDataFlow.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import io.appthreat.dataflowengineoss.semanticsloader.{FlowSemantic, Semantics}
import io.shiftleft.semanticcpg.layers.{LayerCreator, LayerCreatorContext, LayerCreatorOptions}

object OssDataFlow:
val overlayName: String = "dataflowOss"
val description: String = "Layer to support the atom data flow tracker"
val overlayName: String = "dataflowOss"
val description: String = "Layer to support the atom data flow tracker"

def defaultOpts = new OssDataFlowOptions()
def defaultOpts = new OssDataFlowOptions()

class OssDataFlowOptions(
var maxNumberOfDefinitions: Int = 2000,
Expand All @@ -20,12 +20,12 @@ class OssDataFlow(opts: OssDataFlowOptions)(implicit
s: Semantics = Semantics.fromList(DefaultSemantics().elements ++ opts.extraFlows)
) extends LayerCreator:

override val overlayName: String = OssDataFlow.overlayName
override val description: String = OssDataFlow.description
override val overlayName: String = OssDataFlow.overlayName
override val description: String = OssDataFlow.description

override def create(context: LayerCreatorContext, storeUndoInfo: Boolean): Unit =
val cpg = context.cpg
val enhancementExecList = Iterator(new DataDepsPass(cpg, opts.maxNumberOfDefinitions))
enhancementExecList.zipWithIndex.foreach { case (pass, index) =>
runPass(pass, context, storeUndoInfo, index)
}
override def create(context: LayerCreatorContext, storeUndoInfo: Boolean): Unit =
val cpg = context.cpg
val enhancementExecList = Iterator(new DataDepsPass(cpg, opts.maxNumberOfDefinitions))
enhancementExecList.zipWithIndex.foreach { case (pass, index) =>
runPass(pass, context, storeUndoInfo, index)
}
10 changes: 5 additions & 5 deletions src/main/scala/io/appthreat/atom/frontends/clike/C2Atom.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import scala.util.Try

class C2Atom 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).createAndApply()
}
def createCpg(config: Config): Try[Cpg] =
withNewEmptyCpg(config.outputPath, config) { (cpg, config) =>
new MetaDataPass(cpg, Languages.NEWC, config.inputPath).createAndApply()
new AstCreationPass(cpg, config).createAndApply()
}
Loading

0 comments on commit 73efd23

Please sign in to comment.