diff --git a/csharp/ql/integration-tests/all-platforms/dotnet_build/Program.cs b/csharp/ql/integration-tests/all-platforms/dotnet_build/Program.cs index e9708d0b5d2f..bd44629f7e23 100644 --- a/csharp/ql/integration-tests/all-platforms/dotnet_build/Program.cs +++ b/csharp/ql/integration-tests/all-platforms/dotnet_build/Program.cs @@ -1 +1 @@ -Console.WriteLine(args[0]); +Console.WriteLine($"{string.Join(",", args)}"); diff --git a/csharp/ql/integration-tests/all-platforms/dotnet_build/test.py b/csharp/ql/integration-tests/all-platforms/dotnet_build/test.py index 8bc8d33ba1db..6680a708e706 100644 --- a/csharp/ql/integration-tests/all-platforms/dotnet_build/test.py +++ b/csharp/ql/integration-tests/all-platforms/dotnet_build/test.py @@ -1,5 +1,16 @@ from create_database_utils import * from diagnostics_test_utils import * -run_codeql_database_create(['dotnet build'], db=None, lang="csharp") -check_diagnostics() +def check_build_out(msg, s): + if "[build-stdout] " + msg not in s: + raise Exception("The C# tracer did not interpret the dotnet path-to-application command correctly.") + +run_codeql_database_create(['dotnet build'], test_db="test1-db", lang="csharp") +check_diagnostics(test_db="test1-db") + +# This test checks that we don't inject any flags when running the application using `dotnet` +my_dir = "my_program" +my_abs_path = os.path.abspath(f"{my_dir}/dotnet_build.dll") +s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test1-db', 'dotnet build -o my_program', f'dotnet {my_abs_path} build is not a subcommand'], "test2-db", "csharp") +check_build_out("build,is,not,a,subcommand", s) +check_diagnostics(test_db="test2-db") diff --git a/csharp/ql/integration-tests/all-platforms/dotnet_run/test.py b/csharp/ql/integration-tests/all-platforms/dotnet_run/test.py index ef306b1842bb..d1a44bdb1feb 100644 --- a/csharp/ql/integration-tests/all-platforms/dotnet_run/test.py +++ b/csharp/ql/integration-tests/all-platforms/dotnet_run/test.py @@ -1,65 +1,57 @@ from create_database_utils import * from diagnostics_test_utils import * -def run_codeql_database_create_stdout(args, dbname): - stdout = open(dbname + "file.txt", 'w+') - run_codeql_database_create(args, test_db=dbname, db=None, stdout=stdout, lang="csharp") - stdout.seek(0) - s = stdout.read() - stdout.close() - return s - def check_build_out(msg, s): if "[build-stdout] " + msg not in s: - raise Exception("The C# extractor did not interpret the 'dotnet run' command correctly") + raise Exception("The C# tracer did not interpret the 'dotnet run' command correctly") # no arguments -s = run_codeql_database_create_stdout(['dotnet run'], "test-db") +s = run_codeql_database_create_stdout(['dotnet run'], "test-db", "csharp") check_build_out("Default reply", s) check_diagnostics() # no arguments, but `--` -s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test-db', 'dotnet run --'], "test2-db") +s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test-db', 'dotnet run --'], "test2-db", "csharp") check_build_out("Default reply", s) check_diagnostics(test_db="test2-db") # one argument, no `--` -s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test2-db', 'dotnet run hello'], "test3-db") +s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test2-db', 'dotnet run hello'], "test3-db", "csharp") check_build_out("Default reply", s) check_diagnostics(test_db="test3-db") # one argument, but `--` -s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test3-db', 'dotnet run -- hello'], "test4-db") +s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test3-db', 'dotnet run -- hello'], "test4-db", "csharp") check_build_out("Default reply", s) check_diagnostics(test_db="test4-db") # two arguments, no `--` -s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test4-db', 'dotnet run hello world'], "test5-db") +s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test4-db', 'dotnet run hello world'], "test5-db", "csharp") check_build_out("hello, world", s) check_diagnostics(test_db="test5-db") # two arguments, and `--` -s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test5-db', 'dotnet run -- hello world'], "test6-db") +s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test5-db', 'dotnet run -- hello world'], "test6-db", "csharp") check_build_out("hello, world", s) check_diagnostics(test_db="test6-db") # shared compilation enabled; tracer should override by changing the command # to `dotnet run -p:UseSharedCompilation=true -p:UseSharedCompilation=false -- hello world` -s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test6-db', 'dotnet run -p:UseSharedCompilation=true -- hello world'], "test7-db") +s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test6-db', 'dotnet run -p:UseSharedCompilation=true -- hello world'], "test7-db", "csharp") check_build_out("hello, world", s) check_diagnostics(test_db="test7-db") # option passed into `dotnet run` -s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test7-db', 'dotnet build', 'dotnet run --no-build hello world'], "test8-db") +s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test7-db', 'dotnet build', 'dotnet run --no-build hello world'], "test8-db", "csharp") check_build_out("hello, world", s) check_diagnostics(test_db="test8-db") # two arguments, no '--' (first argument quoted) -s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test8-db', 'dotnet run "hello world part1" part2'], "test9-db") +s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test8-db', 'dotnet run "hello world part1" part2'], "test9-db", "csharp") check_build_out("hello world part1, part2", s) check_diagnostics(test_db="test9-db") # two arguments, no '--' (second argument quoted) and using dotnet to execute dotnet -s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test9-db', 'dotnet dotnet run part1 "hello world part2"'], "test10-db") +s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test9-db', 'dotnet dotnet run part1 "hello world part2"'], "test10-db", "csharp") check_build_out("part1, hello world part2", s) check_diagnostics(test_db="test10-db") diff --git a/csharp/tools/tracing-config.lua b/csharp/tools/tracing-config.lua index 55f803c5adbe..5fc1cc8e80eb 100644 --- a/csharp/tools/tracing-config.lua +++ b/csharp/tools/tracing-config.lua @@ -23,6 +23,10 @@ function RegisterExtractorPack(id) not isDotnetPath(arg) end + local function isPathToExecutable(path) + return path:match('%.exe$') or path:match('%.dll') + end + function DotnetMatcherBuild(compilerName, compilerPath, compilerArguments, _languageId) if not isDotnet(compilerName) then @@ -56,8 +60,16 @@ function RegisterExtractorPack(id) NativeArgumentsToArgv(compilerArguments.nativeArgumentPointer) end for i, arg in ipairs(argv) do + -- if dotnet is being used to execute any application except dotnet itself, we should + -- not inject any flags. + if not match and isPathToExecutable(arg) and not isDotnetPath(arg) then + Log(1, 'Execute a .NET application usage detected') + Log(1, 'Dotnet path-to-application detected: %s', arg) + break + end if isPossibleDotnetSubcommand(arg) then - if (not match) and inSubCommandPosition then + if not match and inSubCommandPosition then + Log(1, 'Execute a .NET SDK command usage detected') Log(1, 'Dotnet subcommand detected: %s', arg) end -- only respond to strings that look like sub-command names if we have not yet @@ -85,7 +97,7 @@ function RegisterExtractorPack(id) end -- for `dotnet test`, we should not append `-p:UseSharedCompilation=false` to the command line -- if an `exe` or `dll` is passed as an argument as the call is forwarded to vstest. - if testMatch and (arg:match('%.exe$') or arg:match('%.dll')) then + if testMatch and isPathToExecutable(arg) then match = false break end