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

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

There is a newer version: 4.0.78
Show newest version
package io.joern.dataflowengineoss.language.nodemethods

import io.joern.dataflowengineoss.semanticsloader.*
import io.shiftleft.codepropertygraph.generated.nodes.{Call, Expression, Method}
import io.shiftleft.semanticcpg.language.*

class ExpressionMethods[NodeType <: Expression](val node: NodeType) extends AnyVal {

  /** Determine whether evaluation of the call this argument is a part of results in usage of this argument.
    */
  def isUsed(implicit semantics: Semantics): Boolean = {
    val s = semanticsForCallByArg
    s.isEmpty || s.exists(_.mappings.exists {
      case FlowMapping(ParameterNode(_, Some(srcName)), _) if node.argumentName.isDefined =>
        srcName == node.argumentName.get
      case FlowMapping(ParameterNode(srcIndex, _), _)    => srcIndex == node.argumentIndex
      case PassThroughMapping if node.argumentIndex != 0 => true
      case _                                             => false
    })
  }

  /** Determine whether evaluation of the call this argument is a part of results in definition of this argument.
    */
  def isDefined(implicit semantics: Semantics): Boolean = {
    val s = semanticsForCallByArg.l
    s.isEmpty || s.exists { semantic =>
      semantic.mappings.exists {
        case FlowMapping(_, ParameterNode(_, Some(dstName))) if node.argumentName.isDefined =>
          dstName == node.argumentName.get
        case FlowMapping(_, ParameterNode(dstIndex, _))    => dstIndex == node.argumentIndex
        case PassThroughMapping if node.argumentIndex != 0 => true
        case _                                             => false
      }
    }
  }

  /** Determines if this node and the given target node are arguments to the same call.
    * @param other
    *   the node to compare
    * @return
    *   true if these nodes are arguments to the same call, false if otherwise.
    */
  def isArgToSameCallWith(other: Expression): Boolean =
    node.astParent.start.collectAll[Call].headOption.equals(other.astParent.start.collectAll[Call].headOption)

  /** Determines if this node has a flow to the given target node in the defined semantics.
    * @param tgt
    *   the target node to check.
    * @param semantics
    *   the pre-defined flow semantics.
    * @return
    *   true if there is flow defined between the two nodes, false if otherwise.
    */
  def hasDefinedFlowTo(tgt: Expression)(implicit semantics: Semantics): Boolean = {
    val s = semanticsForCallByArg.l
    s.isEmpty || s.exists { semantic =>
      semantic.mappings.exists {
        case FlowMapping(ParameterNode(_, Some(srcName)), ParameterNode(_, Some(dstName)))
            if node.argumentName.isDefined && tgt.argumentName.isDefined =>
          srcName == node.argumentName.get && dstName == tgt.argumentName.get
        case FlowMapping(ParameterNode(_, Some(srcName)), ParameterNode(dstIndex, _)) if node.argumentName.isDefined =>
          srcName == node.argumentName.get && dstIndex == tgt.argumentIndex
        case FlowMapping(ParameterNode(srcIndex, _), ParameterNode(_, Some(dstName))) if tgt.argumentName.isDefined =>
          srcIndex == node.argumentIndex && dstName == tgt.argumentName.get
        case FlowMapping(ParameterNode(srcIndex, _), ParameterNode(dstIndex, _)) =>
          srcIndex == node.argumentIndex && dstIndex == tgt.argumentIndex
        case PassThroughMapping if tgt.argumentIndex == node.argumentIndex || tgt.argumentIndex == -1 => true
        case _                                                                                        => false
      }
    }
  }

  /** Retrieve flow semantic for the call this argument is a part of.
    */
  def semanticsForCallByArg(implicit semantics: Semantics): Iterator[FlowSemantic] = {
    argToMethods(node).flatMap(semantics.forMethod)
  }

  private def argToMethods(arg: Expression): Iterator[Method] = {
    arg.inCall.flatMap { call =>
      NoResolve.getCalledMethods(call)
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy