Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Adding new Overlay and Concept nodes to the graph. #1897

Merged
merged 16 commits into from
Dec 17, 2024
Merged
27 changes: 18 additions & 9 deletions cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Node.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,16 @@ import de.fraunhofer.aisec.cpg.TranslationContext
import de.fraunhofer.aisec.cpg.TypeManager
import de.fraunhofer.aisec.cpg.frontends.Handler
import de.fraunhofer.aisec.cpg.frontends.Language
import de.fraunhofer.aisec.cpg.graph.declarations.*
import de.fraunhofer.aisec.cpg.graph.edges.*
import de.fraunhofer.aisec.cpg.graph.declarations.MethodDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.TranslationUnitDeclaration
import de.fraunhofer.aisec.cpg.graph.edges.ast.astEdgesOf
import de.fraunhofer.aisec.cpg.graph.edges.flows.ControlDependences
import de.fraunhofer.aisec.cpg.graph.edges.flows.Dataflows
import de.fraunhofer.aisec.cpg.graph.edges.flows.EvaluationOrders
import de.fraunhofer.aisec.cpg.graph.edges.flows.FullDataflowGranularity
import de.fraunhofer.aisec.cpg.graph.edges.flows.ProgramDependences
import de.fraunhofer.aisec.cpg.graph.scopes.*
import de.fraunhofer.aisec.cpg.graph.edges.flows.*
import de.fraunhofer.aisec.cpg.graph.edges.overlay.*
import de.fraunhofer.aisec.cpg.graph.edges.unwrapping
import de.fraunhofer.aisec.cpg.graph.scopes.GlobalScope
import de.fraunhofer.aisec.cpg.graph.scopes.RecordScope
import de.fraunhofer.aisec.cpg.graph.scopes.Scope
import de.fraunhofer.aisec.cpg.helpers.SubgraphWalker
import de.fraunhofer.aisec.cpg.helpers.neo4j.LocationConverter
import de.fraunhofer.aisec.cpg.helpers.neo4j.NameConverter
Expand All @@ -52,7 +53,10 @@ import java.util.*
import kotlin.uuid.Uuid
import org.apache.commons.lang3.builder.ToStringBuilder
import org.apache.commons.lang3.builder.ToStringStyle
import org.neo4j.ogm.annotation.*
import org.neo4j.ogm.annotation.GeneratedValue
import org.neo4j.ogm.annotation.Id
import org.neo4j.ogm.annotation.Relationship
import org.neo4j.ogm.annotation.Transient
import org.neo4j.ogm.annotation.typeconversion.Convert
import org.slf4j.Logger
import org.slf4j.LoggerFactory
Expand Down Expand Up @@ -274,6 +278,11 @@ abstract class Node :
*/
val additionalProblems: MutableSet<ProblemNode> = mutableSetOf()

@Relationship(value = "OVERLAY", direction = Relationship.Direction.OUTGOING)
val overlayEdges: Overlays =
Overlays(this, mirrorProperty = OverlayNode::underlyingNodeEdge, outgoing = true)
var overlays by unwrapping(Node::overlayEdges)

