Skip to content

Commit

Permalink
More fixes, more tests, more types
Browse files Browse the repository at this point in the history
  • Loading branch information
KuechA committed Mar 15, 2024
1 parent 7501ac8 commit f98479f
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -153,20 +153,22 @@ class DFGFunctionSummaries {
/* There are multiple matching entries. We use the following routine:
* First, we filter for existing signatures.
* Second, we filter for the most precise class.
* If there are still multiple options, we take the longest signature and hope it's the most precise one.
* If there are still multiple options, we take the longest signature.
* If this also didn't help to get a precise result, we iterate through the parameters and take the most precise one. We start with index 0 and count upwards, so if param0 leads to a single result, we're done and other entries won't be considered even if all the remaining parameters are more precise or whatever.
* If nothing helped to get a unique entry, we pick the first remaining entry and hope it's the most precise one.
*/
val typeEntryList =
matchingEntries
.filter { it.signature != null }
.map {
Pair(
language.parseName(it.methodName).parent?.let { it1 ->
language?.objectType(it1)
functionDecl.objectType(it1)
},
it
)
}
val mostPreciseClassEntries = mutableListOf<FunctionDeclarationEntry>()
var mostPreciseClassEntries = mutableListOf<FunctionDeclarationEntry>()
var mostPreciseType = typeEntryList.first().first
var superTypes = mostPreciseType?.ancestors?.map { it.type } ?: setOf()
for (typeEntry in typeEntryList) {
Expand All @@ -179,10 +181,39 @@ class DFGFunctionSummaries {
superTypes = mostPreciseType?.ancestors?.map { it.type } ?: setOf()
}
}
val maxSignature = mostPreciseClassEntries.mapNotNull { it.signature?.size }.max()
if (mostPreciseClassEntries.size > 1) {
mostPreciseClassEntries.sortByDescending { it.signature?.size ?: 0 }
mostPreciseClassEntries =
mostPreciseClassEntries
.filter { it.signature?.size == maxSignature }
.toMutableList()
}
functionToDFGEntryMap[matchingEntries.first()]
// Filter parameter types. We start with parameter 0 and continue. Let's hope we remove
// some entries here.
var argIndex = 0
while (mostPreciseClassEntries.size > 1 && argIndex < maxSignature) {
mostPreciseType =
mostPreciseClassEntries.first().signature?.get(argIndex)?.let {
functionDecl.objectType(it)
}
superTypes = mostPreciseType?.ancestors?.map { it.type } ?: setOf()
val newMostPrecise = mutableListOf<FunctionDeclarationEntry>()
for (entry in mostPreciseClassEntries) {
val currentType =
entry.signature?.get(argIndex)?.let { functionDecl.objectType(it) }
if (currentType == mostPreciseType) {
newMostPrecise.add(entry)
} else if (currentType in superTypes) {
newMostPrecise.clear()
newMostPrecise.add(entry)
mostPreciseType = currentType
superTypes = mostPreciseType?.ancestors?.map { it.type } ?: setOf()
}
}
argIndex++
mostPreciseClassEntries = newMostPrecise
}
functionToDFGEntryMap[mostPreciseClassEntries.first()]
} else {
null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,22 @@ class DFGFunctionSummariesTest {
translationUnit("DfgInferredCall.c") {
function("main", t("int")) {
body {
declare {
variable("a", t("test.List")) { construct("test.List") }
}
memberCall("addAll", ref("a", t("test.List"))) {
literal(1, t("int"))
construct("test.Object")
// We need three types with a type hierarchy.
val objectType = t("test.Object")
val listType = t("test.List")
ctx?.let {
val recordDecl =
listType
.startInference(it)
?.inferRecordDeclaration(
listType,
this@translationUnit
)
listType.recordDeclaration = recordDecl
recordDecl?.addSuperClass(objectType)
listType.superTypes.add(objectType)
}

val specialListType = t("test.SpecialList")
ctx?.let {
val recordDecl =
Expand All @@ -103,22 +112,50 @@ class DFGFunctionSummariesTest {
this@translationUnit
)
specialListType.recordDeclaration = recordDecl
val listType = t("test.List")
recordDecl?.addSuperClass(listType)
specialListType.superTypes.add(listType)
}

memberCall("addAll", ref("a", specialListType)) {
val verySpecialListType = t("test.VerySpecialList")
ctx?.let {
val recordDecl =
specialListType
.startInference(it)
?.inferRecordDeclaration(
specialListType,
this@translationUnit
)
specialListType.recordDeclaration = recordDecl
recordDecl?.addSuperClass(listType)
specialListType.superTypes.add(listType)
}

memberCall("addAll", construct("test.VerySpecialList")) {
literal(1, t("int"))
construct("test.Object")
}

memberCall("addAll", ref("a", t("random.Type"))) {
memberCall("addAll", construct("test.SpecialList")) {
literal(1, t("int"))
construct("test.List")
}

memberCall("addAll", construct("test.SpecialList")) {
literal(1, t("int"))
construct("test.Object")
}

memberCall("addAll", construct("test.List")) {
literal(1, t("int"))
construct("test.Object")
}

memberCall("addAll", construct("random.Type")) {
literal(1, t("int"))
construct("test.Object")
}

returnStmt { ref("a") }
returnStmt { literal(0, t("int")) }
}
}
}
Expand All @@ -138,8 +175,11 @@ class DFGFunctionSummariesTest {
assertEquals(setOf(), listAddAllTwoArgs.parameters[0].nextDFG)
assertEquals(setOf(), listAddAllTwoArgs.prevDFG)

// Specified by parent class' method List.addAll
val specialListAddAllTwoArgs = code.methods["test.SpecialList.addAll"]
// Specified by parent class' method List.addAll(int, Object)
val specialListAddAllTwoArgs =
code.methods("test.SpecialList.addAll").first {
it.parameters[1].type.name.lastPartsMatch("test.Object")
}
assertNotNull(specialListAddAllTwoArgs)
assertEquals(2, specialListAddAllTwoArgs.parameters.size)
assertEquals(
Expand All @@ -151,6 +191,37 @@ class DFGFunctionSummariesTest {
assertEquals(setOf(), specialListAddAllTwoArgs.parameters[0].nextDFG)
assertEquals(setOf(), specialListAddAllTwoArgs.prevDFG)

// Specified by parent class' method List.addAll(int, List)
val specialListAddAllSpecializedArgs =
code.methods("test.SpecialList.addAll").first {
it.parameters[1].type.name.lastPartsMatch("test.List")
}
assertNotNull(specialListAddAllSpecializedArgs)
assertEquals(2, specialListAddAllSpecializedArgs.parameters.size)
// Very weird data flow specified: receiver to param0 and param1 to return.
assertEquals(
setOf<Node>(specialListAddAllSpecializedArgs.parameters[0]),
specialListAddAllSpecializedArgs.receiver?.nextDFG ?: setOf()
)
assertEquals(
setOf<Node>(specialListAddAllSpecializedArgs),
specialListAddAllSpecializedArgs.parameters[1].nextDFG
)

// Specified by parent class' method List.addAll(int, List)
val verySpecialListAddAllSpecializedArgs = code.methods["test.VerySpecialList.addAll"]
assertNotNull(verySpecialListAddAllSpecializedArgs)
assertEquals(2, verySpecialListAddAllSpecializedArgs.parameters.size)
// Very weird data flow specified: receiver to param0 and param1 to return.
assertEquals(
setOf<Node>(verySpecialListAddAllSpecializedArgs.parameters[0]),
verySpecialListAddAllSpecializedArgs.receiver?.nextDFG ?: setOf()
)
assertEquals(
setOf<Node>(verySpecialListAddAllSpecializedArgs),
verySpecialListAddAllSpecializedArgs.parameters[1].nextDFG
)

// Not specified => Default behavior (param0 and param1 and receiver to method declaration).
val randomTypeAddAllTwoArgs = code.methods["random.Type.addAll"]
assertNotNull(randomTypeAddAllTwoArgs)
Expand Down
28 changes: 28 additions & 0 deletions cpg-core/src/test/resources/function-dfg2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,35 @@
language: de.fraunhofer.aisec.cpg.frontends.TestLanguage
methodName: test.List.addAll
signature:
- int
- test.List
dataFlows:
- from: base
to: param0
dfgType: full
- from: param1
to: return
dfgType: full

- functionDeclaration:
language: de.fraunhofer.aisec.cpg.frontends.TestLanguage
methodName: test.VerySpecialList.addAll
signature:
- int
- test.Object
dataFlows:
- from: base
to: param0
dfgType: full
- from: param1
to: return
dfgType: full

- functionDeclaration:
language: de.fraunhofer.aisec.cpg.frontends.TestLanguage
methodName: test.List.addAll
signature:
- test.List
dataFlows:
- from: param0
to: base
Expand Down

0 comments on commit f98479f

Please sign in to comment.