diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 13e89b56f7..d26b60c13d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -79,7 +79,7 @@ On some edges, we want to store additional information (e.g., if a `EOG` node is /** The list of function parameters. */ @Relationship(value = "PARAMETERS", direction = Relationship.Direction.OUTGOING) @field:SubGraph("AST") -var parameterEdges = mutableListOf>() +var parameterEdges = mutableListOf>() /** Virtual property for accessing [parameterEdges] without property edges. */ var parameters by PropertyEdgeDelegate(FunctionDeclaration::parameterEdges) 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 f9e44f0eae..ef9560d4e4 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 @@ -73,17 +73,17 @@ class MultiValueEvaluator : ValueEvaluator() { is FieldDeclaration -> { return evaluateInternal(node.initializer, depth + 1) } - is ArrayCreationExpression -> return evaluateInternal(node.initializer, depth + 1) + is NewArrayExpression -> return evaluateInternal(node.initializer, depth + 1) is VariableDeclaration -> return evaluateInternal(node.initializer, depth + 1) // For a literal, we can just take its value, and we are finished is Literal<*> -> return node.value - is DeclaredReferenceExpression -> return handleDeclaredReferenceExpression(node, depth) + is Reference -> return handleReference(node, depth) is UnaryOperator -> return handleUnaryOp(node, depth) is AssignExpression -> return handleAssignExpression(node, depth) is BinaryOperator -> return handleBinaryOperator(node, depth) // Casts are just a wrapper in this case, we are interested in the inner expression is CastExpression -> return this.evaluateInternal(node.expression, depth + 1) - is ArraySubscriptionExpression -> return handleArraySubscriptionExpression(node, depth) + is SubscriptExpression -> return handleSubscriptExpression(node, depth) // While we are not handling different paths of variables with If statements, we can // easily be partly path-sensitive in a conditional expression is ConditionalExpression -> return handleConditionalExpression(node, depth) @@ -170,8 +170,8 @@ class MultiValueEvaluator : ValueEvaluator() { override fun handleConditionalExpression(expr: ConditionalExpression, depth: Int): Any { val result = mutableSetOf() - val elseResult = evaluateInternal(expr.elseExpr, depth + 1) - val thenResult = evaluateInternal(expr.thenExpr, depth + 1) + val elseResult = evaluateInternal(expr.elseExpression, depth + 1) + val thenResult = evaluateInternal(expr.thenExpression, depth + 1) if (thenResult is Collection<*>) result.addAll(thenResult) else result.add(thenResult) if (elseResult is Collection<*>) result.addAll(elseResult) else result.add(elseResult) return result @@ -217,10 +217,7 @@ class MultiValueEvaluator : ValueEvaluator() { * In contrast to the implementation of [ValueEvaluator], this one can handle more than one * value. */ - override fun handleDeclaredReferenceExpression( - expr: DeclaredReferenceExpression, - depth: Int - ): Collection { + override fun handleReference(expr: Reference, depth: Int): Collection { // For a reference, we are interested in its last assignment into the reference // denoted by the previous DFG edge. We need to filter out any self-references for READWRITE // references. @@ -282,10 +279,7 @@ class MultiValueEvaluator : ValueEvaluator() { forStatement.iterationStatement == node.astParent } - private fun handleSimpleLoopVariable( - expr: DeclaredReferenceExpression, - depth: Int - ): Collection { + private fun handleSimpleLoopVariable(expr: Reference, depth: Int): Collection { val loop = expr.prevDFG.firstOrNull { e -> e.astParent is ForStatement }?.astParent as? ForStatement @@ -298,13 +292,13 @@ class MultiValueEvaluator : ValueEvaluator() { val cond = loop.condition as BinaryOperator val result = mutableSetOf() var lhs = - if ((cond.lhs as? DeclaredReferenceExpression)?.refersTo == expr.refersTo) { + if ((cond.lhs as? Reference)?.refersTo == expr.refersTo) { loopVar } else { evaluateInternal(cond.lhs, depth + 1) } var rhs = - if ((cond.rhs as? DeclaredReferenceExpression)?.refersTo == expr.refersTo) { + if ((cond.rhs as? Reference)?.refersTo == expr.refersTo) { loopVar } else { evaluateInternal(cond.rhs, depth + 1) @@ -323,17 +317,16 @@ class MultiValueEvaluator : ValueEvaluator() { is AssignExpression -> { if ( loopOp.operatorCode == "=" && - (loopOp.lhs.singleOrNull() as? DeclaredReferenceExpression) - ?.refersTo == expr.refersTo && + (loopOp.lhs.singleOrNull() as? Reference)?.refersTo == + expr.refersTo && loopOp.rhs.singleOrNull() is BinaryOperator ) { // Assignment to the variable, take the rhs and see if it's also a // binary operator val opLhs = if ( - ((loopOp.rhs())?.lhs - as? DeclaredReferenceExpression) - ?.refersTo == expr.refersTo + ((loopOp.rhs())?.lhs as? Reference)?.refersTo == + expr.refersTo ) { loopVar } else { @@ -341,9 +334,8 @@ class MultiValueEvaluator : ValueEvaluator() { } val opRhs = if ( - ((loopOp.rhs())?.rhs - as? DeclaredReferenceExpression) - ?.refersTo == expr.refersTo + ((loopOp.rhs())?.rhs as? Reference)?.refersTo == + expr.refersTo ) { loopVar } else { @@ -359,19 +351,13 @@ class MultiValueEvaluator : ValueEvaluator() { // No idea what this is but it's a binary op... val opLhs = - if ( - (loopOp.lhs as? DeclaredReferenceExpression)?.refersTo == - expr.refersTo - ) { + if ((loopOp.lhs as? Reference)?.refersTo == expr.refersTo) { loopVar } else { loopOp.lhs } val opRhs = - if ( - (loopOp.rhs as? DeclaredReferenceExpression)?.refersTo == - expr.refersTo - ) { + if ((loopOp.rhs as? Reference)?.refersTo == expr.refersTo) { loopVar } else { loopOp.rhs @@ -380,10 +366,7 @@ class MultiValueEvaluator : ValueEvaluator() { } is UnaryOperator -> { computeUnaryOpEffect( - if ( - (loopOp.input as? DeclaredReferenceExpression)?.refersTo == - expr.refersTo - ) { + if ((loopOp.input as? Reference)?.refersTo == expr.refersTo) { loopVar } else { loopOp.input @@ -400,10 +383,10 @@ class MultiValueEvaluator : ValueEvaluator() { return result } - if ((cond.lhs as? DeclaredReferenceExpression)?.refersTo == expr.refersTo) { + if ((cond.lhs as? Reference)?.refersTo == expr.refersTo) { lhs = loopVar } - if ((cond.rhs as? DeclaredReferenceExpression)?.refersTo == expr.refersTo) { + if ((cond.rhs as? Reference)?.refersTo == expr.refersTo) { rhs = loopVar } comparisonResult = computeBinaryOpEffect(lhs, rhs, cond) diff --git a/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/SizeEvaluator.kt b/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/SizeEvaluator.kt index b64fef2989..2b802201ec 100644 --- a/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/SizeEvaluator.kt +++ b/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/SizeEvaluator.kt @@ -51,17 +51,17 @@ class SizeEvaluator : ValueEvaluator() { node?.let { this.path += it } return when (node) { - is ArrayCreationExpression -> + is NewArrayExpression -> if (node.initializer != null) { evaluateInternal(node.initializer, depth + 1) } else { evaluateInternal(node.dimensions.firstOrNull(), depth + 1) } is VariableDeclaration -> evaluateInternal(node.initializer, depth + 1) - is DeclaredReferenceExpression -> evaluateInternal(node.refersTo, depth + 1) + is Reference -> evaluateInternal(node.refersTo, depth + 1) // For a literal, we can just take its value, and we are finished is Literal<*> -> if (node.value is String) (node.value as String).length else node.value - is ArraySubscriptionExpression -> evaluate(node.arrayExpression) + is SubscriptExpression -> evaluate(node.arrayExpression) else -> cannotEvaluate(node, this) } } diff --git a/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/ValueEvaluator.kt b/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/ValueEvaluator.kt index 477927414d..04ddcdd46c 100644 --- a/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/ValueEvaluator.kt +++ b/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/ValueEvaluator.kt @@ -87,16 +87,16 @@ open class ValueEvaluator( node?.let { this.path += it } when (node) { - is ArrayCreationExpression -> return evaluateInternal(node.initializer, depth + 1) + is NewArrayExpression -> return evaluateInternal(node.initializer, depth + 1) is VariableDeclaration -> return evaluateInternal(node.initializer, depth + 1) // For a literal, we can just take its value, and we are finished is Literal<*> -> return node.value - is DeclaredReferenceExpression -> return handleDeclaredReferenceExpression(node, depth) + is Reference -> return handleReference(node, depth) is UnaryOperator -> return handleUnaryOp(node, depth) is BinaryOperator -> return handleBinaryOperator(node, depth) // Casts are just a wrapper in this case, we are interested in the inner expression is CastExpression -> return this.evaluateInternal(node.expression, depth + 1) - is ArraySubscriptionExpression -> return handleArraySubscriptionExpression(node, depth) + is SubscriptExpression -> return handleSubscriptExpression(node, depth) // While we are not handling different paths of variables with If statements, we can // easily be partly path-sensitive in a conditional expression is ConditionalExpression -> return handleConditionalExpression(node, depth) @@ -277,12 +277,8 @@ open class ValueEvaluator( * basically the case if the base of the subscript expression is a list of [KeyValueExpression] * s. */ - protected fun handleArraySubscriptionExpression( - expr: ArraySubscriptionExpression, - depth: Int - ): Any? { - val array = - (expr.arrayExpression as? DeclaredReferenceExpression)?.refersTo as? VariableDeclaration + protected fun handleSubscriptExpression(expr: SubscriptExpression, depth: Int): Any? { + val array = (expr.arrayExpression as? Reference)?.refersTo as? VariableDeclaration val ile = array?.initializer as? InitializerListExpression ile?.let { @@ -301,7 +297,7 @@ open class ValueEvaluator( return (array.initializer as Literal<*>).value } - if (expr.arrayExpression is ArraySubscriptionExpression) { + if (expr.arrayExpression is SubscriptExpression) { return evaluateInternal(expr.arrayExpression, depth + 1) } @@ -315,9 +311,9 @@ open class ValueEvaluator( val rhs = evaluateInternal((expr.condition as? BinaryOperator)?.rhs, depth) return if (lhs == rhs) { - evaluateInternal(expr.thenExpr, depth + 1) + evaluateInternal(expr.thenExpression, depth + 1) } else { - evaluateInternal(expr.elseExpr, depth + 1) + evaluateInternal(expr.elseExpression, depth + 1) } } @@ -328,10 +324,7 @@ open class ValueEvaluator( * Tries to compute the constant value of a reference. It therefore checks the incoming data * flow edges. */ - protected open fun handleDeclaredReferenceExpression( - expr: DeclaredReferenceExpression, - depth: Int - ): Any? { + protected open fun handleReference(expr: Reference, depth: Int): Any? { // For a reference, we are interested into its last assignment into the reference // denoted by the previous DFG edge. We need to filter out any self-references for READWRITE // references. @@ -358,10 +351,7 @@ open class ValueEvaluator( * If a reference has READWRITE access, ignore any "self-references", e.g. from a * plus/minus/div/times-assign or a plusplus/minusminus, etc. */ - protected fun filterSelfReferences( - ref: DeclaredReferenceExpression, - inDFG: List - ): List { + protected fun filterSelfReferences(ref: Reference, inDFG: List): List { var list = inDFG // The ops +=, -=, ... and ++, -- have in common that we see the ref twice: Once to reach 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 60e0f9d065..1845eee579 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 @@ -27,15 +27,15 @@ package de.fraunhofer.aisec.cpg.analysis.fsm import de.fraunhofer.aisec.cpg.graph.Node import de.fraunhofer.aisec.cpg.graph.declarations.Declaration -import de.fraunhofer.aisec.cpg.graph.declarations.ParamVariableDeclaration +import de.fraunhofer.aisec.cpg.graph.declarations.ParameterDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.VariableDeclaration import de.fraunhofer.aisec.cpg.graph.edge.Properties import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdge import de.fraunhofer.aisec.cpg.graph.statements.ReturnStatement import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.ConstructExpression -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.MemberCallExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import de.fraunhofer.aisec.cpg.passes.astParent import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -285,17 +285,15 @@ open class DFAOrderEvaluator( private fun callUsesInterestingBase(node: CallExpression, eogPath: String): List { val allUsedBases = node.arguments - .map { arg -> (arg as? DeclaredReferenceExpression)?.refersTo } + .map { arg -> (arg as? Reference)?.refersTo } .filter { arg -> arg != null && consideredBases.contains(arg) } .toMutableList() if ( node is MemberCallExpression && - node.base is DeclaredReferenceExpression && - consideredBases.contains( - (node.base as DeclaredReferenceExpression).refersTo as Declaration - ) + node.base is Reference && + consideredBases.contains((node.base as Reference).refersTo as Declaration) ) { - allUsedBases.add((node.base as DeclaredReferenceExpression).refersTo) + allUsedBases.add((node.base as Reference).refersTo) } return allUsedBases.map { "$eogPath|${it?.name}.$it" } @@ -346,7 +344,7 @@ open class DFAOrderEvaluator( // the end. var base = getBaseOfNode(node) - if (base is DeclaredReferenceExpression && base.refersTo != null) { + if (base is Reference && base.refersTo != null) { base = base.refersTo } @@ -355,7 +353,7 @@ open class DFAOrderEvaluator( // the different paths of execution which both can use the same base. val prefixedBase = "$eogPath|${base.name}.$base" - if (base is ParamVariableDeclaration) { + if (base is ParameterDeclaration) { // The base was the parameter of the function? We have an inter-procedural flow! interproceduralFlows[prefixedBase] = true } @@ -393,7 +391,7 @@ open class DFAOrderEvaluator( var node: Node = list.first() // if the node refers to another node, return the node it refers to - (node as? DeclaredReferenceExpression)?.refersTo?.let { node = it } + (node as? Reference)?.refersTo?.let { node = it } return node } @@ -407,7 +405,7 @@ open class DFAOrderEvaluator( private fun Node.getSuitableDFGTarget(): Node? { return this.nextDFG .filter { - it is DeclaredReferenceExpression || + it is Reference || it is ReturnStatement || it is ConstructExpression || it is VariableDeclaration diff --git a/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/EvaluateExtensions.kt b/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/EvaluateExtensions.kt index 6487c872fb..ee820c6496 100644 --- a/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/EvaluateExtensions.kt +++ b/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/EvaluateExtensions.kt @@ -27,8 +27,8 @@ package de.fraunhofer.aisec.cpg.graph import de.fraunhofer.aisec.cpg.analysis.ValueEvaluator import de.fraunhofer.aisec.cpg.graph.declarations.Declaration -import de.fraunhofer.aisec.cpg.graph.statements.expressions.ArrayCreationExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.NewArrayExpression fun Expression.evaluate(evaluator: ValueEvaluator = ValueEvaluator()): Any? { return evaluator.evaluate(this) @@ -38,7 +38,7 @@ fun Declaration.evaluate(evaluator: ValueEvaluator = ValueEvaluator()): Any? { return evaluator.evaluate(this) } -val ArrayCreationExpression.capacity: Int +val NewArrayExpression.capacity: Int get() { return dimensions.first().evaluate() as Int } diff --git a/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/query/Query.kt b/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/query/Query.kt index 2b89f23d97..89aa74fa0b 100644 --- a/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/query/Query.kt +++ b/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/query/Query.kt @@ -359,12 +359,14 @@ fun allNonLiteralsFromFlowTo(from: Node, to: Node, allPaths: List>): it.any { it2 -> if (it2 is AssignmentHolder) { it2.assignments.any { assign -> - val prevMemberFrom = (from as? MemberExpression)?.prevDFG - val nextMemberTo = (assign.target as? MemberExpression)?.nextDFG + val prevMemberFromExpr = (from as? MemberExpression)?.prevDFG + val nextMemberToExpr = (assign.target as? MemberExpression)?.nextDFG assign.target == from || - prevMemberFrom != null && - nextMemberTo != null && - prevMemberFrom.any { it3 -> nextMemberTo.contains(it3) } + prevMemberFromExpr != null && + nextMemberToExpr != null && + prevMemberFromExpr.any { it3 -> + nextMemberToExpr.contains(it3) + } } } else { false diff --git a/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/query/README.md b/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/query/README.md index 9c25867dd7..e1a13f9a09 100644 --- a/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/query/README.md +++ b/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/query/README.md @@ -21,7 +21,7 @@ all (==> false) -------- Starting at CallExpression[name=memcpy,location=vulnerable.cpp(3:5-3:38),type=UNKNOWN,base=]: 5 > 11 (==> false) ------------------------ - sizeof(DeclaredReferenceExpression[DeclaredReferenceExpression[name=array,location=vulnerable.cpp(3:12-3:17),type=PointerType[name=char[]]],refersTo=VariableDeclaration[name=array,location=vulnerable.cpp(2:10-2:28),initializer=Literal[location=vulnerable.cpp(2:21-2:28),type=PointerType[name=char[]],value=hello]]]) (==> 5) + sizeof(Reference[Reference[name=array,location=vulnerable.cpp(3:12-3:17),type=PointerType[name=char[]]],refersTo=VariableDeclaration[name=array,location=vulnerable.cpp(2:10-2:28),initializer=Literal[location=vulnerable.cpp(2:21-2:28),type=PointerType[name=char[]],value=hello]]]) (==> 5) ---------------------------------------- ------------------------ sizeof(Literal[location=vulnerable.cpp(3:19-3:32),type=PointerType[name=char[]],value=Hello world]) (==> 11) 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 fb925ed067..ac3ac136c0 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 @@ -30,10 +30,10 @@ import de.fraunhofer.aisec.cpg.frontends.TestHandler import de.fraunhofer.aisec.cpg.frontends.TestLanguageFrontend import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement import de.fraunhofer.aisec.cpg.graph.statements.DeclarationStatement import de.fraunhofer.aisec.cpg.graph.statements.ForStatement import de.fraunhofer.aisec.cpg.graph.statements.expressions.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 @@ -211,8 +211,7 @@ class MultiValueEvaluatorTest { assertNotNull(forLoop) val evaluator = MultiValueEvaluator() - val iVarList = - ((forLoop.statement as CompoundStatement).statements[0] as AssignExpression).rhs + val iVarList = ((forLoop.statement as Block).statements[0] as AssignExpression).rhs assertEquals(1, iVarList.size) val iVar = iVarList.first() val value = evaluator.evaluate(iVar) as ConcreteNumberSet @@ -228,7 +227,7 @@ class MultiValueEvaluatorTest { val three = newLiteral(3, primitiveType("int")) val four = newLiteral(4, primitiveType("int")) - val ref = newDeclaredReferenceExpression("a") + val ref = newReference("a") ref.prevDFG = mutableSetOf(three, four) val neg = newUnaryOperator("-", false, true) 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 2f470c3695..0c2601be82 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 @@ -32,12 +32,12 @@ 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.invoke -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement import de.fraunhofer.aisec.cpg.graph.statements.DeclarationStatement import de.fraunhofer.aisec.cpg.graph.statements.ForStatement -import de.fraunhofer.aisec.cpg.graph.statements.expressions.ArraySubscriptionExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.AssignExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.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 kotlin.test.Test import kotlin.test.assertEquals @@ -107,8 +107,8 @@ class SizeEvaluatorTest { assertNotNull(forLoop) val subscriptExpr = - ((forLoop.statement as CompoundStatement).statements[0] as AssignExpression).lhs< - ArraySubscriptionExpression + ((forLoop.statement as Block).statements[0] as AssignExpression).lhs< + SubscriptExpression >() value = evaluator.evaluate(subscriptExpr) as Int 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 d53b8ffca0..90aa4825a5 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 @@ -36,8 +36,9 @@ import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration 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.DeclaredReferenceExpression +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 @@ -103,10 +104,10 @@ class ComplexDFAOrderEvaluationTest { val consideredDecl = mutableSetOf(p1Decl.declarations[0]) val nodesToOp = mutableMapOf>() - nodesToOp[(functionOk.body as CompoundStatement).statements[1]] = setOf("create()") - nodesToOp[(functionOk.body as CompoundStatement).statements[2]] = setOf("init()") - nodesToOp[(functionOk.body as CompoundStatement).statements[3]] = setOf("start()") - nodesToOp[(functionOk.body as CompoundStatement).statements[4]] = setOf("finish()") + nodesToOp[(functionOk.body as Block).statements[1]] = setOf("create()") + nodesToOp[(functionOk.body as Block).statements[2]] = setOf("init()") + nodesToOp[(functionOk.body as Block).statements[3]] = setOf("start()") + nodesToOp[(functionOk.body as Block).statements[4]] = setOf("finish()") val orderEvaluator = DFAOrderEvaluator(dfa, consideredDecl, nodesToOp) val everythingOk = orderEvaluator.evaluateOrder(p1Decl) @@ -126,11 +127,11 @@ class ComplexDFAOrderEvaluationTest { val consideredDecl = mutableSetOf(p1Decl.declarations[0]) val nodesToOp = mutableMapOf>() - nodesToOp[(functionOk.body as CompoundStatement).statements[1]] = setOf("create()") - nodesToOp[(functionOk.body as CompoundStatement).statements[2]] = setOf("init()") - nodesToOp[(functionOk.body as CompoundStatement).statements[3]] = setOf("start()") - nodesToOp[(functionOk.body as CompoundStatement).statements[4]] = setOf("process()") - nodesToOp[(functionOk.body as CompoundStatement).statements[5]] = setOf("finish()") + nodesToOp[(functionOk.body as Block).statements[1]] = setOf("create()") + nodesToOp[(functionOk.body as Block).statements[2]] = setOf("init()") + nodesToOp[(functionOk.body as Block).statements[3]] = setOf("start()") + nodesToOp[(functionOk.body as Block).statements[4]] = setOf("process()") + nodesToOp[(functionOk.body as Block).statements[5]] = setOf("finish()") val orderEvaluator = DFAOrderEvaluator(dfa, consideredDecl, nodesToOp) val everythingOk = orderEvaluator.evaluateOrder(p1Decl) @@ -150,12 +151,12 @@ class ComplexDFAOrderEvaluationTest { val consideredDecl = mutableSetOf(p1Decl.declarations[0]) val nodesToOp = mutableMapOf>() - nodesToOp[(functionOk.body as CompoundStatement).statements[1]] = setOf("create()") - nodesToOp[(functionOk.body as CompoundStatement).statements[2]] = setOf("init()") - nodesToOp[(functionOk.body as CompoundStatement).statements[3]] = setOf("start()") - nodesToOp[(functionOk.body as CompoundStatement).statements[4]] = setOf("process()") - nodesToOp[(functionOk.body as CompoundStatement).statements[5]] = setOf("finish()") - nodesToOp[(functionOk.body as CompoundStatement).statements[6]] = setOf("reset()") + nodesToOp[(functionOk.body as Block).statements[1]] = setOf("create()") + nodesToOp[(functionOk.body as Block).statements[2]] = setOf("init()") + nodesToOp[(functionOk.body as Block).statements[3]] = setOf("start()") + nodesToOp[(functionOk.body as Block).statements[4]] = setOf("process()") + nodesToOp[(functionOk.body as Block).statements[5]] = setOf("finish()") + nodesToOp[(functionOk.body as Block).statements[6]] = setOf("reset()") val orderEvaluator = DFAOrderEvaluator(dfa, consideredDecl, nodesToOp) val everythingOk = orderEvaluator.evaluateOrder(p1Decl) @@ -175,14 +176,14 @@ class ComplexDFAOrderEvaluationTest { val consideredDecl = mutableSetOf(p2Decl.declarations[0]) val nodesToOp = mutableMapOf>() - nodesToOp[(functionOk.body as CompoundStatement).statements[1]] = setOf("create()") - nodesToOp[(functionOk.body as CompoundStatement).statements[2]] = setOf("init()") - nodesToOp[(functionOk.body as CompoundStatement).statements[3]] = setOf("start()") - nodesToOp[(functionOk.body as CompoundStatement).statements[4]] = setOf("process()") - nodesToOp[(functionOk.body as CompoundStatement).statements[5]] = setOf("process()") - nodesToOp[(functionOk.body as CompoundStatement).statements[6]] = setOf("process()") - nodesToOp[(functionOk.body as CompoundStatement).statements[7]] = setOf("process()") - nodesToOp[(functionOk.body as CompoundStatement).statements[8]] = setOf("finish()") + nodesToOp[(functionOk.body as Block).statements[1]] = setOf("create()") + nodesToOp[(functionOk.body as Block).statements[2]] = setOf("init()") + nodesToOp[(functionOk.body as Block).statements[3]] = setOf("start()") + nodesToOp[(functionOk.body as Block).statements[4]] = setOf("process()") + nodesToOp[(functionOk.body as Block).statements[5]] = setOf("process()") + nodesToOp[(functionOk.body as Block).statements[6]] = setOf("process()") + nodesToOp[(functionOk.body as Block).statements[7]] = setOf("process()") + nodesToOp[(functionOk.body as Block).statements[8]] = setOf("finish()") val orderEvaluator = DFAOrderEvaluator(dfa, consideredDecl, nodesToOp) val everythingOk = orderEvaluator.evaluateOrder(p2Decl) @@ -202,14 +203,14 @@ class ComplexDFAOrderEvaluationTest { val consideredDecl = mutableSetOf(p3Decl.declarations[0]) val nodesToOp = mutableMapOf>() - nodesToOp[(functionOk.body as CompoundStatement).statements[1]] = setOf("create()") - nodesToOp[(functionOk.body as CompoundStatement).statements[2]] = setOf("init()") - nodesToOp[(functionOk.body as CompoundStatement).statements[3]] = setOf("start()") - nodesToOp[(functionOk.body as CompoundStatement).statements[4]] = setOf("process()") - nodesToOp[(functionOk.body as CompoundStatement).statements[5]] = setOf("finish()") - nodesToOp[(functionOk.body as CompoundStatement).statements[6]] = setOf("start()") - nodesToOp[(functionOk.body as CompoundStatement).statements[7]] = setOf("process()") - nodesToOp[(functionOk.body as CompoundStatement).statements[8]] = setOf("finish()") + nodesToOp[(functionOk.body as Block).statements[1]] = setOf("create()") + nodesToOp[(functionOk.body as Block).statements[2]] = setOf("init()") + nodesToOp[(functionOk.body as Block).statements[3]] = setOf("start()") + nodesToOp[(functionOk.body as Block).statements[4]] = setOf("process()") + nodesToOp[(functionOk.body as Block).statements[5]] = setOf("finish()") + nodesToOp[(functionOk.body as Block).statements[6]] = setOf("start()") + nodesToOp[(functionOk.body as Block).statements[7]] = setOf("process()") + nodesToOp[(functionOk.body as Block).statements[8]] = setOf("finish()") val orderEvaluator = DFAOrderEvaluator(dfa, consideredDecl, nodesToOp) val everythingOk = orderEvaluator.evaluateOrder(p3Decl) @@ -229,15 +230,15 @@ class ComplexDFAOrderEvaluationTest { val consideredDecl = mutableSetOf(p3Decl.declarations[0]) val nodes = mutableMapOf>() - nodes[(functionOk.body as CompoundStatement).statements[1]] = setOf("create()") - nodes[(functionOk.body as CompoundStatement).statements[2]] = setOf("init()") - nodes[(functionOk.body as CompoundStatement).statements[3]] = setOf("start()") - nodes[(functionOk.body as CompoundStatement).statements[4]] = setOf("process()") - nodes[(functionOk.body as CompoundStatement).statements[5]] = setOf("finish()") - nodes[(functionOk.body as CompoundStatement).statements[6]] = setOf("start()") - nodes[(functionOk.body as CompoundStatement).statements[7]] = setOf("process()") - nodes[(functionOk.body as CompoundStatement).statements[8]] = setOf("finish()") - nodes[(functionOk.body as CompoundStatement).statements[9]] = setOf("reset()") + nodes[(functionOk.body as Block).statements[1]] = setOf("create()") + nodes[(functionOk.body as Block).statements[2]] = setOf("init()") + nodes[(functionOk.body as Block).statements[3]] = setOf("start()") + nodes[(functionOk.body as Block).statements[4]] = setOf("process()") + nodes[(functionOk.body as Block).statements[5]] = setOf("finish()") + nodes[(functionOk.body as Block).statements[6]] = setOf("start()") + nodes[(functionOk.body as Block).statements[7]] = setOf("process()") + nodes[(functionOk.body as Block).statements[8]] = setOf("finish()") + nodes[(functionOk.body as Block).statements[9]] = setOf("reset()") val orderEvaluator = DFAOrderEvaluator(dfa, consideredDecl, nodes) val everythingOk = orderEvaluator.evaluateOrder(p3Decl) @@ -257,10 +258,10 @@ class ComplexDFAOrderEvaluationTest { val consideredDecl = mutableSetOf(p5Decl.declarations[0]) val nodesToOp = mutableMapOf>() - nodesToOp[(functionOk.body as CompoundStatement).statements[1]] = setOf("init()") - nodesToOp[(functionOk.body as CompoundStatement).statements[2]] = setOf("start()") - nodesToOp[(functionOk.body as CompoundStatement).statements[3]] = setOf("process()") - nodesToOp[(functionOk.body as CompoundStatement).statements[4]] = setOf("finish()") + nodesToOp[(functionOk.body as Block).statements[1]] = setOf("init()") + nodesToOp[(functionOk.body as Block).statements[2]] = setOf("start()") + nodesToOp[(functionOk.body as Block).statements[3]] = setOf("process()") + nodesToOp[(functionOk.body as Block).statements[4]] = setOf("finish()") val orderEvaluator = DFAOrderEvaluator(dfa, consideredDecl, nodesToOp) val everythingOk = orderEvaluator.evaluateOrder(p5Decl) @@ -280,18 +281,17 @@ class ComplexDFAOrderEvaluationTest { val consideredDecl = mutableSetOf(p6Decl.declarations[0]) val nodesToOp = mutableMapOf>() - nodesToOp[(functionOk.body as CompoundStatement).statements[1]] = setOf("create()") - nodesToOp[(functionOk.body as CompoundStatement).statements[2]] = setOf("init()") + nodesToOp[(functionOk.body as Block).statements[1]] = setOf("create()") + nodesToOp[(functionOk.body as Block).statements[2]] = setOf("init()") val thenBranch = - ((functionOk.body as CompoundStatement).statements[3] as? IfStatement)?.thenStatement - as? CompoundStatement + ((functionOk.body as Block).statements[3] as? IfStatement)?.thenStatement as? Block assertNotNull(thenBranch) nodesToOp[thenBranch.statements[0]] = setOf("start()") nodesToOp[thenBranch.statements[1]] = setOf("process()") nodesToOp[thenBranch.statements[2]] = setOf("finish()") - nodesToOp[(functionOk.body as CompoundStatement).statements[4]] = setOf("reset()") + nodesToOp[(functionOk.body as Block).statements[4]] = setOf("reset()") val orderEvaluator = DFAOrderEvaluator(dfa, consideredDecl, nodesToOp) val everythingOk = orderEvaluator.evaluateOrder(p6Decl) @@ -313,8 +313,7 @@ class ComplexDFAOrderEvaluationTest { val nodesToOp = mutableMapOf>() val loopBody = - ((functionOk.body as CompoundStatement).statements[1] as? WhileStatement)?.statement - as? CompoundStatement + ((functionOk.body as Block).statements[1] as? WhileStatement)?.statement as? Block assertNotNull(loopBody) nodesToOp[loopBody.statements[0]] = setOf("create()") nodesToOp[loopBody.statements[1]] = setOf("init()") @@ -322,7 +321,7 @@ class ComplexDFAOrderEvaluationTest { nodesToOp[loopBody.statements[3]] = setOf("process()") nodesToOp[loopBody.statements[4]] = setOf("finish()") - nodesToOp[(functionOk.body as CompoundStatement).statements[2]] = setOf("reset()") + nodesToOp[(functionOk.body as Block).statements[2]] = setOf("reset()") val orderEvaluator = DFAOrderEvaluator(dfa, consideredDecl, nodesToOp) val everythingOk = orderEvaluator.evaluateOrder(p6Decl) @@ -343,17 +342,16 @@ class ComplexDFAOrderEvaluationTest { val consideredDecl = mutableSetOf(p7Decl.declarations[0]) val nodesToOp = mutableMapOf>() - nodesToOp[(functionOk.body as CompoundStatement).statements[1]] = setOf("create()") - nodesToOp[(functionOk.body as CompoundStatement).statements[2]] = setOf("init()") + nodesToOp[(functionOk.body as Block).statements[1]] = setOf("create()") + nodesToOp[(functionOk.body as Block).statements[2]] = setOf("init()") val loopBody = - ((functionOk.body as CompoundStatement).statements[3] as? WhileStatement)?.statement - as? CompoundStatement + ((functionOk.body as Block).statements[3] as? WhileStatement)?.statement as? Block assertNotNull(loopBody) nodesToOp[loopBody.statements[0]] = setOf("start()") nodesToOp[loopBody.statements[1]] = setOf("process()") nodesToOp[loopBody.statements[2]] = setOf("finish()") - nodesToOp[(functionOk.body as CompoundStatement).statements[4]] = setOf("reset()") + nodesToOp[(functionOk.body as Block).statements[4]] = setOf("reset()") val orderEvaluator = DFAOrderEvaluator(dfa, consideredDecl, nodesToOp) val everythingOk = orderEvaluator.evaluateOrder(p7Decl) @@ -373,17 +371,16 @@ class ComplexDFAOrderEvaluationTest { val consideredDecl = mutableSetOf(p7Decl.declarations[0]) val nodesToOp = mutableMapOf>() - nodesToOp[(functionOk.body as CompoundStatement).statements[1]] = setOf("create()") - nodesToOp[(functionOk.body as CompoundStatement).statements[2]] = setOf("init()") + nodesToOp[(functionOk.body as Block).statements[1]] = setOf("create()") + nodesToOp[(functionOk.body as Block).statements[2]] = setOf("init()") val loopBody = - ((functionOk.body as CompoundStatement).statements[3] as? WhileStatement)?.statement - as? CompoundStatement + ((functionOk.body as Block).statements[3] as? WhileStatement)?.statement as? Block assertNotNull(loopBody) nodesToOp[loopBody.statements[0]] = setOf("start()") nodesToOp[loopBody.statements[1]] = setOf("process()") nodesToOp[loopBody.statements[2]] = setOf("finish()") - nodesToOp[(functionOk.body as CompoundStatement).statements[4]] = setOf("reset()") + nodesToOp[(functionOk.body as Block).statements[4]] = setOf("reset()") val orderEvaluator = DFAOrderEvaluator(dfa, consideredDecl, nodesToOp) val everythingOk = orderEvaluator.evaluateOrder(p7Decl) @@ -403,20 +400,19 @@ class ComplexDFAOrderEvaluationTest { val consideredDecl = mutableSetOf(p8Decl.declarations[0]) val nodesToOp = mutableMapOf>() - nodesToOp[(functionOk.body as CompoundStatement).statements[1]] = setOf("create()") - nodesToOp[(functionOk.body as CompoundStatement).statements[2]] = setOf("init()") - nodesToOp[(functionOk.body as CompoundStatement).statements[3]] = setOf("start()") - nodesToOp[(functionOk.body as CompoundStatement).statements[4]] = setOf("process()") - nodesToOp[(functionOk.body as CompoundStatement).statements[5]] = setOf("finish()") + nodesToOp[(functionOk.body as Block).statements[1]] = setOf("create()") + nodesToOp[(functionOk.body as Block).statements[2]] = setOf("init()") + nodesToOp[(functionOk.body as Block).statements[3]] = setOf("start()") + nodesToOp[(functionOk.body as Block).statements[4]] = setOf("process()") + nodesToOp[(functionOk.body as Block).statements[5]] = setOf("finish()") val loopBody = - ((functionOk.body as CompoundStatement).statements[6] as? WhileStatement)?.statement - as? CompoundStatement + ((functionOk.body as Block).statements[6] as? WhileStatement)?.statement as? Block assertNotNull(loopBody) nodesToOp[loopBody.statements[0]] = setOf("start()") nodesToOp[loopBody.statements[1]] = setOf("process()") nodesToOp[loopBody.statements[2]] = setOf("finish()") - nodesToOp[(functionOk.body as CompoundStatement).statements[7]] = setOf("reset()") + nodesToOp[(functionOk.body as Block).statements[7]] = setOf("reset()") val orderEvaluator = DFAOrderEvaluator(dfa, consideredDecl, nodesToOp) val everythingOk = orderEvaluator.evaluateOrder(p8Decl) @@ -436,17 +432,15 @@ class ComplexDFAOrderEvaluationTest { val consideredDecl = mutableSetOf(p6Decl.declarations[0]) val nodesToOp = mutableMapOf>() - nodesToOp[(functionOk.body as CompoundStatement).statements[1]] = setOf("create()") - nodesToOp[(functionOk.body as CompoundStatement).statements[2]] = setOf("init()") - val loopBody = - ((functionOk.body as CompoundStatement).statements[3] as DoStatement).statement - as? CompoundStatement + nodesToOp[(functionOk.body as Block).statements[1]] = setOf("create()") + nodesToOp[(functionOk.body as Block).statements[2]] = setOf("init()") + val loopBody = ((functionOk.body as Block).statements[3] as DoStatement).statement as? Block assertNotNull(loopBody) nodesToOp[loopBody.statements[0]] = setOf("start()") nodesToOp[loopBody.statements[1]] = setOf("process()") nodesToOp[loopBody.statements[2]] = setOf("finish()") - nodesToOp[(functionOk.body as CompoundStatement).statements[4]] = setOf("reset()") + nodesToOp[(functionOk.body as Block).statements[4]] = setOf("reset()") val orderEvaluator = DFAOrderEvaluator(dfa, consideredDecl, nodesToOp) val everythingOk = orderEvaluator.evaluateOrder(p6Decl) @@ -466,9 +460,9 @@ class ComplexDFAOrderEvaluationTest { val consideredDecl = mutableSetOf(p1Decl.declarations[0]) val nodesToOp = mutableMapOf>() - nodesToOp[(functionOk.body as CompoundStatement).statements[1]] = setOf("create()") - nodesToOp[(functionOk.body as CompoundStatement).statements[3]] = setOf("start()") - nodesToOp[(functionOk.body as CompoundStatement).statements[4]] = setOf("finish()") + nodesToOp[(functionOk.body as Block).statements[1]] = setOf("create()") + nodesToOp[(functionOk.body as Block).statements[3]] = setOf("start()") + nodesToOp[(functionOk.body as Block).statements[4]] = setOf("finish()") val afterInterprocNodes = mutableListOf() val withoutInterprocNodes = mutableListOf() @@ -486,7 +480,7 @@ class ComplexDFAOrderEvaluationTest { assertFalse(everythingOk, "Expected incorrect order") assertContains( afterInterprocNodes, - (functionOk.body as CompoundStatement).statements[3], + (functionOk.body as Block).statements[3], "Expected start() node in list of unknown nodes" ) assertTrue(withoutInterprocNodes.isEmpty(), "No node should be clearly violating the rule") @@ -504,9 +498,9 @@ class ComplexDFAOrderEvaluationTest { val consideredDecl = mutableSetOf(p1Decl) val nodesToOp = mutableMapOf>() - nodesToOp[(functionOk.body as CompoundStatement).statements[0]] = setOf("init()") - nodesToOp[(functionOk.body as CompoundStatement).statements[1]] = setOf("start()") - nodesToOp[(functionOk.body as CompoundStatement).statements[2]] = setOf("finish()") + nodesToOp[(functionOk.body as Block).statements[0]] = setOf("init()") + nodesToOp[(functionOk.body as Block).statements[1]] = setOf("start()") + nodesToOp[(functionOk.body as Block).statements[2]] = setOf("finish()") val afterInterprocNodes = mutableListOf() val withoutInterprocNodes = mutableListOf() @@ -521,13 +515,12 @@ class ComplexDFAOrderEvaluationTest { ) // We cannot use p1Decl as start of the analysis because it has no nextEOG edges. Instead, // we want to start with the first instruction of the function. - val everythingOk = - orderEvaluator.evaluateOrder((functionOk.body as CompoundStatement).statements[0]) + val everythingOk = orderEvaluator.evaluateOrder((functionOk.body as Block).statements[0]) assertFalse(everythingOk, "Expected incorrect order") assertContains( afterInterprocNodes, - (functionOk.body as CompoundStatement).statements[0], + (functionOk.body as Block).statements[0], "Expected init() node in list of unknown nodes" ) assertTrue(withoutInterprocNodes.isEmpty(), "No node should be clearly violating the rule") @@ -545,9 +538,9 @@ class ComplexDFAOrderEvaluationTest { val consideredDecl = mutableSetOf(p1Decl.declarations[0]) val nodesToOp = mutableMapOf>() - nodesToOp[(functionOk.body as CompoundStatement).statements[1]] = setOf("create()") - nodesToOp[(functionOk.body as CompoundStatement).statements[2]] = setOf("init()") - nodesToOp[(functionOk.body as CompoundStatement).statements[3]] = setOf("start()") + nodesToOp[(functionOk.body as Block).statements[1]] = setOf("create()") + nodesToOp[(functionOk.body as Block).statements[2]] = setOf("init()") + nodesToOp[(functionOk.body as Block).statements[3]] = setOf("start()") val possibleInterprocFailures = mutableListOf() val withoutInterprocNodes = mutableListOf() @@ -565,7 +558,7 @@ class ComplexDFAOrderEvaluationTest { assertFalse(everythingOk, "Expected incorrect order") assertContains( possibleInterprocFailures, - (functionOk.body as CompoundStatement).statements[3], + (functionOk.body as Block).statements[3], "Expected start() node in list of unknown nodes" ) assertTrue(withoutInterprocNodes.isEmpty(), "No node should be clearly violating the rule") @@ -583,9 +576,9 @@ class ComplexDFAOrderEvaluationTest { val consideredDecl = mutableSetOf(p1Decl.declarations[0]) val nodesToOp = mutableMapOf>() - nodesToOp[(functionOk.body as CompoundStatement).statements[1]] = setOf("create()") - nodesToOp[(functionOk.body as CompoundStatement).statements[3]] = setOf("start()") - nodesToOp[(functionOk.body as CompoundStatement).statements[4]] = setOf("finish()") + nodesToOp[(functionOk.body as Block).statements[1]] = setOf("create()") + nodesToOp[(functionOk.body as Block).statements[3]] = setOf("start()") + nodesToOp[(functionOk.body as Block).statements[4]] = setOf("finish()") val afterInterprocNodes = mutableListOf() val withoutInterprocNodes = mutableListOf() @@ -603,12 +596,12 @@ class ComplexDFAOrderEvaluationTest { assertFalse(everythingOk, "Expected incorrect order") assertContains( afterInterprocNodes, - (functionOk.body as CompoundStatement).statements[3], + (functionOk.body as Block).statements[3], "Expected start() node in list of unknown nodes" ) assertContains( withoutInterprocNodes, - (functionOk.body as CompoundStatement).statements[3], + (functionOk.body as Block).statements[3], "Expected start() node in list of unknown nodes" ) } @@ -625,9 +618,9 @@ class ComplexDFAOrderEvaluationTest { val consideredDecl = mutableSetOf(p1Decl.declarations[0]) val nodesToOp = mutableMapOf>() - nodesToOp[(functionOk.body as CompoundStatement).statements[2]] = setOf("create()") - nodesToOp[(functionOk.body as CompoundStatement).statements[5]] = setOf("start()") - nodesToOp[(functionOk.body as CompoundStatement).statements[6]] = setOf("finish()") + nodesToOp[(functionOk.body as Block).statements[2]] = setOf("create()") + nodesToOp[(functionOk.body as Block).statements[5]] = setOf("start()") + nodesToOp[(functionOk.body as Block).statements[6]] = setOf("finish()") val afterInterprocNodes = mutableListOf() val withoutInterprocNodes = mutableListOf() @@ -646,7 +639,7 @@ class ComplexDFAOrderEvaluationTest { assertTrue(afterInterprocNodes.isEmpty(), "All nodes clearly violate the rule") assertContains( withoutInterprocNodes, - (functionOk.body as CompoundStatement).statements[5], + (functionOk.body as Block).statements[5], "Expected start() node in list of unknown nodes" ) } @@ -693,14 +686,14 @@ class ComplexDFAOrderEvaluationTest { ) { val lastNode = fsm.executionTrace.last().cpgNode as CallExpression var baseOfLastNode = getBaseOfNode(lastNode) - if (baseOfLastNode is DeclaredReferenceExpression) { + if (baseOfLastNode is Reference) { baseOfLastNode = baseOfLastNode.refersTo } val returnStatements = lastNode.followNextEOG { edge -> edge.end is ReturnStatement && - ((edge.end as ReturnStatement).returnValue as? DeclaredReferenceExpression) - ?.refersTo == baseOfLastNode + ((edge.end as ReturnStatement).returnValue as? Reference)?.refersTo == + baseOfLastNode } if (returnStatements?.isNotEmpty() == true) { // There was a return statement returning the respective variable. The flow of 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 3f79a849d7..4fffc76f4f 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 @@ -32,9 +32,9 @@ 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.* -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement 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 @@ -90,8 +90,8 @@ class SimpleDFAOrderEvaluationTest { val consideredDecl = mutableSetOf(p4Decl.declarations[0]) val nodesToOp = mutableMapOf>() - nodesToOp[(functionOk.body as CompoundStatement).statements[1]] = setOf("start()") - nodesToOp[(functionOk.body as CompoundStatement).statements[2]] = setOf("finish()") + nodesToOp[(functionOk.body as Block).statements[1]] = setOf("start()") + nodesToOp[(functionOk.body as Block).statements[2]] = setOf("finish()") val orderEvaluator = DFAOrderEvaluator(dfa, consideredDecl, nodesToOp) val everythingOk = orderEvaluator.evaluateOrder(p4Decl) @@ -111,9 +111,9 @@ class SimpleDFAOrderEvaluationTest { val consideredDecl = mutableSetOf(p4Decl.declarations[0]) val nodesToOp = mutableMapOf>() - nodesToOp[(functionOk.body as CompoundStatement).statements[1]] = setOf("start()") + nodesToOp[(functionOk.body as Block).statements[1]] = setOf("start()") // We do not model the call to foo() because it does not exist in our model. - nodesToOp[(functionOk.body as CompoundStatement).statements[3]] = setOf("finish()") + nodesToOp[(functionOk.body as Block).statements[3]] = setOf("finish()") val orderEvaluator = DFAOrderEvaluator(dfa, consideredDecl, nodesToOp) val everythingOk = orderEvaluator.evaluateOrder(p4Decl) @@ -135,18 +135,16 @@ class SimpleDFAOrderEvaluationTest { val nodesToOp = mutableMapOf>() // We model the calls to start() for the then and the else branch val thenBranch = - ((functionOk.body as CompoundStatement).statements[2] as? IfStatement)?.thenStatement - as? CompoundStatement + ((functionOk.body as Block).statements[2] as? IfStatement)?.thenStatement as? Block assertNotNull(thenBranch) nodesToOp[thenBranch.statements[0]] = setOf("start()") val elseBranch = - ((functionOk.body as CompoundStatement).statements[2] as? IfStatement)?.elseStatement - as? CompoundStatement + ((functionOk.body as Block).statements[2] as? IfStatement)?.elseStatement as? Block assertNotNull(elseBranch) nodesToOp[elseBranch.statements[0]] = setOf("start()") // We do not model the call to foo() because it does not exist in our model. - nodesToOp[(functionOk.body as CompoundStatement).statements[3]] = setOf("finish()") + nodesToOp[(functionOk.body as Block).statements[3]] = setOf("finish()") val orderEvaluator = DFAOrderEvaluator(dfa, consideredDecl, nodesToOp) val everythingOk = orderEvaluator.evaluateOrder(p4Decl) @@ -166,11 +164,11 @@ class SimpleDFAOrderEvaluationTest { val consideredBases = mutableSetOf(pDecl.declarations[0]) val nodesToOp = mutableMapOf>() - nodesToOp[(functionOk.body as CompoundStatement).statements[1]] = setOf("set_key()") - nodesToOp[(functionOk.body as CompoundStatement).statements[2]] = setOf("start()") - nodesToOp[(functionOk.body as CompoundStatement).statements[3]] = setOf("finish()") + nodesToOp[(functionOk.body as Block).statements[1]] = setOf("set_key()") + nodesToOp[(functionOk.body as Block).statements[2]] = setOf("start()") + nodesToOp[(functionOk.body as Block).statements[3]] = setOf("finish()") // We do not model the call to foo() because it does not exist in our model. - nodesToOp[(functionOk.body as CompoundStatement).statements[5]] = setOf("set_key()") + nodesToOp[(functionOk.body as Block).statements[5]] = setOf("set_key()") val orderEvaluator = DFAOrderEvaluator(dfa, consideredBases, nodesToOp) val everythingOk = orderEvaluator.evaluateOrder(pDecl) @@ -190,7 +188,7 @@ class SimpleDFAOrderEvaluationTest { val consideredBases = mutableSetOf(p2Decl.declarations[0]) val nodesToOp = mutableMapOf>() - nodesToOp[(functionOk.body as CompoundStatement).statements[1]] = setOf("start()") + nodesToOp[(functionOk.body as Block).statements[1]] = setOf("start()") val orderEvaluator = DFAOrderEvaluator(dfa, consideredBases, nodesToOp) val everythingOk = orderEvaluator.evaluateOrder(p2Decl) @@ -211,11 +209,10 @@ class SimpleDFAOrderEvaluationTest { val nodesToOp = mutableMapOf>() val thenBranch = - ((functionOk.body as CompoundStatement).statements[1] as? IfStatement)?.thenStatement - as? CompoundStatement + ((functionOk.body as Block).statements[1] as? IfStatement)?.thenStatement as? Block assertNotNull(thenBranch) nodesToOp[thenBranch.statements[0]] = setOf("start()") - nodesToOp[(functionOk.body as CompoundStatement).statements[2]] = setOf("finish()") + nodesToOp[(functionOk.body as Block).statements[2]] = setOf("finish()") val orderEvaluator = DFAOrderEvaluator(dfa, consideredDecl, nodesToOp) val everythingOk = orderEvaluator.evaluateOrder(p3Decl) @@ -236,13 +233,12 @@ class SimpleDFAOrderEvaluationTest { val nodesToOp = mutableMapOf>() val thenBranch = - ((functionOk.body as CompoundStatement).statements[1] as? IfStatement)?.thenStatement - as? CompoundStatement + ((functionOk.body as Block).statements[1] as? IfStatement)?.thenStatement as? Block assertNotNull(thenBranch) nodesToOp[thenBranch.statements[0]] = setOf("start()") nodesToOp[thenBranch.statements[1]] = setOf("finish()") - nodesToOp[(functionOk.body as CompoundStatement).statements[2]] = setOf("start()") - nodesToOp[(functionOk.body as CompoundStatement).statements[4]] = setOf("finish()") + nodesToOp[(functionOk.body as Block).statements[2]] = setOf("start()") + nodesToOp[(functionOk.body as Block).statements[4]] = 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 7d26b62d7e..1fa67f2282 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 @@ -86,7 +86,7 @@ class UnreachableEOGPassTest { val incOp = thenDecl.end.nextEOGEdges[0] assertFalse(incOp.getProperty(Properties.UNREACHABLE) as Boolean) assertEquals(1, incOp.end.nextEOGEdges.size) - // The compoundStmt + // The block val thenCompound = incOp.end.nextEOGEdges[0] assertFalse(thenCompound.getProperty(Properties.UNREACHABLE) as Boolean) assertEquals(1, thenCompound.end.nextEOGEdges.size) @@ -103,7 +103,7 @@ class UnreachableEOGPassTest { val decOp = elseDecl.end.nextEOGEdges[0] assertTrue(decOp.getProperty(Properties.UNREACHABLE) as Boolean) assertEquals(1, decOp.end.nextEOGEdges.size) - // The compoundStmt + // The block val elseCompound = decOp.end.nextEOGEdges[0] assertTrue(elseCompound.getProperty(Properties.UNREACHABLE) as Boolean) assertEquals(1, elseCompound.end.nextEOGEdges.size) 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 0a70fa2e8d..6cccf1d340 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 @@ -138,8 +138,7 @@ class QueryTest { val queryTreeResult = result.all({ it.name.localName == "free" }) { outer -> !executionPath(outer) { - (it as? DeclaredReferenceExpression)?.refersTo == - (outer.arguments[0] as? DeclaredReferenceExpression)?.refersTo + (it as? Reference)?.refersTo == (outer.arguments[0] as? Reference)?.refersTo } .value } @@ -152,8 +151,8 @@ class QueryTest { { outer -> not( executionPath(outer) { - (it as? DeclaredReferenceExpression)?.refersTo == - (outer.arguments[0] as? DeclaredReferenceExpression)?.refersTo + (it as? Reference)?.refersTo == + (outer.arguments[0] as? Reference)?.refersTo } ) } @@ -178,10 +177,8 @@ class QueryTest { result.all({ it.name.localName == "free" }) { outer -> !executionPath(outer) { (it as? CallExpression)?.name?.localName == "free" && - ((it as? CallExpression)?.arguments?.getOrNull(0) - as? DeclaredReferenceExpression) - ?.refersTo == - (outer.arguments[0] as? DeclaredReferenceExpression)?.refersTo + ((it as? CallExpression)?.arguments?.getOrNull(0) as? Reference) + ?.refersTo == (outer.arguments[0] as? Reference)?.refersTo } .value } @@ -195,10 +192,8 @@ class QueryTest { not( executionPath(outer) { (it as? CallExpression)?.name?.localName == "free" && - ((it as? CallExpression)?.arguments?.getOrNull(0) - as? DeclaredReferenceExpression) - ?.refersTo == - (outer.arguments[0] as? DeclaredReferenceExpression)?.refersTo + ((it as? CallExpression)?.arguments?.getOrNull(0) as? Reference) + ?.refersTo == (outer.arguments[0] as? Reference)?.refersTo } ) } @@ -494,7 +489,7 @@ class QueryTest { val result = analyzer.analyze().get() val queryTreeResult = - result.all( + result.all( mustSatisfy = { max(it.subscriptExpression) < min(it.arraySize) && min(it.subscriptExpression) >= 0 @@ -503,7 +498,7 @@ class QueryTest { assertFalse(queryTreeResult.first) val queryTreeResult2 = - result.allExtended( + result.allExtended( mustSatisfy = { (max(it.subscriptExpression) lt min(it.arraySize)) and (min(it.subscriptExpression) ge 0) @@ -526,7 +521,7 @@ class QueryTest { val result = analyzer.analyze().get() val queryTreeResult = - result.exists( + result.exists( mustSatisfy = { max(it.subscriptExpression) >= min(it.arraySize) || min(it.subscriptExpression) < 0 @@ -535,7 +530,7 @@ class QueryTest { assertTrue(queryTreeResult.first) val queryTreeResult2 = - result.existsExtended( + result.existsExtended( mustSatisfy = { (it.subscriptExpression.max ge it.arraySize.min) or (it.subscriptExpression.min lt 0) @@ -559,7 +554,7 @@ class QueryTest { val result = analyzer.analyze().get() val queryTreeResult = - result.all( + result.all( mustSatisfy = { max(it.subscriptExpression) < min(it.arraySize) && min(it.subscriptExpression) >= 0 @@ -568,7 +563,7 @@ class QueryTest { assertFalse(queryTreeResult.first) val queryTreeResult2 = - result.allExtended( + result.allExtended( mustSatisfy = { (max(it.subscriptExpression) lt min(it.arraySize)) and (min(it.subscriptExpression) ge 0) @@ -592,36 +587,28 @@ class QueryTest { val result = analyzer.analyze().get() val queryTreeResult = - result.all( + result.all( mustSatisfy = { max(it.subscriptExpression) < min( it.arrayExpression - .followPrevDFGEdgesUntilHit { node -> - node is ArrayCreationExpression - } + .followPrevDFGEdgesUntilHit { node -> node is NewArrayExpression } .fulfilled - .map { it2 -> - (it2.last() as ArrayCreationExpression).dimensions[0] - } + .map { it2 -> (it2.last() as NewArrayExpression).dimensions[0] } ) && min(it.subscriptExpression) > 0 } ) assertFalse(queryTreeResult.first) val queryTreeResult2 = - result.allExtended( + result.allExtended( mustSatisfy = { (max(it.subscriptExpression) lt min( it.arrayExpression - .followPrevDFGEdgesUntilHit { node -> - node is ArrayCreationExpression - } + .followPrevDFGEdgesUntilHit { node -> node is NewArrayExpression } .fulfilled - .map { it2 -> - (it2.last() as ArrayCreationExpression).dimensions[0] - } + .map { it2 -> (it2.last() as NewArrayExpression).dimensions[0] } )) and (min(it.subscriptExpression) ge 0) } ) @@ -643,7 +630,7 @@ class QueryTest { val result = analyzer.analyze().get() val queryTreeResult = - result.all( + result.all( mustSatisfy = { val max_sub = max(it.subscriptExpression) val min_dim = min(it.arraySize) @@ -654,7 +641,7 @@ class QueryTest { assertTrue(queryTreeResult.first) val queryTreeResult2 = - result.allExtended( + result.allExtended( mustSatisfy = { val max_sub = max(it.subscriptExpression) val min_dim = min(it.arraySize) diff --git a/cpg-console/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/NullPointerCheck.kt b/cpg-console/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/NullPointerCheck.kt index dc376e8343..80606ac31a 100644 --- a/cpg-console/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/NullPointerCheck.kt +++ b/cpg-console/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/NullPointerCheck.kt @@ -61,7 +61,7 @@ class NullPointerCheck { handleHasBase(v) } - fun visit(v: ArraySubscriptionExpression) { + fun visit(v: SubscriptExpression) { handleHasBase(v) } } diff --git a/cpg-console/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/OutOfBoundsCheck.kt b/cpg-console/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/OutOfBoundsCheck.kt index 9f73e97f16..b30557ec37 100644 --- a/cpg-console/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/OutOfBoundsCheck.kt +++ b/cpg-console/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/OutOfBoundsCheck.kt @@ -30,9 +30,9 @@ import de.fraunhofer.aisec.cpg.console.fancyCode import de.fraunhofer.aisec.cpg.graph.Node import de.fraunhofer.aisec.cpg.graph.capacity import de.fraunhofer.aisec.cpg.graph.declarations.VariableDeclaration -import de.fraunhofer.aisec.cpg.graph.statements.expressions.ArrayCreationExpression -import de.fraunhofer.aisec.cpg.graph.statements.expressions.ArraySubscriptionExpression -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.NewArrayExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference +import de.fraunhofer.aisec.cpg.graph.statements.expressions.SubscriptExpression import de.fraunhofer.aisec.cpg.processing.IVisitor import de.fraunhofer.aisec.cpg.processing.strategy.Strategy import de.fraunhofer.aisec.cpg.sarif.PhysicalLocation @@ -53,7 +53,7 @@ class OutOfBoundsCheck { tu.accept( Strategy::AST_FORWARD, object : IVisitor() { - fun visit(v: ArraySubscriptionExpression) { + fun visit(v: SubscriptExpression) { val evaluator = ValueEvaluator() val resolvedIndex = evaluator.evaluate(v.subscriptExpression) @@ -61,9 +61,8 @@ class OutOfBoundsCheck { // check, if we know that the array was initialized with a fixed length // TODO(oxisto): it would be nice to have a helper that follows the expr val decl = - (v.arrayExpression as? DeclaredReferenceExpression)?.refersTo - as? VariableDeclaration - (decl?.initializer as? ArrayCreationExpression)?.let { + (v.arrayExpression as? Reference)?.refersTo as? VariableDeclaration + (decl?.initializer as? NewArrayExpression)?.let { val capacity = it.capacity if (resolvedIndex >= capacity) { diff --git a/cpg-console/src/main/kotlin/de/fraunhofer/aisec/cpg/console/Extensions.kt b/cpg-console/src/main/kotlin/de/fraunhofer/aisec/cpg/console/Extensions.kt index 274b25f3dc..da3832b394 100644 --- a/cpg-console/src/main/kotlin/de/fraunhofer/aisec/cpg/console/Extensions.kt +++ b/cpg-console/src/main/kotlin/de/fraunhofer/aisec/cpg/console/Extensions.kt @@ -28,7 +28,6 @@ package de.fraunhofer.aisec.cpg.console import de.fraunhofer.aisec.cpg.graph.Node import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.VariableDeclaration -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement import de.fraunhofer.aisec.cpg.graph.statements.DeclarationStatement import de.fraunhofer.aisec.cpg.graph.statements.IfStatement import de.fraunhofer.aisec.cpg.graph.statements.expressions.* @@ -191,7 +190,7 @@ fun getFanciesFor(original: Node?, node: Node?): List { + is Reference -> { // also color it, if it's on its own if (original == node) { node.location?.let { styles.identifier?.let { id -> list += Pair(id, it.region) } } @@ -215,7 +214,7 @@ fun getFanciesFor(original: Node?, node: Node?): List { + is Block -> { // loop through statements for (statement in node.statements) { list.addAll(getFanciesFor(original, statement)) @@ -245,7 +244,7 @@ fun getFanciesFor(original: Node?, node: Node?): List { + is NewArrayExpression -> { fancyWord("new", node, list, styles.keyword) // check for primitive types diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/ScopeManager.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/ScopeManager.kt index 4e42d509f3..12129c0d2e 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/ScopeManager.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/ScopeManager.kt @@ -30,8 +30,9 @@ import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.declarations.* import de.fraunhofer.aisec.cpg.graph.scopes.* 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.DeclaredReferenceExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import de.fraunhofer.aisec.cpg.graph.types.FunctionPointerType import de.fraunhofer.aisec.cpg.graph.types.IncompleteType import de.fraunhofer.aisec.cpg.graph.types.Type @@ -88,8 +89,8 @@ class ScopeManager : ScopeProvider { get() = scopeMap[null] as? GlobalScope /** The current block, according to the scope that is currently active. */ - val currentBlock: CompoundStatement? - get() = this.firstScopeIsInstanceOrNull()?.astNode as? CompoundStatement + val currentBlock: Block? + get() = this.firstScopeIsInstanceOrNull()?.astNode as? Block /** The current function, according to the scope that is currently active. */ val currentFunction: FunctionDeclaration? get() = this.firstScopeIsInstanceOrNull()?.astNode as? FunctionDeclaration @@ -213,7 +214,7 @@ class ScopeManager : ScopeProvider { * on-the-fly, if they do not exist. * * The scope manager has an internal association between the type of scope, e.g. a [BlockScope] - * and the CPG node it represents, e.g. a [CompoundStatement]. + * and the CPG node it represents, e.g. a [Block]. * * Afterwards, all calls to [addDeclaration] will be distributed to the * [de.fraunhofer.aisec.cpg.graph.DeclarationHolder] that is currently in-scope. @@ -225,7 +226,7 @@ class ScopeManager : ScopeProvider { if (!scopeMap.containsKey(nodeToScope)) { newScope = when (nodeToScope) { - is CompoundStatement -> BlockScope(nodeToScope) + is Block -> BlockScope(nodeToScope) is WhileStatement, is DoStatement, is AssertStatement -> LoopScope(nodeToScope as Statement) @@ -596,10 +597,7 @@ class ScopeManager : ScopeProvider { * TODO: We should merge this function with [.resolveFunction] */ @JvmOverloads - fun resolveReference( - ref: DeclaredReferenceExpression, - scope: Scope? = currentScope - ): ValueDeclaration? { + fun resolveReference(ref: Reference, scope: Scope? = currentScope): ValueDeclaration? { return resolve(scope) { if ( it.name.lastPartsMatch(ref.name) diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/DeclarationBuilder.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/DeclarationBuilder.kt index 06a1cd5ee7..b7c8f0b23c 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/DeclarationBuilder.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/DeclarationBuilder.kt @@ -30,8 +30,8 @@ import de.fraunhofer.aisec.cpg.frontends.LanguageFrontend import de.fraunhofer.aisec.cpg.graph.Node.Companion.EMPTY_NAME import de.fraunhofer.aisec.cpg.graph.NodeBuilder.log import de.fraunhofer.aisec.cpg.graph.declarations.* -import de.fraunhofer.aisec.cpg.graph.statements.expressions.ArrayCreationExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.NewArrayExpression import de.fraunhofer.aisec.cpg.graph.types.Type import de.fraunhofer.aisec.cpg.sarif.PhysicalLocation @@ -129,14 +129,14 @@ fun MetadataProvider.newConstructorDeclaration( * argument. */ @JvmOverloads -fun MetadataProvider.newParamVariableDeclaration( +fun MetadataProvider.newParameterDeclaration( name: CharSequence?, type: Type = unknownType(), variadic: Boolean = false, code: String? = null, rawNode: Any? = null -): ParamVariableDeclaration { - val node = ParamVariableDeclaration() +): ParameterDeclaration { + val node = ParameterDeclaration() node.applyMetadata(this, name, rawNode, code, localNameOnly = true) node.type = type @@ -222,18 +222,18 @@ fun MetadataProvider.newTypedefDeclaration( } /** - * Creates a new [TypeParamDeclaration]. The [MetadataProvider] receiver will be used to fill + * Creates a new [TypeParameterDeclaration]. The [MetadataProvider] receiver will be used to fill * different meta-data using [Node.applyMetadata]. Calling this extension function outside of Kotlin * requires an appropriate [MetadataProvider], such as a [LanguageFrontend] as an additional * prepended argument. */ @JvmOverloads -fun MetadataProvider.newTypeParamDeclaration( +fun MetadataProvider.newTypeParameterDeclaration( name: CharSequence?, code: String? = null, rawNode: Any? = null -): TypeParamDeclaration { - val node = TypeParamDeclaration() +): TypeParameterDeclaration { + val node = TypeParameterDeclaration() node.applyMetadata(this, name, rawNode, code, true) log(node) @@ -304,18 +304,18 @@ fun MetadataProvider.newFunctionTemplateDeclaration( } /** - * Creates a new [ClassTemplateDeclaration]. The [MetadataProvider] receiver will be used to fill + * Creates a new [RecordTemplateDeclaration]. The [MetadataProvider] receiver will be used to fill * different meta-data using [Node.applyMetadata]. Calling this extension function outside of Kotlin * requires an appropriate [MetadataProvider], such as a [LanguageFrontend] as an additional * prepended argument. */ @JvmOverloads -fun MetadataProvider.newClassTemplateDeclaration( +fun MetadataProvider.newRecordTemplateDeclaration( name: CharSequence?, code: String? = null, rawNode: Any? = null -): ClassTemplateDeclaration { - val node = ClassTemplateDeclaration() +): RecordTemplateDeclaration { + val node = RecordTemplateDeclaration() node.applyMetadata(this, name, rawNode, code, true) log(node) @@ -369,7 +369,7 @@ fun MetadataProvider.newFieldDeclaration( node.location = location node.isImplicitInitializerAllowed = implicitInitializerAllowed if (initializer != null) { - if (initializer is ArrayCreationExpression) { + if (initializer is NewArrayExpression) { node.isArray = true } node.initializer = initializer @@ -442,18 +442,18 @@ fun MetadataProvider.newNamespaceDeclaration( } /** - * Creates a new [UsingDirective]. The [MetadataProvider] receiver will be used to fill different + * Creates a new [UsingDeclaration]. The [MetadataProvider] receiver will be used to fill different * meta-data using [Node.applyMetadata]. Calling this extension function outside of Kotlin requires * an appropriate [MetadataProvider], such as a [LanguageFrontend] as an additional prepended * argument. */ @JvmOverloads -fun MetadataProvider.newUsingDirective( +fun MetadataProvider.newUsingDeclaration( code: String? = null, qualifiedName: CharSequence?, rawNode: Any? = null -): UsingDirective { - val node = UsingDirective() +): UsingDeclaration { + val node = UsingDeclaration() node.applyMetadata(this, qualifiedName, rawNode, code) node.qualifiedName = qualifiedName.toString() diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/ExpressionBuilder.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/ExpressionBuilder.kt index 94eb6f4691..b9edf83c4c 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/ExpressionBuilder.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/ExpressionBuilder.kt @@ -192,8 +192,8 @@ fun MetadataProvider.newConstructExpression( @JvmOverloads fun MetadataProvider.newConditionalExpression( condition: Expression, - thenExpr: Expression?, - elseExpr: Expression?, + thenExpression: Expression?, + elseExpression: Expression?, type: Type = unknownType(), code: String? = null, rawNode: Any? = null @@ -203,8 +203,8 @@ fun MetadataProvider.newConditionalExpression( node.type = type node.condition = condition - node.thenExpr = thenExpr - node.elseExpr = elseExpr + node.thenExpression = thenExpression + node.elseExpression = elseExpression log(node) return node @@ -252,17 +252,13 @@ fun MetadataProvider.newLambdaExpression( } /** - * Creates a new [CompoundStatementExpression]. The [MetadataProvider] receiver will be used to fill - * different meta-data using [Node.applyMetadata]. Calling this extension function outside of Kotlin - * requires an appropriate [MetadataProvider], such as a [LanguageFrontend] as an additional - * prepended argument. + * Creates a new [Block]. The [MetadataProvider] receiver will be used to fill different meta-data + * using [Node.applyMetadata]. Calling this extension function outside of Kotlin requires an + * appropriate [MetadataProvider], such as a [LanguageFrontend] as an additional prepended argument. */ @JvmOverloads -fun MetadataProvider.newCompoundStatementExpression( - code: String? = null, - rawNode: Any? = null -): CompoundStatementExpression { - val node = CompoundStatementExpression() +fun MetadataProvider.newBlock(code: String? = null, rawNode: Any? = null): Block { + val node = Block() node.applyMetadata(this, EMPTY_NAME, rawNode, code, true) log(node) @@ -300,12 +296,12 @@ fun MetadataProvider.newCallExpression( * argument. */ @JvmOverloads -fun MetadataProvider.newExplicitConstructorInvocation( +fun MetadataProvider.newConstructorCallExpression( containingClass: String?, code: String? = null, rawNode: Any? = null -): ExplicitConstructorInvocation { - val node = ExplicitConstructorInvocation() +): ConstructorCallExpression { + val node = ConstructorCallExpression() node.applyMetadata(this, EMPTY_NAME, rawNode, code, true) node.containingClass = containingClass @@ -409,17 +405,17 @@ fun MetadataProvider.newTypeIdExpression( } /** - * Creates a new [ArraySubscriptionExpression]. The [MetadataProvider] receiver will be used to fill + * Creates a new [SubscriptExpression]. The [MetadataProvider] receiver will be used to fill * different meta-data using [Node.applyMetadata]. Calling this extension function outside of Kotlin * requires an appropriate [MetadataProvider], such as a [LanguageFrontend] as an additional * prepended argument. */ @JvmOverloads -fun MetadataProvider.newArraySubscriptionExpression( +fun MetadataProvider.newSubscriptExpression( code: String? = null, rawNode: Any? = null -): ArraySubscriptionExpression { - val node = ArraySubscriptionExpression() +): SubscriptExpression { + val node = SubscriptExpression() node.applyMetadata(this, EMPTY_NAME, rawNode, code, true) log(node) @@ -450,17 +446,17 @@ fun MetadataProvider.newRangeExpression( } /** - * Creates a new [ArrayCreationExpression]. The [MetadataProvider] receiver will be used to fill + * Creates a new [NewArrayExpression]. The [MetadataProvider] receiver will be used to fill * different meta-data using [Node.applyMetadata]. Calling this extension function outside of Kotlin * requires an appropriate [MetadataProvider], such as a [LanguageFrontend] as an additional * prepended argument. */ @JvmOverloads -fun MetadataProvider.newArrayCreationExpression( +fun MetadataProvider.newNewArrayExpression( code: String? = null, rawNode: Any? = null -): ArrayCreationExpression { - val node = ArrayCreationExpression() +): NewArrayExpression { + val node = NewArrayExpression() node.applyMetadata(this, EMPTY_NAME, rawNode, code, true) log(node) @@ -468,19 +464,19 @@ fun MetadataProvider.newArrayCreationExpression( } /** - * Creates a new [DeclaredReferenceExpression]. The [MetadataProvider] receiver will be used to fill - * different meta-data using [Node.applyMetadata]. Calling this extension function outside of Kotlin - * requires an appropriate [MetadataProvider], such as a [LanguageFrontend] as an additional - * prepended argument. + * Creates a new [Reference]. The [MetadataProvider] receiver will be used to fill different + * meta-data using [Node.applyMetadata]. Calling this extension function outside of Kotlin requires + * an appropriate [MetadataProvider], such as a [LanguageFrontend] as an additional prepended + * argument. */ @JvmOverloads -fun MetadataProvider.newDeclaredReferenceExpression( +fun MetadataProvider.newReference( name: CharSequence?, type: Type = unknownType(), code: String? = null, rawNode: Any? = null -): DeclaredReferenceExpression { - val node = DeclaredReferenceExpression() +): Reference { + val node = Reference() node.applyMetadata(this, name, rawNode, code, true) node.type = type diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Extensions.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Extensions.kt index 6c7dbc9f82..2da58dba07 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Extensions.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Extensions.kt @@ -29,11 +29,11 @@ import de.fraunhofer.aisec.cpg.TranslationResult import de.fraunhofer.aisec.cpg.graph.declarations.* import de.fraunhofer.aisec.cpg.graph.edge.Properties import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdge -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement import de.fraunhofer.aisec.cpg.graph.statements.IfStatement import de.fraunhofer.aisec.cpg.graph.statements.Statement import de.fraunhofer.aisec.cpg.graph.statements.SwitchStatement import de.fraunhofer.aisec.cpg.graph.statements.expressions.* +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block import de.fraunhofer.aisec.cpg.helpers.SubgraphWalker import de.fraunhofer.aisec.cpg.passes.astParent @@ -168,8 +168,8 @@ inline fun DeclarationHolder.byName( * For convenience, `n` defaults to zero, so that the first statement is always easy to fetch. */ inline fun FunctionDeclaration.bodyOrNull(n: Int = 0): T? { - return if (this.body is CompoundStatement) { - return (body as? CompoundStatement)?.statements?.filterIsInstance()?.getOrNull(n) + return if (this.body is Block) { + return (body as? Block)?.statements?.filterIsInstance()?.getOrNull(n) } else { if (n == 0 && this.body is T) { this.body as T @@ -515,8 +515,8 @@ val Node?.methods: List val Node?.fields: List get() = this.allChildren() -/** Returns all [ParamVariableDeclaration] children in this graph, starting with this [Node]. */ -val Node?.parameters: List +/** Returns all [ParameterDeclaration] children in this graph, starting with this [Node]. */ +val Node?.parameters: List get() = this.allChildren() /** Returns all [FunctionDeclaration] children in this graph, starting with this [Node]. */ @@ -539,8 +539,8 @@ val Node?.variables: List val Node?.literals: List> get() = this.allChildren() -/** Returns all [DeclaredReferenceExpression] children in this graph, starting with this [Node]. */ -val Node?.refs: List +/** Returns all [Reference] children in this graph, starting with this [Node]. */ +val Node?.refs: List get() = this.allChildren() /** Returns all [Assignment] child edges in this graph, starting with this [Node]. */ @@ -559,10 +559,7 @@ val Node?.assignments: List val VariableDeclaration.firstAssignment: Expression? get() { val start = this.scope?.astNode ?: return null - val assignments = - start.assignments.filter { - (it.target as? DeclaredReferenceExpression)?.refersTo == this - } + val assignments = start.assignments.filter { (it.target as? Reference)?.refersTo == this } // We need to measure the distance between the start and each assignment value return assignments @@ -604,7 +601,7 @@ val FunctionDeclaration.callees: Set operator fun FunctionDeclaration.get(n: Int): Statement? { val body = this.body - if (body is CompoundStatement) { + if (body is Block) { return body[n] } else if (n == 0) { return body @@ -646,10 +643,10 @@ fun Node.controlledBy(): List { * Returns the expression specifying the dimension (i.e., size) of the array during its * initialization. */ -val ArraySubscriptionExpression.arraySize: Expression +val SubscriptExpression.arraySize: Expression get() = - (((this.arrayExpression as DeclaredReferenceExpression).refersTo as VariableDeclaration) - .initializer as ArrayCreationExpression) + (((this.arrayExpression as Reference).refersTo as VariableDeclaration).initializer + as NewArrayExpression) .dimensions[0] /** diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Holder.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Holder.kt index 47e55df0d0..ad44450b1c 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Holder.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Holder.kt @@ -25,7 +25,7 @@ */ package de.fraunhofer.aisec.cpg.graph -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression /** @@ -33,8 +33,8 @@ import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression * [StatementHolder], in which [Holder] is used as a common interface. * * A primary use-case for the usage of this interface is the Node Fluent DSL in order to create node - * objects which can either be used as a statement (e.g. in a [CompoundStatement]) or as an argument - * (e.g. of a [CallExpression]). + * objects which can either be used as a statement (e.g. in a [Block]) or as an argument (e.g. of a + * [CallExpression]). */ interface Holder { /** Adds a [Node] to the list of "held" nodes. */ diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/StatementBuilder.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/StatementBuilder.kt index c16186e5f0..18f4b65de9 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/StatementBuilder.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/StatementBuilder.kt @@ -147,24 +147,6 @@ fun MetadataProvider.newEmptyStatement(code: String? = null, rawNode: Any? = nul return node } -/** - * Creates a new [CompoundStatement]. The [MetadataProvider] receiver will be used to fill different - * meta-data using [Node.applyMetadata]. Calling this extension function outside of Kotlin requires - * an appropriate [MetadataProvider], such as a [LanguageFrontend] as an additional prepended - * argument. - */ -@JvmOverloads -fun MetadataProvider.newCompoundStatement( - code: String? = null, - rawNode: Any? = null -): CompoundStatement { - val node = CompoundStatement() - node.applyMetadata(this, EMPTY_NAME, rawNode, code, true) - - log(node) - return node -} - /** * Creates a new [DeclarationStatement]. The [MetadataProvider] receiver will be used to fill * different meta-data using [Node.applyMetadata]. Calling this extension function outside of Kotlin 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 7efefcf1f2..02e02f8750 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 @@ -209,31 +209,29 @@ context(RecordDeclaration) fun LanguageFrontend<*, *>.constructor( init: ConstructorDeclaration.() -> Unit ): ConstructorDeclaration { - val recordDecl: RecordDeclaration = this@RecordDeclaration - val node = newConstructorDeclaration(recordDecl.name, recordDeclaration = recordDecl) + val recordDeclaration: RecordDeclaration = this@RecordDeclaration + val node = + newConstructorDeclaration(recordDeclaration.name, recordDeclaration = recordDeclaration) scopeManager.enterScope(node) init(node) scopeManager.leaveScope(node) scopeManager.addDeclaration(node) - recordDecl.addConstructor(node) + recordDeclaration.addConstructor(node) return node } /** - * Creates a new [CompoundStatement] 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. + * 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(FunctionDeclaration) -fun LanguageFrontend<*, *>.body( - needsScope: Boolean = true, - init: CompoundStatement.() -> Unit -): CompoundStatement { - val node = newCompoundStatement() +fun LanguageFrontend<*, *>.body(needsScope: Boolean = true, init: Block.() -> Unit): Block { + val node = newBlock() scopeIfNecessary(needsScope, node, init) body = node @@ -242,7 +240,7 @@ fun LanguageFrontend<*, *>.body( } /** - * Creates a new [ParamVariableDeclaration] in the Fluent Node DSL and adds it to the + * Creates a new [ParameterDeclaration] in the Fluent Node DSL and adds it to the * [FunctionDeclaration.parameters] of the nearest enclosing [FunctionDeclaration]. The [init] block * can be used to create further sub-nodes as well as configuring the created node itself. */ @@ -251,10 +249,10 @@ context(FunctionDeclaration) fun LanguageFrontend<*, *>.param( name: CharSequence, type: Type = unknownType(), - init: (ParamVariableDeclaration.() -> Unit)? = null -): ParamVariableDeclaration { + init: (ParameterDeclaration.() -> Unit)? = null +): ParameterDeclaration { val node = - (this@LanguageFrontend).newParamVariableDeclaration( + (this@LanguageFrontend).newParameterDeclaration( name, type, ) @@ -284,9 +282,9 @@ fun LanguageFrontend<*, *>.returnStmt(init: ReturnStatement.() -> Unit): ReturnS context(Holder) fun LanguageFrontend<*, *>.ase( - init: (ArraySubscriptionExpression.() -> Unit)? = null -): ArraySubscriptionExpression { - val node = newArraySubscriptionExpression() + init: (SubscriptExpression.() -> Unit)? = null +): SubscriptExpression { + val node = newSubscriptExpression() if (init != null) { init(node) @@ -347,9 +345,8 @@ fun LanguageFrontend<*, *>.variable( * * The type of expression is determined whether [name] is either a [Name] with a [Name.parent] or if * it can be parsed as a FQN in the given language. It also automatically creates either a - * [DeclaredReferenceExpression] or [MemberExpression] and sets it as the [CallExpression.callee]. - * The [init] block can be used to create further sub-nodes as well as configuring the created node - * itself. + * [Reference] or [MemberExpression] and sets it as the [CallExpression.callee]. The [init] block + * can be used to create further sub-nodes as well as configuring the created node itself. */ context(Holder) @@ -367,7 +364,7 @@ fun LanguageFrontend<*, *>.call( isStatic ) } else { - newCallExpression(newDeclaredReferenceExpression(parsedName)) + newCallExpression(newReference(parsedName)) } if (init != null) { init(node) @@ -390,9 +387,8 @@ fun LanguageFrontend<*, *>.call( * * The type of expression is determined whether [localName] is either a [Name] with a [Name.parent] * or if it can be parsed as a FQN in the given language. It also automatically creates either a - * [DeclaredReferenceExpression] or [MemberExpression] and sets it as the [CallExpression.callee]. - * The [init] block can be used to create further sub-nodes as well as configuring the created node - * itself. + * [Reference] or [MemberExpression] and sets it as the [CallExpression.callee]. The [init] block + * can be used to create further sub-nodes as well as configuring the created node itself. */ context(Holder) @@ -487,7 +483,7 @@ fun LanguageFrontend<*, *>.memberOrRef(name: Name, type: Type = unknownType()): if (name.parent != null) { newMemberExpression(name.localName, memberOrRef(name.parent)) } else { - newDeclaredReferenceExpression(name.localName) + newReference(name.localName) } if (type !is UnknownType) { node.type = type @@ -596,17 +592,14 @@ fun LanguageFrontend<*, *>.whileCondition( } /** - * 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. */ context(IfStatement) -fun LanguageFrontend<*, *>.thenStmt( - needsScope: Boolean = true, - init: CompoundStatement.() -> Unit -): CompoundStatement { - val node = newCompoundStatement() +fun LanguageFrontend<*, *>.thenStmt(needsScope: Boolean = true, init: Block.() -> Unit): Block { + val node = newBlock() scopeIfNecessary(needsScope, node, init) thenStatement = node @@ -633,28 +626,28 @@ fun LanguageFrontend<*, *>.elseIf(init: IfStatement.() -> Unit): IfStatement { // TODO: Merge the bodies together /** - * Creates a new [CompoundStatement] 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 well as configuring the created node itself. + * 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 + * well as configuring the created node itself. */ context(WhileStatement) -fun LanguageFrontend<*, *>.loopBody(init: CompoundStatement.() -> Unit): CompoundStatement { - val node = newCompoundStatement() +fun LanguageFrontend<*, *>.loopBody(init: Block.() -> Unit): Block { + val node = newBlock() init(node) statement = node return node } /** - * Creates a new [CompoundStatement] 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 well as configuring the created node itself. + * 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 + * well as configuring the created node itself. */ context(ForEachStatement) -fun LanguageFrontend<*, *>.loopBody(init: CompoundStatement.() -> Unit): CompoundStatement { - val node = newCompoundStatement() +fun LanguageFrontend<*, *>.loopBody(init: Block.() -> Unit): Block { + val node = newBlock() init(node) statement = node @@ -662,14 +655,14 @@ fun LanguageFrontend<*, *>.loopBody(init: CompoundStatement.() -> Unit): Compoun } /** - * Creates a new [CompoundStatement] in the Fluent Node DSL and sets it to the + * 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. */ context(SwitchStatement) -fun LanguageFrontend<*, *>.switchBody(init: CompoundStatement.() -> Unit): CompoundStatement { - val node = newCompoundStatement() +fun LanguageFrontend<*, *>.switchBody(init: Block.() -> Unit): Block { + val node = newBlock() init(node) statement = node @@ -677,17 +670,14 @@ fun LanguageFrontend<*, *>.switchBody(init: CompoundStatement.() -> Unit): Compo } /** - * Creates a new [CompoundStatement] in the Fluent Node DSL and sets it to the - * [IfStatement.elseStatement] 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.elseStatement] of + * the nearest enclosing [IfStatement]. The [init] block can be used to create further sub-nodes as + * well as configuring the created node itself. */ context(IfStatement) -fun LanguageFrontend<*, *>.elseStmt( - needsScope: Boolean = true, - init: CompoundStatement.() -> Unit -): CompoundStatement { - val node = newCompoundStatement() +fun LanguageFrontend<*, *>.elseStmt(needsScope: Boolean = true, init: Block.() -> Unit): Block { + val node = newBlock() scopeIfNecessary(needsScope, node, init) elseStatement = node @@ -760,9 +750,9 @@ fun LanguageFrontend<*, *>.breakStmt(label: String? = null): BreakStatement { */ context(Holder) -fun LanguageFrontend<*, *>.case(caseExpr: Expression? = null): CaseStatement { +fun LanguageFrontend<*, *>.case(caseExpression: Expression? = null): CaseStatement { val node = newCaseStatement() - node.caseExpression = caseExpr + node.caseExpression = caseExpression // Only add this to a statement holder if the nearest holder is a statement holder val holder = this@Holder @@ -836,18 +826,17 @@ fun LanguageFrontend<*, *>.ile( } /** - * Creates a new [DeclaredReferenceExpression] in the Fluent Node DSL and invokes - * [ArgumentHolder.addArgument] of the nearest enclosing [Holder], but only if it is an - * [ArgumentHolder]. + * Creates a new [Reference] in the Fluent Node DSL and invokes [ArgumentHolder.addArgument] of the + * nearest enclosing [Holder], but only if it is an [ArgumentHolder]. */ context(Holder) fun LanguageFrontend<*, *>.ref( name: CharSequence, type: Type = unknownType(), - init: (DeclaredReferenceExpression.() -> Unit)? = null -): DeclaredReferenceExpression { - val node = newDeclaredReferenceExpression(name) + init: (Reference.() -> Unit)? = null +): Reference { + val node = newReference(name) node.type = type if (init != null) { @@ -1099,10 +1088,11 @@ context(LanguageFrontend<*, *>, Holder) fun Expression.conditional( condition: Expression, - thenExpr: Expression, - elseExpr: Expression + thenExpression: Expression, + elseExpression: Expression ): ConditionalExpression { - val node = (this@LanguageFrontend).newConditionalExpression(condition, thenExpr, elseExpr) + val node = + (this@LanguageFrontend).newConditionalExpression(condition, thenExpression, elseExpression) if (this@Holder is StatementHolder) { (this@Holder) += node diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/FieldDeclaration.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/FieldDeclaration.kt index e76b68b601..6986ec21e2 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/FieldDeclaration.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/FieldDeclaration.kt @@ -25,7 +25,6 @@ */ package de.fraunhofer.aisec.cpg.graph.declarations -import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression import java.util.* import org.apache.commons.lang3.builder.ToStringBuilder diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/FunctionDeclaration.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/FunctionDeclaration.kt index e92b8d7e7a..49466af8c8 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/FunctionDeclaration.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/FunctionDeclaration.kt @@ -30,8 +30,8 @@ import de.fraunhofer.aisec.cpg.graph.edge.Properties import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdge import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdge.Companion.propertyEqualsList import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdgeDelegate -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement import de.fraunhofer.aisec.cpg.graph.statements.Statement +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression import de.fraunhofer.aisec.cpg.graph.types.Type import de.fraunhofer.aisec.cpg.isDerivedFrom @@ -42,7 +42,7 @@ import org.neo4j.ogm.annotation.Relationship /** Represents the declaration or definition of a function. */ open class FunctionDeclaration : ValueDeclaration(), DeclarationHolder { - /** The function body. Usually a [CompoundStatement]. */ + /** The function body. Usually a [Block]. */ @AST var body: Statement? = null /** @@ -54,7 +54,7 @@ open class FunctionDeclaration : ValueDeclaration(), DeclarationHolder { /** The list of function parameters. */ @Relationship(value = "PARAMETERS", direction = Relationship.Direction.OUTGOING) @AST - var parameterEdges = mutableListOf>() + var parameterEdges = mutableListOf>() /** Virtual property for accessing [parameterEdges] without property edges. */ var parameters by PropertyEdgeDelegate(FunctionDeclaration::parameterEdges) @@ -115,7 +115,7 @@ open class FunctionDeclaration : ValueDeclaration(), DeclarationHolder { val signature = parameters .stream() - .sorted(Comparator.comparingInt(ParamVariableDeclaration::argumentIndex)) + .sorted(Comparator.comparingInt(ParameterDeclaration::argumentIndex)) .collect(Collectors.toList()) return if (targetSignature.size < signature.size) { false @@ -172,16 +172,16 @@ open class FunctionDeclaration : ValueDeclaration(), DeclarationHolder { } fun getBodyStatementAs(i: Int, clazz: Class): T? { - if (body is CompoundStatement) { - val statement = (body as CompoundStatement).statements[i] + if (body is Block) { + val statement = (body as Block).statements[i] return if (clazz.isAssignableFrom(statement.javaClass)) clazz.cast(statement) else null } return null } /** - * A list of default expressions for each item in [parameters]. If a [ParamVariableDeclaration] - * has no default, the list will be null at this index. This list must have the same size as + * A list of default expressions for each item in [parameters]. If a [ParameterDeclaration] has + * no default, the list will be null at this index. This list must have the same size as * [parameters]. */ val defaultParameters: List @@ -205,14 +205,14 @@ open class FunctionDeclaration : ValueDeclaration(), DeclarationHolder { val signatureTypes: List get() = parameters.map { it.type } - fun addParameter(paramVariableDeclaration: ParamVariableDeclaration) { - val propertyEdge = PropertyEdge(this, paramVariableDeclaration) + fun addParameter(parameterDeclaration: ParameterDeclaration) { + val propertyEdge = PropertyEdge(this, parameterDeclaration) propertyEdge.addProperty(Properties.INDEX, parameters.size) parameterEdges.add(propertyEdge) } - fun removeParameter(paramVariableDeclaration: ParamVariableDeclaration) { - parameterEdges.removeIf { it.end == paramVariableDeclaration } + fun removeParameter(parameterDeclaration: ParameterDeclaration) { + parameterEdges.removeIf { it.end == parameterDeclaration } } override fun toString(): String { @@ -239,7 +239,7 @@ open class FunctionDeclaration : ValueDeclaration(), DeclarationHolder { override fun hashCode() = Objects.hash(super.hashCode(), body, parameters, throwsTypes) override fun addDeclaration(declaration: Declaration) { - if (declaration is ParamVariableDeclaration) { + if (declaration is ParameterDeclaration) { addIfNotContains(parameterEdges, declaration) } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/FunctionTemplateDeclaration.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/FunctionTemplateDeclaration.kt index 438104863e..ee452931cc 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/FunctionTemplateDeclaration.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/FunctionTemplateDeclaration.kt @@ -59,7 +59,7 @@ class FunctionTemplateDeclaration : TemplateDeclaration() { } override fun addDeclaration(declaration: Declaration) { - if (declaration is TypeParamDeclaration || declaration is ParamVariableDeclaration) { + if (declaration is TypeParameterDeclaration || declaration is ParameterDeclaration) { addIfNotContains(this.parameterEdges, declaration) } else if (declaration is FunctionDeclaration) { addIfNotContains(realizationEdges, declaration) diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/MethodDeclaration.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/MethodDeclaration.kt index 500590d55b..edfe3e7a6c 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/MethodDeclaration.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/MethodDeclaration.kt @@ -26,7 +26,7 @@ package de.fraunhofer.aisec.cpg.graph.declarations import de.fraunhofer.aisec.cpg.graph.AST -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import de.fraunhofer.aisec.cpg.passes.CallResolver import de.fraunhofer.aisec.cpg.passes.VariableUsageResolver @@ -51,26 +51,25 @@ open class MethodDeclaration : FunctionDeclaration() { * created (usually in the form of a [VariableDeclaration] and added to the scope of the * [MethodDeclaration] by a language frontend. Furthermore, it must be manually set to the * [receiver] property of the method, since the scope manager cannot do this. If the name of the - * receiver, e.g., `this`, is used anywhere in the method body, a [DeclaredReferenceExpression] - * must be created by the language frontend, and its [DeclaredReferenceExpression.refersTo] - * property must point to this [receiver]. The latter is done automatically by the - * [VariableUsageResolver], which treats it like any other regular variable. + * receiver, e.g., `this`, is used anywhere in the method body, a [Reference] must be created by + * the language frontend, and its [Reference.refersTo] property must point to this [receiver]. + * The latter is done automatically by the [VariableUsageResolver], which treats it like any + * other regular variable. * * Some languages (for example Python) denote the first argument in a method declaration as the * receiver (e.g., in `def foo(self, arg1)`, `self` is the receiver). In this case, extra care * needs to be taken that for the first argument of the method, a [VariableDeclaration] is * created and stored in [receiver]. All other arguments must then be processed normally - * (usually into a [ParamVariableDeclaration]). This is also important because from the - * "outside" the method only has the remaining arguments, when called (e.g., - * `object.foo("myarg1")`). + * (usually into a [ParameterDeclaration]). This is also important because from the "outside" + * the method only has the remaining arguments, when called (e.g., `object.foo("myarg1")`). * * There is one special case that concerns the Java language: In Java, there also exists a * `super` keyword, which can be used to explicitly access methods or fields of the (single) - * superclass of the current class. In this case, a [DeclaredReferenceExpression] will also be - * created (with the name `super`) and it will also refer to this receiver, even though the - * receiver's name is `this`. This is one of the very few exceptions where the reference and its - * declaration do not share the same name. The [CallResolver] will recognize this and treat the - * scoping aspect of the super-call accordingly. + * superclass of the current class. In this case, a [Reference] will also be created (with the + * name `super`) and it will also refer to this receiver, even though the receiver's name is + * `this`. This is one of the very few exceptions where the reference and its declaration do not + * share the same name. The [CallResolver] will recognize this and treat the scoping aspect of + * the super-call accordingly. */ @AST var receiver: VariableDeclaration? = null } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/ParamVariableDeclaration.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/ParameterDeclaration.kt similarity index 92% rename from cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/ParamVariableDeclaration.kt rename to cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/ParameterDeclaration.kt index 68def66fe4..d515eaf588 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/ParamVariableDeclaration.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/ParameterDeclaration.kt @@ -32,7 +32,7 @@ import java.util.* import org.neo4j.ogm.annotation.Relationship /** A declaration of a function or nontype template parameter. */ -class ParamVariableDeclaration : ValueDeclaration(), HasDefault { +class ParameterDeclaration : ValueDeclaration(), HasDefault { var isVariadic = false @Relationship(value = "DEFAULT", direction = Relationship.Direction.OUTGOING) @@ -47,7 +47,7 @@ class ParamVariableDeclaration : ValueDeclaration(), HasDefault { override fun equals(other: Any?): Boolean { if (this === other) return true - if (other == null || other !is ParamVariableDeclaration) return false + if (other == null || other !is ParameterDeclaration) return false return super.equals(other) && isVariadic == other.isVariadic && defaultValue == other.defaultValue diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/ClassTemplateDeclaration.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/RecordTemplateDeclaration.kt similarity index 90% rename from cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/ClassTemplateDeclaration.kt rename to cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/RecordTemplateDeclaration.kt index 625e5713fa..4a50f04d19 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/ClassTemplateDeclaration.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/RecordTemplateDeclaration.kt @@ -34,8 +34,8 @@ import java.util.* import kotlin.collections.ArrayList import org.neo4j.ogm.annotation.Relationship -/** Node representing a declaration of a ClassTemplate */ -class ClassTemplateDeclaration : TemplateDeclaration() { +/** Node representing a declaration of a template class or struct */ +class RecordTemplateDeclaration : TemplateDeclaration() { /** * Edges pointing to all RecordDeclarations that are realized by the ClassTempalte. Before the * expansion pass there is only a single RecordDeclaration which is instantiated after the @@ -46,7 +46,7 @@ class ClassTemplateDeclaration : TemplateDeclaration() { val realizationEdges: MutableList> = ArrayList() override val realizations: List by - PropertyEdgeDelegate(ClassTemplateDeclaration::realizationEdges) + PropertyEdgeDelegate(RecordTemplateDeclaration::realizationEdges) fun addRealization(realizedRecord: RecordDeclaration) { val propertyEdge = PropertyEdge(this, realizedRecord) @@ -59,7 +59,7 @@ class ClassTemplateDeclaration : TemplateDeclaration() { } override fun addDeclaration(declaration: Declaration) { - if (declaration is TypeParamDeclaration || declaration is ParamVariableDeclaration) { + if (declaration is TypeParameterDeclaration || declaration is ParameterDeclaration) { addIfNotContains(super.parameterEdges, declaration) } else if (declaration is RecordDeclaration) { addIfNotContains(realizationEdges, declaration) @@ -70,7 +70,7 @@ class ClassTemplateDeclaration : TemplateDeclaration() { if (this === other) return true if (other == null || javaClass != other.javaClass) return false if (!super.equals(other)) return false - val that = other as ClassTemplateDeclaration + val that = other as RecordTemplateDeclaration return realizations == that.realizations && propertyEqualsList(realizationEdges, that.realizationEdges) && parameters == that.parameters && diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/TemplateDeclaration.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/TemplateDeclaration.kt index 7b29ed17ba..15d1f482c5 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/TemplateDeclaration.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/TemplateDeclaration.kt @@ -61,8 +61,8 @@ abstract class TemplateDeclaration : Declaration(), DeclarationHolder { val parametersWithDefaults: MutableList = ArrayList() for (declaration in parameters) { if ( - (declaration is TypeParamDeclaration && declaration.default != null) || - (declaration is ParamVariableDeclaration && declaration.default != null) + (declaration is TypeParameterDeclaration && declaration.default != null) || + (declaration is ParameterDeclaration && declaration.default != null) ) { parametersWithDefaults.add(declaration) } @@ -74,22 +74,22 @@ abstract class TemplateDeclaration : Declaration(), DeclarationHolder { get() { val defaults: MutableList = ArrayList() for (declaration in parameters) { - if (declaration is TypeParamDeclaration) { + if (declaration is TypeParameterDeclaration) { defaults.add(declaration.default) - } else if (declaration is ParamVariableDeclaration) { + } else if (declaration is ParameterDeclaration) { defaults.add(declaration.default) } } return defaults } - fun addParameter(parameterizedType: TypeParamDeclaration) { + fun addParameter(parameterizedType: TypeParameterDeclaration) { val propertyEdge = PropertyEdge(this, parameterizedType) propertyEdge.addProperty(Properties.INDEX, parameterEdges.size) parameterEdges.add(propertyEdge) } - fun addParameter(nonTypeTemplateParamDeclaration: ParamVariableDeclaration) { + fun addParameter(nonTypeTemplateParamDeclaration: ParameterDeclaration) { val propertyEdge = PropertyEdge(this, nonTypeTemplateParamDeclaration) propertyEdge.addProperty(Properties.INDEX, parameterEdges.size) parameterEdges.add(propertyEdge) @@ -102,11 +102,11 @@ abstract class TemplateDeclaration : Declaration(), DeclarationHolder { return list } - fun removeParameter(parameterizedType: TypeParamDeclaration?) { + fun removeParameter(parameterizedType: TypeParameterDeclaration?) { parameterEdges.removeIf { it.end == parameterizedType } } - fun removeParameter(nonTypeTemplateParamDeclaration: ParamVariableDeclaration?) { + fun removeParameter(nonTypeTemplateParamDeclaration: ParameterDeclaration?) { parameterEdges.removeIf { it.end == nonTypeTemplateParamDeclaration } } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/TypeParamDeclaration.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/TypeParameterDeclaration.kt similarity index 93% rename from cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/TypeParamDeclaration.kt rename to cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/TypeParameterDeclaration.kt index cde9143f37..75e9f05d11 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/TypeParamDeclaration.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/TypeParameterDeclaration.kt @@ -32,7 +32,7 @@ import java.util.* import org.neo4j.ogm.annotation.Relationship /** A declaration of a type template parameter */ -class TypeParamDeclaration : ValueDeclaration(), HasDefault { +class TypeParameterDeclaration : ValueDeclaration(), HasDefault { /** TemplateParameters can define a default for the type parameter. */ @Relationship(value = "DEFAULT", direction = Relationship.Direction.OUTGOING) @AST @@ -41,7 +41,7 @@ class TypeParamDeclaration : ValueDeclaration(), HasDefault { override fun equals(other: Any?): Boolean { if (this === other) return true if (other == null || javaClass != other.javaClass) return false - val that = other as TypeParamDeclaration + val that = other as TypeParameterDeclaration return super.equals(that) && default == that.default } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/UsingDirective.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/UsingDeclaration.kt similarity index 88% rename from cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/UsingDirective.kt rename to cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/UsingDeclaration.kt index 696df394c6..fd2e1cb1d8 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/UsingDirective.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/UsingDeclaration.kt @@ -27,13 +27,13 @@ package de.fraunhofer.aisec.cpg.graph.declarations import java.util.Objects -// TODO: Documentation -class UsingDirective : Declaration() { +/** Represents a using directive used to extend the currently valid name scope. */ +class UsingDeclaration : Declaration() { var qualifiedName: String? = null override fun equals(other: Any?): Boolean { if (this === other) return true - if (other !is UsingDirective) return false + if (other !is UsingDeclaration) return false return super.equals(other) && qualifiedName == other.qualifiedName } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/ValueDeclaration.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/ValueDeclaration.kt index 216c175400..3204d7cfd5 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/ValueDeclaration.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/ValueDeclaration.kt @@ -30,7 +30,7 @@ import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.edge.Properties import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdge import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdge.Companion.unwrap -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import de.fraunhofer.aisec.cpg.graph.types.* import de.fraunhofer.aisec.cpg.helpers.identitySetOf import de.fraunhofer.aisec.cpg.passes.VariableUsageResolver @@ -72,23 +72,23 @@ abstract class ValueDeclaration : Declaration(), HasType { } /** - * Links to all the [DeclaredReferenceExpression]s accessing the variable and the respective - * access value (read, write, readwrite). + * Links to all the [Reference]s accessing the variable and the respective access value (read, + * write, readwrite). */ @PopulatedByPass(VariableUsageResolver::class) @Relationship(value = "USAGE") - var usageEdges: MutableList> = ArrayList() + var usageEdges: MutableList> = ArrayList() /** All usages of the variable/field. */ @PopulatedByPass(VariableUsageResolver::class) - var usages: List + var usages: List get() = unwrap(usageEdges, true) /** Set all usages of the variable/field and assembles the access properties. */ set(usages) { usageEdges = usages .stream() - .map { ref: DeclaredReferenceExpression -> + .map { ref: Reference -> val edge = PropertyEdge(this, ref) edge.addProperty(Properties.ACCESS, ref.access) edge @@ -97,7 +97,7 @@ abstract class ValueDeclaration : Declaration(), HasType { } /** Adds a usage of the variable/field and assembles the access property. */ - fun addUsage(reference: DeclaredReferenceExpression) { + fun addUsage(reference: Reference) { val usageEdge = PropertyEdge(this, reference) usageEdge.addProperty(Properties.ACCESS, reference.access) usageEdges.add(usageEdge) diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/VariableDeclaration.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/VariableDeclaration.kt index 0cd98b7f1b..c6e7b5b982 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/VariableDeclaration.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/VariableDeclaration.kt @@ -27,8 +27,8 @@ package de.fraunhofer.aisec.cpg.graph.declarations import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.statements.expressions.ConstructExpression -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import de.fraunhofer.aisec.cpg.graph.types.AutoType import de.fraunhofer.aisec.cpg.graph.types.HasType import de.fraunhofer.aisec.cpg.graph.types.TupleType @@ -67,7 +67,7 @@ open class VariableDeclaration : ValueDeclaration(), HasInitializer, HasType.Typ set(value) { field?.unregisterTypeObserver(this) field = value - if (value is DeclaredReferenceExpression) { + if (value is Reference) { value.resolutionHelper = this } value?.registerTypeObserver(this) diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/BlockScope.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/BlockScope.kt index a3a4c8d4fb..1b038e8b80 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/BlockScope.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/BlockScope.kt @@ -26,10 +26,13 @@ package de.fraunhofer.aisec.cpg.graph.scopes import de.fraunhofer.aisec.cpg.graph.statements.BreakStatement -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block -class BlockScope(blockStatement: CompoundStatement) : - ValueDeclarationScope(blockStatement), Breakable { +/** + * Scope of validity associated to a block of statements. Variables declared inside a block are not + * visible outside. + */ +class BlockScope(blockStatement: Block) : ValueDeclarationScope(blockStatement), Breakable { private val breaks: MutableList = ArrayList() override fun addBreakStatement(breakStatement: BreakStatement) { diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/ValueDeclarationScope.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/ValueDeclarationScope.kt index 008c4aa2e5..60cac11566 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/ValueDeclarationScope.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/ValueDeclarationScope.kt @@ -86,7 +86,7 @@ open class ValueDeclarationScope(override var astNode: Node?) : Scope(astNode) { There are nodes where we do not set the declaration when storing them in the scope, mostly for structures that have a single value-declaration: WhileStatement, DoStatement, ForStatement, SwitchStatement; and others where the location of declaration is somewhere - deeper in the AST-subtree: CompoundStatement, AssertStatement. + deeper in the AST-subtree: Block, AssertStatement. */ } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/ASMDeclarationStatement.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/ASMDeclarationStatement.kt index 7762cedf89..4c75abff9c 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/ASMDeclarationStatement.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/ASMDeclarationStatement.kt @@ -24,5 +24,5 @@ * */ package de.fraunhofer.aisec.cpg.graph.statements - +// TODO Merge and/or refactor class ASMDeclarationStatement : DeclarationStatement() diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/CatchClause.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/CatchClause.kt index a07ab7525e..5c0619c9f8 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/CatchClause.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/CatchClause.kt @@ -29,12 +29,13 @@ 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.declarations.VariableDeclaration +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block import java.util.Objects class CatchClause : Statement(), BranchingNode { @AST var parameter: VariableDeclaration? = null - @AST var body: CompoundStatement? = null + @AST var body: Block? = null override val branchedBy: Node? get() = parameter 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 8f8f583558..4ec062bea7 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 @@ -39,7 +39,7 @@ class DoStatement : Statement() { /** * The statement that is going to be executed and re-executed, until the condition evaluates to - * false for the first time. Usually a [CompoundStatement]. + * false for the first time. Usually a [Block]. */ @AST var statement: Statement? = null diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/ForEachStatement.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/ForEachStatement.kt index 05cce46a10..8060ed57bc 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/ForEachStatement.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/ForEachStatement.kt @@ -27,7 +27,8 @@ package de.fraunhofer.aisec.cpg.graph.statements import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdge -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import java.util.Objects class ForEachStatement : Statement(), BranchingNode, StatementHolder { @@ -38,7 +39,7 @@ class ForEachStatement : Statement(), BranchingNode, StatementHolder { @AST var variable: Statement? = null set(value) { - if (value is DeclaredReferenceExpression) { + if (value is Reference) { value.access = AccessValues.WRITE } field = value @@ -72,13 +73,13 @@ class ForEachStatement : Statement(), BranchingNode, StatementHolder { iterable = s } else if (statement == null) { statement = s - } else if (statement !is CompoundStatement) { - val newStmt = newCompoundStatement() - statement?.let { newStmt.addStatement(it) } - newStmt.addStatement(s) - statement = newStmt + } else if (statement !is Block) { + val block = newBlock() + statement?.let { block.addStatement(it) } + block.addStatement(s) + statement = block } else { - (statement as? CompoundStatement)?.addStatement(s) + (statement as? Block)?.addStatement(s) } } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/IfStatement.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/IfStatement.kt index 602348d241..88905bc585 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/IfStatement.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/IfStatement.kt @@ -51,15 +51,11 @@ class IfStatement : Statement(), BranchingNode, ArgumentHolder { /** C++ constexpr construct. */ var isConstExpression = false - /** - * The statement that is executed, if the condition is evaluated as true. Usually a - * [CompoundStatement]. - */ + /** The statement that is executed, if the condition is evaluated as true. Usually a [Block]. */ @AST var thenStatement: Statement? = null /** - * The statement that is executed, if the condition is evaluated as false. Usually a - * [CompoundStatement]. + * The statement that is executed, if the condition is evaluated as false. Usually a [Block]. */ @AST var elseStatement: Statement? = null diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/SynchronizedStatement.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/SynchronizedStatement.kt index 7640e2b1ab..c6ed76a482 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/SynchronizedStatement.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/SynchronizedStatement.kt @@ -26,21 +26,20 @@ package de.fraunhofer.aisec.cpg.graph.statements import de.fraunhofer.aisec.cpg.graph.AST +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression import java.util.Objects class SynchronizedStatement : Statement() { @AST var expression: Expression? = null - @AST var blockStatement: CompoundStatement? = null + @AST var block: Block? = null override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is SynchronizedStatement) return false - return super.equals(other) && - expression == other.expression && - blockStatement == other.blockStatement + return super.equals(other) && expression == other.expression && block == other.block } - override fun hashCode() = Objects.hash(super.hashCode(), expression, blockStatement) + override fun hashCode() = Objects.hash(super.hashCode(), expression, block) } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/TryStatement.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/TryStatement.kt index 0ac0dc6643..d92011554d 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/TryStatement.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/TryStatement.kt @@ -29,6 +29,7 @@ import de.fraunhofer.aisec.cpg.graph.AST import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdge import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdge.Companion.propertyEqualsList import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdgeDelegate +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block import java.util.* import org.neo4j.ogm.annotation.Relationship @@ -40,9 +41,9 @@ class TryStatement : Statement() { var resources by PropertyEdgeDelegate(TryStatement::resourceEdges) - @AST var tryBlock: CompoundStatement? = null + @AST var tryBlock: Block? = null - @AST var finallyBlock: CompoundStatement? = null + @AST var finallyBlock: Block? = null @Relationship(value = "CATCH_CLAUSES", direction = Relationship.Direction.OUTGOING) @AST diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/WhileStatement.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/WhileStatement.kt index 14b08f2180..b121990bcb 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/WhileStatement.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/WhileStatement.kt @@ -44,7 +44,7 @@ class WhileStatement : Statement(), BranchingNode, ArgumentHolder { /** * The statement that is going to be executed, until the condition evaluates to false for the - * first time. Usually a [CompoundStatement]. + * first time. Usually a [Block]. */ @AST var statement: Statement? = null diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/AssignExpression.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/AssignExpression.kt index d48ebec724..448ce2e767 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/AssignExpression.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/AssignExpression.kt @@ -60,11 +60,9 @@ class AssignExpression : set(value) { field = value if (operatorCode == "=") { - field.forEach { (it as? DeclaredReferenceExpression)?.access = AccessValues.WRITE } + field.forEach { (it as? Reference)?.access = AccessValues.WRITE } } else { - field.forEach { - (it as? DeclaredReferenceExpression)?.access = AccessValues.READWRITE - } + field.forEach { (it as? Reference)?.access = AccessValues.READWRITE } } } @@ -118,13 +116,13 @@ class AssignExpression : override var declarations = mutableListOf() /** Finds the value (of [rhs]) that is assigned to the particular [lhs] expression. */ - fun findValue(lhsExpr: HasType): Expression? { + fun findValue(lhsExpression: HasType): Expression? { return if (lhs.size > 1) { rhs.singleOrNull() } else { // Basically, we need to find out which index on the lhs this variable belongs to and // find the corresponding index on the rhs. - val idx = lhs.indexOf(lhsExpr) + val idx = lhs.indexOf(lhsExpression) if (idx == -1) { null } else { @@ -134,8 +132,8 @@ class AssignExpression : } /** Finds the targets(s) (within [lhs]) that are assigned to the particular [rhs] expression. */ - fun findTargets(rhsExpr: HasType): List { - val type = rhsExpr.type + fun findTargets(rhsExpression: HasType): List { + val type = rhsExpression.type // There are now two possibilities: Either, we have a tuple type, that we need to // deconstruct, or we have a singular type @@ -152,7 +150,7 @@ class AssignExpression : } else { // Basically, we need to find out which index on the rhs this variable belongs to and // find the corresponding index on the rhs. - val idx = rhs.indexOf(rhsExpr) + val idx = rhs.indexOf(rhsExpression) if (idx == -1) { listOf() } else { diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/BinaryOperator.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/BinaryOperator.kt index dad65f97ee..f728c3f79c 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/BinaryOperator.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/BinaryOperator.kt @@ -78,12 +78,11 @@ open class BinaryOperator : private fun connectNewLhs(lhs: Expression) { lhs.registerTypeObserver(this) - if (lhs is DeclaredReferenceExpression && "=" == operatorCode) { + if (lhs is Reference && "=" == operatorCode) { // declared reference expr is the left-hand side of an assignment -> writing to the var lhs.access = AccessValues.WRITE } else if ( - lhs is DeclaredReferenceExpression && - operatorCode in (language?.compoundAssignmentOperators ?: setOf()) + lhs is Reference && operatorCode in (language?.compoundAssignmentOperators ?: setOf()) ) { // declared reference expr is the left-hand side of an assignment -> writing to the var lhs.access = AccessValues.READWRITE diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/CompoundStatement.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/Block.kt similarity index 88% rename from cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/CompoundStatement.kt rename to cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/Block.kt index 8f8257be8a..81d736fc22 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/CompoundStatement.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/Block.kt @@ -23,14 +23,14 @@ * \______/ \__| \______/ * */ -package de.fraunhofer.aisec.cpg.graph.statements +package de.fraunhofer.aisec.cpg.graph.statements.expressions import de.fraunhofer.aisec.cpg.graph.AST import de.fraunhofer.aisec.cpg.graph.StatementHolder import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdge -import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdge.Companion.propertyEqualsList -import java.util.* +import de.fraunhofer.aisec.cpg.graph.statements.Statement +import java.util.Objects import org.apache.commons.lang3.builder.ToStringBuilder import org.neo4j.ogm.annotation.Relationship @@ -38,7 +38,7 @@ import org.neo4j.ogm.annotation.Relationship * A statement which contains a list of statements. A common example is a function body within a * [FunctionDeclaration]. */ -class CompoundStatement : Statement(), StatementHolder { +class Block : Expression(), StatementHolder { /** The list of statements. */ @Relationship(value = "STATEMENTS", direction = Relationship.Direction.OUTGOING) @AST @@ -59,10 +59,10 @@ class CompoundStatement : Statement(), StatementHolder { override fun equals(other: Any?): Boolean { if (this === other) return true - if (other !is CompoundStatement) return false + if (other !is Block) return false return super.equals(other) && this.statements == other.statements && - propertyEqualsList(statementEdges, other.statementEdges) + PropertyEdge.propertyEqualsList(statementEdges, other.statementEdges) } override fun hashCode() = Objects.hash(super.hashCode(), statements) diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/CallExpression.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/CallExpression.kt index 7b38f9cc39..c98fc1d3a8 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/CallExpression.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/CallExpression.kt @@ -91,9 +91,8 @@ open class CallExpression : Expression(), HasType.TypeObserver, ArgumentHolder { /** * The expression that is being "called". This is currently not yet used in the [CallResolver] - * but will be in the future. In most cases, this is a [DeclaredReferenceExpression] and its - * [DeclaredReferenceExpression.refersTo] is intentionally left empty. It is not filled by the - * [VariableUsageResolver]. + * but will be in the future. In most cases, this is a [Reference] and its [Reference.refersTo] + * is intentionally left empty. It is not filled by the [VariableUsageResolver]. */ @AST var callee: Expression? = null diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/CompoundStatementExpression.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/CompoundStatementExpression.kt deleted file mode 100644 index 584a5a8748..0000000000 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/CompoundStatementExpression.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2020, 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.graph.statements.expressions - -import de.fraunhofer.aisec.cpg.graph.AST -import de.fraunhofer.aisec.cpg.graph.statements.Statement -import java.util.Objects - -/** - * An expression, which calls another function. It has a list of arguments (list of [ ]s) and is - * connected via the INVOKES edge to its [FunctionDeclaration]. - */ -class CompoundStatementExpression : Expression() { - /** The list of arguments. */ - @AST var statement: Statement? = null - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is CompoundStatementExpression) return false - return super.equals(other) && statement == other.statement - } - - override fun hashCode() = Objects.hash(super.hashCode(), statement) -} diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/ConditionalExpression.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/ConditionalExpression.kt index 9ba7a88023..c13474224f 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/ConditionalExpression.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/ConditionalExpression.kt @@ -40,7 +40,7 @@ class ConditionalExpression : Expression(), ArgumentHolder, BranchingNode, HasTy @AST var condition: Expression = ProblemExpression("could not parse condition expression") @AST - var thenExpr: Expression? = null + var thenExpression: Expression? = null set(value) { field?.unregisterTypeObserver(this) field = value @@ -48,7 +48,7 @@ class ConditionalExpression : Expression(), ArgumentHolder, BranchingNode, HasTy } @AST - var elseExpr: Expression? = null + var elseExpression: Expression? = null set(value) { field?.unregisterTypeObserver(this) field = value @@ -59,8 +59,8 @@ class ConditionalExpression : Expression(), ArgumentHolder, BranchingNode, HasTy return ToStringBuilder(this, TO_STRING_STYLE) .appendSuper(super.toString()) .append("condition", condition) - .append("thenExpr", thenExpr) - .append("elseExpr", elseExpr) + .append("thenExpr", thenExpression) + .append("elseExpr", elseExpression) .build() } @@ -79,8 +79,8 @@ class ConditionalExpression : Expression(), ArgumentHolder, BranchingNode, HasTy override fun typeChanged(newType: Type, src: HasType) { val types = mutableSetOf() - thenExpr?.type?.let { types.add(it) } - elseExpr?.type?.let { types.add(it) } + thenExpression?.type?.let { types.add(it) } + elseExpression?.type?.let { types.add(it) } val alternative = if (types.isNotEmpty()) types.first() else unknownType() this.type = types.commonType ?: alternative @@ -88,10 +88,10 @@ class ConditionalExpression : Expression(), ArgumentHolder, BranchingNode, HasTy override fun assignedTypeChanged(assignedTypes: Set, src: HasType) { // Merge and propagate the assigned types of our branches - if (src == thenExpr || src == elseExpr) { + if (src == thenExpression || src == elseExpression) { val types = mutableSetOf() - thenExpr?.assignedTypes?.let { types.addAll(it) } - elseExpr?.assignedTypes?.let { types.addAll(it) } + thenExpression?.assignedTypes?.let { types.addAll(it) } + elseExpression?.assignedTypes?.let { types.addAll(it) } addAssignedTypes(types) } } @@ -101,9 +101,10 @@ class ConditionalExpression : Expression(), ArgumentHolder, BranchingNode, HasTy if (other !is ConditionalExpression) return false return super.equals(other) && condition == other.condition && - thenExpr == other.thenExpr && - elseExpr == other.elseExpr + thenExpression == other.thenExpression && + elseExpression == other.elseExpression } - override fun hashCode() = Objects.hash(super.hashCode(), condition, thenExpr, elseExpr) + override fun hashCode() = + Objects.hash(super.hashCode(), condition, thenExpression, elseExpression) } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/ConstructExpression.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/ConstructExpression.kt index 6c3e413591..e69ab80afd 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/ConstructExpression.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/ConstructExpression.kt @@ -39,6 +39,7 @@ import org.apache.commons.lang3.builder.ToStringBuilder * as part of a [NewExpression]. * * In Java, it is the initializer of a [NewExpression]. */ +// TODO Merge and/or refactor class ConstructExpression : CallExpression() { /** * The link to the [ConstructorDeclaration]. This is populated by the diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/ExplicitConstructorInvocation.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/ConstructorCallExpression.kt similarity index 92% rename from cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/ExplicitConstructorInvocation.kt rename to cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/ConstructorCallExpression.kt index ec3c9a39fd..eda95685eb 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/ExplicitConstructorInvocation.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/ConstructorCallExpression.kt @@ -28,7 +28,8 @@ package de.fraunhofer.aisec.cpg.graph.statements.expressions import java.util.Objects import org.apache.commons.lang3.builder.ToStringBuilder -class ExplicitConstructorInvocation : CallExpression() { +// TODO Merge and/or refactor +class ConstructorCallExpression : CallExpression() { var containingClass: String? = null override fun toString(): String { @@ -40,7 +41,7 @@ class ExplicitConstructorInvocation : CallExpression() { override fun equals(other: Any?): Boolean { if (this === other) return true - if (other !is ExplicitConstructorInvocation) return false + if (other !is ConstructorCallExpression) return false return super.equals(other) && containingClass == other.containingClass } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/DesignatedInitializerExpression.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/DesignatedInitializerExpression.kt index 4b69c0f91d..ecfe7450ad 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/DesignatedInitializerExpression.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/DesignatedInitializerExpression.kt @@ -32,6 +32,7 @@ import java.util.Objects import org.apache.commons.lang3.builder.ToStringBuilder import org.neo4j.ogm.annotation.Relationship +// TODO Merge and/or refactor // TODO: Document this class! class DesignatedInitializerExpression : Expression() { @AST var rhs: Expression? = null diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/InitializerListExpression.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/InitializerListExpression.kt index 9a03dd70a3..d3c064e6be 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/InitializerListExpression.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/InitializerListExpression.kt @@ -42,6 +42,7 @@ import org.neo4j.ogm.annotation.Relationship * accurate as possible when propagating types, the [InitializerListExpression.type] property MUST * be set before adding any values to [InitializerListExpression.initializers]. */ +// TODO Merge and/or refactor class InitializerListExpression : Expression(), ArgumentHolder, HasType.TypeObserver { /** The list of initializers. */ @Relationship(value = "INITIALIZERS", direction = Relationship.Direction.OUTGOING) diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/MemberExpression.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/MemberExpression.kt index 59c9588064..3c599ee29d 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/MemberExpression.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/MemberExpression.kt @@ -39,7 +39,7 @@ import org.apache.commons.lang3.builder.ToStringBuilder * use-case is access of a member function (method) as part of the [MemberCallExpression.callee] * property of a [MemberCallExpression]. */ -class MemberExpression : DeclaredReferenceExpression(), HasBase { +class MemberExpression : Reference(), HasBase { @AST override var base: Expression = ProblemExpression("could not parse base expression") set(value) { diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/ArrayCreationExpression.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/NewArrayExpression.kt similarity index 92% rename from cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/ArrayCreationExpression.kt rename to cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/NewArrayExpression.kt index dcf37a3c17..e2b466ebd8 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/ArrayCreationExpression.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/NewArrayExpression.kt @@ -37,7 +37,8 @@ import org.neo4j.ogm.annotation.Relationship * Expressions of the form `new Type[]` that represents the creation of an array, mostly used in * combination with a [VariableDeclaration]. */ -class ArrayCreationExpression : Expression() { +// TODO Merge and/or refactor with new Expression +class NewArrayExpression : Expression() { /** * The initializer of the expression, if present. Many languages, such as Java, either specify * [dimensions] or an initializer. @@ -58,7 +59,7 @@ class ArrayCreationExpression : Expression() { var dimensionEdges = mutableListOf>() /** Virtual property to access [dimensionEdges] without property edges. */ - var dimensions by PropertyEdgeDelegate(ArrayCreationExpression::dimensionEdges) + var dimensions by PropertyEdgeDelegate(NewArrayExpression::dimensionEdges) /** Adds an [Expression] to the existing [dimensions]. */ fun addDimension(expression: Expression) { @@ -67,7 +68,7 @@ class ArrayCreationExpression : Expression() { override fun equals(other: Any?): Boolean { if (this === other) return true - if (other !is ArrayCreationExpression) return false + if (other !is NewArrayExpression) return false return (super.equals(other) && initializer == other.initializer && dimensions == other.dimensions && diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/RangeExpression.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/RangeExpression.kt index d25e242d2f..7fb5c2e839 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/RangeExpression.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/RangeExpression.kt @@ -29,7 +29,7 @@ import java.util.* /** * Represents the specification of a range (e.g., of an array). Usually used in combination with an - * [ArraySubscriptionExpression] as the [ArraySubscriptionExpression.subscriptExpression]. + * [SubscriptExpression] as the [SubscriptExpression.subscriptExpression]. * * Examples can be found in Go: * ```go diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/DeclaredReferenceExpression.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/Reference.kt similarity index 92% rename from cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/DeclaredReferenceExpression.kt rename to cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/Reference.kt index 0a7b589939..e7c06039fb 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/DeclaredReferenceExpression.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/Reference.kt @@ -41,11 +41,10 @@ import org.neo4j.ogm.annotation.Relationship /** * An expression, which refers to something which is declared, e.g. a variable. For example, the - * expression `a = b`, which itself is an [AssignExpression], contains two - * [DeclaredReferenceExpression]s, one for the variable `a` and one for variable `b`, which have - * been previously been declared. + * expression `a = b`, which itself is an [AssignExpression], contains two [Reference]s, one for the + * variable `a` and one for variable `b`, which have been previously been declared. */ -open class DeclaredReferenceExpression : Expression(), HasType.TypeObserver { +open class Reference : Expression(), HasType.TypeObserver { /** * The [Declaration]s this expression might refer to. This will influence the [declaredType] of * this expression. @@ -82,8 +81,8 @@ open class DeclaredReferenceExpression : Expression(), HasType.TypeObserver { /** * This is a MAJOR workaround needed to resolve function pointers, until we properly re-design - * the call resolver. When this [DeclaredReferenceExpression] contains a function pointer - * reference that is assigned to a variable (or to another reference), we need to set + * the call resolver. When this [Reference] contains a function pointer reference that is + * assigned to a variable (or to another reference), we need to set */ var resolutionHelper: HasType? = null @@ -134,7 +133,7 @@ open class DeclaredReferenceExpression : Expression(), HasType.TypeObserver { if (this === other) { return true } - if (other !is DeclaredReferenceExpression) { + if (other !is Reference) { return false } return super.equals(other) && refersTo == other.refersTo diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/ArraySubscriptionExpression.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/SubscriptExpression.kt similarity index 92% rename from cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/ArraySubscriptionExpression.kt rename to cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/SubscriptExpression.kt index 7206864f2c..bb3c7ddc0c 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/ArraySubscriptionExpression.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/SubscriptExpression.kt @@ -35,11 +35,8 @@ import java.util.* * ([arrayExpression]) and `index` ([subscriptExpression]) are of type [Expression]. CPP can * overload operators thus changing semantics of array access. */ -class ArraySubscriptionExpression : Expression(), HasBase, HasType.TypeObserver, ArgumentHolder { - /** - * The array on which the access is happening. This is most likely a - * [DeclaredReferenceExpression]. - */ +class SubscriptExpression : Expression(), HasBase, HasType.TypeObserver, ArgumentHolder { + /** The array on which the access is happening. This is most likely a [Reference]. */ @AST var arrayExpression: Expression = ProblemExpression("could not parse array expression") set(value) { @@ -51,8 +48,8 @@ class ArraySubscriptionExpression : Expression(), HasBase, HasType.TypeObserver, /** * The expression which represents the "subscription" or index on which the array is accessed. - * This can for example be a reference to another variable ([DeclaredReferenceExpression]), a - * [Literal] or a [RangeExpression]. + * This can for example be a reference to another variable ([Reference]), a [Literal] or a + * [RangeExpression]. */ @AST var subscriptExpression: Expression = ProblemExpression("could not parse index expression") @@ -116,7 +113,7 @@ class ArraySubscriptionExpression : Expression(), HasBase, HasType.TypeObserver, override fun equals(other: Any?): Boolean { if (this === other) return true - if (other !is ArraySubscriptionExpression) return false + if (other !is SubscriptExpression) return false return super.equals(other) && arrayExpression == other.arrayExpression && subscriptExpression == other.subscriptExpression diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/UnaryOperator.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/UnaryOperator.kt index fca3d2deda..6fde30092f 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/UnaryOperator.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/UnaryOperator.kt @@ -62,8 +62,8 @@ class UnaryOperator : Expression(), HasType.TypeObserver { if (operatorCode == "++" || operatorCode == "--") { access = AccessValues.READWRITE } - if (input is DeclaredReferenceExpression) { - (input as? DeclaredReferenceExpression)?.access = access + if (input is Reference) { + (input as? Reference)?.access = access } } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/HasSecondaryTypeEdge.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/HasSecondaryTypeEdge.kt index 2f708cd20f..a4a47c667a 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/HasSecondaryTypeEdge.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/HasSecondaryTypeEdge.kt @@ -25,14 +25,15 @@ */ package de.fraunhofer.aisec.cpg.graph.types -import de.fraunhofer.aisec.cpg.graph.declarations.TypeParamDeclaration +import de.fraunhofer.aisec.cpg.graph.declarations.TypeParameterDeclaration import de.fraunhofer.aisec.cpg.passes.TypeResolver /** * The [TypeResolver] needs to be aware of all outgoing edges to types in order to merge equal types * to the same node. For the primary type edge, this is achieved through the [HasType] interface. If - * a node has additional type edges (e.g. [TypeParamDeclaration.default]) the node must implement - * the [updateType] method, so that the current type is always replaced with the merged one. + * a node has additional type edges (e.g. [TypeParameterDeclaration.default]) the node must + * implement the [updateType] method, so that the current type is always replaced with the merged + * one. */ fun interface HasSecondaryTypeEdge { fun updateType(typeState: Collection) diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/HasType.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/HasType.kt index d5e2b6c78b..dccdae4da2 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/HasType.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/HasType.kt @@ -29,9 +29,9 @@ import de.fraunhofer.aisec.cpg.graph.ContextProvider import de.fraunhofer.aisec.cpg.graph.LanguageProvider import de.fraunhofer.aisec.cpg.graph.Node import de.fraunhofer.aisec.cpg.graph.declarations.ValueDeclaration -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression import de.fraunhofer.aisec.cpg.graph.statements.expressions.Literal +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import de.fraunhofer.aisec.cpg.graph.statements.expressions.UnaryOperator /** @@ -47,8 +47,7 @@ interface HasType : ContextProvider, LanguageProvider { * following: * - the type declared by the [Node], e.g., by a [ValueDeclaration] * - intrinsically tied to the node, e.g. an [IntegerType] in an integer [Literal] - * - the [Type] of a declaration a node is referring to, e.g., in a - * [DeclaredReferenceExpression] + * - the [Type] of a declaration a node is referring to, e.g., in a [Reference] * * An implementation of this must be sure to invoke [informObservers]. */ diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/helpers/Util.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/helpers/Util.kt index ae9e080346..381005c1d0 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/helpers/Util.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/helpers/Util.kt @@ -374,19 +374,19 @@ object Util { * * @param n * @param branchingExp - * @param branchingDecl + * @param branchingDeclaration */ fun addDFGEdgesForMutuallyExclusiveBranchingExpression( n: Node, branchingExp: Node?, - branchingDecl: Node? + branchingDeclaration: Node? ) { var conditionNodes = mutableListOf() if (branchingExp != null) { conditionNodes = mutableListOf() conditionNodes.add(branchingExp) - } else if (branchingDecl != null) { - conditionNodes = getAdjacentDFGNodes(branchingDecl, true) + } else if (branchingDeclaration != null) { + conditionNodes = getAdjacentDFGNodes(branchingDeclaration, true) } conditionNodes.forEach { n.addPrevDFG(it) } } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/CXXCallResolverHelper.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/CXXCallResolverHelper.kt index 17e807fd89..449416d5b4 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/CXXCallResolverHelper.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/CXXCallResolverHelper.kt @@ -304,7 +304,7 @@ fun resolveConstructorWithImplicitCast( * realizations of the Template 3. Set return type of the CallExpression and checks if it uses a * ParameterizedType and therefore has to be instantiated 4. Set Template Parameters Edge from the * CallExpression to all Instantiation Values 5. Set DFG Edges from instantiation to - * ParamVariableDeclaration in TemplateDeclaration + * ParameterDeclaration in TemplateDeclaration * * @param templateCall call to instantiate and invoke a function template * @param functionTemplateDeclaration functionTemplate we have identified that should be @@ -363,10 +363,10 @@ fun applyTemplateInstantiation( } } - // Add DFG edges from the instantiation Expression to the ParamVariableDeclaration in the + // Add DFG edges from the instantiation Expression to the ParameterDeclaration in the // Template. for ((declaration) in initializationSignature) { - if (declaration is ParamVariableDeclaration) { + if (declaration is ParameterDeclaration) { initializationSignature[declaration]?.let { declaration.addPrevDFG(it) } } } @@ -421,15 +421,15 @@ fun signatureWithImplicitCastTransformation( * * @param initialization mapping of the declaration of the template parameters to the explicit * values the template is instantiated with - * @return mapping of the parameterized types to the corresponding TypeParamDeclaration in the + * @return mapping of the parameterized types to the corresponding TypeParameterDeclaration in the * template */ fun getParameterizedSignaturesFromInitialization( initialization: Map -): Map { - val parameterizedSignature: MutableMap = HashMap() +): Map { + val parameterizedSignature: MutableMap = HashMap() for (templateParam in initialization.keys) { - if (templateParam is TypeParamDeclaration) { + if (templateParam is TypeParameterDeclaration) { parameterizedSignature[templateParam.type as ParameterizedType] = templateParam } } @@ -454,7 +454,7 @@ fun getParameterizedSignaturesFromInitialization( * @param explicitInstantiated list of all ParameterizedTypes which are explicitly instantiated * @return mapping containing the all elements of the signature of the TemplateDeclaration as key * and the Type/Expression the Parameter is initialized with. This function returns null if the - * {ParamVariableDeclaration, TypeParamDeclaration} do not match the provided value for + * {ParameterDeclaration, TypeParameterDeclaration} do not match the provided value for * initialization -> initialization not possible */ fun getTemplateInitializationSignature( @@ -516,7 +516,7 @@ fun getTemplateInitializationSignature( * @param explicitInstantiated list of all ParameterizedTypes which are explicitly instantiated * @return mapping containing the all elements of the signature of the TemplateDeclaration as key * and the Type/Expression the Parameter is initialized with. This function returns null if the - * {ParamVariableDeclaration, TypeParamDeclaration} do not match the provided value for + * {ParameterDeclaration, TypeParameterDeclaration} do not match the provided value for * initialization -> initialization not possible */ fun constructTemplateInitializationSignatureFromTemplateParameters( @@ -535,7 +535,7 @@ fun constructTemplateInitializationSignatureFromTemplateParameters( instantiationSignature[templateParameter] = callParameter instantiationType[callParameter] = TemplateDeclaration.TemplateInitialization.EXPLICIT - if (templateParameter is TypeParamDeclaration) { + if (templateParameter is TypeParameterDeclaration) { explicitInstantiated.add(templateParameter.type as ParameterizedType) } orderedInitializationSignature[templateParameter] = i @@ -561,19 +561,19 @@ fun constructTemplateInitializationSignatureFromTemplateParameters( * * @param callParameterArg * @param templateParameter - * @return If the TemplateParameter is an TypeParamDeclaration, the callParameter must be an - * ObjectType => returns true If the TemplateParameter is a ParamVariableDeclaration, the + * @return If the TemplateParameter is an TypeParameterDeclaration, the callParameter must be an + * ObjectType => returns true If the TemplateParameter is a ParameterDeclaration, the * callParameterArg must be an Expression and its type must match the type of the - * ParamVariableDeclaration (same type or subtype) => returns true Otherwise return false + * ParameterDeclaration (same type or subtype) => returns true Otherwise return false */ fun isInstantiated(callParameterArg: Node, templateParameter: Declaration?): Boolean { var callParameter = callParameterArg if (callParameter is TypeExpression) { callParameter = callParameter.type } - return if (callParameter is Type && templateParameter is TypeParamDeclaration) { + return if (callParameter is Type && templateParameter is TypeParameterDeclaration) { callParameter is ObjectType - } else if (callParameter is Expression && templateParameter is ParamVariableDeclaration) { + } else if (callParameter is Expression && templateParameter is ParameterDeclaration) { callParameter.type == templateParameter.type || callParameter.type.isDerivedFrom(templateParameter.type) } else { @@ -625,7 +625,7 @@ fun handleImplicitTemplateParameter( /** * @param function FunctionDeclaration realization of the template - * @param parameterizedTypeResolution mapping of ParameterizedTypes to the TypeParamDeclarations + * @param parameterizedTypeResolution mapping of ParameterizedTypes to the TypeParameterDeclarations * that define them, used to backwards resolve * @param initializationSignature mapping between the ParamDeclaration of the template and the * corresponding instantiations @@ -635,7 +635,7 @@ fun handleImplicitTemplateParameter( */ fun getCallSignature( function: FunctionDeclaration, - parameterizedTypeResolution: Map, + parameterizedTypeResolution: Map, initializationSignature: Map ): List { val templateCallSignature = mutableListOf() diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/CallResolver.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/CallResolver.kt index c951b2b510..b22aa025bd 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/CallResolver.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/CallResolver.kt @@ -140,8 +140,8 @@ open class CallResolver(ctx: TranslationContext) : SymbolResolverPass(ctx) { is TranslationUnitDeclaration -> { currentTU = node } - is ExplicitConstructorInvocation -> { - handleExplicitConstructorInvocation(node) + is ConstructorCallExpression -> { + handleConstructorCallExpression(node) } is ConstructExpression -> { // We might have call expressions inside our arguments, so in order to correctly @@ -223,7 +223,7 @@ open class CallResolver(ctx: TranslationContext) : SymbolResolverPass(ctx) { // Additionally, also set the REFERS_TO of the callee. In the future, we might make more // resolution decisions based on the callee itself. Unfortunately we can only set one here, // so we will take the first one - if (callee is DeclaredReferenceExpression) { + if (callee is Reference) { callee.refersTo = candidates.firstOrNull() } } @@ -241,7 +241,7 @@ open class CallResolver(ctx: TranslationContext) : SymbolResolverPass(ctx) { ): List? { return when (callee) { is MemberExpression -> resolveMemberCallee(callee, curClass, call) - is DeclaredReferenceExpression -> resolveReferenceCallee(callee, curClass, call) + is Reference -> resolveReferenceCallee(callee, curClass, call) null -> { Util.warnWithFileLocation( call, @@ -281,11 +281,11 @@ open class CallResolver(ctx: TranslationContext) : SymbolResolverPass(ctx) { } /** - * Resolves a [CallExpression.callee] of type [DeclaredReferenceExpression] to a possible list - * of [FunctionDeclaration] nodes. + * Resolves a [CallExpression.callee] of type [Reference] to a possible list of + * [FunctionDeclaration] nodes. */ protected fun resolveReferenceCallee( - callee: DeclaredReferenceExpression, + callee: Reference, curClass: RecordDeclaration?, call: CallExpression ): List { @@ -317,7 +317,7 @@ open class CallResolver(ctx: TranslationContext) : SymbolResolverPass(ctx) { * delegates resolving of regular function calls within classes to this function (meh!) */ fun resolveMemberCallee( - callee: DeclaredReferenceExpression, + callee: Reference, curClass: RecordDeclaration?, call: CallExpression ): List { @@ -326,8 +326,8 @@ open class CallResolver(ctx: TranslationContext) : SymbolResolverPass(ctx) { if ( curClass != null && callee is MemberExpression && - callee.base is DeclaredReferenceExpression && - isSuperclassReference(callee.base as DeclaredReferenceExpression) + callee.base is Reference && + isSuperclassReference(callee.base as Reference) ) { (callee.language as? HasSuperClasses)?.handleSuperCall( callee, @@ -429,7 +429,7 @@ open class CallResolver(ctx: TranslationContext) : SymbolResolverPass(ctx) { constructExpression.instantiates = recordDeclaration for (template in templateList) { if ( - template is ClassTemplateDeclaration && + template is RecordTemplateDeclaration && recordDeclaration != null && recordDeclaration in template.realizations && (constructExpression.templateParameters.size <= template.parameters.size) @@ -465,16 +465,18 @@ open class CallResolver(ctx: TranslationContext) : SymbolResolverPass(ctx) { } } - protected fun handleExplicitConstructorInvocation(eci: ExplicitConstructorInvocation) { - eci.containingClass?.let { containingClass -> - val recordDeclaration = recordMap[eci.parseName(containingClass)] - val signature = eci.arguments.map { it.type } + protected fun handleConstructorCallExpression( + constructorCallExpression: ConstructorCallExpression + ) { + constructorCallExpression.containingClass?.let { containingClass -> + val recordDeclaration = recordMap[constructorCallExpression.parseName(containingClass)] + val signature = constructorCallExpression.arguments.map { it.type } if (recordDeclaration != null) { val constructor = getConstructorDeclarationForExplicitInvocation(signature, recordDeclaration) val invokes = mutableListOf() invokes.add(constructor) - eci.invokes = invokes + constructorCallExpression.invokes = invokes } } } @@ -631,7 +633,7 @@ open class CallResolver(ctx: TranslationContext) : SymbolResolverPass(ctx) { /** * Adds implicit duplicates of the TemplateParams to the implicit ConstructExpression * - * @param templateParams of the VariableDeclaration/NewExpression + * @param templateParams of the VariableDeclaration/NewExpressionp * @param constructExpression duplicate TemplateParameters (implicit) to preserve AST, as * ConstructExpression uses AST as well as the VariableDeclaration/NewExpression */ diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/ControlDependenceGraphPass.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/ControlDependenceGraphPass.kt index 6ef8833b2d..a1e12fb5df 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/ControlDependenceGraphPass.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/ControlDependenceGraphPass.kt @@ -52,7 +52,7 @@ open class ControlDependenceGraphPass(ctx: TranslationContext) : TranslationUnit } /** - * Computes the CDG for the given [functionDecl]. It performs the following steps: + * Computes the CDG for the given [functionDeclaration]. It performs the following steps: * 1) Compute the "parent branching node" for each node and through which path the node is * reached * 2) Find out which branch of a [BranchingNode] is actually conditional. The other ones aren't. @@ -62,18 +62,19 @@ open class ControlDependenceGraphPass(ctx: TranslationContext) : TranslationUnit * parent node and the path(s) through which the [BranchingNode] node is reachable. 3.c) * Repeat step 3) until you cannot move the node upwards in the CDG anymore. */ - private fun handle(functionDecl: FunctionDeclaration) { + private fun handle(functionDeclaration: FunctionDeclaration) { // Maps nodes to their "cdg parent" (i.e. the dominator) and also has the information // through which path it is reached. If all outgoing paths of the node's dominator result in // the node, we use the dominator's state instead (i.e., we move the node one layer upwards) val startState = PrevEOGState() startState.push( - functionDecl, - PrevEOGLattice(mapOf(Pair(functionDecl, setOf(functionDecl)))) + functionDeclaration, + PrevEOGLattice(mapOf(Pair(functionDeclaration, setOf(functionDeclaration)))) ) - val finalState = iterateEOG(functionDecl.nextEOGEdges, startState, ::handleEdge) ?: return + val finalState = + iterateEOG(functionDeclaration.nextEOGEdges, startState, ::handleEdge) ?: return - val branchingNodeConditionals = getBranchingNodeConditions(functionDecl) + val branchingNodeConditionals = getBranchingNodeConditions(functionDeclaration) // Collect the information, identify merge points, etc. This is not really efficient yet :( for ((node, dominatorPaths) in finalState) { @@ -84,7 +85,10 @@ open class ControlDependenceGraphPass(ctx: TranslationContext) : TranslationUnit val finalDominators = mutableListOf>>() while (dominatorsList.isNotEmpty()) { val (k, v) = dominatorsList.removeFirst() - if (k != functionDecl && v.containsAll(branchingNodeConditionals[k] ?: setOf())) { + if ( + k != functionDeclaration && + v.containsAll(branchingNodeConditionals[k] ?: setOf()) + ) { // We are reachable from all the branches of branch. Add this parent to the // worklist or update an existing entry. Also consider already existing entries // in finalDominators list and update it (if necessary) @@ -125,12 +129,12 @@ open class ControlDependenceGraphPass(ctx: TranslationContext) : TranslationUnit * * This method collects the merging points. It also includes the function declaration itself. */ - private fun getBranchingNodeConditions(functionDecl: FunctionDeclaration) = + private fun getBranchingNodeConditions(functionDeclaration: FunctionDeclaration) = mapOf( // For the function declaration, there's only the path through the function declaration // itself. - Pair(functionDecl, setOf(functionDecl)), - *functionDecl + Pair(functionDeclaration, setOf(functionDeclaration)), + *functionDeclaration .allChildren() .map { branchingNode -> val mergingPoints = diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/ControlFlowSensitiveDFGPass.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/ControlFlowSensitiveDFGPass.kt index ab0e153547..72317c4760 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/ControlFlowSensitiveDFGPass.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/ControlFlowSensitiveDFGPass.kt @@ -38,10 +38,9 @@ import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract /** - * This pass determines the data flows of DeclaredReferenceExpressions which refer to a - * VariableDeclaration (not a field) while considering the control flow of a function. After this - * path, only such data flows are left which can occur when following the control flow (in terms of - * the EOG) of the program. + * This pass determines the data flows of References which refer to a VariableDeclaration (not a + * field) while considering the control flow of a function. After this path, only such data flows + * are left which can occur when following the control flow (in terms of the EOG) of the program. */ @OptIn(ExperimentalContracts::class) @DependsOn(EvaluationOrderGraphPass::class) @@ -108,10 +107,10 @@ open class ControlFlowSensitiveDFGPass(ctx: TranslationContext) : TranslationUni } /** - * Computes the previous write access of [currentEdge].end if it is a - * [DeclaredReferenceExpression] or [ValueDeclaration] based on the given [state] (which maps - * all variables to its last write instruction). It also updates the [state] if - * [currentEdge].end performs a write-operation to a variable. + * Computes the previous write access of [currentEdge].end if it is a [Reference] or + * [ValueDeclaration] based on the given [state] (which maps all variables to its last write + * instruction). It also updates the [state] if [currentEdge].end performs a write-operation to + * a variable. * * It further determines unnecessary implicit return statement which are added by some frontends * even if every path reaching this point already contains a return statement. @@ -122,7 +121,7 @@ open class ControlFlowSensitiveDFGPass(ctx: TranslationContext) : TranslationUni worklist: Worklist, Node, Set> ): State> { // We will set this if we write to a variable - var writtenDecl: Declaration? + var writtenDeclaration: Declaration? val currentNode = currentEdge.end val doubleState = state as DFGPassState @@ -153,8 +152,7 @@ open class ControlFlowSensitiveDFGPass(ctx: TranslationContext) : TranslationUni // correct mapping, we use the "assignments" property which already searches for us. currentNode.assignments.forEach { assignment -> // This was the last write to the respective declaration. - (assignment.target as? Declaration - ?: (assignment.target as? DeclaredReferenceExpression)?.refersTo) + (assignment.target as? Declaration ?: (assignment.target as? Reference)?.refersTo) ?.let { doubleState.declarationsState[it] = PowersetLattice(setOf(assignment.target as Node)) @@ -163,13 +161,13 @@ open class ControlFlowSensitiveDFGPass(ctx: TranslationContext) : TranslationUni } else if (isIncOrDec(currentNode)) { // Increment or decrement => Add the prevWrite of the input to the input. After the // operation, the prevWrite of the input's variable is this node. - val input = (currentNode as UnaryOperator).input as DeclaredReferenceExpression + val input = (currentNode as UnaryOperator).input as Reference // We write to the variable in the input - writtenDecl = input.refersTo + writtenDeclaration = input.refersTo - if (writtenDecl != null) { - state.push(input, doubleState.declarationsState[writtenDecl]) - doubleState.declarationsState[writtenDecl] = PowersetLattice(setOf(input)) + if (writtenDeclaration != null) { + state.push(input, doubleState.declarationsState[writtenDeclaration]) + doubleState.declarationsState[writtenDeclaration] = PowersetLattice(setOf(input)) } } else if (isCompoundAssignment(currentNode)) { // We write to the lhs, but it also serves as an input => We first get all previous @@ -177,17 +175,17 @@ open class ControlFlowSensitiveDFGPass(ctx: TranslationContext) : TranslationUni // The write operation goes to the variable in the lhs val lhs = currentNode.lhs.singleOrNull() - writtenDecl = (lhs as? DeclaredReferenceExpression)?.refersTo + writtenDeclaration = (lhs as? Reference)?.refersTo - if (writtenDecl != null && lhs != null) { + if (writtenDeclaration != null && lhs != null) { // Data flows from the last writes to the lhs variable to this node - state.push(lhs, doubleState.declarationsState[writtenDecl]) + state.push(lhs, doubleState.declarationsState[writtenDeclaration]) // The whole current node is the place of the last update, not (only) the lhs! - doubleState.declarationsState[writtenDecl] = PowersetLattice(setOf(lhs)) + doubleState.declarationsState[writtenDeclaration] = PowersetLattice(setOf(lhs)) } } else if ( - (currentNode as? DeclaredReferenceExpression)?.access == AccessValues.READ && + (currentNode as? Reference)?.access == AccessValues.READ && currentNode.refersTo is VariableDeclaration && currentNode.refersTo !is FieldDeclaration ) { @@ -211,10 +209,10 @@ open class ControlFlowSensitiveDFGPass(ctx: TranslationContext) : TranslationUni } // We wrote something to this variable declaration - writtenDecl = + writtenDeclaration = when (writtenTo) { is Declaration -> writtenTo - is DeclaredReferenceExpression -> writtenTo.refersTo + is Reference -> writtenTo.refersTo else -> { log.error( "The variable of type ${writtenTo?.javaClass} is not yet supported in the foreach loop" @@ -223,7 +221,7 @@ open class ControlFlowSensitiveDFGPass(ctx: TranslationContext) : TranslationUni } } - if (writtenTo is DeclaredReferenceExpression) { + if (writtenTo is Reference) { // This is a special case: We add the nextEOGEdge which goes out of the loop but // with the old previousWrites map. val nodesOutsideTheLoop = @@ -240,7 +238,7 @@ open class ControlFlowSensitiveDFGPass(ctx: TranslationContext) : TranslationUni state.push(writtenTo, PowersetLattice(setOf(iterable))) // Add the variable declaration (or the reference) to the list of previous // write nodes in this path - state.declarationsState[writtenDecl] = PowersetLattice(setOf(writtenTo)) + state.declarationsState[writtenDeclaration] = PowersetLattice(setOf(writtenTo)) } } } else if (currentNode is FunctionDeclaration) { @@ -268,7 +266,7 @@ open class ControlFlowSensitiveDFGPass(ctx: TranslationContext) : TranslationUni return currentNode is AssignExpression && currentNode.operatorCode in (currentNode.language?.compoundAssignmentOperators ?: setOf()) && - (currentNode.lhs.singleOrNull() as? DeclaredReferenceExpression)?.refersTo != null + (currentNode.lhs.singleOrNull() as? Reference)?.refersTo != null } protected fun isSimpleAssignment(currentNode: Node): Boolean { @@ -280,7 +278,7 @@ open class ControlFlowSensitiveDFGPass(ctx: TranslationContext) : TranslationUni protected fun isIncOrDec(currentNode: Node) = currentNode is UnaryOperator && (currentNode.operatorCode == "++" || currentNode.operatorCode == "--") && - (currentNode.input as? DeclaredReferenceExpression)?.refersTo != null + (currentNode.input as? Reference)?.refersTo != null /** * Removes the DFG edges for a potential implicit return statement if it is not in @@ -291,7 +289,7 @@ open class ControlFlowSensitiveDFGPass(ctx: TranslationContext) : TranslationUni reachableReturnStatements: Collection ) { val lastStatement = - ((node as? FunctionDeclaration)?.body as? CompoundStatement)?.statements?.lastOrNull() + ((node as? FunctionDeclaration)?.body as? Block)?.statements?.lastOrNull() if ( lastStatement is ReturnStatement && lastStatement.isImplicit && diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/DFGPass.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/DFGPass.kt index af73e32043..eb67dd0a3f 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/DFGPass.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/DFGPass.kt @@ -64,11 +64,11 @@ class DFGPass(ctx: TranslationContext) : ComponentPass(ctx) { is CastExpression -> handleCastExpression(node) is BinaryOperator -> handleBinaryOp(node, parent) is AssignExpression -> handleAssignExpression(node) - is ArrayCreationExpression -> handleArrayCreationExpression(node) - is ArraySubscriptionExpression -> handleArraySubscriptionExpression(node) + is NewArrayExpression -> handleNewArrayExpression(node) + is SubscriptExpression -> handleSubscriptExpression(node) is ConditionalExpression -> handleConditionalExpression(node) is MemberExpression -> handleMemberExpression(node, inferDfgForUnresolvedSymbols) - is DeclaredReferenceExpression -> handleDeclaredReferenceExpression(node) + is Reference -> handleReference(node) is ExpressionList -> handleExpressionList(node) is NewExpression -> handleNewExpression(node) // We keep the logic for the InitializerListExpression in that class because the @@ -118,7 +118,7 @@ class DFGPass(ctx: TranslationContext) : ComponentPass(ctx) { /** * For a [MemberExpression], the base flows to the expression if the field is not implemented in - * the code under analysis. Otherwise, it's handled as a [DeclaredReferenceExpression]. + * the code under analysis. Otherwise, it's handled as a [Reference]. */ protected fun handleMemberExpression( node: MemberExpression, @@ -127,7 +127,7 @@ class DFGPass(ctx: TranslationContext) : ComponentPass(ctx) { if (node.refersTo == null && inferDfgForUnresolvedCalls) { node.addPrevDFG(node.base) } else { - handleDeclaredReferenceExpression(node) + handleReference(node) } } @@ -309,12 +309,12 @@ class DFGPass(ctx: TranslationContext) : ComponentPass(ctx) { } /** - * Adds the DFG edges to a [DeclaredReferenceExpression] as follows: + * Adds the DFG edges to a [Reference] as follows: * - If the variable is written to, data flows from this node to the variable declaration. * - If the variable is read from, data flows from the variable declaration to this node. * - For a combined read and write, both edges for data flows are added. */ - protected fun handleDeclaredReferenceExpression(node: DeclaredReferenceExpression) { + protected fun handleReference(node: Reference) { node.refersTo?.let { when (node.access) { AccessValues.WRITE -> node.addNextDFG(it) @@ -332,22 +332,20 @@ class DFGPass(ctx: TranslationContext) : ComponentPass(ctx) { * expression to the whole expression. */ protected fun handleConditionalExpression(node: ConditionalExpression) { - node.thenExpr?.let { node.addPrevDFG(it) } - node.elseExpr?.let { node.addPrevDFG(it) } + node.thenExpression?.let { node.addPrevDFG(it) } + node.elseExpression?.let { node.addPrevDFG(it) } } /** - * Adds the DFG edge to an [ArraySubscriptionExpression]. The whole array `x` flows to the - * result `x[i]`. + * Adds the DFG edge to an [SubscriptExpression]. The whole array `x` flows to the result + * `x[i]`. */ - protected fun handleArraySubscriptionExpression(node: ArraySubscriptionExpression) { + protected fun handleSubscriptExpression(node: SubscriptExpression) { node.addPrevDFG(node.arrayExpression) } - /** - * Adds the DFG edge to an [ArrayCreationExpression]. The initializer flows to the expression. - */ - protected fun handleArrayCreationExpression(node: ArrayCreationExpression) { + /** Adds the DFG edge to an [NewArrayExpression]. The initializer flows to the expression. */ + protected fun handleNewArrayExpression(node: NewArrayExpression) { node.initializer?.let { node.addPrevDFG(it) } } @@ -364,7 +362,7 @@ class DFGPass(ctx: TranslationContext) : ComponentPass(ctx) { // Examples: a + (b = 1) or a = a == b ? b = 2: b = 3 // When the parent is a compound statement (or similar block of code), we can safely // assume that we're not in such a sub-expression - if (parent == null || parent !is CompoundStatement) { + if (parent == null || parent !is Block) { node.rhs.addNextDFG(node) } } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/EvaluationOrderGraphPass.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/EvaluationOrderGraphPass.kt index 527a64a4b4..852cb314cc 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/EvaluationOrderGraphPass.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/EvaluationOrderGraphPass.kt @@ -60,8 +60,8 @@ import org.slf4j.LoggerFactory * * For methods without explicit return statement, EOF will have an edge to a virtual return node * with line number -1 which does not exist in the original code. A CFG will always end with the * last reachable statement(s) and not insert any virtual return statements. - * * EOG considers an opening blocking ("CompoundStatement", indicated by a "{") as a separate node. - * A CFG will rather use the first actual executable statement within the block. + * * EOG considers an opening blocking ("Block", indicated by a "{") as a separate node. A CFG will + * rather use the first actual executable statement within the block. * * For IF statements, EOG treats the "if" keyword and the condition as separate nodes. CFG treats * this as one "if" statement. * * EOG considers a method header as a node. CFG will consider the first executable statement of @@ -108,12 +108,10 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa } map[CallExpression::class.java] = { handleCallExpression(it as CallExpression) } map[MemberExpression::class.java] = { handleMemberExpression(it as MemberExpression) } - map[ArraySubscriptionExpression::class.java] = { - handleArraySubscriptionExpression(it as ArraySubscriptionExpression) - } - map[ArrayCreationExpression::class.java] = { - handleArrayCreationExpression(it as ArrayCreationExpression) + map[SubscriptExpression::class.java] = { + handleSubscriptExpression(it as SubscriptExpression) } + map[NewArrayExpression::class.java] = { handleNewArrayExpression(it as NewArrayExpression) } map[RangeExpression::class.java] = { handleRangeExpression(it as RangeExpression) } map[DeclarationStatement::class.java] = { handleDeclarationStatement(it as DeclarationStatement) @@ -122,10 +120,7 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa map[BinaryOperator::class.java] = { handleBinaryOperator(it as BinaryOperator) } map[AssignExpression::class.java] = { handleAssignExpression(it as AssignExpression) } map[UnaryOperator::class.java] = { handleUnaryOperator(it as UnaryOperator) } - map[CompoundStatement::class.java] = { handleCompoundStatement(it as CompoundStatement) } - map[CompoundStatementExpression::class.java] = { - handleCompoundStatementExpression(it as CompoundStatementExpression) - } + map[Block::class.java] = { handleBlock(it as Block) } map[IfStatement::class.java] = { handleIfStatement(it as IfStatement) } map[AssertStatement::class.java] = { handleAssertStatement(it as AssertStatement) } map[WhileStatement::class.java] = { handleWhileStatement(it as WhileStatement) } @@ -160,7 +155,7 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa map[Literal::class.java] = { handleDefault(it) } map[DefaultStatement::class.java] = { handleDefault(it) } map[TypeIdExpression::class.java] = { handleDefault(it) } - map[DeclaredReferenceExpression::class.java] = { handleDefault(it) } + map[Reference::class.java] = { handleDefault(it) } map[LambdaExpression::class.java] = { handleLambdaExpression(it as LambdaExpression) } } @@ -270,7 +265,7 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa // although they can be placed in the same enclosing declaration. val code = statementHolder.statements - val nonStaticCode = code.filter { (it as? CompoundStatement)?.isStaticBlock == false } + val nonStaticCode = code.filter { (it as? Block)?.isStaticBlock == false } val staticCode = code.filter { it !in nonStaticCode } pushToEOG(statementHolder as Node) @@ -421,7 +416,7 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa pushToEOG(node) } - protected fun handleArraySubscriptionExpression(node: ArraySubscriptionExpression) { + protected fun handleSubscriptExpression(node: SubscriptExpression) { // Connect according to evaluation order, first the array reference, then the contained // index. createEOG(node.arrayExpression) @@ -429,7 +424,7 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa pushToEOG(node) } - protected fun handleArrayCreationExpression(node: ArrayCreationExpression) { + protected fun handleNewArrayExpression(node: NewArrayExpression) { for (dimension in node.dimensions) { createEOG(dimension) } @@ -526,7 +521,7 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa pushToEOG(node) } - protected fun handleCompoundStatement(node: CompoundStatement) { + protected fun handleBlock(node: Block) { // not all language handle compound statements as scoping blocks, so we need to avoid // creating new scopes here scopeManager.enterScopeIfExists(node) @@ -581,11 +576,6 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa pushToEOG(node) } - protected fun handleCompoundStatementExpression(node: CompoundStatementExpression) { - createEOG(node.statement) - pushToEOG(node) - } - protected fun handleAssertStatement(node: AssertStatement) { createEOG(node.condition) val openConditionEOGs = ArrayList(currentPredecessors) @@ -819,7 +809,7 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa protected fun handleSynchronizedStatement(node: SynchronizedStatement) { createEOG(node.expression) pushToEOG(node) - createEOG(node.blockStatement) + createEOG(node.block) } protected fun handleConditionalExpression(node: ConditionalExpression) { @@ -829,11 +819,11 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa pushToEOG(node) val openConditionEOGs = ArrayList(currentPredecessors) nextEdgeProperties[Properties.BRANCH] = true - createEOG(node.thenExpr) + createEOG(node.thenExpression) openBranchNodes.addAll(currentPredecessors) setCurrentEOGs(openConditionEOGs) nextEdgeProperties[Properties.BRANCH] = false - createEOG(node.elseExpr) + createEOG(node.elseExpression) openBranchNodes.addAll(currentPredecessors) setCurrentEOGs(openBranchNodes) } @@ -935,9 +925,9 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa val compound = if (node.statement is DoStatement) { createEOG(node.statement) - (node.statement as DoStatement).statement as CompoundStatement + (node.statement as DoStatement).statement as Block } else { - node.statement as CompoundStatement + node.statement as Block } currentPredecessors = ArrayList() for (subStatement in compound.statements) { diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/ImportResolver.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/ImportResolver.kt index 65ae374e2e..85312e8555 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/ImportResolver.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/ImportResolver.kt @@ -57,9 +57,11 @@ open class ImportResolver(ctx: TranslationContext) : ComponentPass(ctx) { } } - protected fun getStaticImports(recordDecl: RecordDeclaration): MutableSet { + protected fun getStaticImports( + recordDeclaration: RecordDeclaration + ): MutableSet { val partitioned = - recordDecl.staticImportStatements.groupBy { it.endsWith("*") }.toMutableMap() + recordDeclaration.staticImportStatements.groupBy { it.endsWith("*") }.toMutableMap() val staticImports = mutableSetOf() val importPattern = Pattern.compile("(?.*)\\.(?.*)") diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/SymbolResolverPass.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/SymbolResolverPass.kt index 3f04655003..3746a4b45d 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/SymbolResolverPass.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/SymbolResolverPass.kt @@ -29,7 +29,7 @@ import de.fraunhofer.aisec.cpg.TranslationContext import de.fraunhofer.aisec.cpg.frontends.HasSuperClasses import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.declarations.* -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import de.fraunhofer.aisec.cpg.graph.types.* import de.fraunhofer.aisec.cpg.helpers.SubgraphWalker import de.fraunhofer.aisec.cpg.passes.order.DependsOn @@ -99,7 +99,7 @@ abstract class SymbolResolverPass(ctx: TranslationContext) : ComponentPass(ctx) /** * Determines if the [reference] refers to the super class and we have to start searching there. */ - protected fun isSuperclassReference(reference: DeclaredReferenceExpression): Boolean { + protected fun isSuperclassReference(reference: Reference): Boolean { val language = reference.language return language is HasSuperClasses && reference.name.endsWith(language.superClassKeyword) } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/TemplateCallResolverHelper.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/TemplateCallResolverHelper.kt index ad5b11dacd..d0887d7cf2 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/TemplateCallResolverHelper.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/TemplateCallResolverHelper.kt @@ -26,13 +26,13 @@ package de.fraunhofer.aisec.cpg.passes import de.fraunhofer.aisec.cpg.graph.Node -import de.fraunhofer.aisec.cpg.graph.declarations.ClassTemplateDeclaration -import de.fraunhofer.aisec.cpg.graph.declarations.ParamVariableDeclaration +import de.fraunhofer.aisec.cpg.graph.declarations.ParameterDeclaration +import de.fraunhofer.aisec.cpg.graph.declarations.RecordTemplateDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.TemplateDeclaration -import de.fraunhofer.aisec.cpg.graph.declarations.TypeParamDeclaration +import de.fraunhofer.aisec.cpg.graph.declarations.TypeParameterDeclaration import de.fraunhofer.aisec.cpg.graph.objectType import de.fraunhofer.aisec.cpg.graph.statements.expressions.ConstructExpression -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import de.fraunhofer.aisec.cpg.graph.statements.expressions.TypeExpression import de.fraunhofer.aisec.cpg.graph.types.ObjectType import de.fraunhofer.aisec.cpg.graph.types.Type @@ -47,7 +47,7 @@ import de.fraunhofer.aisec.cpg.graph.types.Type */ fun addRecursiveDefaultTemplateArgs( constructExpression: ConstructExpression, - template: ClassTemplateDeclaration + template: RecordTemplateDeclaration ) { var templateParameters: Int do { @@ -84,15 +84,15 @@ fun addRecursiveDefaultTemplateArgs( */ fun handleExplicitTemplateParameters( constructExpression: ConstructExpression, - template: ClassTemplateDeclaration, + template: RecordTemplateDeclaration, templateParametersExplicitInitialization: MutableMap ) { for (i in constructExpression.templateParameters.indices) { val explicit = constructExpression.templateParameters[i] - if (template.parameters[i] is TypeParamDeclaration) { + if (template.parameters[i] is TypeParameterDeclaration) { templateParametersExplicitInitialization[ - (template.parameters[i] as TypeParamDeclaration).type] = explicit - } else if (template.parameters[i] is ParamVariableDeclaration) { + (template.parameters[i] as TypeParameterDeclaration).type] = explicit + } else if (template.parameters[i] is ParameterDeclaration) { templateParametersExplicitInitialization[template.parameters[i]] = explicit } } @@ -109,7 +109,7 @@ fun handleExplicitTemplateParameters( * default (no recursive) */ fun applyMissingParams( - template: ClassTemplateDeclaration, + template: RecordTemplateDeclaration, constructExpression: ConstructExpression, templateParametersExplicitInitialization: Map, templateParameterRealDefaultInitialization: Map @@ -122,7 +122,7 @@ fun applyMissingParams( ) for (m in missingParams) { var missingParam = m - if (missingParam is DeclaredReferenceExpression) { + if (missingParam is Reference) { missingParam = missingParam.refersTo } if (missingParam in templateParametersExplicitInitialization) { @@ -172,14 +172,14 @@ fun applyMissingParams( * default (no recursive) */ fun handleDefaultTemplateParameters( - template: ClassTemplateDeclaration, + template: RecordTemplateDeclaration, templateParameterRealDefaultInitialization: MutableMap ) { val declaredTemplateTypes = mutableListOf() - val declaredNonTypeTemplate = mutableListOf() + val declaredNonTypeTemplate = mutableListOf() val parametersWithDefaults = template.parametersWithDefaults for (declaration in template.parameters) { - if (declaration is TypeParamDeclaration) { + if (declaration is TypeParameterDeclaration) { declaredTemplateTypes.add(declaration.type) if ( declaration.default !in declaredTemplateTypes && @@ -187,13 +187,12 @@ fun handleDefaultTemplateParameters( ) { templateParameterRealDefaultInitialization[declaration.type] = declaration.default } - } else if (declaration is ParamVariableDeclaration) { + } else if (declaration is ParameterDeclaration) { declaredNonTypeTemplate.add(declaration) if ( declaration in parametersWithDefaults && - (declaration.default !is DeclaredReferenceExpression || - (declaration.default as DeclaredReferenceExpression?)?.refersTo !in - declaredNonTypeTemplate) + (declaration.default !is Reference || + (declaration.default as Reference?)?.refersTo !in declaredNonTypeTemplate) ) { templateParameterRealDefaultInitialization[declaration] = declaration.default } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/TypeHierarchyResolver.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/TypeHierarchyResolver.kt index 026e9bbb92..54c922dc08 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/TypeHierarchyResolver.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/TypeHierarchyResolver.kt @@ -101,10 +101,14 @@ open class TypeHierarchyResolver(ctx: TranslationContext) : ComponentPass(ctx) { return supertypeRecords.map { it.methods }.flatten() } - protected fun findSupertypeRecords(recordDecl: RecordDeclaration): Set { + protected fun findSupertypeRecords( + recordDeclaration: RecordDeclaration + ): Set { val superTypeDeclarations = - recordDecl.superTypes.mapNotNull { (it as? ObjectType)?.recordDeclaration }.toSet() - recordDecl.superTypeDeclarations = superTypeDeclarations + recordDeclaration.superTypes + .mapNotNull { (it as? ObjectType)?.recordDeclaration } + .toSet() + recordDeclaration.superTypeDeclarations = superTypeDeclarations return superTypeDeclarations } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/VariableUsageResolver.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/VariableUsageResolver.kt index d28e6c1e49..80c6b2a30a 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/VariableUsageResolver.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/VariableUsageResolver.kt @@ -31,9 +31,9 @@ import de.fraunhofer.aisec.cpg.frontends.HasSuperClasses import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.declarations.* import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.MemberCallExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.MemberExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import de.fraunhofer.aisec.cpg.graph.types.* import de.fraunhofer.aisec.cpg.helpers.SubgraphWalker.ScopedWalker import de.fraunhofer.aisec.cpg.helpers.Util @@ -46,17 +46,17 @@ import org.slf4j.LoggerFactory * Creates new connections between the place where a variable is declared and where it is used. * * A field access is modeled with a [MemberExpression]. After AST building, its base and member - * references are set to [DeclaredReferenceExpression] stubs. This pass resolves those references - * and makes the member point to the appropriate [FieldDeclaration] and the base to the "this" - * [FieldDeclaration] of the containing class. It is also capable of resolving references to fields - * that are inherited from a superclass and thus not declared in the actual base class. When base or - * member declarations are not found in the graph, a new "inferred" [FieldDeclaration] is being - * created that is then used to collect all usages to the same unknown declaration. - * [DeclaredReferenceExpression] stubs are removed from the graph after being resolved. + * references are set to [Reference] stubs. This pass resolves those references and makes the member + * point to the appropriate [FieldDeclaration] and the base to the "this" [FieldDeclaration] of the + * containing class. It is also capable of resolving references to fields that are inherited from a + * superclass and thus not declared in the actual base class. When base or member declarations are + * not found in the graph, a new "inferred" [FieldDeclaration] is being created that is then used to + * collect all usages to the same unknown declaration. [Reference] stubs are removed from the graph + * after being resolved. * - * Accessing a local variable is modeled directly with a [DeclaredReferenceExpression]. This step of - * the pass doesn't remove the [DeclaredReferenceExpression] nodes like in the field usage case but - * rather makes their "refersTo" point to the appropriate [ValueDeclaration]. + * Accessing a local variable is modeled directly with a [Reference]. This step of the pass doesn't + * remove the [Reference] nodes like in the field usage case but rather makes their "refersTo" point + * to the appropriate [ValueDeclaration]. */ @DependsOn(TypeHierarchyResolver::class) open class VariableUsageResolver(ctx: TranslationContext) : SymbolResolverPass(ctx) { @@ -89,7 +89,7 @@ open class VariableUsageResolver(ctx: TranslationContext) : SymbolResolverPass(c /** This function seems to resolve function pointers pointing to a [MethodDeclaration]. */ protected fun resolveMethodFunctionPointer( - reference: DeclaredReferenceExpression, + reference: Reference, type: FunctionPointerType ): ValueDeclaration { val parent = reference.name.parent @@ -112,7 +112,7 @@ open class VariableUsageResolver(ctx: TranslationContext) : SymbolResolverPass(c ) { val language = current?.language - if (current !is DeclaredReferenceExpression || current is MemberExpression) return + if (current !is Reference || current is MemberExpression) return // For now, we need to ignore reference expressions that are directly embedded into call // expressions, because they are the "callee" property. In the future, we will use this @@ -223,8 +223,8 @@ open class VariableUsageResolver(ctx: TranslationContext) : SymbolResolverPass(c } var baseTarget: Declaration? = null - if (current.base is DeclaredReferenceExpression) { - val base = current.base as DeclaredReferenceExpression + if (current.base is Reference) { + val base = current.base as Reference if ( current.language is HasSuperClasses && base.name.toString() == (current.language as HasSuperClasses).superClassKeyword @@ -264,7 +264,7 @@ open class VariableUsageResolver(ctx: TranslationContext) : SymbolResolverPass(c base.type = objectType } } else { - baseTarget = resolveBase(current.base as DeclaredReferenceExpression) + baseTarget = resolveBase(current.base as Reference) base.refersTo = baseTarget } if (baseTarget is EnumDeclaration) { @@ -298,7 +298,7 @@ open class VariableUsageResolver(ctx: TranslationContext) : SymbolResolverPass(c current.refersTo = resolveMember(baseType, current) } - protected fun resolveBase(reference: DeclaredReferenceExpression): Declaration? { + protected fun resolveBase(reference: Reference): Declaration? { val declaration = scopeManager.resolveReference(reference) if (declaration != null) { return declaration @@ -314,10 +314,7 @@ open class VariableUsageResolver(ctx: TranslationContext) : SymbolResolverPass(c } } - protected fun resolveMember( - containingClass: Type, - reference: DeclaredReferenceExpression - ): ValueDeclaration? { + protected fun resolveMember(containingClass: Type, reference: Reference): ValueDeclaration? { if (isSuperclassReference(reference)) { // if we have a "super" on the member side, this is a member call. We need to resolve // this in the call resolver instead @@ -346,10 +343,7 @@ open class VariableUsageResolver(ctx: TranslationContext) : SymbolResolverPass(c } // TODO(oxisto): Move to inference class - protected fun handleUnknownField( - base: Type, - ref: DeclaredReferenceExpression - ): FieldDeclaration? { + protected fun handleUnknownField(base: Type, ref: Reference): FieldDeclaration? { val name = ref.name // unwrap a potential pointer-type diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/inference/Inference.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/inference/Inference.kt index eb40b5606e..d8783edbe6 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/inference/Inference.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/inference/Inference.kt @@ -168,7 +168,7 @@ class Inference(val start: Node, override val ctx: TranslationContext) : for (i in signature.indices) { val targetType = signature[i] ?: UnknownType.getUnknownType(function.language) val paramName = generateParamName(i, targetType) - val param = newParamVariableDeclaration(paramName, targetType, false, "") + val param = newParameterDeclaration(paramName, targetType, false, "") param.argumentIndex = i scopeManager.addDeclaration(param) @@ -222,7 +222,7 @@ class Inference(val start: Node, override val ctx: TranslationContext) : return paramName.toString() } - private fun inferNonTypeTemplateParameter(name: String): ParamVariableDeclaration { + private fun inferNonTypeTemplateParameter(name: String): ParameterDeclaration { val expr = start as? Expression ?: throw UnsupportedOperationException( @@ -230,16 +230,16 @@ class Inference(val start: Node, override val ctx: TranslationContext) : ) // Non-Type Template Parameter - return newParamVariableDeclaration(name, expr.type, false, name) + return newParameterDeclaration(name, expr.type, false, name) } private fun inferTemplateParameter( name: String, - ): TypeParamDeclaration { + ): TypeParameterDeclaration { val parameterizedType = ParameterizedType(name, language) typeManager.addTypeParameter(start as FunctionTemplateDeclaration, parameterizedType) - val decl = newTypeParamDeclaration(name, name) + val decl = newTypeParameterDeclaration(name, name) decl.type = parameterizedType return decl diff --git a/cpg-core/src/main/resources/META-INF/native-image/de.fraunhofer.aisec/cpg/reflect-config.json b/cpg-core/src/main/resources/META-INF/native-image/de.fraunhofer.aisec/cpg/reflect-config.json index b67c695ecf..5aadb249d7 100644 --- a/cpg-core/src/main/resources/META-INF/native-image/de.fraunhofer.aisec/cpg/reflect-config.json +++ b/cpg-core/src/main/resources/META-INF/native-image/de.fraunhofer.aisec/cpg/reflect-config.json @@ -80,7 +80,7 @@ "allDeclaredMethods": true }, { - "name": "de.fraunhofer.aisec.cpg.graph.ArrayCreationExpression", + "name": "de.fraunhofer.aisec.cpg.graph.NewArrayExpression", "allDeclaredFields": true, "allDeclaredMethods": true }, @@ -90,7 +90,7 @@ "allDeclaredMethods": true }, { - "name": "de.fraunhofer.aisec.cpg.graph.ArraySubscriptionExpression", + "name": "de.fraunhofer.aisec.cpg.graph.SubscriptExpression", "allDeclaredFields": true, "allDeclaredMethods": true }, @@ -130,12 +130,12 @@ "allDeclaredMethods": true }, { - "name": "de.fraunhofer.aisec.cpg.graph.CompoundStatement", + "name": "de.fraunhofer.aisec.cpg.graph.BlockStatement", "allDeclaredFields": true, "allDeclaredMethods": true }, { - "name": "de.fraunhofer.aisec.cpg.graph.CompoundStatementExpression", + "name": "de.fraunhofer.aisec.cpg.graph.BlockStatementExpression", "allDeclaredFields": true, "allDeclaredMethods": true }, @@ -170,7 +170,7 @@ "allDeclaredMethods": true }, { - "name": "de.fraunhofer.aisec.cpg.graph.DeclaredReferenceExpression", + "name": "de.fraunhofer.aisec.cpg.graph.Reference", "allDeclaredFields": true, "allDeclaredMethods": true }, @@ -213,7 +213,7 @@ "allDeclaredMethods": true }, { - "name": "de.fraunhofer.aisec.cpg.graph.ExplicitConstructorInvocation", + "name": "de.fraunhofer.aisec.cpg.graph.ConstructorCallExpression", "allDeclaredFields": true, "allDeclaredMethods": true }, @@ -323,7 +323,7 @@ "allDeclaredMethods": true }, { - "name": "de.fraunhofer.aisec.cpg.graph.ParamVariableDeclaration", + "name": "de.fraunhofer.aisec.cpg.graph.ParameterDeclaration", "allDeclaredFields": true, "allDeclaredMethods": true }, diff --git a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/FluentTest.kt b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/FluentTest.kt index 63bb5d4eec..f9be5aa68a 100644 --- a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/FluentTest.kt +++ b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/FluentTest.kt @@ -33,7 +33,6 @@ import de.fraunhofer.aisec.cpg.graph.declarations.VariableDeclaration import de.fraunhofer.aisec.cpg.graph.scopes.BlockScope import de.fraunhofer.aisec.cpg.graph.scopes.FunctionScope import de.fraunhofer.aisec.cpg.graph.scopes.GlobalScope -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement import de.fraunhofer.aisec.cpg.graph.statements.DeclarationStatement import de.fraunhofer.aisec.cpg.graph.statements.IfStatement import de.fraunhofer.aisec.cpg.graph.statements.ReturnStatement @@ -82,7 +81,7 @@ class FluentTest { assertLocalName("argc", argc) assertLocalName("int", argc.type) - val body = main.body as? CompoundStatement + val body = main.body as? Block assertNotNull(body) assertTrue { body.scope is FunctionScope @@ -130,7 +129,7 @@ class FluentTest { assertNotNull(printf) assertEquals("else", printf.arguments[0]>()?.value) - var ref = condition.lhs() + var ref = condition.lhs() assertNotNull(ref) assertLocalName("argc", ref) @@ -157,7 +156,7 @@ class FluentTest { assertNotNull(binOp.scope) assertEquals("+", binOp.operatorCode) - ref = binOp.lhs as? DeclaredReferenceExpression + ref = binOp.lhs as? Reference assertNotNull(ref) assertNotNull(ref.scope) assertNull(ref.refersTo) diff --git a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/ShortcutsTest.kt b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/ShortcutsTest.kt index 49ba3c23a7..0663cc55eb 100644 --- a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/ShortcutsTest.kt +++ b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/ShortcutsTest.kt @@ -31,7 +31,6 @@ import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.MethodDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.VariableDeclaration -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement import de.fraunhofer.aisec.cpg.graph.statements.DeclarationStatement import de.fraunhofer.aisec.cpg.graph.statements.IfStatement import de.fraunhofer.aisec.cpg.graph.statements.expressions.* @@ -69,15 +68,14 @@ class ShortcutsTest { val main = classDecl.byNameOrNull("main") assertNotNull(main) expected.add( - ((((main.body as CompoundStatement).statements[0] as DeclarationStatement) - .declarations[0] + ((((main.body as Block).statements[0] as DeclarationStatement).declarations[0] as VariableDeclaration) .initializer as NewExpression) .initializer as ConstructExpression ) - expected.add((main.body as CompoundStatement).statements[1] as MemberCallExpression) - expected.add((main.body as CompoundStatement).statements[2] as MemberCallExpression) - expected.add((main.body as CompoundStatement).statements[3] as MemberCallExpression) + expected.add((main.body as Block).statements[1] as MemberCallExpression) + expected.add((main.body as Block).statements[2] as MemberCallExpression) + expected.add((main.body as Block).statements[3] as MemberCallExpression) val print = classDecl.byNameOrNull("print") assertNotNull(print) @@ -88,7 +86,7 @@ class ShortcutsTest { assertTrue(actual.containsAll(expected)) assertEquals( - listOf((main.body as CompoundStatement).statements[1] as MemberCallExpression), + listOf((main.body as Block).statements[1] as MemberCallExpression), expected("print") ) } @@ -104,7 +102,7 @@ class ShortcutsTest { assertNotNull(classDecl) val main = classDecl.byNameOrNull("main") assertNotNull(main) - expected.add((main.body as CompoundStatement).statements[1] as MemberCallExpression) + expected.add((main.body as Block).statements[1] as MemberCallExpression) assertTrue(expected.containsAll(actual)) assertTrue(actual.containsAll(expected)) } @@ -131,8 +129,7 @@ class ShortcutsTest { val actual = main.callees expected.add( - (((((main.body as CompoundStatement).statements[0] as DeclarationStatement) - .declarations[0] + (((((main.body as Block).statements[0] as DeclarationStatement).declarations[0] as VariableDeclaration) .initializer as NewExpression) .initializer as ConstructExpression) @@ -177,18 +174,17 @@ class ShortcutsTest { assertNotNull(classDecl) val magic = classDecl.byNameOrNull("magic") assertNotNull(magic) - val ifStatement = (magic.body as CompoundStatement).statements[0] as IfStatement + val ifStatement = (magic.body as Block).statements[0] as IfStatement val actual = ifStatement.controls() ifStatement.thenStatement?.let { expected.add(it) } - val thenStatement = - (ifStatement.thenStatement as CompoundStatement).statements[0] as IfStatement + val thenStatement = (ifStatement.thenStatement as Block).statements[0] as IfStatement expected.add(thenStatement) thenStatement.condition?.let { expected.add(it) } expected.add((thenStatement.condition as BinaryOperator).lhs) expected.add(((thenStatement.condition as BinaryOperator).lhs as MemberExpression).base) expected.add((thenStatement.condition as BinaryOperator).rhs) - val nestedThen = thenStatement.thenStatement as CompoundStatement + val nestedThen = thenStatement.thenStatement as Block expected.add(nestedThen) expected.add(nestedThen.statements[0]) expected.add((nestedThen.statements[0] as AssignExpression).lhs.first()) @@ -196,7 +192,7 @@ class ShortcutsTest { ((nestedThen.statements[0] as AssignExpression).lhs.first() as MemberExpression).base ) expected.add((nestedThen.statements[0] as AssignExpression).rhs.first()) - val nestedElse = thenStatement.elseStatement as CompoundStatement + val nestedElse = thenStatement.elseStatement as Block expected.add(nestedElse) expected.add(nestedElse.statements[0]) expected.add((nestedElse.statements[0] as AssignExpression).lhs.first()) @@ -206,22 +202,17 @@ class ShortcutsTest { expected.add((nestedElse.statements[0] as AssignExpression).rhs.first()) ifStatement.elseStatement?.let { expected.add(it) } - expected.add((ifStatement.elseStatement as CompoundStatement).statements[0]) + expected.add((ifStatement.elseStatement as Block).statements[0]) expected.add( - ((ifStatement.elseStatement as CompoundStatement).statements[0] as AssignExpression) - .lhs - .first() + ((ifStatement.elseStatement as Block).statements[0] as AssignExpression).lhs.first() ) expected.add( - (((ifStatement.elseStatement as CompoundStatement).statements[0] as AssignExpression) - .lhs - .first() as MemberExpression) + (((ifStatement.elseStatement as Block).statements[0] as AssignExpression).lhs.first() + as MemberExpression) .base ) expected.add( - ((ifStatement.elseStatement as CompoundStatement).statements[0] as AssignExpression) - .rhs - .first() + ((ifStatement.elseStatement as Block).statements[0] as AssignExpression).rhs.first() ) assertTrue(expected.containsAll(actual)) @@ -246,10 +237,9 @@ class ShortcutsTest { assertNotNull(magic) // get the statement attr = 3; - val ifStatement = (magic.body as CompoundStatement).statements[0] as IfStatement - val thenStatement = - (ifStatement.thenStatement as CompoundStatement).statements[0] as IfStatement - val nestedThen = thenStatement.thenStatement as CompoundStatement + val ifStatement = (magic.body as Block).statements[0] as IfStatement + val thenStatement = (ifStatement.thenStatement as Block).statements[0] as IfStatement + val nestedThen = thenStatement.thenStatement as Block val interestingNode = nestedThen.statements[0] val actual = interestingNode.controlledBy() @@ -268,8 +258,7 @@ class ShortcutsTest { assertNotNull(magic2) val aAssignment2 = - ((((magic2.body as CompoundStatement).statements[1] as IfStatement).elseStatement - as CompoundStatement) + ((((magic2.body as Block).statements[1] as IfStatement).elseStatement as Block) .statements[0] as AssignExpression) .lhs @@ -284,8 +273,7 @@ class ShortcutsTest { assertNotNull(magic) val attrAssignment = - ((((magic.body as CompoundStatement).statements[0] as IfStatement).elseStatement - as CompoundStatement) + ((((magic.body as Block).statements[0] as IfStatement).elseStatement as Block) .statements[0] as AssignExpression) .lhs @@ -305,8 +293,7 @@ class ShortcutsTest { assertNotNull(magic) val attrAssignment = - ((((magic.body as CompoundStatement).statements[0] as IfStatement).elseStatement - as CompoundStatement) + ((((magic.body as Block).statements[0] as IfStatement).elseStatement as Block) .statements[0] as AssignExpression) .lhs @@ -329,15 +316,14 @@ class ShortcutsTest { assertNotNull(magic) val ifCondition = - ((magic.body as CompoundStatement).statements[0] as IfStatement).condition - as BinaryOperator + ((magic.body as Block).statements[0] as IfStatement).condition as BinaryOperator val paramPassed = ifCondition.followNextEOGEdgesUntilHit { it is AssignExpression && it.operatorCode == "=" && - (it.rhs.first() as? DeclaredReferenceExpression)?.refersTo == - (ifCondition.lhs as DeclaredReferenceExpression).refersTo + (it.rhs.first() as? Reference)?.refersTo == + (ifCondition.lhs as Reference).refersTo } assertEquals(1, paramPassed.fulfilled.size) assertEquals(2, paramPassed.failed.size) @@ -351,8 +337,7 @@ class ShortcutsTest { assertNotNull(magic) val attrAssignment = - ((((magic.body as CompoundStatement).statements[0] as IfStatement).elseStatement - as CompoundStatement) + ((((magic.body as Block).statements[0] as IfStatement).elseStatement as Block) .statements[0] as AssignExpression) .lhs diff --git a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/WalkerTest.kt b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/WalkerTest.kt index 6fa8a8be57..e04a6d3e60 100644 --- a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/WalkerTest.kt +++ b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/WalkerTest.kt @@ -27,8 +27,8 @@ package de.fraunhofer.aisec.cpg.graph import de.fraunhofer.aisec.cpg.BaseTest import de.fraunhofer.aisec.cpg.graph.declarations.* -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement import de.fraunhofer.aisec.cpg.graph.statements.DeclarationStatement +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block import de.fraunhofer.aisec.cpg.graph.statements.expressions.Literal import de.fraunhofer.aisec.cpg.helpers.Benchmark import de.fraunhofer.aisec.cpg.helpers.SubgraphWalker @@ -54,7 +54,7 @@ class WalkerTest : BaseTest() { val method = MethodDeclaration() method.name = Name("method${j}", record.name) - val comp = CompoundStatement() + val comp = Block() // Each method has a body with contains a fair amount of variable declarations for (k in 0..10) { diff --git a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/TupleDeclarationTest.kt b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/TupleDeclarationTest.kt index db4d8e8d55..c452f6ee82 100644 --- a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/TupleDeclarationTest.kt +++ b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/TupleDeclarationTest.kt @@ -33,7 +33,7 @@ import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.builder.* import de.fraunhofer.aisec.cpg.graph.objectType import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import de.fraunhofer.aisec.cpg.graph.types.TupleType import kotlin.test.Test import kotlin.test.assertContains @@ -66,7 +66,7 @@ class TupleDeclarationTest { val tuple = newTupleDeclaration( listOf(newVariableDeclaration("a"), newVariableDeclaration("b")), - newCallExpression(newDeclaredReferenceExpression("func")) + newCallExpression(newReference("func")) ) scopeManager.addDeclaration(tuple) tuple.elements.forEach { scopeManager.addDeclaration(it) } @@ -102,7 +102,7 @@ class TupleDeclarationTest { assertNotNull(callPrint) assertIs(callPrint) - val arg = callPrint.arguments(0) + val arg = callPrint.arguments(0) assertNotNull(arg) assertRefersTo(arg, a) assertContains(arg.prevDFG, a) @@ -141,9 +141,7 @@ class TupleDeclarationTest { newVariableDeclaration("a"), newVariableDeclaration("b") ), - newCallExpression( - newDeclaredReferenceExpression("func") - ) + newCallExpression(newReference("func")) ) this.addToPropertyEdgeDeclaration(tuple) scopeManager.addDeclaration(tuple) @@ -182,7 +180,7 @@ class TupleDeclarationTest { assertNotNull(callPrint) assertIs(callPrint) - val arg = callPrint.arguments(0) + val arg = callPrint.arguments(0) assertNotNull(arg) assertRefersTo(arg, a) assertContains(arg.prevDFG, a) diff --git a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/AssignExpressionTest.kt b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/AssignExpressionTest.kt index a99c3f8647..7602cd87c0 100644 --- a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/AssignExpressionTest.kt +++ b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/AssignExpressionTest.kt @@ -30,7 +30,6 @@ import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.builder.function import de.fraunhofer.aisec.cpg.graph.builder.translationResult import de.fraunhofer.aisec.cpg.graph.builder.translationUnit -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement import de.fraunhofer.aisec.cpg.graph.types.TupleType import de.fraunhofer.aisec.cpg.passes.DFGPass import kotlin.test.* @@ -39,8 +38,8 @@ class AssignExpressionTest { @Test fun propagateSimple() { with(TestLanguageFrontend()) { - val refA = newDeclaredReferenceExpression("a") - val refB = newDeclaredReferenceExpression("b") + val refA = newReference("a") + val refB = newReference("b") // Simple assignment from "b" to "a". Both types are unknown at this point val stmt = newAssignExpression(lhs = listOf(refA), rhs = listOf(refB)) @@ -71,9 +70,9 @@ class AssignExpressionTest { ) function("main") { - val refA = newDeclaredReferenceExpression("a") - val refErr = newDeclaredReferenceExpression("err") - val refFunc = newDeclaredReferenceExpression("func") + val refA = newReference("a") + val refErr = newReference("err") + val refFunc = newReference("func") refFunc.refersTo = func val call = newCallExpression(refFunc) @@ -81,8 +80,8 @@ class AssignExpressionTest { val stmt = newAssignExpression(lhs = listOf(refA, refErr), rhs = listOf(call)) - body = newCompoundStatement() - body as CompoundStatement += stmt + body = newBlock() + body as Block += stmt } } } diff --git a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/types/TypePropagationTest.kt b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/types/TypePropagationTest.kt index 05f85022ef..45946b8b88 100644 --- a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/types/TypePropagationTest.kt +++ b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/types/TypePropagationTest.kt @@ -30,10 +30,10 @@ import de.fraunhofer.aisec.cpg.frontends.TestLanguageFrontend import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.builder.* import de.fraunhofer.aisec.cpg.graph.declarations.VariableDeclaration -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement import de.fraunhofer.aisec.cpg.graph.statements.ReturnStatement import de.fraunhofer.aisec.cpg.graph.statements.expressions.AssignExpression -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import de.fraunhofer.aisec.cpg.passes.ControlFlowSensitiveDFGPass import de.fraunhofer.aisec.cpg.passes.EvaluationOrderGraphPass import de.fraunhofer.aisec.cpg.passes.VariableUsageResolver @@ -127,7 +127,7 @@ class TypePropagationTest { val main = result.functions["main"] assertNotNull(main) - val assign = (main.body as? CompoundStatement)?.statements?.get(2) as? AssignExpression + val assign = (main.body as? Block)?.statements?.get(2) as? AssignExpression assertNotNull(assign) val shortVar = main.variables["shortVar"] @@ -136,13 +136,13 @@ class TypePropagationTest { assertEquals(primitiveType("short"), shortVar.type) assertEquals(setOf(primitiveType("short")), shortVar.assignedTypes) - val rhs = assign.rhs.firstOrNull() as? DeclaredReferenceExpression + val rhs = assign.rhs.firstOrNull() as? Reference assertNotNull(rhs) assertIs(rhs.type) assertLocalName("int", rhs.type) assertEquals(32, (rhs.type as IntegerType).bitWidth) - val shortVarRefLhs = assign.lhs.firstOrNull() as? DeclaredReferenceExpression + val shortVarRefLhs = assign.lhs.firstOrNull() as? Reference assertNotNull(shortVarRefLhs) // At this point, shortVar was target of an assignment of an int variable, however, the // int gets truncated into a short, so only short is part of the assigned types. @@ -380,7 +380,7 @@ class TypePropagationTest { .commonType ) - val assign = (body as CompoundStatement).statements(1) + val assign = (body as Block).statements(1) assertNotNull(assign) val bb = variables["bb"] @@ -397,7 +397,7 @@ class TypePropagationTest { bb.assignedTypes ) - val returnStatement = (body as CompoundStatement).statements(3) + val returnStatement = (body as Block).statements(3) assertNotNull(returnStatement) val returnValue = returnStatement.returnValue diff --git a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/ControlDependenceGraphPassTest.kt b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/ControlDependenceGraphPassTest.kt index f227e6a489..eac598e55b 100644 --- a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/ControlDependenceGraphPassTest.kt +++ b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/ControlDependenceGraphPassTest.kt @@ -33,7 +33,7 @@ import de.fraunhofer.aisec.cpg.frontends.TestLanguage import de.fraunhofer.aisec.cpg.frontends.TestLanguageFrontend import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.builder.* -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block import de.fraunhofer.aisec.cpg.graph.statements.expressions.Literal import kotlin.test.Test import kotlin.test.assertEquals @@ -48,7 +48,7 @@ class ControlDependenceGraphPassTest { assertNotNull(result) val main = result.functions["main"] assertNotNull(main) - val if0 = (main.body as CompoundStatement).statements[1] + val if0 = (main.body as Block).statements[1] assertNotNull(if0) assertEquals(1, if0.prevCDG.size) assertTrue(main in if0.prevCDG) @@ -90,7 +90,7 @@ class ControlDependenceGraphPassTest { assertNotNull(result) val main = result.functions["main"] assertNotNull(main) - val forEachStmt = (main.body as CompoundStatement).statements[1] + val forEachStmt = (main.body as Block).statements[1] assertNotNull(forEachStmt) assertEquals(1, forEachStmt.prevCDG.size) assertTrue(main in forEachStmt.prevCDG) diff --git a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/DFGTest.kt b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/DFGTest.kt index db88bc6721..5b3228ed42 100644 --- a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/DFGTest.kt +++ b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/DFGTest.kt @@ -138,8 +138,8 @@ class DFGTest { val varB = TestUtils.findByUniqueName(result.variables, "b") assertNotNull(varB) - val lhsA = binaryOperatorAssignment.lhs.first() as DeclaredReferenceExpression - val rhsA = binaryOperatorAddition.lhs as DeclaredReferenceExpression + val lhsA = binaryOperatorAssignment.lhs.first() as Reference + val rhsA = binaryOperatorAddition.lhs as Reference val b = TestUtils.findByUniqueName(result.refs, "b") assertNotNull(b) @@ -148,7 +148,7 @@ class DFGTest { val literal1 = result.literals[{ it.value == 1 }] assertNotNull(literal1) - // a and b flow to the DeclaredReferenceExpressions in (a+b) + // a and b flow to the References in (a+b) assertEquals(1, varA.nextDFG.size) assertEquals(1, varB.nextDFG.size) assertTrue(varA.nextDFG.contains(rhsA)) @@ -368,10 +368,10 @@ class DFGTest { val b = result.variables["b"] assertNotNull(b) - val ab = b.prevEOG[0] as DeclaredReferenceExpression + val ab = b.prevEOG[0] as Reference val literal4 = result.literals[{ it.value == 4 }] assertNotNull(literal4) - val a4 = ab.prevDFG.first { it is DeclaredReferenceExpression } + val a4 = ab.prevDFG.first { it is Reference } assertTrue(literal4.nextDFG.contains(a4)) assertEquals(1, ab.prevDFG.size) } @@ -394,7 +394,7 @@ class DFGTest { assertEquals( 1, a2.nextDFG.size - ) // Outgoing DFG Edges only to the DeclaredReferenceExpression in the assignment to b + ) // Outgoing DFG Edges only to the Reference in the assignment to b assertEquals( b.initializer!!, a2.nextDFG.first(), @@ -403,7 +403,7 @@ class DFGTest { val refersTo = a2.getRefersToAs(VariableDeclaration::class.java) assertNotNull(refersTo) assertEquals(2, refersTo.nextDFG.size) // The print and assignment to b - // Outgoing DFG Edge to the DeclaredReferenceExpression in the assignment of b + // Outgoing DFG Edge to the Reference in the assignment of b assertTrue(refersTo.nextDFG.contains(b.initializer!!)) // Test Else-Block with System.out.println() @@ -419,7 +419,7 @@ class DFGTest { assertEquals(1, aPrintln.nextEOG.size) assertEquals(println, aPrintln.nextEOG[0]) - val ab = b.prevEOG[0] as DeclaredReferenceExpression + val ab = b.prevEOG[0] as Reference assertTrue(refersTo.nextDFG.contains(ab)) assertTrue(a2.nextDFG.contains(ab)) } @@ -435,7 +435,7 @@ class DFGTest { val b = result.variables["b"] assertNotNull(b) - val ab = b.prevEOG[0] as DeclaredReferenceExpression + val ab = b.prevEOG[0] as Reference val a10 = result.refs[{ TestUtils.compareLineFromLocationIfExists(it, true, 8) }] val a11 = result.refs[{ TestUtils.compareLineFromLocationIfExists(it, true, 11) }] val a12 = result.refs[{ TestUtils.compareLineFromLocationIfExists(it, true, 14) }] diff --git a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/UnresolvedDFGPassTest.kt b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/UnresolvedDFGPassTest.kt index ec3d9d661c..b4984cd78e 100644 --- a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/UnresolvedDFGPassTest.kt +++ b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/UnresolvedDFGPassTest.kt @@ -33,8 +33,8 @@ 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.graph.declarations.MethodDeclaration -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.Literal +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue @@ -48,20 +48,14 @@ class UnresolvedDFGPassTest { val firstCall = result.calls { it.name.localName == "get" }[0] val osDecl = result.variables["os"] assertEquals(1, firstCall.prevDFG.size) - assertEquals( - osDecl, - (firstCall.prevDFG.firstOrNull() as? DeclaredReferenceExpression)?.refersTo - ) + assertEquals(osDecl, (firstCall.prevDFG.firstOrNull() as? Reference)?.refersTo) // Flow from base and argument to return value val callWithParam = result.calls { it.name.localName == "get" }[1] assertEquals(2, callWithParam.prevDFG.size) assertEquals( osDecl, - callWithParam.prevDFG - .filterIsInstance() - .firstOrNull() - ?.refersTo + callWithParam.prevDFG.filterIsInstance().firstOrNull()?.refersTo ) assertEquals(4, callWithParam.prevDFG.filterIsInstance>().firstOrNull()?.value) diff --git a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/VariableResolverTest.kt b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/VariableResolverTest.kt index 117b701d3b..01f1534076 100644 --- a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/VariableResolverTest.kt +++ b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/VariableResolverTest.kt @@ -32,8 +32,8 @@ import de.fraunhofer.aisec.cpg.graph.allChildren import de.fraunhofer.aisec.cpg.graph.fields import de.fraunhofer.aisec.cpg.graph.methods import de.fraunhofer.aisec.cpg.graph.statements.ReturnStatement -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.MemberExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import de.fraunhofer.aisec.cpg.graph.variables import kotlin.test.Test import kotlin.test.assertEquals @@ -74,7 +74,7 @@ internal class VariableResolverTest : BaseTest() { var local = getLocal.variables.firstOrNull { it.name.localName != "this" } - var returnValue = returnStatement.returnValue as DeclaredReferenceExpression + var returnValue = returnStatement.returnValue as Reference assertNotEquals(field, returnValue.refersTo) assertEquals(local, returnValue.refersTo) @@ -85,7 +85,7 @@ internal class VariableResolverTest : BaseTest() { local = getShadow.variables.firstOrNull { it.name.localName != "this" } - returnValue = returnStatement.returnValue as DeclaredReferenceExpression + returnValue = returnStatement.returnValue as Reference assertNotEquals(field, returnValue.refersTo) assertEquals(local, returnValue.refersTo) } diff --git a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/scopes/ScopeManagerTest.kt b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/scopes/ScopeManagerTest.kt index a3674d7583..9cbade8b65 100644 --- a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/scopes/ScopeManagerTest.kt +++ b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/scopes/ScopeManagerTest.kt @@ -97,12 +97,7 @@ internal class ScopeManagerTest : BaseTest() { // resolve symbol val call = - frontend.newCallExpression( - frontend.newDeclaredReferenceExpression("A::func1"), - "A::func1", - null, - false - ) + frontend.newCallExpression(frontend.newReference("A::func1"), "A::func1", null, false) val func = final.resolveFunction(call).firstOrNull() assertEquals(func1, func) diff --git a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/processing/VisitorTest.kt b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/processing/VisitorTest.kt index 3ea2a6942a..7141980bf6 100644 --- a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/processing/VisitorTest.kt +++ b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/processing/VisitorTest.kt @@ -30,7 +30,6 @@ import de.fraunhofer.aisec.cpg.GraphExamples import de.fraunhofer.aisec.cpg.frontends.TranslationException import de.fraunhofer.aisec.cpg.graph.Node import de.fraunhofer.aisec.cpg.graph.bodyOrNull -import de.fraunhofer.aisec.cpg.graph.builder.* import de.fraunhofer.aisec.cpg.graph.byNameOrNull import de.fraunhofer.aisec.cpg.graph.declarations.* import de.fraunhofer.aisec.cpg.graph.records @@ -74,9 +73,9 @@ class VisitorTest : BaseTest() { fun testAllEogNodeVisitor() { val nodeList: MutableList = ArrayList() // val recordDeclaration = namespace?.getDeclarationAs(0, RecordDeclaration::class.java) - assertNotNull(recordDecl) + assertNotNull(recordDeclaration) - val method = recordDecl!!.byNameOrNull("method") + val method = recordDeclaration!!.byNameOrNull("method") assertNotNull(method) val firstStmt = method.bodyOrNull() @@ -97,10 +96,10 @@ class VisitorTest : BaseTest() { /** Visits all nodes along AST. */ @Test fun testAllAstNodeVisitor() { - assertNotNull(recordDecl) + assertNotNull(recordDeclaration) val nodeList = mutableListOf() - recordDecl!!.accept( + recordDeclaration!!.accept( Strategy::AST_FORWARD, object : IVisitor() { override fun visit(n: Node) { @@ -118,22 +117,22 @@ class VisitorTest : BaseTest() { /** Visits only ReturnStatement nodes. */ @Test fun testReturnStmtVisitor() { - val returnStmts: MutableList = ArrayList() - assertNotNull(recordDecl) + val returnStatements: MutableList = ArrayList() + assertNotNull(recordDeclaration) - recordDecl!!.accept( + recordDeclaration!!.accept( Strategy::AST_FORWARD, object : IVisitor() { fun visit(r: ReturnStatement) { - returnStmts.add(r) + returnStatements.add(r) } } ) - assertEquals(2, returnStmts.size) + assertEquals(2, returnStatements.size) } companion object { - private var recordDecl: RecordDeclaration? = null + private var recordDeclaration: RecordDeclaration? = null @BeforeAll @JvmStatic @@ -145,7 +144,7 @@ class VisitorTest : BaseTest() { ) fun setup() { val cpg = GraphExamples.getVisitorTest() - recordDecl = cpg.records.firstOrNull() + recordDeclaration = cpg.records.firstOrNull() } } } 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 f7f12b5811..7f58e472e1 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 @@ -210,8 +210,8 @@ object TestUtils { * Asserts, that the expression given in [expression] refers to the expected declaration [b]. */ fun assertRefersTo(expression: Expression?, b: Declaration?) { - if (expression is DeclaredReferenceExpression) { - assertEquals(b, (expression as DeclaredReferenceExpression?)?.refersTo) + if (expression is Reference) { + assertEquals(b, (expression as Reference?)?.refersTo) } else { fail("not a reference") } @@ -228,9 +228,9 @@ object TestUtils { /** * Asserts equality or containing of the expected usedNode in the usingNode. If - * [ENFORCE_REFERENCES] is true, `usingNode` must be a [DeclaredReferenceExpression] where - * [DeclaredReferenceExpression.refersTo] is or contains `usedNode`. If this is not the case, - * usage can also be interpreted as equality of the two. + * [ENFORCE_REFERENCES] is true, `usingNode` must be a [Reference] where [Reference.refersTo] is + * or contains `usedNode`. If this is not the case, usage can also be interpreted as equality of + * the two. * * @param usingNode * - The node that shows usage of another node. @@ -240,11 +240,11 @@ object TestUtils { */ fun assertUsageOf(usingNode: Node?, usedNode: Node?) { assertNotNull(usingNode) - if (usingNode !is DeclaredReferenceExpression && !ENFORCE_REFERENCES) { + if (usingNode !is Reference && !ENFORCE_REFERENCES) { assertSame(usedNode, usingNode) } else { - assertTrue(usingNode is DeclaredReferenceExpression) - val reference = usingNode as? DeclaredReferenceExpression + assertTrue(usingNode is Reference) + val reference = usingNode as? Reference assertEquals(usedNode, reference?.refersTo) } } @@ -272,12 +272,12 @@ object TestUtils { assertUsageOf(usingNode, usedMember) } else { assertTrue(usingNode is MemberExpression) - val memberExpression = usingNode as MemberExpression? - assertNotNull(memberExpression) + val memberExpressionExpression = usingNode as MemberExpression? + assertNotNull(memberExpressionExpression) - val base = memberExpression.base + val base = memberExpressionExpression.base assertUsageOf(base, usedBase) - assertUsageOf(memberExpression.refersTo, usedMember) + assertUsageOf(memberExpressionExpression.refersTo, usedMember) } } } diff --git a/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXLanguageFrontend.kt b/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXLanguageFrontend.kt index 69276887ca..ab0713f3d3 100644 --- a/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXLanguageFrontend.kt +++ b/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXLanguageFrontend.kt @@ -386,7 +386,7 @@ class CXXLanguageFrontend(language: Language, ctx: Translat val expression: Expression = when (token.tokenType) { 1 -> // a variable - newDeclaredReferenceExpression(code, unknownType(), code) + newReference(code, unknownType(), code) 2 -> // an integer newLiteral(code.toInt(), primitiveType("int"), code) 130 -> // a string diff --git a/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/DeclarationHandler.kt b/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/DeclarationHandler.kt index 0c7dc12bdb..95d4a92b9f 100644 --- a/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/DeclarationHandler.kt +++ b/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/DeclarationHandler.kt @@ -29,10 +29,10 @@ import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.declarations.* import de.fraunhofer.aisec.cpg.graph.scopes.NameScope import de.fraunhofer.aisec.cpg.graph.scopes.TemplateScope -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement import de.fraunhofer.aisec.cpg.graph.statements.ReturnStatement import de.fraunhofer.aisec.cpg.graph.statements.Statement -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import de.fraunhofer.aisec.cpg.graph.statements.expressions.UnaryOperator import de.fraunhofer.aisec.cpg.graph.types.* import java.util.function.Supplier @@ -77,11 +77,11 @@ class DeclarationHandler(lang: CXXLanguageFrontend) : /** * Translates a C++ (using * directive)[https://en.cppreference.com/w/cpp/language/namespace#Using-directives] into a - * [UsingDirective]. However, currently, no actual adjustment of available names / scopes is + * [UsingDeclaration]. However, currently, no actual adjustment of available names / scopes is * done yet. */ private fun handleUsingDirective(using: CPPASTUsingDirective): Declaration { - return newUsingDirective(using.rawSignature, using.qualifiedName.toString()) + return newUsingDeclaration(using.rawSignature, using.qualifiedName.toString()) } /** @@ -195,7 +195,7 @@ class DeclarationHandler(lang: CXXLanguageFrontend) : // Let the statement handler take care of the function body. The outcome should (always) // be a compound statement, holding all other statements. val bodyStatement = frontend.statementHandler.handle(ctx.body) - if (bodyStatement is CompoundStatement) { + if (bodyStatement is Block) { val statements = bodyStatement.statementEdges // get the last statement @@ -273,7 +273,7 @@ class DeclarationHandler(lang: CXXLanguageFrontend) : if (ctx.declaration is CPPASTFunctionDefinition) { newFunctionTemplateDeclaration(name, frontend.codeOf(ctx)) } else { - newClassTemplateDeclaration(name, frontend.codeOf(ctx)) + newRecordTemplateDeclaration(name, frontend.codeOf(ctx)) } templateDeclaration.location = frontend.locationOf(ctx) @@ -310,27 +310,27 @@ class DeclarationHandler(lang: CXXLanguageFrontend) : for (templateParameter in ctx.templateParameters) { if (templateParameter is CPPASTSimpleTypeTemplateParameter) { // Handle Type Parameters - val typeParamDeclaration = - frontend.declaratorHandler.handle(templateParameter) as TypeParamDeclaration + val typeParamDecl = + frontend.declaratorHandler.handle(templateParameter) as TypeParameterDeclaration val parameterizedType = frontend.typeManager.createOrGetTypeParameter( templateDeclaration, templateParameter.name.toString(), language ) - typeParamDeclaration.type = parameterizedType + typeParamDecl.type = parameterizedType if (templateParameter.defaultType != null) { val defaultType = frontend.typeOf(templateParameter.defaultType) - typeParamDeclaration.default = defaultType + typeParamDecl.default = defaultType } - templateDeclaration.addParameter(typeParamDeclaration) + templateDeclaration.addParameter(typeParamDecl) } else if (templateParameter is CPPASTParameterDeclaration) { // Handle Value Parameters val nonTypeTemplateParamDeclaration = frontend.parameterDeclarationHandler.handle( templateParameter as IASTParameterDeclaration ) - if (nonTypeTemplateParamDeclaration is ParamVariableDeclaration) { + if (nonTypeTemplateParamDeclaration is ParameterDeclaration) { if (templateParameter.declarator.initializer != null) { val defaultExpression = frontend.initializerHandler.handle( @@ -502,7 +502,7 @@ class DeclarationHandler(lang: CXXLanguageFrontend) : // the type of this declaration). The typical (and only) scenario we // support here is the assignment of a `&ref` as initializer. initializer is UnaryOperator && type is FunctionPointerType -> { - val ref = initializer.input as? DeclaredReferenceExpression + val ref = initializer.input as? Reference ref?.resolutionHelper = declaration } } diff --git a/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/DeclaratorHandler.kt b/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/DeclaratorHandler.kt index af98a6d8eb..e66c277079 100644 --- a/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/DeclaratorHandler.kt +++ b/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/DeclaratorHandler.kt @@ -295,7 +295,7 @@ class DeclaratorHandler(lang: CXXLanguageFrontend) : for (param in ctx.parameters) { val arg = frontend.parameterDeclarationHandler.handle(param) - if (arg is ParamVariableDeclaration) { + if (arg is ParameterDeclaration) { // check for void type parameters if (arg.type is IncompleteType) { if (arg.name.isNotEmpty()) { @@ -334,7 +334,7 @@ class DeclaratorHandler(lang: CXXLanguageFrontend) : // is appended to the original ones. For coherent graph behaviour, we introduce an implicit // declaration that wraps this list if (ctx.takesVarArgs()) { - val varargs = newParamVariableDeclaration("va_args", unknownType(), true, "") + val varargs = newParameterDeclaration("va_args", unknownType(), true, "") varargs.isImplicit = true varargs.argumentIndex = i frontend.scopeManager.addDeclaration(varargs) @@ -478,12 +478,12 @@ class DeclaratorHandler(lang: CXXLanguageFrontend) : * Handles template parameters that are types * * @param ctx - * @return TypeParamDeclaration with its name + * @return TypeParameterDeclaration with its name */ private fun handleTemplateTypeParameter( ctx: CPPASTSimpleTypeTemplateParameter - ): TypeParamDeclaration { - return newTypeParamDeclaration(ctx.rawSignature, ctx.rawSignature, ctx) + ): TypeParameterDeclaration { + return newTypeParameterDeclaration(ctx.rawSignature, ctx.rawSignature, ctx) } private fun processMembers(ctx: IASTCompositeTypeSpecifier) { diff --git a/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/ExpressionHandler.kt b/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/ExpressionHandler.kt index 9e4e4e7bc4..babe8116ab 100644 --- a/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/ExpressionHandler.kt +++ b/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/ExpressionHandler.kt @@ -96,7 +96,7 @@ class ExpressionHandler(lang: CXXLanguageFrontend) : if (capture.isByReference) { val valueDeclaration = frontend.scopeManager.resolveReference( - newDeclaredReferenceExpression(capture?.identifier?.toString()) + newReference(capture?.identifier?.toString()) ) valueDeclaration?.let { lambda.mutableVariables.add(it) } } @@ -126,9 +126,7 @@ class ExpressionHandler(lang: CXXLanguageFrontend) : private fun handleCompoundStatementExpression( ctx: CPPASTCompoundStatementExpression ): Expression { - val cse = newCompoundStatementExpression(ctx.rawSignature) - cse.statement = frontend.statementHandler.handle(ctx.compoundStatement) - return cse + return frontend.statementHandler.handle(ctx.compoundStatement) as Expression } private fun handleTypeIdExpression(ctx: IASTTypeIdExpression): TypeIdExpression { @@ -167,7 +165,7 @@ class ExpressionHandler(lang: CXXLanguageFrontend) : } private fun handleArraySubscriptExpression(ctx: IASTArraySubscriptExpression): Expression { - val arraySubsExpression = newArraySubscriptionExpression(ctx.rawSignature) + val arraySubsExpression = newSubscriptExpression(ctx.rawSignature) handle(ctx.arrayExpression)?.let { arraySubsExpression.arrayExpression = it } handle(ctx.argument)?.let { arraySubsExpression.subscriptExpression = it } return arraySubsExpression @@ -182,7 +180,7 @@ class ExpressionHandler(lang: CXXLanguageFrontend) : return if (ctx.isArrayAllocation) { t.array() val arrayMods = (ctx.typeId.abstractDeclarator as IASTArrayDeclarator).arrayModifiers - val arrayCreate = newArrayCreationExpression(code) + val arrayCreate = newNewArrayExpression(code) arrayCreate.type = t for (arrayMod in arrayMods) { val constant = handle(arrayMod.constantExpression) @@ -427,7 +425,7 @@ class ExpressionHandler(lang: CXXLanguageFrontend) : ((ctx.functionNameExpression as IASTIdExpression).name as CPPASTTemplateId) .templateName .toString() - val ref = newDeclaredReferenceExpression(name) + val ref = newReference(name) callExpression = newCallExpression(ref, name, ctx.rawSignature, true) getTemplateArguments( (ctx.functionNameExpression as IASTIdExpression).name as CPPASTTemplateId @@ -461,11 +459,11 @@ class ExpressionHandler(lang: CXXLanguageFrontend) : return callExpression } - private fun handleIdExpression(ctx: IASTIdExpression): DeclaredReferenceExpression { + private fun handleIdExpression(ctx: IASTIdExpression): Reference { // this expression could actually be a field / member expression, but somehow CDT only // recognizes them as a member expression if it has an explicit 'this' // TODO: handle this? convert the declared reference expression into a member expression? - return newDeclaredReferenceExpression(ctx.name.toString(), unknownType(), ctx.rawSignature) + return newReference(ctx.name.toString(), unknownType(), ctx.rawSignature) } private fun handleExpressionList(exprList: IASTExpressionList): ExpressionList { @@ -524,8 +522,8 @@ class ExpressionHandler(lang: CXXLanguageFrontend) : val operatorCode = String(ASTStringUtil.getBinaryOperatorString(ctx)) val assign = newAssignExpression(operatorCode, listOf(lhs), listOf(rhs), rawNode = ctx) - if (rhs is UnaryOperator && rhs.input is DeclaredReferenceExpression) { - (rhs.input as DeclaredReferenceExpression).resolutionHelper = lhs + if (rhs is UnaryOperator && rhs.input is Reference) { + (rhs.input as Reference).resolutionHelper = lhs } return assign @@ -566,11 +564,7 @@ class ExpressionHandler(lang: CXXLanguageFrontend) : } is CPPASTFieldDesignator -> { oneLhs = - newDeclaredReferenceExpression( - des.name.toString(), - unknownType(), - des.getRawSignature() - ) + newReference(des.name.toString(), unknownType(), des.getRawSignature()) } is CPPASTArrayRangeDesignator -> { oneLhs = @@ -620,11 +614,7 @@ class ExpressionHandler(lang: CXXLanguageFrontend) : } is CPPASTFieldDesignator -> { oneLhs = - newDeclaredReferenceExpression( - des.name.toString(), - unknownType(), - des.getRawSignature() - ) + newReference(des.name.toString(), unknownType(), des.getRawSignature()) } is CPPASTArrayRangeDesignator -> { oneLhs = @@ -779,17 +769,17 @@ class ExpressionHandler(lang: CXXLanguageFrontend) : /** * In C++, the "this" expression is also modelled as a literal. In our case however, we want to - * return a [DeclaredReferenceExpression], which is then later connected to the current method's + * return a [Reference], which is then later connected to the current method's * [MethodDeclaration.receiver]. */ - private fun handleThisLiteral(ctx: IASTLiteralExpression): DeclaredReferenceExpression { + private fun handleThisLiteral(ctx: IASTLiteralExpression): Reference { // We should be in a record here. However since we are a fuzzy parser, maybe things went // wrong, so we might have an unknown type. val recordType = frontend.scopeManager.currentRecord?.toType() ?: unknownType() // We do want to make sure that the type of the expression is at least a pointer. val pointerType = recordType.pointer() - return newDeclaredReferenceExpression("this", pointerType, ctx.rawSignature, ctx) + return newReference("this", pointerType, ctx.rawSignature, ctx) } private val IASTLiteralExpression.valueWithSuffix: Pair diff --git a/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/ParameterDeclarationHandler.kt b/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/ParameterDeclarationHandler.kt index 94b990e2a8..79e0c240f2 100644 --- a/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/ParameterDeclarationHandler.kt +++ b/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/ParameterDeclarationHandler.kt @@ -26,9 +26,9 @@ package de.fraunhofer.aisec.cpg.frontends.cxx import de.fraunhofer.aisec.cpg.graph.declarations.Declaration -import de.fraunhofer.aisec.cpg.graph.declarations.ParamVariableDeclaration +import de.fraunhofer.aisec.cpg.graph.declarations.ParameterDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.ProblemDeclaration -import de.fraunhofer.aisec.cpg.graph.newParamVariableDeclaration +import de.fraunhofer.aisec.cpg.graph.newParameterDeclaration import java.util.function.Supplier import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration import org.eclipse.cdt.internal.core.dom.parser.c.CASTParameterDeclaration @@ -47,19 +47,12 @@ class ParameterDeclarationHandler(lang: CXXLanguageFrontend) : } } - private fun handleParameterDeclaration( - ctx: IASTParameterDeclaration - ): ParamVariableDeclaration { + private fun handleParameterDeclaration(ctx: IASTParameterDeclaration): ParameterDeclaration { // Parse the type val type = frontend.typeOf(ctx.declarator, ctx.declSpecifier) val paramVariableDeclaration = - newParamVariableDeclaration( - ctx.declarator.name.toString(), - type, - false, - ctx.rawSignature - ) + newParameterDeclaration(ctx.declarator.name.toString(), type, false, ctx.rawSignature) // Add default values if (ctx.declarator.initializer != null) { diff --git a/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/StatementHandler.kt b/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/StatementHandler.kt index 87d5ce18e9..dc759a1f01 100644 --- a/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/StatementHandler.kt +++ b/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/StatementHandler.kt @@ -30,6 +30,7 @@ import de.fraunhofer.aisec.cpg.graph.declarations.Declaration import de.fraunhofer.aisec.cpg.graph.declarations.DeclarationSequence import de.fraunhofer.aisec.cpg.graph.declarations.VariableDeclaration import de.fraunhofer.aisec.cpg.graph.statements.* +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression import de.fraunhofer.aisec.cpg.graph.statements.expressions.Literal import de.fraunhofer.aisec.cpg.graph.statements.expressions.ProblemExpression @@ -73,24 +74,29 @@ class StatementHandler(lang: CXXLanguageFrontend) : } } - private fun handleProblemStatement(problemStmt: IASTProblemStatement): ProblemExpression { - Util.errorWithFileLocation(frontend, problemStmt, log, problemStmt.problem.message) + private fun handleProblemStatement(problemStatement: IASTProblemStatement): ProblemExpression { + Util.errorWithFileLocation( + frontend, + problemStatement, + log, + problemStatement.problem.message + ) return newProblemExpression( - problemStmt.problem.message, + problemStatement.problem.message, ) } - private fun handleEmptyStatement(emptyStmt: IASTNullStatement): EmptyStatement { - return newEmptyStatement(emptyStmt.rawSignature) + private fun handleEmptyStatement(nullStatement: IASTNullStatement): EmptyStatement { + return newEmptyStatement(nullStatement.rawSignature) } - private fun handleTryBlockStatement(tryStmt: CPPASTTryBlockStatement): TryStatement { - val tryStatement = newTryStatement(tryStmt.toString()) + private fun handleTryBlockStatement(tryBlockStatement: CPPASTTryBlockStatement): TryStatement { + val tryStatement = newTryStatement(tryBlockStatement.toString()) frontend.scopeManager.enterScope(tryStatement) - val statement = handle(tryStmt.tryBody) as CompoundStatement? + val statement = handle(tryBlockStatement.tryBody) as Block? val catchClauses = - Arrays.stream(tryStmt.catchHandlers) + Arrays.stream(tryBlockStatement.catchHandlers) .map { handleCatchHandler(it) } .collect(Collectors.toList()) tryStatement.tryBlock = statement @@ -111,7 +117,7 @@ class StatementHandler(lang: CXXLanguageFrontend) : decl = frontend.declarationHandler.handle(catchHandler.declaration) } - catchClause.body = body as? CompoundStatement + catchClause.body = body as? Block if (decl != null) { catchClause.parameter = decl as? VariableDeclaration @@ -310,21 +316,21 @@ class StatementHandler(lang: CXXLanguageFrontend) : return returnStatement } - private fun handleCompoundStatement(ctx: IASTCompoundStatement): CompoundStatement { - val compoundStatement = newCompoundStatement(ctx.rawSignature) + private fun handleCompoundStatement(ctx: IASTCompoundStatement): Block { + val block = newBlock(ctx.rawSignature) - frontend.scopeManager.enterScope(compoundStatement) + frontend.scopeManager.enterScope(block) for (statement in ctx.statements) { val handled = handle(statement) if (handled != null) { - compoundStatement.addStatement(handled) + block.addStatement(handled) } } - frontend.scopeManager.leaveScope(compoundStatement) + frontend.scopeManager.leaveScope(block) - return compoundStatement + return block } private fun handleSwitchStatement(ctx: IASTSwitchStatement): SwitchStatement { 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 db2020ec57..faf20fe1ec 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 @@ -936,15 +936,12 @@ internal class EOGTest : BaseTest() { assertTrue(printFunctionCall in lambda.prevEOG) // The "inner" EOG is assembled correctly. - val body = (lambda.function?.body as? CompoundStatement) + val body = (lambda.function?.body as? Block) assertNotNull(body) assertEquals(1, lambda.function?.nextEOG?.size) - assertEquals( - "std::cout", - (lambda.function?.nextEOG?.get(0) as? DeclaredReferenceExpression)?.name.toString() - ) + assertEquals("std::cout", (lambda.function?.nextEOG?.get(0) as? Reference)?.name.toString()) - val cout = lambda.function?.nextEOG?.get(0) as? DeclaredReferenceExpression + val cout = lambda.function?.nextEOG?.get(0) as? Reference assertNotNull(cout) assertEquals(1, cout.nextEOG.size) assertEquals("Hello ", (cout.nextEOG[0] as? Literal<*>)?.value.toString()) @@ -957,12 +954,9 @@ internal class EOGTest : BaseTest() { val binOpLeft = hello.nextEOG[0] as? BinaryOperator assertNotNull(binOpLeft) assertEquals(1, binOpLeft.nextEOG.size) - assertEquals( - "number", - (binOpLeft.nextEOG[0] as? DeclaredReferenceExpression)?.name.toString() - ) + assertEquals("number", (binOpLeft.nextEOG[0] as? Reference)?.name.toString()) - val number = binOpLeft.nextEOG[0] as? DeclaredReferenceExpression + val number = binOpLeft.nextEOG[0] as? Reference assertNotNull(number) assertEquals(1, number.nextEOG.size) assertEquals("<<", (number.nextEOG[0] as? BinaryOperator)?.operatorCode) @@ -970,12 +964,9 @@ internal class EOGTest : BaseTest() { val binOpCenter = (number.nextEOG[0] as? BinaryOperator) assertNotNull(binOpCenter) assertEquals(1, binOpCenter.nextEOG.size) - assertEquals( - "std::endl", - (binOpCenter.nextEOG[0] as? DeclaredReferenceExpression)?.name.toString() - ) + assertEquals("std::endl", (binOpCenter.nextEOG[0] as? Reference)?.name.toString()) - val endl = (binOpCenter.nextEOG[0] as? DeclaredReferenceExpression) + val endl = (binOpCenter.nextEOG[0] as? Reference) assertNotNull(endl) assertEquals(1, endl.nextEOG.size) assertEquals("<<", (endl.nextEOG[0] as? BinaryOperator)?.operatorCode) @@ -983,9 +974,9 @@ internal class EOGTest : BaseTest() { val binOpRight = (endl.nextEOG[0] as? BinaryOperator) assertNotNull(binOpRight) assertEquals(1, binOpRight.nextEOG.size) - assertTrue(binOpRight.nextEOG.firstOrNull() is CompoundStatement) + assertTrue(binOpRight.nextEOG.firstOrNull() is Block) - assertEquals(0, (binOpRight.nextEOG.firstOrNull() as? CompoundStatement)?.nextEOG?.size) + assertEquals(0, (binOpRight.nextEOG.firstOrNull() as? Block)?.nextEOG?.size) } @Test 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 20c00f0f24..a2a2d791c6 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 @@ -46,14 +46,14 @@ internal class ClassTemplateTest : BaseTest() { private val topLevel = Path.of("src", "test", "resources", "templates", "classtemplates") private fun testTemplateStructure( - template: ClassTemplateDeclaration, + template: RecordTemplateDeclaration, pair: RecordDeclaration?, - type1: TypeParamDeclaration?, - type2: TypeParamDeclaration? + type1: TypeParameterDeclaration?, + type2: TypeParameterDeclaration? ) { assertEquals(2, template.parameters.size) - assertEquals(type1, template.parameters[0] as TypeParamDeclaration?) - assertEquals(type2, template.parameters[1] as TypeParamDeclaration?) + assertEquals(type1, template.parameters[0] as TypeParameterDeclaration?) + assertEquals(type2, template.parameters[1] as TypeParameterDeclaration?) assertEquals(1, template.realizations.size) assertNotNull(pair) assertEquals(pair, template.realizations[0]) @@ -71,8 +71,8 @@ internal class ClassTemplateTest : BaseTest() { private fun testClassTemplatesTypes( pair: RecordDeclaration?, receiver: VariableDeclaration, - type1: TypeParamDeclaration, - type2: TypeParamDeclaration + type1: TypeParameterDeclaration, + type2: TypeParameterDeclaration ): ObjectType { assertLocalName("Pair*", receiver.type) assertTrue(receiver.type is PointerType) @@ -107,7 +107,7 @@ internal class ClassTemplateTest : BaseTest() { constructExpression: ConstructExpression, pair: RecordDeclaration?, pairType: ObjectType, - template: ClassTemplateDeclaration?, + template: RecordTemplateDeclaration?, point1: VariableDeclaration ) { assertEquals(pairConstructorDeclaration, constructExpression.constructor) @@ -144,15 +144,15 @@ internal class ClassTemplateTest : BaseTest() { fun testClassTemplateStructure() { val result = analyze(listOf(Path.of(topLevel.toString(), "pair.cpp").toFile()), topLevel, true) - val classTemplateDeclarations = result.allChildren() + val recordTemplateDeclarations = result.allChildren() val template = findByUniqueName( - classTemplateDeclarations, + recordTemplateDeclarations, "template class Pair" ) val pair = findByUniqueName(result.records, "Pair") - val type1 = findByUniqueName(result.allChildren(), "class Type1") - val type2 = findByUniqueName(result.allChildren(), "class Type2") + val type1 = findByUniqueName(result.allChildren(), "class Type1") + val type2 = findByUniqueName(result.allChildren(), "class Type2") val first = findByUniqueName(result.fields, "first") val second = findByUniqueName(result.fields, "second") val constructor = pair.constructors["Pair"] @@ -161,7 +161,7 @@ internal class ClassTemplateTest : BaseTest() { val receiver = constructor.receiver assertNotNull(receiver) - val pairConstructorDeclaration = + val pairConstructorDecl = findByUniqueName(result.allChildren(), "Pair") val constructExpression = findByUniquePredicate(result.allChildren()) { c: ConstructExpression -> @@ -179,11 +179,11 @@ internal class ClassTemplateTest : BaseTest() { val pairType = testClassTemplatesTypes(pair, receiver, type1, type2) // Test Constructor - testClassTemplateConstructor(pair, pairType, pairConstructorDeclaration) + testClassTemplateConstructor(pair, pairType, pairConstructorDecl) // Test Invocation testClassTemplateInvocation( - pairConstructorDeclaration, + pairConstructorDecl, constructExpression, pair, pairType, @@ -198,10 +198,10 @@ internal class ClassTemplateTest : BaseTest() { // Test pair2.cpp: Add Value Parameter to Template Instantiation val result = analyze(listOf(Path.of(topLevel.toString(), "pair2.cpp").toFile()), topLevel, true) - val classTemplateDeclarations = result.allChildren() + val recordTemplateDeclarations = result.allChildren() val template = findByUniqueName( - classTemplateDeclarations, + recordTemplateDeclarations, "template class Pair" ) val pair = findByUniqueName(result.records, "Pair") @@ -210,9 +210,9 @@ internal class ClassTemplateTest : BaseTest() { val receiver = pair.byNameOrNull("Pair")?.receiver assertNotNull(receiver) - val pairConstructorDeclaration = + val pairConstructorDecl = findByUniqueName(result.allChildren(), "Pair") - val constructExpression = + val constructExpr = findByUniquePredicate(result.allChildren()) { it.code == "Pair()" } val literal3 = findByUniquePredicate(result.literals) { it.value == 3 && !it.isImplicit } val literal3Implicit = @@ -221,20 +221,17 @@ internal class ClassTemplateTest : BaseTest() { assertEquals(3, template.parameters.size) assertEquals(paramN, template.parameters[2]) assertTrue(pair.fields.contains(n)) - assertEquals(paramN, (n.initializer as? DeclaredReferenceExpression)?.refersTo) + assertEquals(paramN, (n.initializer as? Reference)?.refersTo) // Test Type val type = ((receiver.type as? PointerType)?.elementType as? ObjectType) assertNotNull(type) - assertEquals( - (pairConstructorDeclaration.type as? FunctionType)?.returnTypes?.firstOrNull(), - type - ) + assertEquals((pairConstructorDecl.type as? FunctionType)?.returnTypes?.firstOrNull(), type) assertEquals(pair, type.recordDeclaration) assertEquals(2, type.generics.size) assertLocalName("Type1", type.generics[0]) assertLocalName("Type2", type.generics[1]) - val instantiatedType = constructExpression.type as ObjectType + val instantiatedType = constructExpr.type as ObjectType assertEquals(instantiatedType, point1.type) assertEquals(2, instantiatedType.generics.size) assertLocalName("int", instantiatedType.generics[0]) @@ -245,22 +242,20 @@ internal class ClassTemplateTest : BaseTest() { assertEquals(literal3, point1.templateParameters?.get(2)) // Test Invocation - val templateParameters = constructExpression.templateParameters + val templateParameters = constructExpr.templateParameters assertNotNull(templateParameters) assertEquals(3, templateParameters.size) assertEquals(literal3Implicit, templateParameters[2]) assertEquals( TemplateDeclaration.TemplateInitialization.EXPLICIT, - constructExpression.templateParameterEdges - ?.get(2) - ?.getProperty(Properties.INSTANTIATION) + constructExpr.templateParameterEdges?.get(2)?.getProperty(Properties.INSTANTIATION) ) - assertEquals(pair, constructExpression.instantiates) - assertEquals(template, constructExpression.templateInstantiation) + assertEquals(pair, constructExpr.instantiates) + assertEquals(template, constructExpr.templateInstantiation) } private fun testStructTemplateWithSameDefaultTypeInvocation( - template: ClassTemplateDeclaration?, + template: RecordTemplateDeclaration?, pair: RecordDeclaration?, pairConstructorDeclaration: ConstructorDeclaration?, constructExpression: ConstructExpression, @@ -301,19 +296,19 @@ internal class ClassTemplateTest : BaseTest() { analyze(listOf(Path.of(topLevel.toString(), "pair3.cpp").toFile()), topLevel, true) val template = findByUniqueName( - result.allChildren(), + result.allChildren(), "template struct Pair" ) val pair = findByUniqueName(result.records, "Pair") - val pairConstructorDeclaration = + val pairConstructorDecl = findByUniqueName(result.allChildren(), "Pair") - val type1 = findByUniqueName(result.allChildren(), "class Type1") + val type1 = findByUniqueName(result.allChildren(), "class Type1") val type2 = - findByUniqueName(result.allChildren(), "class Type2 = Type1") + findByUniqueName(result.allChildren(), "class Type2 = Type1") val first = findByUniqueName(result.fields, "first") val second = findByUniqueName(result.fields, "second") val point1 = findByUniqueName(result.variables, "point1") - val constructExpression = + val constructExpr = findByUniquePredicate(result.allChildren()) { it.code == "Pair()" } assertEquals(1, template.realizations.size) assertEquals(pair, template.realizations[0]) @@ -331,8 +326,7 @@ internal class ClassTemplateTest : BaseTest() { assertEquals(type1ParameterizedType, type2.default) val pairType = - (pairConstructorDeclaration.type as FunctionType).returnTypes.firstOrNull() - as? ObjectType + (pairConstructorDecl.type as FunctionType).returnTypes.firstOrNull() as? ObjectType assertNotNull(pairType) assertEquals(2, pairType.generics.size) assertEquals(type1ParameterizedType, pairType.generics[0]) @@ -345,8 +339,8 @@ internal class ClassTemplateTest : BaseTest() { testStructTemplateWithSameDefaultTypeInvocation( template, pair, - pairConstructorDeclaration, - constructExpression, + pairConstructorDecl, + constructExpr, point1 ) } @@ -359,49 +353,41 @@ internal class ClassTemplateTest : BaseTest() { analyze(listOf(Path.of(topLevel.toString(), "pair3-1.cpp").toFile()), topLevel, true) val template = findByUniqueName( - result.allChildren(), + result.allChildren(), "template struct Pair" ) val pair = findByUniqueName(result.records, "Pair") - val constructExpression = + val constructExpr = findByUniquePredicate(result.allChildren()) { it.code == "Pair()" } val literal2 = findByUniquePredicate(result.literals) { it.value == 2 && !it.isImplicit } assertNotNull(literal2) val literal2Implicit = findByUniquePredicate(result.literals) { it.value == 2 && it.isImplicit } - assertEquals(pair, constructExpression.instantiates) - assertEquals(template, constructExpression.templateInstantiation) - assertEquals(4, constructExpression.templateParameters.size) - assertLocalName("int", constructExpression.templateParameters[0]) + assertEquals(pair, constructExpr.instantiates) + assertEquals(template, constructExpr.templateInstantiation) + assertEquals(4, constructExpr.templateParameters.size) + assertLocalName("int", constructExpr.templateParameters[0]) assertEquals( TemplateDeclaration.TemplateInitialization.EXPLICIT, - constructExpression.templateParameterEdges - ?.get(0) - ?.getProperty(Properties.INSTANTIATION) + constructExpr.templateParameterEdges?.get(0)?.getProperty(Properties.INSTANTIATION) ) - assertLocalName("int", constructExpression.templateParameters[1]) + assertLocalName("int", constructExpr.templateParameters[1]) assertEquals( TemplateDeclaration.TemplateInitialization.EXPLICIT, - constructExpression.templateParameterEdges - ?.get(1) - ?.getProperty(Properties.INSTANTIATION) + constructExpr.templateParameterEdges?.get(1)?.getProperty(Properties.INSTANTIATION) ) - assertEquals(literal2Implicit, constructExpression.templateParameters[2]) + assertEquals(literal2Implicit, constructExpr.templateParameters[2]) assertEquals( TemplateDeclaration.TemplateInitialization.EXPLICIT, - constructExpression.templateParameterEdges - ?.get(2) - ?.getProperty(Properties.INSTANTIATION) + constructExpr.templateParameterEdges?.get(2)?.getProperty(Properties.INSTANTIATION) ) - assertEquals(literal2Implicit, constructExpression.templateParameters[3]) + assertEquals(literal2Implicit, constructExpr.templateParameters[3]) assertEquals( TemplateDeclaration.TemplateInitialization.DEFAULT, - constructExpression.templateParameterEdges - ?.get(3) - ?.getProperty(Properties.INSTANTIATION) + constructExpr.templateParameterEdges?.get(3)?.getProperty(Properties.INSTANTIATION) ) - val type = constructExpression.type as ObjectType + val type = constructExpr.type as ObjectType assertEquals(pair, type.recordDeclaration) assertEquals(2, type.generics.size) assertLocalName("int", type.generics[0]) @@ -416,7 +402,7 @@ internal class ClassTemplateTest : BaseTest() { analyze(listOf(Path.of(topLevel.toString(), "pair3-2.cpp").toFile()), topLevel, true) val template = findByUniqueName( - result.allChildren(), + result.allChildren(), "template struct Pair" ) val pair = findByUniqueName(result.records, "Pair") @@ -431,7 +417,7 @@ internal class ClassTemplateTest : BaseTest() { assertEquals(paramA, template.parameters[2]) assertEquals(literal1, paramA.default) assertEquals(paramB, template.parameters[3]) - assertEquals(paramA, (paramB.default as DeclaredReferenceExpression).refersTo) + assertEquals(paramA, (paramB.default as Reference).refersTo) assertEquals(pair, constructExpression.instantiates) assertEquals(template, constructExpression.templateInstantiation) assertEquals(4, constructExpression.templateParameters.size) @@ -495,12 +481,12 @@ internal class ClassTemplateTest : BaseTest() { analyze(listOf(Path.of(topLevel.toString(), "array.cpp").toFile()), topLevel, true) val template = findByUniqueName( - result.allChildren(), + result.allChildren(), "template class Array" ) val array = findByUniqueName(result.records, "Array") val paramN = findByUniqueName(result.parameters, "N") - val paramT = findByUniqueName(result.allChildren(), "typename T") + val paramT = findByUniqueName(result.allChildren(), "typename T") val literal10 = findByUniquePredicate(result.literals) { it.value == 10 } val mArray = findByUniqueName(result.fields, "m_Array") assertEquals(2, template.parameters.size) @@ -525,17 +511,17 @@ internal class ClassTemplateTest : BaseTest() { val tArray = mArray.type as PointerType assertEquals(typeT, tArray.elementType) - val constructExpression = + val constructExpr = findByUniquePredicate(result.allChildren()) { it.code == "Array()" } - assertEquals(template, constructExpression.templateInstantiation) - assertEquals(array, constructExpression.instantiates) - assertLocalName("int", constructExpression.templateParameters[0]) - assertEquals(literal10, constructExpression.templateParameters[1]) - assertLocalName("Array", constructExpression.type) + assertEquals(template, constructExpr.templateInstantiation) + assertEquals(array, constructExpr.instantiates) + assertLocalName("int", constructExpr.templateParameters[0]) + assertEquals(literal10, constructExpr.templateParameters[1]) + assertLocalName("Array", constructExpr.type) - val instantiatedType = constructExpression.type as ObjectType + val instantiatedType = constructExpr.type as ObjectType assertEquals(1, instantiatedType.generics.size) assertLocalName("int", instantiatedType.generics[0]) } @@ -548,7 +534,7 @@ internal class ClassTemplateTest : BaseTest() { analyze(listOf(Path.of(topLevel.toString(), "array2.cpp").toFile()), topLevel, true) val template = findByUniqueName( - result.allChildren(), + result.allChildren(), "template class Array" ) val array = findByUniqueName(result.records, "Array") 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 a9dfa42cd6..62b9ce738c 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 @@ -95,14 +95,14 @@ internal class FunctionTemplateTest : BaseTest() { true ) // This test checks the structure of FunctionTemplates without the TemplateExpansionPass - val functionTemplateDeclaration = result.allChildren()[0] + val functionTemplateDecl = result.allChildren()[0] // Check FunctionTemplate Parameters - val typeParamDeclarations = result.allChildren() - assertEquals(1, typeParamDeclarations.size) + val typeParamDecls = result.allChildren() + assertEquals(1, typeParamDecls.size) - val typeParamDeclaration = typeParamDeclarations[0] - assertEquals(typeParamDeclaration, functionTemplateDeclaration.parameters[0]) + val typeParamDeclaration = typeParamDecls[0] + assertEquals(typeParamDeclaration, functionTemplateDecl.parameters[0]) val typeT = ParameterizedType("T", CPPLanguage()) val intType = IntegerType("int", 32, CPPLanguage(), NumericType.Modifier.SIGNED) @@ -114,7 +114,7 @@ internal class FunctionTemplateTest : BaseTest() { val int2 = findByUniquePredicate(result.literals { it.value == 2 }) { it.value == 2 } val int3 = findByUniquePredicate(result.literals) { it.value == 3 } val int5 = findByUniquePredicate(result.literals) { it.value == 5 } - assertEquals(N, functionTemplateDeclaration.parameters[1]) + assertEquals(N, functionTemplateDecl.parameters[1]) assertEquals(intType, N.type) assertEquals(5, (N.default as Literal<*>).value) assertTrue(N.prevDFG.contains(int5)) @@ -122,9 +122,9 @@ internal class FunctionTemplateTest : BaseTest() { assertTrue(N.prevDFG.contains(int2)) // Check the realization - assertEquals(1, functionTemplateDeclaration.realization.size) + assertEquals(1, functionTemplateDecl.realization.size) - val fixedMultiply = functionTemplateDeclaration.realization[0] + val fixedMultiply = functionTemplateDecl.realization[0] val funcType = fixedMultiply.type as? FunctionType assertNotNull(funcType) assertEquals(typeT, funcType.returnTypes.firstOrNull()) @@ -539,8 +539,8 @@ internal class FunctionTemplateTest : BaseTest() { assertEquals(1, templateDeclaration.realization.size) assertEquals(fixedDivision, templateDeclaration.realization[0]) assertEquals(2, templateDeclaration.parameters.size) - assertTrue(templateDeclaration.parameters[0] is TypeParamDeclaration) - assertTrue(templateDeclaration.parameters[1] is ParamVariableDeclaration) + assertTrue(templateDeclaration.parameters[0] is TypeParameterDeclaration) + assertTrue(templateDeclaration.parameters[1] is ParameterDeclaration) assertEquals(1, fixedDivision.parameters.size) val callInt2 = findByUniquePredicate(result.calls) { c: CallExpression -> @@ -565,8 +565,8 @@ internal class FunctionTemplateTest : BaseTest() { assertEquals(1, templateDeclaration.realization.size) assertEquals(fixedDivision, templateDeclaration.realization[0]) assertEquals(2, templateDeclaration.parameters.size) - assertTrue(templateDeclaration.parameters[0] is TypeParamDeclaration) - assertTrue(templateDeclaration.parameters[1] is ParamVariableDeclaration) + assertTrue(templateDeclaration.parameters[0] is TypeParameterDeclaration) + assertTrue(templateDeclaration.parameters[1] is ParameterDeclaration) assertEquals(1, fixedDivision.parameters.size) val callDouble3 = findByUniquePredicate(result.calls) { c: CallExpression -> 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 cef82e7c9b..5a0ea31a7c 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 @@ -32,12 +32,12 @@ import de.fraunhofer.aisec.cpg.TestUtils.assertUsageOfMemberAndBase import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.declarations.* import de.fraunhofer.aisec.cpg.graph.statements.CatchClause -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement import de.fraunhofer.aisec.cpg.graph.statements.ForStatement import de.fraunhofer.aisec.cpg.graph.statements.IfStatement -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression import de.fraunhofer.aisec.cpg.graph.statements.expressions.Literal +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import java.nio.file.Path import java.util.concurrent.ExecutionException import kotlin.test.Test @@ -125,7 +125,7 @@ internal class VariableResolverCppTest : BaseTest() { @Test fun testVarNameOfFirstLoopAccessed() { - val asReference = callParamMap["func1_first_loop_varName"] as? DeclaredReferenceExpression + val asReference = callParamMap["func1_first_loop_varName"] as? Reference assertNotNull(asReference) val vDeclaration = forStatements?.first().variables["varName"] assertUsageOf(callParamMap["func1_first_loop_varName"], vDeclaration) @@ -133,7 +133,7 @@ internal class VariableResolverCppTest : BaseTest() { @Test fun testAccessLocalVarNameInNestedBlock() { - val innerBlock = forStatements?.get(1).allChildren()[""] + val innerBlock = forStatements?.get(1).allChildren()[""] val nestedDeclaration = innerBlock.variables["varName"] assertUsageOf(callParamMap["func1_nested_block_shadowed_local_varName"], nestedDeclaration) } 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 0e4a987c74..291c29a372 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 @@ -34,7 +34,7 @@ import de.fraunhofer.aisec.cpg.graph.get import de.fraunhofer.aisec.cpg.graph.methods import de.fraunhofer.aisec.cpg.graph.records import de.fraunhofer.aisec.cpg.graph.statements.ReturnStatement -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import de.fraunhofer.aisec.cpg.sarif.Region import java.io.File import kotlin.test.* @@ -75,7 +75,7 @@ internal class CXXIncludeTest : BaseTest() { val returnStatement = doSomething.getBodyStatementAs(0, ReturnStatement::class.java) assertNotNull(returnStatement) - val ref = returnStatement.returnValue as DeclaredReferenceExpression + val ref = returnStatement.returnValue as Reference assertNotNull(ref) val someField = someClass.fields["someField"] 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 b618ca00f9..c2efd1901e 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 @@ -69,7 +69,7 @@ internal class CXXLanguageFrontendTest : BaseTest() { assertNotNull(forEachStatement) // should loop over ls - assertEquals(ls, (forEachStatement.iterable as DeclaredReferenceExpression).refersTo) + assertEquals(ls, (forEachStatement.iterable as Reference).refersTo) // should declare auto i (so far no concrete type inferrable) val stmt = forEachStatement.variable @@ -206,7 +206,7 @@ internal class CXXLanguageFrontendTest : BaseTest() { with(tu) { assertNotNull(main) - val statement = main.body as CompoundStatement + val statement = main.body as Block // first statement is the variable declaration val x = @@ -224,9 +224,9 @@ internal class CXXLanguageFrontendTest : BaseTest() { assertEquals(3, initializers.size) // second statement is an expression directly - val ase = statement.statements[1] as ArraySubscriptionExpression + val ase = statement.statements[1] as SubscriptExpression assertNotNull(ase) - assertEquals(x, (ase.arrayExpression as DeclaredReferenceExpression).refersTo) + assertEquals(x, (ase.arrayExpression as Reference).refersTo) assertEquals(0, (ase.subscriptExpression as Literal<*>).value) // third statement declares a pointer to an array @@ -267,7 +267,7 @@ internal class CXXLanguageFrontendTest : BaseTest() { method = declaration.getDeclarationAs(2, FunctionDeclaration::class.java) assertEquals("function0(int)void", method!!.signature) - var statements = (method.body as CompoundStatement).statements + var statements = (method.body as Block).statements assertFalse(statements.isEmpty()) assertEquals(2, statements.size) @@ -279,7 +279,7 @@ internal class CXXLanguageFrontendTest : BaseTest() { method = declaration.getDeclarationAs(3, FunctionDeclaration::class.java) assertEquals("function2()void*", method!!.signature) - statements = (method.body as CompoundStatement).statements + statements = (method.body as Block).statements assertFalse(statements.isEmpty()) assertEquals(1, statements.size) @@ -316,7 +316,7 @@ internal class CXXLanguageFrontendTest : BaseTest() { @Test @Throws(Exception::class) - fun testCompoundStatement() { + fun testBlock() { val file = File("src/test/resources/compoundstmt.cpp") val declaration = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) val function = declaration.getDeclarationAs(0, FunctionDeclaration::class.java) @@ -325,7 +325,7 @@ internal class CXXLanguageFrontendTest : BaseTest() { val functionBody = function.body assertNotNull(functionBody) - val statements = (functionBody as CompoundStatement).statements + val statements = (functionBody as Block).statements assertEquals(1, statements.size) val returnStatement = statements[0] as ReturnStatement @@ -362,9 +362,9 @@ internal class CXXLanguageFrontendTest : BaseTest() { assertTrue(unaryOperatorMinus.isPostfix) // 4th statement is not yet parsed correctly - val memberCallExpression = statements[4] as MemberCallExpression - assertLocalName("test", memberCallExpression.base) - assertLocalName("c_str", memberCallExpression) + val memberCallExpr = statements[4] as MemberCallExpression + assertLocalName("test", memberCallExpr.base) + assertLocalName("c_str", memberCallExpr) } @Test @@ -381,12 +381,8 @@ internal class CXXLanguageFrontendTest : BaseTest() { assertNotNull(ifStatement.condition) assertEquals("bool", ifStatement.condition!!.type.typeName) assertEquals(true, (ifStatement.condition as Literal<*>).value) - assertTrue( - (ifStatement.thenStatement as CompoundStatement).statements[0] is ReturnStatement - ) - assertTrue( - (ifStatement.elseStatement as CompoundStatement).statements[0] is ReturnStatement - ) + assertTrue((ifStatement.thenStatement as Block).statements[0] is ReturnStatement) + assertTrue((ifStatement.elseStatement as Block).statements[0] is ReturnStatement) } @Test @@ -401,7 +397,7 @@ internal class CXXLanguageFrontendTest : BaseTest() { assertTrue(switchStatements.size == 3) val switchStatement = switchStatements[0] - assertTrue((switchStatement.statement as CompoundStatement).statements.size == 11) + assertTrue((switchStatement.statement as Block).statements.size == 11) val caseStatements = switchStatement.allChildren() assertTrue(caseStatements.size == 4) @@ -531,7 +527,7 @@ internal class CXXLanguageFrontendTest : BaseTest() { lhs = assignB.lhs() rhs = assignB.rhs() assertLocalName("a", lhs) - assertTrue(rhs is DeclaredReferenceExpression) + assertTrue(rhs is Reference) assertLocalName("b", rhs) assertRefersTo(rhs, b) @@ -550,8 +546,8 @@ internal class CXXLanguageFrontendTest : BaseTest() { fun testShiftExpression() { val file = File("src/test/resources/shiftexpression.cpp") val declaration = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) - val functionDeclaration = declaration.getDeclarationAs(0, FunctionDeclaration::class.java) - val statements = functionDeclaration?.statements + val functionDecl = declaration.getDeclarationAs(0, FunctionDeclaration::class.java) + val statements = functionDecl?.statements assertNotNull(statements) assertTrue(statements[1] is BinaryOperator) } @@ -639,14 +635,14 @@ internal class CXXLanguageFrontendTest : BaseTest() { var assign = statements[2] as? AssignExpression assertNotNull(assign) - var ref = assign.lhs() + var ref = assign.lhs() assertNotNull(ref) assertLocalName("a", ref) var binOp = assign.rhs() assertNotNull(binOp) - assertTrue(binOp.lhs is DeclaredReferenceExpression) + assertTrue(binOp.lhs is Reference) assertLocalName("b", binOp.lhs) assertTrue(binOp.rhs is Literal<*>) assertEquals(2, (binOp.rhs as Literal<*>).value) @@ -655,7 +651,7 @@ internal class CXXLanguageFrontendTest : BaseTest() { assign = statements[3] as? AssignExpression assertNotNull(assign) - ref = assign.lhs() + ref = assign.lhs() assertNotNull(ref) assertLocalName("a", ref) @@ -791,7 +787,7 @@ internal class CXXLanguageFrontendTest : BaseTest() { assertNotNull(methodCallWithConstant) val arg = methodCallWithConstant.arguments[0] - assertSame(constant, (arg as DeclaredReferenceExpression).refersTo) + assertSame(constant, (arg as Reference).refersTo) val anotherMethod = tu.methods["anotherMethod"] assertNotNull(anotherMethod) @@ -917,7 +913,7 @@ internal class CXXLanguageFrontendTest : BaseTest() { with(tu) { // get the main method val main = tu.getDeclarationAs(3, FunctionDeclaration::class.java) - val statement = main!!.body as CompoundStatement + val statement = main!!.body as Block // Integer i val i = @@ -927,10 +923,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { assertEquals(tu.objectType("Integer"), i.type) // initializer should be a construct expression - var constructExpression = i.initializer as? ConstructExpression - assertNotNull(constructExpression) + var constructExpr = i.initializer as? ConstructExpression + assertNotNull(constructExpr) // type of the construct expression should also be Integer - assertEquals(tu.objectType("Integer"), constructExpression.type) + assertEquals(tu.objectType("Integer"), constructExpr.type) // auto (Integer) m val m = @@ -939,7 +935,7 @@ internal class CXXLanguageFrontendTest : BaseTest() { // type should be Integer* assertEquals(objectType("Integer").pointer(), m.type) - val constructor = constructExpression.constructor + val constructor = constructExpr.constructor assertNotNull(constructor) assertLocalName("Integer", constructor) assertFalse(constructor.isImplicit) @@ -951,13 +947,13 @@ internal class CXXLanguageFrontendTest : BaseTest() { assertEquals(objectType("Integer").pointer(), newExpression.type) // initializer should be a construct expression - constructExpression = newExpression.initializer as? ConstructExpression - assertNotNull(constructExpression) + constructExpr = newExpression.initializer as? ConstructExpression + assertNotNull(constructExpr) // type of the construct expression should be Integer - assertEquals(objectType("Integer"), constructExpression.type) + assertEquals(objectType("Integer"), constructExpr.type) // argument should be named k and of type m - val k = constructExpression.arguments[0] as DeclaredReferenceExpression + val k = constructExpr.arguments[0] as Reference assertLocalName("k", k) // type of the construct expression should also be Integer assertEquals(primitiveType("int"), k.type) @@ -966,7 +962,7 @@ internal class CXXLanguageFrontendTest : BaseTest() { private val FunctionDeclaration.statements: List? get() { - return (this.body as? CompoundStatement)?.statements + return (this.body as? Block)?.statements } @Test @@ -975,7 +971,7 @@ internal class CXXLanguageFrontendTest : BaseTest() { val file = File("src/test/resources/cfg.cpp") val declaration = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) val fdecl = declaration.getDeclarationAs(0, FunctionDeclaration::class.java) - val body = fdecl!!.body as CompoundStatement + val body = fdecl!!.body as Block val expected: MutableMap = HashMap() expected["cout << \"bla\";"] = Region(4, 3, 4, 17) expected["cout << \"blubb\";"] = Region(5, 3, 5, 19) @@ -1001,9 +997,9 @@ internal class CXXLanguageFrontendTest : BaseTest() { val method = declaration.getDeclarationAs(1, FunctionDeclaration::class.java) assertEquals("main()int", method!!.signature) - assertTrue(method.body is CompoundStatement) + assertTrue(method.body is Block) - val statements = (method.body as CompoundStatement).statements + val statements = (method.body as Block).statements assertEquals(4, statements.size) assertTrue(statements[0] is DeclarationStatement) assertTrue(statements[1] is DeclarationStatement) @@ -1020,19 +1016,19 @@ internal class CXXLanguageFrontendTest : BaseTest() { assertTrue(initializer.initializers[2] is DesignatedInitializerExpression) var die = initializer.initializers[0] as DesignatedInitializerExpression - assertTrue(die.lhs[0] is DeclaredReferenceExpression) + assertTrue(die.lhs[0] is Reference) assertTrue(die.rhs is Literal<*>) assertLocalName("y", die.lhs[0]) assertEquals(0, (die.rhs as Literal<*>).value) die = initializer.initializers[1] as DesignatedInitializerExpression - assertTrue(die.lhs[0] is DeclaredReferenceExpression) + assertTrue(die.lhs[0] is Reference) assertTrue(die.rhs is Literal<*>) assertLocalName("z", die.lhs[0]) assertEquals(1, (die.rhs as Literal<*>).value) die = initializer.initializers[2] as DesignatedInitializerExpression - assertTrue(die.lhs[0] is DeclaredReferenceExpression) + assertTrue(die.lhs[0] is Reference) assertTrue(die.rhs is Literal<*>) assertLocalName("x", die.lhs[0]) assertEquals(2, (die.rhs as Literal<*>).value) @@ -1045,7 +1041,7 @@ internal class CXXLanguageFrontendTest : BaseTest() { assertTrue(initializer.initializers[0] is DesignatedInitializerExpression) die = initializer.initializers[0] as DesignatedInitializerExpression - assertTrue(die.lhs[0] is DeclaredReferenceExpression) + assertTrue(die.lhs[0] is Reference) assertTrue(die.rhs is Literal<*>) assertLocalName("x", die.lhs[0]) assertEquals(20, (die.rhs as Literal<*>).value) @@ -1219,7 +1215,7 @@ internal class CXXLanguageFrontendTest : BaseTest() { tu.getDeclarationsByName("main", FunctionDeclaration::class.java).iterator().next() assertNotNull(main) - val body = main.body as CompoundStatement + val body = main.body as Block assertNotNull(body) val returnStatement = body.statements[body.statements.size - 1] @@ -1283,10 +1279,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { val classTReturn = classTFoo.bodyOrNull() assertNotNull(classTReturn) - val classTReturnMember = classTReturn.returnValue as? MemberExpression - assertNotNull(classTReturnMember) + val classTReturnMemberExpression = classTReturn.returnValue as? MemberExpression + assertNotNull(classTReturnMemberExpression) - val classTThisExpression = classTReturnMember.base as? DeclaredReferenceExpression + val classTThisExpression = classTReturnMemberExpression.base as? Reference assertEquals(classTThisExpression?.refersTo, classTFoo.receiver) val classS = tu.byNameOrNull("S") @@ -1298,10 +1294,10 @@ internal class CXXLanguageFrontendTest : BaseTest() { val classSReturn = classSFoo.bodyOrNull() assertNotNull(classSReturn) - val classSReturnMember = classSReturn.returnValue as? MemberExpression - assertNotNull(classSReturnMember) + val classSReturnMemberExpression = classSReturn.returnValue as? MemberExpression + assertNotNull(classSReturnMemberExpression) - val classSThisExpression = classSReturnMember.base as? DeclaredReferenceExpression + val classSThisExpression = classSReturnMemberExpression.base as? Reference assertEquals(classSThisExpression?.refersTo, classSFoo.receiver) assertNotEquals(classTFoo, classSFoo) assertNotEquals(classTFoo.receiver, classSFoo.receiver) @@ -1320,9 +1316,9 @@ internal class CXXLanguageFrontendTest : BaseTest() { tu.getDeclarationsByName("main", FunctionDeclaration::class.java).iterator().next() assertNotNull(main) - val returnStmt = main.bodyOrNull() - assertNotNull(returnStmt) - assertNotNull((returnStmt.returnValue as? DeclaredReferenceExpression)?.refersTo) + val returnStatement = main.bodyOrNull() + assertNotNull(returnStatement) + assertNotNull((returnStatement.returnValue as? Reference)?.refersTo) } @Test @@ -1470,14 +1466,11 @@ internal class CXXLanguageFrontendTest : BaseTest() { tu.calls("no_param_uninitialized").firstOrNull { it.callee is UnaryOperator } assertInvokes(assertNotNull(noParamNoInitPointerCall), target) - val noParamCall = - tu.calls("no_param").firstOrNull { it.callee is DeclaredReferenceExpression } + val noParamCall = tu.calls("no_param").firstOrNull { it.callee is Reference } assertInvokes(assertNotNull(noParamCall), target) val noParamNoInitCall = - tu.calls("no_param_uninitialized").firstOrNull { - it.callee is DeclaredReferenceExpression - } + tu.calls("no_param_uninitialized").firstOrNull { it.callee is Reference } assertInvokes(assertNotNull(noParamNoInitCall), target) val targetCall = tu.calls["target"] @@ -1518,14 +1511,11 @@ internal class CXXLanguageFrontendTest : BaseTest() { tu.calls("no_param_uninitialized").firstOrNull { it.callee is UnaryOperator } assertInvokes(assertNotNull(noParamNoInitPointerCall), target) - val noParamCall = - tu.calls("no_param").firstOrNull { it.callee is DeclaredReferenceExpression } + val noParamCall = tu.calls("no_param").firstOrNull { it.callee is Reference } assertInvokes(assertNotNull(noParamCall), target) val noParamNoInitCall = - tu.calls("no_param_uninitialized").firstOrNull { - it.callee is DeclaredReferenceExpression - } + tu.calls("no_param_uninitialized").firstOrNull { it.callee is Reference } assertInvokes(assertNotNull(noParamNoInitCall), target) val targetCall = tu.calls["target"] diff --git a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXSymbolConfigurationTest.kt b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXSymbolConfigurationTest.kt index 8c9b894742..ccd406702c 100644 --- a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXSymbolConfigurationTest.kt +++ b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXSymbolConfigurationTest.kt @@ -31,8 +31,8 @@ import de.fraunhofer.aisec.cpg.frontends.TranslationException import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration import de.fraunhofer.aisec.cpg.graph.statements.expressions.BinaryOperator import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.Literal +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import java.io.File import kotlin.test.Test import kotlin.test.assertEquals @@ -63,7 +63,7 @@ internal class CXXSymbolConfigurationTest : BaseTest() { // without additional symbols, the first line will look like a reference (to something we do // not know) - val dre = binaryOperator.getRhsAs(DeclaredReferenceExpression::class.java) + val dre = binaryOperator.getRhsAs(Reference::class.java) assertNotNull(dre) assertLocalName("HELLO_WORLD", dre) 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 21b9b6eaac..4e9ea44441 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 @@ -287,7 +287,7 @@ class CallResolverTest : BaseTest() { // Check defines edge assertEquals(displayDefinition, displayDeclaration.definition) - // Check defaults edge of ParamVariableDeclaration + // Check defaults edge of ParameterDeclaration assertEquals(displayDeclaration.defaultParameters, displayDefinition.defaultParameters) // Check call display(1); @@ -368,7 +368,7 @@ class CallResolverTest : BaseTest() { } val literalStar = findByUniquePredicate(result.literals) { it.value == '*' } val literal3 = findByUniquePredicate(result.literals) { it.value == 3 } - // Check defaults edge of ParamVariableDeclaration + // Check defaults edge of ParameterDeclaration assertTrue(displayFunction.defaultParameters[0] is Literal<*>) assertTrue(displayFunction.defaultParameters[1] is Literal<*>) assertEquals('*', (displayFunction.defaultParameters[0] as Literal<*>).value) diff --git a/cpg-language-go/src/main/golang/go.sum b/cpg-language-go/src/main/golang/go.sum index 9333aa5928..4ffefdd5d6 100644 --- a/cpg-language-go/src/main/golang/go.sum +++ b/cpg-language-go/src/main/golang/go.sum @@ -1,4 +1,27 @@ github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/DeclarationHandler.kt b/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/DeclarationHandler.kt index 3d102dc966..5aa878b488 100644 --- a/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/DeclarationHandler.kt +++ b/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/DeclarationHandler.kt @@ -29,8 +29,8 @@ import de.fraunhofer.aisec.cpg.frontends.Handler import de.fraunhofer.aisec.cpg.frontends.HandlerInterface import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.declarations.* -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement import de.fraunhofer.aisec.cpg.graph.statements.ReturnStatement +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block import de.fraunhofer.aisec.cpg.graph.types.Type import de.fraunhofer.aisec.cpg.graph.types.UnknownType @@ -171,7 +171,7 @@ class DeclarationHandler(frontend: GoLanguageFrontend) : frontend.typeOf(param.type) } - val p = newParamVariableDeclaration(name, type, variadic, rawNode = param) + val p = newParameterDeclaration(name, type, variadic, rawNode = param) frontend.scopeManager.addDeclaration(p) @@ -180,7 +180,7 @@ class DeclarationHandler(frontend: GoLanguageFrontend) : // Check, if the last statement is a return statement, otherwise we insert an implicit one val body = frontend.statementHandler.handle(funcDecl.body) - if (body is CompoundStatement) { + if (body is Block) { val last = body.statements.lastOrNull() if (last !is ReturnStatement) { val ret = newReturnStatement() diff --git a/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/ExpressionHandler.kt b/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/ExpressionHandler.kt index 6d268e6b2e..ee5c702d98 100644 --- a/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/ExpressionHandler.kt +++ b/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/ExpressionHandler.kt @@ -109,7 +109,7 @@ class ExpressionHandler(frontend: GoLanguageFrontend) : return literal } - val ref = newDeclaredReferenceExpression(ident.name, rawNode = ident) + val ref = newReference(ident.name, rawNode = ident) // Check, if this refers to a package import val import = frontend.currentTU?.getIncludeByName(ident.name) @@ -121,10 +121,8 @@ class ExpressionHandler(frontend: GoLanguageFrontend) : return ref } - private fun handleIndexExpr( - indexExpr: GoStandardLibrary.Ast.IndexExpr - ): ArraySubscriptionExpression { - val ase = newArraySubscriptionExpression(rawNode = indexExpr) + private fun handleIndexExpr(indexExpr: GoStandardLibrary.Ast.IndexExpr): SubscriptExpression { + val ase = newSubscriptExpression(rawNode = indexExpr) ase.arrayExpression = frontend.expressionHandler.handle(indexExpr.x) ase.subscriptExpression = frontend.expressionHandler.handle(indexExpr.index) @@ -224,7 +222,7 @@ class ExpressionHandler(frontend: GoLanguageFrontend) : val expression = // Actually make() can make more than just arrays, i.e. channels and maps if (args[0] is GoStandardLibrary.Ast.ArrayType) { - val array = newArrayCreationExpression(rawNode = callExpr) + val array = newNewArrayExpression(rawNode = callExpr) // second argument is a dimension (if this is an array), usually a literal if (args.size > 1) { @@ -250,9 +248,7 @@ class ExpressionHandler(frontend: GoLanguageFrontend) : return expression } - private fun handleSelectorExpr( - selectorExpr: GoStandardLibrary.Ast.SelectorExpr - ): DeclaredReferenceExpression { + private fun handleSelectorExpr(selectorExpr: GoStandardLibrary.Ast.SelectorExpr): Reference { val base = handle(selectorExpr.x) ?: newProblemExpression("missing base") // Check, if this just a regular reference to a variable with a package scope and not a @@ -273,7 +269,7 @@ class ExpressionHandler(frontend: GoLanguageFrontend) : // resolver will then resolve this val fqn = "${base.name}.${selectorExpr.sel.name}" - newDeclaredReferenceExpression(fqn, rawNode = selectorExpr) + newReference(fqn, rawNode = selectorExpr) } return ref @@ -281,14 +277,11 @@ class ExpressionHandler(frontend: GoLanguageFrontend) : /** * This function handles a ast.SliceExpr, which is an extended version of ast.IndexExpr. We are - * modelling this as a combination of a [ArraySubscriptionExpression] that contains a - * [RangeExpression] as its subscriptExpression to share some code between this and an index - * expression. + * modelling this as a combination of a [SubscriptExpression] that contains a [RangeExpression] + * as its subscriptExpression to share some code between this and an index expression. */ - private fun handleSliceExpr( - sliceExpr: GoStandardLibrary.Ast.SliceExpr - ): ArraySubscriptionExpression { - val ase = newArraySubscriptionExpression(rawNode = sliceExpr) + private fun handleSliceExpr(sliceExpr: GoStandardLibrary.Ast.SliceExpr): SubscriptExpression { + val ase = newSubscriptExpression(rawNode = sliceExpr) ase.arrayExpression = frontend.expressionHandler.handle(sliceExpr.x) ?: newProblemExpression("missing array expression") diff --git a/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/StatementHandler.kt b/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/StatementHandler.kt index 0159cf2d42..3d84a4a80f 100644 --- a/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/StatementHandler.kt +++ b/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/StatementHandler.kt @@ -96,7 +96,7 @@ class StatementHandler(frontend: GoLanguageFrontend) : } private fun handleBlockStmt(blockStmt: GoStandardLibrary.Ast.BlockStmt): Statement { - val compound = newCompoundStatement(rawNode = blockStmt) + val compound = newBlock(rawNode = blockStmt) frontend.scopeManager.enterScope(compound) @@ -180,7 +180,7 @@ class StatementHandler(frontend: GoLanguageFrontend) : * we create a call expression to a built-in call. */ private fun handleGoStmt(goStmt: GoStandardLibrary.Ast.GoStmt): CallExpression { - val ref = newDeclaredReferenceExpression("go") + val ref = newReference("go") val call = newCallExpression(ref, "go", rawNode = goStmt) call += frontend.expressionHandler.handle(goStmt.call) @@ -252,7 +252,7 @@ class StatementHandler(frontend: GoLanguageFrontend) : // TODO: not really the best way to deal with this // TODO: key type is always int. we could set this var ref = rangeStmt.key?.let { frontend.expressionHandler.handle(it) } - if (ref is DeclaredReferenceExpression) { + if (ref is Reference) { val key = newVariableDeclaration(ref.name, rawNode = rangeStmt.key) frontend.scopeManager.addDeclaration(key) stmt.addToPropertyEdgeDeclaration(key) @@ -260,7 +260,7 @@ class StatementHandler(frontend: GoLanguageFrontend) : // TODO: not really the best way to deal with this ref = rangeStmt.value?.let { frontend.expressionHandler.handle(it) } - if (ref is DeclaredReferenceExpression) { + if (ref is Reference) { val key = newVariableDeclaration(ref.name, rawNode = rangeStmt.key) frontend.scopeManager.addDeclaration(key) stmt.addToPropertyEdgeDeclaration(key) @@ -304,8 +304,7 @@ class StatementHandler(frontend: GoLanguageFrontend) : switchStmt.tag?.let { switch.selector = frontend.expressionHandler.handle(it) } val block = - handle(switchStmt.body) as? CompoundStatement - ?: return newProblemExpression("missing switch body") + handle(switchStmt.body) as? Block ?: return newProblemExpression("missing switch body") // Because of the way we parse the statements, the case statement turns out to be the last // statement. However, we need it to be the first statement, so we need to switch first and diff --git a/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/GoExtraPass.kt b/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/GoExtraPass.kt index de3dd2c9b6..f9c20d952e 100644 --- a/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/GoExtraPass.kt +++ b/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/GoExtraPass.kt @@ -37,7 +37,7 @@ import de.fraunhofer.aisec.cpg.graph.statements.ForEachStatement import de.fraunhofer.aisec.cpg.graph.statements.expressions.AssignExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.CastExpression -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import de.fraunhofer.aisec.cpg.graph.types.HasType import de.fraunhofer.aisec.cpg.graph.types.PointerType import de.fraunhofer.aisec.cpg.graph.types.Type @@ -174,7 +174,7 @@ class GoExtraPass(ctx: TranslationContext) : ComponentPass(ctx), ScopeProvider { // Loop through the target variables (left-hand side) for (expr in assign.lhs) { - if (expr is DeclaredReferenceExpression) { + if (expr is Reference) { // And try to resolve it val ref = scopeManager.resolveReference(expr) if (ref == null) { @@ -231,7 +231,7 @@ class GoExtraPass(ctx: TranslationContext) : ComponentPass(ctx), ScopeProvider { // cast expression. And this is only really necessary, if the function call has a single // argument. val callee = call.callee - if (parent != null && callee is DeclaredReferenceExpression && call.arguments.size == 1) { + if (parent != null && callee is Reference && call.arguments.size == 1) { val language = parent.language ?: GoLanguage() // First, check if this is a built-in type diff --git a/cpg-language-go/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/DeclarationTest.kt b/cpg-language-go/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/DeclarationTest.kt index 5e379141c1..ff07d6aa1a 100644 --- a/cpg-language-go/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/DeclarationTest.kt +++ b/cpg-language-go/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/DeclarationTest.kt @@ -34,7 +34,7 @@ import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.MethodDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.NamespaceDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import de.fraunhofer.aisec.cpg.graph.variables import java.nio.file.Path import kotlin.test.* @@ -163,7 +163,7 @@ class DeclarationTest { assertNotNull(printf) printf.arguments.drop(1).forEach { - val ref = assertIs(it) + val ref = assertIs(it) assertNotNull(ref.refersTo) } diff --git a/cpg-language-go/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/ExpressionTest.kt b/cpg-language-go/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/ExpressionTest.kt index 7921cec047..3bcdab33be 100644 --- a/cpg-language-go/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/ExpressionTest.kt +++ b/cpg-language-go/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/ExpressionTest.kt @@ -70,7 +70,7 @@ class ExpressionTest { val cast = s.initializer as? CastExpression assertNotNull(cast) assertFullName("main.MyStruct", cast.castType) - assertSame(f, (cast.expression as? DeclaredReferenceExpression)?.refersTo) + assertSame(f, (cast.expression as? Reference)?.refersTo) val ignored = main.variables("_") ignored.forEach { assertIs(it.initializer) } @@ -100,7 +100,7 @@ class ExpressionTest { // [:1] var slice = assertIs( - assertIs(b.initializer).subscriptExpression + assertIs(b.initializer).subscriptExpression ) assertNull(slice.floor) assertLiteralValue(1, slice.ceiling) @@ -111,7 +111,7 @@ class ExpressionTest { assertLocalName("int[]", c.type) // [1:] - slice = assertIs(assertIs(c.initializer).subscriptExpression) + slice = assertIs(assertIs(c.initializer).subscriptExpression) assertLiteralValue(1, slice.floor) assertNull(slice.ceiling) assertNull(slice.third) @@ -121,7 +121,7 @@ class ExpressionTest { assertLocalName("int[]", d.type) // [0:1] - slice = assertIs(assertIs(d.initializer).subscriptExpression) + slice = assertIs(assertIs(d.initializer).subscriptExpression) assertLiteralValue(0, slice.floor) assertLiteralValue(1, slice.ceiling) assertNull(slice.third) @@ -131,7 +131,7 @@ class ExpressionTest { assertLocalName("int[]", e.type) // [0:1:1] - slice = assertIs(assertIs(e.initializer).subscriptExpression) + slice = assertIs(assertIs(e.initializer).subscriptExpression) assertLiteralValue(0, slice.floor) assertLiteralValue(1, slice.ceiling) assertLiteralValue(1, slice.third) diff --git a/cpg-language-go/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/GoLanguageFrontendTest.kt b/cpg-language-go/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/GoLanguageFrontendTest.kt index 37776c62a3..c778028686 100644 --- a/cpg-language-go/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/GoLanguageFrontendTest.kt +++ b/cpg-language-go/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/GoLanguageFrontendTest.kt @@ -121,7 +121,7 @@ class GoLanguageFrontendTest : BaseTest() { val main = p.functions["main"] assertNotNull(main) - val body = main.body as? CompoundStatement + val body = main.body as? Block assertNotNull(body) var decl = main.variables["o"] @@ -143,7 +143,7 @@ class GoLanguageFrontendTest : BaseTest() { assertNotNull(make) with(tu) { assertEquals(tu.primitiveType("int").array(), make.type) } - assertTrue(make is ArrayCreationExpression) + assertTrue(make is NewArrayExpression) val dimension = make.dimensions.first() as? Literal<*> assertNotNull(dimension) @@ -266,7 +266,7 @@ class GoLanguageFrontendTest : BaseTest() { assertEquals(myTest.returnTypes.size, type.returnTypes.size) assertEquals(listOf("int", "error"), type.returnTypes.map { it.name.localName }) - var body = main.body as? CompoundStatement + var body = main.body as? Block assertNotNull(body) var callExpression = body.calls.firstOrNull() @@ -282,7 +282,7 @@ class GoLanguageFrontendTest : BaseTest() { assertLocalName("myTest", myTest) - body = myTest.body as? CompoundStatement + body = myTest.body as? Block assertNotNull(body) callExpression = body.statements.first() as? CallExpression @@ -297,7 +297,7 @@ class GoLanguageFrontendTest : BaseTest() { assertEquals("%s", literal.value) assertEquals(tu.primitiveType("string"), literal.type) - val ref = callExpression.arguments[1] as? DeclaredReferenceExpression + val ref = callExpression.arguments[1] as? Reference assertNotNull(ref) assertLocalName("s", ref) @@ -306,7 +306,7 @@ class GoLanguageFrontendTest : BaseTest() { val stmt = body.statements[1] as? AssignExpression assertNotNull(stmt) - val a = stmt.lhs.firstOrNull() as? DeclaredReferenceExpression + val a = stmt.lhs.firstOrNull() as? Reference assertNotNull(a) assertLocalName("a", a) @@ -382,7 +382,7 @@ class GoLanguageFrontendTest : BaseTest() { val newMyStruct = p.functions["NewMyStruct"] assertNotNull(newMyStruct) - val body = newMyStruct.body as? CompoundStatement + val body = newMyStruct.body as? Block assertNotNull(body) @@ -416,7 +416,7 @@ class GoLanguageFrontendTest : BaseTest() { assertNotNull(myFunc) assertLocalName("MyFunc", myFunc) - val body = myFunc.body as? CompoundStatement + val body = myFunc.body as? Block assertNotNull(body) @@ -432,7 +432,7 @@ class GoLanguageFrontendTest : BaseTest() { assertLocalName("myOtherFunc", arg1) assertFullName("p.MyStruct.myOtherFunc", arg1) - assertEquals(myFunc.receiver, (arg1.base as? DeclaredReferenceExpression)?.refersTo) + assertEquals(myFunc.receiver, (arg1.base as? Reference)?.refersTo) } @Test @@ -451,7 +451,7 @@ class GoLanguageFrontendTest : BaseTest() { val myFunc = p.methods["myFunc"] assertNotNull(myFunc) - val body = myFunc.body as? CompoundStatement + val body = myFunc.body as? Block assertNotNull(body) val assign = body.statements.first() as? AssignExpression @@ -459,11 +459,11 @@ class GoLanguageFrontendTest : BaseTest() { val lhs = assign.lhs.firstOrNull() as? MemberExpression assertNotNull(lhs) - assertEquals(myFunc.receiver, (lhs.base as? DeclaredReferenceExpression)?.refersTo) + assertEquals(myFunc.receiver, (lhs.base as? Reference)?.refersTo) assertLocalName("Field", lhs) assertEquals(tu.primitiveType("int"), lhs.type) - val rhs = assign.rhs.firstOrNull() as? DeclaredReferenceExpression + val rhs = assign.rhs.firstOrNull() as? Reference assertNotNull(rhs) assertFullName("otherPackage.OtherField", rhs) } @@ -480,7 +480,7 @@ class GoLanguageFrontendTest : BaseTest() { val main = tu.functions["p.main"] assertNotNull(main) - val body = main.body as? CompoundStatement + val body = main.body as? Block assertNotNull(body) val b = @@ -493,7 +493,7 @@ class GoLanguageFrontendTest : BaseTest() { // true, false are builtin variables, NOT literals in Golang // we might need to parse this special case differently - val initializer = b.initializer as? DeclaredReferenceExpression + val initializer = b.initializer as? Reference assertNotNull(initializer) assertLocalName("true", initializer) @@ -516,13 +516,13 @@ class GoLanguageFrontendTest : BaseTest() { val myFunc = tu.functions["p.myFunc"] assertNotNull(myFunc) - val body = myFunc.body as? CompoundStatement + val body = myFunc.body as? Block assertNotNull(body) val switch = body.statements.first() as? SwitchStatement assertNotNull(switch) - val list = switch.statement as? CompoundStatement + val list = switch.statement as? Block assertNotNull(list) val case1 = list.statements[0] as? CaseStatement @@ -581,7 +581,7 @@ class GoLanguageFrontendTest : BaseTest() { val main = p.functions["main"] assertNotNull(main) - val body = main.body as? CompoundStatement + val body = main.body as? Block assertNotNull(body) val c = body.variables["c"] @@ -606,7 +606,7 @@ class GoLanguageFrontendTest : BaseTest() { val call = body.statements[1] as? MemberCallExpression assertNotNull(call) - val base = call.base as? DeclaredReferenceExpression + val base = call.base as? Reference assertNotNull(base) assertEquals(c, base.refersTo) @@ -634,14 +634,14 @@ class GoLanguageFrontendTest : BaseTest() { val f = main.bodyOrNull() assertNotNull(f) assertTrue(f.condition is BinaryOperator) - assertTrue(f.statement is CompoundStatement) + assertTrue(f.statement is Block) assertTrue(f.initializerStatement is AssignExpression) assertTrue(f.iterationStatement is UnaryOperator) val each = main.bodyOrNull() assertNotNull(each) - val bytes = assertIs(each.iterable) + val bytes = assertIs(each.iterable) assertLocalName("bytes", bytes) assertNotNull(bytes.refersTo) @@ -782,7 +782,7 @@ class GoLanguageFrontendTest : BaseTest() { val assign = tu.functions["main"].assignments.firstOrNull { - (it.target as? DeclaredReferenceExpression)?.refersTo == i + (it.target as? Reference)?.refersTo == i } assertNotNull(assign) diff --git a/cpg-language-go/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/StatementTest.kt b/cpg-language-go/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/StatementTest.kt index 3e698bc905..1abacc2c4c 100644 --- a/cpg-language-go/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/StatementTest.kt +++ b/cpg-language-go/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/StatementTest.kt @@ -29,8 +29,8 @@ import de.fraunhofer.aisec.cpg.TestUtils.analyzeAndGetFirstTU import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.statements.* import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.Literal +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import de.fraunhofer.aisec.cpg.graph.statements.expressions.UnaryOperator import java.nio.file.Path import kotlin.test.Test @@ -102,7 +102,7 @@ class StatementTest { // The EOG for the defer statement itself should be in the regular EOG path op.prevEOG.any { it is CallExpression && it.name.localName == "do" } - op.nextEOG.any { it is DeclaredReferenceExpression && it.name.localName == "that" } + op.nextEOG.any { it is Reference && it.name.localName == "that" } // It should NOT connect to the call expression op.nextEOG.none { it is CallExpression } diff --git a/cpg-language-java/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/java/DeclarationHandler.kt b/cpg-language-java/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/java/DeclarationHandler.kt index c837e27051..285cacf5b9 100644 --- a/cpg-language-java/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/java/DeclarationHandler.kt +++ b/cpg-language-java/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/java/DeclarationHandler.kt @@ -55,25 +55,27 @@ open class DeclarationHandler(lang: JavaLanguageFrontend) : lang ) { fun handleConstructorDeclaration( - constructorDecl: ConstructorDeclaration + constructorDeclaration: ConstructorDeclaration ): de.fraunhofer.aisec.cpg.graph.declarations.ConstructorDeclaration { - val resolvedConstructor = constructorDecl.resolve() + val resolvedConstructor = constructorDeclaration.resolve() val currentRecordDecl = frontend.scopeManager.currentRecord val declaration = this.newConstructorDeclaration( resolvedConstructor.name, - constructorDecl.toString(), + constructorDeclaration.toString(), currentRecordDecl ) frontend.scopeManager.addDeclaration(declaration) frontend.scopeManager.enterScope(declaration) createMethodReceiver(currentRecordDecl, declaration) declaration.addThrowTypes( - constructorDecl.thrownExceptions.map { type: ReferenceType -> frontend.typeOf(type) } + constructorDeclaration.thrownExceptions.map { type: ReferenceType -> + frontend.typeOf(type) + } ) - for (parameter in constructorDecl.parameters) { + for (parameter in constructorDeclaration.parameters) { val param = - this.newParamVariableDeclaration( + this.newParameterDeclaration( parameter.nameAsString, frontend.getTypeAsGoodAsPossible(parameter, parameter.resolve()), parameter.isVarArgs @@ -92,10 +94,10 @@ open class DeclarationHandler(lang: JavaLanguageFrontend) : } // check, if constructor has body (i.e. it's not abstract or something) - val body = constructorDecl.body + val body = constructorDeclaration.body addImplicitReturn(body) declaration.body = frontend.statementHandler.handle(body) - frontend.processAnnotations(declaration, constructorDecl) + frontend.processAnnotations(declaration, constructorDeclaration) frontend.scopeManager.leaveScope(declaration) return declaration } @@ -127,7 +129,7 @@ open class DeclarationHandler(lang: JavaLanguageFrontend) : resolvedType = frontend.getTypeAsGoodAsPossible(parameter, parameter.resolve()) } val param = - this.newParamVariableDeclaration( + this.newParameterDeclaration( parameter.nameAsString, resolvedType, parameter.isVarArgs @@ -157,14 +159,14 @@ open class DeclarationHandler(lang: JavaLanguageFrontend) : } private fun createMethodReceiver( - recordDecl: RecordDeclaration?, + recordDeclaration: RecordDeclaration?, functionDeclaration: de.fraunhofer.aisec.cpg.graph.declarations.MethodDeclaration ) { // create the receiver val receiver = this.newVariableDeclaration( "this", - recordDecl?.toType() ?: unknownType(), + recordDeclaration?.toType() ?: unknownType(), "this", false ) diff --git a/cpg-language-java/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/java/ExpressionHandler.kt b/cpg-language-java/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/java/ExpressionHandler.kt index 5950b651d6..3f2aed1749 100644 --- a/cpg-language-java/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/java/ExpressionHandler.kt +++ b/cpg-language-java/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/java/ExpressionHandler.kt @@ -29,8 +29,30 @@ import com.github.javaparser.Range import com.github.javaparser.TokenRange import com.github.javaparser.ast.Node import com.github.javaparser.ast.body.VariableDeclarator -import com.github.javaparser.ast.expr.* +import com.github.javaparser.ast.expr.ArrayAccessExpr +import com.github.javaparser.ast.expr.ArrayCreationExpr +import com.github.javaparser.ast.expr.ArrayInitializerExpr +import com.github.javaparser.ast.expr.BinaryExpr +import com.github.javaparser.ast.expr.BooleanLiteralExpr +import com.github.javaparser.ast.expr.CharLiteralExpr +import com.github.javaparser.ast.expr.ClassExpr +import com.github.javaparser.ast.expr.DoubleLiteralExpr +import com.github.javaparser.ast.expr.EnclosedExpr import com.github.javaparser.ast.expr.Expression +import com.github.javaparser.ast.expr.FieldAccessExpr +import com.github.javaparser.ast.expr.InstanceOfExpr +import com.github.javaparser.ast.expr.IntegerLiteralExpr +import com.github.javaparser.ast.expr.LiteralExpr +import com.github.javaparser.ast.expr.LongLiteralExpr +import com.github.javaparser.ast.expr.MethodCallExpr +import com.github.javaparser.ast.expr.NameExpr +import com.github.javaparser.ast.expr.NullLiteralExpr +import com.github.javaparser.ast.expr.ObjectCreationExpr +import com.github.javaparser.ast.expr.StringLiteralExpr +import com.github.javaparser.ast.expr.SuperExpr +import com.github.javaparser.ast.expr.ThisExpr +import com.github.javaparser.ast.expr.UnaryExpr +import com.github.javaparser.ast.expr.VariableDeclarationExpr import com.github.javaparser.resolution.UnsolvedSymbolException import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration import de.fraunhofer.aisec.cpg.frontends.Handler @@ -40,6 +62,8 @@ import de.fraunhofer.aisec.cpg.graph.declarations.MethodDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration import de.fraunhofer.aisec.cpg.graph.statements.* import de.fraunhofer.aisec.cpg.graph.statements.expressions.* +import de.fraunhofer.aisec.cpg.graph.statements.expressions.AssignExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.ConditionalExpression import de.fraunhofer.aisec.cpg.graph.types.* import java.util.function.Supplier import kotlin.collections.set @@ -57,7 +81,7 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : for (parameter in lambdaExpr.parameters) { val resolvedType = frontend.getTypeAsGoodAsPossible(parameter.type) val param = - this.newParamVariableDeclaration( + this.newParameterDeclaration( parameter.nameAsString, resolvedType, parameter.isVarArgs @@ -103,15 +127,15 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : } /** - * Creates a new [ArrayCreationExpression], which is usually used as an initializer of a + * Creates a new [NewArrayExpression], which is usually used as an initializer of a * [VariableDeclaration]. * * @param expr the expression - * @return the [ArrayCreationExpression] + * @return the [NewArrayExpression] */ private fun handleArrayCreationExpr(expr: Expression): Statement { val arrayCreationExpr = expr as ArrayCreationExpr - val creationExpression = this.newArrayCreationExpression(expr.toString()) + val creationExpression = this.newNewArrayExpression(expr.toString()) // in Java, an array creation expression either specifies an initializer or dimensions @@ -156,9 +180,9 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : return initList } - private fun handleArrayAccessExpr(expr: Expression): ArraySubscriptionExpression { + private fun handleArrayAccessExpr(expr: Expression): SubscriptExpression { val arrayAccessExpr = expr as ArrayAccessExpr - val arraySubsExpression = this.newArraySubscriptionExpression(expr.toString()) + val arraySubsExpression = this.newSubscriptExpression(expr.toString()) (handle(arrayAccessExpr.name) as de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression?) ?.let { arraySubsExpression.arrayExpression = it } @@ -255,7 +279,7 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : val initializer = handle(oInitializer.get()) as de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression? - if (initializer is ArrayCreationExpression) { + if (initializer is NewArrayExpression) { declaration.isArray = true } declaration.initializer = initializer @@ -334,12 +358,7 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : } } } - base = - this.newDeclaredReferenceExpression( - scope.asNameExpr().nameAsString, - baseType, - scope.toString() - ) + base = this.newReference(scope.asNameExpr().nameAsString, baseType, scope.toString()) base.isStaticAccess = isStaticAccess frontend.setCodeAndLocation(base, fieldAccessExpr.scope) } else if (scope.isFieldAccessExpr) { @@ -353,7 +372,7 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : // to this base tester = tester.base } - if (tester is DeclaredReferenceExpression && tester.isStaticAccess) { + if (tester is Reference && tester.isStaticAccess) { // try to get the name val name: String val tokenRange = scope.asFieldAccessExpr().tokenRange @@ -372,7 +391,7 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : unknownType() } base = - this.newDeclaredReferenceExpression( + this.newReference( scope.asFieldAccessExpr().nameAsString, baseType, scope.toString() @@ -483,11 +502,11 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : } } - private fun handleClassExpression(expr: Expression): DeclaredReferenceExpression { + private fun handleClassExpression(expr: Expression): Reference { val classExpr = expr.asClassExpr() val type = frontend.typeOf(classExpr.type) val thisExpression = - this.newDeclaredReferenceExpression( + this.newReference( classExpr.toString().substring(classExpr.toString().lastIndexOf('.') + 1), type, classExpr.toString() @@ -497,7 +516,7 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : return thisExpression } - private fun handleThisExpression(expr: Expression): DeclaredReferenceExpression { + private fun handleThisExpression(expr: Expression): Reference { val thisExpr = expr.asThisExpr() val resolvedValueDeclaration = thisExpr.resolve() val type = this.objectType(resolvedValueDeclaration.qualifiedName) @@ -512,17 +531,16 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : if (typeName.isPresent) { name = "this$" + typeName.get().identifier } - val thisExpression = this.newDeclaredReferenceExpression(name, type, thisExpr.toString()) + val thisExpression = this.newReference(name, type, thisExpr.toString()) frontend.setCodeAndLocation(thisExpression, thisExpr) return thisExpression } - private fun handleSuperExpression(expr: Expression): DeclaredReferenceExpression { + private fun handleSuperExpression(expr: Expression): Reference { // The actual type is hard to determine at this point, as we may not have full information // about the inheritance structure. Thus, we delay the resolving to the variable resolving // process - val superExpression = - this.newDeclaredReferenceExpression(expr.toString(), unknownType(), expr.toString()) + val superExpression = this.newReference(expr.toString(), unknownType(), expr.toString()) frontend.setCodeAndLocation(superExpression, expr) return superExpression } @@ -539,7 +557,7 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : // try { // ResolvedType resolvedType = nameExpr.calculateResolvedType(); // if (resolvedType.isReferenceType()) { - // return newDeclaredReferenceExpression( + // return newReference( // nameExpr.getNameAsString(), // new Type(((ReferenceTypeImpl) resolvedType).getQualifiedName()), // nameExpr.toString()); @@ -548,7 +566,7 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : // UnsolvedSymbolException // e) { // this might throw, e.g. if the type is simply not defined (i.e., syntax // error) - // return newDeclaredReferenceExpression( + // return newReference( // nameExpr.getNameAsString(), new Type(UNKNOWN_TYPE), nameExpr.toString()); // } val name = this.parseName(nameExpr.nameAsString) @@ -603,7 +621,7 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : if (type == null) { type = frontend.typeOf(symbol.type) } - this.newDeclaredReferenceExpression(symbol.name, type, nameExpr.toString()) + this.newReference(symbol.name, type, nameExpr.toString()) } } catch (ex: UnsolvedSymbolException) { val typeString: String? = @@ -623,8 +641,7 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : t = this.objectType(typeString) t.typeOrigin = Type.Origin.GUESSED } - val declaredReferenceExpression = - this.newDeclaredReferenceExpression(name, t, nameExpr.toString()) + val declaredReferenceExpression = this.newReference(name, t, nameExpr.toString()) val recordDeclaration = frontend.scopeManager.currentRecord if (recordDeclaration != null && recordDeclaration.name.lastPartsMatch(name)) { declaredReferenceExpression.refersTo = recordDeclaration @@ -633,11 +650,11 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : } catch (ex: RuntimeException) { val t = unknownType() log.info("Unresolved symbol: {}", nameExpr.nameAsString) - this.newDeclaredReferenceExpression(nameExpr.nameAsString, t, nameExpr.toString()) + this.newReference(nameExpr.nameAsString, t, nameExpr.toString()) } catch (ex: NoClassDefFoundError) { val t = unknownType() log.info("Unresolved symbol: {}", nameExpr.nameAsString) - this.newDeclaredReferenceExpression(nameExpr.nameAsString, t, nameExpr.toString()) + this.newReference(nameExpr.nameAsString, t, nameExpr.toString()) } } @@ -745,7 +762,7 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : ?: newProblemExpression("Could not parse base") // If the base directly refers to a record, then this is a static call - if (base is DeclaredReferenceExpression && base.refersTo is RecordDeclaration) { + if (base is Reference && base.refersTo is RecordDeclaration) { isStatic = true } } else { @@ -767,7 +784,7 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : this.parseName(qualifiedName).parent } baseType = this.objectType(baseName ?: Type.UNKNOWN_TYPE_STRING) - base = this.newDeclaredReferenceExpression(baseName, baseType) + base = this.newReference(baseName, baseType) } else { // Since it is possible to omit the "this" keyword, some methods in java do not have // a base. @@ -811,7 +828,7 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : val thisType = (frontend.scopeManager.currentFunction as MethodDeclaration?)?.receiver?.type ?: unknownType() - base = this.newDeclaredReferenceExpression("this", thisType, "this") + base = this.newReference("this", thisType, "this") base.isImplicit = true return base } @@ -881,7 +898,7 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : ctor.arguments.forEachIndexed { i, arg -> constructorDeclaration.addParameter( - newParamVariableDeclaration("arg${i}", arg.type) + newParameterDeclaration("arg${i}", arg.type) ) } anonymousRecord.addConstructor(constructorDeclaration) @@ -900,7 +917,9 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : } init { - map[AssignExpr::class.java] = HandlerInterface { handleAssignmentExpression(it) } + map[com.github.javaparser.ast.expr.AssignExpr::class.java] = HandlerInterface { + handleAssignmentExpression(it) + } map[FieldAccessExpr::class.java] = HandlerInterface { handleFieldAccessExpression(it) } map[LiteralExpr::class.java] = HandlerInterface { handleLiteralExpression(it) } map[ThisExpr::class.java] = HandlerInterface { handleThisExpression(it) } @@ -915,12 +934,18 @@ class ExpressionHandler(lang: JavaLanguageFrontend) : } map[MethodCallExpr::class.java] = HandlerInterface { handleMethodCallExpression(it) } map[ObjectCreationExpr::class.java] = HandlerInterface { handleObjectCreationExpr(it) } - map[ConditionalExpr::class.java] = HandlerInterface { handleConditionalExpression(it) } + map[com.github.javaparser.ast.expr.ConditionalExpr::class.java] = HandlerInterface { + handleConditionalExpression(it) + } map[EnclosedExpr::class.java] = HandlerInterface { handleEnclosedExpression(it) } map[ArrayAccessExpr::class.java] = HandlerInterface { handleArrayAccessExpr(it) } map[ArrayCreationExpr::class.java] = HandlerInterface { handleArrayCreationExpr(it) } map[ArrayInitializerExpr::class.java] = HandlerInterface { handleArrayInitializerExpr(it) } - map[CastExpr::class.java] = HandlerInterface { handleCastExpr(it) } - map[LambdaExpr::class.java] = HandlerInterface { handleLambdaExpr(it) } + map[com.github.javaparser.ast.expr.CastExpr::class.java] = HandlerInterface { + handleCastExpr(it) + } + map[com.github.javaparser.ast.expr.LambdaExpr::class.java] = HandlerInterface { + handleLambdaExpr(it) + } } } diff --git a/cpg-language-java/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/java/StatementHandler.kt b/cpg-language-java/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/java/StatementHandler.kt index 4dd85bb37e..70c79305ad 100644 --- a/cpg-language-java/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/java/StatementHandler.kt +++ b/cpg-language-java/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/java/StatementHandler.kt @@ -38,7 +38,21 @@ import de.fraunhofer.aisec.cpg.frontends.HandlerInterface import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.declarations.VariableDeclaration import de.fraunhofer.aisec.cpg.graph.statements.* -import de.fraunhofer.aisec.cpg.graph.statements.expressions.ExplicitConstructorInvocation +import de.fraunhofer.aisec.cpg.graph.statements.AssertStatement +import de.fraunhofer.aisec.cpg.graph.statements.BreakStatement +import de.fraunhofer.aisec.cpg.graph.statements.ContinueStatement +import de.fraunhofer.aisec.cpg.graph.statements.DoStatement +import de.fraunhofer.aisec.cpg.graph.statements.EmptyStatement +import de.fraunhofer.aisec.cpg.graph.statements.ForEachStatement +import de.fraunhofer.aisec.cpg.graph.statements.ForStatement +import de.fraunhofer.aisec.cpg.graph.statements.IfStatement +import de.fraunhofer.aisec.cpg.graph.statements.ReturnStatement +import de.fraunhofer.aisec.cpg.graph.statements.SwitchStatement +import de.fraunhofer.aisec.cpg.graph.statements.SynchronizedStatement +import de.fraunhofer.aisec.cpg.graph.statements.TryStatement +import de.fraunhofer.aisec.cpg.graph.statements.WhileStatement +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block +import de.fraunhofer.aisec.cpg.graph.statements.expressions.ConstructorCallExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.Literal import de.fraunhofer.aisec.cpg.graph.statements.expressions.ProblemExpression import de.fraunhofer.aisec.cpg.graph.types.Type @@ -306,7 +320,7 @@ class StatementHandler(lang: JavaLanguageFrontend?) : synchronizedCPG.expression = frontend.expressionHandler.handle(synchronizedJava.expression) as de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression - synchronizedCPG.blockStatement = handle(synchronizedJava.body) as CompoundStatement? + synchronizedCPG.block = handle(synchronizedJava.body) as Block? return synchronizedCPG } @@ -336,11 +350,11 @@ class StatementHandler(lang: JavaLanguageFrontend?) : return continueStatement } - fun handleBlockStatement(stmt: Statement): CompoundStatement { + fun handleBlockStatement(stmt: Statement): Block { val blockStmt = stmt.asBlockStmt() // first of, all we need a compound statement - val compoundStatement = this.newCompoundStatement(stmt.toString()) + val compoundStatement = this.newBlock(stmt.toString()) frontend.scopeManager.enterScope(compoundStatement) for (child in blockStmt.statements) { val statement = handle(child) @@ -483,7 +497,7 @@ class StatementHandler(lang: JavaLanguageFrontend?) : start = getNextTokenWith("{", tokenRangeSelector.get().end) end = getPreviousTokenWith("}", tokenRange.get().end) } - val compoundStatement = this.newCompoundStatement(getCodeBetweenTokens(start, end)) + val compoundStatement = this.newBlock(getCodeBetweenTokens(start, end)) compoundStatement.location = getLocationsFromTokens(switchStatement.location, start, end) for (sentry in switchStmt.entries) { if (sentry.labels.isEmpty()) { @@ -503,10 +517,8 @@ class StatementHandler(lang: JavaLanguageFrontend?) : return switchStatement } - private fun handleExplicitConstructorInvocation( - stmt: Statement - ): ExplicitConstructorInvocation { - val eciStatement = stmt.asExplicitConstructorInvocationStmt() + private fun handleExplicitConstructorInvocation(stmt: Statement): ConstructorCallExpression { + val explicitConstructorInvocationStmt = stmt.asExplicitConstructorInvocationStmt() var containingClass = "" val currentRecord = frontend.scopeManager.currentRecord if (currentRecord == null) { @@ -516,9 +528,13 @@ class StatementHandler(lang: JavaLanguageFrontend?) : } else { containingClass = currentRecord.name.toString() } - val node = this.newExplicitConstructorInvocation(containingClass, eciStatement.toString()) + val node = + this.newConstructorCallExpression( + containingClass, + explicitConstructorInvocationStmt.toString() + ) val arguments = - eciStatement.arguments + explicitConstructorInvocationStmt.arguments .stream() .map { ctx: Expression -> frontend.expressionHandler.handle(ctx) } .map { obj: de.fraunhofer.aisec.cpg.graph.statements.Statement? -> @@ -604,27 +620,42 @@ class StatementHandler(lang: JavaLanguageFrontend?) : } init { - map[IfStmt::class.java] = HandlerInterface { stmt: Statement -> handleIfStatement(stmt) } - map[AssertStmt::class.java] = HandlerInterface { stmt: Statement -> - handleAssertStatement(stmt) - } - map[WhileStmt::class.java] = HandlerInterface { stmt: Statement -> - handleWhileStatement(stmt) - } - map[DoStmt::class.java] = HandlerInterface { stmt: Statement -> handleDoStatement(stmt) } - map[ForEachStmt::class.java] = HandlerInterface { stmt: Statement -> - handleForEachStatement(stmt) - } - map[ForStmt::class.java] = HandlerInterface { stmt: Statement -> handleForStatement(stmt) } - map[BreakStmt::class.java] = HandlerInterface { stmt: Statement -> - handleBreakStatement(stmt) - } - map[ContinueStmt::class.java] = HandlerInterface { stmt: Statement -> - handleContinueStatement(stmt) - } - map[ReturnStmt::class.java] = HandlerInterface { stmt: Statement -> - handleReturnStatement(stmt) - } + map[com.github.javaparser.ast.stmt.IfStmt::class.java] = + HandlerInterface { stmt: Statement -> + handleIfStatement(stmt) + } + map[com.github.javaparser.ast.stmt.AssertStmt::class.java] = + HandlerInterface { stmt: Statement -> + handleAssertStatement(stmt) + } + map[com.github.javaparser.ast.stmt.WhileStmt::class.java] = + HandlerInterface { stmt: Statement -> + handleWhileStatement(stmt) + } + map[com.github.javaparser.ast.stmt.DoStmt::class.java] = + HandlerInterface { stmt: Statement -> + handleDoStatement(stmt) + } + map[com.github.javaparser.ast.stmt.ForEachStmt::class.java] = + HandlerInterface { stmt: Statement -> + handleForEachStatement(stmt) + } + map[com.github.javaparser.ast.stmt.ForStmt::class.java] = + HandlerInterface { stmt: Statement -> + handleForStatement(stmt) + } + map[com.github.javaparser.ast.stmt.BreakStmt::class.java] = + HandlerInterface { stmt: Statement -> + handleBreakStatement(stmt) + } + map[com.github.javaparser.ast.stmt.ContinueStmt::class.java] = + HandlerInterface { stmt: Statement -> + handleContinueStatement(stmt) + } + map[com.github.javaparser.ast.stmt.ReturnStmt::class.java] = + HandlerInterface { stmt: Statement -> + handleReturnStatement(stmt) + } map[BlockStmt::class.java] = HandlerInterface { stmt: Statement -> handleBlockStatement(stmt) } @@ -637,16 +668,22 @@ class StatementHandler(lang: JavaLanguageFrontend?) : map[ExpressionStmt::class.java] = HandlerInterface { stmt: Statement -> handleExpressionStatement(stmt) } - map[SwitchStmt::class.java] = HandlerInterface { stmt: Statement -> - handleSwitchStatement(stmt) - } - map[EmptyStmt::class.java] = HandlerInterface { stmt: Statement -> - handleEmptyStatement(stmt) - } - map[SynchronizedStmt::class.java] = HandlerInterface { stmt: Statement -> - handleSynchronizedStatement(stmt) - } - map[TryStmt::class.java] = HandlerInterface { stmt: Statement -> handleTryStatement(stmt) } + map[com.github.javaparser.ast.stmt.SwitchStmt::class.java] = + HandlerInterface { stmt: Statement -> + handleSwitchStatement(stmt) + } + map[com.github.javaparser.ast.stmt.EmptyStmt::class.java] = + HandlerInterface { stmt: Statement -> + handleEmptyStatement(stmt) + } + map[com.github.javaparser.ast.stmt.SynchronizedStmt::class.java] = + HandlerInterface { stmt: Statement -> + handleSynchronizedStatement(stmt) + } + map[com.github.javaparser.ast.stmt.TryStmt::class.java] = + HandlerInterface { stmt: Statement -> + handleTryStatement(stmt) + } map[ThrowStmt::class.java] = HandlerInterface { stmt: Statement -> handleThrowStmt(stmt) } } } diff --git a/cpg-language-java/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/JavaCallResolverHelper.kt b/cpg-language-java/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/JavaCallResolverHelper.kt index d1ddc7973a..e556311e66 100644 --- a/cpg-language-java/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/JavaCallResolverHelper.kt +++ b/cpg-language-java/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/JavaCallResolverHelper.kt @@ -31,9 +31,9 @@ import de.fraunhofer.aisec.cpg.graph.Name import de.fraunhofer.aisec.cpg.graph.declarations.MethodDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration import de.fraunhofer.aisec.cpg.graph.objectType -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.MemberCallExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.MemberExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import de.fraunhofer.aisec.cpg.graph.types.HasType import de.fraunhofer.aisec.cpg.helpers.Util import de.fraunhofer.aisec.cpg.passes.CallResolver.Companion.LOGGER @@ -45,9 +45,9 @@ class JavaCallResolverHelper { * Handle calls in the form of `super.call()` or `ClassName.super.call()`, conforming to * JLS13 §15.12.1. * - * This function basically sets the correct type of the [DeclaredReferenceExpression] - * containing the "super" keyword. Afterwards, we can use the regular - * [CallResolver.resolveMemberCallee] to resolve the [MemberCallExpression]. + * This function basically sets the correct type of the [Reference] containing the "super" + * keyword. Afterwards, we can use the regular [CallResolver.resolveMemberCallee] to resolve + * the [MemberCallExpression]. * * @param callee The callee of the call expression that needs to be adjusted * @param curClass The class containing the call @@ -63,7 +63,7 @@ class JavaCallResolverHelper { // need to connect the super reference to the receiver of this method. val func = scopeManager.currentFunction if (func is MethodDeclaration) { - (callee.base as DeclaredReferenceExpression?)?.refersTo = func.receiver + (callee.base as Reference?)?.refersTo = func.receiver } // In the next step we can "cast" the base to the correct type, by setting the base @@ -95,7 +95,7 @@ class JavaCallResolverHelper { // the "this" object to the super class callee.base.type = superType - val refersTo = (callee.base as? DeclaredReferenceExpression)?.refersTo + val refersTo = (callee.base as? Reference)?.refersTo if (refersTo is HasType) { refersTo.type = superType refersTo.assignedTypes = mutableSetOf(superType) diff --git a/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/EOGTest.kt b/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/EOGTest.kt index 543adfc00d..50179304b3 100644 --- a/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/EOGTest.kt +++ b/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/EOGTest.kt @@ -37,7 +37,7 @@ import de.fraunhofer.aisec.cpg.graph.edge.Properties import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdge import de.fraunhofer.aisec.cpg.graph.statements.* import de.fraunhofer.aisec.cpg.graph.statements.expressions.BinaryOperator -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import de.fraunhofer.aisec.cpg.helpers.SubgraphWalker import de.fraunhofer.aisec.cpg.helpers.Util import de.fraunhofer.aisec.cpg.helpers.Util.Connect @@ -759,7 +759,7 @@ internal class EOGTest : BaseTest() { result.allChildren().filter { l -> l.location?.region?.startLine == 6 }[0] val a = result.refs[ - { l: DeclaredReferenceExpression -> + { l: Reference -> l.location?.region?.startLine == 8 && l.name.localName == "a" }] assertNotNull(a) diff --git a/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/calls/SuperCallTest.kt b/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/calls/SuperCallTest.kt index 4e21ae590d..7c7e31fde1 100644 --- a/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/calls/SuperCallTest.kt +++ b/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/calls/SuperCallTest.kt @@ -33,8 +33,8 @@ import de.fraunhofer.aisec.cpg.TestUtils.findByUniqueName import de.fraunhofer.aisec.cpg.TestUtils.findByUniquePredicate import de.fraunhofer.aisec.cpg.frontends.java.JavaLanguage import de.fraunhofer.aisec.cpg.graph.* -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.MemberExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import java.nio.file.Path import kotlin.test.Test import kotlin.test.assertEquals @@ -99,10 +99,10 @@ internal class SuperCallTest : BaseTest() { val getSuperField = findByUniqueName(methods, "getSuperField") refs = getSuperField.allChildren() val superFieldRef = findByUniquePredicate(refs) { "super.field" == it.code } - assertTrue(fieldRef.base is DeclaredReferenceExpression) + assertTrue(fieldRef.base is Reference) assertRefersTo(fieldRef.base, getField.receiver) assertEquals(field, fieldRef.refersTo) - assertTrue(superFieldRef.base is DeclaredReferenceExpression) + assertTrue(superFieldRef.base is Reference) assertRefersTo(superFieldRef.base, getSuperField.receiver) assertEquals(superField, superFieldRef.refersTo) } 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 4f360d1c95..d84509c91f 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 @@ -31,8 +31,8 @@ import de.fraunhofer.aisec.cpg.frontends.java.JavaLanguage import de.fraunhofer.aisec.cpg.graph.declarations.FieldDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.MethodDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement import de.fraunhofer.aisec.cpg.graph.statements.ForStatement +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block import de.fraunhofer.aisec.cpg.sarif.Region import java.io.File import kotlin.test.* @@ -82,7 +82,7 @@ class FrontendHelperTest { // 2 line comment in the constructor val constructor = classDeclaration.constructors.first() - val constructorAssignment = (constructor.body as CompoundStatement).statements[0] + val constructorAssignment = (constructor.body as Block).statements[0] assertNull(constructor.comment) constructorAssignment.comment = "" @@ -96,7 +96,7 @@ class FrontendHelperTest { val mainMethod = classDeclaration.declarations[1] as MethodDeclaration assertNull(mainMethod.comment) - val forLoop = (mainMethod.body as CompoundStatement).statements[0] as ForStatement + val forLoop = (mainMethod.body as Block).statements[0] as ForStatement forLoop.comment = null val comment6 = "for loop" @@ -112,7 +112,7 @@ class FrontendHelperTest { FrontendUtils.matchCommentToNode(comment7, Region(16, 26, 16, 32), tu) // assertEquals(comment7, forLoop.initializerStatement.comment) - val printStatement = (forLoop.statement as CompoundStatement).statements.first() + val printStatement = (forLoop.statement as Block).statements.first() printStatement.comment = null val comment8 = "Crazy print" val comment9 = "Comment which belongs to nothing" @@ -120,7 +120,7 @@ class FrontendHelperTest { FrontendUtils.matchCommentToNode(comment9, Region(18, 16, 18, 48), tu) assertTrue(printStatement.comment?.contains(comment8) == true) // TODO The second comment doesn't belong to the print but to the loop body - assertTrue((forLoop.statement as? CompoundStatement)?.comment?.contains(comment9) == true) + assertTrue((forLoop.statement as? Block)?.comment?.contains(comment9) == true) assertNull(mainMethod.comment) } @@ -148,8 +148,8 @@ class FrontendHelperTest { val tu = result.translationUnits.first() val classDeclaration = tu.declarations.first() as RecordDeclaration val mainMethod = classDeclaration.declarations[1] as MethodDeclaration - val forLoop = (mainMethod.body as CompoundStatement).statements[0] as ForStatement - val printStatement = (forLoop.statement as CompoundStatement).statements.first() + val forLoop = (mainMethod.body as Block).statements[0] as ForStatement + val printStatement = (forLoop.statement as Block).statements.first() val regionSysout = FrontendUtils.parseColumnPositionsFromFile(tu.code!!, 20, 13, 17, 17) 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 ccc0f737ad..db9856a8bb 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 @@ -131,7 +131,7 @@ internal class JavaLanguageFrontendTest : BaseTest() { assertNotNull(forEachStatement) // should loop over ls - assertEquals(ls, (forEachStatement.iterable as? DeclaredReferenceExpression)?.refersTo) + assertEquals(ls, (forEachStatement.iterable as? Reference)?.refersTo) // should declare String s val s = forEachStatement.variable @@ -153,7 +153,7 @@ internal class JavaLanguageFrontendTest : BaseTest() { // Check the flow from the iterable to the variable s assertEquals(1, sDecl.prevDFG.size) - assertTrue(forEachStatement.iterable as DeclaredReferenceExpression in sDecl.prevDFG) + assertTrue(forEachStatement.iterable as Reference in sDecl.prevDFG) // Check the flow from the variable s to the print assertTrue(sDecl in sce.arguments.first().prevDFG) } @@ -339,7 +339,7 @@ internal class JavaLanguageFrontendTest : BaseTest() { assertEquals(3, switchStatements.size) val switchStatement = switchStatements[0] - assertEquals(11, (switchStatement.statement as? CompoundStatement)?.statements?.size) + assertEquals(11, (switchStatement.statement as? Block)?.statements?.size) val caseStatements = switchStatement.allChildren() assertEquals(4, caseStatements.size) @@ -395,7 +395,7 @@ internal class JavaLanguageFrontendTest : BaseTest() { ) // expression itself should be a reference - val ref = cast.expression as? DeclaredReferenceExpression + val ref = cast.expression as? Reference assertNotNull(ref) assertEquals(e, ref.refersTo) } @@ -418,7 +418,7 @@ internal class JavaLanguageFrontendTest : BaseTest() { val main = record.methods[0] assertNotNull(main) - val statements = (main.body as? CompoundStatement)?.statements + val statements = (main.body as? Block)?.statements assertNotNull(statements) val a = (statements[0] as? DeclarationStatement)?.singleDeclaration as? VariableDeclaration @@ -430,7 +430,7 @@ internal class JavaLanguageFrontendTest : BaseTest() { } // it has an array creation initializer - val ace = a.initializer as? ArrayCreationExpression + val ace = a.initializer as? NewArrayExpression assertNotNull(ace) // which has a initializer list (1 entry) @@ -446,9 +446,9 @@ internal class JavaLanguageFrontendTest : BaseTest() { val b = (statements[1] as? DeclarationStatement)?.singleDeclaration as? VariableDeclaration // initializer is array subscription - val ase = b?.initializer as? ArraySubscriptionExpression + val ase = b?.initializer as? SubscriptExpression assertNotNull(ase) - assertEquals(a, (ase.arrayExpression as? DeclaredReferenceExpression)?.refersTo) + assertEquals(a, (ase.arrayExpression as? Reference)?.refersTo) assertEquals(0, (ase.subscriptExpression as? Literal<*>)?.value) } @@ -470,7 +470,7 @@ internal class JavaLanguageFrontendTest : BaseTest() { val main = record.methods[0] assertNotNull(main) - val statements = (main.body as? CompoundStatement)?.statements + val statements = (main.body as? Block)?.statements assertNotNull(statements) val l = (statements[1] as? DeclarationStatement)?.singleDeclaration as? VariableDeclaration @@ -631,8 +631,7 @@ internal class JavaLanguageFrontendTest : BaseTest() { assertNotNull(op) val lhs = op.lhs() - val receiver = - (lhs?.base as? DeclaredReferenceExpression)?.refersTo as? VariableDeclaration? + val receiver = (lhs?.base as? Reference)?.refersTo as? VariableDeclaration? assertNotNull(receiver) assertLocalName("this", receiver) assertEquals(tu.objectType("my.Animal"), receiver.type) @@ -771,7 +770,7 @@ internal class JavaLanguageFrontendTest : BaseTest() { val assign = doSomething.bodyOrNull() assertNotNull(assign) - val ref = ((assign.rhs())?.base as DeclaredReferenceExpression).refersTo + val ref = ((assign.rhs())?.base as Reference).refersTo assertNotNull(ref) assertSame(ref, thisOuterClass) } 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 19ca5ff223..0f2fa225f2 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 @@ -32,7 +32,6 @@ import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.VariableDeclaration import de.fraunhofer.aisec.cpg.graph.get import de.fraunhofer.aisec.cpg.graph.invoke -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement import de.fraunhofer.aisec.cpg.graph.statements.ReturnStatement import de.fraunhofer.aisec.cpg.graph.statements.expressions.* import de.fraunhofer.aisec.cpg.graph.variables @@ -73,25 +72,25 @@ class JavaLambdaTest { assertNotNull(mapBody) val outerVar = result.variables["outerVar"] assertNotNull(outerVar) - assertEquals(outerVar, (mapBody.lhs as? DeclaredReferenceExpression)?.refersTo) + assertEquals(outerVar, (mapBody.lhs as? Reference)?.refersTo) val testfunctionArg = result.calls { it.name.localName == "testFunction" }[0].arguments.first() - assertTrue(testfunctionArg is DeclaredReferenceExpression) + assertTrue(testfunctionArg is Reference) assertTrue( (testfunctionArg.refersTo as? VariableDeclaration)?.initializer is LambdaExpression ) val testfunctionBody = mapArg.function?.body as? BinaryOperator assertNotNull(testfunctionBody) - assertEquals(outerVar, (testfunctionBody.lhs as? DeclaredReferenceExpression)?.refersTo) + assertEquals(outerVar, (testfunctionBody.lhs as? Reference)?.refersTo) val lambdaVar = result.variables["lambdaVar"] assertNotNull(lambdaVar) - val constructExpression = + val constructExpr = (lambdaVar.initializer as? NewExpression)?.initializer as? ConstructExpression - assertNotNull(constructExpression) - val anonymousRecord = constructExpression.instantiates as? RecordDeclaration + assertNotNull(constructExpr) + val anonymousRecord = constructExpr.instantiates as? RecordDeclaration assertNotNull(anonymousRecord) assertTrue(anonymousRecord.isImplicit) assertEquals(1, anonymousRecord.superClasses.size) @@ -101,13 +100,13 @@ class JavaLambdaTest { val applyMethod = anonymousRecord.methods["apply"] assertNotNull(applyMethod) - val returnStmt = - (applyMethod.body as? CompoundStatement)?.statements?.firstOrNull() as? ReturnStatement - assertNotNull(returnStmt) + val returnStatement = + (applyMethod.body as? Block)?.statements?.firstOrNull() as? ReturnStatement + assertNotNull(returnStatement) assertEquals( outerVar, - (((returnStmt.returnValue as? BinaryOperator)?.lhs as? BinaryOperator)?.lhs - as? DeclaredReferenceExpression) + (((returnStatement.returnValue as? BinaryOperator)?.lhs as? BinaryOperator)?.lhs + as? Reference) ?.refersTo ) } diff --git a/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/java/StaticImportsTest.kt b/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/java/StaticImportsTest.kt index 19e796ba2e..b95108e88b 100644 --- a/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/java/StaticImportsTest.kt +++ b/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/java/StaticImportsTest.kt @@ -68,12 +68,12 @@ internal class StaticImportsTest : BaseTest() { assertNotNull(staticField) assertTrue(staticField.modifiers.contains("static")) - val memberExpressions = main.allChildren() + val memberExpressionExpressions = main.allChildren() // we have two member expressions, one to the field and one to the method - assertEquals(2, memberExpressions.size) + assertEquals(2, memberExpressionExpressions.size) // we want the one to the field - val usage = memberExpressions[{ it.type.name.localName == "int" }] + val usage = memberExpressionExpressions[{ it.type.name.localName == "int" }] assertNotNull(usage) assertEquals(staticField, usage.refersTo) } 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 8673c8c951..a94dbb6f50 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 @@ -31,8 +31,8 @@ import de.fraunhofer.aisec.cpg.frontends.java.JavaLanguage import de.fraunhofer.aisec.cpg.graph.declarations.FieldDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.MethodDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement import de.fraunhofer.aisec.cpg.graph.statements.ForStatement +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block import de.fraunhofer.aisec.cpg.sarif.Region import java.io.File import kotlin.test.* @@ -79,7 +79,7 @@ class CommentMatcherTest { // 2 line comment in the constructor val constructor = classDeclaration.constructors.first() - val constructorAssignment = (constructor.body as CompoundStatement).statements[0] + val constructorAssignment = (constructor.body as Block).statements[0] assertNull(constructor.comment) constructorAssignment.comment = "" @@ -93,7 +93,7 @@ class CommentMatcherTest { val mainMethod = classDeclaration.declarations[1] as MethodDeclaration assertNull(mainMethod.comment) - val forLoop = (mainMethod.body as CompoundStatement).statements[0] as ForStatement + val forLoop = (mainMethod.body as Block).statements[0] as ForStatement forLoop.comment = null val comment6 = "for loop" @@ -109,7 +109,7 @@ class CommentMatcherTest { CommentMatcher().matchCommentToNode(comment7, Region(16, 26, 16, 32), tu) // assertEquals(comment7, forLoop.initializerStatement.comment) - val printStatement = (forLoop.statement as CompoundStatement).statements.first() + val printStatement = (forLoop.statement as Block).statements.first() printStatement.comment = null val comment8 = "Crazy print" val comment9 = "Comment which belongs to nothing" @@ -117,7 +117,7 @@ class CommentMatcherTest { CommentMatcher().matchCommentToNode(comment9, Region(18, 16, 18, 48), tu) assertTrue(printStatement.comment?.contains(comment8) == true) // TODO The second comment doesn't belong to the print but to the loop body - assertTrue((forLoop.statement as? CompoundStatement)?.comment?.contains(comment9) == true) + assertTrue((forLoop.statement as? Block)?.comment?.contains(comment9) == true) assertNull(mainMethod.comment) } diff --git a/cpg-language-java/src/test/resources/components/ExplicitConstructorInvocationStmt.java b/cpg-language-java/src/test/resources/components/ExplicitConstructorInvocationStmt.java index ba38273b78..35584e231a 100644 --- a/cpg-language-java/src/test/resources/components/ExplicitConstructorInvocationStmt.java +++ b/cpg-language-java/src/test/resources/components/ExplicitConstructorInvocationStmt.java @@ -1,8 +1,8 @@ import java.util.Arrays; -class ExplicitConstructorInvocationStmt { +class ConstructorCallExpressionStmt { - public ExplicitConstructorInvocationStmt(){ + public ConstructorCallExpressionStmt(){ super(); } diff --git a/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/DeclarationHandler.kt b/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/DeclarationHandler.kt index 69754747d4..8e5b03b417 100644 --- a/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/DeclarationHandler.kt +++ b/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/DeclarationHandler.kt @@ -31,7 +31,7 @@ import de.fraunhofer.aisec.cpg.graph.declarations.Declaration import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.ProblemDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block import de.fraunhofer.aisec.cpg.graph.types.Type import org.bytedeco.javacpp.Pointer import org.bytedeco.llvm.LLVM.LLVMTypeRef @@ -119,7 +119,7 @@ class DeclarationHandler(lang: LLVMIRLanguageFrontend) : val type = frontend.typeOf(param) // TODO: support variardic - val decl = newParamVariableDeclaration(paramName, type, false, frontend.codeOf(param)) + val decl = newParameterDeclaration(paramName, type, false, frontend.codeOf(param)) frontend.scopeManager.addDeclaration(decl) frontend.bindingsCache[paramSymbolName] = decl @@ -148,18 +148,18 @@ class DeclarationHandler(lang: LLVMIRLanguageFrontend) : // as a compound statement // Take the entry block as our body - if (LLVMGetEntryBasicBlock(func) == bb && stmt is CompoundStatement) { + if (LLVMGetEntryBasicBlock(func) == bb && stmt is Block) { functionDeclaration.body = stmt } else if (LLVMGetEntryBasicBlock(func) == bb) { - functionDeclaration.body = newCompoundStatement() + functionDeclaration.body = newBlock() if (stmt != null) { - (functionDeclaration.body as CompoundStatement).addStatement(stmt) + (functionDeclaration.body as Block).addStatement(stmt) } } else { // add the label statement, containing this basic block as a compound statement to // our body (if we have none, which we should) if (stmt != null) { - (functionDeclaration.body as? CompoundStatement)?.addStatement(stmt) + (functionDeclaration.body as? Block)?.addStatement(stmt) } } diff --git a/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/ExpressionHandler.kt b/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/ExpressionHandler.kt index f38f01ff39..a6a6e72817 100644 --- a/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/ExpressionHandler.kt +++ b/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/ExpressionHandler.kt @@ -61,7 +61,7 @@ class ExpressionHandler(lang: LLVMIRLanguageFrontend) : LLVMConstantFPValueKind -> handleConstantFP(value) LLVMConstantPointerNullValueKind -> handleNullPointer(value) LLVMPoisonValueValueKind -> { - newDeclaredReferenceExpression("poison", frontend.typeOf(value), "poison") + newReference("poison", frontend.typeOf(value), "poison") } LLVMConstantTokenNoneValueKind -> newLiteral(null, unknownType(), frontend.codeOf(value)) @@ -80,7 +80,7 @@ class ExpressionHandler(lang: LLVMIRLanguageFrontend) : LLVMFunctionValueKind -> handleFunction(value) LLVMGlobalAliasValueKind -> { val name = frontend.getNameOf(value).first - newDeclaredReferenceExpression(name, frontend.typeOf(value), frontend.codeOf(value)) + newReference(name, frontend.typeOf(value), frontend.codeOf(value)) } LLVMMetadataAsValueValueKind, LLVMInlineAsmValueKind -> { @@ -113,9 +113,9 @@ class ExpressionHandler(lang: LLVMIRLanguageFrontend) : } newLiteral(operandName, cpgType, operandName) } else if (LLVMIsUndef(value) == 1) { - newDeclaredReferenceExpression("undef", cpgType, "undef") + newReference("undef", cpgType, "undef") } else if (LLVMIsPoison(value) == 1) { - newDeclaredReferenceExpression("poison", cpgType, "poison") + newReference("poison", cpgType, "poison") } else { log.error("Unknown expression {}", kind) newProblemExpression( @@ -128,13 +128,9 @@ class ExpressionHandler(lang: LLVMIRLanguageFrontend) : } } - /** Returns a [DeclaredReferenceExpression] for a function (pointer). */ + /** Returns a [Reference] for a function (pointer). */ private fun handleFunction(valueRef: LLVMValueRef): Expression { - return newDeclaredReferenceExpression( - valueRef.name, - frontend.typeOf(valueRef), - frontend.codeOf(valueRef) - ) + return newReference(valueRef.name, frontend.typeOf(valueRef), frontend.codeOf(valueRef)) } /** @@ -152,7 +148,7 @@ class ExpressionHandler(lang: LLVMIRLanguageFrontend) : val type = frontend.typeOf(valueRef) - val ref = newDeclaredReferenceExpression(name, type, "${type.typeName} $name") + val ref = newReference(name, type, "${type.typeName} $name") // try to resolve the reference. actually the valueRef is already referring to the resolved // variable because we obtain it using LLVMGetOperand, so we just need to look it up in the @@ -402,10 +398,10 @@ class ExpressionHandler(lang: LLVMIRLanguageFrontend) : * [`extractvalue`](https://llvm.org/docs/LangRef.html#extractvalue-instruction) instruction * which works in a similar way. * - * We try to convert it either into an [ArraySubscriptionExpression] or an [MemberExpression], - * depending on whether the accessed variable is a struct or an array. Furthermore, since - * `getelementptr` allows an (infinite) chain of sub-element access within a single instruction, - * we need to unwrap those into individual expressions. + * We try to convert it either into an [SubscriptExpression] or an [MemberExpression], depending + * on whether the accessed variable is a struct or an array. Furthermore, since `getelementptr` + * allows an (infinite) chain of sub-element access within a single instruction, we need to + * unwrap those into individual expressions. */ internal fun handleGetElementPtr(instr: LLVMValueRef): Expression { val isGetElementPtr = @@ -452,7 +448,7 @@ class ExpressionHandler(lang: LLVMIRLanguageFrontend) : (operand.value as Long).toInt() } else { // The index is some variable and thus unknown. - operand as DeclaredReferenceExpression + operand as Reference } } else { indices.get(idx.toLong()) @@ -461,7 +457,7 @@ class ExpressionHandler(lang: LLVMIRLanguageFrontend) : // check, if the current base type is a pointer -> then we need to handle this as an // array access if (baseType is PointerType) { - val arrayExpr = newArraySubscriptionExpression("") + val arrayExpr = newSubscriptExpression("") arrayExpr.arrayExpression = base arrayExpr.name = Name(index.toString()) arrayExpr.subscriptExpression = operand @@ -512,7 +508,7 @@ class ExpressionHandler(lang: LLVMIRLanguageFrontend) : // We won't find a field because it's accessed by a variable index. // We indicate this with this array-like notation for now. field = null - "[${(operand as DeclaredReferenceExpression).name.localName}]" + "[${(operand as Reference).name.localName}]" } // our new base-type is the type of the field diff --git a/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/LLVMIRLanguageFrontend.kt b/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/LLVMIRLanguageFrontend.kt index 65642a8d5d..b420810825 100644 --- a/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/LLVMIRLanguageFrontend.kt +++ b/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/LLVMIRLanguageFrontend.kt @@ -33,8 +33,8 @@ import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.declarations.Declaration import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.TranslationUnitDeclaration -import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference import de.fraunhofer.aisec.cpg.graph.types.* import de.fraunhofer.aisec.cpg.helpers.Benchmark import de.fraunhofer.aisec.cpg.helpers.SubgraphWalker @@ -70,9 +70,8 @@ class LLVMIRLanguageFrontend(language: Language, ctx: Tr /** * This contains a cache binding between an LLVMValueRef (representing a variable) and its * [Declaration] in the graph. We need this, because this way we can look up and connect a - * [DeclaredReferenceExpression] to its [Declaration] already in the language frontend. This in - * turn is needed because of the local/global system we cannot rely on the - * [VariableUsageResolver]. + * [Reference] to its [Declaration] already in the language frontend. This in turn is needed + * because of the local/global system we cannot rely on the [VariableUsageResolver]. */ var bindingsCache = mutableMapOf() diff --git a/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/StatementHandler.kt b/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/StatementHandler.kt index 93f6c86170..6383b95613 100644 --- a/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/StatementHandler.kt +++ b/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/StatementHandler.kt @@ -271,7 +271,7 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : val parent = frontend.getOperandValueAtIndex(instr, 0) - val compoundStatement = newCompoundStatement(nodeCode) + val compoundStatement = newBlock(nodeCode) val dummyCall = newCallExpression( @@ -484,10 +484,10 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : /** * Handles the ['alloca'](https://llvm.org/docs/LangRef.html#alloca-instruction) instruction, * which allocates a defined block of memory. The closest what we have in the graph is the - * [ArrayCreationExpression], which creates a fixed sized array, i.e., a block of memory. + * [NewArrayExpression], which creates a fixed sized array, i.e., a block of memory. */ private fun handleAlloca(instr: LLVMValueRef): Statement { - val array = newArrayCreationExpression(frontend.codeOf(instr)) + val array = newNewArrayExpression(frontend.codeOf(instr)) array.type = frontend.typeOf(instr) @@ -643,7 +643,7 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : copy = declarationOrNot(operand, instr) if (copy is DeclarationStatement) { base = - newDeclaredReferenceExpression( + newReference( copy.singleDeclaration?.name?.localName, (copy.singleDeclaration as? VariableDeclaration)?.type ?: unknownType(), frontend.codeOf(instr) @@ -662,7 +662,7 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : } base = base.arguments[index] } else if (baseType is PointerType) { - val arrayExpr = newArraySubscriptionExpression("") + val arrayExpr = newSubscriptExpression("") arrayExpr.arrayExpression = base arrayExpr.name = Name(index.toString()) arrayExpr.subscriptExpression = operand @@ -706,7 +706,7 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : } } - val compoundStatement = newCompoundStatement(frontend.codeOf(instr)) + val compoundStatement = newBlock(frontend.codeOf(instr)) val assignment = newAssignExpression("=", listOf(base), listOf(valueToSet), frontend.codeOf(instr)) compoundStatement.addStatement(copy) @@ -792,19 +792,19 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : /** * Parses the [`cmpxchg`](https://llvm.org/docs/LangRef.html#cmpxchg-instruction) instruction. - * It returns a single [Statement] or a [CompoundStatement] if the value is assigned to another - * variable. Performs the following operation atomically: + * It returns a single [Statement] or a [Block] if the value is assigned to another variable. + * Performs the following operation atomically: * ``` * lhs = {*pointer, *pointer == cmp} // A struct of {T, i1} * if(*pointer == cmp) { *pointer = new } * ``` * - * Returns a [CompoundStatement] with those two instructions or, if `lhs` doesn't exist, only - * the if-then statement. + * Returns a [Block] with those two instructions or, if `lhs` doesn't exist, only the if-then + * statement. */ private fun handleAtomiccmpxchg(instr: LLVMValueRef): Statement { val instrStr = frontend.codeOf(instr) - val compoundStatement = newCompoundStatement(instrStr) + val compoundStatement = newBlock(instrStr) compoundStatement.name = Name("atomiccmpxchg") val ptr = frontend.getOperandValueAtIndex(instr, 0) val cmp = frontend.getOperandValueAtIndex(instr, 1) @@ -859,7 +859,7 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : /** * Parses the `atomicrmw` instruction. It returns either a single [Statement] or a - * [CompoundStatement] if the value is assigned to another variable. + * [BlockStatement] if the value is assigned to another variable. */ private fun handleAtomicrmw(instr: LLVMValueRef): Statement { val lhs = LLVMGetValueName(instr).string @@ -982,7 +982,7 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : return if (lhs != "") { // set lhs = *ptr, then perform the replacement - val compoundStatement = newCompoundStatement(instrStr) + val compoundStatement = newBlock(instrStr) val ptrDerefAssignment = newUnaryOperator("*", false, true, instrStr) ptrDerefAssignment.input = frontend.getOperandValueAtIndex(instr, 0) @@ -1013,7 +1013,7 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : val switchStatement = newSwitchStatement(nodeCode) switchStatement.selector = address - val caseStatements = newCompoundStatement(nodeCode) + val caseStatements = newBlock(nodeCode) var idx = 1 while (idx < numOps) { @@ -1076,7 +1076,7 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : val switchStatement = newSwitchStatement(nodeCode) switchStatement.selector = operand - val caseStatements = newCompoundStatement(nodeCode) + val caseStatements = newBlock(nodeCode) var idx = 2 while (idx < numOps) { @@ -1139,11 +1139,7 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : } val callee = - newDeclaredReferenceExpression( - calledFuncName, - frontend.typeOf(calledFunc), - frontend.codeOf(calledFunc) - ) + newReference(calledFuncName, frontend.typeOf(calledFunc), frontend.codeOf(calledFunc)) val callExpr = newCallExpression(callee, calledFuncName, instrStr, false) @@ -1158,7 +1154,7 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : // contains a goto statement after the call. val tryStatement = newTryStatement(instrStr) frontend.scopeManager.enterScope(tryStatement) - val tryBlock = newCompoundStatement(instrStr) + val tryBlock = newBlock(instrStr) tryBlock.addStatement(declarationOrNot(callExpr, instr)) tryBlock.addStatement(tryContinue) tryStatement.tryBlock = tryBlock @@ -1175,9 +1171,9 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : instr ) - val catchCompoundStatement = newCompoundStatement(instrStr) - catchCompoundStatement.addStatement(gotoCatch) - catchClause.body = catchCompoundStatement + val catchBlockStatement = newBlock(instrStr) + catchBlockStatement.addStatement(gotoCatch) + catchClause.body = catchBlockStatement tryStatement.catchClauses = mutableListOf(catchClause) return tryStatement @@ -1240,16 +1236,16 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : */ private fun handleInsertelement(instr: LLVMValueRef): Statement { val instrStr = frontend.codeOf(instr) - val compoundStatement = newCompoundStatement(instrStr) + val compoundStatement = newBlock(instrStr) // TODO: Probably we should make a proper copy of the array val newArrayDecl = declarationOrNot(frontend.getOperandValueAtIndex(instr, 0), instr) compoundStatement.addStatement(newArrayDecl) val decl = newArrayDecl.declarations[0] as? VariableDeclaration - val arrayExpr = newArraySubscriptionExpression(instrStr) + val arrayExpr = newSubscriptExpression(instrStr) arrayExpr.arrayExpression = - newDeclaredReferenceExpression( + newReference( decl?.name?.toString() ?: Node.EMPTY_NAME, decl?.type ?: unknownType(), instrStr @@ -1273,7 +1269,7 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : * instruction which is modeled as access to an array at a given index. */ private fun handleExtractelement(instr: LLVMValueRef): Statement { - val arrayExpr = newArraySubscriptionExpression(frontend.codeOf(instr)) + val arrayExpr = newSubscriptExpression(frontend.codeOf(instr)) arrayExpr.arrayExpression = frontend.getOperandValueAtIndex(instr, 0) arrayExpr.subscriptExpression = frontend.getOperandValueAtIndex(instr, 1) @@ -1330,7 +1326,7 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : } else if (array1 is Literal<*> && array1.value == null) { initializers += newLiteral(null, elementType, instrStr) } else { - val arrayExpr = newArraySubscriptionExpression(instrStr) + val arrayExpr = newSubscriptExpression(instrStr) arrayExpr.arrayExpression = frontend.getOperandValueAtIndex(instr, 0) arrayExpr.subscriptExpression = newLiteral(idxInt, primitiveType("i32"), instrStr) @@ -1342,7 +1338,7 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : } else if (array2 is Literal<*> && array2.value == null) { initializers += newLiteral(null, elementType, instrStr) } else { - val arrayExpr = newArraySubscriptionExpression(instrStr) + val arrayExpr = newSubscriptExpression(instrStr) arrayExpr.arrayExpression = frontend.getOperandValueAtIndex(instr, 1) arrayExpr.subscriptExpression = newLiteral(idxInt - array1Length, primitiveType("i32"), instrStr) @@ -1393,7 +1389,7 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : if (labelMap.keys.size == 1) { // We only have a single pair, so we insert a declaration in that one BB. val (key, value) = labelMap.entries.elementAt(0) - val basicBlock = key.subStatement as? CompoundStatement + val basicBlock = key.subStatement as? Block val decl = declarationOrNot(value, instr) flatAST.addAll(SubgraphWalker.flattenAST(decl)) val mutableStatements = basicBlock?.statements?.toMutableList() @@ -1418,7 +1414,7 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : throw TranslationException("Wrong number of functions for phi statement.") } // Create the dummy declaration at the beginning of the function body - val firstBB = (functions[0] as FunctionDeclaration).body as CompoundStatement + val firstBB = (functions[0] as FunctionDeclaration).body as Block val varName = instr.name val type = frontend.typeOf(instr) val code = frontend.codeOf(instr) @@ -1441,17 +1437,12 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : for ((l, r) in labelMap) { // Now, we iterate over all the basic blocks and add an assign statement. val assignment = - newAssignExpression( - "=", - listOf(newDeclaredReferenceExpression(varName, type, code)), - listOf(r), - code - ) - (assignment.lhs.first() as DeclaredReferenceExpression).type = type - (assignment.lhs.first() as DeclaredReferenceExpression).refersTo = declaration + newAssignExpression("=", listOf(newReference(varName, type, code)), listOf(r), code) + (assignment.lhs.first() as Reference).type = type + (assignment.lhs.first() as Reference).refersTo = declaration flatAST.add(assignment) - val basicBlock = l.subStatement as? CompoundStatement + val basicBlock = l.subStatement as? Block val mutableStatements = basicBlock?.statements?.toMutableList() mutableStatements?.add(basicBlock.statements.size - 1, assignment) if (mutableStatements != null) { @@ -1498,11 +1489,11 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : } /** - * Handles a basic block and returns a [CompoundStatement] comprised of the statements of this + * Handles a basic block and returns a [BlockStatement] comprised of the statements of this * block or a [LabelStatement] if the basic block has a label. */ private fun handleBasicBlock(bb: LLVMBasicBlockRef): Statement { - val compound = newCompoundStatement("") + val compound = newBlock("") var instr = LLVMGetFirstInstruction(bb) while (instr != null) { @@ -1682,10 +1673,10 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : } /** - * This functions creates a new [DeclaredReferenceExpression] to an internal LLVM function. This - * would allow us to handle them all in the same way. + * This functions creates a new [Reference] to an internal LLVM function. This would allow us to + * handle them all in the same way. */ - private fun llvmInternalRef(name: String): DeclaredReferenceExpression { - return newDeclaredReferenceExpression(name) + private fun llvmInternalRef(name: String): Reference { + return newReference(name) } } diff --git a/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/CompressLLVMPass.kt b/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/CompressLLVMPass.kt index e15b3f5bac..b74660fbf5 100644 --- a/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/CompressLLVMPass.kt +++ b/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/CompressLLVMPass.kt @@ -29,6 +29,7 @@ import de.fraunhofer.aisec.cpg.TranslationContext import de.fraunhofer.aisec.cpg.frontends.llvm.LLVMIRLanguageFrontend import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.statements.* +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block import de.fraunhofer.aisec.cpg.graph.statements.expressions.ProblemExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.UnaryOperator import de.fraunhofer.aisec.cpg.graph.types.UnknownType @@ -57,7 +58,7 @@ class CompressLLVMPass(ctx: TranslationContext) : ComponentPass(ctx) { // prevents to treat the final goto in the case or default statement as a normal // compound // statement which would lead to inlining the instructions BB but we want to keep the BB - // inside a CompoundStatement. + // inside a Block. for (node in flatAST.sortedBy { n -> when (n) { @@ -96,7 +97,7 @@ class CompressLLVMPass(ctx: TranslationContext) : ComponentPass(ctx) { } else if (node is SwitchStatement) { // Iterate over all statements in a body of the switch/case and replace a goto // statement if it is the only one jumping to the target - val caseBodyStatements = node.statement as CompoundStatement + val caseBodyStatements = node.statement as Block val newStatements = caseBodyStatements.statements.toMutableList() for (i in 0 until newStatements.size) { val subStatement = @@ -108,7 +109,7 @@ class CompressLLVMPass(ctx: TranslationContext) : ComponentPass(ctx) { subStatement?.let { newStatements[i] = it } } } - (node.statement as CompoundStatement).statements = newStatements + (node.statement as Block).statements = newStatements } else if ( node is TryStatement && node.catchClauses.size == 1 && @@ -137,22 +138,21 @@ class CompressLLVMPass(ctx: TranslationContext) : ComponentPass(ctx) { } else if ( node is TryStatement && node.catchClauses.size == 1 && - node.catchClauses[0].body?.statements?.get(0) is CompoundStatement + node.catchClauses[0].body?.statements?.get(0) is Block ) { // A compound statement which is wrapped in the catchClause. We can simply move // it // one layer up and make // the compound statement the body of the catch clause. - val innerCompound = - node.catchClauses[0].body?.statements?.get(0) as? CompoundStatement + val innerCompound = node.catchClauses[0].body?.statements?.get(0) as? Block innerCompound?.statements?.let { node.catchClauses[0].body?.statements = it } fixThrowStatementsForCatch(node.catchClauses[0]) } else if (node is TryStatement && node.catchClauses.isNotEmpty()) { for (catch in node.catchClauses) { fixThrowStatementsForCatch(catch) } - } else if (node is CompoundStatement) { - // Get the last statement in a CompoundStatement and replace a goto statement + } else if (node is Block) { + // Get the last statement in a Block and replace a goto statement // iff it is the only one jumping to the target val goto = node.statements.lastOrNull() if ( @@ -165,7 +165,7 @@ class CompressLLVMPass(ctx: TranslationContext) : ComponentPass(ctx) { ) { val subStatement = goto.targetLabel?.subStatement val newStatements = node.statements.dropLast(1).toMutableList() - newStatements.addAll((subStatement as CompoundStatement).statements) + newStatements.addAll((subStatement as Block).statements) node.statements = newStatements } } @@ -196,7 +196,7 @@ class CompressLLVMPass(ctx: TranslationContext) : ComponentPass(ctx) { catch.parameter = error } val exceptionReference = - catch.newDeclaredReferenceExpression( + catch.newReference( catch.parameter?.name, catch.parameter?.type ?: UnknownType.getUnknownType(catch.language), "" diff --git a/cpg-language-llvm/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/LLVMIRLanguageFrontendTest.kt b/cpg-language-llvm/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/LLVMIRLanguageFrontendTest.kt index 97710bb3a0..1c1f7ce344 100644 --- a/cpg-language-llvm/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/LLVMIRLanguageFrontendTest.kt +++ b/cpg-language-llvm/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/LLVMIRLanguageFrontendTest.kt @@ -73,11 +73,11 @@ class LLVMIRLanguageFrontendTest { assertLocalName("i32", main.type) val xVector = - (main.bodyOrNull(0)?.statements?.get(0) as? DeclarationStatement) + (main.bodyOrNull(0)?.statements?.get(0) as? DeclarationStatement) ?.singleDeclaration as? VariableDeclaration val xInit = xVector?.initializer as? InitializerListExpression assertNotNull(xInit) - assertLocalName("poison", xInit.initializers[0] as? DeclaredReferenceExpression) + assertLocalName("poison", xInit.initializers[0] as? Reference) assertEquals(0L, (xInit.initializers[1] as? Literal<*>)?.value) assertEquals(0L, (xInit.initializers[2] as? Literal<*>)?.value) assertEquals(0L, (xInit.initializers[3] as? Literal<*>)?.value) @@ -184,7 +184,7 @@ class LLVMIRLanguageFrontendTest { assertNotNull(unary) assertEquals("&", unary.operatorCode) - var arrayExpr = unary.input as? ArraySubscriptionExpression + var arrayExpr = unary.input as? SubscriptExpression assertNotNull(arrayExpr) assertLocalName("13", arrayExpr) assertEquals( @@ -192,7 +192,7 @@ class LLVMIRLanguageFrontendTest { (arrayExpr.subscriptExpression as? Literal<*>)?.value ) // should this be integer instead of long? - arrayExpr = arrayExpr.arrayExpression as? ArraySubscriptionExpression + arrayExpr = arrayExpr.arrayExpression as? SubscriptExpression assertNotNull(arrayExpr) assertLocalName("5", arrayExpr) assertEquals( @@ -200,15 +200,15 @@ class LLVMIRLanguageFrontendTest { (arrayExpr.subscriptExpression as? Literal<*>)?.value ) // should this be integer instead of long? - var memberExpr = arrayExpr.arrayExpression as? MemberExpression - assertNotNull(memberExpr) - assertLocalName("field_1", memberExpr) + var memberExpression = arrayExpr.arrayExpression as? MemberExpression + assertNotNull(memberExpression) + assertLocalName("field_1", memberExpression) - memberExpr = memberExpr.base as? MemberExpression - assertNotNull(memberExpr) - assertLocalName("field_2", memberExpr) + memberExpression = memberExpression.base as? MemberExpression + assertNotNull(memberExpression) + assertLocalName("field_2", memberExpression) - arrayExpr = memberExpr.base as? ArraySubscriptionExpression + arrayExpr = memberExpression.base as? SubscriptExpression assertNotNull(arrayExpr) assertLocalName("1", arrayExpr) assertEquals( @@ -216,7 +216,7 @@ class LLVMIRLanguageFrontendTest { (arrayExpr.subscriptExpression as? Literal<*>)?.value ) // should this be integer instead of long? - val ref = arrayExpr.arrayExpression as? DeclaredReferenceExpression + val ref = arrayExpr.arrayExpression as? Reference assertNotNull(ref) assertLocalName("s", ref) assertSame(s, ref.refersTo) @@ -240,17 +240,17 @@ class LLVMIRLanguageFrontendTest { val onzeroLabel = main.bodyOrNull(0) assertNotNull(onzeroLabel) assertLocalName("onzero", onzeroLabel) - assertTrue(onzeroLabel.subStatement is CompoundStatement) + assertTrue(onzeroLabel.subStatement is Block) val ononeLabel = main.bodyOrNull(1) assertNotNull(ononeLabel) assertLocalName("onone", ononeLabel) - assertTrue(ononeLabel.subStatement is CompoundStatement) + assertTrue(ononeLabel.subStatement is Block) val defaultLabel = main.bodyOrNull(2) assertNotNull(defaultLabel) assertLocalName("otherwise", defaultLabel) - assertTrue(defaultLabel.subStatement is CompoundStatement) + assertTrue(defaultLabel.subStatement is Block) // Check that the type of %a is i32 val xorStatement = main.bodyOrNull(3) @@ -265,9 +265,9 @@ class LLVMIRLanguageFrontendTest { assertNotNull(switchStatement) // Check that we have switch(a) - assertSame(a, (switchStatement.selector as DeclaredReferenceExpression).refersTo) + assertSame(a, (switchStatement.selector as Reference).refersTo) - val cases = switchStatement.statement as CompoundStatement + val cases = switchStatement.statement as Block // Check that the first case is case 0 -> goto onzero and that the BB is inlined val case1 = cases.statements[0] as CaseStatement assertEquals(0L, (case1.caseExpression as Literal<*>).value as Long) @@ -307,10 +307,10 @@ class LLVMIRLanguageFrontendTest { val comparison = variableDecl.initializer as BinaryOperator assertEquals("==", comparison.operatorCode) val rhs = (comparison.rhs as Literal<*>) - val lhs = (comparison.lhs as DeclaredReferenceExpression).refersTo as VariableDeclaration + val lhs = (comparison.lhs as Reference).refersTo as VariableDeclaration assertEquals(10L, (rhs.value as Long)) assertEquals(tu.primitiveType("i32"), rhs.type) - assertLocalName("x", comparison.lhs as DeclaredReferenceExpression) + assertLocalName("x", comparison.lhs as Reference) assertLocalName("x", lhs) assertEquals(tu.primitiveType("i32"), lhs.type) @@ -318,15 +318,14 @@ class LLVMIRLanguageFrontendTest { val ifStatement = main.bodyOrNull(0) assertNotNull(ifStatement) assertEquals("IfUnequal", (ifStatement.elseStatement!! as GotoStatement).labelName) - val ifBranch = (ifStatement.thenStatement as CompoundStatement) + val ifBranch = (ifStatement.thenStatement as Block) // Check that the condition is set correctly val ifCondition = ifStatement.condition - assertSame(variableDecl, (ifCondition as DeclaredReferenceExpression).refersTo) + assertSame(variableDecl, (ifCondition as Reference).refersTo) val elseBranch = - (ifStatement.elseStatement!! as GotoStatement).targetLabel?.subStatement - as CompoundStatement + (ifStatement.elseStatement!! as GotoStatement).targetLabel?.subStatement as Block assertEquals(2, elseBranch.statements.size) assertEquals(" %y = mul i32 %x, 32768", elseBranch.statements[0].code) assertEquals(" ret i32 %y", elseBranch.statements[1].code) @@ -349,14 +348,14 @@ class LLVMIRLanguageFrontendTest { assertEquals(tu.objectType("ui32"), ifBranchCompLhs.castType) assertEquals(tu.objectType("ui32"), ifBranchCompLhs.type) - val declRefExpr = ifBranchCompLhs.expression as DeclaredReferenceExpression + val declRefExpr = ifBranchCompLhs.expression as Reference assertEquals(-3, ((ifBranchCompRhs.expression as Literal<*>).value as Long)) assertLocalName("x", declRefExpr) // TODO: declRefExpr.refersTo is null. Is that expected/intended? val ifBranchSecondStatement = ifBranch.statements[1] as? IfStatement assertNotNull(ifBranchSecondStatement) - val ifRet = ifBranchSecondStatement.thenStatement as? CompoundStatement + val ifRet = ifBranchSecondStatement.thenStatement as? Block assertNotNull(ifRet) assertEquals(1, ifRet.statements.size) assertEquals(" ret i32 1", ifRet.statements[0].code) @@ -377,7 +376,7 @@ class LLVMIRLanguageFrontendTest { val foo = tu.byNameOrNull("foo") assertNotNull(foo) - val atomicrmwStatement = foo.bodyOrNull() + val atomicrmwStatement = foo.bodyOrNull() assertNotNull(atomicrmwStatement) // Check that the value is assigned to @@ -417,7 +416,7 @@ class LLVMIRLanguageFrontendTest { val foo = tu.byNameOrNull("foo") assertNotNull(foo) - val cmpxchgStatement = foo.bodyOrNull(1) + val cmpxchgStatement = foo.bodyOrNull(1) assertNotNull(cmpxchgStatement) assertEquals(2, cmpxchgStatement.statements.size) @@ -453,8 +452,8 @@ class LLVMIRLanguageFrontendTest { assertEquals("=", thenExpr.operatorCode) assertEquals("*", (thenExpr.lhs.first() as UnaryOperator).operatorCode) assertLocalName("ptr", (thenExpr.lhs.first() as UnaryOperator).input) - assertLocalName("old", thenExpr.rhs.first() as DeclaredReferenceExpression) - assertLocalName("old", (thenExpr.rhs.first() as DeclaredReferenceExpression).refersTo) + assertLocalName("old", thenExpr.rhs.first() as Reference) + assertLocalName("old", (thenExpr.rhs.first() as Reference).refersTo) } @Test @@ -556,7 +555,7 @@ class LLVMIRLanguageFrontendTest { (loadXStatement.singleDeclaration as VariableDeclaration).initializer as UnaryOperator assertEquals("*", initXOp.operatorCode) - var ref = initXOp.input as? DeclaredReferenceExpression + var ref = initXOp.input as? Reference assertNotNull(ref) assertLocalName("x", ref) assertSame(globalX, ref.refersTo) @@ -568,7 +567,7 @@ class LLVMIRLanguageFrontendTest { (loadAStatement.singleDeclaration as VariableDeclaration).initializer as UnaryOperator assertEquals("*", initAOp.operatorCode) - ref = initAOp.input as? DeclaredReferenceExpression + ref = initAOp.input as? Reference assertNotNull(ref) assertLocalName("a", ref) assertSame(globalA, ref.refersTo) @@ -595,7 +594,7 @@ class LLVMIRLanguageFrontendTest { val ptr = main.bodyOrNull()?.singleDeclaration as? VariableDeclaration assertNotNull(ptr) - val alloca = ptr.initializer as? ArrayCreationExpression + val alloca = ptr.initializer as? NewArrayExpression assertNotNull(alloca) assertEquals("i32*", alloca.type.typeName) @@ -609,7 +608,7 @@ class LLVMIRLanguageFrontendTest { assertNotNull(dereferencePtr) assertEquals("*", dereferencePtr.operatorCode) assertEquals("i32", dereferencePtr.type.typeName) - assertSame(ptr, (dereferencePtr.input as? DeclaredReferenceExpression)?.refersTo) + assertSame(ptr, (dereferencePtr.input as? Reference)?.refersTo) assertEquals(1, store.rhs.size) val value = store.rhs.first() as? Literal<*> @@ -651,7 +650,7 @@ class LLVMIRLanguageFrontendTest { assertEquals(100L, (args[0] as Literal<*>).value as Long) assertNull((args[1] as Literal<*>).value) - val compoundStatement = foo.bodyOrNull() + val compoundStatement = foo.bodyOrNull() assertNotNull(compoundStatement) // First copy a to b val copyStatement = @@ -688,7 +687,7 @@ class LLVMIRLanguageFrontendTest { val main = tu.byNameOrNull("main") assertNotNull(main) - val mainBody = main.body as CompoundStatement + val mainBody = main.body as Block val tryStatement = mainBody.statements[0] as? TryStatement assertNotNull(tryStatement) @@ -719,10 +718,10 @@ class LLVMIRLanguageFrontendTest { assertLocalName("_ZTIi | ...", tryStatement.catchClauses[0]) val ifStatement = tryStatement.catchClauses[0].body?.statements?.get(4) as? IfStatement assertNotNull(ifStatement) - assertTrue(ifStatement.thenStatement is CompoundStatement) - assertEquals(4, (ifStatement.thenStatement as CompoundStatement).statements.size) - assertTrue(ifStatement.elseStatement is CompoundStatement) - assertEquals(1, (ifStatement.elseStatement as CompoundStatement).statements.size) + assertTrue(ifStatement.thenStatement is Block) + assertEquals(4, (ifStatement.thenStatement as Block).statements.size) + assertTrue(ifStatement.elseStatement is Block) + assertEquals(1, (ifStatement.elseStatement as Block).statements.size) } @Test @@ -754,7 +753,7 @@ class LLVMIRLanguageFrontendTest { val main = tu.byNameOrNull("main") assertNotNull(main) - val mainBody = main.body as CompoundStatement + val mainBody = main.body as Block val yDecl = (mainBody.statements[0] as DeclarationStatement).singleDeclaration as VariableDeclaration @@ -763,7 +762,7 @@ class LLVMIRLanguageFrontendTest { val ifStatement = mainBody.statements[3] as? IfStatement assertNotNull(ifStatement) - val thenStmt = ifStatement.thenStatement as? CompoundStatement + val thenStmt = ifStatement.thenStatement as? Block assertNotNull(thenStmt) assertEquals(3, thenStmt.statements.size) assertNotNull(thenStmt.statements[1] as? AssignExpression) @@ -773,10 +772,10 @@ class LLVMIRLanguageFrontendTest { val thenY = thenStmt.statements[1] as AssignExpression assertEquals(1, thenY.lhs.size) assertEquals(1, thenY.rhs.size) - assertSame(aDecl, (thenY.rhs.first() as DeclaredReferenceExpression).refersTo) - assertSame(yDecl, (thenY.lhs.first() as DeclaredReferenceExpression).refersTo) + assertSame(aDecl, (thenY.rhs.first() as Reference).refersTo) + assertSame(yDecl, (thenY.lhs.first() as Reference).refersTo) - val elseStmt = ifStatement.elseStatement as? CompoundStatement + val elseStmt = ifStatement.elseStatement as? Block assertNotNull(elseStmt) assertEquals(3, elseStmt.statements.size) val bDecl = @@ -786,18 +785,15 @@ class LLVMIRLanguageFrontendTest { val elseY = elseStmt.statements[1] as AssignExpression assertEquals(1, elseY.lhs.size) assertEquals(1, elseY.lhs.size) - assertSame(bDecl, (elseY.rhs.first() as DeclaredReferenceExpression).refersTo) - assertSame(yDecl, (elseY.lhs.first() as DeclaredReferenceExpression).refersTo) + assertSame(bDecl, (elseY.rhs.first() as Reference).refersTo) + assertSame(yDecl, (elseY.lhs.first() as Reference).refersTo) val continueBlock = - (thenStmt.statements[2] as? GotoStatement)?.targetLabel?.subStatement - as? CompoundStatement + (thenStmt.statements[2] as? GotoStatement)?.targetLabel?.subStatement as? Block assertNotNull(continueBlock) assertEquals( yDecl, - ((continueBlock.statements[1] as ReturnStatement).returnValue - as DeclaredReferenceExpression) - .refersTo + ((continueBlock.statements[1] as ReturnStatement).returnValue as Reference).refersTo ) } @@ -816,7 +812,7 @@ class LLVMIRLanguageFrontendTest { assertNotNull(main) // Test that x is initialized correctly - val mainBody = main.body as CompoundStatement + val mainBody = main.body as Block val origX = ((mainBody.statements[0] as? DeclarationStatement)?.singleDeclaration as? VariableDeclaration) @@ -842,35 +838,31 @@ class LLVMIRLanguageFrontendTest { val zInit = ((mainBody.statements[2] as? DeclarationStatement)?.singleDeclaration as? VariableDeclaration) - ?.initializer as? ArraySubscriptionExpression + ?.initializer as? SubscriptExpression assertNotNull(zInit) assertEquals(0L, (zInit.subscriptExpression as? Literal<*>)?.value) - assertEquals("x", (zInit.arrayExpression as? DeclaredReferenceExpression)?.name?.localName) - assertSame(origX, (zInit.arrayExpression as? DeclaredReferenceExpression)?.refersTo) + assertEquals("x", (zInit.arrayExpression as? Reference)?.name?.localName) + assertSame(origX, (zInit.arrayExpression as? Reference)?.refersTo) // Test the assignment of y to yMod val yModInit = - ((mainBody.statements[3] as CompoundStatement).statements[0] as? DeclarationStatement) + ((mainBody.statements[3] as Block).statements[0] as? DeclarationStatement) ?.singleDeclaration as? VariableDeclaration assertNotNull(yModInit) - assertEquals("y", (yModInit.initializer as? DeclaredReferenceExpression)?.name?.localName) - assertSame(origY, (yModInit.initializer as? DeclaredReferenceExpression)?.refersTo) + assertEquals("y", (yModInit.initializer as? Reference)?.name?.localName) + assertSame(origY, (yModInit.initializer as? Reference)?.refersTo) // Now, test the modification of yMod[3] = 8 - val yMod = - ((mainBody.statements[3] as CompoundStatement).statements[1] as? AssignExpression) + val yMod = ((mainBody.statements[3] as Block).statements[1] as? AssignExpression) assertNotNull(yMod) assertEquals(1, yMod.lhs.size) assertEquals(1, yMod.rhs.size) assertEquals( 3L, - ((yMod.lhs.first() as? ArraySubscriptionExpression)?.subscriptExpression as? Literal<*>) - ?.value + ((yMod.lhs.first() as? SubscriptExpression)?.subscriptExpression as? Literal<*>)?.value ) assertSame( yModInit, - ((yMod.lhs.first() as? ArraySubscriptionExpression)?.arrayExpression - as? DeclaredReferenceExpression) - ?.refersTo + ((yMod.lhs.first() as? SubscriptExpression)?.arrayExpression as? Reference)?.refersTo ) assertEquals(8L, (yMod.rhs.first() as? Literal<*>)?.value) @@ -882,37 +874,34 @@ class LLVMIRLanguageFrontendTest { assertNotNull(shuffledInit) assertSame( origX, - ((shuffledInit.initializers[0] as? ArraySubscriptionExpression)?.arrayExpression - as? DeclaredReferenceExpression) + ((shuffledInit.initializers[0] as? SubscriptExpression)?.arrayExpression as? Reference) ?.refersTo ) assertSame( yModInit, - ((shuffledInit.initializers[1] as? ArraySubscriptionExpression)?.arrayExpression - as? DeclaredReferenceExpression) + ((shuffledInit.initializers[1] as? SubscriptExpression)?.arrayExpression as? Reference) ?.refersTo ) assertSame( yModInit, - ((shuffledInit.initializers[2] as? ArraySubscriptionExpression)?.arrayExpression - as? DeclaredReferenceExpression) + ((shuffledInit.initializers[2] as? SubscriptExpression)?.arrayExpression as? Reference) ?.refersTo ) assertSame( 1, - ((shuffledInit.initializers[0] as? ArraySubscriptionExpression)?.subscriptExpression + ((shuffledInit.initializers[0] as? SubscriptExpression)?.subscriptExpression as? Literal<*>) ?.value ) assertSame( 2, - ((shuffledInit.initializers[1] as? ArraySubscriptionExpression)?.subscriptExpression + ((shuffledInit.initializers[1] as? SubscriptExpression)?.subscriptExpression as? Literal<*>) ?.value ) assertSame( 3, - ((shuffledInit.initializers[2] as? ArraySubscriptionExpression)?.subscriptExpression + ((shuffledInit.initializers[2] as? SubscriptExpression)?.subscriptExpression as? Literal<*>) ?.value ) @@ -933,7 +922,7 @@ class LLVMIRLanguageFrontendTest { assertNotNull(main) // Test that x is initialized correctly - val mainBody = main.body as CompoundStatement + val mainBody = main.body as Block val fenceCall = mainBody.statements[0] as? CallExpression assertNotNull(fenceCall) @@ -964,7 +953,7 @@ class LLVMIRLanguageFrontendTest { assertNotNull(funcF) val tryStatement = - (funcF.bodyOrNull(0)?.subStatement as? CompoundStatement) + (funcF.bodyOrNull(0)?.subStatement as? Block) ?.statements ?.firstOrNull { s -> s is TryStatement } as? TryStatement assertNotNull(tryStatement) @@ -997,13 +986,13 @@ class LLVMIRLanguageFrontendTest { assertFullName("llvm.matchesCatchpad", matchesExceptionCall) assertEquals( catchSwitchExpr.singleDeclaration, - (matchesExceptionCall.arguments[0] as DeclaredReferenceExpression).refersTo + (matchesExceptionCall.arguments[0] as Reference).refersTo ) assertEquals(null, (matchesExceptionCall.arguments[1] as Literal<*>).value) assertEquals(64L, (matchesExceptionCall.arguments[2] as Literal<*>).value as Long) assertEquals(null, (matchesExceptionCall.arguments[3] as Literal<*>).value) - val catchBlock = ifExceptionMatches.thenStatement as? CompoundStatement + val catchBlock = ifExceptionMatches.thenStatement as? Block assertNotNull(catchBlock) assertFullName( "llvm.catchpad", @@ -1025,7 +1014,7 @@ class LLVMIRLanguageFrontendTest { val innerCatchClause = (innerTry.catchClauses[0].body?.statements?.get(1) as? IfStatement)?.thenStatement - as? CompoundStatement + as? Block assertNotNull(innerCatchClause) assertFullName( "llvm.catchpad", @@ -1042,7 +1031,7 @@ class LLVMIRLanguageFrontendTest { assertNotNull(innerCatchThrows.input) assertSame( innerTry.catchClauses[0].parameter, - (innerCatchThrows.input as? DeclaredReferenceExpression)?.refersTo + (innerCatchThrows.input as? Reference)?.refersTo ) } diff --git a/cpg-language-python/src/main/python/CPGPython/__init__.py b/cpg-language-python/src/main/python/CPGPython/__init__.py index 49d84d2bf8..6d40445fc3 100644 --- a/cpg-language-python/src/main/python/CPGPython/__init__.py +++ b/cpg-language-python/src/main/python/CPGPython/__init__.py @@ -65,7 +65,7 @@ def __init__(self, fname, frontend, code): from ._statements import handle_function_or_method from ._statements import handle_statement from ._statements import handle_statement_impl - from ._statements import make_compound_statement + from ._statements import make_block_statement def execute(self): if isinstance(self.rootNode, ast.Module): diff --git a/cpg-language-python/src/main/python/CPGPython/_expressions.py b/cpg-language-python/src/main/python/CPGPython/_expressions.py index b7ee1506a8..f4a31e8ab4 100644 --- a/cpg-language-python/src/main/python/CPGPython/_expressions.py +++ b/cpg-language-python/src/main/python/CPGPython/_expressions.py @@ -315,9 +315,9 @@ def handle_expression_impl(self, expr): if self.is_declaration(value): self.log_with_loc( ("Found a new declaration. " - "Wrapping it in a DeclaredReferenceExpression."), + "Wrapping it in a Reference."), loglevel="DEBUG") - value = ExpressionBuilderKt.newDeclaredReferenceExpression( + value = ExpressionBuilderKt.newReference( self.frontend, value.getName(), value.getType(), value.getCode()) mem = ExpressionBuilderKt.newMemberExpression( @@ -329,7 +329,7 @@ def handle_expression_impl(self, expr): elif isinstance(expr, ast.Subscript): value = self.handle_expression(expr.value) slc = self.handle_expression(expr.slice) - exp = ExpressionBuilderKt.newArraySubscriptionExpression( + exp = ExpressionBuilderKt.newSubscriptExpression( self.frontend, self.get_src_code(expr)) exp.setArrayExpression(value) exp.setSubscriptExpression(slc) @@ -339,7 +339,7 @@ def handle_expression_impl(self, expr): r = ExpressionBuilderKt.newExpression(self.frontend, "") return r elif isinstance(expr, ast.Name): - r = ExpressionBuilderKt.newDeclaredReferenceExpression( + r = ExpressionBuilderKt.newReference( self.frontend, expr.id, TypeBuilderKt.unknownType(self.frontend), self.get_src_code(expr)) diff --git a/cpg-language-python/src/main/python/CPGPython/_misc.py b/cpg-language-python/src/main/python/CPGPython/_misc.py index 23d6407ea2..af9224ec5a 100644 --- a/cpg-language-python/src/main/python/CPGPython/_misc.py +++ b/cpg-language-python/src/main/python/CPGPython/_misc.py @@ -106,7 +106,7 @@ def is_variable_declaration(self, target): def is_declared_reference(self, target): - n = CPG_JAVA + ".graph.statements.expressions.DeclaredReferenceExpression" + n = CPG_JAVA + ".graph.statements.expressions.Reference" return target is not None and target.java_name == n diff --git a/cpg-language-python/src/main/python/CPGPython/_statements.py b/cpg-language-python/src/main/python/CPGPython/_statements.py index 40f7b98a48..dd13767b34 100644 --- a/cpg-language-python/src/main/python/CPGPython/_statements.py +++ b/cpg-language-python/src/main/python/CPGPython/_statements.py @@ -29,7 +29,7 @@ from de.fraunhofer.aisec.cpg.graph import TypeBuilderKt from de.fraunhofer.aisec.cpg.graph import StatementBuilderKt from de.fraunhofer.aisec.cpg.graph import ExpressionBuilderKt -from de.fraunhofer.aisec.cpg.graph.statements import CompoundStatement +from de.fraunhofer.aisec.cpg.graph.statements.expressions import Block from de.fraunhofer.aisec.cpg.graph.types import UnknownType from java.util import ArrayList import ast @@ -117,7 +117,7 @@ def handle_statement_impl(self, stmt): whl_stmt.setConditionDeclaration(expr) else: whl_stmt.setCondition(expr) - body = self.make_compound_statement(stmt.body) + body = self.make_block_statement(stmt.body) whl_stmt.setStatement(body) if stmt.orelse is not None and len(stmt.orelse) != 0: self.log_with_loc( @@ -131,11 +131,11 @@ def handle_statement_impl(self, stmt): # Condition if_stmt.setCondition(self.handle_expression(stmt.test)) # Then - body = self.make_compound_statement(stmt.body) + body = self.make_block_statement(stmt.body) if_stmt.setThenStatement(body) # Else if stmt.orelse is not None and len(stmt.orelse) != 0: - orelse = self.make_compound_statement(stmt.orelse) + orelse = self.make_block_statement(stmt.orelse) if_stmt.setElseStatement(orelse) return if_stmt @@ -233,8 +233,8 @@ def handle_statement_impl(self, stmt): elif isinstance(stmt, ast.Try): s = StatementBuilderKt.newTryStatement(self.frontend, self.get_src_code(stmt)) - try_block = self.make_compound_statement(stmt.body) - finally_block = self.make_compound_statement(stmt.finalbody) + try_block = self.make_block_statement(stmt.body) + finally_block = self.make_block_statement(stmt.finalbody) if stmt.orelse is not None and len(stmt.orelse) != 0: self.log_with_loc(NOT_IMPLEMENTED_MSG, loglevel="ERROR") if len(stmt.handlers) != 0: @@ -337,7 +337,7 @@ def handle_function_or_method(self, node, record=None): loglevel="ERROR") if len(node.body) > 0: - f.setBody(self.make_compound_statement(node.body)) + f.setBody(self.make_block_statement(node.body)) annotations = [] for decorator in node.decorator_list: @@ -414,7 +414,7 @@ def handle_argument(self, arg: ast.arg): else: tpe = TypeBuilderKt.unknownType(self.frontend) # TODO variadic - pvd = DeclarationBuilderKt.newParamVariableDeclaration( + pvd = DeclarationBuilderKt.newParameterDeclaration( self.frontend, arg.arg, tpe, False, self.get_src_code(arg)) self.add_loc_info(arg, pvd) self.scopemanager.addDeclaration(pvd) @@ -455,7 +455,7 @@ def handle_for(self, stmt): for_stmt.setVariable(target) - body = self.make_compound_statement(stmt.body) + body = self.make_block_statement(stmt.body) for_stmt.setStatement(body) if stmt.orelse is not None and len(stmt.orelse) != 0: @@ -464,12 +464,12 @@ def handle_for(self, stmt): return for_stmt -def make_compound_statement(self, stmts) -> CompoundStatement: +def make_block_statement(self, stmts) -> Block: if stmts is None or len(stmts) == 0: self.log_with_loc( "Expected at least one statement. Returning a dummy.", loglevel="WARN") - return StatementBuilderKt.newCompoundStatement(self.frontend, "") + return StatementBuilderKt.newBlock(self.frontend, "") if False and len(stmts) == 1: """ TODO decide how to handle this... """ @@ -478,17 +478,17 @@ def make_compound_statement(self, stmts) -> CompoundStatement: s = self.wrap_declaration_to_stmt(s) return s else: - compound_statement = StatementBuilderKt.newCompoundStatement( + block_statement = ExpressionBuilderKt.newBlock( self.frontend, "") for s in stmts: s = self.handle_statement(s) if self.is_declaration(s): s = self.wrap_declaration_to_stmt(s) - compound_statement.addStatement(s) + block_statement.addStatement(s) if len(stmts) > 0: - self.add_mul_loc_infos(stmts[0], stmts[-1], compound_statement) + self.add_mul_loc_infos(stmts[0], stmts[-1], block_statement) - return compound_statement + return block_statement def handle_assign(self, stmt): @@ -541,7 +541,7 @@ def handle_assign_impl(self, stmt): if not self.is_declared_reference( lhs) and not self.is_member_expression(lhs): self.log_with_loc( - "Expected a DeclaredReferenceExpression or MemberExpression " + "Expected a Reference or MemberExpression " "but got \"%s\". Skipping." % lhs.java_name, loglevel="ERROR") r = ExpressionBuilderKt.newArrayList(self.frontend, @@ -576,7 +576,7 @@ class Foo: else: name = "DUMMY" self.log_with_loc( - "Expected a DeclaredReferenceExpression but got a " + "Expected a Reference but got a " "MemberExpression. Using a dummy.", loglevel="ERROR") diff --git a/cpg-language-python/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/python/PythonFrontendTest.kt b/cpg-language-python/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/python/PythonFrontendTest.kt index ec275da66d..2ca7c4fb66 100644 --- a/cpg-language-python/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/python/PythonFrontendTest.kt +++ b/cpg-language-python/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/python/PythonFrontendTest.kt @@ -129,7 +129,7 @@ class PythonFrontendTest : BaseTest() { assertNotNull(bar) assertEquals(2, bar.parameters.size) - var callExpression = (foo.body as? CompoundStatement)?.statements?.get(0) as? CallExpression + var callExpression = (foo.body as? Block)?.statements?.get(0) as? CallExpression assertNotNull(callExpression) assertLocalName("bar", callExpression) @@ -146,7 +146,7 @@ class PythonFrontendTest : BaseTest() { assertLocalName("bar", bar) - val compStmt = bar.body as? CompoundStatement + val compStmt = bar.body as? Block assertNotNull(compStmt) assertNotNull(compStmt.statements) @@ -161,7 +161,7 @@ class PythonFrontendTest : BaseTest() { assertEquals("bar(s) here: ", literal.value) assertEquals(tu.primitiveType("str"), literal.type) - val ref = callExpression.arguments[1] as? DeclaredReferenceExpression + val ref = callExpression.arguments[1] as? Reference assertNotNull(ref) assertLocalName("s", ref) @@ -211,7 +211,7 @@ class PythonFrontendTest : BaseTest() { val main = p.functions["foo"] assertNotNull(main) - val body = main.body as? CompoundStatement + val body = main.body as? Block assertNotNull(body) val sel = @@ -261,7 +261,7 @@ class PythonFrontendTest : BaseTest() { assertLocalName("someFunc", clsfunc) assertLocalName("foo", foo) - val body = foo.body as? CompoundStatement + val body = foo.body as? Block assertNotNull(body) assertNotNull(body.statements) assertEquals(2, body.statements.size) @@ -278,7 +278,7 @@ class PythonFrontendTest : BaseTest() { assertEquals(ctor, cls.constructors.first()) assertFullName("simple_class.SomeClass", c1.type) - assertEquals(c1, (s2.base as? DeclaredReferenceExpression)?.refersTo) + assertEquals(c1, (s2.base as? Reference)?.refersTo) assertEquals(1, s2.invokes.size) assertEquals(clsfunc, s2.invokes.first()) @@ -302,7 +302,7 @@ class PythonFrontendTest : BaseTest() { val main = p.functions["foo"] assertNotNull(main) - val body = (main.body as? CompoundStatement)?.statements?.get(0) as? DeclarationStatement + val body = (main.body as? Block)?.statements?.get(0) as? DeclarationStatement assertNotNull(body) val foo = body.singleDeclaration as? VariableDeclaration @@ -316,9 +316,9 @@ class PythonFrontendTest : BaseTest() { val ifCond = initializer.condition as? Literal<*> assertNotNull(ifCond) - val thenExpr = initializer.thenExpr as? Literal<*> + val thenExpr = initializer.thenExpression as? Literal<*> assertNotNull(thenExpr) - val elseExpr = initializer.elseExpr as? Literal<*> + val elseExpr = initializer.elseExpression as? Literal<*> assertNotNull(elseExpr) assertEquals(tu.primitiveType("bool"), ifCond.type) @@ -377,12 +377,11 @@ class PythonFrontendTest : BaseTest() { assertNotNull(methBar) assertLocalName("bar", methBar) - val barZ = (methBar.body as? CompoundStatement)?.statements?.get(0) as? MemberExpression + val barZ = (methBar.body as? Block)?.statements?.get(0) as? MemberExpression assertNotNull(barZ) assertEquals(fieldZ, barZ.refersTo) - val barBaz = - (methBar.body as? CompoundStatement)?.statements?.get(1) as? DeclarationStatement + val barBaz = (methBar.body as? Block)?.statements?.get(1) as? DeclarationStatement assertNotNull(barBaz) val barBazInner = barBaz.declarations[0] as? FieldDeclaration assertNotNull(barBazInner) @@ -437,15 +436,14 @@ class PythonFrontendTest : BaseTest() { // self.somevar = i val someVarDeclaration = - ((bar.body as? CompoundStatement)?.statements?.get(0) as? DeclarationStatement) + ((bar.body as? Block)?.statements?.get(0) as? DeclarationStatement) ?.declarations ?.first() as? FieldDeclaration assertNotNull(someVarDeclaration) assertLocalName("somevar", someVarDeclaration) - assertEquals(i, (someVarDeclaration.initializer as? DeclaredReferenceExpression)?.refersTo) + assertEquals(i, (someVarDeclaration.initializer as? Reference)?.refersTo) - val fooMemCall = - (foo.body as? CompoundStatement)?.statements?.get(0) as? MemberCallExpression + val fooMemCall = (foo.body as? Block)?.statements?.get(0) as? MemberCallExpression assertNotNull(fooMemCall) val mem = fooMemCall.callee as? MemberExpression @@ -491,10 +489,10 @@ class PythonFrontendTest : BaseTest() { assertNotNull(bar) assertLocalName("bar", bar) - assertEquals(2, (bar.body as? CompoundStatement)?.statements?.size) - val line1 = (bar.body as? CompoundStatement)?.statements?.get(0) as? DeclarationStatement + assertEquals(2, (bar.body as? Block)?.statements?.size) + val line1 = (bar.body as? Block)?.statements?.get(0) as? DeclarationStatement assertNotNull(line1) - val line2 = (bar.body as? CompoundStatement)?.statements?.get(1) as? MemberCallExpression + val line2 = (bar.body as? Block)?.statements?.get(1) as? MemberCallExpression assertNotNull(line2) assertEquals(1, line1.declarations.size) @@ -505,7 +503,7 @@ class PythonFrontendTest : BaseTest() { val initializer = fooDecl.initializer as? ConstructExpression assertEquals(fooCtor, initializer?.constructor) - assertEquals(fooDecl, (line2.base as? DeclaredReferenceExpression)?.refersTo) + assertEquals(fooDecl, (line2.base as? Reference)?.refersTo) assertEquals(foobar, line2.invokes[0]) } @@ -547,7 +545,7 @@ class PythonFrontendTest : BaseTest() { assertNotNull(countParam) assertLocalName("c", countParam) - val countStmt = (methCount.body as? CompoundStatement)?.statements?.get(0) as? IfStatement + val countStmt = (methCount.body as? Block)?.statements?.get(0) as? IfStatement assertNotNull(countStmt) val ifCond = countStmt.condition as? BinaryOperator @@ -555,18 +553,14 @@ class PythonFrontendTest : BaseTest() { val lhs = ifCond.lhs as? MemberCallExpression assertNotNull(lhs) - assertEquals(countParam, (lhs.base as? DeclaredReferenceExpression)?.refersTo) + assertEquals(countParam, (lhs.base as? Reference)?.refersTo) assertLocalName("inc", lhs) assertEquals(0, lhs.arguments.size) - val ifThen = - (countStmt.thenStatement as? CompoundStatement)?.statements?.get(0) as? CallExpression + val ifThen = (countStmt.thenStatement as? Block)?.statements?.get(0) as? CallExpression assertNotNull(ifThen) assertEquals(methCount, ifThen.invokes.first()) - assertEquals( - countParam, - (ifThen.arguments.first() as? DeclaredReferenceExpression)?.refersTo - ) + assertEquals(countParam, (ifThen.arguments.first() as? Reference)?.refersTo) assertNull(countStmt.elseStatement) // class c1(counter) @@ -590,7 +584,7 @@ class PythonFrontendTest : BaseTest() { assertLocalName("self", selfReceiver) assertEquals(0, meth.parameters.size) // self is receiver and not a parameter - val methBody = meth.body as? CompoundStatement + val methBody = meth.body as? Block assertNotNull(methBody) val assign = methBody.statements[0] as? AssignExpression @@ -601,20 +595,20 @@ class PythonFrontendTest : BaseTest() { assertEquals("=", assign.operatorCode) assertNotNull(assignLhs) assertNotNull(assignRhs) - assertEquals(selfReceiver, (assignLhs.base as? DeclaredReferenceExpression)?.refersTo) + assertEquals(selfReceiver, (assignLhs.base as? Reference)?.refersTo) assertEquals("+", assignRhs.operatorCode) val assignRhsLhs = assignRhs.lhs as? MemberExpression // the second "self.total" in "self.total = self.total + 1" assertNotNull(assignRhsLhs) - assertEquals(selfReceiver, (assignRhsLhs.base as? DeclaredReferenceExpression)?.refersTo) + assertEquals(selfReceiver, (assignRhsLhs.base as? Reference)?.refersTo) val r = methBody.statements[1] as? ReturnStatement assertNotNull(r) assertEquals( selfReceiver, - ((r.returnValue as? MemberExpression)?.base as? DeclaredReferenceExpression)?.refersTo + ((r.returnValue as? MemberExpression)?.base as? Reference)?.refersTo ) // TODO last line "count(c1())" @@ -661,15 +655,12 @@ class PythonFrontendTest : BaseTest() { assertNotNull(assignClsFieldOutsideFunc) assertEquals( classFieldNoInitializer, - (assignClsFieldOutsideFunc.lhs())?.refersTo - ) - assertEquals( - classFieldWithInit, - (assignClsFieldOutsideFunc.rhs())?.refersTo + (assignClsFieldOutsideFunc.lhs())?.refersTo ) + assertEquals(classFieldWithInit, (assignClsFieldOutsideFunc.rhs())?.refersTo) assertEquals("=", assignClsFieldOutsideFunc.operatorCode) - val barBody = methBar.body as? CompoundStatement + val barBody = methBar.body as? Block assertNotNull(barBody) // self.classFieldDeclaredInFunction = 456 @@ -693,27 +684,21 @@ class PythonFrontendTest : BaseTest() { val barStmt3 = barBody.statements[3] as? AssignExpression assertNotNull(barStmt3) assertEquals("=", barStmt3.operatorCode) - assertEquals( - classFieldNoInitializer, - (barStmt3.lhs())?.refersTo - ) + assertEquals(classFieldNoInitializer, (barStmt3.lhs())?.refersTo) assertEquals("shadowed", (barStmt3.rhs>())?.value) // classFieldWithInit = "shadowed" val barStmt4 = barBody.statements[4] as? AssignExpression assertNotNull(barStmt4) assertEquals("=", barStmt4.operatorCode) - assertEquals(classFieldWithInit, (barStmt4.lhs())?.refersTo) + assertEquals(classFieldWithInit, (barStmt4.lhs())?.refersTo) assertEquals("shadowed", (barStmt4.rhs>())?.value) // classFieldDeclaredInFunction = "shadowed" val barStmt5 = barBody.statements[5] as? AssignExpression assertNotNull(barStmt5) assertEquals("=", barStmt5.operatorCode) - assertEquals( - classFieldDeclaredInFunction, - (barStmt5.lhs())?.refersTo - ) + assertEquals(classFieldDeclaredInFunction, (barStmt5.lhs())?.refersTo) assertEquals("shadowed", (barStmt5.rhs>())?.value) /* TODO: @@ -775,13 +760,13 @@ class PythonFrontendTest : BaseTest() { val base = initializer.base as? MemberExpression assertNotNull(base) assertLocalName("baz", base) - val baseBase = base.base as? DeclaredReferenceExpression + val baseBase = base.base as? Reference assertNotNull(baseBase) assertLocalName("bar", baseBase) - val member = initializer.callee as? MemberExpression - assertNotNull(member) - assertLocalName("zzz", member) + val memberExpression = initializer.callee as? MemberExpression + assertNotNull(memberExpression) + assertLocalName("zzz", memberExpression) } @Test @@ -803,22 +788,22 @@ class PythonFrontendTest : BaseTest() { val main = p.functions["main"] assertNotNull(main) - val mainBody = (main as? FunctionDeclaration)?.body as? CompoundStatement + val mainBody = (main as? FunctionDeclaration)?.body as? Block assertNotNull(mainBody) val whlStmt = mainBody.statements[3] as? WhileStatement assertNotNull(whlStmt) - val whlBody = whlStmt.statement as? CompoundStatement + val whlBody = whlStmt.statement as? Block assertNotNull(whlBody) val xDeclaration = whlBody.statements[0] as? DeclarationStatement assertNotNull(xDeclaration) - val ifStmt = whlBody.statements[1] as? IfStatement - assertNotNull(ifStmt) + val ifStatement = whlBody.statements[1] as? IfStatement + assertNotNull(ifStatement) - val brk = ifStmt.elseStatement as? CompoundStatement + val brk = ifStatement.elseStatement as? Block assertNotNull(brk) brk.statements[0] as? BreakStatement } @@ -863,19 +848,19 @@ class PythonFrontendTest : BaseTest() { val forVariable = forStmt.variable as? InitializerListExpression assertNotNull(forVariable) assertEquals(3, forVariable.initializers.size) - val t1Decl = forVariable.initializers[0] as? DeclaredReferenceExpression - val t2Decl = forVariable.initializers[1] as? DeclaredReferenceExpression - val t3Decl = forVariable.initializers[2] as? DeclaredReferenceExpression + val t1Decl = forVariable.initializers[0] as? Reference + val t2Decl = forVariable.initializers[1] as? Reference + val t3Decl = forVariable.initializers[2] as? Reference assertNotNull(t1Decl) assertNotNull(t2Decl) assertNotNull(t3Decl) // TODO no refersTo - val iter = forStmt.iterable as? DeclaredReferenceExpression + val iter = forStmt.iterable as? Reference assertNotNull(iter) assertEquals(testDeclaration, iter.refersTo) - val forBody = forStmt.statement as? CompoundStatement + val forBody = forStmt.statement as? Block assertNotNull(forBody) assertEquals(1, forBody.statements.size) @@ -886,11 +871,11 @@ class PythonFrontendTest : BaseTest() { val printArg = forBodyStmt.arguments[0] as? MemberCallExpression assertNotNull(printArg) - val formatArgT1 = printArg.arguments[0] as? DeclaredReferenceExpression + val formatArgT1 = printArg.arguments[0] as? Reference assertNotNull(formatArgT1) - val formatArgT2 = printArg.arguments[1] as? DeclaredReferenceExpression + val formatArgT2 = printArg.arguments[1] as? Reference assertNotNull(formatArgT2) - val formatArgT3 = printArg.arguments[2] as? DeclaredReferenceExpression + val formatArgT3 = printArg.arguments[2] as? Reference assertNotNull(formatArgT3) // TODO check refersTo } @@ -911,18 +896,18 @@ class PythonFrontendTest : BaseTest() { val p = tu.namespaces["issue473"] assertNotNull(p) - val ifStmt = p.statements[0] as? IfStatement - assertNotNull(ifStmt) - val ifCond = ifStmt.condition as? BinaryOperator + val ifStatement = p.statements[0] as? IfStatement + assertNotNull(ifStatement) + val ifCond = ifStatement.condition as? BinaryOperator assertNotNull(ifCond) - val ifThen = ifStmt.thenStatement as? CompoundStatement + val ifThen = ifStatement.thenStatement as? Block assertNotNull(ifThen) - val ifElse = ifStmt.elseStatement as? CompoundStatement + val ifElse = ifStatement.elseStatement as? Block assertNotNull(ifElse) // sys.version_info.minor > 9 assertEquals(">", ifCond.operatorCode) - assertLocalName("minor", ifCond.lhs as? DeclaredReferenceExpression) + assertLocalName("minor", ifCond.lhs as? Reference) // phr = {"user_id": user_id} | content val phrDeclaration = @@ -978,7 +963,7 @@ class PythonFrontendTest : BaseTest() { assertEquals(1, literals.size) assertEquals("# comment start", literals.first().comment) - val params = commentedNodes.filterIsInstance() + val params = commentedNodes.filterIsInstance() assertEquals(2, params.size) assertEquals("# a parameter", params.first { it.name.localName == "i" }.comment) assertEquals("# another parameter", params.first { it.name.localName == "j" }.comment) @@ -987,7 +972,7 @@ class PythonFrontendTest : BaseTest() { assertEquals(1, variable.size) assertEquals("# A comment", variable.first().comment) - val block = commentedNodes.filterIsInstance() + val block = commentedNodes.filterIsInstance() assertEquals(1, block.size) assertEquals("# foo", block.first().comment) @@ -1036,7 +1021,7 @@ class PythonFrontendTest : BaseTest() { } assertNotNull(tu) - val namespace = tu.functions["forloop"]?.body as? CompoundStatement + val namespace = tu.functions["forloop"]?.body as? Block assertNotNull(namespace) val varDefinedBeforeLoop = namespace.variables["varDefinedBeforeLoop"] @@ -1072,7 +1057,7 @@ class PythonFrontendTest : BaseTest() { ) // dataflow from first loop to foo call - val loopVar = firstLoop.variable as? DeclaredReferenceExpression + val loopVar = firstLoop.variable as? Reference assertNotNull(loopVar) assert(fooCall.arguments.first().prevDFG.contains(loopVar)) diff --git a/cpg-language-typescript/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/typescript/DeclarationHandler.kt b/cpg-language-typescript/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/typescript/DeclarationHandler.kt index f928df4c2d..776b5bd213 100644 --- a/cpg-language-typescript/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/typescript/DeclarationHandler.kt +++ b/cpg-language-typescript/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/typescript/DeclarationHandler.kt @@ -111,7 +111,7 @@ class DeclarationHandler(lang: TypeScriptLanguageFrontend) : val name = this.frontend.getIdentifierName(node) val type = node.typeChildNode?.let { this.frontend.typeOf(it) } ?: unknownType() - return newParamVariableDeclaration(name, type, false, this.frontend.codeOf(node)) + return newParameterDeclaration(name, type, false, this.frontend.codeOf(node)) } fun handleSourceFile(node: TypeScriptNode): TranslationUnitDeclaration { diff --git a/cpg-language-typescript/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/typescript/ExpressionHandler.kt b/cpg-language-typescript/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/typescript/ExpressionHandler.kt index 9b50a431f7..30b5d64666 100644 --- a/cpg-language-typescript/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/typescript/ExpressionHandler.kt +++ b/cpg-language-typescript/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/typescript/ExpressionHandler.kt @@ -169,7 +169,7 @@ class ExpressionHandler(lang: TypeScriptLanguageFrontend) : private fun handleIdentifier(node: TypeScriptNode): Expression { val name = this.frontend.codeOf(node)?.trim() ?: "" - return newDeclaredReferenceExpression(name, unknownType(), this.frontend.codeOf(node)) + return newReference(name, unknownType(), this.frontend.codeOf(node)) } private fun handlePropertyAccessExpression(node: TypeScriptNode): Expression { @@ -190,17 +190,20 @@ class ExpressionHandler(lang: TypeScriptLanguageFrontend) : call = if (propertyAccess != null) { - val memberExpression = + val memberExpressionExpression = this.handle(propertyAccess) as? MemberExpression ?: return ProblemExpression("node is not a member expression") - newMemberCallExpression(memberExpression, code = this.frontend.codeOf(node)) + newMemberCallExpression( + memberExpressionExpression, + code = this.frontend.codeOf(node) + ) } else { // TODO: fqn - how? val fqn = this.frontend.getIdentifierName(node) // regular function call - val ref = newDeclaredReferenceExpression(fqn) + val ref = newReference(fqn) newCallExpression(ref, fqn, this.frontend.codeOf(node), false) } diff --git a/cpg-language-typescript/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/typescript/StatementHandler.kt b/cpg-language-typescript/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/typescript/StatementHandler.kt index 77ae321271..51c1edb9f6 100644 --- a/cpg-language-typescript/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/typescript/StatementHandler.kt +++ b/cpg-language-typescript/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/typescript/StatementHandler.kt @@ -26,13 +26,13 @@ package de.fraunhofer.aisec.cpg.frontends.typescript import de.fraunhofer.aisec.cpg.frontends.Handler -import de.fraunhofer.aisec.cpg.graph.newCompoundStatement +import de.fraunhofer.aisec.cpg.graph.newBlock import de.fraunhofer.aisec.cpg.graph.newDeclarationStatement import de.fraunhofer.aisec.cpg.graph.newReturnStatement -import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement import de.fraunhofer.aisec.cpg.graph.statements.DeclarationStatement import de.fraunhofer.aisec.cpg.graph.statements.ReturnStatement import de.fraunhofer.aisec.cpg.graph.statements.Statement +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression import de.fraunhofer.aisec.cpg.graph.statements.expressions.ProblemExpression @@ -81,8 +81,8 @@ class StatementHandler(lang: TypeScriptLanguageFrontend) : return returnStmt } - private fun handleBlock(node: TypeScriptNode): CompoundStatement { - val block = newCompoundStatement(this.frontend.codeOf(node)) + private fun handleBlock(node: TypeScriptNode): Block { + val block = newBlock(this.frontend.codeOf(node)) node.children?.forEach { this.handle(it)?.let { it1 -> block.addStatement(it1) } } diff --git a/cpg-language-typescript/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/typescript/TypescriptLanguageFrontendTest.kt b/cpg-language-typescript/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/typescript/TypescriptLanguageFrontendTest.kt index 5e465efe3f..e06ebbdb3b 100644 --- a/cpg-language-typescript/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/typescript/TypescriptLanguageFrontendTest.kt +++ b/cpg-language-typescript/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/typescript/TypescriptLanguageFrontendTest.kt @@ -133,11 +133,11 @@ class TypeScriptLanguageFrontendTest { tu.getDeclarationsByName("doJsx", FunctionDeclaration::class.java).iterator().next() assertNotNull(doJsx) - val returnStmt = doJsx.getBodyStatementAs(0, ReturnStatement::class.java) - assertNotNull(returnStmt) + val returnStatement = doJsx.getBodyStatementAs(0, ReturnStatement::class.java) + assertNotNull(returnStatement) // check the return statement for the TSX statements - val jsx = returnStmt.returnValue as? ExpressionList + val jsx = returnStatement.returnValue as? ExpressionList assertNotNull(jsx) val tag = jsx.expressions.firstOrNull() @@ -204,7 +204,7 @@ class TypeScriptLanguageFrontendTest { val fetch = chainedCall.base as? CallExpression assertNotNull(fetch) - val refArg = fetch.arguments.first() as? DeclaredReferenceExpression + val refArg = fetch.arguments.first() as? Reference assertNotNull(refArg) assertLocalName("apiUrl", refArg) @@ -218,7 +218,7 @@ class TypeScriptLanguageFrontendTest { var keyValue = objectArg.initializers.first() as? KeyValueExpression assertNotNull(keyValue) - assertLocalName("method", keyValue.key as? DeclaredReferenceExpression) + assertLocalName("method", keyValue.key as? Reference) assertEquals("POST", (keyValue.value as? Literal<*>)?.value) keyValue = objectArg.initializers.last() as? KeyValueExpression @@ -301,11 +301,11 @@ class TypeScriptLanguageFrontendTest { val render = usersComponent.methods["render"] assertNotNull(render) - val returnStmt = render.getBodyStatementAs(1, ReturnStatement::class.java) - assertNotNull(returnStmt) + val returnStatement = render.getBodyStatementAs(1, ReturnStatement::class.java) + assertNotNull(returnStatement) // check the return statement for the TSX statements - val jsx = returnStmt.returnValue as? ExpressionList + val jsx = returnStatement.returnValue as? ExpressionList assertNotNull(jsx) val tag = jsx.expressions.firstOrNull() diff --git a/docs/docs/CPG/specs/dfg.md b/docs/docs/CPG/specs/dfg.md index ea827917ce..e1bc885f9c 100755 --- a/docs/docs/CPG/specs/dfg.md +++ b/docs/docs/CPG/specs/dfg.md @@ -65,7 +65,7 @@ Interesting fields: ### Case 1: Normal assignment (`operatorCode: =`) The `rhs` flows to `lhs`. In some languages, it is possible to have an assignment in a subexpression (e.g. `a + (b=1)`). -For this reason, if the assignment's ast parent is not a `CompoundStatement` (i.e., a block of statements), we also add a DFG edge to the whole operator. +For this reason, if the assignment's ast parent is not a `Block` (i.e., a block of statements), we also add a DFG edge to the whole operator. If the `lhs` consists of multiple variables (or a tuple), we try to split up the `rhs` by the index. If we can't do this, the whole `rhs` flows to all variables in `lhs`. Scheme: @@ -87,7 +87,7 @@ flowchart LR ```mermaid flowchart LR A[assignment.rhs] -- DFG --> assignment.lhs; - subgraph S[If the ast parent is not a CompoundStatement] + subgraph S[If the ast parent is not a Block direction LR assignment.rhs -- DFG --> assignment; end @@ -140,7 +140,7 @@ Scheme: lhs -- DFG --> node; ``` -## ArrayCreationExpression +## NewArrayExpression Interesting fields: @@ -151,7 +151,7 @@ The `initializer` flows to the array creation expression. Scheme: ```mermaid flowchart LR - node([ArrayCreationExpression]) -.- initializer(initializer) + node([NewArrayExpression]) -.- initializer(initializer) initializer -- DFG --> node ``` @@ -169,7 +169,7 @@ Scheme: initializer -- DFG --> node ``` -## ArraySubscriptionExpression +## SubscriptExpression Interesting fields: @@ -181,7 +181,7 @@ The `arrayExpression` flows to the subscription expression. This means, we do no Scheme: ```mermaid flowchart LR - arrayExpression -- DFG --> node([ArraySubscriptionExpression]); + arrayExpression -- DFG --> node([SubscriptExpression]); arrayExpression -.- node; ``` @@ -191,21 +191,21 @@ Scheme: Interesting fields: * `condition: Expression`: The condition which is evaluated -* `thenExpr: Expression`: The expression which is executed if the condition holds -* `elseExpr: Expression`: The expression which is executed if the condition does not hold +* `thenExpression: Expression`: The expression which is executed if the condition holds +* `elseExpression: Expression`: The expression which is executed if the condition does not hold The `thenExpr` and the `elseExpr` flow to the `ConditionalExpression`. This means that implicit data flows are not considered. Scheme: ```mermaid flowchart LR - thenExpr -- DFG --> node([ConditionalExpression]); - thenExpr -.- node; - elseExpr -.- node; - elseExpr -- DFG --> node; + thenExpression -- DFG --> node([ConditionalExpression]); + thenExpression -.- node; + elseExpression -.- node; + elseExpression -- DFG --> node; ``` -## DeclaredReferenceExpression +## Reference Interesting fields: @@ -219,19 +219,19 @@ The `DFGPass` generates very simple edges based on the access to the variable as * The value flows from the declaration to the expression for read access. Scheme: ```mermaid flowchart LR - refersTo -- DFG --> node([DeclaredReferenceExpression]); + refersTo -- DFG --> node([Reference]); refersTo -.- node; ``` * For write access, data flow from the expression to the declaration. Scheme: ```mermaid flowchart LR - node([DeclaredReferenceExpression]) -- DFG --> refersTo; + node([Reference]) -- DFG --> refersTo; node -.- refersTo; ``` * For readwrite access, both flows are present. Scheme: ```mermaid flowchart LR - refersTo -- DFG 1 --> node([DeclaredReferenceExpression]); + refersTo -- DFG 1 --> node([Reference]); refersTo -.- node; node -- DFG 2 --> refersTo; ``` @@ -240,20 +240,20 @@ This mostly serves one purpose: The current function pointer resolution requires The `ControlFlowSensitiveDFGPass` completely changes this behavior and accounts for the data flows which differ depending on the program's control flow (e.g., different assignments to a variable in an if and else branch, ...). The pass performs the following actions: -* First, it clears all the edges between a `VariableDeclaration` and its `DeclaredReferenceExpression`. Actually, it clears all incoming and outgoing DFG edges of all VariableDeclarations in a function. This includes the initializer but this edge is restored right away. Scheme: +* First, it clears all the edges between a `VariableDeclaration` and its `Reference`. Actually, it clears all incoming and outgoing DFG edges of all VariableDeclarations in a function. This includes the initializer but this edge is restored right away. Scheme: ```mermaid flowchart LR node([VariableDeclaration]) -.- initializer; initializer -- DFG --> node; ``` -* For each read access to a DeclaredReferenceExpression, it collects all potential previous assignments to the variable and adds these to the incoming DFG edges. You can imagine that this is done by traversing the EOG backwards until finding the first assignment to the variable for each possible path. Scheme: +* For each read access to a Reference, it collects all potential previous assignments to the variable and adds these to the incoming DFG edges. You can imagine that this is done by traversing the EOG backwards until finding the first assignment to the variable for each possible path. Scheme: ```mermaid flowchart LR - node([DeclaredReferenceExpression]) -.- refersTo; + node([Reference]) -.- refersTo; A == last write to ==> refersTo; A[/Node/] -- DFG --> node; ``` -* If we increment or decrement a variable with "++" or "--", the data of this statement flows from the previous writes of the variable to the input of the statement (= the DeclaredReferenceExpression). We write back to this reference and consider the lhs as a "write" to the variable! *Attention: This potentially adds loops and can look like a branch. Needs to be handled with care in subsequent passes/analyses!* Scheme: +* If we increment or decrement a variable with "++" or "--", the data of this statement flows from the previous writes of the variable to the input of the statement (= the Reference). We write back to this reference and consider the lhs as a "write" to the variable! *Attention: This potentially adds loops and can look like a branch. Needs to be handled with care in subsequent passes/analyses!* Scheme: ```mermaid flowchart LR node([UnaryOperator]) -.- input; @@ -298,9 +298,9 @@ Interesting fields: * `base: Expression`: The base object whose field is accessed * `refersTo: Declaration?`: The field it refers to. If the class is not implemented in the code under analysis, it is `null`. -The MemberExpression represents an access to an object's field and extends a DeclaredReferenceExpression with a `base`. +The MemberExpression represents an access to an object's field and extends a Reference with a `base`. -If an implementation of the respective class is available, we handle it like a normal DeclaredReferenceExpression. +If an implementation of the respective class is available, we handle it like a normal Reference. If the `refersTo` field is `null` (i.e., the implementation is not available), base flows to the expression. ## ExpressionList @@ -554,7 +554,7 @@ Interesting fields: The value of the initializer flows to the whole field. -In addition, all writes to a reference to the field (via a `DeclaredReferenceExpression`) flow to the field, for all reads, data flow to the reference. +In addition, all writes to a reference to the field (via a `Reference`) flow to the field, for all reads, data flow to the reference. Scheme: ```mermaid @@ -571,7 +571,7 @@ Interesting fields: * `initializer: Expression?`: The value which is used to initialize a variable (if applicable). -The value of the initializer flows to the variable declaration. The value of the variable declarations flows to all `DeclaredReferenceExpressions` which read the value before the value of the variable is written to through another reference to the variable. +The value of the initializer flows to the variable declaration. The value of the variable declarations flows to all `References` which read the value before the value of the variable is written to through another reference to the variable. Scheme: ```mermaid @@ -589,7 +589,7 @@ Interesting fields: * `initializer: Expression?`: The value which is used to initialize a variable (if applicable). * `element: List`: The value which is used to initialize a variable (if applicable). -The value of the initializer flows to the elements of the tuple declaration. The value of the variable declarations flows to all `DeclaredReferenceExpressions` which read the value before the value of the variable is written to through another reference to the variable. +The value of the initializer flows to the elements of the tuple declaration. The value of the variable declarations flows to all `References` which read the value before the value of the variable is written to through another reference to the variable. Scheme: ```mermaid diff --git a/docs/docs/CPG/specs/eog.md b/docs/docs/CPG/specs/eog.md index ca8c1bd700..8ef5512d20 100644 --- a/docs/docs/CPG/specs/eog.md +++ b/docs/docs/CPG/specs/eog.md @@ -15,7 +15,7 @@ The EOG is similar to a CFG which connects basic blocks of statements, but there * For methods without explicit return statement, the EOG will have an edge to a virtual return node with line number -1 which does not exist in the original code. A CFG will always end with the last reachable statement(s) and not insert any virtual return statements. -* The EOG considers an opening blocking (`CompoundStatement`, indicated by a `{`) as a separate node. +* The EOG considers an opening blocking (`Block`, indicated by a `{`) as a separate node. A CFG will rather use the first actual executable statement within the block. * For IF statements, the EOG treats the `if` keyword and the condition as separate nodes. A CFG treats this as one `if` statement. @@ -52,7 +52,7 @@ A function declaration is the start of an intraprocedural EOG and contains its e Interesting fields: -* `parameters: List`: The parameters of the function. +* `parameters: List`: The parameters of the function. * `defaultValue: Expression`: Optional default values of the parameters that have to be evaluated before executing the function's body. * `body: Statement`: One or multiple statements executed when this function is called. @@ -69,11 +69,11 @@ flowchart LR ``` ## StatementHolder -StatementHolder is an interface for any node that is not a function and contains code that should be connected with an EOG. The following classes implement this interface: `NamespaceDeclaration`, `TranslationUnitDeclaration`, `RecordDeclaration` and `CompoundStatement`. The Node implementing the interface is the start of one or multiple EOGs. Note that code inside such a holder can be static or non static (bound to an instance of a record). Therefore, two separate EOGs may be built. +StatementHolder is an interface for any node that is not a function and contains code that should be connected with an EOG. The following classes implement this interface: `NamespaceDeclaration`, `TranslationUnitDeclaration`, `RecordDeclaration` and `Block`. The Node implementing the interface is the start of one or multiple EOGs. Note that code inside such a holder can be static or non static (bound to an instance of a record). Therefore, two separate EOGs may be built. Interesting fields: -* `statements: List`: The code inside a holder. The individual elements are distinguished by a property marking them as `staticBlock` if they are a `CompoundStatement`. +* `statements: List`: The code inside a holder. The individual elements are distinguished by a property marking them as `staticBlock` if they are a `Block`. Scheme: ```mermaid @@ -168,7 +168,7 @@ flowchart LR child --EOG--> parent ``` -## ArraySubscriptionExpression +## SubscriptExpression Array access in the form of `arrayExpression[subscriptExpression]`. Interesting fields: @@ -182,13 +182,13 @@ flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; prev:::outer --EOG--> child child --EOG--> child2["subscriptExpression"] - parent(["ArraySubscriptionExpression"]) --EOG--> next:::outer + parent(["SubscriptExpression"]) --EOG--> next:::outer parent -.-> child["arrayExpression"] parent -.-> child2 child2 --EOG--> parent ``` -## ArrayCreationExpression +## NewArrayExpression Interesting fields: * `dimensions: List`: Multiple expressions that define the array's dimensions. @@ -201,7 +201,7 @@ flowchart LR prev:::outer --EOG--> child1["dimension(i-1)"] child1 --EOG--> child2["dimension(i)"] child2 --EOG--> initializer - parent(["ArrayCreationExpression"]) --EOG--> next:::outer + parent(["NewArrayExpression"]) --EOG--> next:::outer parent -.-> child1 parent -.-> child2 parent -.-> initializer @@ -320,7 +320,7 @@ flowchart LR ``` -## CompoundStatement +## Block Represents an explicit block of statements. @@ -334,7 +334,7 @@ flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; prev:::outer --EOG--> child1["statement(i-1)"] child1 --EOG-->child2["statement(i)"] - parent(["CompoundStatement"]) --EOG--> next:::outer + parent(["Block"]) --EOG--> next:::outer parent -."statements(n)".-> child1 parent -."statements(n)".-> child2 child2 --EOG--> parent @@ -407,9 +407,9 @@ After the execution of the statement the control flow only proceeds with the nex Interesting fields: * `resources:List`: Initialization of values needed in the block or special objects needing cleanup. -* `tryBlock:CompoundStatement`: The code that should be tried, exceptions inside lead to an eog edge to the catch clauses. -* `finallyBlock:CompoundStatement`: All EOG paths inside the `tryBlock` or the `catch` blocks will finally reach this block and evaluate it. -* `catchBlocks:List`: Children of `CatchClause` (omitted here), evaluated when the exception matches the clauses condition. +* `tryBlock:Block`: The code that should be tried, exceptions inside lead to an eog edge to the catch clauses. +* `finallyBlock:Block`: All EOG paths inside the `tryBlock` or the `catch` blocks will finally reach this block and evaluate it. +* `catchBlocks:List`: Children of `CatchClause` (omitted here), evaluated when the exception matches the clauses condition. Scheme: ```mermaid @@ -584,7 +584,7 @@ The placement of the root node between expression and executed block is such tha Interesting fields: * `expression: Expression`: Its evaluation returns an object that acts as a lock for synchronization. -* `blockStatement: CompoundStatement`: Code executed while the object evaluated from `expression` is locked. +* `block: Block`: Code executed while the object evaluated from `expression` is locked. Scheme: ```mermaid @@ -592,7 +592,7 @@ flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; prev:::outer --EOG--> child1["expression"] child1 --EOG--> parent - parent --EOG--> child2["blockStatement"] + parent --EOG--> child2["block"] child2 --EOG--> next:::outer parent -.-> child1 parent -.-> child2 @@ -604,8 +604,8 @@ A conditional evaluation of two expression, realizing the branching pattern of a Interesting fields: * `condition:Expression`: Executed first to decide the branch of evaluation. -* `thenExpr:Expression`: Evaluated if `condition` evaluates to `true.` -* `elseExpr:Expression`: Evaluated if `condition` evaluates to `false.` +* `thenExpression:Expression`: Evaluated if `condition` evaluates to `true.` +* `elseExpression:Expression`: Evaluated if `condition` evaluates to `false.` Scheme: ```mermaid @@ -613,8 +613,8 @@ flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; prev:::outer --EOG--> child1["condition"] child1 --EOG--> parent(["ConditionalExpression"]) - parent --EOG:true--> child2["thenExpr"] - parent --EOG:false--> child3["elseExpr"] + parent --EOG:true--> child2["thenExpression"] + parent --EOG:false--> child3["elseExpression"] child2 --EOG--> next:::outer child3 --EOG--> next:::outer parent -.-> child1 diff --git a/docs/docs/CPG/specs/graph.md b/docs/docs/CPG/specs/graph.md index d4dcc81ecf..7e594aad52 100644 --- a/docs/docs/CPG/specs/graph.md +++ b/docs/docs/CPG/specs/graph.md @@ -77,7 +77,7 @@ Node--"TYPEDEFS*"-->NodeTYPEDEFS[TypedefDeclarati [SwitchStatement](#eswitchstatement) [GotoStatement](#egotostatement) [WhileStatement](#ewhilestatement) -[CompoundStatement](#ecompoundstatement) +[BlockStatement](#ecompoundstatement) [ContinueStatement](#econtinuestatement) [DefaultStatement](#edefaultstatement) [SynchronizedStatement](#esynchronizedstatement) @@ -251,15 +251,15 @@ ReturnStatement--"RETURN_VALUES*"-->ReturnStatementRETURN_VALUES[[CallExpression](#ecallexpression) ### Children -[ExplicitConstructorInvocation](#eexplicitconstructorinvocation) +[ConstructorCallExpression](#eexplicitconstructorinvocation) [ConstructExpression](#econstructexpression) [MemberCallExpression](#emembercallexpression) @@ -530,12 +530,12 @@ flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; CallExpression--"TEMPLATE_PARAMETERS*"-->CallExpressionTEMPLATE_PARAMETERS[Node]:::outer ``` -## ExplicitConstructorInvocation +## ConstructorCallExpression **Labels**:[Node](#enode) [Statement](#estatement) [Expression](#eexpression) [CallExpression](#ecallexpression) -[ExplicitConstructorInvocation](#eexplicitconstructorinvocation) +[ConstructorCallExpression](#eexplicitconstructorinvocation) ### Relationships [CALLEE](#CallExpressionCALLEE) @@ -834,16 +834,16 @@ flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; CastExpression--"EXPRESSION¹"-->CastExpressionEXPRESSION[Expression]:::outer ``` -## ArrayCreationExpression +## NewArrayExpression **Labels**:[Node](#enode) [Statement](#estatement) [Expression](#eexpression) -[ArrayCreationExpression](#earraycreationexpression) +[NewArrayExpression](#earraycreationexpression) ### Relationships -[INITIALIZER](#ArrayCreationExpressionINITIALIZER) +[INITIALIZER](#NewArrayExpressionINITIALIZER) -[DIMENSIONS](#ArrayCreationExpressionDIMENSIONS) +[DIMENSIONS](#NewArrayExpressionDIMENSIONS) [POSSIBLE_SUB_TYPES](#ExpressionPOSSIBLE_SUB_TYPES) @@ -863,28 +863,28 @@ CastExpression--"EXPRESSION¹"-->CastExpressionEXPRESSION[[TYPEDEFS](#NodeTYPEDEFS) -#### INITIALIZER +#### INITIALIZER ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -ArrayCreationExpression--"INITIALIZER¹"-->ArrayCreationExpressionINITIALIZER[Expression]:::outer +NewArrayExpression--"INITIALIZER¹"-->NewArrayExpressionINITIALIZER[Expression]:::outer ``` -#### DIMENSIONS +#### DIMENSIONS ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -ArrayCreationExpression--"DIMENSIONS*"-->ArrayCreationExpressionDIMENSIONS[Expression]:::outer +NewArrayExpression--"DIMENSIONS*"-->NewArrayExpressionDIMENSIONS[Expression]:::outer ``` -## ArraySubscriptionExpression +## SubscriptionExpression **Labels**:[Node](#enode) [Statement](#estatement) [Expression](#eexpression) -[ArraySubscriptionExpression](#earraysubscriptionexpression) +[SubscriptionExpression](#earraysubscriptionexpression) ### Relationships -[ARRAY_EXPRESSION](#ArraySubscriptionExpressionARRAY_EXPRESSION) +[ARRAY_EXPRESSION](#SubscriptionExpressionARRAY_EXPRESSION) -[SUBSCRIPT_EXPRESSION](#ArraySubscriptionExpressionSUBSCRIPT_EXPRESSION) +[SUBSCRIPT_EXPRESSION](#SubscriptionExpressionSUBSCRIPT_EXPRESSION) [POSSIBLE_SUB_TYPES](#ExpressionPOSSIBLE_SUB_TYPES) @@ -904,17 +904,17 @@ ArrayCreationExpression--"DIMENSIONS*"-->ArrayCreationExpressionDIMENSIONS[[TYPEDEFS](#NodeTYPEDEFS) -#### ARRAY_EXPRESSION +#### ARRAY_EXPRESSION ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -ArraySubscriptionExpression--"ARRAY_EXPRESSION¹"-->ArraySubscriptionExpressionARRAY_EXPRESSION[Expression]:::outer +SubscriptionExpression--"ARRAY_EXPRESSION¹"-->SubscriptionExpressionARRAY_EXPRESSION[Expression]:::outer ``` -#### SUBSCRIPT_EXPRESSION +#### SUBSCRIPT_EXPRESSION ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -ArraySubscriptionExpression--"SUBSCRIPT_EXPRESSION¹"-->ArraySubscriptionExpressionSUBSCRIPT_EXPRESSION[Expression]:::outer +SubscriptionExpression--"SUBSCRIPT_EXPRESSION¹"-->SubscriptionExpressionSUBSCRIPT_EXPRESSION[Expression]:::outer ``` ## TypeExpression **Labels**:[Node](#enode) @@ -1031,17 +1031,17 @@ flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; ConditionalExpression--"CONDITION¹"-->ConditionalExpressionCONDITION[Expression]:::outer ``` -## DeclaredReferenceExpression +## Reference **Labels**:[Node](#enode) [Statement](#estatement) [Expression](#eexpression) -[DeclaredReferenceExpression](#edeclaredreferenceexpression) +[Reference](#edeclaredreferenceexpression) ### Children [MemberExpression](#ememberexpression) ### Relationships -[REFERS_TO](#DeclaredReferenceExpressionREFERS_TO) +[REFERS_TO](#ReferenceREFERS_TO) [POSSIBLE_SUB_TYPES](#ExpressionPOSSIBLE_SUB_TYPES) @@ -1061,23 +1061,23 @@ ConditionalExpression--"CONDITION¹"-->ConditionalExpressionCONDITION[Declaration]:::outer +Reference--"REFERS_TO¹"-->ReferenceREFERS_TO[Declaration]:::outer ``` ## MemberExpression **Labels**:[Node](#enode) [Statement](#estatement) [Expression](#eexpression) -[DeclaredReferenceExpression](#edeclaredreferenceexpression) +[Reference](#edeclaredreferenceexpression) [MemberExpression](#ememberexpression) ### Relationships [BASE](#MemberExpressionBASE) -[REFERS_TO](#DeclaredReferenceExpressionREFERS_TO) +[REFERS_TO](#ReferenceREFERS_TO) [POSSIBLE_SUB_TYPES](#ExpressionPOSSIBLE_SUB_TYPES) @@ -1169,14 +1169,14 @@ flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; DeleteExpression--"OPERAND¹"-->DeleteExpressionOPERAND[Expression]:::outer ``` -## CompoundStatementExpression +## BlockStatementExpression **Labels**:[Node](#enode) [Statement](#estatement) [Expression](#eexpression) -[CompoundStatementExpression](#ecompoundstatementexpression) +[BlockStatementExpression](#ecompoundstatementexpression) ### Relationships -[STATEMENT](#CompoundStatementExpressionSTATEMENT) +[STATEMENT](#BlockStatementExpressionSTATEMENT) [POSSIBLE_SUB_TYPES](#ExpressionPOSSIBLE_SUB_TYPES) @@ -1196,11 +1196,11 @@ DeleteExpression--"OPERAND¹"-->DeleteExpressionOPERAND[E [TYPEDEFS](#NodeTYPEDEFS) -#### STATEMENT +#### STATEMENT ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -CompoundStatementExpression--"STATEMENT¹"-->CompoundStatementExpressionSTATEMENT[Statement]:::outer +BlockStatementExpression--"STATEMENT¹"-->BlockStatementExpressionSTATEMENT[Statement]:::outer ``` ## ProblemExpression **Labels**:[Node](#enode) @@ -1526,7 +1526,7 @@ CatchClause--"PARAMETER¹"-->CatchClausePARAMETER[CompoundStatement]:::outer +CatchClause--"BODY¹"-->CatchClauseBODY[BlockStatement]:::outer ``` ## SwitchStatement **Labels**:[Node](#enode) @@ -1652,13 +1652,13 @@ flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; WhileStatement--"STATEMENT¹"-->WhileStatementSTATEMENT[Statement]:::outer ``` -## CompoundStatement +## BlockStatement **Labels**:[Node](#enode) [Statement](#estatement) -[CompoundStatement](#ecompoundstatement) +[BlockStatement](#ecompoundstatement) ### Relationships -[STATEMENTS](#CompoundStatementSTATEMENTS) +[STATEMENTS](#BlockStatementSTATEMENTS) [LOCALS](#StatementLOCALS) @@ -1674,11 +1674,11 @@ WhileStatement--"STATEMENT¹"-->WhileStatementSTATEMENT[St [TYPEDEFS](#NodeTYPEDEFS) -#### STATEMENTS +#### STATEMENTS ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -CompoundStatement--"STATEMENTS*"-->CompoundStatementSTATEMENTS[Statement]:::outer +BlockStatement--"STATEMENTS*"-->BlockStatementSTATEMENTS[Statement]:::outer ``` ## ContinueStatement **Labels**:[Node](#enode) @@ -1748,7 +1748,7 @@ CompoundStatement--"STATEMENTS*"-->CompoundStatementSTATEMENTS[CompoundStatement]:::outer +SynchronizedStatement--"BLOCK_STATEMENT¹"-->SynchronizedStatementBLOCK_STATEMENT[BlockStatement]:::outer ``` #### EXPRESSION ```mermaid @@ -1794,13 +1794,13 @@ TryStatement--"RESOURCES*"-->TryStatementRESOURCES[Stateme ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -TryStatement--"FINALLY_BLOCK¹"-->TryStatementFINALLY_BLOCK[CompoundStatement]:::outer +TryStatement--"FINALLY_BLOCK¹"-->TryStatementFINALLY_BLOCK[BlockStatement]:::outer ``` #### TRY_BLOCK ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -TryStatement--"TRY_BLOCK¹"-->TryStatementTRY_BLOCK[CompoundStatement]:::outer +TryStatement--"TRY_BLOCK¹"-->TryStatementTRY_BLOCK[BlockStatement]:::outer ``` #### CATCH_CLAUSES ```mermaid @@ -1960,8 +1960,8 @@ LabelStatement--"SUB_STATEMENT¹"-->LabelStatementSUB_STATEMENT[Type]:::o ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -ValueDeclaration--"USAGE*"-->ValueDeclarationUSAGE[DeclaredReferenceExpression]:::outer +ValueDeclaration--"USAGE*"-->ValueDeclarationUSAGE[Reference]:::outer ``` ## FieldDeclaration **Labels**:[Node](#enode) @@ -2216,7 +2216,7 @@ FunctionDeclaration--"RETURN_TYPES*"-->FunctionDeclarationRETURN_TYPES[ParamVariableDeclaration]:::outer +FunctionDeclaration--"PARAMETERS*"-->FunctionDeclarationPARAMETERS[ParameterDeclaration]:::outer ``` #### DEFINES ```mermaid @@ -2328,14 +2328,14 @@ MethodDeclaration--"RECORD_DECLARATION¹"-->MethodDeclarationRECORD_DECLARATION[ [TYPEDEFS](#NodeTYPEDEFS) -## ParamVariableDeclaration +## ParameterDeclaration **Labels**:[Node](#enode) [Declaration](#edeclaration) [ValueDeclaration](#evaluedeclaration) -[ParamVariableDeclaration](#eparamvariabledeclaration) +[ParameterDeclaration](#eparamvariabledeclaration) ### Relationships -[DEFAULT](#ParamVariableDeclarationDEFAULT) +[DEFAULT](#ParameterDeclarationDEFAULT) [POSSIBLE_SUB_TYPES](#ValueDeclarationPOSSIBLE_SUB_TYPES) @@ -2355,20 +2355,20 @@ MethodDeclaration--"RECORD_DECLARATION¹"-->MethodDeclarationRECORD_DECLARATION[ [TYPEDEFS](#NodeTYPEDEFS) -#### DEFAULT +#### DEFAULT ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -ParamVariableDeclaration--"DEFAULT¹"-->ParamVariableDeclarationDEFAULT[Expression]:::outer +ParameterDeclaration--"DEFAULT¹"-->ParameterDeclarationDEFAULT[Expression]:::outer ``` -## TypeParamDeclaration +## TypeParameterDeclaration **Labels**:[Node](#enode) [Declaration](#edeclaration) [ValueDeclaration](#evaluedeclaration) -[TypeParamDeclaration](#etypeparamdeclaration) +[TypeParameterDeclaration](#etypeparamdeclaration) ### Relationships -[DEFAULT](#TypeParamDeclarationDEFAULT) +[DEFAULT](#TypeParameterDeclarationDEFAULT) [POSSIBLE_SUB_TYPES](#ValueDeclarationPOSSIBLE_SUB_TYPES) @@ -2388,11 +2388,11 @@ ParamVariableDeclaration--"DEFAULT¹"-->ParamVariableDeclarationDEFAULT[[TYPEDEFS](#NodeTYPEDEFS) -#### DEFAULT +#### DEFAULT ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -TypeParamDeclaration--"DEFAULT¹"-->TypeParamDeclarationDEFAULT[Type]:::outer +TypeParameterDeclaration--"DEFAULT¹"-->TypeParameterDeclarationDEFAULT[Type]:::outer ``` ## TemplateDeclaration **Labels**:[Node](#enode) diff --git a/docs/docs/CPG/specs/schema.md b/docs/docs/CPG/specs/schema.md index dcb736047a..3b91b95eb8 100644 --- a/docs/docs/CPG/specs/schema.md +++ b/docs/docs/CPG/specs/schema.md @@ -238,7 +238,7 @@ Node--"TYPEDEFS*"-->NodeTYPEDEFS[TypedefDeclarati text-align: center; margin-bottom: 10px; padding-left: 10px; - padding-right: 10px;">[CompoundStatement](#ecompoundstatement) [BlockStatement](#ecompoundstatement) ReturnStatementRETURN_VALUES[[DeclaredReferenceExpression](#edeclaredreferenceexpression) [Reference](#edeclaredreferenceexpression) ReturnStatementRETURN_VALUES[[ExplicitConstructorInvocation](#eexplicitconstructorinvocation) [ConstructorCallExpression](#eexplicitconstructorinvocation) CallExpressionTEMPLATE_PARAMETERS[Node]:::outer ``` -# ExplicitConstructorInvocation +# ConstructorCallExpression **Labels**:CallExpressionTEMPLATE_PARAMETERS[[ExplicitConstructorInvocation](#eexplicitconstructorinvocation) + padding-right: 10px;">[ConstructorCallExpression](#eexplicitconstructorinvocation) ## Relationships CastExpressionEXPRESSION[Expression]:::outer ``` -# ArrayCreationExpression +# NewArrayExpression **Labels**:CastExpressionEXPRESSION[[ArrayCreationExpression](#earraycreationexpression) + padding-right: 10px;">[NewArrayExpression](#earraycreationexpression) ## Relationships CastExpressionEXPRESSION[[INITIALIZER](#ArrayCreationExpressionINITIALIZER) + padding-right: 10px;">[INITIALIZER](#NewArrayExpressionINITIALIZER) CastExpressionEXPRESSION[[DIMENSIONS](#ArrayCreationExpressionDIMENSIONS) + padding-right: 10px;">[DIMENSIONS](#NewArrayExpressionDIMENSIONS) CastExpressionEXPRESSION[[TYPEDEFS](#NodeTYPEDEFS) -### INITIALIZER +### INITIALIZER ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -ArrayCreationExpression--"INITIALIZER¹"-->ArrayCreationExpressionINITIALIZER[Expression]:::outer +NewArrayExpression--"INITIALIZER¹"-->NewArrayExpressionINITIALIZER[Expression]:::outer ``` -### DIMENSIONS +### DIMENSIONS ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -ArrayCreationExpression--"DIMENSIONS*"-->ArrayCreationExpressionDIMENSIONS[Expression]:::outer +NewArrayExpression--"DIMENSIONS*"-->NewArrayExpressionDIMENSIONS[Expression]:::outer ``` -# ArraySubscriptionExpression +# SubscriptionExpression **Labels**:ArrayCreationExpressionDIMENSIONS[[ArraySubscriptionExpression](#earraysubscriptionexpression) + padding-right: 10px;">[SubscriptionExpression](#earraysubscriptionexpression) ## Relationships ArrayCreationExpressionDIMENSIONS[[ARRAY_EXPRESSION](#ArraySubscriptionExpressionARRAY_EXPRESSION) + padding-right: 10px;">[ARRAY_EXPRESSION](#SubscriptionExpressionARRAY_EXPRESSION) ArrayCreationExpressionDIMENSIONS[[SUBSCRIPT_EXPRESSION](#ArraySubscriptionExpressionSUBSCRIPT_EXPRESSION) + padding-right: 10px;">[SUBSCRIPT_EXPRESSION](#SubscriptionExpressionSUBSCRIPT_EXPRESSION) ArrayCreationExpressionDIMENSIONS[[TYPEDEFS](#NodeTYPEDEFS) -### ARRAY_EXPRESSION +### ARRAY_EXPRESSION ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -ArraySubscriptionExpression--"ARRAY_EXPRESSION¹"-->ArraySubscriptionExpressionARRAY_EXPRESSION[Expression]:::outer +SubscriptionExpression--"ARRAY_EXPRESSION¹"-->SubscriptionExpressionARRAY_EXPRESSION[Expression]:::outer ``` -### SUBSCRIPT_EXPRESSION +### SUBSCRIPT_EXPRESSION ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -ArraySubscriptionExpression--"SUBSCRIPT_EXPRESSION¹"-->ArraySubscriptionExpressionSUBSCRIPT_EXPRESSION[Expression]:::outer +SubscriptionExpression--"SUBSCRIPT_EXPRESSION¹"-->SubscriptionExpressionSUBSCRIPT_EXPRESSION[Expression]:::outer ``` # TypeExpression **Labels**:ConditionalExpressionCONDITION[Expression]:::outer ``` -# DeclaredReferenceExpression +# Reference **Labels**:ConditionalExpressionCONDITION[[REFERS_TO](#DeclaredReferenceExpressionREFERS_TO) + padding-right: 10px;">[REFERS_TO](#ReferenceREFERS_TO) ConditionalExpressionCONDITION[Declaration]:::outer +Reference--"REFERS_TO¹"-->ReferenceREFERS_TO[Declaration]:::outer ``` # MemberExpression **Labels**:DeclaredReferenceExpressionREFERS_T text-align: center; margin-bottom: 10px; padding-left: 10px; - padding-right: 10px;">[DeclaredReferenceExpression](#edeclaredreferenceexpression) [Reference](#edeclaredreferenceexpression) DeclaredReferenceExpressionREFERS_T text-align: center; margin-bottom: 10px; padding-left: 10px; - padding-right: 10px;">[REFERS_TO](#DeclaredReferenceExpressionREFERS_TO) + padding-right: 10px;">[REFERS_TO](#ReferenceREFERS_TO) DeleteExpressionOPERAND[Expression]:::outer ``` -# CompoundStatementExpression +# BlockStatementExpression **Labels**:DeleteExpressionOPERAND[E text-align: center; margin-bottom: 10px; padding-left: 10px; - padding-right: 10px;">[CompoundStatementExpression](#ecompoundstatementexpression) + padding-right: 10px;">[BlockStatementExpression](#ecompoundstatementexpression) ## Relationships DeleteExpressionOPERAND[E text-align: center; margin-bottom: 10px; padding-left: 10px; - padding-right: 10px;">[STATEMENT](#CompoundStatementExpressionSTATEMENT) + padding-right: 10px;">[STATEMENT](#BlockStatementExpressionSTATEMENT) DeleteExpressionOPERAND[E margin-bottom: 10px; padding-left: 10px; padding-right: 10px;">[TYPEDEFS](#NodeTYPEDEFS) -### STATEMENT +### STATEMENT ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -CompoundStatementExpression--"STATEMENT¹"-->CompoundStatementExpressionSTATEMENT[Statement]:::outer +BlockStatementExpression--"STATEMENT¹"-->BlockStatementExpressionSTATEMENT[Statement]:::outer ``` # ProblemExpression **Labels**:CatchClausePARAMETER[CompoundStatement]:::outer +CatchClause--"BODY¹"-->CatchClauseBODY[BlockStatement]:::outer ``` # SwitchStatement **Labels**:WhileStatementSTATEMENT[Statement]:::outer ``` -# CompoundStatement +# BlockStatement **Labels**:WhileStatementSTATEMENT[St text-align: center; margin-bottom: 10px; padding-left: 10px; - padding-right: 10px;">[CompoundStatement](#ecompoundstatement) + padding-right: 10px;">[BlockStatement](#ecompoundstatement) ## Relationships WhileStatementSTATEMENT[St text-align: center; margin-bottom: 10px; padding-left: 10px; - padding-right: 10px;">[STATEMENTS](#CompoundStatementSTATEMENTS) + padding-right: 10px;">[STATEMENTS](#BlockStatementSTATEMENTS) WhileStatementSTATEMENT[St margin-bottom: 10px; padding-left: 10px; padding-right: 10px;">[TYPEDEFS](#NodeTYPEDEFS) -### STATEMENTS +### STATEMENTS ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -CompoundStatement--"STATEMENTS*"-->CompoundStatementSTATEMENTS[Statement]:::outer +BlockStatement--"STATEMENTS*"-->BlockStatementSTATEMENTS[Statement]:::outer ``` # ContinueStatement **Labels**:CompoundStatementSTATEMENTS[CompoundStatement]:::outer +SynchronizedStatement--"BLOCK_STATEMENT¹"-->SynchronizedStatementBLOCK_STATEMENT[BlockStatement]:::outer ``` ### EXPRESSION ```mermaid @@ -5908,13 +5908,13 @@ TryStatement--"RESOURCES*"-->TryStatementRESOURCES[Stateme ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -TryStatement--"FINALLY_BLOCK¹"-->TryStatementFINALLY_BLOCK[CompoundStatement]:::outer +TryStatement--"FINALLY_BLOCK¹"-->TryStatementFINALLY_BLOCK[BlockStatement]:::outer ``` ### TRY_BLOCK ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -TryStatement--"TRY_BLOCK¹"-->TryStatementTRY_BLOCK[CompoundStatement]:::outer +TryStatement--"TRY_BLOCK¹"-->TryStatementTRY_BLOCK[BlockStatement]:::outer ``` ### CATCH_CLAUSES ```mermaid @@ -6501,14 +6501,14 @@ LabelStatement--"SUB_STATEMENT¹"-->LabelStatementSUB_STATEMENT[Type]:::o ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -ValueDeclaration--"USAGE*"-->ValueDeclarationUSAGE[DeclaredReferenceExpression]:::outer +ValueDeclaration--"USAGE*"-->ValueDeclarationUSAGE[Reference]:::outer ``` # FieldDeclaration **Labels**:FunctionDeclarationRETURN_TYPES[ParamVariableDeclaration]:::outer +FunctionDeclaration--"PARAMETERS*"-->FunctionDeclarationPARAMETERS[ParameterDeclaration]:::outer ``` ### DEFINES ```mermaid @@ -7684,7 +7684,7 @@ MethodDeclaration--"RECORD_DECLARATION¹"-->MethodDeclarationRECORD_DECLARATION[ margin-bottom: 10px; padding-left: 10px; padding-right: 10px;">[TYPEDEFS](#NodeTYPEDEFS) -# ParamVariableDeclaration +# ParameterDeclaration **Labels**:MethodDeclarationRECORD_DECLARATION[ text-align: center; margin-bottom: 10px; padding-left: 10px; - padding-right: 10px;">[ParamVariableDeclaration](#eparamvariabledeclaration) + padding-right: 10px;">[ParameterDeclaration](#eparamvariabledeclaration) ## Relationships MethodDeclarationRECORD_DECLARATION[ text-align: center; margin-bottom: 10px; padding-left: 10px; - padding-right: 10px;">[DEFAULT](#ParamVariableDeclarationDEFAULT) + padding-right: 10px;">[DEFAULT](#ParameterDeclarationDEFAULT) MethodDeclarationRECORD_DECLARATION[ margin-bottom: 10px; padding-left: 10px; padding-right: 10px;">[TYPEDEFS](#NodeTYPEDEFS) -### DEFAULT +### DEFAULT ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -ParamVariableDeclaration--"DEFAULT¹"-->ParamVariableDeclarationDEFAULT[Expression]:::outer +ParameterDeclaration--"DEFAULT¹"-->ParameterDeclarationDEFAULT[Expression]:::outer ``` -# TypeParamDeclaration +# TypeParameterDeclaration **Labels**:ParamVariableDeclarationDEFAULT[[TypeParamDeclaration](#etypeparamdeclaration) + padding-right: 10px;">[TypeParameterDeclaration](#etypeparamdeclaration) ## Relationships ParamVariableDeclarationDEFAULT[[DEFAULT](#TypeParamDeclarationDEFAULT) + padding-right: 10px;">[DEFAULT](#TypeParameterDeclarationDEFAULT) ParamVariableDeclarationDEFAULT[[TYPEDEFS](#NodeTYPEDEFS) -### DEFAULT +### DEFAULT ```mermaid flowchart LR classDef outer fill:#fff,stroke:#ddd,stroke-dasharray:5 5; classDef special fill:#afa,stroke:#5a5,stroke-dasharray:5 5; -TypeParamDeclaration--"DEFAULT¹"-->TypeParamDeclarationDEFAULT[Type]:::outer +TypeParameterDeclaration--"DEFAULT¹"-->TypeParameterDeclarationDEFAULT[Type]:::outer ``` # TemplateDeclaration **Labels**:>() +var parameterEdges = mutableListOf>() /** Virtual property for accessing [parameterEdges] without property edges. */ var parameters by PropertyEdgeDelegate(FunctionDeclaration::parameterEdges) diff --git a/docs/docs/GettingStarted/query.md b/docs/docs/GettingStarted/query.md index 6fb8a49444..361e78b760 100755 --- a/docs/docs/GettingStarted/query.md +++ b/docs/docs/GettingStarted/query.md @@ -49,7 +49,7 @@ all (==> false) -------- Starting at CallExpression[name=memcpy,location=vulnerable.cpp(3:5-3:38),type=UNKNOWN,base=]: 5 > 11 (==> false) ------------------------ - sizeof(DeclaredReferenceExpression[DeclaredReferenceExpression[name=array,location=vulnerable.cpp(3:12-3:17),type=PointerType[name=char[]]],refersTo=VariableDeclaration[name=array,location=vulnerable.cpp(2:10-2:28),initializer=Literal[location=vulnerable.cpp(2:21-2:28),type=PointerType[name=char[]],value=hello]]]) (==> 5) + sizeof(Reference[Reference[name=array,location=vulnerable.cpp(3:12-3:17),type=PointerType[name=char[]]],refersTo=VariableDeclaration[name=array,location=vulnerable.cpp(2:10-2:28),initializer=Literal[location=vulnerable.cpp(2:21-2:28),type=PointerType[name=char[]],value=hello]]]) (==> 5) ---------------------------------------- ------------------------ sizeof(Literal[location=vulnerable.cpp(3:19-3:32),type=PointerType[name=char[]],value=Hello world]) (==> 11) diff --git a/docs/docs/GettingStarted/shortcuts.md b/docs/docs/GettingStarted/shortcuts.md index f97492c443..3bfc3448d3 100644 --- a/docs/docs/GettingStarted/shortcuts.md +++ b/docs/docs/GettingStarted/shortcuts.md @@ -86,7 +86,7 @@ which search for other patterns in the graph. Note that these are often less stable than the information from above! * The size of an array is evaluated using - `ArraySubscriptionExpression.arraySize`. Unfortunately, this only works if the + `SubscriptExpression.arraySize`. Unfortunately, this only works if the size is given in the initialization. Updates are not considered. * Control dependencies are currently available via the extensions `Node.controlledBy()` and `IfStatement.controls()`. diff --git a/tutorial.md b/tutorial.md index 008b636ce3..c12f5686f0 100644 --- a/tutorial.md +++ b/tutorial.md @@ -89,22 +89,22 @@ In the following, we will use the aforementioned objects to query the source cod res3: List = ... ``` -The output here can be quite verbose, so additional filtering is needed. The `all` function takes an additional type parameter, which can be used to further filter nodes of a particular type. In this case, we are interested in all `ArraySubscriptionExpression` nodes, i.e. those that represent access to an element of an array. These operations are often prone to out of bounds errors and we want to explore, whether our code is also affected by that. +The output here can be quite verbose, so additional filtering is needed. The `all` function takes an additional type parameter, which can be used to further filter nodes of a particular type. In this case, we are interested in all `SubscriptExpression` nodes, i.e. those that represent access to an element of an array. These operations are often prone to out of bounds errors and we want to explore, whether our code is also affected by that. ```kotlin -[4] result.all() -res4: List = [ - {"@type":"ArraySubscriptionExpression","location":"array.go(6:2-6:7)","type":{"@type":"ObjectType","name":"int"}}, - {"@type":"ArraySubscriptionExpression","location":"array.cpp(6:12-6:18)","type":{"@type":"ObjectType","name":"char"}}, - {"@type":"ArraySubscriptionExpression","location":"Array.java(8:18-8:22)","type":{"@type":"ObjectType","name":"char"}}, - {"@type":"ArraySubscriptionExpression","location":"array.cpp(12:12-12:16)","type":{"@type":"ObjectType","name":"char"}} +[4] result.all() +res4: List = [ + {"@type":"SubscriptExpression","location":"array.go(6:2-6:7)","type":{"@type":"ObjectType","name":"int"}}, + {"@type":"SubscriptExpression","location":"array.cpp(6:12-6:18)","type":{"@type":"ObjectType","name":"char"}}, + {"@type":"SubscriptExpression","location":"Array.java(8:18-8:22)","type":{"@type":"ObjectType","name":"char"}}, + {"@type":"SubscriptExpression","location":"array.cpp(12:12-12:16)","type":{"@type":"ObjectType","name":"char"}} ] ``` Much better. We have found four nodes that represent an array access. To see the corresponding source code of our result, we can prefix our previous command with `:code` or `:c`. This shows the raw source code as well as the location of the file where the code is located. ```kotlin -[5] :code result.all() +[5] :code result.all() --- src/test/resources/array.go:6:2 --- 6: a[11] ------------------------------------------------ @@ -129,7 +129,7 @@ This also demonstrates quite nicely, that queries on the CPG work independently In a next step, we want to identify, which of those expression are accessing an array index that is greater than its capacity, thus leading to an error. From the code output we have seen before we can already identify two array indicies: `0` and `11`. But the other two are using a variable `b` as the index. Using the `evaluate` function, we can try to evaluate the variable `b`, to check if it has a constant value. ```kotlin -[6] result.all().map { it.subscriptExpression.evaluate() } +[6] result.all().map { it.subscriptExpression.evaluate() } res6: List = [11, 5, 5, 0] ``` @@ -138,17 +138,17 @@ In this case we are in luck and we see that, next to the `0` and `11` we already In a next step, we want to check to capacity of the array the access is referring to. We can make use of two helper functions `dfgFrom` and `capacity` to quickly check this, using the built-in data flow analysis. ```kotlin -[7] var expr = result.all().map { Triple( +[7] var expr = result.all().map { Triple( it.subscriptExpression.evaluate() as Int, - it.arrayExpression.dfgFrom().first().capacity, + it.arrayExpression.dfgFrom().first().capacity, it ) } [8]: expr -res8: List> = [ - (11, 10, {"@type":"ArraySubscriptionExpression","location":"array.go(6:2-6:7)","type":{"@type":"ObjectType","name":"int"}}), - (5, 4, {"@type":"ArraySubscriptionExpression","location":"array.cpp(6:12-6:18)","type":{"@type":"ObjectType","name":"char"}}), - (5, 4, {"@type":"ArraySubscriptionExpression","location":"Array.java(8:18-8:22)","type":{"@type":"ObjectType","name":"char"}}), - (0, 100, {"@type":"ArraySubscriptionExpression","location":"array.cpp(12:12-12:16)","type":{"@type":"ObjectType","name":"char"}}) +res8: List> = [ + (11, 10, {"@type":"SubscriptExpression","location":"array.go(6:2-6:7)","type":{"@type":"ObjectType","name":"int"}}), + (5, 4, {"@type":"SubscriptExpression","location":"array.cpp(6:12-6:18)","type":{"@type":"ObjectType","name":"char"}}), + (5, 4, {"@type":"SubscriptExpression","location":"Array.java(8:18-8:22)","type":{"@type":"ObjectType","name":"char"}}), + (0, 100, {"@type":"SubscriptExpression","location":"array.cpp(12:12-12:16)","type":{"@type":"ObjectType","name":"char"}}) ] ``` @@ -158,10 +158,10 @@ Lastly, we can make use of the `filter` function to return only those nodes wher ```kotlin [9] expr.filter { it.first >= it.second } -res8: List> = [ - (11, 10, {"@type":"ArraySubscriptionExpression","location":"array.go(6:2-6:7)","type":{"@type":"ObjectType","name":"int"}}), - (5, 4, {"@type":"ArraySubscriptionExpression","location":"array.cpp(6:12-6:18)","type":{"@type":"ObjectType","name":"char"}}), - (5, 4, {"@type":"ArraySubscriptionExpression","location":"Array.java(8:18-8:22)","type":{"@type":"ObjectType","name":"char"}}) +res8: List> = [ + (11, 10, {"@type":"SubscriptExpression","location":"array.go(6:2-6:7)","type":{"@type":"ObjectType","name":"int"}}), + (5, 4, {"@type":"SubscriptExpression","location":"array.cpp(6:12-6:18)","type":{"@type":"ObjectType","name":"char"}}), + (5, 4, {"@type":"SubscriptExpression","location":"Array.java(8:18-8:22)","type":{"@type":"ObjectType","name":"char"}}) ] ``` @@ -189,13 +189,13 @@ Because the manual analyis we have shown can be quite tedious, we already includ ```kotlin [11] :run ---- FINDING: Out of bounds access in ArrayCreationExpression when accessing index 11 of a, an array of length 10 --- +--- FINDING: Out of bounds access in NewArrayExpression when accessing index 11 of a, an array of length 10 --- src/test/resources/array.go:6:2: a[11] The following path was discovered that leads to 11 being 11: src/test/resources/array.go:6:4: 11 ---- FINDING: Out of bounds access in ArrayCreationExpression when accessing index 5 of c, an array of length 4 --- +--- FINDING: Out of bounds access in NewArrayExpression when accessing index 5 of c, an array of length 4 --- src/test/resources/array.cpp:6:12: = c[b] The following path was discovered that leads to b being 5: