Skip to content

Commit

Permalink
[dataflowengineoss] globalFromLit only when it's a standalone assignm…
Browse files Browse the repository at this point in the history
…ent (joernio#4559)

* [dataflowengineoss] globalFromLit trigger only when it's a standalone assignment

* fix unit-tests
  • Loading branch information
xavierpinho authored May 15, 2024
1 parent 91614ff commit 4f78879
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import io.shiftleft.semanticcpg.language.*

package object dataflowengineoss {

def globalFromLiteral(lit: Literal): Iterator[Expression] = lit.start.inAssignment
def globalFromLiteral(lit: Literal): Iterator[Expression] = lit.start.inCall.assignment
.where(_.method.isModule)
.argument(1)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.joern.pysrc2cpg

import io.joern.dataflowengineoss.DefaultSemantics
import io.joern.dataflowengineoss.language.Path
import io.joern.dataflowengineoss.layers.dataflows.*
import io.joern.dataflowengineoss.queryengine.EngineContext
import io.joern.dataflowengineoss.semanticsloader.{FlowSemantic, Semantics}
Expand Down Expand Up @@ -61,4 +62,8 @@ class PySrc2CpgFixture(

implicit val resolver: ICallResolver = NoResolve

protected def flowToResultPairs(path: Path): List[(String, Integer)] =
path.resultPairs().collect { case (firstElement: String, secondElement: Option[Integer]) =>
(firstElement, secondElement.getOrElse(-1))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ class DataFlowTests extends PySrc2CpgFixture(withOssDataflow = true) {
sink.reachableByFlows(source).size shouldBe 1
}

"intra-procedural 2" in {
val cpg = code("""
|x = foo(20)
|print(x)
|""".stripMargin)
val source = cpg.literal("20")
val sink = cpg.call("print").argument
val List(flow) = sink.reachableByFlows(source).map(flowToResultPairs).distinct.sortBy(_.length).l
flow shouldBe List(("foo(20)", 2), ("x = foo(20)", 2), ("print(x)", 3))
}

"chained call" in {
val cpg: Cpg = code("""
|a = 42
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,10 @@ class ArrayTests extends RubyCode2CpgFixture(withPostProcessing = true, withData
|puts a
|""".stripMargin)

val source = cpg.literal.code("b").l
val sink = cpg.call.name("puts").argument(1).l
sink.reachableByFlows(source).size shouldBe 2
val source = cpg.literal.code("b").l
val sink = cpg.call.name("puts").argument(1).l
val List(flow) = sink.reachableByFlows(source).map(flowToResultPairs).distinct.sortBy(_.length).l
flow shouldBe List(("%w[b c]", 2), ("a = %w[b c]", 2), ("puts a", 3))
}

"flow through %i array" in {
Expand All @@ -129,9 +130,22 @@ class ArrayTests extends RubyCode2CpgFixture(withPostProcessing = true, withData
|puts a
|""".stripMargin)

val source = cpg.literal.code("b").l
val sink = cpg.call.name("puts").argument(1).l
sink.reachableByFlows(source).size shouldBe 2
val source = cpg.literal.code("b").l
val sink = cpg.call.name("puts").argument(1).l
val List(flow) = sink.reachableByFlows(source).map(flowToResultPairs).distinct.sortBy(_.length).l
flow shouldBe List(
(
"""|%i[b
| c]""".stripMargin,
2
),
(
"""|a = %i[b
| c]""".stripMargin,
2
),
("puts a", 4)
)
}

"flow through array constructor using []" in {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,9 +290,30 @@ class CallTests extends RubyCode2CpgFixture(withPostProcessing = true, withDataF
|puts y
|""".stripMargin)

val src = cpg.literal.code("1").l
val sink = cpg.call.name("puts").argument(1).l
sink.reachableByFlows(src).size shouldBe 2
val src = cpg.literal.code("1").l
val sink = cpg.call.name("puts").argument(1).l
val List(flow) = sink.reachableByFlows(src).map(flowToResultPairs).distinct.sortBy(_.length).l
flow shouldBe List(
(
"""|foo
| .bar(1)""".stripMargin,
11
),
("bar(this, x)", 3),
("return x", 4),
("RET", 3),
(
"""|foo
| .bar(1)""".stripMargin,
10
),
(
"""|y = foo
| .bar(1)""".stripMargin,
10
),
("puts y", 12)
)
}

"flow through a method call present in next line, with the first line ending with `.`" in {
Expand All @@ -310,8 +331,29 @@ class CallTests extends RubyCode2CpgFixture(withPostProcessing = true, withDataF
|puts y
|""".stripMargin)

val src = cpg.literal.code("1").l
val sink = cpg.call.name("puts").argument(1).l
sink.reachableByFlows(src).size shouldBe 2
val src = cpg.literal.code("1").l
val sink = cpg.call.name("puts").argument(1).l
val List(flow) = sink.reachableByFlows(src).map(flowToResultPairs).distinct.sortBy(_.length).l
flow shouldBe List(
(
"""|foo.
| bar(1)""".stripMargin,
11
),
("bar(this, x)", 3),
("return x", 4),
("RET", 3),
(
"""|foo.
| bar(1)""".stripMargin,
10
),
(
"""|y = foo.
| bar(1)""".stripMargin,
10
),
("puts y", 12)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,12 @@ class SingleAssignmentTests extends RubyCode2CpgFixture(withPostProcessing = tru
val source = cpg.literal.l
val sink = cpg.method.name("puts").callIn.argument.l
val flows = sink.reachableByFlows(source).map(flowToResultPairs).distinct.sortBy(_.length).l
flows.size shouldBe 6
val List(flow1, flow2, flow3, flow4, flow5, flow6) = flows
val List(flow1, flow2, flow3, flow4, flow5) = flows
flow1 shouldBe List(("y = 1", 2), ("puts y", 3))
flow2 shouldBe List(("y = 1", 2), ("x = y = 1", 2), ("puts x", 4))
flow3 shouldBe List(("y = 1", 2), ("z = x = y = 1", 2), ("puts z", 5))
flow4 shouldBe List(("y = 1", 2), ("puts y", 3), ("puts x", 4))
flow2 shouldBe List(("y = 1", 2), ("puts y", 3), ("puts x", 4))
flow3 shouldBe List(("y = 1", 2), ("x = y = 1", 2), ("puts x", 4))
flow4 shouldBe List(("y = 1", 2), ("x = y = 1", 2), ("z = x = y = 1", 2), ("puts z", 5))
flow5 shouldBe List(("y = 1", 2), ("x = y = 1", 2), ("puts x", 4), ("puts z", 5))
flow6 shouldBe List(("y = 1", 2), ("x = y = 1", 2), ("z = x = y = 1", 2), ("puts z", 5))
}

"flow through expressions" in {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2498,9 +2498,10 @@ class DataFlowTests
|puts a
|""".stripMargin)

val source = cpg.literal.code("b").l
val sink = cpg.call.name("puts").l
sink.reachableByFlows(source).size shouldBe 2
val source = cpg.literal.code("b").l
val sink = cpg.call.name("puts").l
val List(flow) = sink.reachableByFlows(source).map(flowToResultPairs).distinct.sortBy(_.length).l
flow shouldBe List(("[b, c]", 2), ("[b, c]", -1), ("a = %w[b c]", 2), ("puts a", 3))
}

"flow through hash containing splatting literal" in {
Expand Down Expand Up @@ -2585,9 +2586,19 @@ class DataFlowTests
|puts a
|""".stripMargin)

val source = cpg.literal.code("b").l
val sink = cpg.call.name("puts").l
sink.reachableByFlows(source).size shouldBe 2
val source = cpg.literal.code("b").l
val sink = cpg.call.name("puts").l
val List(flow) = sink.reachableByFlows(source).map(flowToResultPairs).distinct.sortBy(_.length).l
flow shouldBe List(
("[b, c]", 2),
("[b, c]", -1),
(
"""|a = %i[b
| c]""".stripMargin,
2
),
("puts a", 4)
)
}

"flow through array constructor using []" in {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class RubyCode2CpgFixture(

protected def flowToResultPairs(path: Path): List[(String, Integer)] =
path.resultPairs().collect { case (firstElement: String, secondElement: Option[Integer]) =>
(firstElement, secondElement.get)
(firstElement, secondElement.getOrElse(-1))
}
}

Expand Down

0 comments on commit 4f78879

Please sign in to comment.