Skip to content

Commit

Permalink
Fixed crash in Java hiearchy resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
oxisto committed Nov 15, 2024
1 parent b343a8c commit c2002ef
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,8 @@ fun <T : Node, AstNode> T.codeAndLocationFromOtherRawNode(rawNode: AstNode?): T
* are between the child nodes.
*
* @param parentNode Used to extract the code for this node.
* @param newLineType The char(s) used to describe a new line, usually either "\n" or "\r\n". This
* is needed because the location block spanning the children usually comprises more than one
* @param lineBreakSequence The char(s) used to describe a new line, usually either "\n" or "\r\n".
* This is needed because the location block spanning the children usually comprises more than one
* line.
*/
context(CodeAndLocationProvider<AstNode>)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ fun assertUsageOfMemberAndBase(usingNode: Node?, usedBase: Node?, usedMember: De
}

fun assertFullName(fqn: String, node: Node?, message: String? = null) {
assertNotNull(node)
assertNotNull(node, message)
assertEquals(fqn, node.name.toString(), message)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import de.fraunhofer.aisec.cpg.graph.*
import de.fraunhofer.aisec.cpg.graph.scopes.Scope
import de.fraunhofer.aisec.cpg.graph.types.Type
import de.fraunhofer.aisec.cpg.helpers.CommonPath
import de.fraunhofer.aisec.cpg.passes.SymbolResolver.Companion.LOGGER
import de.fraunhofer.aisec.cpg.passes.configuration.DependsOn
import de.fraunhofer.aisec.cpg.passes.configuration.ExecuteBefore
import de.fraunhofer.aisec.cpg.passes.configuration.RequiredFrontend
Expand Down Expand Up @@ -71,10 +72,12 @@ class JavaExternalTypeHierarchyResolver(ctx: TranslationContext) : ComponentPass
}

// Iterate over all known types and add their (direct) supertypes.
for (t in typeManager.firstOrderTypes) {
var types = typeManager.firstOrderTypes.toList()
for (t in types) {
val symbol = resolver.tryToSolveType(t.typeName)
if (symbol.isSolved) {
try {

val resolvedSuperTypes = symbol.correspondingDeclaration.getAncestors(true)
for (anc in resolvedSuperTypes) {
// We need to try to resolve the type first in order to create weirdly
Expand All @@ -90,10 +93,11 @@ class JavaExternalTypeHierarchyResolver(ctx: TranslationContext) : ComponentPass
// Add all resolved supertypes to the type.
t.superTypes.add(superType)
}
} catch (e: UnsolvedSymbolException) {
// Even if the symbol itself is resolved, "getAncestors()" may throw exception.
} catch (_: UnsolvedSymbolException) {
// Even if the symbol itself is resolved, "getAncestors()" may throw
// exception.
LOGGER.warn(
"Could not resolve supertypes of ${symbol.correspondingDeclaration}"
"Could not resolve supertypes of ${symbol?.correspondingDeclaration}"
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,18 +111,20 @@ internal class TypeTests : BaseTest() {
fun testCommonTypeTestJava() {
val topLevel = Path.of("src", "test", "resources", "compiling", "hierarchy")
val result = analyze("java", topLevel, true) { it.registerLanguage(JavaLanguage()) }
val root = assertNotNull(result.records["multistep.Root"]).toType()
val level0 = assertNotNull(result.records["multistep.Level0"]).toType()
val level1 = assertNotNull(result.records["multistep.Level1"]).toType()
val level1b = assertNotNull(result.records["multistep.Level1B"]).toType()
val level2 = assertNotNull(result.records["multistep.Level2"]).toType()
val unrelated = assertNotNull(result.records["multistep.Unrelated"]).toType()
println(
result.finalCtx.typeManager.firstOrderTypes
.filter { it.typeName == "multistep.Root" }
.map { it.superTypes }
)
getCommonTypeTestGeneral(root, level0, level1, level1b, level2, unrelated)
with(result) {
val root = assertResolvedType("multistep.Root")
val level0 = assertResolvedType("multistep.Level0")
val level1 = assertResolvedType("multistep.Level1")
val level1b = assertResolvedType("multistep.Level1B")
val level2 = assertResolvedType("multistep.Level2")
val unrelated = assertResolvedType("multistep.Unrelated")
println(
result.finalCtx.typeManager.firstOrderTypes
.filter { it.typeName == "multistep.Root" }
.map { it.superTypes }
)
getCommonTypeTestGeneral(root, level0, level1, level1b, level2, unrelated)
}
}

private fun getCommonTypeTestGeneral(
Expand Down Expand Up @@ -169,7 +171,11 @@ internal class TypeTests : BaseTest() {

// Check unrelated type behavior: No common root class
for (t in listOf(root, level0, level1, level1b, level2)) {
assertFullName("java.lang.Object", setOf(unrelated, t).commonType)
assertFullName(
"java.lang.Object",
setOf(unrelated, t).commonType,
"${t.typeName} and ${unrelated.typeName} do not have a common type (java.lang.Object) which they should"
)
}
}
}

0 comments on commit c2002ef

Please sign in to comment.