Skip to content

Commit

Permalink
[dataflowengineoss] Passes/PassesNot Fix (#4494)
Browse files Browse the repository at this point in the history
In a more naive time in my life, I wrote #1423, but this did not *exactly* achieve what I wanted, since this is designed for sanitizers. This also took a set argument, which was a bit weird.

This fixes the above approach, by actually checking the path for the element in the traversal.

Note: For some calls, one might need to have something like `sink.reachableByFlows(source).passesNot(_.collectAll[Expression].inCall.name("sanitizer"))"` as the way the path elements are presented, the call may be skipped in languages such as Python.

Resolves #2438
Resolves #2175
  • Loading branch information
DavidBakerEffendi authored Apr 28, 2024
1 parent 69affbe commit deec496
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package io.joern.dataflowengineoss

import io.shiftleft.codepropertygraph.generated.nodes._
import io.shiftleft.codepropertygraph.generated.nodes.*
import io.shiftleft.semanticcpg.language.*
import io.joern.dataflowengineoss.language.dotextension.DdgNodeDot
import io.joern.dataflowengineoss.language.nodemethods.{ExpressionMethods, ExtendedCfgNodeMethods}
import overflowdb.traversal.help.Doc

import scala.language.implicitConversions

package object language {

Expand All @@ -21,4 +25,21 @@ package object language {
implicit def toDdgNodeDotSingle(method: Method): DdgNodeDot =
new DdgNodeDot(Iterator.single(method))

implicit def toExtendedPathsTrav[NodeType <: Path](traversal: IterableOnce[NodeType]): PassesExt =
new PassesExt(traversal.iterator)

class PassesExt(traversal: Iterator[Path]) {

@Doc(info = "Filters in paths that pass though the given paths")
def passes(trav: Iterator[AstNode] => Iterator[?]): Iterator[Path] = {
traversal.filter(_.elements.exists(_.start.where(trav).nonEmpty))
}

@Doc(info = "Filters out paths that pass though the given paths")
def passesNot(trav: Iterator[AstNode] => Iterator[?]): Iterator[Path] = {
traversal.filter(_.elements.forall(_.start.where(trav).isEmpty))
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -83,26 +83,6 @@ class CfgNodeMethods(val node: CfgNode) extends AnyVal with NodeExtension {
}
}

/** Using the post dominator tree, will determine if this node passes through the included set of nodes and filter it
* in.
* @param included
* the nodes this node must pass through.
* @return
* the traversal of this node if it passes through the included set.
*/
def passes(included: Set[CfgNode]): Iterator[CfgNode] =
Iterator.single(node).filter(_.postDominatedBy.exists(included.contains))

/** Using the post dominator tree, will determine if this node passes through the excluded set of nodes and filter it
* out.
* @param excluded
* the nodes this node must not pass through.
* @return
* the traversal of this node if it does not pass through the excluded set.
*/
def passesNot(excluded: Set[CfgNode]): Iterator[CfgNode] =
Iterator.single(node).filterNot(_.postDominatedBy.exists(excluded.contains))

private def expandExhaustively(expand: CfgNode => Iterator[StoredNode]): Iterator[CfgNode] = {
var controllingNodes = List.empty[CfgNode]
var visited = Set.empty + node
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,4 @@ class CfgNodeTraversal[A <: CfgNode](val traversal: Iterator[A]) extends AnyVal
def address: Iterator[Option[String]] =
traversal.map(_.address)

@Doc(info = "Filters in paths that pass though the given traversal")
def passes(included: Iterator[CfgNode]): Iterator[CfgNode] = {
val in = included.toSet
traversal.flatMap(_.passes(in))
}

@Doc(info = "Filters out paths that pass though the given traversal")
def passesNot(excluded: Iterator[CfgNode]): Iterator[CfgNode] = {
val ex = excluded.toSet
traversal.flatMap(_.passesNot(ex))
}

}

0 comments on commit deec496

Please sign in to comment.