Skip to content

Commit

Permalink
Merge main into symbol-resolver-with-eog-power
Browse files Browse the repository at this point in the history
  • Loading branch information
KuechA committed Sep 14, 2023
2 parents 9eca8c9 + 15ca3aa commit 39d9d9c
Show file tree
Hide file tree
Showing 147 changed files with 1,659 additions and 1,837 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ On some edges, we want to store additional information (e.g., if a `EOG` node is
/** The list of function parameters. */
@Relationship(value = "PARAMETERS", direction = Relationship.Direction.OUTGOING)
@field:SubGraph("AST")
var parameterEdges = mutableListOf<PropertyEdge<ParamVariableDeclaration>>()
var parameterEdges = mutableListOf<PropertyEdge<ParameterDeclaration>>()

/** Virtual property for accessing [parameterEdges] without property edges. */
var parameters by PropertyEdgeDelegate(FunctionDeclaration::parameterEdges)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,17 @@ class MultiValueEvaluator : ValueEvaluator() {
is FieldDeclaration -> {
return evaluateInternal(node.initializer, depth + 1)
}
is ArrayCreationExpression -> return evaluateInternal(node.initializer, depth + 1)
is NewArrayExpression -> return evaluateInternal(node.initializer, depth + 1)
is VariableDeclaration -> return evaluateInternal(node.initializer, depth + 1)
// For a literal, we can just take its value, and we are finished
is Literal<*> -> return node.value
is DeclaredReferenceExpression -> return handleDeclaredReferenceExpression(node, depth)
is Reference -> return handleReference(node, depth)
is UnaryOperator -> return handleUnaryOp(node, depth)
is AssignExpression -> return handleAssignExpression(node, depth)
is BinaryOperator -> return handleBinaryOperator(node, depth)
// Casts are just a wrapper in this case, we are interested in the inner expression
is CastExpression -> return this.evaluateInternal(node.expression, depth + 1)
is ArraySubscriptionExpression -> return handleArraySubscriptionExpression(node, depth)
is SubscriptExpression -> return handleSubscriptExpression(node, depth)
// While we are not handling different paths of variables with If statements, we can
// easily be partly path-sensitive in a conditional expression
is ConditionalExpression -> return handleConditionalExpression(node, depth)
Expand Down Expand Up @@ -170,8 +170,8 @@ class MultiValueEvaluator : ValueEvaluator() {

override fun handleConditionalExpression(expr: ConditionalExpression, depth: Int): Any {
val result = mutableSetOf<Any?>()
val elseResult = evaluateInternal(expr.elseExpr, depth + 1)
val thenResult = evaluateInternal(expr.thenExpr, depth + 1)
val elseResult = evaluateInternal(expr.elseExpression, depth + 1)
val thenResult = evaluateInternal(expr.thenExpression, depth + 1)
if (thenResult is Collection<*>) result.addAll(thenResult) else result.add(thenResult)
if (elseResult is Collection<*>) result.addAll(elseResult) else result.add(elseResult)
return result
Expand Down Expand Up @@ -217,10 +217,7 @@ class MultiValueEvaluator : ValueEvaluator() {
* In contrast to the implementation of [ValueEvaluator], this one can handle more than one
* value.
*/
override fun handleDeclaredReferenceExpression(
expr: DeclaredReferenceExpression,
depth: Int
): Collection<Any?> {
override fun handleReference(expr: Reference, depth: Int): Collection<Any?> {
// For a reference, we are interested in its last assignment into the reference
// denoted by the previous DFG edge. We need to filter out any self-references for READWRITE
// references.
Expand Down Expand Up @@ -282,10 +279,7 @@ class MultiValueEvaluator : ValueEvaluator() {
forStatement.iterationStatement == node.astParent
}

private fun handleSimpleLoopVariable(
expr: DeclaredReferenceExpression,
depth: Int
): Collection<Any?> {
private fun handleSimpleLoopVariable(expr: Reference, depth: Int): Collection<Any?> {
val loop =
expr.prevDFG.firstOrNull { e -> e.astParent is ForStatement }?.astParent
as? ForStatement
Expand All @@ -298,13 +292,13 @@ class MultiValueEvaluator : ValueEvaluator() {
val cond = loop.condition as BinaryOperator
val result = mutableSetOf<Any?>()
var lhs =
if ((cond.lhs as? DeclaredReferenceExpression)?.refersTo == expr.refersTo) {
if ((cond.lhs as? Reference)?.refersTo == expr.refersTo) {
loopVar
} else {
evaluateInternal(cond.lhs, depth + 1)
}
var rhs =
if ((cond.rhs as? DeclaredReferenceExpression)?.refersTo == expr.refersTo) {
if ((cond.rhs as? Reference)?.refersTo == expr.refersTo) {
loopVar
} else {
evaluateInternal(cond.rhs, depth + 1)
Expand All @@ -323,27 +317,25 @@ class MultiValueEvaluator : ValueEvaluator() {
is AssignExpression -> {
if (
loopOp.operatorCode == "=" &&
(loopOp.lhs.singleOrNull() as? DeclaredReferenceExpression)
?.refersTo == expr.refersTo &&
(loopOp.lhs.singleOrNull() as? Reference)?.refersTo ==
expr.refersTo &&
loopOp.rhs.singleOrNull() is BinaryOperator
) {
// Assignment to the variable, take the rhs and see if it's also a
// binary operator
val opLhs =
if (
((loopOp.rhs<BinaryOperator>())?.lhs
as? DeclaredReferenceExpression)
?.refersTo == expr.refersTo
((loopOp.rhs<BinaryOperator>())?.lhs as? Reference)?.refersTo ==
expr.refersTo
) {
loopVar
} else {
(loopOp.rhs<BinaryOperator>())?.lhs
}
val opRhs =
if (
((loopOp.rhs<BinaryOperator>())?.rhs
as? DeclaredReferenceExpression)
?.refersTo == expr.refersTo
((loopOp.rhs<BinaryOperator>())?.rhs as? Reference)?.refersTo ==
expr.refersTo
) {
loopVar
} else {
Expand All @@ -359,19 +351,13 @@ class MultiValueEvaluator : ValueEvaluator() {

// No idea what this is but it's a binary op...
val opLhs =
if (
(loopOp.lhs as? DeclaredReferenceExpression)?.refersTo ==
expr.refersTo
) {
if ((loopOp.lhs as? Reference)?.refersTo == expr.refersTo) {
loopVar
} else {
loopOp.lhs
}
val opRhs =
if (
(loopOp.rhs as? DeclaredReferenceExpression)?.refersTo ==
expr.refersTo
) {
if ((loopOp.rhs as? Reference)?.refersTo == expr.refersTo) {
loopVar
} else {
loopOp.rhs
Expand All @@ -380,10 +366,7 @@ class MultiValueEvaluator : ValueEvaluator() {
}
is UnaryOperator -> {
computeUnaryOpEffect(
if (
(loopOp.input as? DeclaredReferenceExpression)?.refersTo ==
expr.refersTo
) {
if ((loopOp.input as? Reference)?.refersTo == expr.refersTo) {
loopVar
} else {
loopOp.input
Expand All @@ -400,10 +383,10 @@ class MultiValueEvaluator : ValueEvaluator() {
return result
}

if ((cond.lhs as? DeclaredReferenceExpression)?.refersTo == expr.refersTo) {
if ((cond.lhs as? Reference)?.refersTo == expr.refersTo) {
lhs = loopVar
}
if ((cond.rhs as? DeclaredReferenceExpression)?.refersTo == expr.refersTo) {
if ((cond.rhs as? Reference)?.refersTo == expr.refersTo) {
rhs = loopVar
}
comparisonResult = computeBinaryOpEffect(lhs, rhs, cond)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,17 @@ class SizeEvaluator : ValueEvaluator() {
node?.let { this.path += it }

return when (node) {
is ArrayCreationExpression ->
is NewArrayExpression ->
if (node.initializer != null) {
evaluateInternal(node.initializer, depth + 1)
} else {
evaluateInternal(node.dimensions.firstOrNull(), depth + 1)
}
is VariableDeclaration -> evaluateInternal(node.initializer, depth + 1)
is DeclaredReferenceExpression -> evaluateInternal(node.refersTo, depth + 1)
is Reference -> evaluateInternal(node.refersTo, depth + 1)
// For a literal, we can just take its value, and we are finished
is Literal<*> -> if (node.value is String) (node.value as String).length else node.value
is ArraySubscriptionExpression -> evaluate(node.arrayExpression)
is SubscriptExpression -> evaluate(node.arrayExpression)
else -> cannotEvaluate(node, this)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,16 @@ open class ValueEvaluator(
node?.let { this.path += it }

when (node) {
is ArrayCreationExpression -> return evaluateInternal(node.initializer, depth + 1)
is NewArrayExpression -> return evaluateInternal(node.initializer, depth + 1)
is VariableDeclaration -> return evaluateInternal(node.initializer, depth + 1)
// For a literal, we can just take its value, and we are finished
is Literal<*> -> return node.value
is DeclaredReferenceExpression -> return handleDeclaredReferenceExpression(node, depth)
is Reference -> return handleReference(node, depth)
is UnaryOperator -> return handleUnaryOp(node, depth)
is BinaryOperator -> return handleBinaryOperator(node, depth)
// Casts are just a wrapper in this case, we are interested in the inner expression
is CastExpression -> return this.evaluateInternal(node.expression, depth + 1)
is ArraySubscriptionExpression -> return handleArraySubscriptionExpression(node, depth)
is SubscriptExpression -> return handleSubscriptExpression(node, depth)
// While we are not handling different paths of variables with If statements, we can
// easily be partly path-sensitive in a conditional expression
is ConditionalExpression -> return handleConditionalExpression(node, depth)
Expand Down Expand Up @@ -277,12 +277,8 @@ open class ValueEvaluator(
* basically the case if the base of the subscript expression is a list of [KeyValueExpression]
* s.
*/
protected fun handleArraySubscriptionExpression(
expr: ArraySubscriptionExpression,
depth: Int
): Any? {
val array =
(expr.arrayExpression as? DeclaredReferenceExpression)?.refersTo as? VariableDeclaration
protected fun handleSubscriptExpression(expr: SubscriptExpression, depth: Int): Any? {
val array = (expr.arrayExpression as? Reference)?.refersTo as? VariableDeclaration
val ile = array?.initializer as? InitializerListExpression

ile?.let {
Expand All @@ -301,7 +297,7 @@ open class ValueEvaluator(
return (array.initializer as Literal<*>).value
}

if (expr.arrayExpression is ArraySubscriptionExpression) {
if (expr.arrayExpression is SubscriptExpression) {
return evaluateInternal(expr.arrayExpression, depth + 1)
}

Expand All @@ -315,9 +311,9 @@ open class ValueEvaluator(
val rhs = evaluateInternal((expr.condition as? BinaryOperator)?.rhs, depth)

return if (lhs == rhs) {
evaluateInternal(expr.thenExpr, depth + 1)
evaluateInternal(expr.thenExpression, depth + 1)
} else {
evaluateInternal(expr.elseExpr, depth + 1)
evaluateInternal(expr.elseExpression, depth + 1)
}
}

Expand All @@ -328,10 +324,7 @@ open class ValueEvaluator(
* Tries to compute the constant value of a reference. It therefore checks the incoming data
* flow edges.
*/
protected open fun handleDeclaredReferenceExpression(
expr: DeclaredReferenceExpression,
depth: Int
): Any? {
protected open fun handleReference(expr: Reference, depth: Int): Any? {
// For a reference, we are interested into its last assignment into the reference
// denoted by the previous DFG edge. We need to filter out any self-references for READWRITE
// references.
Expand All @@ -358,10 +351,7 @@ open class ValueEvaluator(
* If a reference has READWRITE access, ignore any "self-references", e.g. from a
* plus/minus/div/times-assign or a plusplus/minusminus, etc.
*/
protected fun filterSelfReferences(
ref: DeclaredReferenceExpression,
inDFG: List<Node>
): List<Node> {
protected fun filterSelfReferences(ref: Reference, inDFG: List<Node>): List<Node> {
var list = inDFG

// The ops +=, -=, ... and ++, -- have in common that we see the ref twice: Once to reach
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@
package de.fraunhofer.aisec.cpg.analysis.fsm

import de.fraunhofer.aisec.cpg.graph.Node
import de.fraunhofer.aisec.cpg.graph.declarations.ParamVariableDeclaration
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
import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.MemberCallExpression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference
import de.fraunhofer.aisec.cpg.passes.astParent
import org.slf4j.Logger
import org.slf4j.LoggerFactory
Expand Down Expand Up @@ -284,16 +284,14 @@ open class DFAOrderEvaluator(
private fun callUsesInterestingBase(node: CallExpression, eogPath: String): List<String> {
val allUsedBases =
node.arguments
.map { arg -> (arg as? DeclaredReferenceExpression)?.refersTo }
.map { arg -> (arg as? Reference)?.refersTo }
.filter { arg -> arg != null && consideredBases.contains(arg) }
.toMutableList()
if (
node is MemberCallExpression &&
node.base is DeclaredReferenceExpression &&
(node.base as DeclaredReferenceExpression).refersTo != null &&
consideredBases.contains((node.base as DeclaredReferenceExpression).refersTo!!)
(node.base as? Reference)?.refersTo?.let { it in consideredBases } == true
) {
allUsedBases.add((node.base as DeclaredReferenceExpression).refersTo)
allUsedBases.add((node.base as Reference).refersTo)
}

return allUsedBases.map { "$eogPath|${it?.name}.$it" }
Expand Down Expand Up @@ -344,7 +342,7 @@ open class DFAOrderEvaluator(
// the end.
var base = getBaseOfNode(node)

if (base is DeclaredReferenceExpression && base.refersTo != null) {
if (base is Reference && base.refersTo != null) {
base = base.refersTo
}

Expand All @@ -353,7 +351,7 @@ open class DFAOrderEvaluator(
// the different paths of execution which both can use the same base.
val prefixedBase = "$eogPath|${base.name}.$base"

if (base is ParamVariableDeclaration) {
if (base is ParameterDeclaration) {
// The base was the parameter of the function? We have an inter-procedural flow!
interproceduralFlows[prefixedBase] = true
}
Expand Down Expand Up @@ -391,7 +389,7 @@ open class DFAOrderEvaluator(

var node: Node = list.first()
// if the node refers to another node, return the node it refers to
(node as? DeclaredReferenceExpression)?.refersTo?.let { node = it }
(node as? Reference)?.refersTo?.let { node = it }
return node
}

Expand All @@ -405,7 +403,7 @@ open class DFAOrderEvaluator(
private fun Node.getSuitableDFGTarget(): Node? {
return this.nextDFG
.filter {
it is DeclaredReferenceExpression ||
it is Reference ||
it is ReturnStatement ||
it is ConstructExpression ||
it is VariableDeclaration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ package de.fraunhofer.aisec.cpg.graph

import de.fraunhofer.aisec.cpg.analysis.ValueEvaluator
import de.fraunhofer.aisec.cpg.graph.declarations.Declaration
import de.fraunhofer.aisec.cpg.graph.statements.expressions.ArrayCreationExpression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.NewArrayExpression

fun Expression.evaluate(evaluator: ValueEvaluator = ValueEvaluator()): Any? {
return evaluator.evaluate(this)
Expand All @@ -38,7 +38,7 @@ fun Declaration.evaluate(evaluator: ValueEvaluator = ValueEvaluator()): Any? {
return evaluator.evaluate(this)
}

val ArrayCreationExpression.capacity: Int
val NewArrayExpression.capacity: Int
get() {
return dimensions.first().evaluate() as Int
}
Original file line number Diff line number Diff line change
Expand Up @@ -359,12 +359,14 @@ fun allNonLiteralsFromFlowTo(from: Node, to: Node, allPaths: List<List<Node>>):
it.any { it2 ->
if (it2 is AssignmentHolder) {
it2.assignments.any { assign ->
val prevMemberFrom = (from as? MemberExpression)?.prevDFG
val nextMemberTo = (assign.target as? MemberExpression)?.nextDFG
val prevMemberFromExpr = (from as? MemberExpression)?.prevDFG
val nextMemberToExpr = (assign.target as? MemberExpression)?.nextDFG
assign.target == from ||
prevMemberFrom != null &&
nextMemberTo != null &&
prevMemberFrom.any { it3 -> nextMemberTo.contains(it3) }
prevMemberFromExpr != null &&
nextMemberToExpr != null &&
prevMemberFromExpr.any { it3 ->
nextMemberToExpr.contains(it3)
}
}
} else {
false
Expand Down
Loading

0 comments on commit 39d9d9c

Please sign in to comment.