Skip to content

Commit

Permalink
Minor fixes to the broken EOG
Browse files Browse the repository at this point in the history
  • Loading branch information
KuechA committed Sep 12, 2023
1 parent 5c7b07d commit 8773b83
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,14 @@ import de.fraunhofer.aisec.cpg.ScopeManager
import de.fraunhofer.aisec.cpg.frontends.LanguageFrontend
import de.fraunhofer.aisec.cpg.graph.AST
import de.fraunhofer.aisec.cpg.graph.Node
import de.fraunhofer.aisec.cpg.graph.allChildren
import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration
import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdge
import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdge.Companion.checkForPropertyEdge
import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdge.Companion.unwrap
import de.fraunhofer.aisec.cpg.graph.statements.expressions.ConstructExpression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.LambdaExpression
import de.fraunhofer.aisec.cpg.passes.ResolutionStartHolder
import de.fraunhofer.aisec.cpg.processing.strategy.Strategy
import java.lang.annotation.AnnotationFormatError
import java.lang.reflect.Field
Expand Down Expand Up @@ -316,7 +320,36 @@ object SubgraphWalker {
Consumer { c: BiConsumer<Node, Node?> -> c.accept(current, parent) }
)
val unseenChildren =
strategy(current).asSequence().filter { it !in seen }.toList()
strategy(current).asSequence().filter { it !in seen }.toMutableList()

if (
strategy == Strategy::EOG_FORWARD &&
current is LambdaExpression &&
current.function?.let { it !in unseenChildren } == true
) {
// Check if there are AST children which aren't reachable through the
// EOG. If so, add them to the unseenChildren.
unseenChildren.addAll(
current.function
.allChildren<ResolutionStartHolder>()
.flatMap { it.resolutionStartNodes }
.toSet()
)
}

if (
strategy == Strategy::EOG_FORWARD &&
current is ConstructExpression &&
current.anoymousClass != null
) {
unseenChildren.addAll(
current.anoymousClass
.allChildren<ResolutionStartHolder>()
.flatMap { it.resolutionStartNodes }
.toSet()
)
}

seen.addAll(unseenChildren)
unseenChildren.asReversed().forEach { child: Node ->
(todo as ArrayDeque<Pair<Node, Node?>>).push(Pair(child, current))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa

/**
* Removes EOG edges by first building the negative set of nodes that cannot be visited and then
* remove there outgoing edges. This also removes cycles.
* remove their outgoing edges. This also removes cycles.
*/
protected fun removeUnreachableEOGEdges(tu: TranslationUnitDeclaration) {
// All nodes which have an eog edge
Expand All @@ -200,9 +200,11 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa
}
.toSet()
// Remove all nodes from eogNodes which are reachable from validStarts and transitively.
val alreadySeen = IdentitySet<Node>()
while (validStarts.isNotEmpty()) {
eogNodes.removeAll(validStarts)
validStarts = validStarts.flatMap { it.nextEOG }.filter { it in eogNodes }.toSet()
validStarts = validStarts.flatMap { it.nextEOG }.filter { it !in alreadySeen }.toSet()
alreadySeen.addAll(validStarts)
}
// The remaining nodes are unreachable from the entry points. We delete their outgoing EOG
// edges.
Expand All @@ -211,7 +213,7 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa
next.end.removePrevEOGEntry(unvisitedNode)
}

unvisitedNode.nextEOGEdges.clear()
unvisitedNode.clearNextEOG()
}
}

Expand Down Expand Up @@ -521,8 +523,13 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa
// Handle left hand side(s) first
node.lhs.forEach { createEOG(it) }

// Then the right side(s)
node.rhs.forEach { createEOG(it) }
// Then the right side(s). Avoid creating the EOG twice if it's already part of the
// initializer of a declaration
node.rhs.forEach {
if (it !in node.declarations.map { decl -> decl.initializer }) {
createEOG(it)
}
}

pushToEOG(node)
}
Expand Down Expand Up @@ -739,6 +746,28 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa
createEOG(arg)
}
pushToEOG(node)

if (node.anoymousClass != null) {
// Generate the EOG inside the anonymous class. It's not linked to the EOG of the outer
// part.
val tmpCurrentEOG = currentPredecessors.toMutableList()
val tmpCurrentProperties = nextEdgeProperties.toMutableMap()
val tmpIntermediateNodes = intermediateNodes.toMutableList()

nextEdgeProperties.clear()
currentPredecessors.clear()
intermediateNodes.clear()

createEOG(node.anoymousClass)

nextEdgeProperties.clear()
currentPredecessors.clear()
intermediateNodes.clear()

nextEdgeProperties.putAll(tmpCurrentProperties)
currentPredecessors.addAll(tmpCurrentEOG)
intermediateNodes.addAll(tmpIntermediateNodes)
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ import de.fraunhofer.aisec.cpg.passes.order.ExecuteBefore
* [CallResolver] and convert certain [CallExpression] nodes into a [CastExpression].
*/
@ExecuteBefore(SymbolResolver::class)
@ExecuteBefore(EvaluationOrderGraphPass::class)
@ExecuteBefore(DFGPass::class)
class GoExtraPass(ctx: TranslationContext) : ComponentPass(ctx), ScopeProvider {

Expand Down Expand Up @@ -177,7 +178,7 @@ class GoExtraPass(ctx: TranslationContext) : ComponentPass(ctx), ScopeProvider {
// And try to resolve it
val ref = scopeManager.resolveReference(expr)
if (ref == null) {
// We need to implicitly declare it, if its not declared before.
// We need to implicitly declare it, if it's not declared before.
val decl = newVariableDeclaration(expr.name, expr.autoType())
decl.location = expr.location
decl.isImplicit = true
Expand Down

0 comments on commit 8773b83

Please sign in to comment.