Skip to content

Commit

Permalink
Make flows via statically dispatched methods work (#2810)
Browse files Browse the repository at this point in the history
* Make flows via statically dispatched methods work

* Fixed IdentifierTests

---------

Co-authored-by: Fabian Yamaguchi <fabs@joern.io>
  • Loading branch information
fabsx00 and Fabian Yamaguchi committed Jun 5, 2023
1 parent e2542f3 commit daa68e3
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1192,12 +1192,13 @@ class AstCreator(filename: String, global: Global)
}

def astForCallNode(localIdentifier: TerminalNode): Seq[Ast] = {
val column = localIdentifier.getSymbol().getCharPositionInLine()
val line = localIdentifier.getSymbol().getLine()
val name = getActualMethodName(localIdentifier.getText)
val column = localIdentifier.getSymbol().getCharPositionInLine()
val line = localIdentifier.getSymbol().getLine()
val name = getActualMethodName(localIdentifier.getText)
val methodFullName = s"$filename:$name"
val callNode = NewCall()
.name(name)
.methodFullName(name)
.methodFullName(methodFullName)
.signature(localIdentifier.getText())
.typeFullName(MethodFullNames.UnknownFullName)
.dispatchType(DispatchTypes.STATIC_DISPATCH)
Expand Down Expand Up @@ -1401,11 +1402,13 @@ class AstCreator(filename: String, global: Global)
val astBody = astForBodyStatementContext(ctx.bodyStatement())
popScope()

// TODO why is there a `callNode` here?

val classPath = classStack.toList.mkString(".") + "."
val methodNode = NewMethod()
.code(callNode.code)
.name(callNode.name)
.fullName(classPath + callNode.name)
.fullName(s"$filename:${callNode.name}")
.columnNumber(callNode.columnNumber)
.lineNumber(callNode.lineNumber)
.filename(filename)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,25 @@ class DataFlowTests extends DataFlowCodeToCpgSuite {
sink.reachableByFlows(source).l.size shouldBe 2
}
}

"Flow via call" should {
val cpg = code("""
|def print(content)
|puts content
|end
|
|def main
|n = 1
|print( n )
|end
|""".stripMargin)

"be found" in {
implicit val resolver: ICallResolver = NoResolve
val src = cpg.identifier.name("n").where(_.inCall.name("print")).l
val sink = cpg.method.name("puts").callIn.argument(1).l
sink.reachableByFlows(src).size shouldBe 1
}
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.joern.rubysrc2cpg.querying

import io.joern.rubysrc2cpg.testfixtures.RubyCode2CpgFixture
import io.shiftleft.codepropertygraph.generated.nodes.Method
import io.shiftleft.semanticcpg.language._

class CallGraphTests extends RubyCode2CpgFixture {
Expand All @@ -18,8 +19,11 @@ class CallGraphTests extends RubyCode2CpgFixture {
"should identify call from `foo` to `bar`" in {
val List(callToBar) = cpg.call("bar").l
callToBar.name shouldBe "bar"
callToBar.methodFullName.matches(".*Test.*.rb:bar") shouldBe true
callToBar.lineNumber shouldBe Some(7)
cpg.method("bar").caller.name.l shouldBe List("foo")
val List(bar: Method) = cpg.method("bar").internal.l
bar.fullName shouldBe callToBar.methodFullName
bar.caller.name.l shouldBe List("foo")
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class IdentifierTests extends RubyCode2CpgFixture {
cpg.method.name("initialize").size shouldBe 1
cpg.method
.name("greet")
.size shouldBe 2 // FIXME the second node is coming in without adding it. Need to check this
.size shouldBe 1
cpg.call.name("puts").size shouldBe 2
cpg.method.name("have_birthday").size shouldBe 1
cpg.identifier.size shouldBe 11
Expand Down Expand Up @@ -468,7 +468,7 @@ class IdentifierTests extends RubyCode2CpgFixture {
|""".stripMargin)

"recognise all method nodes" in {
cpg.method.name("yield_with_args_method").l.size shouldBe 2
cpg.method.name("yield_with_args_method").l.size shouldBe 1
// TODO need to figure out how yield block should be connected to the method
}

Expand Down

0 comments on commit daa68e3

Please sign in to comment.