Skip to content

Commit

Permalink
Fixed missing DFG edges in Go frontend (#784)
Browse files Browse the repository at this point in the history
* Fixed missing DFG edge in InitializerListExpression::addInitializer
* Adding prevDFG edge from ConstructExpression to InitializerListExpression in Go frontend
* Supporting array composite literals
  • Loading branch information
oxisto authored May 26, 2022
1 parent 9e4e60d commit 8c84cd2
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 8 deletions.
21 changes: 21 additions & 0 deletions cpg-core/src/main/java/de/fraunhofer/aisec/cpg/graph/Extensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,24 @@ fun Node.followPrevEOG(predicate: (PropertyEdge<*>) -> Boolean): List<PropertyEd

return null
}

fun Node.followPrevDFG(predicate: (Node) -> Boolean): MutableList<Node>? {
val path = mutableListOf<Node>()

for (prev in this.prevDFG) {
path.add(prev)

if (predicate(prev)) {
return path
}

val subPath = prev.followPrevDFG(predicate)
if (subPath != null) {
path.addAll(subPath)
}

return path
}

return null
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ public void addInitializer(Expression initializer) {
var edge = new PropertyEdge<>(this, initializer);
edge.addProperty(Properties.INDEX, this.initializers.size());

initializer.registerTypeListener(this);
this.addPrevDFG(initializer);

this.initializers.add(edge);
}

Expand Down
4 changes: 4 additions & 0 deletions cpg-language-go/src/main/golang/expressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,10 @@ func (c *ConstructExpression) AddArgument(e *Expression) {
(*jnigi.ObjectRef)(c).CallMethod(env, "addArgument", jnigi.Void, (*jnigi.ObjectRef)(e).Cast("de/fraunhofer/aisec/cpg/graph/statements/expressions/Expression"))
}

func (c *ConstructExpression) AddPrevDFG(n *Node) {
(*jnigi.ObjectRef)(c).CallMethod(env, "addPrevDFG", jnigi.Void, (*jnigi.ObjectRef)(n).Cast("de/fraunhofer/aisec/cpg/graph/Node"))
}

func (n *NewExpression) SetInitializer(e *Expression) (err error) {
_, err = (*jnigi.ObjectRef)(n).CallMethod(env, "setInitializer", jnigi.Void, (*jnigi.ObjectRef)(e).Cast("de/fraunhofer/aisec/cpg/graph/statements/expressions/Expression"))

Expand Down
14 changes: 9 additions & 5 deletions cpg-language-go/src/main/golang/frontend/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -1098,18 +1098,22 @@ func (this *GoLanguageFrontend) handleCompositeLit(fset *token.FileSet, lit *ast
c := cpg.NewConstructExpression(fset, lit)

// parse the type field, to see which kind of expression it is
var reference = this.handleExpr(fset, lit.Type)
var typ = this.handleType(lit.Type)

if reference == nil {
return nil
if typ != nil {
(*cpg.Node)(c).SetName((*cpg.Node)(typ).GetName())
(*cpg.Expression)(c).SetType(typ)
}

(*cpg.Node)(c).SetName(reference.GetName())

l := cpg.NewInitializerListExpression(fset, lit)

c.AddArgument((*cpg.Expression)(l))

// Normally, the construct expression would not have DFG edge, but in this case we are mis-using it
// to simulate an object literal, so we need to add a DFG here, otherwise a declaration is disconnected
// from its initialization.
c.AddPrevDFG((*cpg.Node)(l))

for _, elem := range lit.Elts {
expr := this.handleExpr(fset, elem)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ package de.fraunhofer.aisec.cpg.frontends.golang
import de.fraunhofer.aisec.cpg.BaseTest
import de.fraunhofer.aisec.cpg.ExperimentalGolang
import de.fraunhofer.aisec.cpg.TestUtils
import de.fraunhofer.aisec.cpg.graph.body
import de.fraunhofer.aisec.cpg.graph.bodyOrNull
import de.fraunhofer.aisec.cpg.graph.byNameOrNull
import de.fraunhofer.aisec.cpg.graph.*
import de.fraunhofer.aisec.cpg.graph.declarations.*
import de.fraunhofer.aisec.cpg.graph.statements.*
import de.fraunhofer.aisec.cpg.graph.statements.expressions.*
Expand All @@ -44,6 +42,82 @@ import kotlin.test.assertTrue
@ExperimentalGolang
class GoLanguageFrontendTest : BaseTest() {

@Test
fun testArrayCompositeLiteral() {
val topLevel = Path.of("src", "test", "resources", "golang")
val tu =
TestUtils.analyzeAndGetFirstTU(
listOf(topLevel.resolve("values.go").toFile()),
topLevel,
true
) {
it.registerLanguage(
GoLanguageFrontend::class.java,
GoLanguageFrontend.GOLANG_EXTENSIONS
)
}
assertNotNull(tu)

val p = tu.byNameOrNull<NamespaceDeclaration>("p")
assertNotNull(p)

val main = p.byNameOrNull<FunctionDeclaration>("main")

assertNotNull(main)

val message =
main.bodyOrNull<DeclarationStatement>(2)?.singleDeclaration as? VariableDeclaration

assertNotNull(message)

val map =
((message.initializer as? ConstructExpression)?.arguments?.firstOrNull() as?
InitializerListExpression)

assertNotNull(map)

val nameEntry = map.initializers.firstOrNull() as? KeyValueExpression

assertNotNull(nameEntry)

assertEquals("string[]", (nameEntry.value as? ConstructExpression)?.name)
}

@Test
fun testDFG() {
val topLevel = Path.of("src", "test", "resources", "golang")
val tu =
TestUtils.analyzeAndGetFirstTU(
listOf(topLevel.resolve("dfg.go").toFile()),
topLevel,
true
) {
it.registerLanguage(
GoLanguageFrontend::class.java,
GoLanguageFrontend.GOLANG_EXTENSIONS
)
}
assertNotNull(tu)

val p = tu.byNameOrNull<NamespaceDeclaration>("p")
assertNotNull(p)

val main = p.byNameOrNull<FunctionDeclaration>("main")

assertNotNull(main)

val data = main.bodyOrNull<DeclarationStatement>(0)?.singleDeclaration

assertNotNull(data)

// We should be able to follow the DFG backwards from the declaration to the individual
// key/value expressions
val path = data.followPrevDFG { it is KeyValueExpression }

assertNotNull(path)
assertEquals(4, path.size)
}

@Test
fun testConstruct() {
val topLevel = Path.of("src", "test", "resources", "golang")
Expand Down
6 changes: 6 additions & 0 deletions cpg-language-go/src/test/resources/golang/dfg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package p

func main() int {
data := &Data{Name: name}
db.Create(data)
}
13 changes: 13 additions & 0 deletions cpg-language-go/src/test/resources/golang/values.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package p

import "net/url"

func main() {
name := "firstname lastname"
data := "data"

message := url.Values{
"Name": []string{name},
"Data": []string{data},
}
}

0 comments on commit 8c84cd2

Please sign in to comment.