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 56fb4c9348..9c0273a97a 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 @@ -33,7 +33,7 @@ import de.fraunhofer.aisec.cpg.graph.statements.DeclarationStatement import de.fraunhofer.aisec.cpg.graph.statements.ForStatement import de.fraunhofer.aisec.cpg.graph.statements.expressions.* import de.fraunhofer.aisec.cpg.passes.EdgeCachePass -import de.fraunhofer.aisec.cpg.passes.astParent +import de.fraunhofer.aisec.cpg.passes.astParentLegacy import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -186,7 +186,7 @@ class MultiValueEvaluator : ValueEvaluator() { } } "--" -> { - if (expr.astParent is ForStatement) { + if (expr.astParentLegacy is ForStatement) { evaluateInternal(expr.input, depth + 1) } else { when (val input = evaluateInternal(expr.input, depth + 1)) { @@ -196,7 +196,7 @@ class MultiValueEvaluator : ValueEvaluator() { } } "++" -> { - if (expr.astParent is ForStatement) { + if (expr.astParentLegacy is ForStatement) { evaluateInternal(expr.input, depth + 1) } else { when (val input = evaluateInternal(expr.input, depth + 1)) { @@ -256,8 +256,8 @@ class MultiValueEvaluator : ValueEvaluator() { private fun isSimpleForLoop(node: Node): Boolean { // Are we in the for statement somehow? - var forStatement = node.astParent as? ForStatement - if (forStatement == null) forStatement = node.astParent?.astParent as? ForStatement + var forStatement = node.astParentLegacy as? ForStatement + if (forStatement == null) forStatement = node.astParentLegacy?.astParentLegacy as? ForStatement if (forStatement == null) return false // ...no, we're not. @@ -268,20 +268,20 @@ class MultiValueEvaluator : ValueEvaluator() { forStatement.initializerStatement == node || // The node is the initialization (initializerDecl != null && initializerDecl == - node.astParent) || // The parent of the node is the initializer of the loop + node.astParentLegacy) || // The parent of the node is the initializer of the loop // variable forStatement.iterationStatement == node || // The node or its parent are the iteration statement of the loop - forStatement.iterationStatement == node.astParent + forStatement.iterationStatement == node.astParentLegacy } private fun handleSimpleLoopVariable(expr: Reference, depth: Int): Collection { val loop = - expr.prevDFG.firstOrNull { it.astParent is ForStatement }?.astParent as? ForStatement + expr.prevDFG.firstOrNull { it.astParentLegacy is ForStatement }?.astParentLegacy as? ForStatement ?: expr.prevDFG - .firstOrNull { it.astParent?.astParent is ForStatement } - ?.astParent - ?.astParent as? ForStatement + .firstOrNull { it.astParentLegacy?.astParentLegacy is ForStatement } + ?.astParentLegacy + ?.astParentLegacy as? ForStatement if (loop == null || loop.condition !is BinaryOperator) return setOf() var loopVar: Any? = diff --git a/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/fsm/DFAOrderEvaluator.kt b/cpg-analysis/src/main/kotlin/de/fraunhofer/aisec/cpg/analysis/fsm/DFAOrderEvaluator.kt index 27476e882c..13f6dc4146 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 @@ -33,7 +33,7 @@ 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.MemberCallExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference -import de.fraunhofer.aisec.cpg.passes.astParent +import de.fraunhofer.aisec.cpg.passes.astParentLegacy import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -304,7 +304,7 @@ open class DFAOrderEvaluator( fun getBaseOfNode(node: CallExpression) = when { node is MemberCallExpression -> node.base - node is ConstructExpression -> node.astParent?.getSuitableDFGTarget() + node is ConstructExpression -> node.astParentLegacy?.getSuitableDFGTarget() node.thisPosition != null -> node.getBaseOfCallExpressionUsingArgument(node.thisPosition!!) else -> { 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 54deee38d8..ee96ca3cca 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 @@ -40,7 +40,7 @@ import de.fraunhofer.aisec.cpg.graph.statements.WhileStatement 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 +import de.fraunhofer.aisec.cpg.passes.astParentLegacy import kotlin.math.absoluteValue /** @@ -694,7 +694,7 @@ fun Node.controlledBy(): List { val result = mutableListOf() var checkedNode: Node? = this while (checkedNode !is FunctionDeclaration) { - checkedNode = checkedNode?.astParent + checkedNode = checkedNode?.astParentLegacy if (checkedNode == null) { break } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Node.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Node.kt index 01fdd695e2..3c3df12481 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Node.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Node.kt @@ -165,6 +165,9 @@ abstract class Node : var astChildren: List = listOf() get() = SubgraphWalker.getAstChildren(this) + @Transient + var astParent: Node? = null + /** Virtual property for accessing [prevEOGEdges] without property edges. */ @PopulatedByPass(EvaluationOrderGraphPass::class) var prevEOG by unwrapping(Node::prevEOGEdges) diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/edges/ast/AstEdge.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/edges/ast/AstEdge.kt index 7f3663746c..25b1e420e6 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/edges/ast/AstEdge.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/edges/ast/AstEdge.kt @@ -28,14 +28,13 @@ package de.fraunhofer.aisec.cpg.graph.edges.ast import de.fraunhofer.aisec.cpg.graph.Node import de.fraunhofer.aisec.cpg.graph.edges.Edge import de.fraunhofer.aisec.cpg.graph.edges.collections.EdgeList -import de.fraunhofer.aisec.cpg.graph.edges.collections.EdgeSingletonList import org.neo4j.ogm.annotation.* /** This property edge describes a parent/child relationship in the Abstract Syntax Tree (AST). */ @RelationshipEntity open class AstEdge : Edge { constructor(start: Node, end: T) : super(start, end) { - // In a future PR, we will set the astParent here + end.astParent = start } } @@ -47,17 +46,6 @@ fun Node.astEdgesOf( return AstEdges(this, postAdd, postRemove) } -fun Node.astEdgeOf( - of: NodeType, -): EdgeSingletonList> { - return EdgeSingletonList>( - thisRef = this, - init = ::AstEdge, - outgoing = true, - of = of - ) -} - /** This property edge list describes elements that are AST children of a node. */ open class AstEdges>( thisRef: Node, diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/EdgeCachePass.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/EdgeCachePass.kt index 3d97fca01d..779e5ebfa9 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/EdgeCachePass.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/EdgeCachePass.kt @@ -144,7 +144,7 @@ class EdgeCachePass(ctx: TranslationContext) : ComponentPass(ctx) { } } -val Node.astParent: Node? +val Node.astParentLegacy: Node? get() { return Edges.to(this, EdgeType.AST).firstOrNull()?.source } diff --git a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/ControlFlowSensitiveDFGPassTest.kt b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/ControlFlowSensitiveDFGPassTest.kt index 52e4ea72f7..e2dc637781 100644 --- a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/ControlFlowSensitiveDFGPassTest.kt +++ b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/ControlFlowSensitiveDFGPassTest.kt @@ -87,13 +87,13 @@ class ControlFlowSensitiveDFGPassTest { val baseOfMemberRead11 = assertNotNull(next.firstOrNull()?.end) assertEquals(11, baseOfMemberRead11.location?.region?.startLine) assertIs(baseOfMemberRead11) - assertIs(baseOfMemberRead11.astParent) + assertIs(baseOfMemberRead11.astParentLegacy) assertEquals(AccessValues.READ, baseOfMemberRead11.access) val baseOfMemberWrite13 = assertNotNull(next.getOrNull(1)?.end) assertEquals(13, baseOfMemberWrite13.location?.region?.startLine) assertIs(baseOfMemberWrite13) - assertIs(baseOfMemberWrite13.astParent) + assertIs(baseOfMemberWrite13.astParentLegacy) assertEquals( AccessValues.READ, baseOfMemberWrite13.access @@ -180,7 +180,7 @@ class ControlFlowSensitiveDFGPassTest { val single = assertNotNull(next.singleOrNull()?.end) assertEquals(14, single.location?.region?.startLine) assertIs(single) - val me = assertIs(single.astParent) + val me = assertIs(single.astParentLegacy) assertEquals(AccessValues.WRITE, me.access) // The rest should be the same as s1, so we can probably skip the rest of the asserts diff --git a/cpg-language-jvm/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/jvm/JVMLanguageFrontendTest.kt b/cpg-language-jvm/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/jvm/JVMLanguageFrontendTest.kt index 2577a63de9..f8de73fe82 100644 --- a/cpg-language-jvm/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/jvm/JVMLanguageFrontendTest.kt +++ b/cpg-language-jvm/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/jvm/JVMLanguageFrontendTest.kt @@ -30,7 +30,7 @@ import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.statements.expressions.* import de.fraunhofer.aisec.cpg.graph.types.PointerType import de.fraunhofer.aisec.cpg.passes.EdgeCachePass -import de.fraunhofer.aisec.cpg.passes.astParent +import de.fraunhofer.aisec.cpg.passes.astParentLegacy import de.fraunhofer.aisec.cpg.test.analyze import de.fraunhofer.aisec.cpg.test.analyzeAndGetFirstTU import de.fraunhofer.aisec.cpg.test.assertFullName @@ -139,7 +139,7 @@ class JVMLanguageFrontendTest { // All references (which are not part of a call) and not to the stdlib should be resolved val refs = tu.refs refs - .filter { it.astParent !is CallExpression } + .filter { it.astParentLegacy !is CallExpression } .filter { !it.name.startsWith("java.") } .forEach { val refersTo = it.refersTo