From 06170c4fac752a77d84cd9cd3f199922db63ae89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20Leuth=C3=A4user?= <1417198+max-leuthaeuser@users.noreply.github.com> Date: Mon, 3 Feb 2025 09:19:17 +0100 Subject: [PATCH 1/2] [c2cpg] Fixed fullNames for function problem bindings --- .../c2cpg/astcreation/FullNameProvider.scala | 14 ++++++++--- .../passes/ast/AstCreationPassTests.scala | 25 +++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/FullNameProvider.scala b/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/FullNameProvider.scala index 6d1e7832a34c..bdb67cec39de 100644 --- a/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/FullNameProvider.scala +++ b/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/FullNameProvider.scala @@ -167,8 +167,11 @@ trait FullNameProvider { this: AstCreator => safeGetBinding(declarator.getName) match { case Some(value: ICPPMethod) => cleanType(value.getType.getReturnType.toString) - case _ => + case _ if declarator.getParent.isInstanceOf[IASTSimpleDeclaration] => cleanType(typeForDeclSpecifier(declarator.getParent.asInstanceOf[IASTSimpleDeclaration].getDeclSpecifier)) + case _ if declarator.getParent.isInstanceOf[IASTFunctionDefinition] => + cleanType(typeForDeclSpecifier(declarator.getParent.asInstanceOf[IASTFunctionDefinition].getDeclSpecifier)) + case _ => Defines.Any } } @@ -330,10 +333,15 @@ trait FullNameProvider { this: AstCreator => case Some(_: IProblemBinding) => val fullNameNoSig = replaceOperator(ASTStringUtil.getQualifiedName(declarator.getName)) val fixedFullName = fixQualifiedName(fullNameNoSig) + val returnTpe = declarator.getParent match { + case definition: ICPPASTFunctionDefinition if !isCppConstructor(definition) => returnType(definition) + case _ => returnType(declarator) + } + val signature_ = signature(returnTpe, declarator) if (fixedFullName.isEmpty) { - Option(s"${X2CpgDefines.UnresolvedNamespace}:${X2CpgDefines.UnresolvedSignature}") + Option(s"${X2CpgDefines.UnresolvedNamespace}:$signature_") } else { - Option(s"$fixedFullName:${X2CpgDefines.UnresolvedSignature}") + Option(s"$fixedFullName:$signature_") } case _ => None } diff --git a/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/ast/AstCreationPassTests.scala b/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/ast/AstCreationPassTests.scala index a36e60d69b64..62c9629e6ba6 100644 --- a/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/ast/AstCreationPassTests.scala +++ b/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/ast/AstCreationPassTests.scala @@ -30,6 +30,31 @@ class AstCreationPassTests extends AstC2CpgSuite { } } + "be correct for full names and signatures for method problem bindings" in { + val cpg = code( + """ + |char tpe::foo(char_type a, char b) const { + | return static_cast(a); + |} + |const wchar_t* tpe::foo(const char_type* a, const char_type* b, char c, char* d) const { + | return a; + |} + |""".stripMargin, + "foo.cpp" + ) + // tpe can't be resolved for both methods resulting in problem bindings. + // We can however manually reconstruct the signature from the params and return type without + // relying on the resolved function binding signature. + val fullNames = cpg.method.nameNot("").map(m => (m.fullName, m.signature)).l.sortBy(_._1) + fullNames shouldBe List( + ("tpe.foo:char(char_type,char)", "char(char_type,char)"), + ( + "tpe.foo:const wchar_t*(char_type*,char_type*,char,char*)", + "const wchar_t*(char_type*,char_type*,char,char*)" + ) + ) + } + "be correct for packed args" in { val cpg = code( """ From 6d67279dac2baf022c4eb5eb69f832a4f43ca4f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20Leuth=C3=A4user?= <1417198+max-leuthaeuser@users.noreply.github.com> Date: Mon, 3 Feb 2025 15:32:33 +0100 Subject: [PATCH 2/2] simpler test --- .../c2cpg/passes/ast/AstCreationPassTests.scala | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/ast/AstCreationPassTests.scala b/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/ast/AstCreationPassTests.scala index 62c9629e6ba6..6b641e11884d 100644 --- a/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/ast/AstCreationPassTests.scala +++ b/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/ast/AstCreationPassTests.scala @@ -45,14 +45,11 @@ class AstCreationPassTests extends AstC2CpgSuite { // tpe can't be resolved for both methods resulting in problem bindings. // We can however manually reconstruct the signature from the params and return type without // relying on the resolved function binding signature. - val fullNames = cpg.method.nameNot("").map(m => (m.fullName, m.signature)).l.sortBy(_._1) - fullNames shouldBe List( - ("tpe.foo:char(char_type,char)", "char(char_type,char)"), - ( - "tpe.foo:const wchar_t*(char_type*,char_type*,char,char*)", - "const wchar_t*(char_type*,char_type*,char,char*)" - ) - ) + val List(foo1, foo2) = cpg.method.nameExact("foo").l + foo1.fullName shouldBe "tpe.foo:char(char_type,char)" + foo1.signature shouldBe "char(char_type,char)" + foo2.fullName shouldBe "tpe.foo:const wchar_t*(char_type*,char_type*,char,char*)" + foo2.signature shouldBe "const wchar_t*(char_type*,char_type*,char,char*)" } "be correct for packed args" in {