Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update chen to bring c fullname improvements #150

Merged
merged 1 commit into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading