diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilations/Compilation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilations/Compilation.cs
index 7fbbc44857f..ae516cd10da 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilations/Compilation.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilations/Compilation.cs
@@ -39,7 +39,35 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.compilation_assembly(this, assembly);
// Arguments
- Compilation.Settings.Args.ForEach((arg, index) => trapFile.compilation_args(this, index, arg));
+ var expandedIndex = 0;
+ for (var i = 0; i < Compilation.Settings.Args.Length; i++)
+ {
+ var arg = Compilation.Settings.Args[i];
+ trapFile.compilation_args(this, i, arg);
+
+ if (CommandLineExtensions.IsFileArgument(arg))
+ {
+ try
+ {
+ var rspFileContent = System.IO.File.ReadAllText(arg[1..]);
+ var rspArgs = CommandLineParser.SplitCommandLineIntoArguments(rspFileContent, removeHashComments: true);
+ foreach (var rspArg in rspArgs)
+ {
+ trapFile.compilation_expanded_args(this, expandedIndex, rspArg);
+ expandedIndex++;
+ }
+ }
+ catch (Exception exc)
+ {
+ Context.ExtractionError($"Couldn't read compiler argument file: {arg}. {exc.Message}", null, null, exc.StackTrace);
+ }
+ }
+ else
+ {
+ trapFile.compilation_expanded_args(this, expandedIndex, arg);
+ expandedIndex++;
+ }
+ }
// Files
Context.Compilation.SyntaxTrees.Select(tree => File.Create(Context, tree.FilePath)).ForEach((file, index) => trapFile.compilation_compiling_files(this, index, file));
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TracingAnalyser.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TracingAnalyser.cs
index c6c8cb0f7aa..22db6710f36 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TracingAnalyser.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TracingAnalyser.cs
@@ -67,8 +67,8 @@ namespace Semmle.Extraction.CSharp
bool argsWritten;
using (var streamWriter = new StreamWriter(new FileStream(tempFile, FileMode.Append, FileAccess.Write)))
{
- streamWriter.WriteLine($"# Arguments to Roslyn: {string.Join(' ', roslynArgs.Where(arg => !arg.StartsWith('@')))}");
- argsWritten = roslynArgs.WriteCommandLine(streamWriter);
+ streamWriter.WriteLine($"# Arguments to Roslyn: {string.Join(' ', roslynArgs.Where(arg => !CommandLineExtensions.IsFileArgument(arg)))}");
+ argsWritten = streamWriter.WriteContentFromArgumentFile(roslynArgs);
}
var hash = FileUtils.ComputeFileHash(tempFile);
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs
index b621ee64813..4b89e1077f0 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs
@@ -68,6 +68,9 @@ namespace Semmle.Extraction.CSharp
internal static void compilation_args(this TextWriter trapFile, Compilation compilation, int index, string arg) =>
trapFile.WriteTuple("compilation_args", compilation, index, arg);
+ internal static void compilation_expanded_args(this TextWriter trapFile, Compilation compilation, int index, string arg) =>
+ trapFile.WriteTuple("compilation_expanded_args", compilation, index, arg);
+
internal static void compilation_compiling_files(this TextWriter trapFile, Compilation compilation, int index, Extraction.Entities.File file) =>
trapFile.WriteTuple("compilation_compiling_files", compilation, index, file);
diff --git a/csharp/extractor/Semmle.Extraction.Tests/Options.cs b/csharp/extractor/Semmle.Extraction.Tests/Options.cs
index 81b750368ca..492d5ce5f5e 100644
--- a/csharp/extractor/Semmle.Extraction.Tests/Options.cs
+++ b/csharp/extractor/Semmle.Extraction.Tests/Options.cs
@@ -210,7 +210,7 @@ namespace Semmle.Extraction.Tests
try
{
File.AppendAllText(file, "Test");
- new string[] { "/noconfig", "@" + file }.WriteCommandLine(sw);
+ sw.WriteContentFromArgumentFile(new string[] { "/noconfig", "@" + file });
Assert.Equal("Test", Regex.Replace(sw.ToString(), @"\t|\n|\r", ""));
}
finally
diff --git a/csharp/extractor/Semmle.Util/CommandLineExtensions.cs b/csharp/extractor/Semmle.Util/CommandLineExtensions.cs
index 2f58877c49f..ad28ac4da92 100644
--- a/csharp/extractor/Semmle.Util/CommandLineExtensions.cs
+++ b/csharp/extractor/Semmle.Util/CommandLineExtensions.cs
@@ -6,22 +6,25 @@ namespace Semmle.Util
{
public static class CommandLineExtensions
{
+ public static bool IsFileArgument(string arg) => arg.StartsWith('@');
+
///
- /// Archives the first "@" argument in a list of command line arguments.
- /// Subsequent "@" arguments are ignored.
+ /// Archives the content of all the "@" arguments in a list of command line arguments.
///
- /// The raw command line arguments.
/// The writer to archive to.
+ /// The raw command line arguments.
/// True iff the file was written.
- public static bool WriteCommandLine(this IEnumerable commandLineArguments, TextWriter textWriter)
+ public static bool WriteContentFromArgumentFile(this TextWriter textWriter, IEnumerable commandLineArguments)
{
var found = false;
- foreach (var arg in commandLineArguments.Where(arg => arg.StartsWith('@')).Select(arg => arg.Substring(1)))
+ foreach (var arg in commandLineArguments.Where(IsFileArgument).Select(arg => arg[1..]))
{
string? line;
using var file = new StreamReader(arg);
while ((line = file.ReadLine()) is not null)
+ {
textWriter.WriteLine(line);
+ }
found = true;
}
return found;
diff --git a/csharp/ql/integration-tests/linux-only/compiler_args/CompilerArgs.expected b/csharp/ql/integration-tests/linux-only/compiler_args/CompilerArgs.expected
new file mode 100644
index 00000000000..25f075b84d2
--- /dev/null
+++ b/csharp/ql/integration-tests/linux-only/compiler_args/CompilerArgs.expected
@@ -0,0 +1,187 @@
+| 0 | /noconfig |
+| 1 | /unsafe- |
+| 2 | /checked- |
+| 4 | /fullpaths |
+| 5 | /nostdlib+ |
+| 9 | /highentropyva+ |
+| 11 | /reference:[...]/8.0.0/ref/net8.0/Microsoft.CSharp.dll |
+| 12 | /reference:[...]/8.0.0/ref/net8.0/Microsoft.VisualBasic.Core.dll |
+| 13 | /reference:[...]/8.0.0/ref/net8.0/Microsoft.VisualBasic.dll |
+| 14 | /reference:[...]/8.0.0/ref/net8.0/Microsoft.Win32.Primitives.dll |
+| 15 | /reference:[...]/8.0.0/ref/net8.0/Microsoft.Win32.Registry.dll |
+| 16 | /reference:[...]/8.0.0/ref/net8.0/mscorlib.dll |
+| 17 | /reference:[...]/8.0.0/ref/net8.0/netstandard.dll |
+| 18 | /reference:[...]/8.0.0/ref/net8.0/System.AppContext.dll |
+| 19 | /reference:[...]/8.0.0/ref/net8.0/System.Buffers.dll |
+| 20 | /reference:[...]/8.0.0/ref/net8.0/System.Collections.Concurrent.dll |
+| 21 | /reference:[...]/8.0.0/ref/net8.0/System.Collections.dll |
+| 22 | /reference:[...]/8.0.0/ref/net8.0/System.Collections.Immutable.dll |
+| 23 | /reference:[...]/8.0.0/ref/net8.0/System.Collections.NonGeneric.dll |
+| 24 | /reference:[...]/8.0.0/ref/net8.0/System.Collections.Specialized.dll |
+| 25 | /reference:[...]/8.0.0/ref/net8.0/System.ComponentModel.Annotations.dll |
+| 26 | /reference:[...]/8.0.0/ref/net8.0/System.ComponentModel.DataAnnotations.dll |
+| 27 | /reference:[...]/8.0.0/ref/net8.0/System.ComponentModel.dll |
+| 28 | /reference:[...]/8.0.0/ref/net8.0/System.ComponentModel.EventBasedAsync.dll |
+| 29 | /reference:[...]/8.0.0/ref/net8.0/System.ComponentModel.Primitives.dll |
+| 30 | /reference:[...]/8.0.0/ref/net8.0/System.ComponentModel.TypeConverter.dll |
+| 31 | /reference:[...]/8.0.0/ref/net8.0/System.Configuration.dll |
+| 32 | /reference:[...]/8.0.0/ref/net8.0/System.Console.dll |
+| 33 | /reference:[...]/8.0.0/ref/net8.0/System.Core.dll |
+| 34 | /reference:[...]/8.0.0/ref/net8.0/System.Data.Common.dll |
+| 35 | /reference:[...]/8.0.0/ref/net8.0/System.Data.DataSetExtensions.dll |
+| 36 | /reference:[...]/8.0.0/ref/net8.0/System.Data.dll |
+| 37 | /reference:[...]/8.0.0/ref/net8.0/System.Diagnostics.Contracts.dll |
+| 38 | /reference:[...]/8.0.0/ref/net8.0/System.Diagnostics.Debug.dll |
+| 39 | /reference:[...]/8.0.0/ref/net8.0/System.Diagnostics.DiagnosticSource.dll |
+| 40 | /reference:[...]/8.0.0/ref/net8.0/System.Diagnostics.FileVersionInfo.dll |
+| 41 | /reference:[...]/8.0.0/ref/net8.0/System.Diagnostics.Process.dll |
+| 42 | /reference:[...]/8.0.0/ref/net8.0/System.Diagnostics.StackTrace.dll |
+| 43 | /reference:[...]/8.0.0/ref/net8.0/System.Diagnostics.TextWriterTraceListener.dll |
+| 44 | /reference:[...]/8.0.0/ref/net8.0/System.Diagnostics.Tools.dll |
+| 45 | /reference:[...]/8.0.0/ref/net8.0/System.Diagnostics.TraceSource.dll |
+| 46 | /reference:[...]/8.0.0/ref/net8.0/System.Diagnostics.Tracing.dll |
+| 47 | /reference:[...]/8.0.0/ref/net8.0/System.dll |
+| 48 | /reference:[...]/8.0.0/ref/net8.0/System.Drawing.dll |
+| 49 | /reference:[...]/8.0.0/ref/net8.0/System.Drawing.Primitives.dll |
+| 50 | /reference:[...]/8.0.0/ref/net8.0/System.Dynamic.Runtime.dll |
+| 51 | /reference:[...]/8.0.0/ref/net8.0/System.Formats.Asn1.dll |
+| 52 | /reference:[...]/8.0.0/ref/net8.0/System.Formats.Tar.dll |
+| 53 | /reference:[...]/8.0.0/ref/net8.0/System.Globalization.Calendars.dll |
+| 54 | /reference:[...]/8.0.0/ref/net8.0/System.Globalization.dll |
+| 55 | /reference:[...]/8.0.0/ref/net8.0/System.Globalization.Extensions.dll |
+| 56 | /reference:[...]/8.0.0/ref/net8.0/System.IO.Compression.Brotli.dll |
+| 57 | /reference:[...]/8.0.0/ref/net8.0/System.IO.Compression.dll |
+| 58 | /reference:[...]/8.0.0/ref/net8.0/System.IO.Compression.FileSystem.dll |
+| 59 | /reference:[...]/8.0.0/ref/net8.0/System.IO.Compression.ZipFile.dll |
+| 60 | /reference:[...]/8.0.0/ref/net8.0/System.IO.dll |
+| 61 | /reference:[...]/8.0.0/ref/net8.0/System.IO.FileSystem.AccessControl.dll |
+| 62 | /reference:[...]/8.0.0/ref/net8.0/System.IO.FileSystem.dll |
+| 63 | /reference:[...]/8.0.0/ref/net8.0/System.IO.FileSystem.DriveInfo.dll |
+| 64 | /reference:[...]/8.0.0/ref/net8.0/System.IO.FileSystem.Primitives.dll |
+| 65 | /reference:[...]/8.0.0/ref/net8.0/System.IO.FileSystem.Watcher.dll |
+| 66 | /reference:[...]/8.0.0/ref/net8.0/System.IO.IsolatedStorage.dll |
+| 67 | /reference:[...]/8.0.0/ref/net8.0/System.IO.MemoryMappedFiles.dll |
+| 68 | /reference:[...]/8.0.0/ref/net8.0/System.IO.Pipes.AccessControl.dll |
+| 69 | /reference:[...]/8.0.0/ref/net8.0/System.IO.Pipes.dll |
+| 70 | /reference:[...]/8.0.0/ref/net8.0/System.IO.UnmanagedMemoryStream.dll |
+| 71 | /reference:[...]/8.0.0/ref/net8.0/System.Linq.dll |
+| 72 | /reference:[...]/8.0.0/ref/net8.0/System.Linq.Expressions.dll |
+| 73 | /reference:[...]/8.0.0/ref/net8.0/System.Linq.Parallel.dll |
+| 74 | /reference:[...]/8.0.0/ref/net8.0/System.Linq.Queryable.dll |
+| 75 | /reference:[...]/8.0.0/ref/net8.0/System.Memory.dll |
+| 76 | /reference:[...]/8.0.0/ref/net8.0/System.Net.dll |
+| 77 | /reference:[...]/8.0.0/ref/net8.0/System.Net.Http.dll |
+| 78 | /reference:[...]/8.0.0/ref/net8.0/System.Net.Http.Json.dll |
+| 79 | /reference:[...]/8.0.0/ref/net8.0/System.Net.HttpListener.dll |
+| 80 | /reference:[...]/8.0.0/ref/net8.0/System.Net.Mail.dll |
+| 81 | /reference:[...]/8.0.0/ref/net8.0/System.Net.NameResolution.dll |
+| 82 | /reference:[...]/8.0.0/ref/net8.0/System.Net.NetworkInformation.dll |
+| 83 | /reference:[...]/8.0.0/ref/net8.0/System.Net.Ping.dll |
+| 84 | /reference:[...]/8.0.0/ref/net8.0/System.Net.Primitives.dll |
+| 85 | /reference:[...]/8.0.0/ref/net8.0/System.Net.Quic.dll |
+| 86 | /reference:[...]/8.0.0/ref/net8.0/System.Net.Requests.dll |
+| 87 | /reference:[...]/8.0.0/ref/net8.0/System.Net.Security.dll |
+| 88 | /reference:[...]/8.0.0/ref/net8.0/System.Net.ServicePoint.dll |
+| 89 | /reference:[...]/8.0.0/ref/net8.0/System.Net.Sockets.dll |
+| 90 | /reference:[...]/8.0.0/ref/net8.0/System.Net.WebClient.dll |
+| 91 | /reference:[...]/8.0.0/ref/net8.0/System.Net.WebHeaderCollection.dll |
+| 92 | /reference:[...]/8.0.0/ref/net8.0/System.Net.WebProxy.dll |
+| 93 | /reference:[...]/8.0.0/ref/net8.0/System.Net.WebSockets.Client.dll |
+| 94 | /reference:[...]/8.0.0/ref/net8.0/System.Net.WebSockets.dll |
+| 95 | /reference:[...]/8.0.0/ref/net8.0/System.Numerics.dll |
+| 96 | /reference:[...]/8.0.0/ref/net8.0/System.Numerics.Vectors.dll |
+| 97 | /reference:[...]/8.0.0/ref/net8.0/System.ObjectModel.dll |
+| 98 | /reference:[...]/8.0.0/ref/net8.0/System.Reflection.DispatchProxy.dll |
+| 99 | /reference:[...]/8.0.0/ref/net8.0/System.Reflection.dll |
+| 100 | /reference:[...]/8.0.0/ref/net8.0/System.Reflection.Emit.dll |
+| 101 | /reference:[...]/8.0.0/ref/net8.0/System.Reflection.Emit.ILGeneration.dll |
+| 102 | /reference:[...]/8.0.0/ref/net8.0/System.Reflection.Emit.Lightweight.dll |
+| 103 | /reference:[...]/8.0.0/ref/net8.0/System.Reflection.Extensions.dll |
+| 104 | /reference:[...]/8.0.0/ref/net8.0/System.Reflection.Metadata.dll |
+| 105 | /reference:[...]/8.0.0/ref/net8.0/System.Reflection.Primitives.dll |
+| 106 | /reference:[...]/8.0.0/ref/net8.0/System.Reflection.TypeExtensions.dll |
+| 107 | /reference:[...]/8.0.0/ref/net8.0/System.Resources.Reader.dll |
+| 108 | /reference:[...]/8.0.0/ref/net8.0/System.Resources.ResourceManager.dll |
+| 109 | /reference:[...]/8.0.0/ref/net8.0/System.Resources.Writer.dll |
+| 110 | /reference:[...]/8.0.0/ref/net8.0/System.Runtime.CompilerServices.Unsafe.dll |
+| 111 | /reference:[...]/8.0.0/ref/net8.0/System.Runtime.CompilerServices.VisualC.dll |
+| 112 | /reference:[...]/8.0.0/ref/net8.0/System.Runtime.dll |
+| 113 | /reference:[...]/8.0.0/ref/net8.0/System.Runtime.Extensions.dll |
+| 114 | /reference:[...]/8.0.0/ref/net8.0/System.Runtime.Handles.dll |
+| 115 | /reference:[...]/8.0.0/ref/net8.0/System.Runtime.InteropServices.dll |
+| 116 | /reference:[...]/8.0.0/ref/net8.0/System.Runtime.InteropServices.JavaScript.dll |
+| 117 | /reference:[...]/8.0.0/ref/net8.0/System.Runtime.InteropServices.RuntimeInformation.dll |
+| 118 | /reference:[...]/8.0.0/ref/net8.0/System.Runtime.Intrinsics.dll |
+| 119 | /reference:[...]/8.0.0/ref/net8.0/System.Runtime.Loader.dll |
+| 120 | /reference:[...]/8.0.0/ref/net8.0/System.Runtime.Numerics.dll |
+| 121 | /reference:[...]/8.0.0/ref/net8.0/System.Runtime.Serialization.dll |
+| 122 | /reference:[...]/8.0.0/ref/net8.0/System.Runtime.Serialization.Formatters.dll |
+| 123 | /reference:[...]/8.0.0/ref/net8.0/System.Runtime.Serialization.Json.dll |
+| 124 | /reference:[...]/8.0.0/ref/net8.0/System.Runtime.Serialization.Primitives.dll |
+| 125 | /reference:[...]/8.0.0/ref/net8.0/System.Runtime.Serialization.Xml.dll |
+| 126 | /reference:[...]/8.0.0/ref/net8.0/System.Security.AccessControl.dll |
+| 127 | /reference:[...]/8.0.0/ref/net8.0/System.Security.Claims.dll |
+| 128 | /reference:[...]/8.0.0/ref/net8.0/System.Security.Cryptography.Algorithms.dll |
+| 129 | /reference:[...]/8.0.0/ref/net8.0/System.Security.Cryptography.Cng.dll |
+| 130 | /reference:[...]/8.0.0/ref/net8.0/System.Security.Cryptography.Csp.dll |
+| 131 | /reference:[...]/8.0.0/ref/net8.0/System.Security.Cryptography.dll |
+| 132 | /reference:[...]/8.0.0/ref/net8.0/System.Security.Cryptography.Encoding.dll |
+| 133 | /reference:[...]/8.0.0/ref/net8.0/System.Security.Cryptography.OpenSsl.dll |
+| 134 | /reference:[...]/8.0.0/ref/net8.0/System.Security.Cryptography.Primitives.dll |
+| 135 | /reference:[...]/8.0.0/ref/net8.0/System.Security.Cryptography.X509Certificates.dll |
+| 136 | /reference:[...]/8.0.0/ref/net8.0/System.Security.dll |
+| 137 | /reference:[...]/8.0.0/ref/net8.0/System.Security.Principal.dll |
+| 138 | /reference:[...]/8.0.0/ref/net8.0/System.Security.Principal.Windows.dll |
+| 139 | /reference:[...]/8.0.0/ref/net8.0/System.Security.SecureString.dll |
+| 140 | /reference:[...]/8.0.0/ref/net8.0/System.ServiceModel.Web.dll |
+| 141 | /reference:[...]/8.0.0/ref/net8.0/System.ServiceProcess.dll |
+| 142 | /reference:[...]/8.0.0/ref/net8.0/System.Text.Encoding.CodePages.dll |
+| 143 | /reference:[...]/8.0.0/ref/net8.0/System.Text.Encoding.dll |
+| 144 | /reference:[...]/8.0.0/ref/net8.0/System.Text.Encoding.Extensions.dll |
+| 145 | /reference:[...]/8.0.0/ref/net8.0/System.Text.Encodings.Web.dll |
+| 146 | /reference:[...]/8.0.0/ref/net8.0/System.Text.Json.dll |
+| 147 | /reference:[...]/8.0.0/ref/net8.0/System.Text.RegularExpressions.dll |
+| 148 | /reference:[...]/8.0.0/ref/net8.0/System.Threading.Channels.dll |
+| 149 | /reference:[...]/8.0.0/ref/net8.0/System.Threading.dll |
+| 150 | /reference:[...]/8.0.0/ref/net8.0/System.Threading.Overlapped.dll |
+| 151 | /reference:[...]/8.0.0/ref/net8.0/System.Threading.Tasks.Dataflow.dll |
+| 152 | /reference:[...]/8.0.0/ref/net8.0/System.Threading.Tasks.dll |
+| 153 | /reference:[...]/8.0.0/ref/net8.0/System.Threading.Tasks.Extensions.dll |
+| 154 | /reference:[...]/8.0.0/ref/net8.0/System.Threading.Tasks.Parallel.dll |
+| 155 | /reference:[...]/8.0.0/ref/net8.0/System.Threading.Thread.dll |
+| 156 | /reference:[...]/8.0.0/ref/net8.0/System.Threading.ThreadPool.dll |
+| 157 | /reference:[...]/8.0.0/ref/net8.0/System.Threading.Timer.dll |
+| 158 | /reference:[...]/8.0.0/ref/net8.0/System.Transactions.dll |
+| 159 | /reference:[...]/8.0.0/ref/net8.0/System.Transactions.Local.dll |
+| 160 | /reference:[...]/8.0.0/ref/net8.0/System.ValueTuple.dll |
+| 161 | /reference:[...]/8.0.0/ref/net8.0/System.Web.dll |
+| 162 | /reference:[...]/8.0.0/ref/net8.0/System.Web.HttpUtility.dll |
+| 163 | /reference:[...]/8.0.0/ref/net8.0/System.Windows.dll |
+| 164 | /reference:[...]/8.0.0/ref/net8.0/System.Xml.dll |
+| 165 | /reference:[...]/8.0.0/ref/net8.0/System.Xml.Linq.dll |
+| 166 | /reference:[...]/8.0.0/ref/net8.0/System.Xml.ReaderWriter.dll |
+| 167 | /reference:[...]/8.0.0/ref/net8.0/System.Xml.Serialization.dll |
+| 168 | /reference:[...]/8.0.0/ref/net8.0/System.Xml.XDocument.dll |
+| 169 | /reference:[...]/8.0.0/ref/net8.0/System.Xml.XmlDocument.dll |
+| 170 | /reference:[...]/8.0.0/ref/net8.0/System.Xml.XmlSerializer.dll |
+| 171 | /reference:[...]/8.0.0/ref/net8.0/System.Xml.XPath.dll |
+| 172 | /reference:[...]/8.0.0/ref/net8.0/System.Xml.XPath.XDocument.dll |
+| 173 | /reference:[...]/8.0.0/ref/net8.0/WindowsBase.dll |
+| 174 | /debug+ |
+| 178 | /optimize- |
+| 182 | /warnaserror- |
+| 183 | /utf8output |
+| 184 | /deterministic+ |
+| 193 | /analyzerconfig:[...]/8.0.100/Sdks/Microsoft.NET.Sdk/analyzers/build/config/analysislevel_8_default.globalconfig |
+| 194 | /analyzer:[...]/8.0.100/Sdks/Microsoft.NET.Sdk/targets/../analyzers/Microsoft.CodeAnalysis.CSharp.NetAnalyzers.dll |
+| 195 | /analyzer:[...]/8.0.100/Sdks/Microsoft.NET.Sdk/targets/../analyzers/Microsoft.CodeAnalysis.NetAnalyzers.dll |
+| 196 | /analyzer:[...]/8.0.0/analyzers/dotnet/cs/Microsoft.Interop.ComInterfaceGenerator.dll |
+| 197 | /analyzer:[...]/8.0.0/analyzers/dotnet/cs/Microsoft.Interop.JavaScript.JSImportGenerator.dll |
+| 198 | /analyzer:[...]/8.0.0/analyzers/dotnet/cs/Microsoft.Interop.LibraryImportGenerator.dll |
+| 199 | /analyzer:[...]/8.0.0/analyzers/dotnet/cs/Microsoft.Interop.SourceGeneration.dll |
+| 200 | /analyzer:[...]/8.0.0/analyzers/dotnet/cs/System.Text.Json.SourceGeneration.dll |
+| 201 | /analyzer:[...]/8.0.0/analyzers/dotnet/cs/System.Text.RegularExpressions.Generator.dll |
+| 202 | Program.cs |
+| 203 | obj/Debug/net8.0/test.GlobalUsings.g.cs |
+| 204 | obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs |
+| 205 | obj/Debug/net8.0/test.AssemblyInfo.cs |
diff --git a/csharp/ql/integration-tests/linux-only/compiler_args/CompilerArgs.ql b/csharp/ql/integration-tests/linux-only/compiler_args/CompilerArgs.ql
new file mode 100644
index 00000000000..774388896e9
--- /dev/null
+++ b/csharp/ql/integration-tests/linux-only/compiler_args/CompilerArgs.ql
@@ -0,0 +1,17 @@
+import csharp
+import semmle.code.csharp.commons.Compilation
+
+bindingset[arg]
+private string normalize(string arg) {
+ not exists(arg.indexOf(":")) and result = arg
+ or
+ exists(int i, int j |
+ i = arg.indexOf(":") and
+ j = arg.indexOf("/8.0") and
+ result = arg.substring(0, i + 1) + "[...]" + arg.substring(j, arg.length())
+ )
+}
+
+from Compilation c, int i, string s
+where s = normalize(c.getExpandedArgument(i))
+select i, s
diff --git a/csharp/ql/integration-tests/linux-only/compiler_args/Program.cs b/csharp/ql/integration-tests/linux-only/compiler_args/Program.cs
new file mode 100644
index 00000000000..47eee48cc79
--- /dev/null
+++ b/csharp/ql/integration-tests/linux-only/compiler_args/Program.cs
@@ -0,0 +1 @@
+var dummy = "dummy";
\ No newline at end of file
diff --git a/csharp/ql/integration-tests/linux-only/compiler_args/global.json b/csharp/ql/integration-tests/linux-only/compiler_args/global.json
new file mode 100644
index 00000000000..33021c04f16
--- /dev/null
+++ b/csharp/ql/integration-tests/linux-only/compiler_args/global.json
@@ -0,0 +1,5 @@
+{
+ "sdk": {
+ "version": "8.0.100"
+ }
+}
\ No newline at end of file
diff --git a/csharp/ql/integration-tests/linux-only/compiler_args/test.csproj b/csharp/ql/integration-tests/linux-only/compiler_args/test.csproj
new file mode 100644
index 00000000000..324eba5d4ef
--- /dev/null
+++ b/csharp/ql/integration-tests/linux-only/compiler_args/test.csproj
@@ -0,0 +1,14 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/csharp/ql/integration-tests/linux-only/compiler_args/test.py b/csharp/ql/integration-tests/linux-only/compiler_args/test.py
new file mode 100644
index 00000000000..6a1f8864145
--- /dev/null
+++ b/csharp/ql/integration-tests/linux-only/compiler_args/test.py
@@ -0,0 +1,3 @@
+from create_database_utils import *
+
+run_codeql_database_create([], lang="csharp", extra_args=["--extractor-option=cil=false"])
diff --git a/csharp/ql/lib/semmle/code/csharp/commons/Compilation.qll b/csharp/ql/lib/semmle/code/csharp/commons/Compilation.qll
index a8eaad13b80..df53084c835 100644
--- a/csharp/ql/lib/semmle/code/csharp/commons/Compilation.qll
+++ b/csharp/ql/lib/semmle/code/csharp/commons/Compilation.qll
@@ -23,6 +23,22 @@ class Compilation extends @compilation {
result = concat(int i | exists(this.getArgument(i)) | this.getArgument(i), " ")
}
+ /**
+ * Gets the `i`th expanded command line argument. This is similar to
+ * `getArgument`, but for a `@someFile.rsp` argument, it includes the arguments
+ * from that file, rather than just taking the argument literally.
+ */
+ string getExpandedArgument(int i) { compilation_expanded_args(this, i, result) }
+
+ /**
+ * Gets the expanded arguments as a concatenated string. This is similar to
+ * `getArguments`, but for a `@someFile.rsp` argument, it includes the arguments
+ * from that file, rather than just taking the argument literally.
+ */
+ string getExpandedArguments() {
+ result = concat(int i | exists(this.getExpandedArgument(i)) | this.getExpandedArgument(i), " ")
+ }
+
/** Gets the 'i'th source file in this compilation. */
File getFileCompiled(int i) { compilation_compiling_files(this, i, result) }
diff --git a/csharp/ql/lib/semmlecode.csharp.dbscheme b/csharp/ql/lib/semmlecode.csharp.dbscheme
index fc9c7ab844a..f145a9a7275 100644
--- a/csharp/ql/lib/semmlecode.csharp.dbscheme
+++ b/csharp/ql/lib/semmlecode.csharp.dbscheme
@@ -47,6 +47,19 @@ compilation_args(
string arg : string ref
);
+/**
+ * The expanded arguments that were passed to the extractor for a
+ * compiler invocation. This is similar to `compilation_args`, but
+ * for a `@someFile.rsp` argument, it includes the arguments from that
+ * file, rather than just taking the argument literally.
+ */
+#keyset[id, num]
+compilation_expanded_args(
+ int id : @compilation ref,
+ int num : int ref,
+ string arg : string ref
+);
+
/**
* The source files that are compiled by a compiler invocation.
* If `id` is for the compiler invocation