diff --git a/README.md b/README.md index 4e1eea4d7e4..7c5b791cb32 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/cpg-analysis/build.gradle.kts b/cpg-analysis/build.gradle.kts index 65d6a2e623a..201e7932b3b 100644 --- a/cpg-analysis/build.gradle.kts +++ b/cpg-analysis/build.gradle.kts @@ -42,8 +42,6 @@ publishing { dependencies { api(projects.cpgCore) - testImplementation(projects.cpgLanguageJava) - testImplementation(projects.cpgLanguageCxx) testImplementation(testFixtures(projects.cpgCore)) } diff --git a/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/MultiValueEvaluator.kt b/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/MultiValueEvaluator.kt index ef9560d4e4e..13c8d2d0f85 100644 --- a/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/MultiValueEvaluator.kt +++ b/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/MultiValueEvaluator.kt @@ -281,8 +281,11 @@ class MultiValueEvaluator : ValueEvaluator() { private fun handleSimpleLoopVariable(expr: Reference, depth: Int): Collection { 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? = diff --git a/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/fsm/DFAOrderEvaluator.kt b/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/fsm/DFAOrderEvaluator.kt index 6b9852303d7..5ca64973950 100644 --- a/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/fsm/DFAOrderEvaluator.kt +++ b/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/fsm/DFAOrderEvaluator.kt @@ -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() // Stores the states (i.e., nodes and their states in the fsm) to avoid endless loops. - val seenStates = mutableSetOf() + val seenStates = mutableSetOf>() // 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 @@ -429,7 +429,7 @@ open class DFAOrderEvaluator( node: Node, eogPath: String, baseToFSM: MutableMap, - seenStates: MutableSet, + seenStates: MutableSet>, interproceduralFlows: MutableMap ): List { val outNodes = mutableListOf() @@ -453,8 +453,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) } @@ -479,8 +479,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." ) @@ -507,7 +507,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 { + private fun getStateSnapshot(node: Node, baseToFSM: Map): Pair { val grouped = baseToFSM.entries .groupBy { e -> e.key.split("|")[1] } @@ -517,6 +517,6 @@ open class DFAOrderEvaluator( .sorted() .joinToString(",") - return "$node $grouped" + return Pair(node, grouped) } } diff --git a/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/MultiValueEvaluatorTest.kt b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/MultiValueEvaluatorTest.kt index ac3ac136c0a..49fc6e0926e 100644 --- a/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/MultiValueEvaluatorTest.kt +++ b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/MultiValueEvaluatorTest.kt @@ -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.* @@ -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 @@ -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("main") assertNotNull(main) @@ -139,15 +129,7 @@ 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("main") assertNotNull(main) @@ -155,7 +137,7 @@ class MultiValueEvaluatorTest { val b = main.bodyOrNull()?.singleDeclaration assertNotNull(b) - var printB = main.bodyOrNull() + var printB = main.calls("println")[0] assertNotNull(printB) val evaluator = MultiValueEvaluator() @@ -165,25 +147,25 @@ class MultiValueEvaluatorTest { value = evaluator.evaluate(printB.arguments.firstOrNull()) as ConcreteNumberSet assertEquals(setOf(1, 2), value.values) - printB = main.bodyOrNull(1) + printB = main.calls("println")[1] assertNotNull(printB) evaluator.clearPath() value = evaluator.evaluate(printB.arguments.firstOrNull()) as ConcreteNumberSet assertEquals(setOf(0, 1, 2), value.values) - printB = main.bodyOrNull(2) + printB = main.calls("println")[2] assertNotNull(printB) evaluator.clearPath() value = evaluator.evaluate(printB.arguments.firstOrNull()) as ConcreteNumberSet assertEquals(setOf(0, 1, 2, 4), value.values) - printB = main.bodyOrNull(3) + printB = main.calls("println")[3] assertNotNull(printB) evaluator.clearPath() value = evaluator.evaluate(printB.arguments.firstOrNull()) as ConcreteNumberSet assertEquals(setOf(-4, -2, -1, 0, 1, 2, 4), value.values) - printB = main.bodyOrNull(4) + printB = main.calls("println")[4] assertNotNull(printB) evaluator.clearPath() value = evaluator.evaluate(printB.arguments.firstOrNull()) as ConcreteNumberSet @@ -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() - } - - assertNotNull(tu) + val tu = ValueEvaluationTests.getCfExample().components.first().translationUnits.first() val main = tu.byNameOrNull("loop") assertNotNull(main) diff --git a/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/SizeEvaluatorTest.kt b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/SizeEvaluatorTest.kt index 0c2601be82e..57d7f2eb08c 100644 --- a/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/SizeEvaluatorTest.kt +++ b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/SizeEvaluatorTest.kt @@ -25,12 +25,11 @@ */ 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 @@ -38,26 +37,24 @@ 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("MainClass") assertNotNull(mainClass) val main = mainClass.byNameOrNull("main") @@ -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("MainClass") assertNotNull(mainClass) val main = mainClass.byNameOrNull("main") @@ -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("MainClass") assertNotNull(mainClass) val main = mainClass.byNameOrNull("main") diff --git a/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/ValueEvaluatorTest.kt b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/ValueEvaluatorTest.kt index 1a994ca749b..91d8deb9b08 100644 --- a/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/ValueEvaluatorTest.kt +++ b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/ValueEvaluatorTest.kt @@ -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 @@ -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("main") assertNotNull(main) @@ -168,20 +158,16 @@ class ValueEvaluatorTest { value = m.evaluate() assertFalse(value as Boolean) - m.fields + val n = main.bodyOrNull(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) diff --git a/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/fsm/ComplexDFAOrderEvaluationTest.kt b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/fsm/ComplexDFAOrderEvaluationTest.kt index 90aa4825a5c..be48e0997b0 100644 --- a/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/fsm/ComplexDFAOrderEvaluationTest.kt +++ b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/fsm/ComplexDFAOrderEvaluationTest.kt @@ -25,23 +25,13 @@ */ package de.fraunhofer.aisec.cpg.analysis.fsm -import de.fraunhofer.aisec.cpg.TestUtils -import de.fraunhofer.aisec.cpg.TranslationManager -import de.fraunhofer.aisec.cpg.frontends.java.JavaLanguage -import de.fraunhofer.aisec.cpg.graph.Node -import de.fraunhofer.aisec.cpg.graph.bodyOrNull -import de.fraunhofer.aisec.cpg.graph.byNameOrNull -import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration -import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration +import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.declarations.TranslationUnitDeclaration -import de.fraunhofer.aisec.cpg.graph.followNextEOG import de.fraunhofer.aisec.cpg.graph.statements.* 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.Reference -import de.fraunhofer.aisec.cpg.passes.EdgeCachePass -import de.fraunhofer.aisec.cpg.passes.UnreachableEOGPass -import java.nio.file.Path +import de.fraunhofer.aisec.cpg.testcases.GraphExamples import kotlin.test.* import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.TestInstance @@ -78,25 +68,12 @@ class ComplexDFAOrderEvaluationTest { @BeforeAll fun beforeAll() { - val topLevel = Path.of("src", "test", "resources", "analyses", "ordering") - TranslationManager.builder().build().analyze() - tu = - TestUtils.analyzeAndGetFirstTU( - listOf(topLevel.resolve("ComplexOrder.java").toFile()), - topLevel, - true - ) { - it.registerLanguage() - .registerPass() - .registerPass() - } + tu = GraphExamples.getComplexOrder().components.first().translationUnits.first() } @Test fun testSuccessMinimal1FSM() { - val functionOk = - tu.byNameOrNull("ComplexOrder") - ?.byNameOrNull("ok_minimal1") + val functionOk = tu.functions["ok_minimal1"] assertNotNull(functionOk) val p1Decl = functionOk.bodyOrNull(0) @@ -117,9 +94,7 @@ class ComplexDFAOrderEvaluationTest { @Test fun testSuccessMinimal2FSM() { - val functionOk = - tu.byNameOrNull("ComplexOrder") - ?.byNameOrNull("ok_minimal2") + val functionOk = tu.functions["ok_minimal2"] assertNotNull(functionOk) val p1Decl = functionOk.bodyOrNull(0) @@ -141,9 +116,7 @@ class ComplexDFAOrderEvaluationTest { @Test fun testSuccessMimimal3FSM() { - val functionOk = - tu.byNameOrNull("ComplexOrder") - ?.byNameOrNull("ok_minimal3") + val functionOk = tu.functions["ok_minimal3"] assertNotNull(functionOk) val p1Decl = functionOk.bodyOrNull(0) @@ -166,9 +139,7 @@ class ComplexDFAOrderEvaluationTest { @Test fun testSuccessMultiProcessFSM() { - val functionOk = - tu.byNameOrNull("ComplexOrder") - ?.byNameOrNull("ok2") + val functionOk = tu.functions["ok2"] assertNotNull(functionOk) val p2Decl = functionOk.bodyOrNull(0) @@ -193,9 +164,7 @@ class ComplexDFAOrderEvaluationTest { @Test fun testSuccessLoopFSM() { - val functionOk = - tu.byNameOrNull("ComplexOrder") - ?.byNameOrNull("ok3") + val functionOk = tu.functions["ok3"] assertNotNull(functionOk) val p3Decl = functionOk.bodyOrNull(0) @@ -220,9 +189,7 @@ class ComplexDFAOrderEvaluationTest { @Test fun testSuccessLoopResetFSM() { - val functionOk = - tu.byNameOrNull("ComplexOrder") - ?.byNameOrNull("ok4") + val functionOk = tu.functions["ok4"] assertNotNull(functionOk) val p3Decl = functionOk.bodyOrNull(0) @@ -248,9 +215,7 @@ class ComplexDFAOrderEvaluationTest { @Test fun testFailMissingCreateFSM() { - val functionOk = - tu.byNameOrNull("ComplexOrder") - ?.byNameOrNull("nok1") + val functionOk = tu.functions["nok1"] assertNotNull(functionOk) val p5Decl = functionOk.bodyOrNull(0) @@ -271,9 +236,7 @@ class ComplexDFAOrderEvaluationTest { @Test fun testFailIfFSM() { - val functionOk = - tu.byNameOrNull("ComplexOrder") - ?.byNameOrNull("nok2") + val functionOk = tu.functions["nok2"] assertNotNull(functionOk) val p6Decl = functionOk.bodyOrNull(0) @@ -301,9 +264,7 @@ class ComplexDFAOrderEvaluationTest { @Test fun testFailWhileLoopFSM() { - val functionOk = - tu.byNameOrNull("ComplexOrder") - ?.byNameOrNull("nok3") + val functionOk = tu.functions["nok3"] assertNotNull(functionOk) @@ -331,9 +292,7 @@ class ComplexDFAOrderEvaluationTest { @Test fun testFailWhileLoop2FSM() { - val functionOk = - tu.byNameOrNull("ComplexOrder") - ?.byNameOrNull("nokWhile") + val functionOk = tu.functions["nokWhile"] assertNotNull(functionOk) @@ -361,9 +320,7 @@ class ComplexDFAOrderEvaluationTest { @Test fun testSuccessWhileLoop2FSM() { - val functionOk = - tu.byNameOrNull("ComplexOrder") - ?.byNameOrNull("okWhile2") + val functionOk = tu.functions["okWhile2"] assertNotNull(functionOk) val p7Decl = functionOk.bodyOrNull(0) @@ -390,9 +347,7 @@ class ComplexDFAOrderEvaluationTest { @Test fun testSuccessWhileLoopFSM() { - val functionOk = - tu.byNameOrNull("ComplexOrder") - ?.byNameOrNull("okWhile") + val functionOk = tu.functions["okWhile"] assertNotNull(functionOk) val p8Decl = functionOk.bodyOrNull(0) @@ -422,9 +377,7 @@ class ComplexDFAOrderEvaluationTest { @Test fun testSuccessDoWhileLoopFSM() { - val functionOk = - tu.byNameOrNull("ComplexOrder") - ?.byNameOrNull("okDoWhile") + val functionOk = tu.functions["okDoWhile"] assertNotNull(functionOk) val p6Decl = functionOk.bodyOrNull(0) @@ -450,9 +403,7 @@ class ComplexDFAOrderEvaluationTest { @Test fun testSuccessMinimalInterprocUnclearFSM() { - val functionOk = - tu.byNameOrNull("ComplexOrder") - ?.byNameOrNull("minimalInterprocUnclear") + val functionOk = tu.functions["minimalInterprocUnclear"] assertNotNull(functionOk) val p1Decl = functionOk.bodyOrNull(0) @@ -488,9 +439,7 @@ class ComplexDFAOrderEvaluationTest { @Test fun testSuccessMinimalInterprocUnclearArgumentFSM() { - val functionOk = - tu.byNameOrNull("ComplexOrder") - ?.byNameOrNull("minimalInterprocUnclearArgument") + val functionOk = tu.functions["minimalInterprocUnclearArgument"] assertNotNull(functionOk) val p1Decl = functionOk.parameters[0] @@ -528,9 +477,7 @@ class ComplexDFAOrderEvaluationTest { @Test fun testSuccessMinimalInterprocUnclearReturnFSM() { - val functionOk = - tu.byNameOrNull("ComplexOrder") - ?.byNameOrNull("minimalInterprocUnclearReturn") + val functionOk = tu.functions["minimalInterprocUnclearReturn"] assertNotNull(functionOk) val p1Decl = functionOk.bodyOrNull(0) @@ -566,9 +513,7 @@ class ComplexDFAOrderEvaluationTest { @Test fun testSuccessMinimalInterprocFailFSM() { - val functionOk = - tu.byNameOrNull("ComplexOrder") - ?.byNameOrNull("minimalInterprocFail") + val functionOk = tu.functions["minimalInterprocFail"] assertNotNull(functionOk) val p1Decl = functionOk.bodyOrNull(0) @@ -608,9 +553,7 @@ class ComplexDFAOrderEvaluationTest { @Test fun testSuccessMinimalInterprocFail2FSM() { - val functionOk = - tu.byNameOrNull("ComplexOrder") - ?.byNameOrNull("minimalInterprocFail2") + val functionOk = tu.functions["minimalInterprocFail2"] assertNotNull(functionOk) val p1Decl = functionOk.bodyOrNull(0) diff --git a/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/fsm/SimpleDFAOrderEvaluationTest.kt b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/fsm/SimpleDFAOrderEvaluationTest.kt index 4fffc76f4f8..cda94ef3f91 100644 --- a/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/fsm/SimpleDFAOrderEvaluationTest.kt +++ b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/fsm/SimpleDFAOrderEvaluationTest.kt @@ -25,9 +25,6 @@ */ package de.fraunhofer.aisec.cpg.analysis.fsm -import de.fraunhofer.aisec.cpg.TestUtils -import de.fraunhofer.aisec.cpg.TranslationManager -import de.fraunhofer.aisec.cpg.frontends.java.JavaLanguage import de.fraunhofer.aisec.cpg.graph.Node import de.fraunhofer.aisec.cpg.graph.bodyOrNull import de.fraunhofer.aisec.cpg.graph.byNameOrNull @@ -35,9 +32,7 @@ import de.fraunhofer.aisec.cpg.graph.declarations.* import de.fraunhofer.aisec.cpg.graph.statements.DeclarationStatement import de.fraunhofer.aisec.cpg.graph.statements.IfStatement import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block -import de.fraunhofer.aisec.cpg.passes.EdgeCachePass -import de.fraunhofer.aisec.cpg.passes.UnreachableEOGPass -import java.nio.file.Path +import de.fraunhofer.aisec.cpg.testcases.GraphExamples import kotlin.test.BeforeTest import kotlin.test.Test import kotlin.test.assertFalse @@ -64,18 +59,7 @@ class SimpleDFAOrderEvaluationTest { @BeforeAll fun beforeAll() { - val topLevel = Path.of("src", "test", "resources", "analyses", "ordering") - TranslationManager.builder().build().analyze() - tu = - TestUtils.analyzeAndGetFirstTU( - listOf(topLevel.resolve("SimpleOrder.java").toFile()), - topLevel, - true - ) { - it.registerLanguage() - .registerPass() - .registerPass() - } + tu = GraphExamples.getSimpleOrder().components.first().translationUnits.first() } @Test @@ -238,7 +222,7 @@ class SimpleDFAOrderEvaluationTest { nodesToOp[thenBranch.statements[0]] = setOf("start()") nodesToOp[thenBranch.statements[1]] = setOf("finish()") nodesToOp[(functionOk.body as Block).statements[2]] = setOf("start()") - nodesToOp[(functionOk.body as Block).statements[4]] = setOf("finish()") + nodesToOp[(functionOk.body as Block).statements[3]] = setOf("finish()") val orderEvaluator = DFAOrderEvaluator(dfa, consideredDecl, nodesToOp) val everythingOk = orderEvaluator.evaluateOrder(p4Decl) diff --git a/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/UnreachableEOGPassTest.kt b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/UnreachableEOGPassTest.kt index 1fa67f22826..b58ddc1756f 100644 --- a/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/UnreachableEOGPassTest.kt +++ b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/UnreachableEOGPassTest.kt @@ -25,15 +25,12 @@ */ package de.fraunhofer.aisec.cpg.passes -import de.fraunhofer.aisec.cpg.TestUtils -import de.fraunhofer.aisec.cpg.TranslationManager -import de.fraunhofer.aisec.cpg.frontends.java.JavaLanguage import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.declarations.TranslationUnitDeclaration import de.fraunhofer.aisec.cpg.graph.edge.Properties import de.fraunhofer.aisec.cpg.graph.statements.IfStatement import de.fraunhofer.aisec.cpg.graph.statements.WhileStatement -import java.nio.file.Path +import de.fraunhofer.aisec.cpg.testcases.Passes import kotlin.test.* import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.TestInstance @@ -44,16 +41,7 @@ class UnreachableEOGPassTest { @BeforeAll fun beforeAll() { - val topLevel = Path.of("src", "test", "resources", "passes", "unreachable") - TranslationManager.builder().build().analyze() - tu = - TestUtils.analyzeAndGetFirstTU( - listOf(topLevel.resolve("Unreachability.java").toFile()), - topLevel, - true - ) { - it.registerLanguage().registerPass() - } + tu = Passes.getUnreachability().components.first().translationUnits.first() } @Test diff --git a/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/UnreachableEOGandDFGTest.kt b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/UnreachableEOGandDFGTest.kt index f23854f609b..507bc612bf2 100644 --- a/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/UnreachableEOGandDFGTest.kt +++ b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/UnreachableEOGandDFGTest.kt @@ -25,13 +25,10 @@ */ package de.fraunhofer.aisec.cpg.passes -import de.fraunhofer.aisec.cpg.TestUtils -import de.fraunhofer.aisec.cpg.TranslationManager -import de.fraunhofer.aisec.cpg.frontends.java.JavaLanguage import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.declarations.TranslationUnitDeclaration import de.fraunhofer.aisec.cpg.graph.statements.IfStatement -import java.nio.file.Path +import de.fraunhofer.aisec.cpg.testcases.Passes import kotlin.test.Ignore import kotlin.test.assertEquals import kotlin.test.assertNotNull @@ -46,16 +43,7 @@ class UnreachableEOGandDFGTest { @BeforeAll fun beforeAll() { - val topLevel = Path.of("src", "test", "resources", "passes", "unreachable") - TranslationManager.builder().build().analyze() - tu = - TestUtils.analyzeAndGetFirstTU( - listOf(topLevel.resolve("Unreachability.java").toFile()), - topLevel, - true - ) { - it.registerLanguage().registerPass() - } + tu = Passes.getUnreachability().components.first().translationUnits.first() } @Test diff --git a/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/query/QueryTest.kt b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/query/QueryTest.kt index 6cccf1d340f..67330289742 100644 --- a/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/query/QueryTest.kt +++ b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/query/QueryTest.kt @@ -25,16 +25,12 @@ */ package de.fraunhofer.aisec.cpg.query -import de.fraunhofer.aisec.cpg.TranslationConfiguration -import de.fraunhofer.aisec.cpg.TranslationManager import de.fraunhofer.aisec.cpg.analysis.MultiValueEvaluator import de.fraunhofer.aisec.cpg.analysis.NumberSet -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.expressions.* -import de.fraunhofer.aisec.cpg.passes.EdgeCachePass -import java.io.File +import de.fraunhofer.aisec.cpg.testcases.Query import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertTrue @@ -43,15 +39,7 @@ import org.junit.jupiter.api.Test class QueryTest { @Test fun testMemcpyTooLargeQuery2() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/vulnerable.cpp")) - .defaultPasses() - .defaultLanguages() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getVulnerable() val queryTreeResult = result.all( @@ -75,15 +63,7 @@ class QueryTest { @Test fun testMemcpyTooLargeQuery() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/vulnerable.cpp")) - .defaultPasses() - .defaultLanguages() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getVulnerable() val queryTreeResult = result.all({ it.name.localName == "memcpy" }) { @@ -102,15 +82,7 @@ class QueryTest { @Test fun testMemcpyTooLargeQueryImplies() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/vulnerable.cpp")) - .defaultPasses() - .defaultLanguages() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getVulnerable() val queryTreeResult = result.allExtended( @@ -125,15 +97,7 @@ class QueryTest { @Test fun testUseAfterFree() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/vulnerable.cpp")) - .defaultPasses() - .defaultLanguages() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getVulnerable() val queryTreeResult = result.all({ it.name.localName == "free" }) { outer -> @@ -163,15 +127,7 @@ class QueryTest { @Test fun testDoubleFree() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/vulnerable.cpp")) - .defaultPasses() - .defaultLanguages() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getVulnerable() val queryTreeResult = result.all({ it.name.localName == "free" }) { outer -> @@ -205,15 +161,7 @@ class QueryTest { @Test fun testParameterGreaterThanOrEqualConst() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/vulnerable.cpp")) - .defaultPasses() - .defaultLanguages() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getVulnerable() val queryTreeResult = result.all({ it.name.localName == "memcpy" }) { @@ -240,15 +188,7 @@ class QueryTest { @Test fun testParameterGreaterThanConst() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/vulnerable.cpp")) - .defaultPasses() - .defaultLanguages() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getVulnerable() val queryTreeResult = result.all({ it.name.localName == "memcpy" }) { @@ -275,15 +215,7 @@ class QueryTest { @Test fun testParameterLessThanOrEqualConst() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/vulnerable.cpp")) - .defaultPasses() - .defaultLanguages() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getVulnerable() val queryTreeResult = result.all({ it.name.localName == "memcpy" }) { @@ -310,15 +242,7 @@ class QueryTest { @Test fun testParameterEqualsConst() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/vulnerable.cpp")) - .defaultPasses() - .defaultLanguages() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getVulnerable() val queryTreeResult = result.all({ it.name.localName == "memcpy" }) { @@ -345,15 +269,7 @@ class QueryTest { @Test fun testParameterLessThanConst() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/vulnerable.cpp")) - .defaultPasses() - .defaultLanguages() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getVulnerable() val queryTreeResult = result.all({ it.name.localName == "memcpy" }) { @@ -380,15 +296,7 @@ class QueryTest { @Test fun testParameterNotEqualsConst() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/vulnerable.cpp")) - .defaultPasses() - .defaultLanguages() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getVulnerable() val queryTreeResult = result.all({ it.name.localName == "memcpy" }) { @@ -415,15 +323,7 @@ class QueryTest { @Test fun testParameterIn() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/vulnerable.cpp")) - .defaultPasses() - .defaultLanguages() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getVulnerable() val queryTreeResult = result.all({ it.name.localName == "memcpy" }) { @@ -450,21 +350,11 @@ class QueryTest { @Test fun testAssign() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/assign.cpp")) - .defaultPasses() - .defaultLanguages() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getAssign() val queryTreeResult = result.all( - mustSatisfy = { - it.assignments.all { (it.value.invoke() as QueryTree) < 5 } - } + mustSatisfy = { it.assignments.all { (it.value() as QueryTree) < 5 } } ) assertTrue(queryTreeResult.first) @@ -478,15 +368,7 @@ class QueryTest { @Test fun testOutOfBoundsQuery() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/array.cpp")) - .defaultPasses() - .defaultLanguages() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getArray() val queryTreeResult = result.all( @@ -510,15 +392,7 @@ class QueryTest { @Test fun testOutOfBoundsQueryExists() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/array.cpp")) - .defaultPasses() - .defaultLanguages() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getArray() val queryTreeResult = result.exists( @@ -542,16 +416,7 @@ class QueryTest { @Test fun testOutOfBoundsQuery2() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/array2.cpp")) - .defaultPasses() - .defaultLanguages() - .registerPass() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getArray2() val queryTreeResult = result.all( @@ -575,16 +440,10 @@ class QueryTest { @Test fun testOutOfBoundsQuery3() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/array3.cpp")) - .defaultPasses() - .defaultLanguages() - .registerPass() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getArray3() + val subscripts = + MultiValueEvaluator() + .evaluate(result.allChildren().first().subscriptExpression) val queryTreeResult = result.all( @@ -618,16 +477,7 @@ class QueryTest { @Test fun testOutOfBoundsQueryCorrect() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/array_correct.cpp")) - .defaultPasses() - .defaultLanguages() - .registerPass() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getArrayCorrect() val queryTreeResult = result.all( @@ -655,15 +505,7 @@ class QueryTest { @Test fun testDivisionBy0() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/vulnerable.cpp")) - .defaultPasses() - .defaultLanguages() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getVulnerable() val queryTreeResult = result.all( @@ -683,15 +525,7 @@ class QueryTest { @Test fun testIntOverflowAssignment() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/vulnerable.cpp")) - .defaultPasses() - .defaultLanguages() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getVulnerable() val queryTreeResult = result.all( @@ -724,16 +558,7 @@ class QueryTest { @Test fun testDataFlowRequirement() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/Dataflow.java")) - .defaultPasses() - .defaultLanguages() - .registerLanguage(JavaLanguage()) - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getDataflow() val queryTreeResult = result.all( @@ -798,17 +623,7 @@ class QueryTest { @Test fun testComplexDFGAndEOGRequirement() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/ComplexDataflow.java")) - .defaultPasses() - .defaultLanguages() - .registerLanguage(JavaLanguage()) - .registerPass() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getComplexDataflow() val queryTreeResult = result.allExtended( @@ -852,17 +667,7 @@ class QueryTest { @Test fun testComplexDFGAndEOGRequirement2() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/ComplexDataflow2.java")) - .defaultPasses() - .defaultLanguages() - .registerLanguage(JavaLanguage()) - .registerPass() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getComplexDataflow2() val queryTreeResult = result.allExtended( @@ -906,17 +711,7 @@ class QueryTest { @Test fun testClomplexDFGAndEOGRequirement3() { - val config = - TranslationConfiguration.builder() - .sourceLocations(File("src/test/resources/query/ComplexDataflow3.java")) - .defaultPasses() - .defaultLanguages() - .registerLanguage(JavaLanguage()) - .registerPass() - .build() - - val analyzer = TranslationManager.builder().config(config).build() - val result = analyzer.analyze().get() + val result = Query.getComplexDataflow3() val queryTreeResult = result.allExtended( diff --git a/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/testcases/OrderingTests.kt b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/testcases/OrderingTests.kt new file mode 100644 index 00000000000..06753748bb0 --- /dev/null +++ b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/testcases/OrderingTests.kt @@ -0,0 +1,644 @@ +/* + * Copyright (c) 2023, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +package de.fraunhofer.aisec.cpg.testcases + +import de.fraunhofer.aisec.cpg.ScopeManager +import de.fraunhofer.aisec.cpg.TranslationConfiguration +import de.fraunhofer.aisec.cpg.TranslationContext +import de.fraunhofer.aisec.cpg.TypeManager +import de.fraunhofer.aisec.cpg.frontends.TestLanguage +import de.fraunhofer.aisec.cpg.frontends.TestLanguageFrontend +import de.fraunhofer.aisec.cpg.graph.array +import de.fraunhofer.aisec.cpg.graph.builder.* +import de.fraunhofer.aisec.cpg.passes.EdgeCachePass +import de.fraunhofer.aisec.cpg.passes.UnreachableEOGPass + +class GraphExamples { + + companion object { + fun getSimpleOrder( + config: TranslationConfiguration = + TranslationConfiguration.builder() + .defaultPasses() + .registerLanguage(TestLanguage(".")) + .registerPass() + .registerPass() + .build() + ) = + testFrontend(config).build { + translationResult { + translationUnit("SimpleOrder.java") { + import("kotlin.random.URandomKt") + record("Botan") { + constructor { + param("i", t("int")) + body {} + } + method("create", void()) { body {} } + method("finish", void()) { + param("b", t("char").array()) + body {} + } + method("init", void()) { body {} } + method("process", void()) { body {} } + method("reset", void()) { body {} } + method("start", void()) { + param("i", t("int")) + body {} + } + method("set_key", void()) { + param("i", t("int")) + body {} + } + } + record("SimpleOrder") { + field("cipher", t("char").array()) {} + field("key", t("int")) {} + field("iv", t("int")) {} + field("direction", t("Cipher_Dir")) {} + field("buf", t("char").array()) {} + + method("ok", void()) { + body { + declare { + variable("p4", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + memberCall("start", ref("p4")) { ref("iv") } + memberCall("finish", ref("p4")) { ref("buf") } + returnStmt {} + } + } + + method("ok2", void()) { + body { + declare { + variable("p4", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + memberCall("start", ref("p4")) { ref("iv") } + memberCall( + "foo", + ref("p4") + ) // Not in the entity and therefore ignored + memberCall("finish", ref("p4")) { ref("buf") } + returnStmt {} + } + } + + method("ok3", void()) { + body { + declare { + variable("p4", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + declare { + variable("x", t("int")) { + memberCall("nextUInt", ref("URandomKt")) + } + } + ifStmt { + condition { ref("x") le literal(5, t("int")) } + thenStmt { memberCall("start", ref("p4")) { ref("iv") } } + elseStmt { memberCall("start", ref("p4")) { ref("iv") } } + } + memberCall( + "foo", + ref("p4") + ) // Not in the entity and therefore ignored + memberCall("finish", ref("p4")) { ref("buf") } + returnStmt {} + } + } + + method("nok1", void()) { + body { + declare { + variable("p4", t("Botan")) { + construct("Botan") { literal(1, t("int")) } + } + } + memberCall("set_key", ref("p4")) { + ref("key") + } // Not allowed as start + memberCall("start", ref("p4")) { ref("iv") } + memberCall("finish", ref("p4")) { ref("buf") } + memberCall( + "foo", + ref("p4") + ) // Not in the entity and therefore ignored + memberCall("set_key", ref("p4")) { ref("key") } + returnStmt {} + } + } + + method("nok2", void()) { + body { + declare { + variable("p4", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + memberCall("start", ref("p4")) { ref("iv") } + // Missing: memberCall("finish", ref("p4")) {ref("buf")} + returnStmt {} + } + } + + method("nok3", void()) { + body { + declare { + variable("p4", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + ifStmt { + condition { + memberCall("nextUInt", ref("URandomKt")) le + literal(5, t("int")) + } + thenStmt { memberCall("start", ref("p4")) { ref("iv") } } + } + // start could be missing here + memberCall("finish", ref("p4")) { ref("buf") } + returnStmt {} + } + } + + method("nok4", void()) { + body { + declare { + variable("p4", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + ifStmt { + condition { literal(true, t("boolean")) } + thenStmt { + memberCall("start", ref("p4")) { ref("iv") } + memberCall("finish", ref("p4")) { ref("buf") } + } + } + // Not ok because p4 is already finished + memberCall("start", ref("p4")) { ref("iv") } + memberCall("finish", ref("p4")) { ref("buf") } + returnStmt {} + } + } + + method("nok5", void()) { + body { + block { + declare { + variable("p4", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + memberCall("start", ref("p4")) { ref("iv") } + } + block { + declare { + variable("p5", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + memberCall("finish", ref("p5")) { ref("buf") } + returnStmt {} + } + } + } + } + } + } + } + + fun getComplexOrder( + config: TranslationConfiguration = + TranslationConfiguration.builder() + .defaultPasses() + .registerLanguage(TestLanguage(".")) + .registerPass() + .registerPass() + .build() + ) = + testFrontend(config).build { + translationResult { + translationUnit("ComplexOrder.java") { + import("kotlin.random.URandomKt") + record("Botan") { + constructor { + param("i", t("int")) + body {} + } + method("create", void()) { body {} } + method("finish", void()) { body {} } + method("init", void()) { body {} } + method("process", void()) { body {} } + method("reset", void()) { body {} } + method("start", void()) { body {} } + } + record("ComplexOrder") { + method("ok_minimal1", void()) { + body { + declare { + variable("p1", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + memberCall("create", ref("p1")) + memberCall("init", ref("p1")) + memberCall("start", ref("p1")) + memberCall("finish", ref("p1")) + returnStmt {} + } + } + + method("ok_minimal2", void()) { + body { + declare { + variable("p1", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + memberCall("create", ref("p1")) + memberCall("init", ref("p1")) + memberCall("start", ref("p1")) + memberCall("process", ref("p1")) + memberCall("finish", ref("p1")) + returnStmt {} + } + } + + method("ok_minimal3", void()) { + body { + declare { + variable("p1", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + memberCall("create", ref("p1")) + memberCall("init", ref("p1")) + memberCall("start", ref("p1")) + memberCall("process", ref("p1")) + memberCall("finish", ref("p1")) + memberCall("reset", ref("p1")) + returnStmt {} + } + } + + method("ok2", void()) { + body { + declare { + variable("p2", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + memberCall("create", ref("p2")) + memberCall("init", ref("p2")) + memberCall("start", ref("p2")) + memberCall("process", ref("p2")) + memberCall("process", ref("p2")) + memberCall("process", ref("p2")) + memberCall("process", ref("p2")) + memberCall("finish", ref("p2")) + returnStmt {} + } + } + + method("ok3", void()) { + body { + declare { + variable("p3", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + memberCall("create", ref("p3")) + memberCall("init", ref("p3")) + memberCall("start", ref("p3")) + memberCall("process", ref("p3")) + memberCall("finish", ref("p3")) + memberCall("start", ref("p3")) + memberCall("process", ref("p3")) + memberCall("finish", ref("p3")) + returnStmt {} + } + } + + method("ok4", void()) { + body { + declare { + variable("p3", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + memberCall("create", ref("p3")) + memberCall("init", ref("p3")) + memberCall("start", ref("p3")) + memberCall("process", ref("p3")) + memberCall("finish", ref("p3")) + memberCall("start", ref("p3")) + memberCall("process", ref("p3")) + memberCall("finish", ref("p3")) + memberCall("reset", ref("p3")) + returnStmt {} + } + } + + method("nok1", void()) { + body { + declare { + variable("p5", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + memberCall("init", ref("p5")) + memberCall("start", ref("p5")) + memberCall("process", ref("p5")) + memberCall("finish", ref("p5")) + returnStmt {} + } + } + + method("nok2", void()) { + body { + declare { + variable("p6", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + memberCall("create", ref("p6")) + memberCall("init", ref("p6")) + ifStmt { + condition { literal(false, t("boolean")) } + thenStmt { + memberCall("start", ref("p6")) + memberCall("process", ref("p6")) + memberCall("finish", ref("p6")) + } + } + memberCall("reset", ref("p6")) + returnStmt {} + } + } + + method("nok3", void()) { + body { + declare { + variable("p6", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + whileStmt { + whileCondition { literal(true, t("boolean")) } + loopBody { + memberCall("create", ref("p6")) + memberCall("init", ref("p6")) + memberCall("start", ref("p6")) + memberCall("process", ref("p6")) + memberCall("finish", ref("p6")) + } + } + memberCall("reset", ref("p6")) + returnStmt {} + } + } + + method("nokWhile", void()) { + body { + declare { + variable("p7", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + memberCall("create", ref("p7")) + memberCall("init", ref("p7")) + whileStmt { + whileCondition { + memberCall("nextUInt", ref("URandomKt"), true) gt + literal(5, t("int")) + } + loopBody { + memberCall("start", ref("p7")) + memberCall("process", ref("p7")) + memberCall("finish", ref("p7")) + } + } + memberCall("reset", ref("p7")) + returnStmt {} + } + } + + method("okWhile", void()) { + body { + declare { + variable("p8", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + memberCall("create", ref("p8")) + memberCall("init", ref("p8")) + memberCall("start", ref("p8")) + memberCall("process", ref("p8")) + memberCall("finish", ref("p8")) + whileStmt { + whileCondition { literal(true, t("boolean")) } + loopBody { + memberCall("start", ref("p8")) + memberCall("process", ref("p8")) + memberCall("finish", ref("p8")) + } + } + memberCall("reset", ref("p8")) + returnStmt {} + } + } + + method("okWhile2", void()) { + body { + declare { + variable("p8", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + memberCall("create", ref("p8")) + memberCall("init", ref("p8")) + whileStmt { + whileCondition { literal(true, t("boolean")) } + loopBody { + memberCall("start", ref("p8")) + memberCall("process", ref("p8")) + memberCall("finish", ref("p8")) + } + } + memberCall("reset", ref("p8")) + returnStmt {} + } + } + + method("okDoWhile", void()) { + body { + declare { + variable("p6", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + memberCall("create", ref("p6")) + memberCall("init", ref("p6")) + doStmt { + loopBody { + memberCall("start", ref("p6")) + memberCall("process", ref("p6")) + memberCall("finish", ref("p6")) + } + + whileCondition { + memberCall("nextUInt", ref("URandomKt")) gt + literal(5, t("int")) + } + } + memberCall("reset", ref("p6")) + returnStmt {} + } + } + + method("minimalInterprocUnclear", void()) { + body { + declare { + variable("p1", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + memberCall("create", ref("p1")) + memberCall("foo", ref("this")) { ref("p1") } + memberCall("start", ref("p1")) + memberCall("finish", ref("p1")) + returnStmt {} + } + } + + method("minimalInterprocFail", void()) { + body { + declare { + variable("p1", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + memberCall("create", ref("p1")) + ifStmt { + condition { + memberCall("nextUInt", ref("URandomKt")) gt + literal(5, t("int")) + } + thenStmt { memberCall("foo", ref("this")) { ref("p1") } } + } + memberCall("start", ref("p1")) + memberCall("finish", ref("p1")) + returnStmt {} + } + } + + method("minimalInterprocFail2", void()) { + body { + declare { + variable("p1", t("Botan")) { + construct("Botan") { literal(1, t("int")) } + } + } + declare { + variable("p2", t("Botan")) { + construct("Botan") { literal(2, t("int")) } + } + } + memberCall("create", ref("p1")) + memberCall("create", ref("p2")) + memberCall("foo", ref("this")) { ref("p2") } + memberCall("start", ref("p1")) + memberCall("finish", ref("p1")) + returnStmt {} + } + } + + method("foo", void()) { + param("p1", t("Botan")) + body { + memberCall("init", ref("p1")) + returnStmt {} + } + } + + method("bar", void()) { + body { + declare { + variable("p1", t("Botan")) { + construct("Botan") { literal(1, t("int")) } + } + } + memberCall("create", ref("p1")) + memberCall("minimalInterprocUnclearArgument", ref("this")) { + ref("p1") + } + returnStmt {} + } + } + + method("minimalInterprocUnclearArgument", void()) { + param("p1", t("Botan")) + body { + memberCall("init", ref("p1")) + memberCall("start", ref("p1")) + memberCall("finish", ref("p1")) + returnStmt {} + } + } + + method("minimalInterprocUnclearReturn", t("Botan")) { + body { + declare { + variable("p1", t("Botan")) { + construct("Botan") { literal(1, t("int")) } + } + } + memberCall("create", ref("p1")) + memberCall("init", ref("p1")) + memberCall("start", ref("p1")) + returnStmt { ref("p1") } + } + } + } + } + } + } + } +} + +fun testFrontend(config: TranslationConfiguration): TestLanguageFrontend { + val ctx = TranslationContext(config, ScopeManager(), TypeManager()) + val language = config.languages.filterIsInstance().first() + return TestLanguageFrontend(language.namespaceDelimiter, language, ctx) +} diff --git a/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/testcases/Passes.kt b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/testcases/Passes.kt new file mode 100644 index 00000000000..c639e3ec830 --- /dev/null +++ b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/testcases/Passes.kt @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2023, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +package de.fraunhofer.aisec.cpg.testcases + +import de.fraunhofer.aisec.cpg.TranslationConfiguration +import de.fraunhofer.aisec.cpg.frontends.TestLanguage +import de.fraunhofer.aisec.cpg.graph.builder.* +import de.fraunhofer.aisec.cpg.passes.UnreachableEOGPass + +class Passes { + companion object { + fun getUnreachability( + config: TranslationConfiguration = + TranslationConfiguration.builder() + .defaultPasses() + .registerPass() + .registerLanguage(TestLanguage(".")) + .build() + ) = + testFrontend(config).build { + translationResult { + translationUnit("Unreachability.java") { + import("kotlin.random.URandomKt") + record("TestClass") { + method("ifBothPossible", void()) { + body { + declare { variable("y", t("int")) { literal(6, t("int")) } } + declare { + variable("x", t("int")) { + memberCall("nextUInt", ref("URandomKt")) + } + } + + ifStmt { + condition { ref("x") lt ref("y") } + thenStmt { ref("y").inc() } + elseStmt { ref("y").dec() } + } + memberCall("println", member("out", ref("System"))) { ref("y") } + returnStmt {} + } + } + + method("ifTrue", void()) { + body { + declare { variable("y", t("int")) { literal(6, t("int")) } } + declare { + variable("x", t("int")) { + memberCall("nextUInt", ref("URandomKt")) + } + } + + ifStmt { + condition { literal(true, t("boolean")) } + thenStmt { ref("y").inc() } + elseStmt { ref("y").dec() } + } + memberCall("println", member("out", ref("System"))) { ref("y") } + returnStmt {} + } + } + + method("ifFalse", void()) { + body { + declare { variable("y", t("int")) { literal(6, t("int")) } } + declare { + variable("x", t("int")) { + memberCall("nextUInt", ref("URandomKt")) + } + } + + ifStmt { + condition { literal(false, t("boolean")) } + thenStmt { ref("y").inc() } + elseStmt { ref("y").dec() } + } + memberCall("println", member("out", ref("System"))) { ref("y") } + returnStmt {} + } + } + + method("ifTrueComputed", void()) { + body { + declare { variable("y", t("int")) { literal(6, t("int")) } } + declare { + variable("x", t("int")) { + memberCall("nextUInt", ref("URandomKt")) + } + } + + ifStmt { + condition { ref("y") lt literal(10, t("int")) } + thenStmt { ref("y").inc() } + elseStmt { ref("y").dec() } + } + memberCall("println", member("out", ref("System"))) { ref("y") } + returnStmt {} + } + } + + method("ifTrueComputedHard", void()) { + body { + declare { variable("z", t("int")) { literal(2, t("int")) } } + declare { variable("y", t("int")) { ref("z") } } + declare { + variable("x", t("int")) { + memberCall("nextUInt", ref("URandomKt")) + } + } + + ifStmt { + condition { ref("y") + ref("z") lt literal(10, t("int")) } + thenStmt { ref("y").inc() } + elseStmt { ref("y").dec() } + } + ref("z") assign literal(10, t("int")) + memberCall("println", member("out", ref("System"))) { ref("y") } + returnStmt {} + } + } + + method("ifFalseComputedHard", void()) { + body { + declare { variable("z", t("int")) { literal(5, t("int")) } } + declare { variable("y", t("int")) { ref("z") } } + declare { + variable("x", t("int")) { + memberCall("nextUInt", ref("URandomKt")) + } + } + + ifStmt { + condition { ref("y") + ref("z") lt literal(10, t("int")) } + thenStmt { ref("y").inc() } + elseStmt { ref("y").dec() } + } + ref("z") assign literal(3, t("int")) + memberCall("println", member("out", ref("System"))) { ref("y") } + returnStmt {} + } + } + + method("ifFalseComputed", void()) { + body { + declare { variable("y", t("int")) { literal(6, t("int")) } } + declare { + variable("x", t("int")) { + memberCall("nextUInt", ref("URandomKt")) + } + } + + ifStmt { + condition { ref("y") lt literal(0, t("int")) } + thenStmt { ref("y").inc() } + elseStmt { ref("y").dec() } + } + memberCall("println", member("out", ref("System"))) { ref("y") } + returnStmt {} + } + } + + method("whileTrueEndless", void()) { + body { + declare { + variable("x", t("boolean")) { literal(true, t("boolean")) } + } + + whileStmt { + whileCondition { ref("x") } + loopBody { + memberCall("println", member("out", ref("System"))) { + literal("Cool loop", t("string")) + } + } + } + + memberCall("println", member("out", ref("System"))) { + literal("After cool loop", t("string")) + } + returnStmt {} + } + } + + method("whileTrue", void()) { + body { + declare { + variable("x", t("boolean")) { literal(true, t("boolean")) } + } + + whileStmt { + whileCondition { ref("x") } + loopBody { + memberCall("println", member("out", ref("System"))) { + literal("Cool loop", t("string")) + } + ref("x") assign literal(false, t("boolean")) + } + } + + memberCall("println", member("out", ref("System"))) { + literal("After cool loop", t("string")) + } + returnStmt {} + } + } + + method("whileFalse", void()) { + body { + whileStmt { + whileCondition { literal(false, t("boolean")) } + loopBody { + memberCall("println", member("out", ref("System"))) { + literal("Cool loop", t("string")) + } + } + } + + memberCall("println", member("out", ref("System"))) { + literal("After cool loop", t("string")) + } + returnStmt {} + } + } + + method("whileComputedTrue", void()) { + body { + declare { variable("x", t("boolean")) { literal(1, t("int")) } } + + whileStmt { + whileCondition { ref("x") lt literal(3, t("int")) } + loopBody { + memberCall("println", member("out", ref("System"))) { + literal("Cool loop", t("string")) + } + } + } + + memberCall("println", member("out", ref("System"))) { + literal("After cool loop", t("string")) + } + returnStmt {} + } + } + + method("whileComputedFalse", void()) { + body { + declare { variable("x", t("boolean")) { literal(1, t("int")) } } + + whileStmt { + whileCondition { ref("x") gt literal(3, t("int")) } + loopBody { + memberCall("println", member("out", ref("System"))) { + literal("Cool loop", t("string")) + } + } + } + + memberCall("println", member("out", ref("System"))) { + literal("After cool loop", t("string")) + } + returnStmt {} + } + } + + method("whileUnknown", void()) { + body { + declare { + variable("y", t("int")) { + memberCall("nextUInt", ref("URandomKt")) + } + } + + whileStmt { + whileCondition { ref("y") lt literal(3, t("int")) } + loopBody { + memberCall("println", member("out", ref("System"))) { + literal("Cool loop", t("string")) + } + ref("y") assign memberCall("nextUInt", ref("URandomKt")) + } + } + + memberCall("println", member("out", ref("System"))) { + literal("After cool loop", t("string")) + } + returnStmt {} + } + } + } + } + } + } + } +} diff --git a/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/testcases/Query.kt b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/testcases/Query.kt new file mode 100644 index 00000000000..53283d40844 --- /dev/null +++ b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/testcases/Query.kt @@ -0,0 +1,618 @@ +/* + * Copyright (c) 2023, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +package de.fraunhofer.aisec.cpg.testcases + +import de.fraunhofer.aisec.cpg.TranslationConfiguration +import de.fraunhofer.aisec.cpg.frontends.TestLanguage +import de.fraunhofer.aisec.cpg.graph.array +import de.fraunhofer.aisec.cpg.graph.builder.* +import de.fraunhofer.aisec.cpg.graph.newNewArrayExpression +import de.fraunhofer.aisec.cpg.graph.pointer +import de.fraunhofer.aisec.cpg.passes.EdgeCachePass + +class Query { + companion object { + fun getDataflow( + config: TranslationConfiguration = + TranslationConfiguration.builder() + .defaultPasses() + .registerLanguage(TestLanguage(".")) + .build() + ) = + testFrontend(config).build { + translationResult { + translationUnit("Dataflow.java") { + record("Dataflow") { + field("attr", t("string")) {} + method("toString", t("string")) { + body { + returnStmt { + literal("Dataflow: attr=", t("string")) + ref("attr") + } + } + } + + method("test", t("string")) { + body { returnStmt { literal("abcd", t("string")) } } + } + + method("print", void()) { + param("s", t("string")) + body { + memberCall("println", member("out", ref("System"))) { ref("s") } + returnStmt {} + } + } + + method("main", void()) { + isStatic = true + param("args", t("string").array()) + body { + declare { + variable("sc", t("Dataflow")) { + new { construct("Dataflow") } + } + } + + declare { + variable("s", t("string")) { + memberCall("toString", ref("sc")) + } + } + memberCall("print", ref("sc")) { ref("s") } + memberCall("print", ref("sc")) { + memberCall("test", ref("sc", makeMagic = false)) + } + } + } + } + } + } + } + + fun getComplexDataflow( + config: TranslationConfiguration = + TranslationConfiguration.builder() + .defaultPasses() + .registerLanguage(TestLanguage(".")) + .registerPass() + .build() + ) = + testFrontend(config).build { + translationResult { + translationUnit("ComplexDataflow.java") { + record("Dataflow") { + field("logger", t("Logger")) { + // TODO: this field is static. How do we model this? + this.modifiers = listOf("static") + memberCall("getLogger", ref("Logger")) { + literal("DataflowLogger", t("string")) + } + } + + field("a", t("int")) {} + + method("highlyCriticalOperation", void()) { + isStatic = true + param("s", t("string")) + body { + memberCall("println", member("out", ref("System"))) { ref("s") } + returnStmt {} + } + } + + method("main", void()) { + isStatic = true + param("args", t("string").array()) + body { + declare { + variable("sc", t("Dataflow")) { + new { construct("Dataflow") } + } + } + + member("a", ref("sc")) assign literal(5, t("int")) + + memberCall( + "highlyCriticalOperation", + ref("Dataflow", t("Dataflow")) { + isStatic = true + refersTo = this@record + } + ) { + this@memberCall.isStatic = true + memberCall( + "toString", + ref("Integer", t("Integer"), makeMagic = false) + ) { + this.type = t("string") + this@memberCall.isStatic = true + isStatic = true + member("a", ref("sc", makeMagic = false)) + } + } + + memberCall("log", ref("logger")) { + member("INFO", ref("Level", makeMagic = false)) + literal("put ", t("string")) + + member("a", ref("a", makeMagic = false)) + + literal(" into highlyCriticalOperation()", t("string")) + } + returnStmt {} + } + } + } + } + } + } + + fun getComplexDataflow2( + config: TranslationConfiguration = + TranslationConfiguration.builder() + .defaultPasses() + .registerLanguage(TestLanguage(".")) + .registerPass() + .build() + ) = + testFrontend(config).build { + translationResult { + translationUnit("ComplexDataflow2.java") { + record("Dataflow") { + field("logger", t("Logger")) { + // TODO: this field is static. How do we model this? + this.modifiers = listOf("static") + memberCall("getLogger", ref("Logger")) { + literal("DataflowLogger", t("string")) + } + } + + field("a", t("int")) {} + + method("highlyCriticalOperation", void()) { + isStatic = true + param("s", t("string")) + body { + memberCall("println", member("out", ref("System"))) { ref("s") } + returnStmt {} + } + } + + method("main", void()) { + isStatic = true + param("args", t("string").array()) + body { + declare { + variable("sc", t("Dataflow")) { + new { construct("Dataflow") } + } + } + + member("a", ref("sc")) assign literal(5, t("int")) + + memberCall("log", ref("logger")) { + member("INFO", ref("Level", makeMagic = false)) + literal("put ", t("string")) + + member("a", ref("a", makeMagic = false)) + + literal(" into highlyCriticalOperation()", t("string")) + } + + memberCall( + "highlyCriticalOperation", + ref("Dataflow", t("Dataflow")) { + isStatic = true + refersTo = this@record + } + ) { + this@memberCall.isStatic = true + memberCall( + "toString", + ref("Integer", t("Integer"), makeMagic = false) + ) { + this.type = t("string") + this@memberCall.isStatic = true + isStatic = true + member("a", ref("sc", makeMagic = false)) + } + } + returnStmt {} + } + } + } + } + } + } + + fun getComplexDataflow3( + config: TranslationConfiguration = + TranslationConfiguration.builder() + .defaultPasses() + .registerLanguage(TestLanguage(".")) + .registerPass() + .build() + ) = + testFrontend(config).build { + translationResult { + translationUnit("ComplexDataflow3.java") { + record("Dataflow") { + field("logger", t("Logger")) { + // TODO: this field is static. How do we model this? + this.modifiers = listOf("static") + memberCall("getLogger", ref("Logger")) { + literal("DataflowLogger", t("string")) + } + } + + field("a", t("int")) {} + + method("highlyCriticalOperation", void()) { + isStatic = true + param("s", t("string")) + body { + memberCall("println", member("out", ref("System"))) { ref("s") } + returnStmt {} + } + } + + method("main", void()) { + isStatic = true + param("args", t("string").array()) + body { + declare { + variable("sc", t("Dataflow")) { + new { construct("Dataflow") } + } + } + + member("a", ref("sc")) assign literal(5, t("int")) + + memberCall("log", ref("logger")) { + member("INFO", ref("Level", makeMagic = false)) + literal("put ", t("string")) + + member("a", ref("a", makeMagic = false)) + + literal(" into highlyCriticalOperation()", t("string")) + } + + member("a", ref("sc")) assign literal(3, t("int")) + + memberCall( + "highlyCriticalOperation", + ref("Dataflow", t("Dataflow")) { + isStatic = true + refersTo = this@record + } + ) { + this@memberCall.isStatic = true + memberCall( + "toString", + ref("Integer", t("Integer"), makeMagic = false) + ) { + this.type = t("string") + this@memberCall.isStatic = true + isStatic = true + member("a", ref("sc", makeMagic = false)) + } + } + returnStmt {} + } + } + } + } + } + } + + fun getArray( + config: TranslationConfiguration = + TranslationConfiguration.builder() + .defaultPasses() + .registerLanguage(TestLanguage(".")) + .build() + ) = + testFrontend(config).build { + translationResult { + translationUnit("array.cpp") { + function("main", t("int")) { + body { + declare { + variable("c", t("char").pointer()) { + val creationExpr = newNewArrayExpression() + creationExpr.addDimension(literal(4, t("int"))) + creationExpr.type = t("char") + this.initializer = creationExpr + } + } + + declare { variable("a", t("int")) { literal(4, t("int")) } } + + declare { + variable("b", t("int")) { ref("a") + literal(1, t("int")) } + } + + declare { + variable("d", t("char")) { + ase { + ref("c") + ref("b") + } + } + } + + returnStmt { literal(0, t("int")) } + } + } + + function("some_other_function", t("char")) { + declare { + variable("c", t("char").pointer()) { + val creationExpr = newNewArrayExpression() + creationExpr.addDimension(literal(100, t("int"))) + creationExpr.type = t("char") + this.initializer = creationExpr + } + } + returnStmt { + ase { + ref("c") + literal(0, t("int")) + } + } + } + } + } + } + + fun getArray2( + config: TranslationConfiguration = + TranslationConfiguration.builder() + .defaultPasses() + .registerPass() + .registerLanguage(TestLanguage(".")) + .build() + ) = + testFrontend(config).build { + translationResult { + translationUnit("array2.cpp") { + function("main", t("int")) { + body { + declare { + variable("c", t("char").pointer()) { + val creationExpr = newNewArrayExpression() + creationExpr.addDimension(literal(4, t("int"))) + creationExpr.type = t("char") + this.initializer = creationExpr + } + } + + declare { variable("a", t("int")) { literal(0, t("int")) } } + + forStmt( + declareVar("i", t("int")) { literal(0, t("int")) }, + ref("i") le literal(4, t("int")), + ref("i").incNoContext() + ) { + ref("a") assign + { + ref("a") + + ase { + ref("c") + ref("i") + } + } + } + + returnStmt { ref("a") } + } + } + } + } + } + + fun getArray3( + config: TranslationConfiguration = + TranslationConfiguration.builder() + .defaultPasses() + .registerPass() + .registerLanguage(TestLanguage(".")) + .build() + ) = + testFrontend(config).build { + translationResult { + translationUnit("array3.cpp") { + function("main", t("int")) { + body { + declare { variable("c", t("char").pointer()) } + ifStmt { + condition { literal(5, t("int")) gt literal(4, t("int")) } + thenStmt { + ref("c") assign + run { + val creationExpr = newNewArrayExpression() + creationExpr.addDimension(literal(4, t("int"))) + creationExpr.type = t("char") + (creationExpr) + } + } + elseStmt { + ref("c") assign + run { + val creationExpr = newNewArrayExpression() + creationExpr.addDimension(literal(5, t("int"))) + creationExpr.type = t("char") + (creationExpr) + } + } + } + + declare { variable("a", t("int")) { literal(0, t("int")) } } + + forStmt( + declareVar("i", t("int")) { literal(0, t("int")) }, + ref("i") le literal(4, t("int")), + ref("i").incNoContext() + ) { + ref("a") assign + { + ref("a") + + ase { + ref("c") + ref("i") + } + } + } + + returnStmt { ref("a") } + } + } + } + } + } + + fun getArrayCorrect( + config: TranslationConfiguration = + TranslationConfiguration.builder() + .defaultPasses() + .registerPass() + .registerLanguage(TestLanguage(".")) + .build() + ) = + testFrontend(config).build { + translationResult { + translationUnit("array_correct.cpp") { + function("main", t("int")) { + body { + declare { + variable("c", t("char").pointer()) { + val creationExpr = newNewArrayExpression() + creationExpr.addDimension(literal(4, t("int"))) + creationExpr.type = t("char") + this.initializer = creationExpr + } + } + + declare { variable("a", t("int")) { literal(0, t("int")) } } + + forStmt( + declareVar("i", t("int")) { literal(0, t("int")) }, + ref("i") lt literal(4, t("int")), + ref("i").incNoContext() + ) { + ref("a") assign + { + ref("a") + + ase { + ref("c") + ref("i") + } + } + } + + returnStmt { ref("a") } + } + } + } + } + } + + fun getAssign( + config: TranslationConfiguration = + TranslationConfiguration.builder() + .defaultPasses() + .registerLanguage(TestLanguage(".")) + .build() + ) = + testFrontend(config).build { + translationResult { + translationUnit("assign.cpp") { + function("main", t("int")) { + body { + declare { variable("a", t("int")) { literal(4, t("int")) } } + // TODO: There was a commented-out line. No idea what to do with it: + // int a, b = 4; // this is broken, a is missing an initializer + + ref("a") assign literal(3, t("int")) + + returnStmt { ref("a") } + } + } + } + } + } + + fun getVulnerable( + config: TranslationConfiguration = + TranslationConfiguration.builder() + .defaultPasses() + .registerLanguage(TestLanguage(".")) + .build() + ) = + testFrontend(config).build { + translationResult { + translationUnit("assign.cpp") { + function("main", t("int")) { + body { + declare { + variable("array", t("char").array()) { + literal("hello", t("char").array()) + } + } + call("memcpy") { + ref("array") + literal("Hello world", t("char").array()) + literal(11, t("int")) + } + + call("printf") { ref("array") } + + call("free") { ref("array") } + + call("free") { ref("array") } + + declare { variable("a", t("short")) { literal(2, t("int")) } } + + ifStmt { + condition { ref("array") eq literal("hello", t("string")) } + thenStmt { ref("a") assign literal(0, t("int")) } + } + + declare { + variable("x", t("double")) { literal(5, t("int")) / ref("a") } + } + + declare { + variable("b", t("int")) { literal(2147483648, t("int")) } + } + + ref("b") assign literal(2147483648, t("int")) + + declare { variable("c", t("long")) { literal(-10000, t("long")) } } + + returnStmt { literal(0, t("int")) } + } + } + } + } + } + } +} diff --git a/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/testcases/ValueEvaluationTests.kt b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/testcases/ValueEvaluationTests.kt new file mode 100644 index 00000000000..ba6a168da13 --- /dev/null +++ b/cpg-analysis/src/test/kotlin/de/fraunhofer/aisec/cpg/testcases/ValueEvaluationTests.kt @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2023, Fraunhofer AISEC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $$$$$$\ $$$$$$$\ $$$$$$\ + * $$ __$$\ $$ __$$\ $$ __$$\ + * $$ / \__|$$ | $$ |$$ / \__| + * $$ | $$$$$$$ |$$ |$$$$\ + * $$ | $$ ____/ $$ |\_$$ | + * $$ | $$\ $$ | $$ | $$ | + * \$$$$$ |$$ | \$$$$$ | + * \______/ \__| \______/ + * + */ +package de.fraunhofer.aisec.cpg.testcases + +import de.fraunhofer.aisec.cpg.TranslationConfiguration +import de.fraunhofer.aisec.cpg.frontends.TestLanguage +import de.fraunhofer.aisec.cpg.graph.* +import de.fraunhofer.aisec.cpg.graph.builder.* +import de.fraunhofer.aisec.cpg.passes.EdgeCachePass +import de.fraunhofer.aisec.cpg.passes.UnreachableEOGPass + +class ValueEvaluationTests { + companion object { + fun getSizeExample( + config: TranslationConfiguration = + TranslationConfiguration.builder() + .defaultPasses() + .registerLanguage(TestLanguage(".")) + .registerPass() + .registerPass() + .build() + ) = + testFrontend(config).build { + translationResult { + translationUnit("size.java") { + record("MainClass") { + method("main") { + this.isStatic = true + param("args", t("String").array()) + body { + declare { + variable("array", t("int").array()) { + val newExpr = newNewArrayExpression() + newExpr.addDimension(literal(3, t("int"))) + this.initializer = newExpr + } + } + forStmt( + declare { + variable("i", t("int")) { literal(0, t("int")) } + }, + ref("i") lt member("length", ref("array")), + ref("i").inc() + ) { + ase { + ref("array") + ref("i") + } assign ref("i") + } + memberCall("println", member("out", ref("System"))) { + ase { + ref("array") + literal(1, t("int")) + } + } + + declare { + variable("str", t("String")) { + literal("abcde", t("String")) + } + } + + memberCall("println", member("out", ref("System"))) { + ref("str") + } + returnStmt {} + } + } + } + } + } + } + + fun getComplexExample( + config: TranslationConfiguration = + TranslationConfiguration.builder() + .defaultPasses() + .registerLanguage(TestLanguage(".")) + .registerPass() + .registerPass() + .build() + ) = + testFrontend(config).build { + translationResult { + translationUnit("complex.java") { + record("MainClass") { + method("main") { + this.isStatic = true + param("args", t("String").array()) + body { + declare { variable("i", t("int")) { literal(3, t("int")) } } + declare { variable("s", t("String")) } + + ifStmt { + condition { ref("i") lt literal(2, t("int")) } + thenStmt { ref("s") assign literal("small", t("String")) } + elseStmt { ref("s") assign literal("big", t("String")) } + } + + ref("s") assignPlus literal("!", t("String")) + + ref("s") assign { ref("s") + literal("?", t("string")) } + + ref("i").inc() + + memberCall("println", member("out", ref("System"))) { ref("s") } + + memberCall("println", member("out", ref("System"))) { ref("i") } + returnStmt {} + } + } + } + } + } + } + + fun getExample( + config: TranslationConfiguration = + TranslationConfiguration.builder() + .defaultPasses() + .registerLanguage(TestLanguage(".")) + .registerPass() + .registerPass() + .build() + ) = + testFrontend(config).build { + translationResult { + translationUnit("example.cpp") { + function("main", t("int")) { + body { + declare { + variable("b", t("int")) { + literal(1, t("int")) + literal(1, t("int")) + } + } + call("println") { ref("b") } + + declare { variable("a", t("int")) { literal(1, t("int")) } } + ref("a") assign literal(2, t("int")) + call("println") { ref("a") } + + declare { + variable("c", t("int")) { + literal(5, t("int")) - literal(2, t("int")) + } + } + + declare { + variable("d", t("float")) { + literal(8, t("int")) / literal(3, t("int")) + } + } + + declare { + variable("e", t("float")) { + literal(7.0, t("float")) / literal(2, t("int")) + } + } + + declare { + variable("f", t("int")) { + literal(2, t("int")) * literal(5, t("int")) + } + } + + declare { variable("g", t("int")) { -ref("c") } } + + call("println") { + literal("Hello ", t("String")) + literal("world", t("String")) + } + + declare { + variable("h", t("bool")) { + literal(5, t("int")) lt literal(3, t("int")) + } + } + + declare { + variable("i", t("bool")) { + literal(3, t("int")) gt literal(3, t("int")) + } + } + + declare { + variable("j", t("bool")) { + literal(3, t("int")) ge literal(3.2, t("float")) + } + } + + declare { + variable("k", t("bool")) { + literal(3.1, t("float")) le literal(3, t("int")) + } + } + + declare { + variable("l", t("bool")) { + literal(3L, t("long")) ge + cast(t("float")) { literal(3.1, t("float")) } + } + } + + declare { + variable("m", t("bool")) { + cast(t("char")) { literal(3, t("int")) } ge + literal(3.1, t("float")) + } + } + + declare { + variable("n", t("bool")) { + literal(3, t("int")) eq literal(3.1, t("float")) + } + } + + returnStmt { literal(0, t("int")) } + } + } + } + } + } + + fun getCfExample( + config: TranslationConfiguration = + TranslationConfiguration.builder() + .defaultPasses() + .registerLanguage(TestLanguage(".")) + .registerPass() + .registerPass() + .build() + ) = + testFrontend(config).build { + translationResult { + translationUnit("cfexample.cpp") { + import("time.h") + import("stdlib.h") + function("main", t("int")) { + body { + call("srand") { call("time") { ref("NULL") } } + + declare { variable("b", t("int")) { literal(1, t("int")) } } + + ifStmt { + condition { call("rand") lt literal(10, t("int")) } + thenStmt { ref("b") assign { ref("b") + literal(1, t("int")) } } + } + + call("println") { ref("b") } // 1, 2 + + ifStmt { + condition { call("rand") gt literal(5, t("int")) } + thenStmt { ref("b") assign { ref("b") - literal(1, t("int")) } } + } + + call("println") { ref("b") } // 0, 1, 2 + + ifStmt { + condition { call("rand") gt literal(3, t("int")) } + thenStmt { ref("b") assign { ref("b") * literal(2, t("int")) } } + } + + call("println") { ref("b") } // 0, 1, 2, 4 + + ifStmt { + condition { call("rand") lt literal(4, t("int")) } + thenStmt { ref("b") assign -ref("b") } + } + + call("println") { ref("b") } // -4, -2, -1, 0, 1, 2, 4 + + declare { + variable("a", t("int")) { + this.initializer = + newConditionalExpression( + ref("b") lt literal(2, t("int")), + literal(3, t("int")), + literal(5, t("int")).inc() + ) + } + } + + call("println") { ref("a") } // 3, 6 + + returnStmt { literal(0, t("int")) } + } + } + + function("loop", t("int")) { + body { + declare { + variable("array", t("int").array()) { + val creationExpr = newNewArrayExpression() + creationExpr.addDimension(literal(6, t("int"))) + this.initializer = creationExpr + } + } + + forStmt( + declareVar("i", t("int")) { literal(0, t("int")) }, + ref("i") lt literal(6, t("int")), + ref("i").incNoContext() + ) { + ase { + ref("array") + ref("i") + } assign ref("i") + } + returnStmt { literal(0, t("int")) } + } + } + } + } + } + } +} diff --git a/cpg-analysis/src/test/resources/analyses/ordering/ComplexOrder.java b/cpg-analysis/src/test/resources/analyses/ordering/ComplexOrder.java deleted file mode 100644 index aab0bdc4da3..00000000000 --- a/cpg-analysis/src/test/resources/analyses/ordering/ComplexOrder.java +++ /dev/null @@ -1,223 +0,0 @@ -import kotlin.random.URandomKt; - -public class ComplexOrder { - // DOES NOT COMPILE - // DOES NOT MAKE REAL SENSE - - // allowed: - // cm.create(), cm.init(), (cm.start(), cm.process()*, cm.finish())+, cm.reset()? - - - void ok_minimal1() { - Botan2 p1 = new Botan2(1); - p1.create(); - p1.init(); - p1.start(); - p1.finish(); - } - - void ok_minimal2() { - Botan2 p1 = new Botan2(1); - p1.create(); - p1.init(); - p1.start(); - p1.process(); - p1.finish(); - } - - void ok_minimal3() { - Botan2 p1 = new Botan2(1); - p1.create(); - p1.init(); - p1.start(); - p1.process(); - p1.finish(); - p1.reset(); - } - - void ok2() { - Botan2 p2 = new Botan2(1); - p2.create(); - p2.init(); - p2.start(); - p2.process(); - p2.process(); - p2.process(); - p2.process(); - p2.finish(); - } - - void ok3() { - Botan2 p3 = new Botan2(1); - p3.create(); - p3.init(); - p3.start(); - p3.process(); - p3.finish(); - p3.start(); - p3.process(); - p3.finish(); - } - - void ok4() { - Botan2 p3 = new Botan2(1); - p3.create(); - p3.init(); - p3.start(); - p3.process(); - p3.finish(); - p3.start(); - p3.process(); - p3.finish(); - p3.reset(); - } - - void nok1() { - Botan2 p5 = new Botan2(1); - p5.init(); - p5.start(); - p5.process(); - p5.finish(); - } - - void nok2() { - Botan2 p6 = new Botan2(1); - p6.create(); - p6.init(); - if (false) { - p6.start(); - p6.process(); - p6.finish(); - } - p6.reset(); - } - - void nok3() { - Botan2 p6 = new Botan2(1); - while (true) { - p6.create(); - p6.init(); - p6.start(); - p6.process(); - p6.finish(); - } - p6.reset(); - } - - void nokWhile() { - Botan2 p7 = new Botan2(1); - p7.create(); - p7.init(); - while (URandomKt.nextUInt() > 5) { - p7.start(); - p7.process(); - p7.finish(); - } - p7.reset(); - } - - void okWhile() { - Botan2 p8 = new Botan2(1); - p8.create(); - p8.init(); - p8.start(); - p8.process(); - p8.finish(); - while (true) { - p8.start(); - p8.process(); - p8.finish(); - } - p8.reset(); - } - - void okWhile2() { - Botan2 p7 = new Botan2(1); - p7.create(); - p7.init(); - while (true) { - p7.start(); - p7.process(); - p7.finish(); - } - p7.reset(); - } - - void okDoWhile() { - Botan2 p6 = new Botan2(1); - p6.create(); - p6.init(); - do { - p6.start(); - p6.process(); - p6.finish(); - } while(URandomKt.nextUInt() > 5); - p6.reset(); - } - - void minimalInterprocUnclear() { - Botan2 p1 = new Botan2(1); - p1.create(); - foo(p1); - p1.start(); - p1.finish(); - } - - void minimalInterprocFail() { - Botan2 p1 = new Botan2(1); - p1.create(); - if (URandomKt.nextUInt() > 5) { - foo(p1); - } - p1.start(); - p1.finish(); - } - - void minimalInterprocFail2() { - Botan2 p1 = new Botan2(1); - Botan2 p2 = new Botan2(2); - p1.create(); - p2.create(); - foo(p2); - p1.start(); - p1.finish(); - } - - void foo(Botan2 p1) { - p1.init(); - } - - void minimalInterprocUnclearArgument(Botan2 p1) { - p1.init(); - p1.start(); - p1.finish(); - } - - void bar() { - Botan2 p1 = new Botan2(1); - p1.create(); - minimalInterprocUnclear2(p1); - } - - void minimalInterprocUnclearReturn() { - Botan2 p1 = new Botan2(1); - p1.create(); - p1.init(); - p1.start(); - return p1; - } -} - -public class Botan2 { - public void create() {} - - public void finish() {} - - public void init() {} - - public void process() {} - - public void reset() {} - - public void start() {} -} diff --git a/cpg-analysis/src/test/resources/analyses/ordering/SimpleOrder.java b/cpg-analysis/src/test/resources/analyses/ordering/SimpleOrder.java deleted file mode 100644 index 52be8c6bc5c..00000000000 --- a/cpg-analysis/src/test/resources/analyses/ordering/SimpleOrder.java +++ /dev/null @@ -1,104 +0,0 @@ -import kotlin.random.URandomKt; - -public class SimpleOrder { - // DOES NOT COMPILE - // DOES NOT MAKE REAL SENSE - - char[] cipher; - int key; - int iv; - Cipher_Dir direction; - char[] buf; - - void ok() { - // ok: - Botan p4 = new Botan(2); - p4.start(iv); - p4.finish(buf); - } - - void ok2() { - // ok: - Botan p4 = new Botan(2); - p4.start(iv); - p4.foo(); // not in the entity and therefore ignored - p4.finish(buf); - } - - void ok3() { - // ok: - Botan p4 = new Botan(2); - int x = URandomKt.nextUInt(); - if(x < 5) { - p4.start(iv); - } else { - p4.start(iv); - } - p4.foo(); // not in the entity and therefore ignored - p4.finish(buf); - } - - void nok1() { - Botan p = new Botan(1); - p.set_key(key); // not allowed as start - p.start(iv); - p.finish(buf); - p.foo(); // not in the entity and therefore ignored - p.set_key(key); - } - - void nok2() { - Botan p2 = new Botan(2); - p2.start(iv); - // missing p2.finish(buf); - } - - void nok3() { - Botan p3 = new Botan(2); - if (URandomKt.nextUInt() < 4) { - p3.start(iv); - } - p3.finish(buf); - // potentially wrong path which only calls p3.finish without p3.start - } - - void nok4() { - Botan p4 = new Botan(2); - if (true) { - p4.start(iv); - p4.finish(buf); - } - p4.start(iv); // not ok, p4 is already finished - p4.finish(buf); - } - - void nok5() { - // ok: - { - Botan p5 = new Botan(2); - p5.start(iv); - } - { - Botan p5 = new Botan(2); - p5.finish(buf); - } - } -} - -public class Botan { - public Botan(int i) {} - - public void create() {} - - public void finish(char[] b) {} - - public void init() {} - - public void process() {} - - public void reset() {} - - public void start(int i) {} - - public void set_key(int i) {} -} diff --git a/cpg-analysis/src/test/resources/passes/unreachable/Unreachability.java b/cpg-analysis/src/test/resources/passes/unreachable/Unreachability.java deleted file mode 100644 index 847fd121db3..00000000000 --- a/cpg-analysis/src/test/resources/passes/unreachable/Unreachability.java +++ /dev/null @@ -1,133 +0,0 @@ -import kotlin.random.URandomKt; - -public class TestClass { - public void ifBothPossible() { - int y = 6; - int x = URandomKt.nextUInt(); - if(x < y) { - y++; - } else { - y--; - } - System.out.println(y); - } - - public void ifTrue() { - int y = 6; - int x = URandomKt.nextUInt(); - if(true) { - y++; - } else { - y--; - } - System.out.println(y); - } - - public void ifFalse() { - int y = 6; - int x = URandomKt.nextUInt(); - if(false) { - y++; - } else { - y--; - } - System.out.println(y); - } - - public void ifTrueComputed() { - int y = 6; - int x = URandomKt.nextUInt(); - if(y < 10) { - y++; - } else { - y--; - } - System.out.println(y); - } - - public void ifTrueComputedHard() { - int z = 2; - int y = z; - int x = URandomKt.nextUInt(); - if(y + z < 10) { - y++; - } else { - y--; - } - z = 10; - System.out.println(y); - } - - public void ifFalseComputedHard() { - int z = 5; - int y = z; - int x = URandomKt.nextUInt(); - if(y + z < 10) { - y++; - } else { - y--; - } - z = 3; - System.out.println(y); - } - - public void ifFalseComputed() { - int y = 6; - int x = URandomKt.nextUInt(); - if(y < 0) { - y++; - } else { - y--; - } - System.out.println(y); - } - - public void whileTrueEndless() { - boolean x = true; - while(x) { - System.out.println("Cool loop"); - } - System.out.println("After cool loop"); - } - - public void whileTrue() { - boolean x = true; - while(x) { - System.out.println("Cool loop"); - x = false; - } - System.out.println("After cool loop"); - } - - public void whileFalse() { - while(false) { - System.out.println("Cool loop"); - } - System.out.println("After cool loop"); - } - - public void whileComputedTrue() { - int y = 1; - while(y < 3) { - System.out.println("Cool loop"); - } - System.out.println("After cool loop"); - } - - public void whileComputedFalse() { - int y = 1; - while(y > 3) { - System.out.println("Cool loop"); - } - System.out.println("After cool loop"); - } - - public void whileUnknown() { - int y = URandomKt.nextUInt(); - while(y < 3) { - System.out.println("Cool loop"); - y = URandomKt.nextUInt(); - } - System.out.println("After cool loop"); - } -} \ No newline at end of file diff --git a/cpg-analysis/src/test/resources/query/ComplexDataflow.java b/cpg-analysis/src/test/resources/query/ComplexDataflow.java deleted file mode 100644 index 20805bcfb64..00000000000 --- a/cpg-analysis/src/test/resources/query/ComplexDataflow.java +++ /dev/null @@ -1,17 +0,0 @@ -public class Dataflow { - static Logger logger = Logger.getLogger("DataflowLogger"); - - public int a; - - public static void highlyCriticalOperation(String s) { - System.out.println(s); - } - - - public static void main(String[] args) { - Dataflow sc = new Dataflow(); - sc.a = 5; - Dataflow.highlyCriticalOperation(Integer.toString(sc.a)); - logger.log(Level.INFO, "put " + sc.a + " into highlyCriticalOperation()"); - } -} \ No newline at end of file diff --git a/cpg-analysis/src/test/resources/query/ComplexDataflow2.java b/cpg-analysis/src/test/resources/query/ComplexDataflow2.java deleted file mode 100644 index 9ea961f7f91..00000000000 --- a/cpg-analysis/src/test/resources/query/ComplexDataflow2.java +++ /dev/null @@ -1,17 +0,0 @@ -public class Dataflow { - static Logger logger = Logger.getLogger("DataflowLogger"); - - public int a; - - public static void highlyCriticalOperation(String s) { - System.out.println(s); - } - - - public static void main(String[] args) { - Dataflow sc = new Dataflow(); - sc.a = 5; - logger.log(Level.INFO, "put " + sc.a + " into highlyCriticalOperation()"); - Dataflow.highlyCriticalOperation(Integer.toString(sc.a)); - } -} \ No newline at end of file diff --git a/cpg-analysis/src/test/resources/query/ComplexDataflow3.java b/cpg-analysis/src/test/resources/query/ComplexDataflow3.java deleted file mode 100644 index 6600d5d6544..00000000000 --- a/cpg-analysis/src/test/resources/query/ComplexDataflow3.java +++ /dev/null @@ -1,18 +0,0 @@ -public class Dataflow { - static Logger logger = Logger.getLogger("DataflowLogger"); - - public int a; - - public static void highlyCriticalOperation(String s) { - System.out.println(s); - } - - - public static void main(String[] args) { - Dataflow sc = new Dataflow(); - sc.a = 5; - logger.log(Level.INFO, "put " + sc.a + " into highlyCriticalOperation()"); - sc.a = 3; - Dataflow.highlyCriticalOperation(Integer.toString(sc.a)); - } -} \ No newline at end of file diff --git a/cpg-analysis/src/test/resources/query/Dataflow.java b/cpg-analysis/src/test/resources/query/Dataflow.java deleted file mode 100644 index 4f905fac8e8..00000000000 --- a/cpg-analysis/src/test/resources/query/Dataflow.java +++ /dev/null @@ -1,20 +0,0 @@ -public class Dataflow { - public String toString() { - return "Dataflow: attr=" + attr; - } - - public String test() { return "abcd"; } - - public int print(String s) { - System.out.println(s); - } - - - public static void main(String[] args) { - Dataflow sc = new Dataflow(); - String s = sc.toString(); - sc.print(s); - - sc.print(sc.test()); - } -} \ No newline at end of file diff --git a/cpg-analysis/src/test/resources/query/array.cpp b/cpg-analysis/src/test/resources/query/array.cpp deleted file mode 100644 index 4429239d93d..00000000000 --- a/cpg-analysis/src/test/resources/query/array.cpp +++ /dev/null @@ -1,13 +0,0 @@ -int main() { - char* c = new char[4]; - int a = 4; - int b = a + 1; - - char d = c[b]; -} - -void some_other_function() { - char* c = new char[100]; - - return c[0]; -} \ No newline at end of file diff --git a/cpg-analysis/src/test/resources/query/array2.cpp b/cpg-analysis/src/test/resources/query/array2.cpp deleted file mode 100644 index 940a178f4fa..00000000000 --- a/cpg-analysis/src/test/resources/query/array2.cpp +++ /dev/null @@ -1,8 +0,0 @@ -int main() { - char* c = new char[4]; - int a = 0; - for(int i = 0; i <= 4; i++) { - a = a + c[i]; - } - return a; -} diff --git a/cpg-analysis/src/test/resources/query/array3.cpp b/cpg-analysis/src/test/resources/query/array3.cpp deleted file mode 100644 index df8cae02950..00000000000 --- a/cpg-analysis/src/test/resources/query/array3.cpp +++ /dev/null @@ -1,12 +0,0 @@ -int main() { - char* c; - if(5 > 4) - c = new char[4]; - else - c = new char[5]; - int a = 0; - for(int i = 0; i <= 4; i++) { - a = a + c[i]; - } - return a; -} diff --git a/cpg-analysis/src/test/resources/query/array_correct.cpp b/cpg-analysis/src/test/resources/query/array_correct.cpp deleted file mode 100644 index 735b7324e24..00000000000 --- a/cpg-analysis/src/test/resources/query/array_correct.cpp +++ /dev/null @@ -1,8 +0,0 @@ -int main() { - char* c = new char[4]; - int a = 0; - for(int i = 0; i < 4; i++) { - a = a + c[i]; - } - return a; -} diff --git a/cpg-analysis/src/test/resources/query/assign.cpp b/cpg-analysis/src/test/resources/query/assign.cpp deleted file mode 100644 index 2b4588416ab..00000000000 --- a/cpg-analysis/src/test/resources/query/assign.cpp +++ /dev/null @@ -1,6 +0,0 @@ -int main() { - int a = 4; - // int a, b = 4; // this is broken, a is missing an initializer - - a = 3; -} \ No newline at end of file diff --git a/cpg-analysis/src/test/resources/query/vulnerable.cpp b/cpg-analysis/src/test/resources/query/vulnerable.cpp deleted file mode 100644 index dcaa510dbbc..00000000000 --- a/cpg-analysis/src/test/resources/query/vulnerable.cpp +++ /dev/null @@ -1,18 +0,0 @@ -int main() { - char array[6] = "hello"; - memcpy(array, "Hello world", 11); - printf(array); - free(array); - free(array); - - short a = 2; - if(array == "hello") { - a = 0; - } - - double x = 5/a; - - int b = 2147483648; - b = 2147483648; - long c = -10000; -} \ No newline at end of file diff --git a/cpg-analysis/src/test/resources/value_evaluation/cfexample.cpp b/cpg-analysis/src/test/resources/value_evaluation/cfexample.cpp deleted file mode 100644 index bb9181b48b2..00000000000 --- a/cpg-analysis/src/test/resources/value_evaluation/cfexample.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include - -int main() { - srand(time(NULL)); - int b = 1; - if(rand() < 10) { - b = b+1; - } - println(b); // {1, 2} - - if(rand() > 5) { - b = b-1; - } - println(b); // {0, 1, 2} - - if(rand() > 3) { - b = b*2; - } - println(b); // {0, 1, 2, 4} - - if(rand() < 4) { - b = -b; - } - println(b); // {-4, -2, -1, 0, 1, 2, 4} - - int a = b < 2 ? 3 : 5++; - println(a); // {3, 6} - return 0; -} - -int loop() { - int array[6]; - for(int i = 0; i < 6; i++) { - array[i] = i; - } - return 0; -} \ No newline at end of file diff --git a/cpg-analysis/src/test/resources/value_evaluation/complex.java b/cpg-analysis/src/test/resources/value_evaluation/complex.java deleted file mode 100644 index 49955f77296..00000000000 --- a/cpg-analysis/src/test/resources/value_evaluation/complex.java +++ /dev/null @@ -1,21 +0,0 @@ -public class MainClass { - public static void main(String[] args) { - int i = 3; - - String s; - - if (i < 2) { - s = "small"; - } else { - s = "big"; - } - - s += "!"; - s = s + "?"; - - i++; - - System.out.println(s); - System.out.println(i); - } -} \ No newline at end of file diff --git a/cpg-analysis/src/test/resources/value_evaluation/example.cpp b/cpg-analysis/src/test/resources/value_evaluation/example.cpp deleted file mode 100644 index fd4df33a380..00000000000 --- a/cpg-analysis/src/test/resources/value_evaluation/example.cpp +++ /dev/null @@ -1,24 +0,0 @@ -int main() { - int b = 1 + 1; - println(b); - - int a = 1; - a = 2; - println(a); - - int c = 5-2; - float d = 8/3; - float e = 7.0/2; - int f = 2*5; - int g = -c; - - println("Hello " + "world"); - - bool h = 5 < 3; - bool i = 3 > 3; - bool j = 3 >= 3.2; - bool k = 3.1 <= 3; - bool l = 3L >= ((float) 3.1); - bool m = ((char) 3) >= 3.1; - bool n = 3 == 3.1; -} \ No newline at end of file diff --git a/cpg-analysis/src/test/resources/value_evaluation/size.java b/cpg-analysis/src/test/resources/value_evaluation/size.java deleted file mode 100644 index 5bde3a1eddb..00000000000 --- a/cpg-analysis/src/test/resources/value_evaluation/size.java +++ /dev/null @@ -1,13 +0,0 @@ -public class MainClass { - public static void main(String[] args) { - int[] array = new int[3]; - for(int i = 0; i < array.length; i++) { - array[i] = i; - } - System.out.println(array[1]); - - String str = "abcde"; - System.out.println(str); - return 0; - } - } \ No newline at end of file diff --git a/cpg-console/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/AnalysisTest.kt b/cpg-console/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/AnalysisTest.kt index 8a92a1993ba..c63cb9d1478 100644 --- a/cpg-console/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/AnalysisTest.kt +++ b/cpg-console/src/test/kotlin/de/fraunhofer/aisec/cpg/analysis/AnalysisTest.kt @@ -28,6 +28,7 @@ package de.fraunhofer.aisec.cpg.analysis import de.fraunhofer.aisec.cpg.TranslationConfiguration import de.fraunhofer.aisec.cpg.TranslationManager import de.fraunhofer.aisec.cpg.console.fancyCode +import de.fraunhofer.aisec.cpg.frontends.cxx.CPPLanguage import de.fraunhofer.aisec.cpg.frontends.java.JavaLanguage import de.fraunhofer.aisec.cpg.graph.body import de.fraunhofer.aisec.cpg.graph.byNameOrNull @@ -45,7 +46,7 @@ class AnalysisTest { TranslationConfiguration.builder() .sourceLocations(File("src/test/resources/array.cpp")) .defaultPasses() - .defaultLanguages() + .registerLanguage() .build() val analyzer = TranslationManager.builder().config(config).build() @@ -60,7 +61,7 @@ class AnalysisTest { TranslationConfiguration.builder() .sourceLocations(File("src/test/resources/Array.java")) .defaultPasses() - .defaultLanguages() + .registerLanguage() .build() val analyzer = TranslationManager.builder().config(config).build() @@ -75,8 +76,7 @@ class AnalysisTest { TranslationConfiguration.builder() .sourceLocations(File("src/test/resources/Array.java")) .defaultPasses() - .defaultLanguages() - .registerLanguage(JavaLanguage()) + .registerLanguage() .build() val analyzer = TranslationManager.builder().config(config).build() diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/TranslationConfiguration.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/TranslationConfiguration.kt index f5749c85de9..71bbf7145ce 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/TranslationConfiguration.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/TranslationConfiguration.kt @@ -509,19 +509,6 @@ private constructor( } } - /** Register all default languages. */ - @Deprecated( - message = - "We moved all languages out of the core package and therefore you should register individual languages instead. For compatibility reasons we do a dynamic lookup to Java and C/C++ languages here but this function will be removed in the future." - ) - fun defaultLanguages(): Builder { - optionalLanguage("de.fraunhofer.aisec.cpg.frontends.cxx.CLanguage") - optionalLanguage("de.fraunhofer.aisec.cpg.frontends.cxx.CPPLanguage") - optionalLanguage("de.fraunhofer.aisec.cpg.frontends.java.JavaLanguage") - - return this - } - /** * Safely register an additional [Language] from a class name. If the [Language] given by * the class name could not be loaded or instantiated, no [Language] is registered and no diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/builder/Fluent.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/builder/Fluent.kt index ed4e214fada..446e090b9d7 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/builder/Fluent.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/builder/Fluent.kt @@ -138,6 +138,17 @@ fun LanguageFrontend<*, *>.field( return node } +/** + * Creates a new [IncludeDeclaration] and adds it to the surrounding [TranslationUnitDeclaration]. + */ +context(TranslationUnitDeclaration) + +fun LanguageFrontend<*, *>.import(name: CharSequence): IncludeDeclaration { + val node = newIncludeDeclaration(name) + (this@TranslationUnitDeclaration).addDeclaration(node) + return node +} + /** * Creates a new [FunctionDeclaration] in the Fluent Node DSL with the given [name] and optional * [returnType]. The [init] block can be used to create further sub-nodes as well as configuring the @@ -239,6 +250,22 @@ fun LanguageFrontend<*, *>.body(needsScope: Boolean = true, init: Block.() -> Un return node } +/** + * Creates a new [Block] in the Fluent Node DSL and sets it to the [FunctionDeclaration.body] of the + * nearest enclosing [FunctionDeclaration]. The [init] block can be used to create further sub-nodes + * as well as configuring the created node itself. + */ +context(StatementHolder) + +fun LanguageFrontend<*, *>.block(needsScope: Boolean = true, init: Block.() -> Unit): Block { + val node = newBlock() + + scopeIfNecessary(needsScope, node, init) + (this@StatementHolder).addStatement(node) + + return node +} + /** * Creates a new [ParameterDeclaration] in the Fluent Node DSL and adds it to the * [FunctionDeclaration.parameters] of the nearest enclosing [FunctionDeclaration]. The [init] block @@ -315,6 +342,23 @@ fun LanguageFrontend<*, *>.declare(init: DeclarationStatement.() -> Unit): Decla return node } +/** + * Creates a new [DeclarationStatement] in the Fluent Node DSL. The [init] block can be used to + * create further sub-nodes as well as configuring the created node itself. + */ +fun LanguageFrontend<*, *>.declareVar( + name: String, + type: Type, + init: VariableDeclaration.() -> Unit +): DeclarationStatement { + val node = (this@LanguageFrontend).newDeclarationStatement() + val variableDecl = newVariableDeclaration(name, type) + init(variableDecl) + node.singleDeclaration = variableDecl + + return node +} + /** * Creates a new [VariableDeclaration] in the Fluent Node DSL and adds it to the * [DeclarationStatement.declarations] of the nearest enclosing [DeclarationStatement]. The [init] @@ -396,7 +440,7 @@ fun LanguageFrontend<*, *>.memberCall( localName: CharSequence, base: Expression, isStatic: Boolean = false, - init: (CallExpression.() -> Unit)? = null + init: (MemberCallExpression.() -> Unit)? = null ): MemberCallExpression { // Try to parse the name val node = newMemberCallExpression(newMemberExpression(localName, base), isStatic) @@ -525,6 +569,37 @@ fun LanguageFrontend<*, *>.forEachStmt(init: ForEachStatement.() -> Unit): ForEa return node } +/** + * Creates a new [ForStatement] in the Fluent Node DSL and adds it to the + * [StatementHolder.statements] of the nearest enclosing [StatementHolder]. The [init] block can be + * used to create further sub-nodes as well as configuring the created node itself. + */ +context(StatementHolder) + +fun LanguageFrontend<*, *>.forStmt( + initializer: DeclarationStatement, + condition: Expression, + iteration: Statement, + init: Block.() -> Unit +): ForStatement { + val node = newForStatement() + node.initializerStatement = initializer + if (initializer.isSingleDeclaration()) { + + scopeManager.addDeclaration(initializer.singleDeclaration, false) + } + node.condition = condition + node.iterationStatement = iteration + + val body = newBlock() + init(body) + node.statement = body + + (this@StatementHolder) += node + + return node +} + /** * Creates a new [SwitchStatement] in the Fluent Node DSL and adds it to the * [StatementHolder.statements] of the nearest enclosing [StatementHolder]. The [init] block can be @@ -565,6 +640,25 @@ fun LanguageFrontend<*, *>.whileStmt( return node } +/** + * Creates a new [DoStatement] in the Fluent Node DSL and adds it to the + * [StatementHolder.statements] of the nearest enclosing [StatementHolder]. The [init] block can be + * used to create further sub-nodes as well as configuring the created node itself. + */ +context(StatementHolder) + +fun LanguageFrontend<*, *>.doStmt( + needsScope: Boolean = true, + init: DoStatement.() -> Unit +): DoStatement { + val node = newDoStatement() + scopeIfNecessary(needsScope, node, init) + + (this@StatementHolder) += node + + return node +} + // TODO: Combine the condition functions /** @@ -574,7 +668,7 @@ fun LanguageFrontend<*, *>.whileStmt( */ context(IfStatement) -fun LanguageFrontend<*, *>.condition(init: IfStatement.() -> BinaryOperator): BinaryOperator { +fun LanguageFrontend<*, *>.condition(init: IfStatement.() -> Expression): Expression { return init(this@IfStatement) } @@ -585,16 +679,29 @@ fun LanguageFrontend<*, *>.condition(init: IfStatement.() -> BinaryOperator): Bi */ context(WhileStatement) -fun LanguageFrontend<*, *>.whileCondition( - init: WhileStatement.() -> BinaryOperator -): BinaryOperator { +fun LanguageFrontend<*, *>.whileCondition(init: WhileStatement.() -> Expression): Expression { return init(this@WhileStatement) } /** + * <<<<<<< HEAD Configures the [DoStatement.condition] in the Fluent Node DSL of the nearest + * enclosing [DoStatement]. The [init] block can be used to create further sub-nodes as well as + * configuring the created node itself. + */ +context(DoStatement) + +fun LanguageFrontend<*, *>.whileCondition(init: DoStatement.() -> Expression): Expression { + return init(this@DoStatement) +} + +/** + * Creates a new [CompoundStatement] in the Fluent Node DSL and sets it to the + * [IfStatement.thenStatement] of the nearest enclosing [IfStatement]. The [init] block can be used + * to create further sub-nodes as well as configuring the created node itself. + * ======= * Creates a new [Block] in the Fluent Node DSL and sets it to the [IfStatement.thenStatement] of * the nearest enclosing [IfStatement]. The [init] block can be used to create further sub-nodes as - * well as configuring the created node itself. + * well as configuring the created node itself. >>>>>>> main */ context(IfStatement) @@ -639,6 +746,22 @@ fun LanguageFrontend<*, *>.loopBody(init: Block.() -> Unit): Block { return node } + +/** + * Creates a new [CompoundStatement] in the Fluent Node DSL and sets it to the + * [DoStatement.statement] of the nearest enclosing [DoStatement]. The [init] block can be used to + * create further sub-nodes as well as configuring the created node itself. + */ +context(DoStatement) + +fun LanguageFrontend<*, *>.loopBody(init: Block.() -> Unit): Block { + val node = newBlock() + init(node) + statement = node + + return node +} + /** * Creates a new [Block] in the Fluent Node DSL and sets it to the [WhileStatement.statement] of the * nearest enclosing [WhileStatement]. The [init] block can be used to create further sub-nodes as @@ -655,9 +778,9 @@ fun LanguageFrontend<*, *>.loopBody(init: Block.() -> Unit): Block { } /** - * Creates a new [BlockStatement] in the Fluent Node DSL and sets it to the - * [SwitchStatement.statement] of the nearest enclosing [SwitchStatement]. The [init] block can be - * used to create further sub-nodes as well as configuring the created node itself. + * Creates a new [Block] in the Fluent Node DSL and sets it to the [SwitchStatement.statement] of + * the nearest enclosing [SwitchStatement]. The [init] block can be used to create further sub-nodes + * as well as configuring the created node itself. */ context(SwitchStatement) @@ -834,6 +957,7 @@ context(Holder) fun LanguageFrontend<*, *>.ref( name: CharSequence, type: Type = unknownType(), + makeMagic: Boolean = true, init: (Reference.() -> Unit)? = null ): Reference { val node = newReference(name) @@ -843,10 +967,12 @@ fun LanguageFrontend<*, *>.ref( init(node) } - // Only add this to an argument holder if the nearest holder is an argument holder - val holder = this@Holder - if (holder is ArgumentHolder) { - holder += node + if (makeMagic) { + // Only add this to an argument holder if the nearest holder is an argument holder + val holder = this@Holder + if (holder is ArgumentHolder) { + holder += node + } } return node @@ -911,6 +1037,48 @@ operator fun Expression.times(rhs: Expression): BinaryOperator { return node } +/** + * Creates a new [UnaryOperator] with a `-` [UnaryOperator.operatorCode] in the Fluent Node DSL and + * invokes [ArgumentHolder.addArgument] of the nearest enclosing [ArgumentHolder]. + */ +context(LanguageFrontend<*, *>, ArgumentHolder) + +operator fun Expression.unaryMinus(): UnaryOperator { + val node = (this@LanguageFrontend).newUnaryOperator("-", false, false) + node.input = this + + (this@ArgumentHolder) += node + + // We need to do a little trick here. Because of the evaluation order, lhs and rhs might also + // been added to the argument holders arguments (and we do not want that). However, we cannot + // prevent it, so we need to remove them again + (this@ArgumentHolder) -= node.input + + return node +} + +/** + * Creates a new [BinaryOperator] with a `/` [BinaryOperator.operatorCode] in the Fluent Node DSL + * and invokes [ArgumentHolder.addArgument] of the nearest enclosing [ArgumentHolder]. + */ +context(LanguageFrontend<*, *>, ArgumentHolder) + +operator fun Expression.div(rhs: Expression): BinaryOperator { + val node = (this@LanguageFrontend).newBinaryOperator("/") + node.lhs = this + node.rhs = rhs + + (this@ArgumentHolder) += node + + // We need to do a little trick here. Because of the evaluation order, lhs and rhs might also + // been added to the argument holders arguments (and we do not want that). However, we cannot + // prevent it, so we need to remove them again + (this@ArgumentHolder) -= node.lhs + (this@ArgumentHolder) -= node.rhs + + return node +} + /** * Creates a new [BinaryOperator] with a `+` [BinaryOperator.operatorCode] in the Fluent Node DSL * and invokes [ArgumentHolder.addArgument] of the nearest enclosing [ArgumentHolder]. @@ -1032,6 +1200,19 @@ operator fun Expression.inc(): UnaryOperator { return node } +/** + * Creates a new [UnaryOperator] with a `++` [UnaryOperator.operatorCode] in the Fluent Node DSL and + * invokes [ArgumentHolder.addArgument] of the nearest enclosing [ArgumentHolder]. + */ +context(LanguageFrontend<*, *>) + +fun Expression.incNoContext(): UnaryOperator { + val node = (this@LanguageFrontend).newUnaryOperator("++", true, false) + node.input = this + + return node +} + /** * Creates a new [BinaryOperator] with a `==` [BinaryOperator.operatorCode] in the Fluent Node DSL * and invokes [ArgumentHolder.addArgument] of the nearest enclosing [ArgumentHolder]. @@ -1065,21 +1246,75 @@ infix fun Expression.gt(rhs: Expression): BinaryOperator { } /** - * Creates a new [BinaryOperator] with a `<` [BinaryOperator.operatorCode] in the Fluent Node DSL + * Creates a new [BinaryOperator] with a `>=` [BinaryOperator.operatorCode] in the Fluent Node DSL * and invokes [ArgumentHolder.addArgument] of the nearest enclosing [ArgumentHolder]. */ context(LanguageFrontend<*, *>, ArgumentHolder) +infix fun Expression.ge(rhs: Expression): BinaryOperator { + val node = (this@LanguageFrontend).newBinaryOperator(">=") + node.lhs = this + node.rhs = rhs + + (this@ArgumentHolder) += node + + return node +} + +/** + * Creates a new [BinaryOperator] with a `<` [BinaryOperator.operatorCode] in the Fluent Node DSL + * and invokes [ArgumentHolder.addArgument] of the nearest enclosing [ArgumentHolder]. + */ +context(LanguageFrontend<*, *>, Holder) + +infix fun Expression.lt(rhs: Expression): BinaryOperator { + val node = (this@LanguageFrontend).newBinaryOperator("<") + node.lhs = this + node.rhs = rhs + + if (this@Holder is ArgumentHolder) { + this@Holder += node + } + + return node +} + +context(LanguageFrontend<*, *>) + infix fun Expression.lt(rhs: Expression): BinaryOperator { val node = (this@LanguageFrontend).newBinaryOperator("<") node.lhs = this node.rhs = rhs + return node +} + +/** + * Creates a new [BinaryOperator] with a `<=` [BinaryOperator.operatorCode] in the Fluent Node DSL + * and invokes [ArgumentHolder.addArgument] of the nearest enclosing [ArgumentHolder]. + */ +context(LanguageFrontend<*, *>, ArgumentHolder) + +infix fun Expression.le(rhs: Expression): BinaryOperator { + val node = (this@LanguageFrontend).newBinaryOperator("<=") + node.lhs = this + node.rhs = rhs + (this@ArgumentHolder) += node return node } +context(LanguageFrontend<*, *>) + +infix fun Expression.le(rhs: Expression): BinaryOperator { + val node = (this@LanguageFrontend).newBinaryOperator("<=") + node.lhs = this + node.rhs = rhs + + return node +} + /** * Creates a new [ConditionalExpression] with a `=` [BinaryOperator.operatorCode] in the Fluent Node * DSL and invokes [StatementHolder.addStatement] of the nearest enclosing [StatementHolder]. @@ -1136,6 +1371,22 @@ infix fun Expression.assign(rhs: Expression): AssignExpression { return node } +/** + * Creates a new [AssignExpression] with a `+=` [AssignExpression.operatorCode] in the Fluent Node + * DSL and invokes [StatementHolder.addStatement] of the nearest enclosing [StatementHolder]. + */ +context(LanguageFrontend<*, *>, Holder) + +infix fun Expression.assignPlus(rhs: Expression): AssignExpression { + val node = (this@LanguageFrontend).newAssignExpression("+=", listOf(this), listOf(rhs)) + + if (this@Holder is StatementHolder) { + this@Holder += node + } + + return node +} + /** * Creates a new [AssignExpression] with a `=` [AssignExpression.operatorCode] in the Fluent Node * DSL and invokes [StatementHolder.addStatement] of the nearest enclosing [StatementHolder]. @@ -1168,6 +1419,9 @@ infix fun Expression.assignAsExpr(rhs: AssignExpression.() -> Unit): AssignExpre fun LanguageFrontend<*, *>.t(name: CharSequence, generics: List = listOf()) = objectType(name, generics) +/** Creates a new [Type] with the given [name] in the Fluent Node DSL. */ +fun LanguageFrontend<*, *>.void() = incompleteType() + /** * Internally used to enter a new scope if [needsScope] is true before invoking [init] and leaving * it afterwards. diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/DoStatement.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/DoStatement.kt index 4ec062bea78..4c526d50d6d 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/DoStatement.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/DoStatement.kt @@ -26,12 +26,13 @@ package de.fraunhofer.aisec.cpg.graph.statements import de.fraunhofer.aisec.cpg.graph.AST +import de.fraunhofer.aisec.cpg.graph.ArgumentHolder import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression import java.util.* import org.apache.commons.lang3.builder.ToStringBuilder /** Represents a conditional loop statement of the form: `do{...}while(...)`. */ -class DoStatement : Statement() { +class DoStatement : Statement(), ArgumentHolder { /** * The loop condition that is evaluated after the loop statement and may trigger reevaluation. */ @@ -50,6 +51,18 @@ class DoStatement : Statement() { .append("statement", statement) .toString() + override fun addArgument(expression: Expression) { + this.condition = expression + } + + override fun replaceArgument(old: Expression, new: Expression): Boolean { + if (condition == old) { + this.condition = new + return true + } + return false + } + override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is DoStatement) return false diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/ForStatement.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/ForStatement.kt index 24a3a1af345..7bc4dff12e5 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/ForStatement.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/ForStatement.kt @@ -25,9 +25,7 @@ */ package de.fraunhofer.aisec.cpg.graph.statements -import de.fraunhofer.aisec.cpg.graph.AST -import de.fraunhofer.aisec.cpg.graph.BranchingNode -import de.fraunhofer.aisec.cpg.graph.Node +import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.declarations.Declaration import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression import java.util.* diff --git a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/helpers/SubgraphWalkerTest.kt b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/helpers/SubgraphWalkerTest.kt index cb8f7c3b37a..11d0dc5ad8a 100644 --- a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/helpers/SubgraphWalkerTest.kt +++ b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/helpers/SubgraphWalkerTest.kt @@ -64,7 +64,6 @@ internal class SubgraphWalkerTest : BaseTest() { .debugParser(true) .failOnError(true) .useParallelFrontends(true) - .defaultLanguages() .registerLanguage(TestLanguage(".")) .defaultPasses() .build() diff --git a/cpg-core/src/testFixtures/kotlin/de/fraunhofer/aisec/cpg/TestUtils.kt b/cpg-core/src/testFixtures/kotlin/de/fraunhofer/aisec/cpg/TestUtils.kt index 1382a03c012..9e90709b905 100644 --- a/cpg-core/src/testFixtures/kotlin/de/fraunhofer/aisec/cpg/TestUtils.kt +++ b/cpg-core/src/testFixtures/kotlin/de/fraunhofer/aisec/cpg/TestUtils.kt @@ -132,7 +132,6 @@ object TestUtils { .debugParser(true) .failOnError(true) .useParallelFrontends(true) - .defaultLanguages() if (usePasses) { builder.defaultPasses() } diff --git a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/PerformanceRegressionTest.kt b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/PerformanceRegressionTest.kt index c8b4fcb8ae2..65a78bf6eae 100644 --- a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/PerformanceRegressionTest.kt +++ b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/PerformanceRegressionTest.kt @@ -27,6 +27,7 @@ package de.fraunhofer.aisec.cpg import de.fraunhofer.aisec.cpg.TestUtils.analyzeAndGetFirstTU import de.fraunhofer.aisec.cpg.frontends.TestLanguageFrontend +import de.fraunhofer.aisec.cpg.frontends.cxx.CLanguage import de.fraunhofer.aisec.cpg.frontends.cxx.CPPLanguage import de.fraunhofer.aisec.cpg.frontends.cxx.CXXLanguageFrontend import de.fraunhofer.aisec.cpg.graph.Node @@ -73,6 +74,7 @@ class PerformanceRegressionTest { // enough for those special moments where for some reasons the GitHub runners // are slowing down (maybe because of some hidden quota). it.useParallelFrontends(false) + it.registerLanguage() } assertNotNull(tu) } diff --git a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/EOGTest.kt b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/EOGTest.kt index 1eb0129333f..d5202124e5d 100644 --- a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/EOGTest.kt +++ b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/EOGTest.kt @@ -30,6 +30,7 @@ import de.fraunhofer.aisec.cpg.TestUtils.analyzeAndGetFirstTU import de.fraunhofer.aisec.cpg.TestUtils.findByUniqueName import de.fraunhofer.aisec.cpg.TranslationConfiguration import de.fraunhofer.aisec.cpg.TranslationManager +import de.fraunhofer.aisec.cpg.frontends.cxx.CPPLanguage import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.SearchModifier.UNIQUE import de.fraunhofer.aisec.cpg.graph.allChildren @@ -41,7 +42,6 @@ import de.fraunhofer.aisec.cpg.graph.statements.expressions.* import de.fraunhofer.aisec.cpg.helpers.SubgraphWalker import de.fraunhofer.aisec.cpg.helpers.Util import de.fraunhofer.aisec.cpg.helpers.Util.Connect -import de.fraunhofer.aisec.cpg.passes.EvaluationOrderGraphPass import de.fraunhofer.aisec.cpg.processing.IVisitor import de.fraunhofer.aisec.cpg.processing.strategy.Strategy import de.fraunhofer.aisec.cpg.sarif.PhysicalLocation @@ -915,7 +915,7 @@ internal class EOGTest : BaseTest() { TranslationConfiguration.builder() .sourceLocations(File("src/test/resources/cxx/lambdas.cpp")) .defaultPasses() - .defaultLanguages() + .registerLanguage() .build() val analyzer = TranslationManager.builder().config(config).build() val result = analyzer.analyze().get() @@ -979,15 +979,6 @@ internal class EOGTest : BaseTest() { assertEquals(0, (binOpRight.nextEOG.firstOrNull() as? Block)?.nextEOG?.size) } - @Test - @Throws(Exception::class) - @Ignore - fun testEOGInvariant() { - val file = File("src/main/java/de/fraunhofer/aisec/cpg/passes/CallResolver.java") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) - assertTrue(EvaluationOrderGraphPass.checkEOGInvariant(tu)) - } - /** * Translates the given file into CPG and returns the graph. Extracted to reduce code duplicates * @@ -998,7 +989,10 @@ internal class EOGTest : BaseTest() { private fun translateToNodes(path: String): List { val toTranslate = File(path) val topLevel = toTranslate.parentFile.toPath() - val tu = analyzeAndGetFirstTU(listOf(toTranslate), topLevel, true) + val tu = + analyzeAndGetFirstTU(listOf(toTranslate), topLevel, true) { + it.registerLanguage() + } var nodes = SubgraphWalker.flattenAST(tu) // TODO: until explicitly added Return Statements are either removed again or code and // region set properly diff --git a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/calls/ConstructorsTest.kt b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/calls/ConstructorsTest.kt index fabfa500eb0..4e2d175d98f 100644 --- a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/calls/ConstructorsTest.kt +++ b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/calls/ConstructorsTest.kt @@ -30,6 +30,7 @@ import de.fraunhofer.aisec.cpg.TestUtils import de.fraunhofer.aisec.cpg.TestUtils.findByUniqueName import de.fraunhofer.aisec.cpg.TestUtils.findByUniquePredicate import de.fraunhofer.aisec.cpg.assertLocalName +import de.fraunhofer.aisec.cpg.frontends.cxx.CPPLanguage import de.fraunhofer.aisec.cpg.graph.allChildren import de.fraunhofer.aisec.cpg.graph.declarations.ConstructorDeclaration import de.fraunhofer.aisec.cpg.graph.literals @@ -44,7 +45,7 @@ internal class ConstructorsTest : BaseTest() { @Test @Throws(Exception::class) fun testCPP() { - val result = TestUtils.analyze("cpp", topLevel, true) + val result = TestUtils.analyze("cpp", topLevel, true) { it.registerLanguage() } val constructors = result.allChildren() val noArg = findByUniquePredicate(constructors) { @@ -144,7 +145,9 @@ internal class ConstructorsTest : BaseTest() { ), topLevel, true - ) + ) { + it.registerLanguage() + } val constructors = result.allChildren() val variables = result.variables val twoDefaultArg = @@ -199,7 +202,9 @@ internal class ConstructorsTest : BaseTest() { ), topLevel, true - ) + ) { + it.registerLanguage() + } val constructors = result.allChildren() val variables = result.variables val singleDefaultArg = @@ -244,7 +249,9 @@ internal class ConstructorsTest : BaseTest() { ), topLevel, true - ) + ) { + it.registerLanguage() + } val constructors = result.allChildren() val variables = result.variables val implicitConstructor = diff --git a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/calls/FunctionPointerTest.kt b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/calls/FunctionPointerTest.kt index a911cf74a57..75ed6b310f1 100644 --- a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/calls/FunctionPointerTest.kt +++ b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/calls/FunctionPointerTest.kt @@ -28,7 +28,10 @@ package de.fraunhofer.aisec.cpg.enhancements.calls import de.fraunhofer.aisec.cpg.BaseTest import de.fraunhofer.aisec.cpg.TestUtils import de.fraunhofer.aisec.cpg.TestUtils.findByUniquePredicate +import de.fraunhofer.aisec.cpg.TranslationConfiguration import de.fraunhofer.aisec.cpg.TranslationResult +import de.fraunhofer.aisec.cpg.frontends.cxx.CLanguage +import de.fraunhofer.aisec.cpg.frontends.cxx.CPPLanguage import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.VariableDeclaration @@ -43,15 +46,18 @@ import kotlin.test.* internal class FunctionPointerTest : BaseTest() { @Throws(Exception::class) - private fun analyze(language: String): TranslationResult { + private fun analyze( + language: String, + configModifier: Consumer? = null + ): TranslationResult { val topLevel = Path.of("src", "test", "resources", "functionPointers") - return TestUtils.analyze(language, topLevel, true) + return TestUtils.analyze(language, topLevel, true, configModifier) } @Throws(Exception::class) - fun test(language: String) { - val result = analyze(language) + fun test(language: String, configModifier: Consumer? = null) { + val result = analyze(language, configModifier) val functions = result.functions val main = functions["main", SearchModifier.UNIQUE] val calls = main.calls @@ -183,12 +189,12 @@ internal class FunctionPointerTest : BaseTest() { @Test @Throws(Exception::class) fun testC() { - test("c") + test("c") { it.registerLanguage() } } @Test @Throws(Exception::class) fun testCPP() { - test("cpp") + test("cpp") { it.registerLanguage() } } } diff --git a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/templates/ClassTemplateTest.kt b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/templates/ClassTemplateTest.kt index a2a2d791c61..6403d734aff 100644 --- a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/templates/ClassTemplateTest.kt +++ b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/templates/ClassTemplateTest.kt @@ -30,6 +30,7 @@ import de.fraunhofer.aisec.cpg.TestUtils.analyze import de.fraunhofer.aisec.cpg.TestUtils.findByUniqueName import de.fraunhofer.aisec.cpg.TestUtils.findByUniquePredicate import de.fraunhofer.aisec.cpg.assertLocalName +import de.fraunhofer.aisec.cpg.frontends.cxx.CPPLanguage import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.declarations.* import de.fraunhofer.aisec.cpg.graph.edge.Properties @@ -143,7 +144,9 @@ internal class ClassTemplateTest : BaseTest() { @Throws(Exception::class) fun testClassTemplateStructure() { val result = - analyze(listOf(Path.of(topLevel.toString(), "pair.cpp").toFile()), topLevel, true) + analyze(listOf(Path.of(topLevel.toString(), "pair.cpp").toFile()), topLevel, true) { + it.registerLanguage() + } val recordTemplateDeclarations = result.allChildren() val template = findByUniqueName( @@ -197,7 +200,9 @@ internal class ClassTemplateTest : BaseTest() { fun testClassTemplateWithValueParameter() { // Test pair2.cpp: Add Value Parameter to Template Instantiation val result = - analyze(listOf(Path.of(topLevel.toString(), "pair2.cpp").toFile()), topLevel, true) + analyze(listOf(Path.of(topLevel.toString(), "pair2.cpp").toFile()), topLevel, true) { + it.registerLanguage() + } val recordTemplateDeclarations = result.allChildren() val template = findByUniqueName( @@ -293,7 +298,9 @@ internal class ClassTemplateTest : BaseTest() { fun testStructTemplateWithSameDefaultType() { // Test pair3.cpp: Template a struct instead of a class and use a Type1 as default of Type2 val result = - analyze(listOf(Path.of(topLevel.toString(), "pair3.cpp").toFile()), topLevel, true) + analyze(listOf(Path.of(topLevel.toString(), "pair3.cpp").toFile()), topLevel, true) { + it.registerLanguage() + } val template = findByUniqueName( result.allChildren(), @@ -350,7 +357,9 @@ internal class ClassTemplateTest : BaseTest() { fun testTemplateOverrindingDefaults() { // Test pair3-1.cpp: Override defaults of template val result = - analyze(listOf(Path.of(topLevel.toString(), "pair3-1.cpp").toFile()), topLevel, true) + analyze(listOf(Path.of(topLevel.toString(), "pair3-1.cpp").toFile()), topLevel, true) { + it.registerLanguage() + } val template = findByUniqueName( result.allChildren(), @@ -399,7 +408,9 @@ internal class ClassTemplateTest : BaseTest() { fun testTemplateRecursiveDefaults() { // Test pair3-2.cpp: Use recursive template parameters using defaults val result = - analyze(listOf(Path.of(topLevel.toString(), "pair3-2.cpp").toFile()), topLevel, true) + analyze(listOf(Path.of(topLevel.toString(), "pair3-2.cpp").toFile()), topLevel, true) { + it.registerLanguage() + } val template = findByUniqueName( result.allChildren(), @@ -478,7 +489,9 @@ internal class ClassTemplateTest : BaseTest() { fun testReferenceInTemplates() { // Test array.cpp: checks usage of referencetype of parameterized type (T[]) val result = - analyze(listOf(Path.of(topLevel.toString(), "array.cpp").toFile()), topLevel, true) + analyze(listOf(Path.of(topLevel.toString(), "array.cpp").toFile()), topLevel, true) { + it.registerLanguage() + } val template = findByUniqueName( result.allChildren(), @@ -531,7 +544,9 @@ internal class ClassTemplateTest : BaseTest() { fun testTemplateInstantiationWithNew() { // Test array2.cpp: Test template usage with new keyword val result = - analyze(listOf(Path.of(topLevel.toString(), "array2.cpp").toFile()), topLevel, true) + analyze(listOf(Path.of(topLevel.toString(), "array2.cpp").toFile()), topLevel, true) { + it.registerLanguage() + } val template = findByUniqueName( result.allChildren(), diff --git a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/templates/FunctionTemplateTest.kt b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/templates/FunctionTemplateTest.kt index 62b9ce738c8..aff504c16f8 100644 --- a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/templates/FunctionTemplateTest.kt +++ b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/templates/FunctionTemplateTest.kt @@ -51,7 +51,9 @@ internal class FunctionTemplateTest : BaseTest() { listOf(Path.of(topLevel.toString(), "functionTemplate.cpp").toFile()), topLevel, true - ) + ) { + it.registerLanguage() + } val x = result.variables["x"] assertNotNull(x) assertIs(x.type) @@ -93,7 +95,9 @@ internal class FunctionTemplateTest : BaseTest() { listOf(Path.of(topLevel.toString(), "functionTemplate.cpp").toFile()), topLevel, true - ) + ) { + it.registerLanguage() + } // This test checks the structure of FunctionTemplates without the TemplateExpansionPass val functionTemplateDecl = result.allChildren()[0] @@ -161,7 +165,9 @@ internal class FunctionTemplateTest : BaseTest() { listOf(Path.of(topLevel.toString(), "functionTemplateInvocation1.cpp").toFile()), topLevel, true - ) + ) { + it.registerLanguage() + } val doubleFixedMultiply = findByUniquePredicate(result.functions) { f: FunctionDeclaration -> f.name.localName == "fixed_multiply" && @@ -189,7 +195,9 @@ internal class FunctionTemplateTest : BaseTest() { listOf(Path.of(topLevel.toString(), "functionTemplateInvocation2.cpp").toFile()), topLevel, true - ) + ) { + it.registerLanguage() + } val templateDeclaration = findByUniquePredicate(result.allChildren()) { t: FunctionTemplateDeclaration -> @@ -233,7 +241,9 @@ internal class FunctionTemplateTest : BaseTest() { listOf(Path.of(topLevel.toString(), "functionTemplateInvocation3.cpp").toFile()), topLevel, true - ) + ) { + it.registerLanguage() + } val templateDeclaration = findByUniquePredicate(result.allChildren()) { t: FunctionTemplateDeclaration -> @@ -273,7 +283,9 @@ internal class FunctionTemplateTest : BaseTest() { listOf(Path.of(topLevel.toString(), "functionTemplateInvocation4.cpp").toFile()), topLevel, true - ) + ) { + it.registerLanguage() + } val templateDeclaration = findByUniquePredicate(result.allChildren()) { it.name.localName == "fixed_multiply" @@ -320,7 +332,9 @@ internal class FunctionTemplateTest : BaseTest() { listOf(Path.of(topLevel.toString(), "functionTemplateInvocation5.cpp").toFile()), topLevel, true - ) + ) { + it.registerLanguage() + } val templateDeclaration = findByUniquePredicate(result.allChildren()) { t: FunctionTemplateDeclaration -> @@ -364,7 +378,9 @@ internal class FunctionTemplateTest : BaseTest() { listOf(Path.of(topLevel.toString(), "functionTemplateInvocation6.cpp").toFile()), topLevel, true - ) + ) { + it.registerLanguage() + } val templateDeclaration = findByUniquePredicate(result.allChildren()) { t: FunctionTemplateDeclaration -> @@ -418,7 +434,9 @@ internal class FunctionTemplateTest : BaseTest() { listOf(Path.of(topLevel.toString(), "functionTemplateInvocation7.cpp").toFile()), topLevel, true - ) + ) { + it.registerLanguage() + } val templateDeclaration = findByUniquePredicate(result.allChildren()) { t: FunctionTemplateDeclaration -> @@ -470,7 +488,9 @@ internal class FunctionTemplateTest : BaseTest() { listOf(Path.of(topLevel.toString(), "functionTemplateMethod.cpp").toFile()), topLevel, true - ) + ) { + it.registerLanguage() + } val recordDeclaration = findByUniquePredicate(result.records) { c: RecordDeclaration -> c.name.localName == "MyClass" @@ -524,7 +544,9 @@ internal class FunctionTemplateTest : BaseTest() { listOf(Path.of(topLevel.toString(), "functionTemplateInvocation8.cpp").toFile()), topLevel, true - ) + ) { + it.registerLanguage() + } // Check inferred for first fixed_division call var templateDeclaration = diff --git a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/types/TypeTests.kt b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/types/TypeTests.kt index 873a2bc1588..f2ebeb185a1 100644 --- a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/types/TypeTests.kt +++ b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/types/TypeTests.kt @@ -116,7 +116,13 @@ internal class TypeTests : BaseTest() { fun testFunctionPointerTypes() { val topLevel = Path.of("src", "test", "resources", "types") val tu = - analyzeAndGetFirstTU(listOf(topLevel.resolve("fptr_type.cpp").toFile()), topLevel, true) + analyzeAndGetFirstTU( + listOf(topLevel.resolve("fptr_type.cpp").toFile()), + topLevel, + true + ) { + it.registerLanguage() + } val noParamType = FunctionPointerType(emptyList(), CPPLanguage(), IncompleteType()) val oneParamType = FunctionPointerType( @@ -171,7 +177,10 @@ internal class TypeTests : BaseTest() { ) { val topLevel = Path.of("src", "test", "resources", "compiling", "hierarchy", "multistep") - val result = analyze("simple_inheritance.cpp", topLevel, true) + val result = + analyze("simple_inheritance.cpp", topLevel, true) { + it.registerLanguage() + } val root = assertNotNull(result.records["Root"]).toType() val level0 = assertNotNull(result.records["Level0"]).toType() val level1 = assertNotNull(result.records["Level1"]).toType() @@ -187,7 +196,8 @@ internal class TypeTests : BaseTest() { @Test fun testCommonTypeTestCppMultiInheritance() { val topLevel = Path.of("src", "test", "resources", "compiling", "hierarchy", "multistep") - val result = analyze("multi_inheritance.cpp", topLevel, true) + val result = + analyze("multi_inheritance.cpp", topLevel, true) { it.registerLanguage() } val root = assertNotNull(result.records["Root"]).toType() val level0 = assertNotNull(result.records["Level0"]).toType() @@ -228,7 +238,7 @@ internal class TypeTests : BaseTest() { @Throws(Exception::class) fun graphTest() { val topLevel = Path.of("src", "test", "resources", "types") - val result = analyze("cpp", topLevel, true) + val result = analyze("cpp", topLevel, true) { it.registerLanguage() } val variableDeclarations = result.variables // Test PointerType chain with pointer diff --git a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/types/TypedefTest.kt b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/types/TypedefTest.kt index b9bab4af9e7..6416d951365 100644 --- a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/types/TypedefTest.kt +++ b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/types/TypedefTest.kt @@ -29,6 +29,7 @@ import de.fraunhofer.aisec.cpg.BaseTest import de.fraunhofer.aisec.cpg.TestUtils.analyze import de.fraunhofer.aisec.cpg.TestUtils.findByUniqueName import de.fraunhofer.aisec.cpg.TestUtils.findByUniquePredicate +import de.fraunhofer.aisec.cpg.frontends.cxx.CPPLanguage import de.fraunhofer.aisec.cpg.graph.declarations.ValueDeclaration import de.fraunhofer.aisec.cpg.graph.records import de.fraunhofer.aisec.cpg.graph.types.FunctionPointerType @@ -43,7 +44,7 @@ internal class TypedefTest : BaseTest() { @Test @Throws(Exception::class) fun testSingle() { - val result = analyze("cpp", topLevel, true) + val result = analyze("cpp", topLevel, true) { it.registerLanguage() } val variables = result.variables // normal type @@ -82,7 +83,7 @@ internal class TypedefTest : BaseTest() { @Test @Throws(Exception::class) fun testWithModifier() { - val result = analyze("cpp", topLevel, true) + val result = analyze("cpp", topLevel, true) { it.registerLanguage() } val variables = result.variables // pointer @@ -98,7 +99,7 @@ internal class TypedefTest : BaseTest() { @Test @Throws(Exception::class) fun testChained() { - val result = analyze("cpp", topLevel, true) + val result = analyze("cpp", topLevel, true) { it.registerLanguage() } val variables = result.variables val l1 = findByUniqueName(variables, "l1") val l3 = findByUniqueName(variables, "l3") @@ -110,7 +111,7 @@ internal class TypedefTest : BaseTest() { @Test @Throws(Exception::class) fun testMultiple() { - val result = analyze("cpp", topLevel, true) + val result = analyze("cpp", topLevel, true) { it.registerLanguage() } val variables = result.variables // simple type @@ -144,7 +145,7 @@ internal class TypedefTest : BaseTest() { @Test @Throws(Exception::class) fun testStructs() { - val result = analyze("cpp", topLevel, true) + val result = analyze("cpp", topLevel, true) { it.registerLanguage() } val variables = result.variables val ps1 = findByUniqueName(variables, "ps1") val ps2 = findByUniqueName(variables, "ps2") @@ -154,7 +155,7 @@ internal class TypedefTest : BaseTest() { @Test @Throws(Exception::class) fun testArbitraryTypedefLocation() { - val result = analyze("cpp", topLevel, true) + val result = analyze("cpp", topLevel, true) { it.registerLanguage() } val variables = result.variables val ullong1 = findByUniqueName(variables, "someUllong1") val ullong2 = findByUniqueName(variables, "someUllong2") @@ -164,7 +165,7 @@ internal class TypedefTest : BaseTest() { @Test @Throws(Exception::class) fun testMemberTypeDef() { - val result = analyze("cpp", topLevel, true) + val result = analyze("cpp", topLevel, true) { it.registerLanguage() } val variables = result.variables val records = result.records val addConst = findByUniqueName(records, "add_const") diff --git a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/variable_resolution/VariableResolverCppTest.kt b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/variable_resolution/VariableResolverCppTest.kt index 5a0ea31a7ca..ac6ec530ac8 100644 --- a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/variable_resolution/VariableResolverCppTest.kt +++ b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/variable_resolution/VariableResolverCppTest.kt @@ -29,6 +29,7 @@ import de.fraunhofer.aisec.cpg.BaseTest import de.fraunhofer.aisec.cpg.TestUtils.analyze import de.fraunhofer.aisec.cpg.TestUtils.assertUsageOf import de.fraunhofer.aisec.cpg.TestUtils.assertUsageOfMemberAndBase +import de.fraunhofer.aisec.cpg.frontends.cxx.CPPLanguage import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.declarations.* import de.fraunhofer.aisec.cpg.graph.statements.CatchClause @@ -76,7 +77,7 @@ internal class VariableResolverCppTest : BaseTest() { listOf("scope_variables.cpp", "external_class.cpp").map { topLevel.resolve(it).toFile() } - val result = analyze(files, topLevel, true) + val result = analyze(files, topLevel, true) { it.registerLanguage() } val calls = result.calls { it.name.localName == "printLog" } val records = result.records val functions = result.functions diff --git a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXAmbiguitiesTest.kt b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXAmbiguitiesTest.kt index 087f756f0f6..6a868e92841 100644 --- a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXAmbiguitiesTest.kt +++ b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXAmbiguitiesTest.kt @@ -55,7 +55,11 @@ class CXXAmbiguitiesTest { @Test fun testCallVsFunctionDeclaration() { val file = File("src/test/resources/call_me_crazy.h") - val tu = TestUtils.analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + TestUtils.analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + it.registerLanguage() + } assertNotNull(tu) // make sure we still have only one declaration in the file (the record) @@ -87,7 +91,10 @@ class CXXAmbiguitiesTest { @Test fun testFunctionCallOrTypeCast() { val file = File("src/test/resources/function_ptr_or_type_cast.c") - val tu = TestUtils.analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + TestUtils.analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } assertNotNull(tu) val mainFunc = tu.byNameOrNull("main") @@ -124,7 +131,10 @@ class CXXAmbiguitiesTest { @Test fun testMethodOrFunction() { val file = File("src/test/resources/method_or_function_call.cpp") - val tu = TestUtils.analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + TestUtils.analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } assertNotNull(tu) val mainFunc = tu.byNameOrNull("main") diff --git a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXCompilationDatabaseTest.kt b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXCompilationDatabaseTest.kt index 8a9a38c7ca1..bbbbf0a9eec 100644 --- a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXCompilationDatabaseTest.kt +++ b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXCompilationDatabaseTest.kt @@ -46,7 +46,11 @@ class CXXCompilationDatabaseTest { ) for (path in ccs) { val cc = File(path) - val result = TestUtils.analyzeWithCompilationDatabase(cc, true) + val result = + TestUtils.analyzeWithCompilationDatabase(cc, true) { + it.registerLanguage() + it.registerLanguage() + } val tu = result.translationUnits.firstOrNull() assertNotNull(tu) @@ -95,7 +99,11 @@ class CXXCompilationDatabaseTest { @Test fun testCompilationDatabaseSimple() { val cc = File("src/test/resources/cxxCompilationDatabase/compile_commands_simple.json") - val result = TestUtils.analyzeWithCompilationDatabase(cc, true) + val result = + TestUtils.analyzeWithCompilationDatabase(cc, true) { + it.registerLanguage() + it.registerLanguage() + } val tu = result.translationUnits.firstOrNull() assertNotNull(tu) assertNotNull(tu) @@ -113,7 +121,11 @@ class CXXCompilationDatabaseTest { @Test fun testCompilationDatabaseMultiTUs() { val cc = File("src/test/resources/cxxCompilationDatabase/compile_commands_multi_tus.json") - val result = TestUtils.analyzeWithCompilationDatabase(cc, true) + val result = + TestUtils.analyzeWithCompilationDatabase(cc, true) { + it.registerLanguage() + it.registerLanguage() + } val tus = result.translationUnits assertEquals(2, tus.size) val ref = mapOf("main_tu_1.c" to 1, "main_tu_2.c" to 2) @@ -137,7 +149,11 @@ class CXXCompilationDatabaseTest { @Test fun testCompilationDatabaseArch() { val cc = File("src/test/resources/cxxCompilationDatabase/compile_commands_arch.json") - val result = TestUtils.analyzeWithCompilationDatabase(cc, true) + val result = + TestUtils.analyzeWithCompilationDatabase(cc, true) { + it.registerLanguage() + it.registerLanguage() + } val main = result.translationUnits.firstOrNull()?.byNameOrNull("main") assertNotNull(main) diff --git a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXIncludeTest.kt b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXIncludeTest.kt index 291c29a3728..0db9bec36de 100644 --- a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXIncludeTest.kt +++ b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXIncludeTest.kt @@ -45,7 +45,10 @@ internal class CXXIncludeTest : BaseTest() { @Throws(Exception::class) fun testDefinitionsAndDeclaration() { val file = File("src/test/resources/include.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } for (d in tu.declarations) { println(d.name.localName + " " + d.location) } @@ -88,7 +91,10 @@ internal class CXXIncludeTest : BaseTest() { fun testCodeAndRegionInInclude() { // checks, whether code and region for nodes in includes are properly set val file = File("src/test/resources/include.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val someClass = tu.getDeclarationsByName("SomeClass", RecordDeclaration::class.java) assertFalse(someClass.isEmpty()) diff --git a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXLanguageFrontendTest.kt b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXLanguageFrontendTest.kt index ce28cc0d2a8..3ba7ed9ddcc 100644 --- a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXLanguageFrontendTest.kt +++ b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXLanguageFrontendTest.kt @@ -55,7 +55,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testForEach() { val file = File("src/test/resources/cxx/foreachstmt.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val main = tu.getDeclarationsByName("main", FunctionDeclaration::class.java) assertFalse(main.isEmpty()) @@ -87,7 +90,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testTryCatch() { val file = File("src/test/resources/components/trystmt.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val main = tu.getDeclarationsByName("main", FunctionDeclaration::class.java) assertFalse(main.isEmpty()) @@ -120,7 +126,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testTypeId() { val file = File("src/test/resources/typeidexpr.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val main = tu.getDeclarationsByName("main", FunctionDeclaration::class.java) with(tu) { assertNotNull(main) @@ -158,7 +167,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testCast() { val file = File("src/test/resources/cxx/castexpr.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } with(tu) { val main = tu.functions["main"] assertNotNull(main) @@ -201,7 +213,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testArrays() { val file = File("src/test/resources/cxx/arrays.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val main = tu.byNameOrNull("main") with(tu) { assertNotNull(main) @@ -250,7 +265,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testFunctionDeclaration() { val file = File("src/test/resources/cxx/functiondecl.cpp") - val declaration = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val declaration = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } // should be seven function nodes assertEquals(8, declaration.declarations.size) @@ -318,7 +336,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testBlock() { val file = File("src/test/resources/compoundstmt.cpp") - val declaration = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val declaration = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val function = declaration.getDeclarationAs(0, FunctionDeclaration::class.java) assertNotNull(function) @@ -340,7 +361,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testPostfixExpression() { val file = File("src/test/resources/postfixexpression.cpp") - val declaration = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val declaration = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val statements = declaration.getDeclarationAs(0, FunctionDeclaration::class.java)?.statements assertNotNull(statements) @@ -371,7 +395,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testIf() { val file = File("src/test/resources/if.cpp") - val declaration = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val declaration = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val statements = declaration.getDeclarationAs(0, FunctionDeclaration::class.java)?.statements assertNotNull(statements) @@ -389,7 +416,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testSwitch() { val file = File("src/test/resources/cfg/switch.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } assertTrue(tu.allChildren().isNotEmpty()) @@ -410,7 +440,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testDeclarationStatement() { val file = File("src/test/resources/cxx/declstmt.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } with(tu) { val function = tu.getDeclarationAs(0, FunctionDeclaration::class.java) val statements = function?.statements @@ -499,7 +532,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testAssignmentExpression() { val file = File("src/test/resources/cxx/assignmentexpression.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } // just take a look at the second function val main = tu.functions["main"] @@ -545,7 +581,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testShiftExpression() { val file = File("src/test/resources/shiftexpression.cpp") - val declaration = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val declaration = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val functionDecl = declaration.getDeclarationAs(0, FunctionDeclaration::class.java) val statements = functionDecl?.statements assertNotNull(statements) @@ -556,7 +595,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testUnaryOperator() { val file = File("src/test/resources/unaryoperator.cpp") - val unit = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val unit = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val statements = unit.getDeclarationAs(0, FunctionDeclaration::class.java)?.statements assertNotNull(statements) @@ -622,7 +664,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testBinaryOperator() { val file = File("src/test/resources/cxx/binaryoperator.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val main = tu.functions["main"] assertNotNull(main) @@ -684,7 +729,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testRecordDeclaration() { val file = File("src/test/resources/cxx/recordstmt.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val recordDeclaration = tu.records.firstOrNull() assertNotNull(recordDeclaration) @@ -798,7 +846,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testLiterals() { val file = File("src/test/resources/cxx/literals.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val s = tu.variables["s"] assertNotNull(s) @@ -872,7 +923,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testInitListExpression() { val file = File("src/test/resources/initlistexpression.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } // x y = { 1, 2 }; val y = tu.getDeclarationAs(1, VariableDeclaration::class.java) @@ -908,7 +962,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testObjectCreation() { val file = File("src/test/resources/cxx/objcreation.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } assertNotNull(tu) with(tu) { // get the main method @@ -969,7 +1026,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testRegionsCfg() { val file = File("src/test/resources/cfg.cpp") - val declaration = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val declaration = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val fdecl = declaration.getDeclarationAs(0, FunctionDeclaration::class.java) val body = fdecl!!.body as Block val expected: MutableMap = HashMap() @@ -990,7 +1050,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testDesignatedInitializer() { val file = File("src/test/resources/components/designatedInitializer.cpp") - val declaration = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val declaration = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } // should be four method nodes assertEquals(2, declaration.declarations.size) @@ -1071,7 +1134,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testLocalVariables() { val file = File("src/test/resources/variables/local_variables.cpp") - val declaration = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val declaration = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val function = declaration.byNameOrNull("testExpressionInExpressionList") @@ -1093,7 +1159,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testLocation() { val file = File("src/test/resources/cxx/foreachstmt.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val main = tu.functions["main"] assertNotNull(main) @@ -1109,7 +1178,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testNamespaces() { val file = File("src/test/resources/namespaces.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } assertNotNull(tu) val firstNamespace = @@ -1210,7 +1282,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testEOGCompleteness() { val file = File("src/test/resources/fix-455/main.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val main = tu.getDeclarationsByName("main", FunctionDeclaration::class.java).iterator().next() assertNotNull(main) @@ -1242,8 +1317,8 @@ internal class CXXLanguageFrontendTest : BaseTest() { val file = File("src/test/resources/cxx/parenthesis.cpp") val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { - config: TranslationConfiguration.Builder -> - config.inferenceConfiguration(builder().guessCastExpressions(true).build()) + it.inferenceConfiguration(builder().guessCastExpressions(true).build()) + it.registerLanguage() } val main = tu.getDeclarationsByName("main", FunctionDeclaration::class.java).iterator().next() @@ -1266,7 +1341,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testCppThis() { val file = File("src/test/resources/cpp-this-field.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val main = tu.byNameOrNull("main") assertNotNull(main) @@ -1307,7 +1385,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testEnum() { val file = File("src/test/resources/c/enum.c") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } // TU should only contain two AST declarations (EnumDeclaration and FunctionDeclaration), // but NOT any EnumConstantDeclarations assertEquals(2, tu.declarations.size) @@ -1325,7 +1406,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testStruct() { val file = File("src/test/resources/c/struct.c") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val main = tu.functions["main"] assertNotNull(main) @@ -1346,7 +1430,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testTypedef() { val file = File("src/test/resources/c/typedef_in_header/main.c") - val result = analyze(listOf(file), file.parentFile.toPath(), true) + val result = + analyze(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val typedefs = result.finalCtx.scopeManager.currentTypedefs assertNotNull(typedefs) @@ -1371,7 +1458,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testFunctionPointerToClassMethodSimple() { val file = File("src/test/resources/cxx/funcptr_class_simple.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val myClass = tu.records["MyClass"] assertNotNull(myClass) @@ -1438,6 +1528,7 @@ internal class CXXLanguageFrontendTest : BaseTest() { val file = File("src/test/resources/c/func_ptr_call.c") val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), false) { + it.registerLanguage() it.registerPass() it.registerPass() it.registerPass() @@ -1483,6 +1574,7 @@ internal class CXXLanguageFrontendTest : BaseTest() { val file = File("src/test/resources/c/func_ptr_call.c") val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), false) { + it.registerLanguage() it.registerPass() it.registerPass() it.registerPass() @@ -1526,7 +1618,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testNamespacedFunction() { val file = File("src/test/resources/cxx/namespaced_function.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } assertNotNull(tu) // everything in the TU should be a function (within a namespace), not a method (except the @@ -1557,7 +1652,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testLambdas() { val file = File("src/test/resources/cxx/lambdas.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } assertNotNull(tu) } @@ -1565,7 +1663,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testCFunctionReturnType() { val file = File("src/test/resources/c/types.c") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } assertNotNull(tu) assertLocalName("int", tu.functions["main"]?.returnTypes?.firstOrNull()) @@ -1575,7 +1676,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Throws(Exception::class) fun testFancyTypes() { val file = File("src/test/resources/cxx/fancy_types.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } assertNotNull(tu) val ptr = tu.variables["ptr"] @@ -1591,7 +1695,9 @@ internal class CXXLanguageFrontendTest : BaseTest() { listOf(file.resolve("main1.cpp"), file.resolve("main2.cpp")), file.toPath(), true - ) + ) { + it.registerLanguage() + } assertNotNull(result) // For now, we have duplicate functions because we include the header twice. This might diff --git a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXLiteralTest.kt b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXLiteralTest.kt index d3761416d7f..fcc11421ba9 100644 --- a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXLiteralTest.kt +++ b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXLiteralTest.kt @@ -47,7 +47,10 @@ internal class CXXLiteralTest : BaseTest() { @Throws(Exception::class) fun testZeroIntegerLiterals() { val file = File("src/test/resources/integer_literals.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val zero = tu.getDeclarationsByName("zero", FunctionDeclaration::class.java) assertFalse(zero.isEmpty()) @@ -68,7 +71,10 @@ internal class CXXLiteralTest : BaseTest() { @Throws(Exception::class) fun testDecimalIntegerLiterals() { val file = File("src/test/resources/integer_literals.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val decimal = tu.getDeclarationsByName("decimal", FunctionDeclaration::class.java) assertFalse(decimal.isEmpty()) val funcDecl = decimal.iterator().next() @@ -107,7 +113,10 @@ internal class CXXLiteralTest : BaseTest() { @Throws(Exception::class) fun testOctalIntegerLiterals() { val file = File("src/test/resources/integer_literals.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val octal = tu.getDeclarationsByName("octal", FunctionDeclaration::class.java) assertFalse(octal.isEmpty()) val funcDecl = octal.iterator().next() @@ -127,7 +136,10 @@ internal class CXXLiteralTest : BaseTest() { @Throws(Exception::class) fun testNonDecimalIntegerLiterals() { val file = File("src/test/resources/integer_literals.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val hex = tu.getDeclarationsByName("hex", FunctionDeclaration::class.java) assertFalse(hex.isEmpty()) val funcDecl = hex.iterator().next() @@ -146,7 +158,10 @@ internal class CXXLiteralTest : BaseTest() { @Throws(Exception::class) fun testLargeNegativeNumber() { val file = File("src/test/resources/largenegativenumber.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } val main = tu.getDeclarationsByName("main", FunctionDeclaration::class.java) assertFalse(main.isEmpty()) diff --git a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXResolveTest.kt b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXResolveTest.kt index 6813991d470..001e664d9fd 100644 --- a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXResolveTest.kt +++ b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXResolveTest.kt @@ -47,6 +47,7 @@ class CXXResolveTest { it.inferenceConfiguration( InferenceConfiguration.builder().inferRecords(true).build() ) + it.registerLanguage() } assertNotNull(tu) @@ -102,6 +103,7 @@ class CXXResolveTest { it.inferenceConfiguration( InferenceConfiguration.builder().inferRecords(true).build() ) + it.registerLanguage() } assertNotNull(tu) diff --git a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/helpers/BenchmarkCXXTest.kt b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/helpers/BenchmarkCXXTest.kt index 1d283bf9b5e..223272691f4 100644 --- a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/helpers/BenchmarkCXXTest.kt +++ b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/helpers/BenchmarkCXXTest.kt @@ -26,6 +26,7 @@ package de.fraunhofer.aisec.cpg.helpers import de.fraunhofer.aisec.cpg.TestUtils +import de.fraunhofer.aisec.cpg.frontends.cxx.CPPLanguage import java.io.File import kotlin.io.path.Path import kotlin.test.assertContains @@ -38,7 +39,10 @@ class BenchmarkCXXTest { @Test fun testGetBenchmarkResult() { val file = File("src/test/resources/cxx/foreachstmt.cpp") - val tr = TestUtils.analyze(listOf(file), file.parentFile.toPath(), true) + val tr = + TestUtils.analyze(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } assertNotNull(tr) val res = tr.benchmarkResults @@ -59,7 +63,10 @@ class BenchmarkCXXTest { @Test fun testPrintBenchmark() { val file = File("src/test/resources/cxx/foreachstmt.cpp") - val tr = TestUtils.analyze(listOf(file), file.parentFile.toPath(), true) + val tr = + TestUtils.analyze(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } assertNotNull(tr) tr.benchmarkResults.print() diff --git a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/CallResolverTest.kt b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/CallResolverTest.kt index 4e9ea44441c..39ddd7d3348 100644 --- a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/CallResolverTest.kt +++ b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/CallResolverTest.kt @@ -153,7 +153,9 @@ class CallResolverTest : BaseTest() { listOf(Path.of(topLevel.toString(), "calls.cpp").toFile()), topLevel, true - ) + ) { + it.registerLanguage() + } val tu = result.translationUnits.firstOrNull() assertNotNull(tu) @@ -184,7 +186,9 @@ class CallResolverTest : BaseTest() { ), topLevel, true - ) + ) { + it.registerLanguage() + } val functionDeclarations = result.functions val callExpressions = result.calls @@ -224,7 +228,9 @@ class CallResolverTest : BaseTest() { ), topLevel, true - ) + ) { + it.registerLanguage() + } val callExpressions = result.calls // Check resolution of implicit cast @@ -272,7 +278,9 @@ class CallResolverTest : BaseTest() { ), topLevel, true - ) + ) { + it.registerLanguage() + } val calls = result.calls val functionDeclarations = result.functions val displayDeclaration = @@ -359,7 +367,9 @@ class CallResolverTest : BaseTest() { ), topLevel, true - ) + ) { + it.registerLanguage() + } val calls = result.calls val functionDeclarations = result.functions val displayFunction = @@ -423,7 +433,9 @@ class CallResolverTest : BaseTest() { listOf(Path.of(topLevel.toString(), "defaultargs", "partialDefaults.cpp").toFile()), topLevel, true - ) + ) { + it.registerLanguage() + } val calls = result.calls val functionDeclarations = result.functions val addFunction = @@ -493,7 +505,9 @@ class CallResolverTest : BaseTest() { listOf(Path.of(topLevel.toString(), "defaultargs", "defaultInMethod.cpp").toFile()), topLevel, true - ) + ) { + it.registerLanguage() + } val calls = result.calls val functionDeclarations = result.functions val declaredReferenceExpressions = result.refs @@ -535,7 +549,9 @@ class CallResolverTest : BaseTest() { listOf(Path.of(topLevel.toString(), "cxxprioresolution", "undefined.cpp").toFile()), topLevel, true - ) + ) { + it.registerLanguage() + } val calls = result.calls assertEquals(1, calls.size) @@ -553,7 +569,9 @@ class CallResolverTest : BaseTest() { listOf(Path.of(topLevel.toString(), "cxxprioresolution", "defined.cpp").toFile()), topLevel, true - ) + ) { + it.registerLanguage() + } val calls = result.calls assertEquals(1, calls.size) @@ -646,7 +664,9 @@ class CallResolverTest : BaseTest() { ), topLevel, true - ) + ) { + it.registerLanguage() + } val calls = result.calls testScopedFunctionResolutionFunctionGlobal(result, calls) testScopedFunctionResolutionRedeclaration(result, calls) @@ -669,7 +689,9 @@ class CallResolverTest : BaseTest() { ), topLevel, true - ) + ) { + it.registerLanguage() + } val calls = result.calls val methodDeclarations = result.methods val calcOverload: FunctionDeclaration = @@ -717,7 +739,9 @@ class CallResolverTest : BaseTest() { ), topLevel, true - ) + ) { + it.registerLanguage() + } val calls = result.calls val calcCall = @@ -735,7 +759,10 @@ class CallResolverTest : BaseTest() { @Throws(Exception::class) fun testCallWithIgnoredResult() { val file = File("src/test/resources/calls/ignore-return.cpp") - val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) + val tu = + analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { + it.registerLanguage() + } // check for function declarations, we only want two: main and someFunction // we do NOT want any inferred/implicit function declarations that could exist, if diff --git a/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/FrontendHelperTest.kt b/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/FrontendHelperTest.kt index d84509c91f3..c893a8b2b44 100644 --- a/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/FrontendHelperTest.kt +++ b/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/FrontendHelperTest.kt @@ -50,9 +50,8 @@ class FrontendHelperTest { .sourceLocations(listOf(file)) .defaultPasses() .debugParser(true) - .defaultLanguages() + .registerLanguage() .failOnError(true) - .registerLanguage(JavaLanguage()) .build() val analyzer = TranslationManager.builder().config(config).build() @@ -135,8 +134,7 @@ class FrontendHelperTest { .sourceLocations(listOf(file)) .defaultPasses() .debugParser(true) - .defaultLanguages() - .registerLanguage(JavaLanguage()) + .registerLanguage() .failOnError(true) .build() diff --git a/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/java/JavaLanguageFrontendTest.kt b/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/java/JavaLanguageFrontendTest.kt index db9856a8bb4..0c32a00c4d4 100644 --- a/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/java/JavaLanguageFrontendTest.kt +++ b/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/java/JavaLanguageFrontendTest.kt @@ -530,8 +530,7 @@ internal class JavaLanguageFrontendTest : BaseTest() { .sourceLocations(listOf(file)) .topLevel(file.parentFile) .defaultPasses() - .defaultLanguages() - .registerLanguage(JavaLanguage()) + .registerLanguage() .processAnnotations(true) ) assertFalse(declarations.isEmpty()) @@ -674,7 +673,6 @@ internal class JavaLanguageFrontendTest : BaseTest() { val file = File("src/test/resources/compiling/RecordDeclaration.java") val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { - it.unregisterLanguage(JavaLanguage::class.java) it.registerLanguage(MyJavaLanguage()) } @@ -702,8 +700,7 @@ internal class JavaLanguageFrontendTest : BaseTest() { .sourceLocations(*files.toTypedArray()) .topLevel(topLevel.toFile()) .defaultPasses() - .defaultLanguages() - .registerLanguage(JavaLanguage()) + .registerLanguage() .debugParser(true) .failOnError(true) .build() @@ -727,8 +724,7 @@ internal class JavaLanguageFrontendTest : BaseTest() { .sourceLocations(*files.toTypedArray()) .topLevel(topLevel.toFile()) .defaultPasses() - .defaultLanguages() - .registerLanguage(JavaLanguage()) + .registerLanguage() .debugParser(true) .failOnError(true) .build() diff --git a/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/java/LambdaTest.kt b/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/java/LambdaTest.kt index 0f2fa225f2f..77da17cba76 100644 --- a/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/java/LambdaTest.kt +++ b/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/java/LambdaTest.kt @@ -48,8 +48,7 @@ class JavaLambdaTest { TranslationConfiguration.builder() .sourceLocations(File("src/test/resources/Lambda.java")) .defaultPasses() - .defaultLanguages() - .registerLanguage(JavaLanguage()) + .registerLanguage() .build() val analyzer = TranslationManager.builder().config(config).build() val result = analyzer.analyze().get() diff --git a/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/helpers/CommentMatcherTest.kt b/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/helpers/CommentMatcherTest.kt index a94dbb6f501..1625312c595 100644 --- a/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/helpers/CommentMatcherTest.kt +++ b/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/helpers/CommentMatcherTest.kt @@ -47,8 +47,7 @@ class CommentMatcherTest { .sourceLocations(listOf(file)) .defaultPasses() .debugParser(true) - .defaultLanguages() - .registerLanguage(JavaLanguage()) + .registerLanguage() .failOnError(true) .build() diff --git a/cpg-neo4j/src/main/kotlin/de/fraunhofer/aisec/cpg_vis_neo4j/Application.kt b/cpg-neo4j/src/main/kotlin/de/fraunhofer/aisec/cpg_vis_neo4j/Application.kt index a436cb39515..022309fd2aa 100644 --- a/cpg-neo4j/src/main/kotlin/de/fraunhofer/aisec/cpg_vis_neo4j/Application.kt +++ b/cpg-neo4j/src/main/kotlin/de/fraunhofer/aisec/cpg_vis_neo4j/Application.kt @@ -345,7 +345,8 @@ class Application : Callable { val translationConfiguration = TranslationConfiguration.builder() .topLevel(topLevel) - .defaultLanguages() + .optionalLanguage("de.fraunhofer.aisec.cpg.frontends.cxx.CLanguage") + .optionalLanguage("de.fraunhofer.aisec.cpg.frontends.cxx.CPPLanguage") .optionalLanguage("de.fraunhofer.aisec.cpg.frontends.java.JavaLanguage") .optionalLanguage("de.fraunhofer.aisec.cpg.frontends.golang.GoLanguage") .optionalLanguage("de.fraunhofer.aisec.cpg.frontends.llvm.LLVMIRLanguage")