From 13a88001fdf1cd49a83a2aa89b252d115dc0af46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20Leuth=C3=A4user?= <1417198+max-leuthaeuser@users.noreply.github.com> Date: Fri, 10 Jan 2025 11:08:54 +0100 Subject: [PATCH 1/2] [c2cpg] Fix missing type register call for implicit this access --- .../io/joern/c2cpg/astcreation/AstForPrimitivesCreator.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/AstForPrimitivesCreator.scala b/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/AstForPrimitivesCreator.scala index 2eb7357a7f0f..5ce7f415c2df 100644 --- a/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/AstForPrimitivesCreator.scala +++ b/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/AstForPrimitivesCreator.scala @@ -110,7 +110,7 @@ trait AstForPrimitivesCreator(implicit withSchemaValidation: ValidationMode) { t private def syntheticThisAccess(ident: CPPASTIdExpression, identifierName: String): String | Ast = { val tpe = ident.getName.getBinding match { - case f: CPPField => cleanType(f.getType.toString) + case f: CPPField => f.getType.toString case _ => typeFor(ident) } Try(ident.getEvaluation).toOption match { @@ -125,7 +125,8 @@ trait AstForPrimitivesCreator(implicit withSchemaValidation: ValidationMode) { t val code = s"this->$identifierName" val thisIdentifier = identifierNode(ident, "this", "this", ownerType) val member = fieldIdentifierNode(ident, identifierName, identifierName) - val ma = callNode(ident, code, op, op, DispatchTypes.STATIC_DISPATCH, None, Some(tpe)) + val ma = + callNode(ident, code, op, op, DispatchTypes.STATIC_DISPATCH, None, Some(registerType(cleanType(tpe)))) callAst(ma, Seq(Ast(thisIdentifier).withRefEdge(thisIdentifier, variable), Ast(member))) case None => tpe } From dfa556a2c08e84b0c9056553b0c541f4e1496fe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20Leuth=C3=A4user?= <1417198+max-leuthaeuser@users.noreply.github.com> Date: Fri, 10 Jan 2025 11:57:01 +0100 Subject: [PATCH 2/2] also fix type cleaning --- .../c2cpg/astcreation/AstCreatorHelper.scala | 47 +++++++++---------- .../c2cpg/passes/types/ClassTypeTests.scala | 8 ++-- .../c2cpg/querying/LocalQueryTests.scala | 8 +++- 3 files changed, 32 insertions(+), 31 deletions(-) diff --git a/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/AstCreatorHelper.scala b/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/AstCreatorHelper.scala index 4e9b4d97d451..199d6d64b80c 100644 --- a/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/AstCreatorHelper.scala +++ b/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/AstCreatorHelper.scala @@ -125,7 +125,7 @@ trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: As } // Sadly, there is no predefined List / Enum of this within Eclipse CDT: - private val ReservedTypeKeywords: List[String] = + private val ReservedKeywordsAtTypes: List[String] = List( "const", "static", @@ -142,23 +142,23 @@ trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: As "class" ) - private val KeepTypeKeywords: List[String] = List("unsigned", "volatile", "const", "static") + private val KeywordsAtTypesToKeep: List[String] = List("unsigned", "volatile", "static", "const") protected def cleanType(rawType: String, stripKeywords: Boolean = true): String = { if (rawType == Defines.Any) return rawType - val tpe = - if (stripKeywords) { - ReservedTypeKeywords.foldLeft(rawType) { (cur, repl) => - if (cur.startsWith(s"$repl ") || cur.contains(s" $repl ")) { - cur.replace(s" $repl ", " ").replace(s"$repl ", "") - } else cur - } - } else { - rawType + val tpe = if (stripKeywords) { + ReservedKeywordsAtTypes.foldLeft(rawType) { (cur, repl) => + if (cur.startsWith(s"$repl ") || cur.contains(s" $repl ")) { + cur.replace(s" $repl ", " ").replace(s"$repl ", "") + } else cur } - StringUtils.normalizeSpace(tpe.stripSuffix(" ()")) match { + } else { + rawType + } + val normalizedTpe = StringUtils.normalizeSpace(tpe.stripSuffix(" ()")) + replaceWhitespaceAfterKeyword(normalizedTpe) match { case "" => Defines.Any - case t if t.startsWith("[*this]") || t.startsWith("[this]") => t + case t if t.startsWith("[*this]") || t.startsWith("[this]") => normalizedTpe case t if t.startsWith("[") && t.endsWith("]") => Defines.Array case t if t.contains("->") => Defines.Function case t if t.contains("?") => Defines.Any @@ -166,27 +166,24 @@ trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: As case t if t.contains("::{") || t.contains("}::") => Defines.Any case t if t.contains("{") || t.contains("}") => Defines.Any case t if t.contains("org.eclipse.cdt.internal.core.dom.parser.ProblemType") => Defines.Any - case t if t.contains("( ") => replaceWhitespaceAfterTypeKeyword(fixQualifiedName(t.substring(0, t.indexOf("( ")))) - case t if t.contains(Defines.QualifiedNameSeparator) => replaceWhitespaceAfterTypeKeyword(fixQualifiedName(t)) - case t if KeepTypeKeywords.exists(k => t.startsWith(s"$k ")) => replaceWhitespaceAfterTypeKeyword(t) - case t if t.contains("[") && t.contains("]") => replaceWhitespaceAfterTypeKeyword(t) - case t if t.contains("<") && t.contains(">") => replaceWhitespaceAfterTypeKeyword(t) - case t if t.contains("*") => replaceWhitespaceAfterTypeKeyword(t) - case someType => someType + case t if t.contains("( ") => fixQualifiedName(t.substring(0, t.indexOf("( "))) + case t if t.contains(Defines.QualifiedNameSeparator) => fixQualifiedName(t) + case someType => someType } } - private def replaceWhitespaceAfterTypeKeyword(tpe: String): String = { - if (KeepTypeKeywords.exists(k => tpe.startsWith(s"$k ") || tpe.contains(s" $k "))) { - KeepTypeKeywords.foldLeft(tpe) { (cur, repl) => + private def replaceWhitespaceAfterKeyword(tpe: String): String = { + val keywordsToKeep = ReservedKeywordsAtTypes ++ KeywordsAtTypesToKeep + if (keywordsToKeep.exists(k => tpe.startsWith(s"$k ") || tpe.contains(s" $k "))) { + keywordsToKeep.foldLeft(tpe) { (cur, repl) => val prefixStartsWith = s"$repl " val prefixContains = s" $repl " if (cur.startsWith(prefixStartsWith)) { - prefixStartsWith + replaceWhitespaceAfterTypeKeyword(cur.substring(prefixStartsWith.length)) + prefixStartsWith + replaceWhitespaceAfterKeyword(cur.substring(prefixStartsWith.length)) } else if (cur.contains(prefixContains)) { val front = tpe.substring(0, tpe.indexOf(prefixContains)) val back = tpe.substring(tpe.indexOf(prefixContains) + prefixContains.length) - s"${replaceWhitespaceAfterTypeKeyword(front)}$prefixContains${replaceWhitespaceAfterTypeKeyword(back)}" + s"${replaceWhitespaceAfterKeyword(front)}$prefixContains${replaceWhitespaceAfterKeyword(back)}" } else { cur } diff --git a/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/types/ClassTypeTests.scala b/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/types/ClassTypeTests.scala index db3a31fcc80a..14ef97dd1e87 100644 --- a/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/types/ClassTypeTests.scala +++ b/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/types/ClassTypeTests.scala @@ -201,13 +201,13 @@ class ClassTypeTests extends C2CpgSuite(FileDefaults.CppExt) { del.name shouldBe "delete" del.fullName shouldBe "Foo.delete:void(void*)" eq.name shouldBe "==" - eq.fullName shouldBe "Foo.==:bool(Foo &,Foo &)" + eq.fullName shouldBe "Foo.==:bool(Foo&,Foo&)" plus.name shouldBe "+" - plus.fullName shouldBe "Foo.+:Foo &(Foo &,Foo &)" + plus.fullName shouldBe "Foo.+:Foo&(Foo&,Foo&)" apply.name shouldBe "()" - apply.fullName shouldBe "Foo.():Foo &(Foo &)" + apply.fullName shouldBe "Foo.():Foo&(Foo&)" idx.name shouldBe "[]" - idx.fullName shouldBe "Foo.[]:Foo &(int)" + idx.fullName shouldBe "Foo.[]:Foo&(int)" } "generate correct fullnames in classes with conversions" in { diff --git a/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/querying/LocalQueryTests.scala b/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/querying/LocalQueryTests.scala index 203e7fc289a5..a2dfaa429d6c 100644 --- a/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/querying/LocalQueryTests.scala +++ b/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/querying/LocalQueryTests.scala @@ -13,14 +13,18 @@ class LocalQueryTests extends C2CpgSuite { """ |void foo() { | static const Foo::Bar bar{}; + | static extern std::vector vec; |} |""".stripMargin, "test.cpp" ) - val List(barLocal) = cpg.method.name("foo").local.l - barLocal.name shouldBe "bar" + val List(barLocal) = cpg.method.name("foo").local.nameExact("bar").l barLocal.typeFullName shouldBe "Foo.Bar" barLocal.code shouldBe "static const Foo.Bar bar" + + val List(vecLocal) = cpg.method.name("foo").local.nameExact("vec").l + vecLocal.typeFullName shouldBe "std.vector" + vecLocal.code shouldBe "static extern std.vector vec" } }