Skip to content

Commit

Permalink
Improved property edges
Browse files Browse the repository at this point in the history
This PR adds major improvements to property edges
  • Loading branch information
oxisto committed Aug 4, 2024
1 parent bfedc3d commit b29ff80
Show file tree
Hide file tree
Showing 90 changed files with 1,978 additions and 1,473 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ package de.fraunhofer.aisec.cpg.analysis.fsm
import de.fraunhofer.aisec.cpg.graph.Node
import de.fraunhofer.aisec.cpg.graph.declarations.ParameterDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.VariableDeclaration
import de.fraunhofer.aisec.cpg.graph.edge.Properties
import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdge
import de.fraunhofer.aisec.cpg.graph.statements.ReturnStatement
import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.ConstructExpression
Expand Down Expand Up @@ -435,14 +433,12 @@ open class DFAOrderEvaluator(
val outNodes = mutableListOf<Node>()
outNodes +=
if (eliminateUnreachableCode) {
PropertyEdge.unwrap(
node.nextEOGEdges.filter { e -> e.getProperty(Properties.UNREACHABLE) != true }
)
node.nextEOGEdges.filter { e -> e.unreachable != true }.map { it.end }
} else {
node.nextEOG
}

if (outNodes.size == 1 && node.nextEOG.size == 1) {
if (outNodes.size == 1 && node.nextEOGEdges.size == 1) {
// We only have one node following this node, so we
// simply propagate the current eogPath to the next node.
outNodes[0].addEogPath(eogPath)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,16 @@ import de.fraunhofer.aisec.cpg.analysis.ValueEvaluator
import de.fraunhofer.aisec.cpg.graph.Node
import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.TranslationUnitDeclaration
import de.fraunhofer.aisec.cpg.graph.edge.Properties
import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdge
import de.fraunhofer.aisec.cpg.graph.edge.flows.EvaluationOrder
import de.fraunhofer.aisec.cpg.graph.statements.IfStatement
import de.fraunhofer.aisec.cpg.graph.statements.WhileStatement
import de.fraunhofer.aisec.cpg.helpers.*
import de.fraunhofer.aisec.cpg.passes.configuration.DependsOn

/**
* A [Pass] which uses a simple logic to determine constant values and mark unreachable code regions
* by setting the [Properties.UNREACHABLE] property of an eog-edge to true.
* by setting the [EvaluationOrder.unreachable] property to true.
*/
@DependsOn(ControlFlowSensitiveDFGPass::class)
class UnreachableEOGPass(ctx: TranslationContext) : TranslationUnitPass(ctx) {
Expand Down Expand Up @@ -68,7 +68,7 @@ class UnreachableEOGPass(ctx: TranslationContext) : TranslationUnitPass(ctx) {

for ((key, value) in finalState) {
if (value.elements == Reachability.UNREACHABLE) {
key.addProperty(Properties.UNREACHABLE, true)
(key as? EvaluationOrder)?.unreachable = true
}
}
}
Expand Down Expand Up @@ -126,13 +126,13 @@ private fun handleIfStatement(
val (unreachableEdge, remainingEdges) =
if (evalResult is Boolean && evalResult == true) {
Pair(
n.nextEOGEdges.firstOrNull { e -> e.getProperty(Properties.INDEX) == 1 },
n.nextEOGEdges.filter { e -> e.getProperty(Properties.INDEX) != 1 }
n.nextEOGEdges.firstOrNull { e -> e.index == 1 },
n.nextEOGEdges.filter { e -> e.index != 1 }
)
} else if (evalResult is Boolean && evalResult == false) {
Pair(
n.nextEOGEdges.firstOrNull { e -> e.getProperty(Properties.INDEX) == 0 },
n.nextEOGEdges.filter { e -> e.getProperty(Properties.INDEX) != 0 }
n.nextEOGEdges.firstOrNull { e -> e.index == 0 },
n.nextEOGEdges.filter { e -> e.index != 0 }
)
} else {
Pair(null, n.nextEOGEdges)
Expand Down Expand Up @@ -173,13 +173,13 @@ private fun handleWhileStatement(
val (unreachableEdge, remainingEdges) =
if (evalResult is Boolean && evalResult == true) {
Pair(
n.nextEOGEdges.firstOrNull { e -> e.getProperty(Properties.INDEX) == 1 },
n.nextEOGEdges.filter { e -> e.getProperty(Properties.INDEX) != 1 }
n.nextEOGEdges.firstOrNull { e -> e.index == 1 },
n.nextEOGEdges.filter { e -> e.index != 1 }
)
} else if (evalResult is Boolean && evalResult == false) {
Pair(
n.nextEOGEdges.firstOrNull { e -> e.getProperty(Properties.INDEX) == 0 },
n.nextEOGEdges.filter { e -> e.getProperty(Properties.INDEX) != 0 }
n.nextEOGEdges.firstOrNull { e -> e.index == 0 },
n.nextEOGEdges.filter { e -> e.index != 0 }
)
} else {
Pair(null, n.nextEOGEdges)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ package de.fraunhofer.aisec.cpg.passes

import de.fraunhofer.aisec.cpg.graph.*
import de.fraunhofer.aisec.cpg.graph.declarations.TranslationUnitDeclaration
import de.fraunhofer.aisec.cpg.graph.edge.Properties
import de.fraunhofer.aisec.cpg.testcases.Passes
import kotlin.test.*
import org.junit.jupiter.api.BeforeAll
Expand All @@ -51,7 +50,7 @@ class UnreachableEOGPassTest {
assertNotNull(ifStatement)

for (edge in ifStatement.nextEOGEdges) {
assertFalse(edge.getProperty(Properties.UNREACHABLE) as Boolean)
assertFalse(edge.unreachable)
}
}

Expand All @@ -66,43 +65,43 @@ class UnreachableEOGPassTest {
// Check if the then-branch is set as reachable including all the edges until reaching the
// print
val thenDecl = ifStatement.nextEOGEdges[0]
assertFalse(thenDecl.getProperty(Properties.UNREACHABLE) as Boolean)
assertFalse(thenDecl.unreachable)
assertEquals(1, thenDecl.end.nextEOGEdges.size)
// The "++"
val incOp = thenDecl.end.nextEOGEdges[0]
assertFalse(incOp.getProperty(Properties.UNREACHABLE) as Boolean)
assertFalse(incOp.unreachable)
assertEquals(1, incOp.end.nextEOGEdges.size)
// The block
val thenCompound = incOp.end.nextEOGEdges[0]
assertFalse(thenCompound.getProperty(Properties.UNREACHABLE) as Boolean)
assertFalse(thenCompound.unreachable)
assertEquals(1, thenCompound.end.nextEOGEdges.size)
// There's the outgoing EOG edge to the statement after the branching
val thenExit = thenCompound.end.nextEOGEdges[0]
assertFalse(thenExit.getProperty(Properties.UNREACHABLE) as Boolean)
assertFalse(thenExit.unreachable)

// Check if the else-branch is set as unreachable including all the edges until reaching the
// print
val elseDecl = ifStatement.nextEOGEdges[1]
assertTrue(elseDecl.getProperty(Properties.UNREACHABLE) as Boolean)
assertTrue(elseDecl.unreachable)
assertEquals(1, elseDecl.end.nextEOGEdges.size)
// The "--"
val decOp = elseDecl.end.nextEOGEdges[0]
assertTrue(decOp.getProperty(Properties.UNREACHABLE) as Boolean)
assertTrue(decOp.unreachable)
assertEquals(1, decOp.end.nextEOGEdges.size)
// The block
val elseCompound = decOp.end.nextEOGEdges[0]
assertTrue(elseCompound.getProperty(Properties.UNREACHABLE) as Boolean)
assertTrue(elseCompound.unreachable)
assertEquals(1, elseCompound.end.nextEOGEdges.size)
// There's the outgoing EOG edge to the statement after the branching
val elseExit = elseCompound.end.nextEOGEdges[0]
assertTrue(elseExit.getProperty(Properties.UNREACHABLE) as Boolean)
assertTrue(elseExit.unreachable)

// After the branching, it's reachable again. Check that we found the merge node and that we
// continue with reachable edges.
assertEquals(thenExit.end, elseExit.end)
val mergeNode = thenExit.end
assertEquals(1, mergeNode.nextEOGEdges.size)
assertFalse(mergeNode.nextEOGEdges[0].getProperty(Properties.UNREACHABLE) as Boolean)
assertFalse(mergeNode.nextEOGEdges[0].unreachable)
}

@Test
Expand All @@ -113,8 +112,8 @@ class UnreachableEOGPassTest {
val ifStatement = method.ifs.firstOrNull()
assertNotNull(ifStatement)

assertFalse(ifStatement.nextEOGEdges[1].getProperty(Properties.UNREACHABLE) as Boolean)
assertTrue(ifStatement.nextEOGEdges[0].getProperty(Properties.UNREACHABLE) as Boolean)
assertFalse(ifStatement.nextEOGEdges[1].unreachable)
assertTrue(ifStatement.nextEOGEdges[0].unreachable)
}

@Test
Expand All @@ -125,8 +124,8 @@ class UnreachableEOGPassTest {
val ifStatement = method.ifs.firstOrNull()
assertNotNull(ifStatement)

assertFalse(ifStatement.nextEOGEdges[0].getProperty(Properties.UNREACHABLE) as Boolean)
assertTrue(ifStatement.nextEOGEdges[1].getProperty(Properties.UNREACHABLE) as Boolean)
assertFalse(ifStatement.nextEOGEdges[0].unreachable)
assertTrue(ifStatement.nextEOGEdges[1].unreachable)
}

@Test
Expand All @@ -137,8 +136,8 @@ class UnreachableEOGPassTest {
val ifStatement = method.ifs.firstOrNull()
assertNotNull(ifStatement)

assertFalse(ifStatement.nextEOGEdges[1].getProperty(Properties.UNREACHABLE) as Boolean)
assertTrue(ifStatement.nextEOGEdges[0].getProperty(Properties.UNREACHABLE) as Boolean)
assertFalse(ifStatement.nextEOGEdges[1].unreachable)
assertTrue(ifStatement.nextEOGEdges[0].unreachable)
}

@Test
Expand All @@ -149,8 +148,8 @@ class UnreachableEOGPassTest {
val whileStatement = method.whileLoops.firstOrNull()
assertNotNull(whileStatement)

assertFalse(whileStatement.nextEOGEdges[0].getProperty(Properties.UNREACHABLE) as Boolean)
assertTrue(whileStatement.nextEOGEdges[1].getProperty(Properties.UNREACHABLE) as Boolean)
assertFalse(whileStatement.nextEOGEdges[0].unreachable)
assertTrue(whileStatement.nextEOGEdges[1].unreachable)
}

@Test
Expand All @@ -161,8 +160,8 @@ class UnreachableEOGPassTest {
val whileStatement = method.whileLoops.firstOrNull()
assertNotNull(whileStatement)

assertFalse(whileStatement.nextEOGEdges[0].getProperty(Properties.UNREACHABLE) as Boolean)
assertFalse(whileStatement.nextEOGEdges[1].getProperty(Properties.UNREACHABLE) as Boolean)
assertFalse(whileStatement.nextEOGEdges[0].unreachable)
assertFalse(whileStatement.nextEOGEdges[1].unreachable)
}

@Test
Expand All @@ -173,8 +172,8 @@ class UnreachableEOGPassTest {
val whileStatement = method.whileLoops.firstOrNull()
assertNotNull(whileStatement)

assertFalse(whileStatement.nextEOGEdges[0].getProperty(Properties.UNREACHABLE) as Boolean)
assertTrue(whileStatement.nextEOGEdges[1].getProperty(Properties.UNREACHABLE) as Boolean)
assertFalse(whileStatement.nextEOGEdges[0].unreachable)
assertTrue(whileStatement.nextEOGEdges[1].unreachable)
}

@Test
Expand All @@ -185,8 +184,8 @@ class UnreachableEOGPassTest {
val whileStatement = method.whileLoops.firstOrNull()
assertNotNull(whileStatement)

assertFalse(whileStatement.nextEOGEdges[1].getProperty(Properties.UNREACHABLE) as Boolean)
assertTrue(whileStatement.nextEOGEdges[0].getProperty(Properties.UNREACHABLE) as Boolean)
assertFalse(whileStatement.nextEOGEdges[1].unreachable)
assertTrue(whileStatement.nextEOGEdges[0].unreachable)
}

@Test
Expand All @@ -197,8 +196,8 @@ class UnreachableEOGPassTest {
val whileStatement = method.whileLoops.firstOrNull()
assertNotNull(whileStatement)

assertFalse(whileStatement.nextEOGEdges[1].getProperty(Properties.UNREACHABLE) as Boolean)
assertTrue(whileStatement.nextEOGEdges[0].getProperty(Properties.UNREACHABLE) as Boolean)
assertFalse(whileStatement.nextEOGEdges[1].unreachable)
assertTrue(whileStatement.nextEOGEdges[0].unreachable)
}

@Test
Expand All @@ -209,7 +208,7 @@ class UnreachableEOGPassTest {
val whileStatement = method.whileLoops.firstOrNull()
assertNotNull(whileStatement)

assertFalse(whileStatement.nextEOGEdges[1].getProperty(Properties.UNREACHABLE) as Boolean)
assertFalse(whileStatement.nextEOGEdges[0].getProperty(Properties.UNREACHABLE) as Boolean)
assertFalse(whileStatement.nextEOGEdges[1].unreachable)
assertFalse(whileStatement.nextEOGEdges[0].unreachable)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ import de.fraunhofer.aisec.cpg.*
import de.fraunhofer.aisec.cpg.graph.Name
import de.fraunhofer.aisec.cpg.graph.Node
import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration
import de.fraunhofer.aisec.cpg.graph.edge.ast.TemplateParameters
import de.fraunhofer.aisec.cpg.graph.statements.expressions.BinaryOperator
import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression
import de.fraunhofer.aisec.cpg.graph.types.*
import de.fraunhofer.aisec.cpg.graph.unknownType
import de.fraunhofer.aisec.cpg.passes.SymbolResolver
import java.io.File
import kotlin.reflect.KClass
import kotlin.reflect.full.primaryConstructor
Expand Down Expand Up @@ -322,7 +322,7 @@ abstract class Language<T : LanguageFrontend<*, *>> : Node() {
// matches
val source = result.source
if (this is HasTemplates && source is CallExpression) {
source.templateParameterEdges = mutableListOf()
source.templateParameterEdges = TemplateParameters(source)
val (ok, candidates) =
this.handleTemplateFunctionCalls(
null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@
package de.fraunhofer.aisec.cpg.graph

import de.fraunhofer.aisec.cpg.graph.declarations.Declaration
import de.fraunhofer.aisec.cpg.graph.edge.Properties
import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdge
import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdgeList
import de.fraunhofer.aisec.cpg.graph.edge.ast.AstEdge
import de.fraunhofer.aisec.cpg.graph.edge.ast.AstEdges

interface DeclarationHolder {
/**
Expand All @@ -44,8 +46,12 @@ interface DeclarationHolder {
}
}

fun <T : Node> addIfNotContains(
collection: MutableCollection<PropertyEdge<T>>,
fun <T : Node, P : AstEdge<T>> addIfNotContains(collection: AstEdges<T, P>, declaration: T) {
addIfNotContains(collection, declaration, true)
}

fun <T : Node, P : PropertyEdge<T>> addIfNotContains(
collection: PropertyEdgeList<T, P>,
declaration: T
) {
addIfNotContains(collection, declaration, true)
Expand All @@ -59,28 +65,31 @@ interface DeclarationHolder {
* @param <T> the type of the declaration
* @param outgoing whether the property is outgoing </T>
*/
fun <T : Node> addIfNotContains(
collection: MutableCollection<PropertyEdge<T>>,
fun <T : Node, P : PropertyEdge<T>> addIfNotContains(
collection: PropertyEdgeList<T, out P>,
declaration: T,
outgoing: Boolean
) {
// create a new property edge
val propertyEdge =
if (outgoing) PropertyEdge(this as Node, declaration)
else PropertyEdge(declaration, this as T)

// set the index property
propertyEdge.addProperty(Properties.INDEX, collection.size)
var contains = false
for (element in collection) {
if (element.end == propertyEdge.end) {
contains = true
break
if (outgoing) {
if (element.end == declaration) {
contains = true
break
}
} else {
if (element.start == declaration) {
contains = true
break
}
}
}
if (!contains) {
collection.add(propertyEdge)

if (contains) {
return
}

collection.add(declaration)
}

val declarations: List<Declaration>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,10 @@
*/
package de.fraunhofer.aisec.cpg.graph

import de.fraunhofer.aisec.cpg.frontends.Handler
import de.fraunhofer.aisec.cpg.frontends.HasShortCircuitOperators
import de.fraunhofer.aisec.cpg.frontends.LanguageFrontend
import de.fraunhofer.aisec.cpg.graph.Node.Companion.EMPTY_NAME
import de.fraunhofer.aisec.cpg.graph.NodeBuilder.log
import de.fraunhofer.aisec.cpg.graph.edge.ContextSensitiveDataflow
import de.fraunhofer.aisec.cpg.graph.edge.flows.ContextSensitiveDataflow
import de.fraunhofer.aisec.cpg.graph.statements.expressions.*
import de.fraunhofer.aisec.cpg.graph.statements.expressions.AssignExpression
import de.fraunhofer.aisec.cpg.graph.types.ProblemType
Expand Down Expand Up @@ -567,7 +565,7 @@ fun <T> Literal<T>.duplicate(implicit: Boolean): Literal<T> {
duplicate.file = this.file
duplicate.name = this.name.clone()
for (next in this.nextDFGEdges) {
duplicate.addNextDFG(
duplicate.nextDFGEdges.add(
next.end,
next.granularity,
(next as? ContextSensitiveDataflow)?.callingContext
Expand Down
Loading

0 comments on commit b29ff80

Please sign in to comment.