Skip to content

Commit

Permalink
Removes handling of break, continue and throw from scopes (#1788)
Browse files Browse the repository at this point in the history
  • Loading branch information
konradweiss authored Oct 18, 2024
1 parent c9fa0e5 commit 39ef4cf
Show file tree
Hide file tree
Showing 7 changed files with 399 additions and 394 deletions.
68 changes: 4 additions & 64 deletions cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/ScopeManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -468,71 +468,11 @@ class ScopeManager : ScopeProvider {
}

/**
* This function SHOULD only be used by the
* [de.fraunhofer.aisec.cpg.passes.EvaluationOrderGraphPass] while building up the EOG. It adds
* a [BreakStatement] to the list of break statements of the current "breakable" scope.
* This function retrieves the [LabelStatement] associated with the [labelString]. This depicts
* the feature of some languages to attach a label to a point in the source code and use it as
* the target for control flow manipulation, e.g. [BreakStatement], [GotoStatement].
*/
fun addBreakStatement(breakStatement: BreakStatement) {
if (breakStatement.label == null) {
val scope = firstScopeOrNull { scope: Scope? -> scope?.isBreakable() == true }
if (scope == null) {
Util.errorWithFileLocation(
breakStatement,
LOGGER,
"Break inside of unbreakable scope. The break will be ignored, but may lead " +
"to an incorrect graph. The source code is not valid or incomplete."
)
return
}
(scope as Breakable).addBreakStatement(breakStatement)
} else {
val labelStatement = getLabelStatement(breakStatement.label)
labelStatement?.subStatement?.let {
val scope = lookupScope(it)
(scope as Breakable?)?.addBreakStatement(breakStatement)
}
}
}

/**
* This function SHOULD only be used by the
* [de.fraunhofer.aisec.cpg.passes.EvaluationOrderGraphPass] while building up the EOG. It adds
* a [ContinueStatement] to the list of continue statements of the current "continuable" scope.
*/
fun addContinueStatement(continueStatement: ContinueStatement) {
if (continueStatement.label == null) {
val scope = firstScopeOrNull { scope: Scope? -> scope?.isContinuable() == true }
if (scope == null) {
LOGGER.error(
"Continue inside of not continuable scope. The continue will be ignored, but may lead " +
"to an incorrect graph. The source code is not valid or incomplete."
)
return
}
(scope as Continuable).addContinueStatement(continueStatement)
} else {
val labelStatement = getLabelStatement(continueStatement.label)
labelStatement?.subStatement?.let {
val scope = lookupScope(it)
(scope as Continuable?)?.addContinueStatement(continueStatement)
}
}
}

/**
* This function SHOULD only be used by the
* [de.fraunhofer.aisec.cpg.passes.EvaluationOrderGraphPass] while building up the EOG. It adds
* a [LabelStatement] to the list of label statements of the current scope.
*/
fun addLabelStatement(labelStatement: LabelStatement) {
currentScope?.addLabelStatement(labelStatement)
}

/**
* This function is internal to the scope manager and primarily used by [addBreakStatement] and
* [addContinueStatement]. It retrieves the [LabelStatement] associated with the [labelString].
*/
private fun getLabelStatement(labelString: String?): LabelStatement? {
fun getLabelStatement(labelString: String?): LabelStatement? {
if (labelString == null) return null
var labelStatement: LabelStatement?
var searchScope = currentScope
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,31 @@ val Node?.returns: List<ReturnStatement>
val Node?.assigns: List<AssignExpression>
get() = this.allChildren()

/**
* This function tries to find the first parent node that satisfies the condition specified in
* [predicate]. It starts searching in the [searchNode], moving up-wards using the [Node.astParent]
* attribute.
*
* @param searchNode the child node that we start the search from
* @param predicate the search predicate
*/
fun Node.firstParentOrNull(predicate: (Node) -> Boolean): Node? {

// start at searchNodes parent
var node: Node? = this.astParent

while (node != null) {
if (predicate(node)) {
return node
}

// go up-wards in the ast tree
node = node.astParent
}

return null
}

/**
* Return all [ProblemNode] children in this graph (either stored directly or in
* [Node.additionalProblems]), starting with this [Node].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@
*/
package de.fraunhofer.aisec.cpg.graph.scopes

import de.fraunhofer.aisec.cpg.graph.Node
import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration
import de.fraunhofer.aisec.cpg.graph.types.Type

class FunctionScope(astNode: FunctionDeclaration) : ValueDeclarationScope(astNode) {
@Transient var catchesOrRelays = mutableMapOf<Type, MutableList<Node>>()
}
class FunctionScope(astNode: FunctionDeclaration) : ValueDeclarationScope(astNode) {}
Original file line number Diff line number Diff line change
Expand Up @@ -25,70 +25,11 @@
*/
package de.fraunhofer.aisec.cpg.graph.scopes

import de.fraunhofer.aisec.cpg.graph.Node
import de.fraunhofer.aisec.cpg.graph.statements.*
import de.fraunhofer.aisec.cpg.helpers.SubgraphWalker
import org.slf4j.LoggerFactory

class LoopScope(loopStatement: Statement) :
ValueDeclarationScope(loopStatement), Breakable, Continuable {
/**
* Statements that constitute the start of the Loop depending on the used pass, mostly of size 1
*/
val starts: List<Node>
get() =
when (val loopStatement = astNode) {
is WhileStatement -> {
if (loopStatement.conditionDeclaration != null)
SubgraphWalker.getEOGPathEdges(loopStatement.conditionDeclaration).entries
else if (loopStatement.condition != null)
SubgraphWalker.getEOGPathEdges(loopStatement.condition).entries
else SubgraphWalker.getEOGPathEdges(loopStatement.statement).entries
}
is ForStatement -> {
if (loopStatement.conditionDeclaration != null)
SubgraphWalker.getEOGPathEdges(loopStatement.conditionDeclaration).entries
else if (loopStatement.condition != null)
SubgraphWalker.getEOGPathEdges(loopStatement.condition).entries
else SubgraphWalker.getEOGPathEdges(loopStatement.statement).entries
}
is ForEachStatement -> {
SubgraphWalker.getEOGPathEdges(loopStatement).entries
}
is DoStatement -> {
SubgraphWalker.getEOGPathEdges(loopStatement.statement).entries
}
else -> {
LOGGER.error(
"Currently the component {} is not supported as loop scope.",
astNode?.javaClass
)
ArrayList()
}
}

/** Statements that constitute the start of the Loop condition evaluation, mostly of size 1 */
val conditions: List<Node>
get() =
when (val node = astNode) {
is WhileStatement ->
mutableListOf(node.condition, node.conditionDeclaration).filterNotNull()
is ForStatement -> mutableListOf(node.condition).filterNotNull()
is ForEachStatement -> mutableListOf(node.variable).filterNotNull()
is DoStatement -> mutableListOf(node.condition).filterNotNull()
is AssertStatement -> mutableListOf(node.condition).filterNotNull()
null -> {
LOGGER.error("Ast node of loop scope is null.")
mutableListOf()
}
else -> {
LOGGER.error(
"Currently the component {} is not supported as loop scope.",
node.javaClass
)
mutableListOf()
}
}

private val breaks = mutableListOf<BreakStatement>()
private val continues = mutableListOf<ContinueStatement>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,8 @@ package de.fraunhofer.aisec.cpg.graph.scopes

import de.fraunhofer.aisec.cpg.graph.Node
import de.fraunhofer.aisec.cpg.graph.statements.BreakStatement
import de.fraunhofer.aisec.cpg.graph.types.Type

class TryScope(astNode: Node?) : ValueDeclarationScope(astNode), Breakable {
@Transient val catchesOrRelays = mutableMapOf<Type, MutableList<Node>>()

private val breaks = mutableListOf<BreakStatement>()

Expand Down
Loading

0 comments on commit 39ef4cf

Please sign in to comment.