From 982e7ee43b14bebef1c057ff778dd616238842df Mon Sep 17 00:00:00 2001 From: Xavier Pinho Date: Fri, 6 Dec 2024 17:40:50 +0000 Subject: [PATCH] [c#] add `disable-builtin-summaries` (#5168) --- .../joern/csharpsrc2cpg/CSharpSrc2Cpg.scala | 14 +++--- .../scala/io/joern/csharpsrc2cpg/Main.scala | 11 ++++- .../passes/DependencyTests.scala | 44 +++++++++++++++++++ 3 files changed, 62 insertions(+), 7 deletions(-) diff --git a/joern-cli/frontends/csharpsrc2cpg/src/main/scala/io/joern/csharpsrc2cpg/CSharpSrc2Cpg.scala b/joern-cli/frontends/csharpsrc2cpg/src/main/scala/io/joern/csharpsrc2cpg/CSharpSrc2Cpg.scala index 096ccca8c4d4..d388c2cbe619 100644 --- a/joern-cli/frontends/csharpsrc2cpg/src/main/scala/io/joern/csharpsrc2cpg/CSharpSrc2Cpg.scala +++ b/joern-cli/frontends/csharpsrc2cpg/src/main/scala/io/joern/csharpsrc2cpg/CSharpSrc2Cpg.scala @@ -44,11 +44,15 @@ class CSharpSrc2Cpg extends X2CpgFrontend[Config] { } .foldLeft(CSharpProgramSummary(imports = CSharpProgramSummary.initialImports))(_ ++= _) - val builtinSummary = CSharpProgramSummary( - mutable.Map - .fromSpecific(CSharpProgramSummary.BuiltinTypes.view.filterKeys(internalProgramSummary.imports(_))) - .result() - ) + val builtinSummary = if (config.useBuiltinSummaries) { + CSharpProgramSummary( + mutable.Map + .fromSpecific(CSharpProgramSummary.BuiltinTypes.view.filterKeys(internalProgramSummary.imports(_))) + .result() + ) + } else { + CSharpProgramSummary() + } val internalAndBuiltinSummary = internalProgramSummary ++= builtinSummary diff --git a/joern-cli/frontends/csharpsrc2cpg/src/main/scala/io/joern/csharpsrc2cpg/Main.scala b/joern-cli/frontends/csharpsrc2cpg/src/main/scala/io/joern/csharpsrc2cpg/Main.scala index 273366a8d6a4..dc5de02dc44d 100644 --- a/joern-cli/frontends/csharpsrc2cpg/src/main/scala/io/joern/csharpsrc2cpg/Main.scala +++ b/joern-cli/frontends/csharpsrc2cpg/src/main/scala/io/joern/csharpsrc2cpg/Main.scala @@ -11,7 +11,7 @@ import scopt.OParser import java.nio.file.Paths -final case class Config(downloadDependencies: Boolean = false) +final case class Config(downloadDependencies: Boolean = false, useBuiltinSummaries: Boolean = true) extends X2CpgConfig[Config] with DependencyDownloadConfig[Config] with TypeRecoveryParserConfig[Config] @@ -24,6 +24,10 @@ final case class Config(downloadDependencies: Boolean = false) copy(downloadDependencies = value).withInheritedFields(this) } + def withUseBuiltinSummaries(value: Boolean): Config = { + copy(useBuiltinSummaries = value).withInheritedFields(this) + } + } object Frontend { @@ -35,7 +39,10 @@ object Frontend { OParser.sequence( programName("csharpsrc2cpg"), DependencyDownloadConfig.parserOptions, - XTypeRecoveryConfig.parserOptionsForParserConfig + XTypeRecoveryConfig.parserOptionsForParserConfig, + opt[Unit]("disable-builtin-summaries") + .text("do not use the built-in type summaries") + .action((_, c) => c.withUseBuiltinSummaries(false)) ) } diff --git a/joern-cli/frontends/csharpsrc2cpg/src/test/scala/io/joern/csharpsrc2cpg/passes/DependencyTests.scala b/joern-cli/frontends/csharpsrc2cpg/src/test/scala/io/joern/csharpsrc2cpg/passes/DependencyTests.scala index 488baaa5a695..0fbb6b482bc6 100644 --- a/joern-cli/frontends/csharpsrc2cpg/src/test/scala/io/joern/csharpsrc2cpg/passes/DependencyTests.scala +++ b/joern-cli/frontends/csharpsrc2cpg/src/test/scala/io/joern/csharpsrc2cpg/passes/DependencyTests.scala @@ -101,7 +101,51 @@ class DependencyTests extends CSharpCode2CpgFixture { fail("Expected a call node for `Entity`") } } + } + + "a `csproj` file specifying a built-in dependency but built-in type summaries are disabled" when { + val csCode = """ + |using Microsoft.EntityFrameworkCore; + | + |public class Foo + |{ + | static void bar(ModelBuilder modelBuilder) + | { + | modelBuilder.Entity("test"); + | } + |}""".stripMargin + val csProj = """ + | + | + | + | + | + |""".stripMargin + + "the ability to download dependencies is also turned off" should { + val cpg = code(csCode) + .moreCode(csProj, "Foo.csproj") + .withConfig(Config().withUseBuiltinSummaries(false).withDownloadDependencies(false)) + "not resolve the call since there are no type summaries available for it" in { + inside(cpg.call("Entity").headOption) { + case Some(entity) => entity.methodFullName shouldBe "ModelBuilder.Entity:" + case None => fail("Expected call node for `Entity`") + } + } + } + "the ability to download dependencies is turned on" should { + val cpg = code(csCode) + .moreCode(csProj, "Foo.csproj") + .withConfig(Config().withUseBuiltinSummaries(false).withDownloadDependencies(true)) + "resolve the call since the dependency shall be downloaded and a type summary for it be built" in { + inside(cpg.call("Entity").headOption) { + case Some(entity) => + entity.methodFullName shouldBe "Microsoft.EntityFrameworkCore.ModelBuilder.Entity:Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder(System.String)" + case None => fail("Expected call node for `Entity`") + } + } + } } "a `csproj` file specifying a dependency with the `Update` attribute" should {