Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use FluentDSL in analysis module #1311

Merged
merged 26 commits into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -287,8 +287,11 @@ class MultiValueEvaluator : ValueEvaluator() {
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 @@ -140,7 +140,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 @@ -431,7 +431,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 @@ -455,8 +455,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 @@ -481,8 +481,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 @@ -509,7 +509,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 @@ -519,6 +519,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.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.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,25 @@ class MultiValueEvaluatorTest {

@Test
fun testMultipleValues() {
val topLevel = Path.of("src", "test", "resources", "value_evaluation")
val tu = ValueEvaluationTests.getCfExample().components.first().translationUnits.first()

/*val topLevel = Path.of("src", "test", "resources", "value_evaluation")
KuechA marked this conversation as resolved.
Show resolved Hide resolved
val tu =
TestUtils.analyzeAndGetFirstTU(
listOf(topLevel.resolve("cfexample.cpp").toFile()),
topLevel,
true
)

assertNotNull(tu)
assertNotNull(tu)*/

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 +157,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,7 +184,8 @@ class MultiValueEvaluatorTest {

@Test
fun testLoop() {
val topLevel = Path.of("src", "test", "resources", "value_evaluation")
val tu = ValueEvaluationTests.getCfExample().components.first().translationUnits.first()
/*val topLevel = Path.of("src", "test", "resources", "value_evaluation")
KuechA marked this conversation as resolved.
Show resolved Hide resolved
val tu =
TestUtils.analyzeAndGetFirstTU(
listOf(topLevel.resolve("cfexample.cpp").toFile()),
Expand All @@ -202,7 +195,7 @@ class MultiValueEvaluatorTest {
it.registerPass<EdgeCachePass>()
}

assertNotNull(tu)
assertNotNull(tu)*/

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.CompoundStatement
import de.fraunhofer.aisec.cpg.graph.statements.DeclarationStatement
import de.fraunhofer.aisec.cpg.graph.statements.ForStatement
import de.fraunhofer.aisec.cpg.graph.statements.expressions.ArraySubscriptionExpression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.AssignExpression
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.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