Skip to content

Commit

Permalink
Use FluentDSL in analysis module (#1311)
Browse files Browse the repository at this point in the history
  • Loading branch information
KuechA authored and oxisto committed Sep 24, 2023
1 parent 8252eb9 commit 400d7e0
Show file tree
Hide file tree
Showing 62 changed files with 2,676 additions and 1,333 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ val translationConfig = TranslationConfiguration
### Experimental Languages

Some languages, such as Golang are experimental and depend on other native libraries. Therefore, they are not included in the `cpg-core` module but have separate gradle submodules.
C/CPP and Java are currently required by some of the modules (e.g. `cpg-analysis`) and thus, disabling them can lead to compile errors!
To include the desired submodules simply toggle them on in your local `gradle.properties` file by setting the value of the properties to `true` e.g., (`enableGoFrontend=true`).
We provide a sample file with all languages switched on [here](./gradle.properties.example).
Instead of manually editing the `gradle.properties` file, you can also use the `configure_frontends.sh` script, which edits the properties for you.
Expand Down
2 changes: 0 additions & 2 deletions cpg-analysis/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ publishing {

dependencies {
api(projects.cpgCore)
testImplementation(projects.cpgLanguageJava)
testImplementation(projects.cpgLanguageCxx)

testImplementation(testFixtures(projects.cpgCore))
}
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,11 @@ class MultiValueEvaluator : ValueEvaluator() {

private fun handleSimpleLoopVariable(expr: Reference, depth: Int): Collection<Any?> {
val loop =
expr.prevDFG.firstOrNull { e -> e.astParent is ForStatement }?.astParent
as? ForStatement
expr.prevDFG.firstOrNull { it.astParent is ForStatement }?.astParent as? ForStatement
?: expr.prevDFG
.firstOrNull { it.astParent?.astParent is ForStatement }
?.astParent
?.astParent as? ForStatement
if (loop == null || loop.condition !is BinaryOperator) return setOf()

var loopVar: Any? =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ open class DFAOrderEvaluator(
// Stores the current markings in the FSM (i.e., which base is at which FSM-node).
val baseToFSM = mutableMapOf<String, DFA>()
// Stores the states (i.e., nodes and their states in the fsm) to avoid endless loops.
val seenStates = mutableSetOf<String>()
val seenStates = mutableSetOf<Pair<Node, String>>()
// Maps a node to all the paths which were followed to reach the node.
startNode.addEogPath("")
// Collect bases (with their eogPath) which have already been found to be incorrect due to
Expand Down Expand Up @@ -427,7 +427,7 @@ open class DFAOrderEvaluator(
node: Node,
eogPath: String,
baseToFSM: MutableMap<String, DFA>,
seenStates: MutableSet<String>,
seenStates: MutableSet<Pair<Node, String>>,
interproceduralFlows: MutableMap<String, Boolean>
): List<Node> {
val outNodes = mutableListOf<Node>()
Expand All @@ -451,8 +451,8 @@ open class DFAOrderEvaluator(
// We still add this node but this time, we also check if have seen the state it before
// to avoid endless loops etc.
outNodes[0].addEogPath(eogPath)
val stateOfNext: String = getStateSnapshot(outNodes[0], baseToFSM)
if (seenStates.contains(stateOfNext)) {
val stateOfNext = getStateSnapshot(outNodes[0], baseToFSM)
if (stateOfNext in seenStates) {
log.debug("Node/FSM state already visited: ${stateOfNext}. Remove from next nodes.")
outNodes.removeAt(0)
}
Expand All @@ -477,8 +477,8 @@ open class DFAOrderEvaluator(
// (1) Update all entries previously removed from the baseToFSM map with
// the new eog-path as prefix to the base
for (i in outNodes.indices.reversed()) {
val stateOfNext: String = getStateSnapshot(outNodes[i], baseToFSM)
if (seenStates.contains(stateOfNext)) {
val stateOfNext = getStateSnapshot(outNodes[i], baseToFSM)
if (stateOfNext in seenStates) {
log.debug(
"Node/FSM state already visited: ${stateOfNext}. Remove from next nodes."
)
Expand All @@ -505,7 +505,7 @@ open class DFAOrderEvaluator(
* [node]. It is used to keep track of the states which have already been analyzed and to avoid
* getting stuck in loops.
*/
private fun getStateSnapshot(node: Node, baseToFSM: Map<String, DFA>): String {
private fun getStateSnapshot(node: Node, baseToFSM: Map<String, DFA>): Pair<Node, String> {
val grouped =
baseToFSM.entries
.groupBy { e -> e.key.split("|")[1] }
Expand All @@ -515,6 +515,6 @@ open class DFAOrderEvaluator(
.sorted()
.joinToString(",")

return "$node $grouped"
return Pair(node, grouped)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
*/
package de.fraunhofer.aisec.cpg.analysis

import de.fraunhofer.aisec.cpg.TestUtils
import de.fraunhofer.aisec.cpg.frontends.TestHandler
import de.fraunhofer.aisec.cpg.frontends.TestLanguageFrontend
import de.fraunhofer.aisec.cpg.graph.*
Expand All @@ -35,8 +34,7 @@ import de.fraunhofer.aisec.cpg.graph.statements.ForStatement
import de.fraunhofer.aisec.cpg.graph.statements.expressions.AssignExpression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block
import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression
import de.fraunhofer.aisec.cpg.passes.EdgeCachePass
import java.nio.file.Path
import de.fraunhofer.aisec.cpg.testcases.ValueEvaluationTests
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
Expand All @@ -46,15 +44,7 @@ import kotlin.test.assertTrue
class MultiValueEvaluatorTest {
@Test
fun testSingleValue() {
val topLevel = Path.of("src", "test", "resources", "value_evaluation")
val tu =
TestUtils.analyzeAndGetFirstTU(
listOf(topLevel.resolve("example.cpp").toFile()),
topLevel,
true
)

assertNotNull(tu)
val tu = ValueEvaluationTests.getExample().components.first().translationUnits.first()

val main = tu.byNameOrNull<FunctionDeclaration>("main")
assertNotNull(main)
Expand Down Expand Up @@ -139,23 +129,15 @@ class MultiValueEvaluatorTest {

@Test
fun testMultipleValues() {
val topLevel = Path.of("src", "test", "resources", "value_evaluation")
val tu =
TestUtils.analyzeAndGetFirstTU(
listOf(topLevel.resolve("cfexample.cpp").toFile()),
topLevel,
true
)

assertNotNull(tu)
val tu = ValueEvaluationTests.getCfExample().components.first().translationUnits.first()

val main = tu.byNameOrNull<FunctionDeclaration>("main")
assertNotNull(main)

val b = main.bodyOrNull<DeclarationStatement>()?.singleDeclaration
assertNotNull(b)

var printB = main.bodyOrNull<CallExpression>()
var printB = main.calls("println")[0]
assertNotNull(printB)

val evaluator = MultiValueEvaluator()
Expand All @@ -165,25 +147,25 @@ class MultiValueEvaluatorTest {
value = evaluator.evaluate(printB.arguments.firstOrNull()) as ConcreteNumberSet
assertEquals(setOf<Long>(1, 2), value.values)

printB = main.bodyOrNull<CallExpression>(1)
printB = main.calls("println")[1]
assertNotNull(printB)
evaluator.clearPath()
value = evaluator.evaluate(printB.arguments.firstOrNull()) as ConcreteNumberSet
assertEquals(setOf<Long>(0, 1, 2), value.values)

printB = main.bodyOrNull<CallExpression>(2)
printB = main.calls("println")[2]
assertNotNull(printB)
evaluator.clearPath()
value = evaluator.evaluate(printB.arguments.firstOrNull()) as ConcreteNumberSet
assertEquals(setOf<Long>(0, 1, 2, 4), value.values)

printB = main.bodyOrNull<CallExpression>(3)
printB = main.calls("println")[3]
assertNotNull(printB)
evaluator.clearPath()
value = evaluator.evaluate(printB.arguments.firstOrNull()) as ConcreteNumberSet
assertEquals(setOf<Long>(-4, -2, -1, 0, 1, 2, 4), value.values)

printB = main.bodyOrNull<CallExpression>(4)
printB = main.calls("println")[4]
assertNotNull(printB)
evaluator.clearPath()
value = evaluator.evaluate(printB.arguments.firstOrNull()) as ConcreteNumberSet
Expand All @@ -192,17 +174,7 @@ class MultiValueEvaluatorTest {

@Test
fun testLoop() {
val topLevel = Path.of("src", "test", "resources", "value_evaluation")
val tu =
TestUtils.analyzeAndGetFirstTU(
listOf(topLevel.resolve("cfexample.cpp").toFile()),
topLevel,
true
) {
it.registerPass<EdgeCachePass>()
}

assertNotNull(tu)
val tu = ValueEvaluationTests.getCfExample().components.first().translationUnits.first()

val main = tu.byNameOrNull<FunctionDeclaration>("loop")
assertNotNull(main)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,39 +25,36 @@
*/
package de.fraunhofer.aisec.cpg.analysis

import de.fraunhofer.aisec.cpg.TestUtils
import de.fraunhofer.aisec.cpg.frontends.java.JavaLanguage
import de.fraunhofer.aisec.cpg.graph.bodyOrNull
import de.fraunhofer.aisec.cpg.graph.byNameOrNull
import de.fraunhofer.aisec.cpg.graph.declarations.MethodDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.TranslationUnitDeclaration
import de.fraunhofer.aisec.cpg.graph.invoke
import de.fraunhofer.aisec.cpg.graph.statements.DeclarationStatement
import de.fraunhofer.aisec.cpg.graph.statements.ForStatement
import de.fraunhofer.aisec.cpg.graph.statements.expressions.AssignExpression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block
import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.SubscriptExpression
import java.nio.file.Path
import de.fraunhofer.aisec.cpg.testcases.ValueEvaluationTests
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.TestInstance

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class SizeEvaluatorTest {
private lateinit var tu: TranslationUnitDeclaration

@BeforeAll
fun beforeAll() {
tu = ValueEvaluationTests.getSizeExample().components.first().translationUnits.first()
}

@Test
fun testArraySize() {
val topLevel = Path.of("src", "test", "resources", "value_evaluation")
val tu =
TestUtils.analyzeAndGetFirstTU(
listOf(topLevel.resolve("size.java").toFile()),
topLevel,
true
) {
it.registerLanguage(JavaLanguage())
}

assertNotNull(tu)

val mainClass = tu.byNameOrNull<RecordDeclaration>("MainClass")
assertNotNull(mainClass)
val main = mainClass.byNameOrNull<MethodDeclaration>("main")
Expand All @@ -79,18 +76,6 @@ class SizeEvaluatorTest {

@Test
fun testArraySizeFromSubscript() {
val topLevel = Path.of("src", "test", "resources", "value_evaluation")
val tu =
TestUtils.analyzeAndGetFirstTU(
listOf(topLevel.resolve("size.java").toFile()),
topLevel,
true
) {
it.registerLanguage(JavaLanguage())
}

assertNotNull(tu)

val mainClass = tu.byNameOrNull<RecordDeclaration>("MainClass")
assertNotNull(mainClass)
val main = mainClass.byNameOrNull<MethodDeclaration>("main")
Expand All @@ -117,18 +102,6 @@ class SizeEvaluatorTest {

@Test
fun testStringSize() {
val topLevel = Path.of("src", "test", "resources", "value_evaluation")
val tu =
TestUtils.analyzeAndGetFirstTU(
listOf(topLevel.resolve("size.java").toFile()),
topLevel,
true
) {
it.registerLanguage(JavaLanguage())
}

assertNotNull(tu)

val mainClass = tu.byNameOrNull<RecordDeclaration>("MainClass")
assertNotNull(mainClass)
val main = mainClass.byNameOrNull<MethodDeclaration>("main")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,13 @@
*/
package de.fraunhofer.aisec.cpg.analysis

import de.fraunhofer.aisec.cpg.TestUtils
import de.fraunhofer.aisec.cpg.frontends.TestHandler
import de.fraunhofer.aisec.cpg.frontends.TestLanguageFrontend
import de.fraunhofer.aisec.cpg.frontends.java.JavaLanguage
import de.fraunhofer.aisec.cpg.graph.*
import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration
import de.fraunhofer.aisec.cpg.graph.statements.DeclarationStatement
import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression
import java.nio.file.Path
import de.fraunhofer.aisec.cpg.testcases.ValueEvaluationTests
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
Expand Down Expand Up @@ -70,15 +68,7 @@ class ValueEvaluatorTest {

@Test
fun test() {
val topLevel = Path.of("src", "test", "resources", "value_evaluation")
val tu =
TestUtils.analyzeAndGetFirstTU(
listOf(topLevel.resolve("example.cpp").toFile()),
topLevel,
true
)

assertNotNull(tu)
val tu = ValueEvaluationTests.getExample().components.first().translationUnits.first()

val main = tu.byNameOrNull<FunctionDeclaration>("main")
assertNotNull(main)
Expand Down Expand Up @@ -168,20 +158,16 @@ class ValueEvaluatorTest {
value = m.evaluate()
assertFalse(value as Boolean)

m.fields
val n = main.bodyOrNull<DeclarationStatement>(13)?.singleDeclaration
assertNotNull(n)
value = n.evaluate()
assertFalse(value as Boolean)
}

@Test
fun testComplex() {
val topLevel = Path.of("src", "test", "resources", "value_evaluation")
val tu =
TestUtils.analyzeAndGetFirstTU(
listOf(topLevel.resolve("complex.java").toFile()),
topLevel,
true
) {
it.registerLanguage(JavaLanguage())
}
ValueEvaluationTests.getComplexExample().components.first().translationUnits.first()

assertNotNull(tu)

Expand Down
Loading

0 comments on commit 400d7e0

Please sign in to comment.