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 e24ce7ff18..c2e429edfd 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 @@ -107,7 +107,7 @@ fun MetadataProvider.newOperatorDeclaration( operatorCode: String, recordDeclaration: RecordDeclaration? = null, rawNode: Any? = null -): MethodDeclaration { +): OperatorDeclaration { val node = OperatorDeclaration() node.applyMetadata(this, name, rawNode, defaultNamespace = recordDeclaration?.name) diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/helpers/SubgraphWalker.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/helpers/SubgraphWalker.kt index 4960d1677c..e5821b00d7 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/helpers/SubgraphWalker.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/helpers/SubgraphWalker.kt @@ -346,8 +346,26 @@ object SubgraphWalker { } } +/** + * Tries to replace the [old] expression with a [new] one, given the [parent]. + * + * There are two things to consider: + * - First, this only works if [parent] is either an [ArgumentHolder] or [StatementHolder]. + * Otherwise, we cannot instruct the parent to exchange the node + * - Second, since exchanging the node has influence on their edges (such as EOG, DFG, etc.), we + * only support a replacement very early in the pass system. To be specific, we only allow + * replacement before any DFG edges are set. We are re-wiring EOG edges, but nothing else. If one + * tries to replace a node with existing [Node.nextDFG] or [Node.prevDFG], we fail. + */ context(ContextProvider) fun SubgraphWalker.ScopedWalker.replace(parent: Node?, old: Expression, new: Expression): Boolean { + // We do not allow to replace nodes where the DFG (or other dependent nodes, such as PDG have + // been set). The reason for that is that these edges contain a lot of information on the edges + // themselves and replacing this edge would be very complicated. + if (old.prevDFG.isNotEmpty() || old.nextDFG.isNotEmpty()) { + return false + } + val success = when (parent) { is ArgumentHolder -> parent.replace(old, new) @@ -359,13 +377,12 @@ fun SubgraphWalker.ScopedWalker.replace(parent: Node?, old: Expression, new: Exp return false } } - if (!success) { Pass.log.error( "Replacing expression $old was not successful. Further analysis might not be entirely accurate." ) } else { - // Store any eventual EOG nodes and disconnect old node + // Store any eventual EOG/DFG nodes and disconnect old node val oldPrevEOG = old.prevEOG.toMutableList() val oldNextEOG = old.nextEOG.toMutableList() old.disconnectFromGraph() diff --git a/cpg-language-python/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/python/StatementHandler.kt b/cpg-language-python/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/python/StatementHandler.kt index 48532c8c1e..4b874063be 100644 --- a/cpg-language-python/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/python/StatementHandler.kt +++ b/cpg-language-python/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/python/StatementHandler.kt @@ -39,6 +39,7 @@ import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression import de.fraunhofer.aisec.cpg.graph.statements.expressions.MemberExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.ProblemExpression import de.fraunhofer.aisec.cpg.graph.types.FunctionType +import de.fraunhofer.aisec.cpg.helpers.Util import kotlin.collections.plusAssign class StatementHandler(frontend: PythonLanguageFrontend) : @@ -300,12 +301,22 @@ class StatementHandler(frontend: PythonLanguageFrontend) : rawNode = s ) } else if (language is HasOperatorOverloading && s.name.isKnownOperatorName) { - newOperatorDeclaration( - name = s.name, - recordDeclaration = recordDeclaration, - operatorCode = language.operatorCodeFor(s.name) ?: "", - rawNode = s - ) + var decl = + newOperatorDeclaration( + name = s.name, + recordDeclaration = recordDeclaration, + operatorCode = language.operatorCodeFor(s.name) ?: "", + rawNode = s + ) + if (decl.operatorCode == "") { + Util.warnWithFileLocation( + decl, + log, + "Could not find operator code for operator {}. This will most likely result in a failure", + s.name + ) + } + decl } else { newMethodDeclaration( name = s.name,