diff --git a/build.sbt b/build.sbt index 671a8efc..f041219f 100644 --- a/build.sbt +++ b/build.sbt @@ -3,7 +3,7 @@ name := "Plume" inThisBuild( List( organization := "com.github.plume-oss", - version := "1.2.1", + version := "1.2.2", scalaVersion := "2.13.8", crossScalaVersions := Seq("2.13.8", "3.1.1"), resolvers ++= Seq( @@ -15,8 +15,8 @@ inThisBuild( ) ) -val cpgVersion = "1.3.523" -val joernVersion = "1.1.678" +val cpgVersion = "1.3.527" +val joernVersion = "1.1.692" val sootVersion = "4.3.0" val tinkerGraphVersion = "3.4.11" val neo4jVersion = "4.4.5" diff --git a/src/main/scala/com/github/plume/oss/domain/package.scala b/src/main/scala/com/github/plume/oss/domain/package.scala index e5c3706a..319ca757 100644 --- a/src/main/scala/com/github/plume/oss/domain/package.scala +++ b/src/main/scala/com/github/plume/oss/domain/package.scala @@ -32,7 +32,8 @@ package object domain { dataFlowCacheFile: Option[Path] = Some(Paths.get("dataFlowCache.cbor")), compressDataFlowCache: Boolean = true, maxCallDepth: Int = 2, - maxCachedPaths: Int = 1_000 + maxCachedPaths: Int = 1_000, + shareCacheBetweenTasks: Boolean = false ) /** Given an object and a path, will serialize the object to the given path. diff --git a/src/main/scala/com/github/plume/oss/drivers/OverflowDbDriver.scala b/src/main/scala/com/github/plume/oss/drivers/OverflowDbDriver.scala index cb7a023a..bcc3a364 100644 --- a/src/main/scala/com/github/plume/oss/drivers/OverflowDbDriver.scala +++ b/src/main/scala/com/github/plume/oss/drivers/OverflowDbDriver.scala @@ -90,7 +90,8 @@ final case class OverflowDbDriver( Semantics.fromList(List()), EngineConfig( maxCallDepth = cacheConfig.maxCallDepth, - initialTable = resultTable + initialTable = resultTable, + shareCacheBetweenTasks = cacheConfig.shareCacheBetweenTasks ) ) @@ -120,7 +121,8 @@ final case class OverflowDbDriver( def setDataflowContext( maxCallDepth: Int, methodSemantics: Option[BufferedSource] = None, - initialCache: Option[ResultTable] = None + initialCache: Option[ResultTable] = None, + shareCacheBetweenTasks: Boolean = false ): EngineContext = { val cache = if (initialCache.isDefined) initialCache else resultTable @@ -129,7 +131,8 @@ final case class OverflowDbDriver( setDataflowContext( maxCallDepth, Semantics.fromList(semanticsParser.parse(methodSemantics.get.getLines().mkString("\n"))), - cache + cache, + shareCacheBetweenTasks ) } else if (defaultSemantics.isSuccess) { logger.info( @@ -138,24 +141,26 @@ final case class OverflowDbDriver( setDataflowContext( maxCallDepth, Semantics.fromList(semanticsParser.parse(defaultSemantics.get.getLines().mkString("\n"))), - cache + cache, + shareCacheBetweenTasks ) } else { logger.warn( "No \"default.semantics\" file found under resources - data flow tracking may not perform correctly." ) - setDataflowContext(maxCallDepth, Semantics.fromList(List()), cache) + setDataflowContext(maxCallDepth, Semantics.fromList(List()), cache, shareCacheBetweenTasks) } } private def setDataflowContext( maxCallDepth: Int, methodSemantics: Semantics, - cache: Option[ResultTable] + cache: Option[ResultTable], + shareCacheBetweenTasks: Boolean ): EngineContext = { context = EngineContext( methodSemantics, - EngineConfig(maxCallDepth, cache) + EngineConfig(maxCallDepth, cache, shareCacheBetweenTasks) ) context } @@ -412,7 +417,12 @@ final case class OverflowDbDriver( case Some(_) => val oldCache = resultTable.getOrElse(new ResultTable) if (oldCache.table.map(_._2.size).sum <= cacheConfig.maxCachedPaths) { - setDataflowContext(context.config.maxCallDepth, context.semantics, Some(oldCache)) + setDataflowContext( + context.config.maxCallDepth, + context.semantics, + Some(oldCache), + cacheConfig.shareCacheBetweenTasks + ) } else { val newCache = new ResultTable var currPathsInCache = 0 @@ -428,7 +438,12 @@ final case class OverflowDbDriver( } oldCache.table.clear() resultTable = Some(newCache) - setDataflowContext(context.config.maxCallDepth, context.semantics, resultTable) + setDataflowContext( + context.config.maxCallDepth, + context.semantics, + resultTable, + cacheConfig.shareCacheBetweenTasks + ) } case _ => } diff --git a/src/test/scala/com/github/plume/oss/querying/ArrayTests.scala b/src/test/scala/com/github/plume/oss/querying/ArrayTests.scala index c3c8d9ef..9eb64a87 100644 --- a/src/test/scala/com/github/plume/oss/querying/ArrayTests.scala +++ b/src/test/scala/com/github/plume/oss/querying/ArrayTests.scala @@ -33,12 +33,12 @@ class ArrayTests extends Jimple2CpgFixture { def m = cpg.method(".*foo.*") val List(placeholderArg: Identifier, arrayInit: Call) = - m.assignment.codeExact("$stack2 = newarray (int)[3]").argument.l + m.assignment.codeExact("$stack2 = new int[3]").argument.l placeholderArg.code shouldBe "$stack2" placeholderArg.typeFullName shouldBe "int[]" - arrayInit.code shouldBe "newarray (int)[3]" - arrayInit.methodFullName shouldBe Operators.arrayInitializer + arrayInit.code shouldBe "new int[3]" + arrayInit.methodFullName shouldBe ".arrayCreator" arrayInit.astChildren.headOption match { case Some(alloc) => alloc shouldBe a[Literal] @@ -84,11 +84,11 @@ class ArrayTests extends Jimple2CpgFixture { def m = cpg.method(".*bar.*") val List(arg1: Identifier, arg2: Call) = - m.assignment.codeExact("x = newmultiarray (int)[5][2]").argument.l + m.assignment.codeExact("x = new int[5][2]").argument.l arg1.typeFullName shouldBe "int[][]" - arg2.code shouldBe "newmultiarray (int)[5][2]" + arg2.code shouldBe "new int[5][2]" val List(lvl1: Literal, lvl2: Literal) = arg2.argument.l lvl1.code shouldBe "5" lvl2.code shouldBe "2" diff --git a/src/test/scala/com/github/plume/oss/querying/IfGotoTests.scala b/src/test/scala/com/github/plume/oss/querying/IfGotoTests.scala index a92d0edf..80464e3b 100644 --- a/src/test/scala/com/github/plume/oss/querying/IfGotoTests.scala +++ b/src/test/scala/com/github/plume/oss/querying/IfGotoTests.scala @@ -30,11 +30,7 @@ class IfGotoTests extends Jimple2CpgFixture { |""".stripMargin "should identify `goto` blocks" in { - cpg.all.collect { case x: Unknown => x }.code.toSet shouldBe Set( - "goto [?= $stack6 = y]", - "goto [?= i = i + 1]", - "goto [?= (branch)]" - ) + cpg.all.collect { case x: Unknown => x }.code.toSet shouldBe Set("goto 5", "goto 9") } "should contain 4 branching nodes at conditional calls" in { diff --git a/src/test/scala/com/github/plume/oss/querying/MethodReturnTests.scala b/src/test/scala/com/github/plume/oss/querying/MethodReturnTests.scala index 1b1cbca9..525aa016 100644 --- a/src/test/scala/com/github/plume/oss/querying/MethodReturnTests.scala +++ b/src/test/scala/com/github/plume/oss/querying/MethodReturnTests.scala @@ -22,6 +22,15 @@ class MethodReturnTests extends Jimple2CpgFixture { x.order shouldBe 2 } + "should have a RETURN node with correct fields" in { + val List(x) = cpg.method.name("foo").ast.isReturn.l + x.code shouldBe "return 1;" + x.order shouldBe 2 + x.argumentIndex shouldBe 2 + x.astChildren.size shouldBe 1 + x.argumentOut.size shouldBe 1 + } + "should allow traversing to method" in { cpg.methodReturn.code("int").method.name.l shouldBe List("foo") }