Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable using function summaries to get more precise and custom DFG edges for inferred functions. #1430

Merged
merged 33 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
8475a22
Initial prototype for specifying function dfg-summaries
KuechA Feb 9, 2024
dea03f9
Connect new summaries also to dfg of the declaration
KuechA Feb 9, 2024
4fffec7
Handle non-existing list
KuechA Feb 9, 2024
af5fd2c
Document the file format
KuechA Feb 9, 2024
c1860a7
Added yml support
KuechA Feb 12, 2024
33de45c
Move dependency to toml file
KuechA Feb 12, 2024
fb44dff
Document the class
KuechA Feb 12, 2024
9a9372d
Propagate DFG to calling expressions and arguments
KuechA Feb 12, 2024
e2e6236
Fix serialization
KuechA Feb 12, 2024
35dcf01
integration test tag again
KuechA Feb 13, 2024
eed6009
integration test tag again
KuechA Feb 13, 2024
d34e7ab
New property edges
KuechA Mar 1, 2024
d72d9cc
Flows are now also control flow sensitive
KuechA Mar 1, 2024
e585b57
Merge branch 'main' into dfg-hardcode-file
KuechA Mar 12, 2024
7a22b10
Merge branch 'main' into dfg-hardcode-file
KuechA Mar 12, 2024
2eeb5de
Copy property edges
KuechA Mar 12, 2024
8e0d577
Remove unused method
KuechA Mar 12, 2024
a017f39
Re-add connector method if ControlFlowSensitiveDFG is not executed
KuechA Mar 12, 2024
bbce365
Fix
KuechA Mar 14, 2024
937734e
Add another test
KuechA Mar 14, 2024
bc4b101
Merge branch 'main' into dfg-hardcode-file
KuechA Mar 14, 2024
aac8bbc
Coverage++
KuechA Mar 14, 2024
28bc31e
Try more tests, problems with ContextProvider
KuechA Mar 14, 2024
548cffb
Fix problem with types
KuechA Mar 15, 2024
7501ac8
Handle supertypes properly, extend test
KuechA Mar 15, 2024
f98479f
More fixes, more tests, more types
KuechA Mar 15, 2024
8d1b686
Documentation
KuechA Mar 15, 2024
43ffd46
test coverage++
KuechA Mar 18, 2024
66654b4
All the small comments
KuechA Mar 19, 2024
4b3152a
More comments, smaller fixes
KuechA Mar 19, 2024
47f0737
Merge methods together
KuechA Mar 19, 2024
c320855
Merge branch 'main' into dfg-hardcode-file
KuechA Mar 19, 2024
e9ecdac
Less C&P
KuechA Mar 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cpg-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ dependencies {
implementation(libs.bundles.log4j)
implementation(libs.kotlin.reflect)

implementation(libs.jacksonyml)

testImplementation(libs.junit.params)

testFixturesApi(libs.kotlin.test.junit5) // somehow just using testFixturesApi(kotlin("test")) does not work for testFixtures
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import de.fraunhofer.aisec.cpg.frontends.Language
import de.fraunhofer.aisec.cpg.frontends.LanguageFrontend
import de.fraunhofer.aisec.cpg.graph.Node
import de.fraunhofer.aisec.cpg.passes.*
import de.fraunhofer.aisec.cpg.passes.inference.DFGFunctionSummaries
import de.fraunhofer.aisec.cpg.passes.order.*
import java.io.File
import java.nio.file.Path
Expand Down Expand Up @@ -102,6 +103,8 @@ private constructor(
*/
val replacedPasses:
Map<Pair<KClass<out Pass<out Node>>, KClass<out Language<*>>>, KClass<out Pass<out Node>>>,
/** This list contains the files with function summaries which should be considered. */
val functionSummaries: DFGFunctionSummaries,
languages: List<Language<*>>,
codeInNodes: Boolean,
processAnnotations: Boolean,
Expand Down Expand Up @@ -240,6 +243,7 @@ private constructor(
private val passes = mutableListOf<KClass<out Pass<*>>>()
private val replacedPasses =
mutableMapOf<Pair<KClass<out Pass<*>>, KClass<out Language<*>>>, KClass<out Pass<*>>>()
private val functionSummaries = mutableListOf<File>()
private var codeInNodes = true
private var processAnnotations = false
private var disableCleanup = false
Expand Down Expand Up @@ -420,6 +424,11 @@ private constructor(
return this
}

fun registerFunctionSummaries(vararg functionSummary: File): Builder {
this.functionSummaries.addAll(functionSummary)
return this
}

/** Registers an additional [Language]. */
fun registerLanguage(language: Language<*>): Builder {
languages.add(language)
Expand Down Expand Up @@ -625,6 +634,7 @@ private constructor(
includeBlocklist,
orderPasses(),
replacedPasses,
DFGFunctionSummaries.fromFiles(functionSummaries),
languages,
codeInNodes,
processAnnotations,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ 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.statements.expressions.*
import de.fraunhofer.aisec.cpg.graph.statements.expressions.AssignExpression
import de.fraunhofer.aisec.cpg.graph.types.ProblemType
Expand Down Expand Up @@ -561,8 +562,21 @@ fun <T> Literal<T>.duplicate(implicit: Boolean): Literal<T> {
duplicate.comment = this.comment
duplicate.file = this.file
duplicate.name = this.name.clone()
duplicate.nextDFG = this.nextDFG
duplicate.prevDFG = this.prevDFG
for (next in this.nextDFGEdges) {
duplicate.addNextDFG(
next.end,
next.granularity,
(next as? ContextSensitiveDataflow)?.callingContext
)
}
for (next in this.prevDFGEdges) {
duplicate.addPrevDFG(
next.start,
next.granularity,
(next as? ContextSensitiveDataflow)?.callingContext
)
}
// TODO: This loses the properties of the edges.
duplicate.nextEOG = this.nextEOG
duplicate.prevEOG = this.prevEOG
duplicate.isImplicit = implicit
Expand Down
29 changes: 24 additions & 5 deletions cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Node.kt
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,14 @@ open class Node : IVisitable<Node>, Persistable, LanguageProvider, ScopeProvider
fun addNextDFG(
next: Node,
granularity: Granularity = default(),
callingContext: CallingContext? = null,
) {
val edge = Dataflow(this, next, granularity)
val edge =
if (callingContext != null) {
ContextSensitiveDataflow(this, next, callingContext, granularity)
} else {
Dataflow(this, next, granularity)
}
nextDFGEdges.add(edge)
next.prevDFGEdges.add(edge)
}
Expand All @@ -269,12 +275,21 @@ open class Node : IVisitable<Node>, Persistable, LanguageProvider, ScopeProvider
}
}

/** Adds a [Dataflow] edge from [prev] node to this node, with the given [Granularity]. */
/**
* Adds a [Dataflow] edge from [prev] node to this node, with the given [Granularity] and
* [CallingContext].
*/
open fun addPrevDFG(
prev: Node,
granularity: Granularity = default(),
callingContext: CallingContext? = null,
) {
val edge = Dataflow(prev, this, granularity)
val edge =
if (callingContext != null) {
ContextSensitiveDataflow(prev, this, callingContext, granularity)
} else {
Dataflow(prev, this, granularity)
}
prevDFGEdges.add(edge)
prev.nextDFGEdges.add(edge)
}
Expand All @@ -288,12 +303,16 @@ open class Node : IVisitable<Node>, Persistable, LanguageProvider, ScopeProvider
prev.nextCDGEdges.add(edge)
}

/** Adds a [Dataflow] edge from all [prev] nodes to this node, with the given [Granularity]. */
/**
* Adds a [Dataflow] edge from all [prev] nodes to this node, with the given [Granularity] and
* [CallingContext] if applicable.
*/
fun addAllPrevDFG(
prev: Collection<Node>,
granularity: Granularity = full(),
callingContext: CallingContext? = null,
) {
prev.forEach { addPrevDFG(it, granularity) }
prev.forEach { addPrevDFG(it, granularity, callingContext) }
}

fun addAllPrevPDG(prev: Collection<Node>, dependenceType: DependenceType) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import de.fraunhofer.aisec.cpg.graph.declarations.Declaration
import de.fraunhofer.aisec.cpg.graph.declarations.FieldDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.TupleDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.VariableDeclaration
import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.MemberExpression
import org.neo4j.ogm.annotation.RelationshipEntity

Expand Down Expand Up @@ -80,11 +81,40 @@ fun partial(target: Declaration?): PartialDataflowGranularity {
* [granularity].
*/
@RelationshipEntity
class Dataflow(
open class Dataflow(
start: Node,
end: Node,
/** The granularity of this dataflow. */
val granularity: Granularity = default(),
val granularity: Granularity = default()
) : PropertyEdge<Node>(start, end) {
override val label: String = "DFG"
}

sealed interface CallingContext

class CallingContextIn(
/** The call expression that affects this dataflow edge. */
val call: CallExpression
) : CallingContext

class CallingContextOut(
/** The call expression that affects this dataflow edge. */
val call: CallExpression
) : CallingContext

/**
* This edge class defines a flow of data between [start] and [end]. The flow must have a
* [callingContext] which allows for a context-sensitive dataflow analysis. This edge can also have
* a certain [granularity].
*/
@RelationshipEntity
class ContextSensitiveDataflow(
start: Node,
end: Node,
/** The calling context affecting this dataflow. */
val callingContext: CallingContext,
/** The granularity of this dataflow. */
granularity: Granularity,
) : Dataflow(start, end, granularity) {
override val label: String = "DFG"
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
package de.fraunhofer.aisec.cpg.graph.edge

import de.fraunhofer.aisec.cpg.graph.declarations.TemplateDeclaration.TemplateInitialization
import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression
import java.util.function.Function

/**
Expand All @@ -49,6 +50,9 @@ class PropertyEdgeConverterManager private constructor() {
addDeserializer("INSTANTIATION") { s: Any? ->
if (s != null) TemplateInitialization.valueOf(s.toString()) else null
}
addSerializer(CallExpression::class.java.name) { it.toString() }
addDeserializer("CALLING_CONTEXT_IN") { null } // TODO: Not supported yet
addDeserializer("CALLING_CONTEXT_OUT") { null } // TODO: Not supported yet
}

fun addSerializer(clazz: String, func: Function<Any, String>) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import de.fraunhofer.aisec.cpg.graph.Node
import de.fraunhofer.aisec.cpg.graph.declarations.Declaration
import de.fraunhofer.aisec.cpg.graph.declarations.ValueDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.VariableDeclaration
import de.fraunhofer.aisec.cpg.graph.edge.CallingContext
import de.fraunhofer.aisec.cpg.graph.edge.Granularity
import de.fraunhofer.aisec.cpg.graph.scopes.Scope
import de.fraunhofer.aisec.cpg.graph.types.HasType
Expand Down Expand Up @@ -147,8 +148,8 @@ open class Reference : Expression(), HasType.TypeObserver, HasAliases {
return super.hashCode()
}

override fun addPrevDFG(prev: Node, granularity: Granularity) {
super.addPrevDFG(prev, granularity)
override fun addPrevDFG(prev: Node, granularity: Granularity, callingContext: CallingContext?) {
super.addPrevDFG(prev, granularity, callingContext)

// We want to propagate assigned types all through the previous DFG nodes. Therefore, we
// override the DFG adding function here and add a type observer to the previous node (if it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import de.fraunhofer.aisec.cpg.frontends.LanguageFrontend
import de.fraunhofer.aisec.cpg.graph.Node
import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.MethodDeclaration
import de.fraunhofer.aisec.cpg.graph.edge.CallingContextIn
import de.fraunhofer.aisec.cpg.graph.edge.Properties
import de.fraunhofer.aisec.cpg.graph.statements.expressions.*
import de.fraunhofer.aisec.cpg.sarif.PhysicalLocation
Expand Down Expand Up @@ -355,7 +356,9 @@ object Util {
fun attachCallParameters(target: FunctionDeclaration, call: CallExpression) {
// Add an incoming DFG edge from a member call's base to the method's receiver
if (target is MethodDeclaration && call is MemberCallExpression && !call.isStatic) {
target.receiver?.let { receiver -> call.base?.addNextDFG(receiver) }
target.receiver?.let { receiver ->
call.base?.addNextDFG(receiver, callingContext = CallingContextIn(call))
}
}

// Connect the arguments to parameters
Expand All @@ -370,12 +373,12 @@ object Util {
if (param.isVariadic) {
while (j < arguments.size) {
// map all the following arguments to this variadic param
param.addPrevDFG(arguments[j])
param.addPrevDFG(arguments[j], callingContext = CallingContextIn(call))
j++
}
break
} else {
param.addPrevDFG(arguments[j])
param.addPrevDFG(arguments[j], callingContext = CallingContextIn(call))
}
}
j++
Expand Down
Loading
Loading