From fe62900a1579b02502a3b1dcd78946f8ebd5b9f3 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 11 Nov 2024 12:08:37 +0100 Subject: [PATCH 1/2] C#: Change extractor to accept multiple `binlog` files --- csharp/codeql-extractor.yml | 2 +- .../Extractor/Extractor.cs | 23 +++++++++- .../Extractor/Options.cs | 6 +-- .../binlog_multiple/Files.expected | 10 +++++ .../all-platforms/binlog_multiple/Files.ql | 5 +++ .../all-platforms/binlog_multiple/a/A.cs | 9 ++++ .../binlog_multiple/a/test.csproj | 10 +++++ .../all-platforms/binlog_multiple/b/B.cs | 9 ++++ .../binlog_multiple/b/test.csproj | 10 +++++ .../binlog_multiple/diagnostics.expected | 42 +++++++++++++++++++ .../all-platforms/binlog_multiple/global.json | 5 +++ .../all-platforms/binlog_multiple/test.py | 7 ++++ 12 files changed, 132 insertions(+), 6 deletions(-) create mode 100644 csharp/ql/integration-tests/all-platforms/binlog_multiple/Files.expected create mode 100644 csharp/ql/integration-tests/all-platforms/binlog_multiple/Files.ql create mode 100644 csharp/ql/integration-tests/all-platforms/binlog_multiple/a/A.cs create mode 100644 csharp/ql/integration-tests/all-platforms/binlog_multiple/a/test.csproj create mode 100644 csharp/ql/integration-tests/all-platforms/binlog_multiple/b/B.cs create mode 100644 csharp/ql/integration-tests/all-platforms/binlog_multiple/b/test.csproj create mode 100644 csharp/ql/integration-tests/all-platforms/binlog_multiple/diagnostics.expected create mode 100644 csharp/ql/integration-tests/all-platforms/binlog_multiple/global.json create mode 100644 csharp/ql/integration-tests/all-platforms/binlog_multiple/test.py diff --git a/csharp/codeql-extractor.yml b/csharp/codeql-extractor.yml index 43c4adaafbf9..c4d7352cc439 100644 --- a/csharp/codeql-extractor.yml +++ b/csharp/codeql-extractor.yml @@ -70,4 +70,4 @@ options: description: > [EXPERIMENTAL] The value is a path to the MsBuild binary log file that should be extracted. This option only works when `--build-mode none` is also specified. - type: string + type: array diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Extractor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Extractor.cs index d87f6fd24c0c..b3ffcd442f44 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Extractor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Extractor.cs @@ -106,10 +106,10 @@ public static ExitCode Run(string[] args) var canonicalPathCache = CanonicalPathCache.Create(logger, 1000); var pathTransformer = new PathTransformer(canonicalPathCache); - if (options.BinaryLogPath is string binlogPath) + if (options.BinaryLogPaths is string[] binlogPaths) { logger.LogInfo(" Running binary log analysis."); - return RunBinaryLogAnalysis(analyzerStopwatch, options, binlogPath, logger, canonicalPathCache, pathTransformer); + return RunBinaryLogAnalysis(analyzerStopwatch, options, binlogPaths, logger, canonicalPathCache, pathTransformer); } else { @@ -124,6 +124,25 @@ public static ExitCode Run(string[] args) } } + private static ExitCode RunBinaryLogAnalysis(Stopwatch stopwatch, Options options, string[] binlogPaths, ILogger logger, CanonicalPathCache canonicalPathCache, PathTransformer pathTransformer) + { + var allFailed = true; + foreach (var binlogPath in binlogPaths) + { + var exit = RunBinaryLogAnalysis(stopwatch, options, binlogPath, logger, canonicalPathCache, pathTransformer); + switch (exit) + { + case ExitCode.Ok: + case ExitCode.Errors: + allFailed &= false; + break; + case ExitCode.Failed: + break; + } + } + return allFailed ? ExitCode.Failed : ExitCode.Ok; + } + private static ExitCode RunBinaryLogAnalysis(Stopwatch stopwatch, Options options, string binlogPath, ILogger logger, CanonicalPathCache canonicalPathCache, PathTransformer pathTransformer) { logger.LogInfo($"Reading compiler calls from binary log {binlogPath}"); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Options.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Options.cs index 7f3815520d62..3ff881d0a85a 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Options.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Options.cs @@ -33,9 +33,9 @@ public sealed class Options : CommonOptions public bool AssemblySensitiveTrap { get; private set; } = false; /// - /// The path to the binary log file, or null if unspecified. + /// The paths to the binary log files, or null if unspecified. /// - public string? BinaryLogPath { get; set; } + public string[]? BinaryLogPaths { get; set; } public static Options CreateWithEnvironment(string[] arguments) { @@ -71,7 +71,7 @@ public override bool HandleOption(string key, string value) ProjectsToLoad.Add(value); return true; case "binlog": - BinaryLogPath = value; + BinaryLogPaths = value.Split(FileUtils.NewLineCharacters, StringSplitOptions.RemoveEmptyEntries); return true; default: return base.HandleOption(key, value); diff --git a/csharp/ql/integration-tests/all-platforms/binlog_multiple/Files.expected b/csharp/ql/integration-tests/all-platforms/binlog_multiple/Files.expected new file mode 100644 index 000000000000..bf3694ff9caa --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/binlog_multiple/Files.expected @@ -0,0 +1,10 @@ +| a/A.cs:0:0:0:0 | a/A.cs | +| a/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs:0:0:0:0 | a/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs | +| a/obj/Debug/net8.0/test.AssemblyInfo.cs:0:0:0:0 | a/obj/Debug/net8.0/test.AssemblyInfo.cs | +| a/obj/Debug/net8.0/test.GlobalUsings.g.cs:0:0:0:0 | a/obj/Debug/net8.0/test.GlobalUsings.g.cs | +| b/B.cs:0:0:0:0 | b/B.cs | +| b/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs:0:0:0:0 | b/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs | +| b/obj/Debug/net8.0/test.AssemblyInfo.cs:0:0:0:0 | b/obj/Debug/net8.0/test.AssemblyInfo.cs | +| b/obj/Debug/net8.0/test.GlobalUsings.g.cs:0:0:0:0 | b/obj/Debug/net8.0/test.GlobalUsings.g.cs | +| generated/a/test.csproj (net8.0)/System.Text.RegularExpressions.Generator/System.Text.RegularExpressions.Generator.RegexGenerator/RegexGenerator.g.cs:0:0:0:0 | generated/a/test.csproj (net8.0)/System.Text.RegularExpressions.Generator/System.Text.RegularExpressions.Generator.RegexGenerator/RegexGenerator.g.cs | +| generated/b/test.csproj (net8.0)/System.Text.RegularExpressions.Generator/System.Text.RegularExpressions.Generator.RegexGenerator/RegexGenerator.g.cs:0:0:0:0 | generated/b/test.csproj (net8.0)/System.Text.RegularExpressions.Generator/System.Text.RegularExpressions.Generator.RegexGenerator/RegexGenerator.g.cs | diff --git a/csharp/ql/integration-tests/all-platforms/binlog_multiple/Files.ql b/csharp/ql/integration-tests/all-platforms/binlog_multiple/Files.ql new file mode 100644 index 000000000000..bea5557a25f1 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/binlog_multiple/Files.ql @@ -0,0 +1,5 @@ +import csharp + +from File f +where f.fromSource() +select f diff --git a/csharp/ql/integration-tests/all-platforms/binlog_multiple/a/A.cs b/csharp/ql/integration-tests/all-platforms/binlog_multiple/a/A.cs new file mode 100644 index 000000000000..2c75e62d019d --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/binlog_multiple/a/A.cs @@ -0,0 +1,9 @@ +using System.Text.RegularExpressions; + +var dummy = "dummy"; + +partial class Test +{ + [GeneratedRegex("abc|def", RegexOptions.IgnoreCase, "en-US")] + private static partial Regex AbcOrDefGeneratedRegex(); +} diff --git a/csharp/ql/integration-tests/all-platforms/binlog_multiple/a/test.csproj b/csharp/ql/integration-tests/all-platforms/binlog_multiple/a/test.csproj new file mode 100644 index 000000000000..91b464afeacc --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/binlog_multiple/a/test.csproj @@ -0,0 +1,10 @@ + + + + Exe + net8.0 + enable + enable + + + diff --git a/csharp/ql/integration-tests/all-platforms/binlog_multiple/b/B.cs b/csharp/ql/integration-tests/all-platforms/binlog_multiple/b/B.cs new file mode 100644 index 000000000000..2c75e62d019d --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/binlog_multiple/b/B.cs @@ -0,0 +1,9 @@ +using System.Text.RegularExpressions; + +var dummy = "dummy"; + +partial class Test +{ + [GeneratedRegex("abc|def", RegexOptions.IgnoreCase, "en-US")] + private static partial Regex AbcOrDefGeneratedRegex(); +} diff --git a/csharp/ql/integration-tests/all-platforms/binlog_multiple/b/test.csproj b/csharp/ql/integration-tests/all-platforms/binlog_multiple/b/test.csproj new file mode 100644 index 000000000000..91b464afeacc --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/binlog_multiple/b/test.csproj @@ -0,0 +1,10 @@ + + + + Exe + net8.0 + enable + enable + + + diff --git a/csharp/ql/integration-tests/all-platforms/binlog_multiple/diagnostics.expected b/csharp/ql/integration-tests/all-platforms/binlog_multiple/diagnostics.expected new file mode 100644 index 000000000000..1a10ae9ded54 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/binlog_multiple/diagnostics.expected @@ -0,0 +1,42 @@ +{ + "markdownMessage": "C# analysis with build-mode 'none' completed.", + "severity": "unknown", + "source": { + "extractorName": "csharp", + "id": "csharp/autobuilder/buildless/complete", + "name": "C# analysis with build-mode 'none' completed" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": false, + "telemetry": true + } +} +{ + "markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.", + "severity": "note", + "source": { + "extractorName": "csharp", + "id": "csharp/autobuilder/buildless/mode-active", + "name": "C# was extracted with build-mode set to 'none'" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} +{ + "markdownMessage": "C# was extracted with the experimental 'binlog' option.", + "severity": "note", + "source": { + "extractorName": "csharp", + "id": "csharp/autobuilder/buildless/binlog", + "name": "C# was extracted with the experimental 'binlog' option" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/csharp/ql/integration-tests/all-platforms/binlog_multiple/global.json b/csharp/ql/integration-tests/all-platforms/binlog_multiple/global.json new file mode 100644 index 000000000000..5c3fd64fbd12 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/binlog_multiple/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "version": "8.0.101" + } +} diff --git a/csharp/ql/integration-tests/all-platforms/binlog_multiple/test.py b/csharp/ql/integration-tests/all-platforms/binlog_multiple/test.py new file mode 100644 index 000000000000..585d86ef57b5 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/binlog_multiple/test.py @@ -0,0 +1,7 @@ +import commands + + +def test(codeql, csharp): + commands.run(["dotnet", "build", "a/test.csproj", "/bl:a.binlog"]) + commands.run(["dotnet", "build", "b/test.csproj", "/bl:b.binlog"]) + codeql.database.create(build_mode="none", extractor_option=["binlog=a.binlog", "binlog=b.binlog"]) From 46f168823c832694a11c7abef2c33d78109e4449 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 11 Nov 2024 14:10:13 +0100 Subject: [PATCH 2/2] Improve code quality --- .../Semmle.Extraction.CSharp/Extractor/Extractor.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Extractor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Extractor.cs index b3ffcd442f44..a2cfa5669df0 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Extractor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Extractor.cs @@ -134,7 +134,7 @@ private static ExitCode RunBinaryLogAnalysis(Stopwatch stopwatch, Options option { case ExitCode.Ok: case ExitCode.Errors: - allFailed &= false; + allFailed = false; break; case ExitCode.Failed: break; @@ -209,11 +209,11 @@ static bool filter(CompilerCall compilerCall) switch (exit) { case ExitCode.Ok: - allFailed &= false; + allFailed = false; logger.LogInfo($" Compilation {diagnosticName} succeeded"); break; case ExitCode.Errors: - allFailed &= false; + allFailed = false; logger.LogWarning($" Compilation {diagnosticName} had errors"); break; case ExitCode.Failed: