diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs b/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs index 7eb0d539812..a8ce9653916 100644 --- a/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs +++ b/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs @@ -158,6 +158,10 @@ namespace Semmle.Autobuild.CSharp.Tests bool IBuildActions.IsMacOs() => IsMacOs; + public bool IsLinux { get; set; } + + bool IBuildActions.IsLinux() => IsLinux; + public bool IsRunningOnAppleSilicon { get; set; } bool IBuildActions.IsRunningOnAppleSilicon() => IsRunningOnAppleSilicon; diff --git a/csharp/autobuilder/Semmle.Autobuild.Cpp.Tests/BuildScripts.cs b/csharp/autobuilder/Semmle.Autobuild.Cpp.Tests/BuildScripts.cs index afa4ea4b41c..fd5e4073d6d 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Cpp.Tests/BuildScripts.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Cpp.Tests/BuildScripts.cs @@ -146,6 +146,10 @@ namespace Semmle.Autobuild.Cpp.Tests bool IBuildActions.IsMacOs() => IsMacOs; + public bool IsLinux { get; set; } + + bool IBuildActions.IsLinux() => IsLinux; + public bool IsRunningOnAppleSilicon { get; set; } bool IBuildActions.IsRunningOnAppleSilicon() => IsRunningOnAppleSilicon; diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs index 4fce6f3eb65..8c64798987f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs @@ -814,6 +814,43 @@ namespace Semmle.Extraction.CSharp.DependencyFetching private (HashSet explicitFeeds, HashSet allFeeds) GetAllFeeds() { var nugetConfigs = fileProvider.NugetConfigs; + + // On systems with case-sensitive file systems (for simplicity, we assume that is Linux), the + // filenames of NuGet configuration files must be named correctly. For compatibility with projects + // that are typically built on Windows or macOS where this doesn't matter, we accept all variants + // of `nuget.config` ourselves. However, `dotnet` does not. If we detect that incorrectly-named + // files are present, we emit a diagnostic to warn the user. + if (SystemBuildActions.Instance.IsLinux()) + { + string[] acceptedNugetConfigNames = ["nuget.config", "NuGet.config", "NuGet.Config"]; + var invalidNugetConfigs = nugetConfigs + .Where(path => acceptedNugetConfigNames.Contains(Path.GetFileName(path))); + + if (invalidNugetConfigs.Count() > 0) + { + this.logger.LogWarning(string.Format( + "Found incorrectly named NuGet configuration files: {0}", + string.Join(", ", invalidNugetConfigs) + )); + this.diagnosticsWriter.AddEntry(new DiagnosticMessage( + Language.CSharp, + "buildless/case-sensitive-nuget-config", + "Found NuGet configuration files which are not correctly named", + visibility: new DiagnosticMessage.TspVisibility(statusPage: true, cliSummaryTable: true, telemetry: true), + markdownMessage: string.Format( + "On platforms with case-sensitive file systems, NuGet only accepts files with one of the following names: {0}.\n\n" + + "CodeQL found the following files while performing an analysis on a platform with a case-sensitive file system:\n\n" + + "{1}\n\n" + + "To avoid unexpected results, rename these files to match the casing of one of the accepted filenames.", + string.Join(", ", acceptedNugetConfigNames), + string.Join("\n", invalidNugetConfigs.Select(path => string.Format("- `{0}`", path))) + ), + severity: DiagnosticMessage.TspSeverity.Warning + )); + } + } + + // Find feeds that are explicitly configured in the NuGet configuration files that we found. var explicitFeeds = nugetConfigs .SelectMany(config => GetFeeds(() => dotnet.GetNugetFeeds(config))) .ToHashSet(); diff --git a/csharp/extractor/Semmle.Util/BuildActions.cs b/csharp/extractor/Semmle.Util/BuildActions.cs index 38210402945..09696564efc 100644 --- a/csharp/extractor/Semmle.Util/BuildActions.cs +++ b/csharp/extractor/Semmle.Util/BuildActions.cs @@ -119,6 +119,12 @@ namespace Semmle.Util /// True if we are running on macOS. bool IsMacOs(); + /// + /// Gets a value indicating whether we are running on Linux. + /// + /// True if we are running on Linux. + bool IsLinux(); + /// /// Gets a value indicating whether we are running on Apple Silicon. /// @@ -246,6 +252,8 @@ namespace Semmle.Util bool IBuildActions.IsMacOs() => RuntimeInformation.IsOSPlatform(OSPlatform.OSX); + bool IBuildActions.IsLinux() => RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + bool IBuildActions.IsRunningOnAppleSilicon() { var thisBuildActions = (IBuildActions)this;