/**
* If a node should be removed from the graph, just removing it from the AST is not enough (see
* issue #60). It will most probably be referenced somewhere via DFG or EOG edges. Thus, if it
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2024, 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

import de.fraunhofer.aisec.cpg.graph.edges.overlay.OverlaySingleEdge
import de.fraunhofer.aisec.cpg.graph.edges.unwrapping
import org.neo4j.ogm.annotation.Relationship

/**
* Represents an extra node added to the CPG. These nodes can live next to the regular nodes,
* typically having shared edges to extend the original graph.
*/
abstract class OverlayNode() : Node() {
@Relationship(value = "OVERLAY", direction = Relationship.Direction.INCOMING)
/** All [OverlayNode]s nodes are connected to an original cpg [Node] by this. */
val underlyingNodeEdge: OverlaySingleEdge =
OverlaySingleEdge(
this,
of = null,
mirrorProperty = Node::overlayEdges,
outgoing = false,
)
var underlyingNode by unwrapping(OverlayNode::underlyingNodeEdge)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2024, 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.concepts

import de.fraunhofer.aisec.cpg.graph.OverlayNode

/**
* Represents a new concept added to the CPG. This is intended for modelling "concepts" like
* logging, files, databases. The relevant operations on this concept are modeled as [Operation]s
* and stored in [ops].
*/
abstract class Concept<T : Operation>() : OverlayNode() {
/** All [Operation]s belonging to this concept. */
val ops: MutableSet<T> = mutableSetOf()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2024, 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.concepts

import de.fraunhofer.aisec.cpg.graph.OverlayNode

/**
* Represents an operation executed on/with a [Concept] (stored in [concept]). This is typically a
* `write` on a file or log object or an `execute` on a database.
*/
abstract class Operation(
/** The [Concept] this operation belongs to. */
val concept: Concept<*>
) : OverlayNode()
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ import org.neo4j.ogm.annotation.Transient
*
* Therefore, we need to wrap the edge in a list with a single element.
*/
class EdgeSingletonList<NodeType : Node, NullableNodeType : NodeType?, EdgeType : Edge<NodeType>>(
open class EdgeSingletonList<
konradweiss marked this conversation as resolved.
Show resolved Hide resolved
NodeType : Node,
NullableNodeType : NodeType?,
EdgeType : Edge<NodeType>
>(
override var thisRef: Node,
override var init: (Node, NodeType) -> EdgeType,
var onChanged: ((old: EdgeType?, new: EdgeType?) -> Unit)? = null,
Expand Down Expand Up @@ -71,7 +75,15 @@ class EdgeSingletonList<NodeType : Node, NullableNodeType : NodeType?, EdgeType
}

override fun add(element: EdgeType): Boolean {
throw UnsupportedOperationException()
if (this.element == null) {
this.element = element
onChanged?.invoke(null, this.element)
return true
} else {
throw UnsupportedOperationException(
"We cannot 'add' to a singleton edge list, that is already populated"
)
}
}

override fun addAll(elements: Collection<EdgeType>): Boolean {
Expand Down Expand Up @@ -151,6 +163,13 @@ class EdgeSingletonList<NodeType : Node, NullableNodeType : NodeType?, EdgeType
@Suppress("UNCHECKED_CAST") init(node, thisRef as NodeType)
}
onChanged?.invoke(old, this.element)

val element = this.element
if (element != null) {
handleOnAdd(element)
} else if (old != null) {
handleOnRemove(old)
}
}

fun <ThisType : Node> delegate(): UnwrapDelegate<ThisType> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright (c) 2024, 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.edges.overlay

import de.fraunhofer.aisec.cpg.graph.Node
import de.fraunhofer.aisec.cpg.graph.edges.Edge
import de.fraunhofer.aisec.cpg.graph.edges.collections.EdgeSet
import de.fraunhofer.aisec.cpg.graph.edges.collections.EdgeSingletonList
import de.fraunhofer.aisec.cpg.graph.edges.collections.MirroredEdgeCollection
import kotlin.reflect.KProperty

/**
* Represents an edge in a graph specifically used for overlay purposes.
*
* @param start The starting node of the edge.
* @param end The ending node of the edge.
* @constructor Constructs an [OverlayEdge] with a specified [start] and [end] node.
* @property labels A predefined set of labels associated with the OverlayEdge. By default, it is
* initialized with the label "OVERLAY".
*/
class OverlayEdge(start: Node, end: Node) : Edge<Node>(start, end) {
override var labels: Set<String> = setOf("OVERLAY")
}

/**
* Represents a single edge in an overlay graph structure, linking nodes with specific properties.
*
* @param thisRef The current node that the edge originates from or is associated with.
* @param of The optional target node of the edge.
* @param mirrorProperty The property representing a mutable collection of mirrored overlay edges.
* @param outgoing A flag indicating whether the edge is outgoing (default is true).
* @constructor Initializes the [OverlaySingleEdge] instance with the provided parameters.
*/
class OverlaySingleEdge(
thisRef: Node,
of: Node?,
override var mirrorProperty: KProperty<MutableCollection<OverlayEdge>>,
outgoing: Boolean = true,
) :
EdgeSingletonList<Node, Node?, OverlayEdge>(
thisRef = thisRef,
init = ::OverlayEdge,
outgoing = outgoing,
of = of,
),
MirroredEdgeCollection<Node, OverlayEdge>

/**
* Represents a collection of overlay edges connected to a specific node. This class is used to
* manage and define relationships between nodes through overlay edges, providing both outgoing and
* incoming edge handling capabilities.
*
* @param thisRef The reference node that the overlays are associated with.
* @param mirrorProperty A reference to a property that mirrors the collection of overlay edges.
* @param outgoing A boolean indicating whether the edges managed by this collection are outgoing.
* @constructor Initializes the [Overlays] object with a reference node, a property for edge
* mirroring, and a direction to specify outgoing or incoming edges.
*/
class Overlays(
thisRef: Node,
override var mirrorProperty: KProperty<MutableCollection<OverlayEdge>>,
outgoing: Boolean,
) :
EdgeSet<Node, OverlayEdge>(thisRef = thisRef, init = ::OverlayEdge, outgoing = outgoing),
MirroredEdgeCollection<Node, OverlayEdge>
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class TestCommon {
"DFG",
"EOG",
"LANGUAGE",
"OVERLAY",
"OVERRIDES",
"PARAMETERS",
"PDG",
Expand All @@ -91,6 +92,7 @@ class TestCommon {
"DFG",
"EOG",
"LANGUAGE",
"OVERLAY",
"PDG",
"SCOPE",
),
Expand Down
Loading
Loading