Skip to content

Commit

Permalink
Add test and fix EOG pass implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
konradweiss committed Oct 24, 2024
1 parent e8d7719 commit 389eb01
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ fun LanguageFrontend<*, *>.listComp(

// Only add this to an argument holder if the nearest holder is an argument holder
val holder = this@Holder
if (holder is ArgumentHolder) {
if (holder is StatementHolder) {
holder += node
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -970,19 +970,21 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa
private fun handleCollectionComprehension(node: CollectionComprehension) {
// Process the comprehension expressions from 0 to n and connect the EOG of i to i+1.
var prevComprehensionExpression: ComprehensionExpression? = null
var noMoreElementsEOGExits = listOf<Node>()
var noMoreElementsInCollection = listOf<Node>()
node.comprehensionExpressions.forEach {
handleEOG(it)

val noMoreElements = SubgraphWalker.getEOGPathEdges(it.iterable).exits

// [ComprehensionExpression] yields no more elements => EOG:false
val prevComp = prevComprehensionExpression
if (prevComp == null) {
// We handle the EOG:false edges of the outermost comprehensionExpression later,
// they continue the
// path of execution when no more elements are yielded
noMoreElementsEOGExits = currentPredecessors.toList()
noMoreElementsInCollection = noMoreElements
} else {
drawEOGToEntriesOf(currentPredecessors, prevComp.iterable, branchLabel = false)
drawEOGToEntriesOf(noMoreElements, prevComp.iterable, branchLabel = false)
}
prevComprehensionExpression = it

Expand All @@ -996,7 +998,7 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa
drawEOGToEntriesOf(currentPredecessors, it.iterable)
}
currentPredecessors.clear()
currentPredecessors.addAll(noMoreElementsEOGExits)
currentPredecessors.addAll(noMoreElementsInCollection)
nextEdgeBranch =
false // This path is followed when the comprehensions yield no more elements
attachToEOG(node)
Expand Down
34 changes: 34 additions & 0 deletions cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/GraphExamples.kt
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,40 @@ class GraphExamples {
}
}

fun getNestedComprehensionExpressions(
config: TranslationConfiguration =
TranslationConfiguration.builder()
.defaultPasses()
.registerLanguage(TestLanguage("."))
.build()
) =
testFrontend(config).build {
translationResult {
translationUnit("whileWithBreakAndElse.py") {
record("someRecord") {
method("func") {
body {
call("preComprehensions")
listComp {
ref("i")
compExpr {
ref("i")
ref("someIterable")
}
compExpr {
ref("j")
ref("i")
ref("j") gt literal(5, t("int"))
}
}
call("postComprehensions")
}
}
}
}
}
}

fun testFrontend(config: TranslationConfiguration): TestLanguageFrontend {
val ctx = TranslationContext(config, ScopeManager(), TypeManager())
val language = config.languages.filterIsInstance<TestLanguage>().first()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ package de.fraunhofer.aisec.cpg.passes

import de.fraunhofer.aisec.cpg.GraphExamples
import de.fraunhofer.aisec.cpg.graph.*
import de.fraunhofer.aisec.cpg.graph.statements.expressions.CollectionComprehension
import de.fraunhofer.aisec.cpg.helpers.Util
import kotlin.test.Test
import kotlin.test.assertNotNull
Expand Down Expand Up @@ -217,4 +218,133 @@ class EvaluationOrderGraphPassTest {
cr = Util.Connect.SUBTREE
)
}

@Test
fun testCollectionComprehensionStatement() {
val compExample = GraphExamples.getNestedComprehensionExpressions()

val listComp = compExample.allChildren<CollectionComprehension>().first()
assertNotNull(listComp)

val preCall = compExample.calls["preComprehensions"]
assertNotNull(preCall)

val postCall = compExample.calls["postComprehensions"]
assertNotNull(postCall)

assertTrue { listComp.comprehensionExpressions.size == 2 }

val outerComprehensionExpression = listComp.comprehensionExpressions.first()
assertNotNull(outerComprehensionExpression)

val innerComprehensionExpression = listComp.comprehensionExpressions.last()
assertNotNull(innerComprehensionExpression)

assertTrue(
Util.eogConnect(
en = Util.Edge.EXITS,
n = preCall,
refs = listOf(listComp),
cr = Util.Connect.SUBTREE
)
)
assertTrue(
Util.eogConnect(
en = Util.Edge.EXITS,
n = listComp,
refs = listOf(postCall),
cr = Util.Connect.SUBTREE
)
)
assertTrue(
Util.eogConnect(
en = Util.Edge.EXITS,
n = outerComprehensionExpression,
refs =
listOf(
innerComprehensionExpression,
listComp,
outerComprehensionExpression.variable
),
cr = Util.Connect.SUBTREE
)
)
assertTrue(
Util.eogConnect(
q = Util.Quantifier.ANY,
en = Util.Edge.EXITS,
n = outerComprehensionExpression,
refs =
listOf(
innerComprehensionExpression,
),
cr = Util.Connect.SUBTREE,
predicate = { it.branch == true }
)
)

assertTrue(
Util.eogConnect(
q = Util.Quantifier.ANY,
en = Util.Edge.EXITS,
n = outerComprehensionExpression,
refs = listOf(listComp),
cr = Util.Connect.SUBTREE,
predicate = { it.branch == false }
)
)

assertTrue(
Util.eogConnect(
en = Util.Edge.EXITS,
n = innerComprehensionExpression,
refs = listOf(outerComprehensionExpression, listComp.statement),
cr = Util.Connect.SUBTREE
)
)

assertTrue(
Util.eogConnect(
q = Util.Quantifier.ANY,
en = Util.Edge.EXITS,
n = innerComprehensionExpression,
refs = listOf(listComp.statement),
cr = Util.Connect.SUBTREE,
predicate = { it.branch == true }
)
)

assertTrue(
Util.eogConnect(
q = Util.Quantifier.ANY,
en = Util.Edge.EXITS,
n = innerComprehensionExpression,
refs = listOf(outerComprehensionExpression),
cr = Util.Connect.SUBTREE,
predicate = { it.branch == false }
)
)

assertTrue(
Util.eogConnect(
q = Util.Quantifier.ANY,
en = Util.Edge.EXITS,
n = outerComprehensionExpression.iterable,
refs = listOf(outerComprehensionExpression.variable),
cr = Util.Connect.SUBTREE,
predicate = { it.branch == true }
)
)

assertTrue(
Util.eogConnect(
q = Util.Quantifier.ANY,
en = Util.Edge.EXITS,
n = innerComprehensionExpression.iterable,
refs = listOf(innerComprehensionExpression.variable),
cr = Util.Connect.SUBTREE,
predicate = { it.branch == true }
)
)
}
}

0 comments on commit 389eb01

Please sign in to comment.