Skip to content
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
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name := "joern"
ThisBuild / organization := "io.joern"
ThisBuild / scalaVersion := "3.6.4"

val cpgVersion = "1.7.35"
val cpgVersion = "1.7.36"

lazy val joerncli = Projects.joerncli
lazy val querydb = Projects.querydb
Expand Down
2 changes: 1 addition & 1 deletion console/src/main/scala/io/joern/console/scan/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ package object scan {

/** Print human readable list of findings to standard out.
*/
def outputFindings(cpg: Cpg)(implicit finder: NodeExtensionFinder): Unit = {
def outputFindings(cpg: Cpg)(implicit locationCreator: LocationCreator): Unit = {
cpg.finding.sortBy(_.score.toInt).foreach { finding =>
val evidence = finding.evidence.headOption
.map { e =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ import io.shiftleft.semanticcpg.language.*
class CodeDumperTests extends JavaSrcCode2CpgFixture {

"a Java source code CPG" should {

implicit val finder: NodeExtensionFinder = DefaultNodeExtensionFinder

val cpg = code("""
|public class Foo {
|
Expand Down
4 changes: 1 addition & 3 deletions joern-cli/src/main/scala/io/joern/joerncli/JoernScan.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import io.joern.joerncli.JoernScan.getQueriesFromQueryDb
import io.joern.joerncli.Scan.{allTag, defaultTag}
import io.joern.joerncli.console.ReplBridge
import io.shiftleft.codepropertygraph.generated.Languages
import io.shiftleft.semanticcpg.language.{DefaultNodeExtensionFinder, NodeExtensionFinder}
import io.shiftleft.semanticcpg.language.{DefaultNodeExtensionFinder, NodeExtensionFinder, locationCreator}
import io.shiftleft.semanticcpg.layers.{LayerCreator, LayerCreatorContext, LayerCreatorOptions}
import io.shiftleft.semanticcpg.utils.FileUtil
import io.shiftleft.semanticcpg.utils.FileUtil.*
Expand Down Expand Up @@ -259,8 +259,6 @@ class ScanOptions(var maxCallDepth: Int, var names: Array[String], var tags: Arr
extends LayerCreatorOptions {}

class Scan(options: ScanOptions)(implicit engineContext: EngineContext) extends LayerCreator {
implicit val finder: NodeExtensionFinder = DefaultNodeExtensionFinder

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

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.shiftleft.semanticcpg.codedumper

import io.shiftleft.codepropertygraph.generated.Languages
import io.shiftleft.codepropertygraph.generated.nodes.{Expression, Local, Method, NewLocation}
import io.shiftleft.codepropertygraph.generated.nodes.{Expression, Local, Method}
import io.shiftleft.semanticcpg.language.*
import io.shiftleft.utils.IOUtils
import org.slf4j.{Logger, LoggerFactory}
Expand Down Expand Up @@ -39,7 +39,7 @@ object CodeDumper {
/** Dump string representation of code at given `location`.
*/
def dump(
location: NewLocation,
location: LocationInfo,
language: Option[String],
rootPath: Option[String],
highlight: Boolean,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package io.shiftleft.semanticcpg.language

import io.shiftleft.codepropertygraph.generated.nodes.*
import io.shiftleft.codepropertygraph.generated.{Properties, PropertyNames}
import io.shiftleft.semanticcpg.language.*

import scala.annotation.tailrec

trait LocationInfo {
def node: Option[AbstractNode]
def symbol: String
def nodeLabel: String
def lineNumber: Option[Int]
def methodFullName: String
def methodShortName: String
def packageName: String
def className: String
def classShortName: String
def filename: String
}

// Previously, the non-stored Location node generated
// from the CPG schema was named NewLocation. The
// addition of lazily computed location info in this
// file brought the deletion of these CPG nodes. This
// is not directly used in joern, but intended to not
// break usage in users of the API. Users directly
// importing NewLocation from the CPG package rather
// will still have a break.
@deprecated("NewLocation is deprecated, prefer LocationInfo")
type NewLocation = LocationInfo

// This design: 1) lets implementors put all logic for
// determining how to fill out `LocationInfo` for each
// type of node in one central place, and 2) allow consumers
// of joern, which may also provide different node types
// and/or location information, to provide alternate or
// extended implementations of LocationCreator.
trait LocationCreator {
implicit def apply(node: StoredNode, filenameOverride: Option[String] = None): LocationInfo
}

object EmptyLocation extends LocationInfo {
override def node: Option[AbstractNode] = None
override def symbol: String = "<empty>"
override def nodeLabel: String = "<empty>"
override def lineNumber: Option[Int] = None
override def methodFullName: String = "<empty>"
override def methodShortName: String = "<empty>"
override def packageName: String = "<empty>"
override def className: String = "<empty>"
override def classShortName: String = "<empty>"
override def filename: String = "<empty>"
}

object LazyLocation extends LocationCreator {
implicit def apply(node: StoredNode, filenameOverride: Option[String] = None): LocationInfo = {
new LazyLocation(node, filenameOverride)
}
}

implicit val locationCreator: LocationCreator = LazyLocation

class LazyLocation(storedNode: StoredNode, filenameOverride: Option[String]) extends LocationInfo with Product {
def node: Option[AbstractNode] = Some(storedNode)

def symbol: String = {
storedNode match {
case _: Call | _: Literal | _: MethodRef | _: Block | _: JumpTarget | _: Member | _: TemplateDom =>
storedNode.property(Properties.Code)
case _: Identifier | _: Local | _: MethodParameterIn | _: MethodParameterOut | _: Method =>
storedNode.property(Properties.Name)
case _: MethodReturn => "$ret"
case cfgFile: ConfigFile => cfgFile.content
case _ => defaultString
}
}

def nodeLabel: String = storedNode.label

def lineNumber: Option[Int] = storedNode.propertyOption[Int](PropertyNames.LINE_NUMBER)

def methodFullName: String = method.fullName

def methodShortName: String = method.name

def packageName: String = namespaceOption.getOrElse(defaultString)

def className: String = typeOption.map(_.fullName).getOrElse(defaultString)

def classShortName: String = typeOption.map(_.name).getOrElse(defaultString)

def filename: String = filenameOverride.getOrElse(if (method.filename.isEmpty) "N/A" else method.filename)

final protected val defaultString = "<empty>";

private lazy val typeOption = findParentTypeDecl(method)

private lazy val namespaceOption = for {
tpe <- typeOption
namespaceBlock <- tpe.namespaceBlock
namespace <- namespaceBlock._namespaceViaRefOut.nextOption()
} yield namespace.name

private lazy val method: Method = storedNode match {
case cfgNode: CfgNode => cfgNode.method
case local: Local => local.method.head
}

@tailrec
private def findParentTypeDecl(node: StoredNode): Option[TypeDecl] = {
node._astIn.iterator.nextOption() match {
case Some(head) if head.isInstanceOf[TypeDecl] => Some(head.asInstanceOf[TypeDecl])
case Some(head) => findParentTypeDecl(head)
case None => None
}
}

// The product implementation is required for json serialization. See io.shiftleft.semanticcpg.language.Steps
private lazy val productElements: Array[(String, Any)] = Array(
("packageName", packageName),
("symbol", symbol),
("filename", filename),
("className", className),
("methodFullName", methodFullName),
("classShortName", classShortName),
("methodShortName", methodShortName),
("node", node),
("_label", "LOCATION"),
("nodeLabel", nodeLabel),
("lineNumber", lineNumber)
)

override def canEqual(that: Any): Boolean = that != null && that.isInstanceOf[LazyLocation]

override def productArity: Int = productElements.size

override def productElementName(n: Int): String = {
productElements(n)._1
}

override def productElement(n: Int): Any = {
productElements(n)._2
}

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class NodeSteps[NodeType <: StoredNode](val traversal: Iterator[NodeType]) exten
|on the user's side.
|"""
)
def location(implicit finder: NodeExtensionFinder): Iterator[NewLocation] =
def location(implicit locationCreator: LocationCreator): Iterator[LocationInfo] =
traversal.map(_.location)

@Doc(
Expand All @@ -56,7 +56,7 @@ class NodeSteps[NodeType <: StoredNode](val traversal: Iterator[NodeType]) exten
|This only works for source frontends.
|"""
)
def dump(implicit finder: NodeExtensionFinder): List[String] =
def dump(implicit locationCreator: LocationCreator): List[String] =
_dump(highlight = true)

@Doc(
Expand All @@ -67,10 +67,10 @@ class NodeSteps[NodeType <: StoredNode](val traversal: Iterator[NodeType]) exten
|to the expression. No color highlighting.
|"""
)
def dumpRaw(implicit finder: NodeExtensionFinder): List[String] =
def dumpRaw(implicit locationCreator: LocationCreator): List[String] =
_dump(highlight = false)

private def _dump(highlight: Boolean)(implicit finder: NodeExtensionFinder): List[String] = {
private def _dump(highlight: Boolean)(implicit locationCreator: LocationCreator): List[String] = {
// initialized on first element as we need the graph for retrieving the metaData node.
// TODO: there should be a step to retrieve the metaData node for any node
// so we could avoid instantiating a new Cpg everytime using dump
Expand Down
Loading
Loading