From a00bf37b381d8999fc6f87a7188c98676a0b2eb5 Mon Sep 17 00:00:00 2001 From: guorenqi_i Date: Mon, 22 Sep 2025 14:42:50 +0800 Subject: [PATCH 1/4] fix bug in issue 5654 keyword "final" --- .../astcreation/declarations/AstForTypeDeclsCreator.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/astcreation/declarations/AstForTypeDeclsCreator.scala b/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/astcreation/declarations/AstForTypeDeclsCreator.scala index 2ac4a7c9f7d7..fea54bdf1777 100644 --- a/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/astcreation/declarations/AstForTypeDeclsCreator.scala +++ b/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/astcreation/declarations/AstForTypeDeclsCreator.scala @@ -705,7 +705,8 @@ private[declarations] trait AstForTypeDeclsCreator { this: AstCreator => private def modifiersForFieldDeclaration(decl: FieldDeclaration): Seq[Ast] = { val staticModifier = Option.when(decl.isStatic)(modifierNode(decl, ModifierTypes.STATIC)) - + val finalModifier = + Option.when(decl.isFinal)(modifierNode(decl, ModifierTypes.FINAL)) val accessModifierType = if (decl.isPublic) Some(ModifierTypes.PUBLIC) @@ -718,7 +719,7 @@ private[declarations] trait AstForTypeDeclsCreator { this: AstCreator => val accessModifier = accessModifierType.map(modifierNode(decl, _)) - List(staticModifier, accessModifier).flatten.map(Ast(_)) + List(staticModifier, finalModifier, accessModifier).flatten.map(Ast(_)) } private def createTypeDeclNode( From 73e9499a6fd6b982d6a237b50b92c2d9302d9a79 Mon Sep 17 00:00:00 2001 From: jjzdxmd Date: Tue, 14 Oct 2025 17:44:44 +0800 Subject: [PATCH 2/4] fix bug in issue 5676 keyword "null" --- .../passes/TypeInferencePass.scala | 37 +++++++++++++++---- .../typesolvers/TypeInfoCalculator.scala | 1 + 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/passes/TypeInferencePass.scala b/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/passes/TypeInferencePass.scala index bfe620e9dc52..b00883ab7852 100644 --- a/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/passes/TypeInferencePass.scala +++ b/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/passes/TypeInferencePass.scala @@ -32,15 +32,22 @@ class TypeInferencePass(cpg: Cpg) extends ForkJoinParallelCpgPass[Call](cpg) { } private def isMatchingMethod(method: Method, call: Call, callNameParts: NameParts): Boolean = { + if (call.name == "createScript") { + println(s"\n Checking method: ${method.fullName}") + } // An erroneous `this` argument is added for unresolved calls to static methods. val argSizeMod = if (method.modifier.modifierType.iterator.contains(ModifierTypes.STATIC)) 1 else 0 lazy val methodNameParts = getNameParts(method.name, method.fullName) val parameterSizesMatch = (method.parameter.size == (call.argument.size - argSizeMod)) - + if (call.name == "createScript") { + println(s" parameterSizesMatch: $parameterSizesMatch (${method.parameter.size} == ${call.argument.size} - $argSizeMod)") + } lazy val argTypesMatch = doArgumentTypesMatch(method: Method, call: Call, skipCallThis = argSizeMod == 1) - + if (call.name == "createScript" && parameterSizesMatch) { + println(s" argTypesMatch: $argTypesMatch") + } lazy val typeDeclMatches = (callNameParts.typeDecl == methodNameParts.typeDecl) parameterSizesMatch && argTypesMatch && typeDeclMatches @@ -52,17 +59,31 @@ class TypeInferencePass(cpg: Cpg) extends ForkJoinParallelCpgPass[Call](cpg) { */ private def doArgumentTypesMatch(method: Method, call: Call, skipCallThis: Boolean): Boolean = { val callArgs = if (skipCallThis) call.argument.toList.tail else call.argument.toList - - val hasDifferingArg = method.parameter.zip(callArgs).exists { case (parameter, argument) => +// if (call.name == "createScript") { +// println(s"\n === doArgumentTypesMatch ===") +// println(s" skipCallThis: $skipCallThis") +// println(s" call.argument.size: ${call.argument.size}") +// println(s" callArgs.size after skip: ${callArgs.size}") +// println(s" method.parameter.size: ${method.parameter.size}") +// } + val hasDifferingArg = method.parameter.zip(callArgs).zipWithIndex.exists { case ((parameter, argument), idx) => val maybeArgumentType = argument.propertyOption(Properties.TypeFullName).getOrElse(TypeConstants.Any) - val argMatches = maybeArgumentType == TypeConstants.Any || maybeArgumentType == parameter.typeFullName - + val argMatches = maybeArgumentType == TypeConstants.Any || maybeArgumentType == parameter.typeFullName || (maybeArgumentType == TypeConstants.NULL && !isPrimitiveType(parameter.typeFullName)) +// if (call.name == "createScript") { +// println(s" [$idx] Param: ${parameter.name} (${parameter.typeFullName}) vs Arg: ${argument.code} (${maybeArgumentType})") +// println(s" Match: $argMatches") +// } !argMatches } - +// if (call.name == "createScript") { +// println(s" hasDifferingArg: $hasDifferingArg") +// println(s" === End doArgumentTypesMatch ===\n") +// } !hasDifferingArg } - + private def isPrimitiveType(typeName: String): Boolean = { + Set("byte", "short", "int", "long", "float", "double", "boolean", "char").contains(typeName) + } private def getNameParts(name: String, fullName: String): NameParts = { val Array(qualifiedName, signature) = fullName.split(":", 2) diff --git a/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/typesolvers/TypeInfoCalculator.scala b/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/typesolvers/TypeInfoCalculator.scala index a37410c6384a..4e5ebc4859d9 100644 --- a/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/typesolvers/TypeInfoCalculator.scala +++ b/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/typesolvers/TypeInfoCalculator.scala @@ -264,6 +264,7 @@ object TypeInfoCalculator { val Record: String = "java.lang.Record" val Void: String = "void" val Any: String = "ANY" + val NULL: String = "null" } object TypeNameConstants { From efd0e4e9d5c2418b4456cb4a4d39694bd8d7ea50 Mon Sep 17 00:00:00 2001 From: Xmd Date: Wed, 15 Oct 2025 17:37:20 +0800 Subject: [PATCH 3/4] fix bug in issue 5679 --- .../javasrc2cpg/passes/TypeInferencePass.scala | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/passes/TypeInferencePass.scala b/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/passes/TypeInferencePass.scala index b00883ab7852..85e9de534f85 100644 --- a/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/passes/TypeInferencePass.scala +++ b/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/passes/TypeInferencePass.scala @@ -68,7 +68,7 @@ class TypeInferencePass(cpg: Cpg) extends ForkJoinParallelCpgPass[Call](cpg) { // } val hasDifferingArg = method.parameter.zip(callArgs).zipWithIndex.exists { case ((parameter, argument), idx) => val maybeArgumentType = argument.propertyOption(Properties.TypeFullName).getOrElse(TypeConstants.Any) - val argMatches = maybeArgumentType == TypeConstants.Any || maybeArgumentType == parameter.typeFullName || (maybeArgumentType == TypeConstants.NULL && !isPrimitiveType(parameter.typeFullName)) + val argMatches = maybeArgumentType == TypeConstants.Any || maybeArgumentType == parameter.typeFullName || (maybeArgumentType == TypeConstants.NULL && !isPrimitiveType(parameter.typeFullName)) || isSubtypeOf(maybeArgumentType, parameter.typeFullName) // if (call.name == "createScript") { // println(s" [$idx] Param: ${parameter.name} (${parameter.typeFullName}) vs Arg: ${argument.code} (${maybeArgumentType})") // println(s" Match: $argMatches") @@ -84,6 +84,20 @@ class TypeInferencePass(cpg: Cpg) extends ForkJoinParallelCpgPass[Call](cpg) { private def isPrimitiveType(typeName: String): Boolean = { Set("byte", "short", "int", "long", "float", "double", "boolean", "char").contains(typeName) } + + private def isSubtypeOf(argumentType: String, parameterType: String): Boolean = { + if (argumentType == parameterType) { + return true + } + + cpg.typeDecl.fullNameExact(argumentType).headOption match { + case Some(typeDecl) => + typeDecl.inheritsFromTypeFullName.contains(parameterType) + case None => + false + } + } + private def getNameParts(name: String, fullName: String): NameParts = { val Array(qualifiedName, signature) = fullName.split(":", 2) From d2e1ed27c060626e7de643a251488c0adbb723e1 Mon Sep 17 00:00:00 2001 From: Xmd Date: Thu, 16 Oct 2025 14:28:16 +0800 Subject: [PATCH 4/4] fix bug in issue 5679 and checking inheritance chain. --- .../passes/TypeInferencePass.scala | 40 ++++++++++++++++--- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/passes/TypeInferencePass.scala b/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/passes/TypeInferencePass.scala index 85e9de534f85..7759dda904f4 100644 --- a/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/passes/TypeInferencePass.scala +++ b/joern-cli/frontends/javasrc2cpg/src/main/scala/io/joern/javasrc2cpg/passes/TypeInferencePass.scala @@ -75,24 +75,52 @@ class TypeInferencePass(cpg: Cpg) extends ForkJoinParallelCpgPass[Call](cpg) { // } !argMatches } -// if (call.name == "createScript") { -// println(s" hasDifferingArg: $hasDifferingArg") -// println(s" === End doArgumentTypesMatch ===\n") -// } + if (call.name == "createScript") { + println(s" hasDifferingArg: $hasDifferingArg") + println(s" === End doArgumentTypesMatch ===\n") + } !hasDifferingArg } private def isPrimitiveType(typeName: String): Boolean = { Set("byte", "short", "int", "long", "float", "double", "boolean", "char").contains(typeName) } - private def isSubtypeOf(argumentType: String, parameterType: String): Boolean = { +// private def isSubtypeOf(argumentType: String, parameterType: String): Boolean = { +// if (argumentType == parameterType) { +// return true +// } +// +// cpg.typeDecl.fullNameExact(argumentType).headOption match { +// case Some(typeDecl) => +// typeDecl.inheritsFromTypeFullName.contains(parameterType) +// case None => +// false +// } +// } + private def isSubtypeOf( + argumentType: String, + parameterType: String, + visited: Set[String] = Set.empty + ): Boolean = { if (argumentType == parameterType) { return true } + if (visited.contains(argumentType)) { + return false + } + cpg.typeDecl.fullNameExact(argumentType).headOption match { case Some(typeDecl) => - typeDecl.inheritsFromTypeFullName.contains(parameterType) + val parents = typeDecl.inheritsFromTypeFullName.l + + if (parents.contains(parameterType)) { + return true + } + + val newVisited = visited + argumentType + parents.exists(parent => isSubtypeOf(parent, parameterType, newVisited)) + case None => false }