Skip to content

Commit

Permalink
Handle supertypes properly, extend test
Browse files Browse the repository at this point in the history
  • Loading branch information
KuechA committed Mar 15, 2024
1 parent 548cffb commit 7501ac8
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import de.fraunhofer.aisec.cpg.graph.declarations.*
import de.fraunhofer.aisec.cpg.graph.objectType
import de.fraunhofer.aisec.cpg.graph.parseName
import de.fraunhofer.aisec.cpg.graph.types.Type
import de.fraunhofer.aisec.cpg.isDerivedFrom
import java.io.File

/**
Expand Down Expand Up @@ -111,14 +112,36 @@ class DFGFunctionSummaries {
// to match to the one of the FunctionDeclaration, null indicates that we accept everything.
val matchingEntries =
functionToDFGEntryMap.keys.filter {
it.language == languageName &&
methodName.lastPartsMatch(it.methodName) &&
(it.signature == null ||
functionDecl.hasSignature(
it.signature.map { signatureType ->
functionDecl.objectType(signatureType)
}
))
// The language has to match otherwise the remaining comparison is useless
if (it.language == languageName) {
// Split the name if we have a FQN
val entryMethodName = language.parseName(it.methodName)
val entryRecord =
entryMethodName.parent?.let {
functionDecl.objectType(entryMethodName.parent)
}
methodName.lastPartsMatch(
entryMethodName.localName
) && // The local name has to match
// If it's a method, the record declaration has to be compatible with the
// type of the entry's record declaration. We take the type of the method
// name's parent and generate a type from it. We then check if this type is
// a supertype
(entryRecord == null ||
(functionDecl as? MethodDeclaration)
?.recordDeclaration
?.toType()
?.isDerivedFrom(entryRecord) == true) &&
// The parameter types have to match
(it.signature == null ||
functionDecl.hasSignature(
it.signature.map { signatureType ->
functionDecl.objectType(signatureType)
}
))
} else {
false
}
}
return if (matchingEntries.size == 1) {
// Only one entry => We take this one.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ 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.graph.types.recordDeclaration
import de.fraunhofer.aisec.cpg.passes.ControlFlowSensitiveDFGPass
import de.fraunhofer.aisec.cpg.passes.inference.DFGFunctionSummaries
import de.fraunhofer.aisec.cpg.passes.inference.startInference
import java.io.File
import kotlin.test.Test
import kotlin.test.assertEquals
Expand Down Expand Up @@ -91,6 +93,30 @@ class DFGFunctionSummariesTest {
literal(1, t("int"))
construct("test.Object")
}
val specialListType = t("test.SpecialList")
ctx?.let {
val recordDecl =
specialListType
.startInference(it)
?.inferRecordDeclaration(
specialListType,
this@translationUnit
)
specialListType.recordDeclaration = recordDecl
val listType = t("test.List")
recordDecl?.addSuperClass(listType)
specialListType.superTypes.add(listType)
}

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

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

returnStmt { ref("a") }
}
Expand All @@ -99,12 +125,43 @@ class DFGFunctionSummariesTest {
}
}

val methodAddAllTwoArgs = code.methods["addAll"]
assertNotNull(methodAddAllTwoArgs)
assertEquals(2, methodAddAllTwoArgs.parameters.size)
// Explicitly specified
val listAddAllTwoArgs = code.methods["test.List.addAll"]
assertNotNull(listAddAllTwoArgs)
assertEquals(2, listAddAllTwoArgs.parameters.size)
assertEquals(
setOf<Node>(listAddAllTwoArgs.receiver!!),
listAddAllTwoArgs.parameters[1].nextDFG
)
// No flow from param0 or receiver specified => Should be empty and differ from default
// behavior
assertEquals(setOf(), listAddAllTwoArgs.parameters[0].nextDFG)
assertEquals(setOf(), listAddAllTwoArgs.prevDFG)

// Specified by parent class' method List.addAll
val specialListAddAllTwoArgs = code.methods["test.SpecialList.addAll"]
assertNotNull(specialListAddAllTwoArgs)
assertEquals(2, specialListAddAllTwoArgs.parameters.size)
assertEquals(
setOf<Node>(specialListAddAllTwoArgs.receiver!!),
specialListAddAllTwoArgs.parameters[1].nextDFG
)
// No flow from param0 or receiver specified => Should be empty and differ from default
// behavior
assertEquals(setOf(), specialListAddAllTwoArgs.parameters[0].nextDFG)
assertEquals(setOf(), specialListAddAllTwoArgs.prevDFG)

// Not specified => Default behavior (param0 and param1 and receiver to method declaration).
val randomTypeAddAllTwoArgs = code.methods["random.Type.addAll"]
assertNotNull(randomTypeAddAllTwoArgs)
assertEquals(2, randomTypeAddAllTwoArgs.parameters.size)
assertEquals(
setOf<Node>(methodAddAllTwoArgs.receiver!!),
methodAddAllTwoArgs.parameters[1].nextDFG
setOf<Node>(
randomTypeAddAllTwoArgs.parameters[1],
randomTypeAddAllTwoArgs.parameters[0],
randomTypeAddAllTwoArgs.receiver!!
),
randomTypeAddAllTwoArgs.prevDFG
)
}

Expand Down

0 comments on commit 7501ac8

Please sign in to comment.