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

io.joern.dataflowengineoss.language.nodemethods.ExtendedCfgNodeMethods.scala Maven / Gradle / Ivy

package io.joern.dataflowengineoss.language.nodemethods

import io.joern.dataflowengineoss.DefaultSemantics
import io.joern.dataflowengineoss.language.*
import io.joern.dataflowengineoss.queryengine.{Engine, EngineContext, PathElement}
import io.joern.dataflowengineoss.semanticsloader.Semantics
import io.shiftleft.codepropertygraph.generated.nodes.*
import io.shiftleft.semanticcpg.language.*

import scala.collection.mutable
import scala.jdk.CollectionConverters.*

class ExtendedCfgNodeMethods[NodeType <: CfgNode](val node: NodeType) extends AnyVal {

  /** Convert to nearest AST node
    */
  def astNode: AstNode = node

  def reachableBy[NodeType](sourceTrav: Iterator[NodeType], sourceTravs: IterableOnce[NodeType]*)(implicit
    context: EngineContext
  ): Iterator[NodeType] =
    node.start.reachableBy(sourceTrav, sourceTravs*)

  def ddgIn(implicit semantics: Semantics = DefaultSemantics()): Iterator[CfgNode] = {
    val cache  = mutable.HashMap[CfgNode, Vector[PathElement]]()
    val result = ddgIn(Vector(PathElement(node)), withInvisible = false, cache)
    cache.clear()
    result
  }

  def ddgInPathElem(
    withInvisible: Boolean,
    cache: mutable.HashMap[CfgNode, Vector[PathElement]] = mutable.HashMap[CfgNode, Vector[PathElement]]()
  )(implicit semantics: Semantics): Iterator[PathElement] =
    ddgInPathElem(Vector(PathElement(node)), withInvisible, cache)

  def ddgInPathElem(implicit semantics: Semantics): Iterator[PathElement] = {
    val cache  = mutable.HashMap[CfgNode, Vector[PathElement]]()
    val result = ddgInPathElem(Vector(PathElement(node)), withInvisible = false, cache)
    cache.clear()
    result
  }

  /** Traverse back in the data dependence graph by one step, taking into account semantics
    * @param path
    *   optional list of path elements that have been expanded already
    */
  def ddgIn(path: Vector[PathElement], withInvisible: Boolean, cache: mutable.HashMap[CfgNode, Vector[PathElement]])(
    implicit semantics: Semantics
  ): Iterator[CfgNode] = {
    ddgInPathElem(path, withInvisible, cache).map(_.node.asInstanceOf[CfgNode])
  }

  /** Traverse back in the data dependence graph by one step and generate corresponding PathElement, taking into account
    * semantics
    * @param path
    *   optional list of path elements that have been expanded already
    */
  def ddgInPathElem(
    path: Vector[PathElement],
    withInvisible: Boolean,
    cache: mutable.HashMap[CfgNode, Vector[PathElement]]
  )(implicit semantics: Semantics): Iterator[PathElement] = {
    val result = ddgInPathElemInternal(path, withInvisible, cache).iterator
    result
  }

  private def ddgInPathElemInternal(
    path: Vector[PathElement],
    withInvisible: Boolean,
    cache: mutable.HashMap[CfgNode, Vector[PathElement]]
  )(implicit semantics: Semantics): Vector[PathElement] = {

    if (cache.contains(node)) {
      return cache(node)
    }

    val elems = Engine.expandIn(node, path)
    val result = if (withInvisible) {
      elems
    } else {
      (elems.filter(_.visible) ++ elems
        .filterNot(_.visible)
        .flatMap(x => x.node.asInstanceOf[CfgNode].ddgInPathElem(x +: path, withInvisible = false, cache))).distinct
    }
    cache.put(node, result)
    result
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy