Skip to content

Commit

Permalink
Flows are now also control flow sensitive
Browse files Browse the repository at this point in the history
  • Loading branch information
KuechA authored and oxisto committed Mar 7, 2024
1 parent d34e7ab commit d72d9cc
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ package de.fraunhofer.aisec.cpg.passes
import de.fraunhofer.aisec.cpg.TranslationContext
import de.fraunhofer.aisec.cpg.graph.*
import de.fraunhofer.aisec.cpg.graph.declarations.*
import de.fraunhofer.aisec.cpg.graph.edge.Properties
import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdge
import de.fraunhofer.aisec.cpg.graph.edge.partial
import de.fraunhofer.aisec.cpg.graph.edge.*
import de.fraunhofer.aisec.cpg.graph.statements.DeclarationStatement
import de.fraunhofer.aisec.cpg.graph.statements.ForEachStatement
import de.fraunhofer.aisec.cpg.graph.statements.ReturnStatement
Expand Down Expand Up @@ -122,11 +120,15 @@ open class ControlFlowSensitiveDFGPass(ctx: TranslationContext) : EOGStarterPass
)
}
} else {
key.addAllPrevDFG(
value.elements.filterNot {
(it is VariableDeclaration || it is ParameterDeclaration) && key == it
value.elements.forEach {
if ((it is VariableDeclaration || it is ParameterDeclaration) && key == it) {
// Nothing to do
} else if (it in edgePropertiesMap && edgePropertiesMap[it] is CallingContext) {
key.addPrevDFGContext(it, (edgePropertiesMap[it] as CallingContext))
} else {
key.addPrevDFG(it)
}
)
}
}
}
}
Expand Down Expand Up @@ -388,6 +390,26 @@ open class ControlFlowSensitiveDFGPass(ctx: TranslationContext) : EOGStarterPass
currentNode,
PowersetLattice(identitySetOf(currentNode))
)
} else if (currentNode is CallExpression) {
for (invoked in
currentNode.invokes.filter {
it in ctx.config.functionSummaries.functionToChangedParameters
}) {
val changedParams =
ctx.config.functionSummaries.functionToChangedParameters[invoked] ?: mapOf()
for ((param, _) in changedParams) {
if (param == (invoked as? MethodDeclaration)?.receiver) {
doubleState.declarationsState[
((currentNode as? MemberCallExpression)?.base as? Reference)
?.refersTo] = PowersetLattice(identitySetOf(param))
} else if (param is ParameterDeclaration) {
val arg = currentNode.arguments[param.argumentIndex]
doubleState.declarationsState[(arg as? Reference)?.refersTo] =
PowersetLattice(identitySetOf(param))
}
edgePropertiesMap[param] = CallingContextOut(currentNode)
}
}
} else {
doubleState.declarationsState.push(
currentNode,
Expand All @@ -397,6 +419,8 @@ open class ControlFlowSensitiveDFGPass(ctx: TranslationContext) : EOGStarterPass
return state
}

val edgePropertiesMap = mutableMapOf<Node, Any>()

/**
* Checks if the node performs an operation and an assignment at the same time e.g. with the
* operators +=, -=, *=, ...
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class DFGPass(ctx: TranslationContext) : ComponentPass(ctx) {
walker.iterate(tu)
}

connectInferredCallArguments(config.functionSummaries)
// connectInferredCallArguments(config.functionSummaries)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import de.fraunhofer.aisec.cpg.graph.edge.CallingContextOut
import de.fraunhofer.aisec.cpg.graph.edge.ContextsensitiveDataflow
import de.fraunhofer.aisec.cpg.graph.functions
import de.fraunhofer.aisec.cpg.graph.pointer
import de.fraunhofer.aisec.cpg.graph.statements.ReturnStatement
import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference
import de.fraunhofer.aisec.cpg.passes.inference.DFGFunctionSummaries
import java.io.File
import kotlin.test.Test
Expand Down Expand Up @@ -78,14 +80,14 @@ class DFGFunctionSummariesTest {

val argA = call.arguments[0]
assertNotNull(argA)

assertEquals(1, argA.nextDFG.size)
assertEquals(2, argA.prevDFG.size)
/*
The flows should be as follows:
VariableDeclaration["a"] -> Reference["a" (argument of call)] -CallingContextIn-> ParameterDeclaration -CallingContextOut-> Reference["a" (return)]
*/

assertEquals(1, argA.nextDFG.size)
assertEquals(1, argA.prevDFG.size)

val nextDfg = argA.nextDFGEdges.single()
assertEquals(
call,
Expand All @@ -94,26 +96,26 @@ class DFGFunctionSummariesTest {
)
assertEquals(param0, nextDfg.end)

val prevDfgThroughFunction =
argA.prevDFGEdges.singleOrNull {
((it as? ContextsensitiveDataflow)?.callingContext as? CallingContextOut)
?.callExpression != call
}
assertNotNull(prevDfgThroughFunction)
assertEquals(param0, prevDfgThroughFunction.start)
val variableA = main.variables["a"]
assertNotNull(variableA)
assertEquals(mutableSetOf<Node>(variableA), argA.prevDFG)

val prevDfgOfParam0 = param0.prevDFGEdges.singleOrNull { it !is ContextsensitiveDataflow }
assertNotNull(prevDfgOfParam0)
assertEquals(param1, prevDfgOfParam0.start)

val variableDeclA = main.variables["a"]
assertNotNull(variableDeclA)
val returnA = main.allChildren<ReturnStatement>().singleOrNull()?.returnValue as? Reference
assertNotNull(returnA)

val prevDfgNotThroughFunction =
argA.prevDFGEdges.singleOrNull {
assertEquals(mutableSetOf<Node>(returnA), param0.nextDFG)

// Check that also the CallingContext property is set correctly
val nextDfgOfParam0 =
param0.nextDFGEdges.singleOrNull {
((it as? ContextsensitiveDataflow)?.callingContext as? CallingContextOut)
?.callExpression != call
?.callExpression == call
}
assertNotNull(prevDfgNotThroughFunction)
assertEquals(variableDeclA, prevDfgNotThroughFunction.start)

assertEquals(setOf<Node>(argA, param1), param0.prevDFG)
assertEquals(returnA, nextDfgOfParam0?.end)
}

companion object {
Expand Down

0 comments on commit d72d9cc

Please sign in to comment.