Skip to content

Commit

Permalink
Added hash to CPG metadata (#19)
Browse files Browse the repository at this point in the history
The hash is calculated as a checksum of all *.js input files.
This is done after transpiling. Otherwise, it may happen, that we end up with
no files for the hash calculation at all (e.g., for TS projects).
max-leuthaeuser authored Oct 4, 2021
1 parent dfa14cd commit 3fdac01
Showing 4 changed files with 28 additions and 8 deletions.
5 changes: 3 additions & 2 deletions src/main/scala/io/shiftleft/js2cpg/core/Js2Cpg.scala
Original file line number Diff line number Diff line change
@@ -198,12 +198,13 @@ class Js2Cpg {
val privateKeyFilePassPool = otherPools(3)
val htmlAsConfigPassPool = otherPools(4)

val cpg = newEmptyCpg(Some(config.outputFile))
val cpg = newEmptyCpg(Some(config.outputFile))
val hash = FileUtils.md5(jsFilesWithRoot.map(_._1))

new AstCreationPass(File(config.srcDir), jsFilesWithRoot, cpg, functionKeyPool, report)
.createAndApply()

new JsMetaDataPass(cpg, metaDataKeyPool).createAndApply()
new JsMetaDataPass(cpg, metaDataKeyPool, hash).createAndApply()
new BuiltinTypesPass(cpg, builtinTypesKeyPool).createAndApply()
new DependenciesPass(cpg, config, dependenciesKeyPool)
.createAndApply()
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
package io.shiftleft.js2cpg.cpg.passes

import io.shiftleft.codepropertygraph.Cpg
import io.shiftleft.codepropertygraph.generated.{Languages, nodes}
import io.shiftleft.codepropertygraph.generated.Languages
import io.shiftleft.codepropertygraph.generated.nodes.NewMetaData
import io.shiftleft.passes.{CpgPass, DiffGraph, KeyPool}
import org.slf4j.LoggerFactory

class JsMetaDataPass(cpg: Cpg, keyPool: KeyPool) extends CpgPass(cpg, keyPool = Some(keyPool)) {
class JsMetaDataPass(cpg: Cpg, keyPool: KeyPool, hash: String)
extends CpgPass(cpg, keyPool = Some(keyPool)) {

private val logger = LoggerFactory.getLogger(getClass)

override def run(): Iterator[DiffGraph] = {
logger.debug(s"Generating meta-data.")

val diffGraph = DiffGraph.newBuilder
val metaNode = nodes.NewMetaData().language(Languages.JAVASCRIPT)
val metaNode = NewMetaData().language(Languages.JAVASCRIPT).hash(hash)
diffGraph.addNode(metaNode)
Iterator(diffGraph.build())
}
17 changes: 15 additions & 2 deletions src/main/scala/io/shiftleft/js2cpg/io/FileUtils.scala
Original file line number Diff line number Diff line change
@@ -5,14 +5,15 @@ import better.files.File
import java.io.Reader
import java.math.BigInteger
import java.nio.charset.{CharsetDecoder, CodingErrorAction}
import java.nio.file.{Files, FileVisitResult, Path, SimpleFileVisitor}
import java.nio.file.{FileVisitResult, Files, Path, SimpleFileVisitor}
import io.shiftleft.js2cpg.core.Config
import io.shiftleft.js2cpg.io.FileDefaults._
import org.slf4j.LoggerFactory

import java.nio.file.attribute.BasicFileAttributes
import java.security.{DigestInputStream, MessageDigest}
import scala.collection.concurrent.TrieMap
import scala.collection.{mutable, SortedMap}
import scala.collection.{SortedMap, mutable}
import scala.io.{BufferedSource, Codec, Source}
import scala.jdk.CollectionConverters._

@@ -23,6 +24,18 @@ object FileUtils {
// we only want to print excluded files and folders once (Path -> Reason as String)
private val excludedPaths = TrieMap.empty[Path, String]

def md5(files: Seq[Path]): String = {
val md = MessageDigest.getInstance("MD5")
files.sortBy(_.toRealPath().toString).foreach { path =>
val dis = new DigestInputStream(Files.newInputStream(path), md)
while (dis.available() > 0) {
dis.read()
}
dis.close()
}
md.digest().map(b => String.format("%02x", Byte.box(b))).mkString
}

def logAndClearExcludedPaths(): Unit = {
excludedPaths.foreach {
case (path, reason) =>
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ class JsMetaDataPassTest extends AbstractPassTest {
val cpg = Cpg.emptyCpg
val jsMetaDataKeyPool = new IntervalKeyPool(1, 100)

new JsMetaDataPass(cpg, jsMetaDataKeyPool).createAndApply()
new JsMetaDataPass(cpg, jsMetaDataKeyPool, "somehash").createAndApply()

"create exactly 1 node" in {
cpg.graph.V.asScala.size shouldBe 1
@@ -26,6 +26,10 @@ class JsMetaDataPassTest extends AbstractPassTest {
"create a metadata node with correct language" in {
cpg.metaData.language.l shouldBe List(Languages.JAVASCRIPT)
}

"create a metadata node with a hash" in {
cpg.metaData.hash.l shouldBe List("somehash")
}
}

}

0 comments on commit 3fdac01

Please sign in to comment.