Skip to content

Commit

Permalink
[gosrc2cpg] Channel Support for make Function (#3653)
Browse files Browse the repository at this point in the history
Extension of: #3647

added support for channel.

---------

Co-authored-by: “Hitesh <hitesh.bedre@privado.com>
  • Loading branch information
hiteshbedre and “Hitesh authored Sep 15, 2023
1 parent 734d14b commit fe1406f
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.joern.gosrc2cpg.astcreation

import io.joern.gosrc2cpg.parser.ParserAst.{BasicLit, Ident, MapType, SelectorExpr, CallExpr}
import io.joern.gosrc2cpg.parser.ParserAst.{BasicLit, Ident, MapType, SelectorExpr, CallExpr, ChanType}
import io.joern.gosrc2cpg.parser.{ParserKeys, ParserNodeInfo}
import io.joern.x2cpg.{Ast, ValidationMode, Defines as XDefines}
import io.shiftleft.codepropertygraph.generated.DispatchTypes
Expand Down Expand Up @@ -107,8 +107,9 @@ trait AstForMethodCallExpressionCreator(implicit withSchemaValidation: Validatio
.flatMap(x => {
val argNode = createParserNodeInfo(x)
argNode.node match
case MapType => astForMapType(argNode)
case _ => astForNode(argNode)
case MapType => astForMapType(argNode)
case ChanType => astForChanType(argNode)
case _ => astForNode(argNode)
})
.toSeq
}
Expand All @@ -117,6 +118,10 @@ trait AstForMethodCallExpressionCreator(implicit withSchemaValidation: Validatio
Seq(Ast(literalNode(arg, arg.code, Defines.map)))
}

private def astForChanType(arg: ParserNodeInfo): Seq[Ast] = {
Seq(Ast(literalNode(arg, arg.code, Defines.chan)))
}

private def callMethodFullNameTypeFullNameAndSignature(
methodName: String,
aliasName: Option[(String, Value)] = None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ object Defines {
val empty = "<empty>"
val dot = "."
val map = "map"
val chan = "chan"

val primitiveTypeMap: Map[String, String] =
// This list is prepared with reference to primitives defined at https://pkg.go.dev/builtin#pkg-types
Expand Down Expand Up @@ -48,7 +49,7 @@ object Defines {
("delete", ("delete(map[any]any, any)", "delete", voidTypeName)),
("imag", ("imag(ComplexType)FloatType", "imag", "FloatType")),
("len", ("len(any)int", "len", "int")),
("make", ("make(map)map", "map", "map")),
("make", ("make(map)map|make(chan)chan", "make", "map|chan")),
("max", ("max[cmp.Ordered](cmp.Ordered, []cmp.Ordered)cmp.Ordered", "max", "cmp.Ordered")),
("min", ("min[cmp.Ordered](cmp.Ordered, []cmp.Ordered)cmp.Ordered", "min", "cmp.Ordered")),
("new", ("new(any)*any", "new", "*any")),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ object ParserAst {
object FieldList extends ParserNode
object ArrayType extends ParserNode
object MapType extends ParserNode
object ChanType extends ParserNode
object Field extends ParserNode
object TypeSpec extends ParserNode
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,35 @@ class OperatorDataflowTests extends GoCodeToCpgSuite(withOssDataflow = true) {
}
}

"Check dataflow when channel is used" should {
val cpg = code("""package main
|
|import "fmt"
|
|func main() {
| ch := make(chan int)
|
| go func() {
| ch <- 42 // Send a value to the channel
| }()
|
| // Receive the value from the channel
| value := <-ch
| fmt.Println(value)
|}""".stripMargin)

"check dataflow from literal to Println" ignore {
val source = cpg.literal("42")
val sink = cpg.call("Println")
sink.reachableByFlows(source).size shouldBe 1
}

"check dataflow from identifier to Println" in {
val source = cpg.identifier("ch").lineNumber(6)
val sink = cpg.call("Println")
sink.reachableByFlows(source).size shouldBe 1
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class BuiltInMethodCallTests extends GoCodeToCpgSuite {
"check call node properties" in {
val List(x) = cpg.call("make").l
x.name shouldBe "make"
x.typeFullName shouldBe "map"
x.typeFullName shouldBe "map|chan"
}

"check call node arguments" in {
Expand All @@ -39,4 +39,55 @@ class BuiltInMethodCallTests extends GoCodeToCpgSuite {

}

"When inbuilt method(make) is used to create channel" should {
val cpg = code("""package main
|
|func main() {
| ch := make(chan int)
|}""".stripMargin)
"check identifier properties" in {
val List(x) = cpg.identifier("ch").l
x.lineNumber.get shouldBe 4
x.name shouldBe "ch"
}

"check call node properties" in {
val List(x) = cpg.call("make").l
x.name shouldBe "make"
x.typeFullName shouldBe "map|chan"
}

"check call node arguments" in {
val List(x) = cpg.call("make").argument.isLiteral.l
x.code shouldBe "chan int"
x.argumentIndex shouldBe 1
x.typeFullName shouldBe "chan"
}

}

"Check assignment operation when channel is used" should {
val cpg = code("""package main
|
|import "fmt"
|
|func main() {
| ch := make(chan int)
|
| go func() {
| ch <- 42 // Send a value to the channel
| }()
|
| // Receive the value from the channel
| value := <-ch
| fmt.Println(value)
|}""".stripMargin)
"check identifier properties" in {
val List(channelDeclarationNode, channelEnqueueNode) = cpg.identifier("ch").l
channelDeclarationNode.lineNumber.get shouldBe 6
channelEnqueueNode.lineNumber.get shouldBe 13
}

}

}

0 comments on commit fe1406f

Please sign in to comment.