mirror of
https://github.com/github/codeql.git
synced 2026-04-24 08:15:14 +02:00
Merge branch 'main' into redsun82/swift-integration-test-pack
This commit is contained in:
@@ -26,9 +26,10 @@ runs:
|
||||
echo "merge_base=$MERGE_BASE" >> $GITHUB_ENV
|
||||
- name: Read CodeQL query compilation - PR
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
uses: actions/cache@v3
|
||||
uses: erik-krogh/actions-cache@a88d0603fe5fb5606db9f002dfcadeb32b5f84c6
|
||||
with:
|
||||
path: '**/.cache'
|
||||
read-only: true
|
||||
key: codeql-compile-${{ inputs.key }}-pr-${{ github.sha }} # deliberately not using the `compile-compile-main` keys here.
|
||||
restore-keys: |
|
||||
codeql-compile-${{ inputs.key }}-${{ github.base_ref }}-${{ env.merge_base }}
|
||||
@@ -36,7 +37,7 @@ runs:
|
||||
codeql-compile-${{ inputs.key }}-main-
|
||||
- name: Fill CodeQL query compilation cache - main
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
uses: actions/cache@v3
|
||||
uses: erik-krogh/actions-cache@a88d0603fe5fb5606db9f002dfcadeb32b5f84c6
|
||||
with:
|
||||
path: '**/.cache'
|
||||
key: codeql-compile-${{ inputs.key }}-${{ github.ref_name }}-${{ github.sha }} # just fill on main
|
||||
|
||||
86
.github/workflows/csharp-qltest.yml
vendored
Normal file
86
.github/workflows/csharp-qltest.yml
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
name: "C#: Run QL Tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "csharp/**"
|
||||
- "shared/**"
|
||||
- .github/actions/fetch-codeql/action.yml
|
||||
- codeql-workspace.yml
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
pull_request:
|
||||
paths:
|
||||
- "csharp/**"
|
||||
- "shared/**"
|
||||
- .github/workflows/csharp-qltest.yml
|
||||
- .github/actions/fetch-codeql/action.yml
|
||||
- codeql-workspace.yml
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: csharp
|
||||
|
||||
jobs:
|
||||
qlupgrade:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
- name: Check DB upgrade scripts
|
||||
run: |
|
||||
echo >empty.trap
|
||||
codeql dataset import -S ql/lib/upgrades/initial/semmlecode.csharp.dbscheme testdb empty.trap
|
||||
codeql dataset upgrade testdb --additional-packs ql/lib
|
||||
diff -q testdb/semmlecode.csharp.dbscheme ql/lib/semmlecode.csharp.dbscheme
|
||||
- name: Check DB downgrade scripts
|
||||
run: |
|
||||
echo >empty.trap
|
||||
rm -rf testdb; codeql dataset import -S ql/lib/semmlecode.csharp.dbscheme testdb empty.trap
|
||||
codeql resolve upgrades --format=lines --allow-downgrades --additional-packs downgrades \
|
||||
--dbscheme=ql/lib/semmlecode.csharp.dbscheme --target-dbscheme=downgrades/initial/semmlecode.csharp.dbscheme |
|
||||
xargs codeql execute upgrades testdb
|
||||
diff -q testdb/semmlecode.csharp.dbscheme downgrades/initial/semmlecode.csharp.dbscheme
|
||||
qltest:
|
||||
runs-on: ubuntu-latest-xl
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
slice: ["1/2", "2/2"]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
- uses: ./csharp/actions/create-extractor-pack
|
||||
- name: Cache compilation cache
|
||||
id: query-cache
|
||||
uses: ./.github/actions/cache-query-compilation
|
||||
with:
|
||||
key: csharp-qltest-${{ matrix.slice }}
|
||||
- name: Run QL tests
|
||||
run: |
|
||||
CODEQL_PATH=$(gh codeql version --format=json | jq -r .unpackedLocation)
|
||||
# The legacy ASP extractor is not in this repo, so take the one from the nightly build
|
||||
mv "$CODEQL_PATH/csharp/tools/extractor-asp.jar" "${{ github.workspace }}/csharp/extractor-pack/tools"
|
||||
# Safe guard against using the bundled extractor
|
||||
rm -rf "$CODEQL_PATH/csharp"
|
||||
codeql test run --threads=0 --ram 52000 --slice ${{ matrix.slice }} --search-path "${{ github.workspace }}/csharp/extractor-pack" --check-databases --check-undefined-labels --check-repeated-labels --check-redefined-labels --consistency-queries ql/consistency-queries ql/test --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
unit-tests:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup dotnet
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 6.0.202
|
||||
- name: Extractor unit tests
|
||||
run: |
|
||||
dotnet test -p:RuntimeFrameworkVersion=6.0.4 "${{ github.workspace }}/csharp/extractor/Semmle.Util.Tests"
|
||||
dotnet test -p:RuntimeFrameworkVersion=6.0.4 "${{ github.workspace }}/csharp/extractor/Semmle.Extraction.Tests"
|
||||
dotnet test -p:RuntimeFrameworkVersion=6.0.4 "${{ github.workspace }}/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests"
|
||||
dotnet test -p:RuntimeFrameworkVersion=6.0.4 "${{ github.workspace }}/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests"
|
||||
18
.github/workflows/ruby-build.yml
vendored
18
.github/workflows/ruby-build.yml
vendored
@@ -48,7 +48,19 @@ jobs:
|
||||
run: |
|
||||
brew install gnu-tar
|
||||
echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH
|
||||
- name: Cache entire extractor
|
||||
uses: actions/cache@v3
|
||||
id: cache-extractor
|
||||
with:
|
||||
path: |
|
||||
ruby/target/release/ruby-autobuilder
|
||||
ruby/target/release/ruby-autobuilder.exe
|
||||
ruby/target/release/ruby-extractor
|
||||
ruby/target/release/ruby-extractor.exe
|
||||
ruby/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll
|
||||
key: ${{ runner.os }}-ruby-extractor-${{ hashFiles('ruby/rust-toolchain.toml', 'ruby/**/Cargo.lock') }}--${{ hashFiles('ruby/**/*.rs') }}
|
||||
- uses: actions/cache@v3
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
@@ -56,15 +68,19 @@ jobs:
|
||||
ruby/target
|
||||
key: ${{ runner.os }}-ruby-rust-cargo-${{ hashFiles('ruby/rust-toolchain.toml', 'ruby/**/Cargo.lock') }}
|
||||
- name: Check formatting
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
run: cargo fmt --all -- --check
|
||||
- name: Build
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
run: cargo build --verbose
|
||||
- name: Run tests
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
run: cargo test --verbose
|
||||
- name: Release build
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
run: cargo build --release
|
||||
- name: Generate dbscheme
|
||||
if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||
if: ${{ matrix.os == 'ubuntu-latest' && steps.cache-extractor.outputs.cache-hit != 'true'}}
|
||||
run: target/release/ruby-generator --dbscheme ql/lib/ruby.dbscheme --library ql/lib/codeql/ruby/ast/internal/TreeSitter.qll
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -27,8 +27,6 @@
|
||||
# It's useful (though not required) to be able to unpack codeql in the ql checkout itself
|
||||
/codeql/
|
||||
|
||||
csharp/extractor/Semmle.Extraction.CSharp.Driver/Properties/launchSettings.json
|
||||
|
||||
# Avoid committing cached package components
|
||||
.codeql
|
||||
|
||||
|
||||
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@@ -1,3 +1,5 @@
|
||||
{
|
||||
"omnisharp.autoStart": false
|
||||
"omnisharp.autoStart": false,
|
||||
"cmake.sourceDirectory": "${workspaceFolder}/swift",
|
||||
"cmake.buildDirectory": "${workspaceFolder}/bazel-cmake-build"
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/javascript/ @github/codeql-javascript
|
||||
/python/ @github/codeql-python
|
||||
/ruby/ @github/codeql-ruby
|
||||
/swift/ @github/codeql-c
|
||||
/swift/ @github/codeql-swift
|
||||
/java/kotlin-extractor/ @github/codeql-kotlin
|
||||
/java/kotlin-explorer/ @github/codeql-kotlin
|
||||
|
||||
@@ -45,4 +45,4 @@ WORKSPACE.bazel @github/codeql-ci-reviewers
|
||||
/.github/workflows/js-ml-tests.yml @github/codeql-ml-powered-queries-reviewers
|
||||
/.github/workflows/ql-for-ql-* @github/codeql-ql-for-ql-reviewers
|
||||
/.github/workflows/ruby-* @github/codeql-ruby
|
||||
/.github/workflows/swift.yml @github/codeql-c
|
||||
/.github/workflows/swift.yml @github/codeql-swift
|
||||
|
||||
@@ -26,7 +26,7 @@ provide:
|
||||
- "ruby/extractor-pack/codeql-extractor.yml"
|
||||
- "swift/extractor-pack/codeql-extractor.yml"
|
||||
- "swift/integration-tests/qlpack.yml"
|
||||
- "ql/extractor-pack/codeql-extractor.ym"
|
||||
- "ql/extractor-pack/codeql-extractor.yml"
|
||||
|
||||
versionPolicies:
|
||||
default:
|
||||
|
||||
@@ -257,11 +257,11 @@ namespace Semmle.Autobuild.Cpp.Tests
|
||||
Actions.GetCurrentDirectory = cwd;
|
||||
Actions.IsWindows = isWindows;
|
||||
|
||||
var options = new AutobuildOptions(Actions, Language.Cpp);
|
||||
var options = new CppAutobuildOptions(Actions);
|
||||
return new CppAutobuilder(Actions, options);
|
||||
}
|
||||
|
||||
void TestAutobuilderScript(Autobuilder autobuilder, int expectedOutput, int commandsRun)
|
||||
void TestAutobuilderScript(CppAutobuilder autobuilder, int expectedOutput, int commandsRun)
|
||||
{
|
||||
Assert.Equal(expectedOutput, autobuilder.GetBuildScript().Run(Actions, StartCallback, EndCallback));
|
||||
|
||||
@@ -299,7 +299,7 @@ namespace Semmle.Autobuild.Cpp.Tests
|
||||
{
|
||||
Actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test.sln -DisableParallelProcessing"] = 1;
|
||||
Actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\test.sln -DisableParallelProcessing"] = 0;
|
||||
Actions.RunProcess[@"cmd.exe /C CALL ^""C:\Program Files ^(x86^)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat^"" && set Platform=&& type NUL && C:\odasa\tools\odasa index --auto msbuild C:\Project\test.sln /t:rebuild /p:Platform=""x86"" /p:Configuration=""Release"" /p:MvcBuildViews=true"] = 0;
|
||||
Actions.RunProcess[@"cmd.exe /C CALL ^""C:\Program Files ^(x86^)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat^"" && set Platform=&& type NUL && msbuild C:\Project\test.sln /t:rebuild /p:Platform=""x86"" /p:Configuration=""Release"""] = 0;
|
||||
Actions.RunProcessOut[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationPath"] = "";
|
||||
Actions.RunProcess[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationPath"] = 1;
|
||||
Actions.RunProcess[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationVersion"] = 0;
|
||||
|
||||
@@ -2,9 +2,26 @@
|
||||
|
||||
namespace Semmle.Autobuild.Cpp
|
||||
{
|
||||
public class CppAutobuilder : Autobuilder
|
||||
/// <summary>
|
||||
/// Encapsulates C++ build options.
|
||||
/// </summary>
|
||||
public class CppAutobuildOptions : AutobuildOptionsShared
|
||||
{
|
||||
public CppAutobuilder(IBuildActions actions, AutobuildOptions options) : base(actions, options) { }
|
||||
public override Language Language => Language.Cpp;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reads options from environment variables.
|
||||
/// Throws ArgumentOutOfRangeException for invalid arguments.
|
||||
/// </summary>
|
||||
public CppAutobuildOptions(IBuildActions actions) : base(actions)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class CppAutobuilder : Autobuilder<CppAutobuildOptions>
|
||||
{
|
||||
public CppAutobuilder(IBuildActions actions, CppAutobuildOptions options) : base(actions, options) { }
|
||||
|
||||
public override BuildScript GetBuildScript()
|
||||
{
|
||||
|
||||
@@ -11,14 +11,14 @@ namespace Semmle.Autobuild.Cpp
|
||||
try
|
||||
{
|
||||
var actions = SystemBuildActions.Instance;
|
||||
var options = new AutobuildOptions(actions, Language.Cpp);
|
||||
var options = new CppAutobuildOptions(actions);
|
||||
try
|
||||
{
|
||||
Console.WriteLine("CodeQL C++ autobuilder");
|
||||
var builder = new CppAutobuilder(actions, options);
|
||||
return builder.AttemptBuild();
|
||||
}
|
||||
catch(InvalidEnvironmentException ex)
|
||||
catch (InvalidEnvironmentException ex)
|
||||
{
|
||||
Console.WriteLine("The environment is invalid: {0}", ex.Message);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* Support for tracking tainted data through the program. This is an alias for
|
||||
* `semmle.code.cpp.ir.dataflow.DefaultTaintTracking` provided for backwards
|
||||
* compatibility.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* Common functions for implementing naming conventions
|
||||
*
|
||||
* Naming rules are the following:
|
||||
|
||||
5
csharp/.gitignore
vendored
5
csharp/.gitignore
vendored
@@ -11,4 +11,7 @@ csharp.log
|
||||
*.tlog
|
||||
.vs
|
||||
*.user
|
||||
.vscode/launch.json
|
||||
.vscode/launch.json
|
||||
|
||||
extractor/Semmle.Extraction.CSharp.Driver/Properties/launchSettings.json
|
||||
extractor-pack
|
||||
13
csharp/actions/create-extractor-pack/action.yml
Normal file
13
csharp/actions/create-extractor-pack/action.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
name: Build C# CodeQL pack
|
||||
description: Builds the C# CodeQL pack
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Setup dotnet
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 6.0.202
|
||||
- name: Build Extractor
|
||||
shell: bash
|
||||
run: scripts/create-extractor-pack.sh
|
||||
working-directory: csharp
|
||||
@@ -403,7 +403,7 @@ namespace Semmle.Autobuild.CSharp.Tests
|
||||
actions.GetCurrentDirectory = cwd;
|
||||
actions.IsWindows = isWindows;
|
||||
|
||||
var options = new AutobuildOptions(actions, Language.CSharp);
|
||||
var options = new CSharpAutobuildOptions(actions);
|
||||
return new CSharpAutobuilder(actions, options);
|
||||
}
|
||||
|
||||
@@ -576,7 +576,7 @@ namespace Semmle.Autobuild.CSharp.Tests
|
||||
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat"] = false;
|
||||
}
|
||||
|
||||
private void TestAutobuilderScript(Autobuilder autobuilder, int expectedOutput, int commandsRun)
|
||||
private void TestAutobuilderScript(CSharpAutobuilder autobuilder, int expectedOutput, int commandsRun)
|
||||
{
|
||||
Assert.Equal(expectedOutput, autobuilder.GetBuildScript().Run(actions, StartCallback, EndCallback));
|
||||
|
||||
|
||||
@@ -4,9 +4,32 @@ using Semmle.Autobuild.Shared;
|
||||
|
||||
namespace Semmle.Autobuild.CSharp
|
||||
{
|
||||
public class CSharpAutobuilder : Autobuilder
|
||||
/// <summary>
|
||||
/// Encapsulates C# build options.
|
||||
/// </summary>
|
||||
public class CSharpAutobuildOptions : AutobuildOptionsShared
|
||||
{
|
||||
public CSharpAutobuilder(IBuildActions actions, AutobuildOptions options) : base(actions, options) { }
|
||||
private const string extractorOptionPrefix = "CODEQL_EXTRACTOR_CSHARP_OPTION_";
|
||||
|
||||
public bool Buildless { get; }
|
||||
|
||||
public override Language Language => Language.CSharp;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reads options from environment variables.
|
||||
/// Throws ArgumentOutOfRangeException for invalid arguments.
|
||||
/// </summary>
|
||||
public CSharpAutobuildOptions(IBuildActions actions) : base(actions)
|
||||
{
|
||||
Buildless = actions.GetEnvironmentVariable(lgtmPrefix + "BUILDLESS").AsBool("buildless", false) ||
|
||||
actions.GetEnvironmentVariable(extractorOptionPrefix + "BUILDLESS").AsBool("buildless", false);
|
||||
}
|
||||
}
|
||||
|
||||
public class CSharpAutobuilder : Autobuilder<CSharpAutobuildOptions>
|
||||
{
|
||||
public CSharpAutobuilder(IBuildActions actions, CSharpAutobuildOptions options) : base(actions, options) { }
|
||||
|
||||
public override BuildScript GetBuildScript()
|
||||
{
|
||||
|
||||
@@ -13,9 +13,9 @@ namespace Semmle.Autobuild.CSharp
|
||||
/// A build rule where the build command is of the form "dotnet build".
|
||||
/// Currently unused because the tracer does not work with dotnet.
|
||||
/// </summary>
|
||||
internal class DotNetRule : IBuildRule
|
||||
internal class DotNetRule : IBuildRule<CSharpAutobuildOptions>
|
||||
{
|
||||
public BuildScript Analyse(Autobuilder builder, bool auto)
|
||||
public BuildScript Analyse(IAutobuilder<CSharpAutobuildOptions> builder, bool auto)
|
||||
{
|
||||
if (!builder.ProjectsOrSolutionsToBuild.Any())
|
||||
return BuildScript.Failure;
|
||||
@@ -24,7 +24,7 @@ namespace Semmle.Autobuild.CSharp
|
||||
{
|
||||
var notDotNetProject = builder.ProjectsOrSolutionsToBuild
|
||||
.SelectMany(p => Enumerators.Singleton(p).Concat(p.IncludedProjects))
|
||||
.OfType<Project>()
|
||||
.OfType<Project<CSharpAutobuildOptions>>()
|
||||
.FirstOrDefault(p => !p.DotNetProject);
|
||||
if (notDotNetProject is not null)
|
||||
{
|
||||
@@ -56,7 +56,7 @@ namespace Semmle.Autobuild.CSharp
|
||||
});
|
||||
}
|
||||
|
||||
private static BuildScript WithDotNet(Autobuilder builder, Func<string?, IDictionary<string, string>?, BuildScript> f)
|
||||
private static BuildScript WithDotNet(IAutobuilder<AutobuildOptionsShared> builder, Func<string?, IDictionary<string, string>?, BuildScript> f)
|
||||
{
|
||||
var installDir = builder.Actions.PathCombine(builder.Options.RootDirectory, ".dotnet");
|
||||
var installScript = DownloadDotNet(builder, installDir);
|
||||
@@ -92,7 +92,7 @@ namespace Semmle.Autobuild.CSharp
|
||||
/// variables needed by the installed .NET Core (<code>null</code> when no variables
|
||||
/// are needed).
|
||||
/// </summary>
|
||||
public static BuildScript WithDotNet(Autobuilder builder, Func<IDictionary<string, string>?, BuildScript> f)
|
||||
public static BuildScript WithDotNet(IAutobuilder<AutobuildOptionsShared> builder, Func<IDictionary<string, string>?, BuildScript> f)
|
||||
=> WithDotNet(builder, (_1, env) => f(env));
|
||||
|
||||
/// <summary>
|
||||
@@ -100,7 +100,7 @@ namespace Semmle.Autobuild.CSharp
|
||||
/// .NET Core SDK. The SDK(s) will be installed at <code>installDir</code>
|
||||
/// (provided that the script succeeds).
|
||||
/// </summary>
|
||||
private static BuildScript DownloadDotNet(Autobuilder builder, string installDir)
|
||||
private static BuildScript DownloadDotNet(IAutobuilder<AutobuildOptionsShared> builder, string installDir)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(builder.Options.DotNetVersion))
|
||||
// Specific version supplied in configuration: always use that
|
||||
@@ -137,7 +137,7 @@ namespace Semmle.Autobuild.CSharp
|
||||
///
|
||||
/// See https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script.
|
||||
/// </summary>
|
||||
private static BuildScript DownloadDotNetVersion(Autobuilder builder, string path, string version)
|
||||
private static BuildScript DownloadDotNetVersion(IAutobuilder<AutobuildOptionsShared> builder, string path, string version)
|
||||
{
|
||||
return BuildScript.Bind(GetInstalledSdksScript(builder.Actions), (sdks, sdksRet) =>
|
||||
{
|
||||
@@ -233,7 +233,7 @@ namespace Semmle.Autobuild.CSharp
|
||||
/// <summary>
|
||||
/// Gets the `dotnet build` script.
|
||||
/// </summary>
|
||||
private static BuildScript GetBuildScript(Autobuilder builder, string? dotNetPath, IDictionary<string, string>? environment, string projOrSln)
|
||||
private static BuildScript GetBuildScript(IAutobuilder<CSharpAutobuildOptions> builder, string? dotNetPath, IDictionary<string, string>? environment, string projOrSln)
|
||||
{
|
||||
var build = new CommandBuilder(builder.Actions, null, environment);
|
||||
var script = build.RunCommand(DotNetCommand(builder.Actions, dotNetPath)).
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Semmle.Autobuild.CSharp
|
||||
try
|
||||
{
|
||||
var actions = SystemBuildActions.Instance;
|
||||
var options = new AutobuildOptions(actions, Language.CSharp);
|
||||
var options = new CSharpAutobuildOptions(actions);
|
||||
try
|
||||
{
|
||||
Console.WriteLine("CodeQL C# autobuilder");
|
||||
|
||||
@@ -6,9 +6,9 @@ namespace Semmle.Autobuild.CSharp
|
||||
/// <summary>
|
||||
/// Build using standalone extraction.
|
||||
/// </summary>
|
||||
internal class StandaloneBuildRule : IBuildRule
|
||||
internal class StandaloneBuildRule : IBuildRule<CSharpAutobuildOptions>
|
||||
{
|
||||
public BuildScript Analyse(Autobuilder builder, bool auto)
|
||||
public BuildScript Analyse(IAutobuilder<CSharpAutobuildOptions> builder, bool auto)
|
||||
{
|
||||
BuildScript GetCommand(string? solution)
|
||||
{
|
||||
|
||||
@@ -6,12 +6,12 @@ using System.Text.RegularExpressions;
|
||||
namespace Semmle.Autobuild.Shared
|
||||
{
|
||||
/// <summary>
|
||||
/// Encapsulates build options.
|
||||
/// Encapsulates build options shared between C# and C++.
|
||||
/// </summary>
|
||||
public class AutobuildOptions
|
||||
public abstract class AutobuildOptionsShared
|
||||
{
|
||||
private const string lgtmPrefix = "LGTM_INDEX_";
|
||||
private const string extractorOptionPrefix = "CODEQL_EXTRACTOR_CSHARP_OPTION_";
|
||||
protected const string lgtmPrefix = "LGTM_INDEX_";
|
||||
|
||||
|
||||
public int SearchDepth { get; } = 3;
|
||||
public string RootDirectory { get; }
|
||||
@@ -25,16 +25,16 @@ namespace Semmle.Autobuild.Shared
|
||||
public string? BuildCommand { get; }
|
||||
public IEnumerable<string> Solution { get; }
|
||||
public bool IgnoreErrors { get; }
|
||||
public bool Buildless { get; }
|
||||
|
||||
public bool AllSolutions { get; }
|
||||
public bool NugetRestore { get; }
|
||||
public Language Language { get; }
|
||||
public abstract Language Language { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Reads options from environment variables.
|
||||
/// Throws ArgumentOutOfRangeException for invalid arguments.
|
||||
/// </summary>
|
||||
public AutobuildOptions(IBuildActions actions, Language language)
|
||||
public AutobuildOptionsShared(IBuildActions actions)
|
||||
{
|
||||
RootDirectory = actions.GetCurrentDirectory();
|
||||
VsToolsVersion = actions.GetEnvironmentVariable(lgtmPrefix + "VSTOOLS_VERSION");
|
||||
@@ -48,12 +48,8 @@ namespace Semmle.Autobuild.Shared
|
||||
Solution = actions.GetEnvironmentVariable(lgtmPrefix + "SOLUTION").AsListWithExpandedEnvVars(actions, Array.Empty<string>());
|
||||
|
||||
IgnoreErrors = actions.GetEnvironmentVariable(lgtmPrefix + "IGNORE_ERRORS").AsBool("ignore_errors", false);
|
||||
Buildless = actions.GetEnvironmentVariable(lgtmPrefix + "BUILDLESS").AsBool("buildless", false) ||
|
||||
actions.GetEnvironmentVariable(extractorOptionPrefix + "BUILDLESS").AsBool("buildless", false);
|
||||
AllSolutions = actions.GetEnvironmentVariable(lgtmPrefix + "ALL_SOLUTIONS").AsBool("all_solutions", false);
|
||||
NugetRestore = actions.GetEnvironmentVariable(lgtmPrefix + "NUGET_RESTORE").AsBool("nuget_restore", true);
|
||||
|
||||
Language = language;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,21 +9,21 @@ namespace Semmle.Autobuild.Shared
|
||||
/// <summary>
|
||||
/// A build rule analyses the files in "builder" and outputs a build script.
|
||||
/// </summary>
|
||||
public interface IBuildRule
|
||||
public interface IBuildRule<TAutobuildOptions> where TAutobuildOptions : AutobuildOptionsShared
|
||||
{
|
||||
/// <summary>
|
||||
/// Analyse the files and produce a build script.
|
||||
/// </summary>
|
||||
/// <param name="builder">The files and options relating to the build.</param>
|
||||
/// <param name="auto">Whether this build rule is being automatically applied.</param>
|
||||
BuildScript Analyse(Autobuilder builder, bool auto);
|
||||
BuildScript Analyse(IAutobuilder<TAutobuildOptions> builder, bool auto);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A delegate used to wrap a build script in an environment where an appropriate
|
||||
/// version of .NET Core is automatically installed.
|
||||
/// </summary>
|
||||
public delegate BuildScript WithDotNet(Autobuilder builder, Func<IDictionary<string, string>?, BuildScript> f);
|
||||
public delegate BuildScript WithDotNet<TAutobuildOptions>(IAutobuilder<TAutobuildOptions> builder, Func<IDictionary<string, string>?, BuildScript> f) where TAutobuildOptions : AutobuildOptionsShared;
|
||||
|
||||
/// <summary>
|
||||
/// Exception indicating that environment variables are missing or invalid.
|
||||
@@ -33,6 +33,59 @@ namespace Semmle.Autobuild.Shared
|
||||
public InvalidEnvironmentException(string m) : base(m) { }
|
||||
}
|
||||
|
||||
public interface IAutobuilder<out TAutobuildOptions> where TAutobuildOptions : AutobuildOptionsShared
|
||||
{
|
||||
/// <summary>
|
||||
/// Full file paths of files found in the project directory, as well as
|
||||
/// their distance from the project root folder. The list is sorted
|
||||
/// by distance in ascending order.
|
||||
/// </summary>
|
||||
IEnumerable<(string, int)> Paths { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets all paths matching a particular filename, as well as
|
||||
/// their distance from the project root folder. The list is sorted
|
||||
/// by distance in ascending order.
|
||||
/// </summary>
|
||||
/// <param name="name">The filename to find.</param>
|
||||
/// <returns>Possibly empty sequence of paths with the given filename.</returns>
|
||||
IEnumerable<(string, int)> GetFilename(string name) =>
|
||||
Paths.Where(p => Actions.GetFileName(p.Item1) == name);
|
||||
|
||||
/// <summary>
|
||||
/// List of project/solution files to build.
|
||||
/// </summary>
|
||||
IList<IProjectOrSolution> ProjectsOrSolutionsToBuild { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the supplied build configuration.
|
||||
/// </summary>
|
||||
TAutobuildOptions Options { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The set of build actions used during the autobuilder.
|
||||
/// Could be real system operations, or a stub for testing.
|
||||
/// </summary>
|
||||
IBuildActions Actions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Log a given build event to the console.
|
||||
/// </summary>
|
||||
/// <param name="format">The format string.</param>
|
||||
/// <param name="args">Inserts to the format string.</param>
|
||||
void Log(Severity severity, string format, params object[] args);
|
||||
|
||||
/// <summary>
|
||||
/// Value of CODEQL_EXTRACTOR_<LANG>_ROOT environment variable.
|
||||
/// </summary>
|
||||
string? CodeQLExtractorLangRoot { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Value of CODEQL_PLATFORM environment variable.
|
||||
/// </summary>
|
||||
string? CodeQlPlatform { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Main application logic, containing all data
|
||||
/// gathered from the project and filesystem.
|
||||
@@ -40,7 +93,7 @@ namespace Semmle.Autobuild.Shared
|
||||
/// The overall design is intended to be extensible so that in theory,
|
||||
/// it should be possible to add new build rules without touching this code.
|
||||
/// </summary>
|
||||
public abstract class Autobuilder
|
||||
public abstract class Autobuilder<TAutobuildOptions> : IAutobuilder<TAutobuildOptions> where TAutobuildOptions : AutobuildOptionsShared
|
||||
{
|
||||
/// <summary>
|
||||
/// Full file paths of files found in the project directory, as well as
|
||||
@@ -60,16 +113,6 @@ namespace Semmle.Autobuild.Shared
|
||||
public IEnumerable<(string, int)> GetExtensions(params string[] extensions) =>
|
||||
Paths.Where(p => extensions.Contains(Path.GetExtension(p.Item1)));
|
||||
|
||||
/// <summary>
|
||||
/// Gets all paths matching a particular filename, as well as
|
||||
/// their distance from the project root folder. The list is sorted
|
||||
/// by distance in ascending order.
|
||||
/// </summary>
|
||||
/// <param name="name">The filename to find.</param>
|
||||
/// <returns>Possibly empty sequence of paths with the given filename.</returns>
|
||||
public IEnumerable<(string, int)> GetFilename(string name) =>
|
||||
Paths.Where(p => Actions.GetFileName(p.Item1) == name);
|
||||
|
||||
/// <summary>
|
||||
/// Holds if a given path, relative to the root of the source directory
|
||||
/// was found.
|
||||
@@ -115,7 +158,7 @@ namespace Semmle.Autobuild.Shared
|
||||
/// <summary>
|
||||
/// Gets the supplied build configuration.
|
||||
/// </summary>
|
||||
public AutobuildOptions Options { get; }
|
||||
public TAutobuildOptions Options { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The set of build actions used during the autobuilder.
|
||||
@@ -123,7 +166,7 @@ namespace Semmle.Autobuild.Shared
|
||||
/// </summary>
|
||||
public IBuildActions Actions { get; }
|
||||
|
||||
private IEnumerable<IProjectOrSolution>? FindFiles(string extension, Func<string, ProjectOrSolution> create)
|
||||
private IEnumerable<IProjectOrSolution>? FindFiles(string extension, Func<string, ProjectOrSolution<TAutobuildOptions>> create)
|
||||
{
|
||||
var matchingFiles = GetExtensions(extension)
|
||||
.Select(p => (ProjectOrSolution: create(p.Item1), DistanceFromRoot: p.Item2))
|
||||
@@ -146,7 +189,7 @@ namespace Semmle.Autobuild.Shared
|
||||
/// solution file and tools.
|
||||
/// </summary>
|
||||
/// <param name="options">The command line options.</param>
|
||||
protected Autobuilder(IBuildActions actions, AutobuildOptions options)
|
||||
protected Autobuilder(IBuildActions actions, TAutobuildOptions options)
|
||||
{
|
||||
Actions = actions;
|
||||
Options = options;
|
||||
@@ -167,7 +210,7 @@ namespace Semmle.Autobuild.Shared
|
||||
foreach (var solution in options.Solution)
|
||||
{
|
||||
if (actions.FileExists(solution))
|
||||
ret.Add(new Solution(this, solution, true));
|
||||
ret.Add(new Solution<TAutobuildOptions>(this, solution, true));
|
||||
else
|
||||
Log(Severity.Error, $"The specified project or solution file {solution} was not found");
|
||||
}
|
||||
@@ -175,17 +218,17 @@ namespace Semmle.Autobuild.Shared
|
||||
}
|
||||
|
||||
// First look for `.proj` files
|
||||
ret = FindFiles(".proj", f => new Project(this, f))?.ToList();
|
||||
ret = FindFiles(".proj", f => new Project<TAutobuildOptions>(this, f))?.ToList();
|
||||
if (ret is not null)
|
||||
return ret;
|
||||
|
||||
// Then look for `.sln` files
|
||||
ret = FindFiles(".sln", f => new Solution(this, f, false))?.ToList();
|
||||
ret = FindFiles(".sln", f => new Solution<TAutobuildOptions>(this, f, false))?.ToList();
|
||||
if (ret is not null)
|
||||
return ret;
|
||||
|
||||
// Finally look for language specific project files, e.g. `.csproj` files
|
||||
ret = FindFiles(this.Options.Language.ProjectExtension, f => new Project(this, f))?.ToList();
|
||||
ret = FindFiles(this.Options.Language.ProjectExtension, f => new Project<TAutobuildOptions>(this, f))?.ToList();
|
||||
return ret ?? new List<IProjectOrSolution>();
|
||||
});
|
||||
|
||||
|
||||
@@ -7,11 +7,11 @@ namespace Semmle.Autobuild.Shared
|
||||
/// <summary>
|
||||
/// Auto-detection of build scripts.
|
||||
/// </summary>
|
||||
public class BuildCommandAutoRule : IBuildRule
|
||||
public class BuildCommandAutoRule : IBuildRule<AutobuildOptionsShared>
|
||||
{
|
||||
private readonly WithDotNet withDotNet;
|
||||
private readonly WithDotNet<AutobuildOptionsShared> withDotNet;
|
||||
|
||||
public BuildCommandAutoRule(WithDotNet withDotNet)
|
||||
public BuildCommandAutoRule(WithDotNet<AutobuildOptionsShared> withDotNet)
|
||||
{
|
||||
this.withDotNet = withDotNet;
|
||||
}
|
||||
@@ -31,7 +31,7 @@ namespace Semmle.Autobuild.Shared
|
||||
"build"
|
||||
};
|
||||
|
||||
public BuildScript Analyse(Autobuilder builder, bool auto)
|
||||
public BuildScript Analyse(IAutobuilder<AutobuildOptionsShared> builder, bool auto)
|
||||
{
|
||||
builder.Log(Severity.Info, "Attempting to locate build script");
|
||||
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
/// <summary>
|
||||
/// Execute the build_command rule.
|
||||
/// </summary>
|
||||
public class BuildCommandRule : IBuildRule
|
||||
public class BuildCommandRule : IBuildRule<AutobuildOptionsShared>
|
||||
{
|
||||
private readonly WithDotNet withDotNet;
|
||||
private readonly WithDotNet<AutobuildOptionsShared> withDotNet;
|
||||
|
||||
public BuildCommandRule(WithDotNet withDotNet)
|
||||
public BuildCommandRule(WithDotNet<AutobuildOptionsShared> withDotNet)
|
||||
{
|
||||
this.withDotNet = withDotNet;
|
||||
}
|
||||
|
||||
public BuildScript Analyse(Autobuilder builder, bool auto)
|
||||
public BuildScript Analyse(IAutobuilder<AutobuildOptionsShared> builder, bool auto)
|
||||
{
|
||||
if (builder.Options.BuildCommand is null)
|
||||
return BuildScript.Failure;
|
||||
|
||||
@@ -6,14 +6,14 @@ namespace Semmle.Autobuild.Shared
|
||||
/// <summary>
|
||||
/// A build rule using msbuild.
|
||||
/// </summary>
|
||||
public class MsBuildRule : IBuildRule
|
||||
public class MsBuildRule : IBuildRule<AutobuildOptionsShared>
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the msbuild command.
|
||||
/// </summary>
|
||||
private const string msBuild = "msbuild";
|
||||
|
||||
public BuildScript Analyse(Autobuilder builder, bool auto)
|
||||
public BuildScript Analyse(IAutobuilder<AutobuildOptionsShared> builder, bool auto)
|
||||
{
|
||||
if (!builder.ProjectsOrSolutionsToBuild.Any())
|
||||
return BuildScript.Failure;
|
||||
@@ -27,8 +27,8 @@ namespace Semmle.Autobuild.Shared
|
||||
{
|
||||
var firstSolution = builder.ProjectsOrSolutionsToBuild.OfType<ISolution>().FirstOrDefault();
|
||||
vsTools = firstSolution is not null
|
||||
? BuildTools.FindCompatibleVcVars(builder.Actions, firstSolution)
|
||||
: BuildTools.VcVarsAllBatFiles(builder.Actions).OrderByDescending(b => b.ToolsVersion).FirstOrDefault();
|
||||
? BuildTools.FindCompatibleVcVars(builder.Actions, firstSolution)
|
||||
: BuildTools.VcVarsAllBatFiles(builder.Actions).OrderByDescending(b => b.ToolsVersion).FirstOrDefault();
|
||||
}
|
||||
|
||||
if (vsTools is null && builder.Actions.IsWindows())
|
||||
@@ -123,7 +123,7 @@ namespace Semmle.Autobuild.Shared
|
||||
///
|
||||
/// Returns <code>null</code> when no version is specified.
|
||||
/// </summary>
|
||||
public static VcVarsBatFile? GetVcVarsBatFile(Autobuilder builder)
|
||||
public static VcVarsBatFile? GetVcVarsBatFile<TAutobuildOptions>(IAutobuilder<TAutobuildOptions> builder) where TAutobuildOptions : AutobuildOptionsShared
|
||||
{
|
||||
VcVarsBatFile? vsTools = null;
|
||||
|
||||
@@ -154,7 +154,7 @@ namespace Semmle.Autobuild.Shared
|
||||
/// <summary>
|
||||
/// Returns a script for downloading `nuget.exe` from nuget.org.
|
||||
/// </summary>
|
||||
private static BuildScript DownloadNugetExe(Autobuilder builder, string path) =>
|
||||
private static BuildScript DownloadNugetExe<TAutobuildOptions>(IAutobuilder<TAutobuildOptions> builder, string path) where TAutobuildOptions : AutobuildOptionsShared =>
|
||||
BuildScript.Create(_ =>
|
||||
{
|
||||
builder.Log(Severity.Info, "Attempting to download nuget.exe");
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Semmle.Autobuild.Shared
|
||||
/// C# project files come in 2 flavours, .Net core and msbuild, but they
|
||||
/// have the same file extension.
|
||||
/// </summary>
|
||||
public class Project : ProjectOrSolution
|
||||
public class Project<TAutobuildOptions> : ProjectOrSolution<TAutobuildOptions> where TAutobuildOptions : AutobuildOptionsShared
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds if this project is for .Net core.
|
||||
@@ -23,13 +23,13 @@ namespace Semmle.Autobuild.Shared
|
||||
|
||||
public Version ToolsVersion { get; private set; }
|
||||
|
||||
private readonly Lazy<List<Project>> includedProjectsLazy;
|
||||
private readonly Lazy<List<Project<TAutobuildOptions>>> includedProjectsLazy;
|
||||
public override IEnumerable<IProjectOrSolution> IncludedProjects => includedProjectsLazy.Value;
|
||||
|
||||
public Project(Autobuilder builder, string path) : base(builder, path)
|
||||
public Project(Autobuilder<TAutobuildOptions> builder, string path) : base(builder, path)
|
||||
{
|
||||
ToolsVersion = new Version();
|
||||
includedProjectsLazy = new Lazy<List<Project>>(() => new List<Project>());
|
||||
includedProjectsLazy = new Lazy<List<Project<TAutobuildOptions>>>(() => new List<Project<TAutobuildOptions>>());
|
||||
|
||||
if (!builder.Actions.FileExists(FullPath))
|
||||
return;
|
||||
@@ -70,9 +70,9 @@ namespace Semmle.Autobuild.Shared
|
||||
}
|
||||
}
|
||||
|
||||
includedProjectsLazy = new Lazy<List<Project>>(() =>
|
||||
includedProjectsLazy = new Lazy<List<Project<TAutobuildOptions>>>(() =>
|
||||
{
|
||||
var ret = new List<Project>();
|
||||
var ret = new List<Project<TAutobuildOptions>>();
|
||||
// The documentation on `.proj` files is very limited, but it appears that both
|
||||
// `<ProjectFile Include="X"/>` and `<ProjectFiles Include="X"/>` is valid
|
||||
var mgr = new XmlNamespaceManager(projFile.NameTable);
|
||||
@@ -89,7 +89,7 @@ namespace Semmle.Autobuild.Shared
|
||||
}
|
||||
|
||||
var includePath = builder.Actions.PathCombine(include.Value.Split('\\', StringSplitOptions.RemoveEmptyEntries));
|
||||
ret.Add(new Project(builder, builder.Actions.PathCombine(DirectoryName, includePath)));
|
||||
ret.Add(new Project<TAutobuildOptions>(builder, builder.Actions.PathCombine(DirectoryName, includePath)));
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
|
||||
@@ -20,13 +20,13 @@ namespace Semmle.Autobuild.Shared
|
||||
IEnumerable<IProjectOrSolution> IncludedProjects { get; }
|
||||
}
|
||||
|
||||
public abstract class ProjectOrSolution : IProjectOrSolution
|
||||
public abstract class ProjectOrSolution<TAutobuildOptions> : IProjectOrSolution where TAutobuildOptions : AutobuildOptionsShared
|
||||
{
|
||||
public string FullPath { get; }
|
||||
|
||||
public string DirectoryName { get; }
|
||||
|
||||
protected ProjectOrSolution(Autobuilder builder, string path)
|
||||
protected ProjectOrSolution(Autobuilder<TAutobuildOptions> builder, string path)
|
||||
{
|
||||
FullPath = builder.Actions.GetFullPath(path);
|
||||
DirectoryName = builder.Actions.GetDirectoryName(path) ?? "";
|
||||
|
||||
@@ -40,11 +40,11 @@ namespace Semmle.Autobuild.Shared
|
||||
/// <summary>
|
||||
/// A solution file on the filesystem, read using Microsoft.Build.
|
||||
/// </summary>
|
||||
internal class Solution : ProjectOrSolution, ISolution
|
||||
internal class Solution<TAutobuildOptions> : ProjectOrSolution<TAutobuildOptions>, ISolution where TAutobuildOptions : AutobuildOptionsShared
|
||||
{
|
||||
private readonly SolutionFile? solution;
|
||||
|
||||
private readonly IEnumerable<Project> includedProjects;
|
||||
private readonly IEnumerable<Project<TAutobuildOptions>> includedProjects;
|
||||
|
||||
public override IEnumerable<IProjectOrSolution> IncludedProjects => includedProjects;
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Semmle.Autobuild.Shared
|
||||
public string DefaultPlatformName =>
|
||||
solution is null ? "" : solution.GetDefaultPlatformName();
|
||||
|
||||
public Solution(Autobuilder builder, string path, bool allowProject) : base(builder, path)
|
||||
public Solution(Autobuilder<TAutobuildOptions> builder, string path, bool allowProject) : base(builder, path)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -69,19 +69,19 @@ namespace Semmle.Autobuild.Shared
|
||||
// that scenario as a solution with just that one project
|
||||
if (allowProject)
|
||||
{
|
||||
includedProjects = new[] { new Project(builder, path) };
|
||||
includedProjects = new[] { new Project<TAutobuildOptions>(builder, path) };
|
||||
return;
|
||||
}
|
||||
|
||||
builder.Log(Severity.Info, $"Unable to read solution file {path}.");
|
||||
includedProjects = Array.Empty<Project>();
|
||||
includedProjects = Array.Empty<Project<TAutobuildOptions>>();
|
||||
return;
|
||||
}
|
||||
|
||||
includedProjects = solution.ProjectsInOrder
|
||||
.Where(p => p.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat)
|
||||
.Select(p => builder.Actions.PathCombine(DirectoryName, builder.Actions.PathCombine(p.RelativePath.Split('\\', StringSplitOptions.RemoveEmptyEntries))))
|
||||
.Select(p => new Project(builder, p))
|
||||
.Select(p => new Project<TAutobuildOptions>(builder, p))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* Provides reusable predicates related to Solorigate
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* Predicates that help detect potential non-cryptographic hash functions
|
||||
*
|
||||
* By themselves, non-cryptographic functions are common and not dangerous
|
||||
|
||||
@@ -47,19 +47,19 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
ReadAccess getAFirstRead(Definition def) {
|
||||
ReadAccess getAFirstReadExt(DefinitionExt def) {
|
||||
exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
|
||||
def.definesAt(_, bb1, i1) and
|
||||
adjacentDefRead(def, bb1, i1, bb2, i2) and
|
||||
def.definesAt(_, bb1, i1, _) and
|
||||
adjacentDefReadExt(def, _, bb1, i1, bb2, i2) and
|
||||
result = bb2.getNode(i2)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hasAdjacentReads(Definition def, ReadAccess first, ReadAccess second) {
|
||||
predicate hasAdjacentReadsExt(DefinitionExt def, ReadAccess first, ReadAccess second) {
|
||||
exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
|
||||
first = bb1.getNode(i1) and
|
||||
adjacentDefRead(def, bb1, i1, bb2, i2) and
|
||||
adjacentDefReadExt(def, _, bb1, i1, bb2, i2) and
|
||||
second = bb2.getNode(i2)
|
||||
)
|
||||
}
|
||||
@@ -68,9 +68,35 @@ private module Cached {
|
||||
Definition getAPhiInput(PhiNode phi) { phiHasInputFromBlock(phi, result, _) }
|
||||
|
||||
cached
|
||||
predicate lastRefBeforeRedef(Definition def, BasicBlock bb, int i, Definition next) {
|
||||
lastRefRedef(def, bb, i, next)
|
||||
predicate lastRefBeforeRedefExt(DefinitionExt def, BasicBlock bb, int i, DefinitionExt next) {
|
||||
lastRefRedefExt(def, _, bb, i, next)
|
||||
}
|
||||
}
|
||||
|
||||
import Cached
|
||||
|
||||
private module Deprecated {
|
||||
private import CIL
|
||||
|
||||
deprecated ReadAccess getAFirstRead(Definition def) {
|
||||
exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
|
||||
def.definesAt(_, bb1, i1) and
|
||||
adjacentDefRead(def, bb1, i1, bb2, i2) and
|
||||
result = bb2.getNode(i2)
|
||||
)
|
||||
}
|
||||
|
||||
deprecated predicate hasAdjacentReads(Definition def, ReadAccess first, ReadAccess second) {
|
||||
exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
|
||||
first = bb1.getNode(i1) and
|
||||
adjacentDefRead(def, bb1, i1, bb2, i2) and
|
||||
second = bb2.getNode(i2)
|
||||
)
|
||||
}
|
||||
|
||||
deprecated predicate lastRefBeforeRedef(Definition def, BasicBlock bb, int i, Definition next) {
|
||||
lastRefRedef(def, bb, i, next)
|
||||
}
|
||||
}
|
||||
|
||||
import Deprecated
|
||||
|
||||
@@ -103,7 +103,6 @@ abstract class Completion extends TCompletion {
|
||||
* otherwise it is a normal non-Boolean completion.
|
||||
*/
|
||||
predicate isValidFor(ControlFlowElement cfe) {
|
||||
cfe instanceof NonReturningCall and
|
||||
this = cfe.(NonReturningCall).getACompletion()
|
||||
or
|
||||
this = TThrowCompletion(cfe.(TriedControlFlowElement).getAThrownException())
|
||||
|
||||
@@ -90,43 +90,6 @@ private import internal.FlowSummaryImpl::Public
|
||||
private import internal.FlowSummaryImpl::Private::External
|
||||
private import internal.FlowSummaryImplSpecific
|
||||
|
||||
/**
|
||||
* A module importing the frameworks that provide external flow data,
|
||||
* ensuring that they are visible to the taint tracking / data flow library.
|
||||
*/
|
||||
private module Frameworks {
|
||||
private import semmle.code.csharp.frameworks.EntityFramework
|
||||
private import semmle.code.csharp.frameworks.JsonNET
|
||||
private import semmle.code.csharp.frameworks.ServiceStack
|
||||
private import semmle.code.csharp.frameworks.Sql
|
||||
private import semmle.code.csharp.frameworks.System
|
||||
private import semmle.code.csharp.frameworks.system.CodeDom
|
||||
private import semmle.code.csharp.frameworks.system.Collections
|
||||
private import semmle.code.csharp.frameworks.system.collections.Generic
|
||||
private import semmle.code.csharp.frameworks.system.collections.Specialized
|
||||
private import semmle.code.csharp.frameworks.system.Data
|
||||
private import semmle.code.csharp.frameworks.system.data.Common
|
||||
private import semmle.code.csharp.frameworks.system.Diagnostics
|
||||
private import semmle.code.csharp.frameworks.system.Linq
|
||||
private import semmle.code.csharp.frameworks.system.Net
|
||||
private import semmle.code.csharp.frameworks.system.net.Mail
|
||||
private import semmle.code.csharp.frameworks.system.IO
|
||||
private import semmle.code.csharp.frameworks.system.io.Compression
|
||||
private import semmle.code.csharp.frameworks.system.runtime.CompilerServices
|
||||
private import semmle.code.csharp.frameworks.system.Security
|
||||
private import semmle.code.csharp.frameworks.system.security.Cryptography
|
||||
private import semmle.code.csharp.frameworks.system.security.cryptography.X509Certificates
|
||||
private import semmle.code.csharp.frameworks.system.Text
|
||||
private import semmle.code.csharp.frameworks.system.text.RegularExpressions
|
||||
private import semmle.code.csharp.frameworks.system.threading.Tasks
|
||||
private import semmle.code.csharp.frameworks.system.Web
|
||||
private import semmle.code.csharp.frameworks.system.web.ui.WebControls
|
||||
private import semmle.code.csharp.frameworks.system.Xml
|
||||
private import semmle.code.csharp.security.dataflow.flowsinks.Html
|
||||
private import semmle.code.csharp.security.dataflow.flowsources.Local
|
||||
private import semmle.code.csharp.security.dataflow.XSSSinks
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Define source models as data extensions instead.
|
||||
*
|
||||
|
||||
@@ -6,7 +6,6 @@ private import DataFlowPublic
|
||||
private import DataFlowPrivate
|
||||
private import FlowSummaryImpl as FlowSummaryImpl
|
||||
private import semmle.code.csharp.dataflow.FlowSummary as FlowSummary
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
private import semmle.code.csharp.dispatch.Dispatch
|
||||
private import semmle.code.csharp.dispatch.RuntimeCallable
|
||||
private import semmle.code.csharp.frameworks.system.Collections
|
||||
|
||||
@@ -18,6 +18,7 @@ private import semmle.code.csharp.frameworks.NHibernate
|
||||
private import semmle.code.csharp.frameworks.system.Collections
|
||||
private import semmle.code.csharp.frameworks.system.threading.Tasks
|
||||
private import semmle.code.cil.Ssa::Ssa as CilSsa
|
||||
private import semmle.code.cil.internal.SsaImpl as CilSsaImpl
|
||||
|
||||
/** Gets the callable in which this node occurs. */
|
||||
DataFlowCallable nodeGetEnclosingCallable(NodeImpl n) { result = n.getEnclosingCallableImpl() }
|
||||
@@ -174,7 +175,7 @@ predicate hasNodePath(ControlFlowReachabilityConfiguration conf, ExprNode n1, No
|
||||
cfn = n1.getControlFlowNode() and
|
||||
ssaDef.getADefinition() = def and
|
||||
ssaDef.getControlFlowNode() = cfnDef and
|
||||
n2.(SsaDefinitionNode).getDefinition() = ssaDef
|
||||
n2.(SsaDefinitionExtNode).getDefinitionExt() = ssaDef
|
||||
)
|
||||
}
|
||||
|
||||
@@ -306,17 +307,28 @@ module LocalFlow {
|
||||
}
|
||||
}
|
||||
|
||||
/** An SSA definition into which another SSA definition may flow. */
|
||||
private class SsaInputDefinitionExtNode extends SsaDefinitionExtNode {
|
||||
SsaInputDefinitionExtNode() {
|
||||
def instanceof Ssa::PhiNode
|
||||
or
|
||||
def instanceof SsaImpl::PhiReadNode
|
||||
or
|
||||
def instanceof LocalFlow::UncertainExplicitSsaDefinition
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `nodeFrom` is a last node referencing SSA definition `def`, which
|
||||
* can reach `next`.
|
||||
*/
|
||||
private predicate localFlowSsaInputFromDef(
|
||||
Node nodeFrom, Ssa::Definition def, Ssa::Definition next
|
||||
Node nodeFrom, SsaImpl::DefinitionExt def, SsaInputDefinitionExtNode next
|
||||
) {
|
||||
exists(ControlFlow::BasicBlock bb, int i |
|
||||
SsaImpl::lastRefBeforeRedef(def, bb, i, next) and
|
||||
def.definesAt(_, bb, i) and
|
||||
def = getSsaDefinition(nodeFrom)
|
||||
SsaImpl::lastRefBeforeRedefExt(def, bb, i, next.getDefinitionExt()) and
|
||||
def.definesAt(_, bb, i, _) and
|
||||
def = getSsaDefinitionExt(nodeFrom)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -324,18 +336,17 @@ module LocalFlow {
|
||||
* Holds if `read` is a last node reading SSA definition `def`, which
|
||||
* can reach `next`.
|
||||
*/
|
||||
predicate localFlowSsaInputFromExpr(
|
||||
ControlFlow::Node read, Ssa::Definition def, Ssa::Definition next
|
||||
predicate localFlowSsaInputFromRead(
|
||||
Node read, SsaImpl::DefinitionExt def, SsaInputDefinitionExtNode next
|
||||
) {
|
||||
exists(ControlFlow::BasicBlock bb, int i |
|
||||
SsaImpl::lastRefBeforeRedef(def, bb, i, next) and
|
||||
read = bb.getNode(i) and
|
||||
read.getElement() instanceof AssignableRead
|
||||
SsaImpl::lastRefBeforeRedefExt(def, bb, i, next.getDefinitionExt()) and
|
||||
read.asExprAtNode(bb.getNode(i)) instanceof AssignableRead
|
||||
)
|
||||
}
|
||||
|
||||
private Ssa::Definition getSsaDefinition(Node n) {
|
||||
result = n.(SsaDefinitionNode).getDefinition()
|
||||
private SsaImpl::DefinitionExt getSsaDefinitionExt(Node n) {
|
||||
result = n.(SsaDefinitionExtNode).getDefinitionExt()
|
||||
or
|
||||
result = n.(ExplicitParameterNode).getSsaDefinition()
|
||||
}
|
||||
@@ -344,9 +355,9 @@ module LocalFlow {
|
||||
* Holds if there is a local use-use flow step from `nodeFrom` to `nodeTo`
|
||||
* involving SSA definition `def`.
|
||||
*/
|
||||
predicate localSsaFlowStepUseUse(Ssa::Definition def, Node nodeFrom, Node nodeTo) {
|
||||
predicate localSsaFlowStepUseUse(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
|
||||
exists(ControlFlow::Node cfnFrom, ControlFlow::Node cfnTo |
|
||||
SsaImpl::adjacentReadPairSameVar(def, cfnFrom, cfnTo) and
|
||||
SsaImpl::adjacentReadPairSameVarExt(def, cfnFrom, cfnTo) and
|
||||
nodeTo = TExprNode(cfnTo) and
|
||||
nodeFrom = TExprNode(cfnFrom)
|
||||
)
|
||||
@@ -356,31 +367,22 @@ module LocalFlow {
|
||||
* Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving
|
||||
* SSA definition `def`.
|
||||
*/
|
||||
predicate localSsaFlowStep(Ssa::Definition def, Node nodeFrom, Node nodeTo) {
|
||||
predicate localSsaFlowStep(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
|
||||
// Flow from SSA definition/parameter to first read
|
||||
exists(ControlFlow::Node cfn |
|
||||
def = getSsaDefinition(nodeFrom) and
|
||||
nodeTo.asExprAtNode(cfn) = def.getAFirstReadAtNode(cfn)
|
||||
)
|
||||
def = getSsaDefinitionExt(nodeFrom) and
|
||||
SsaImpl::firstReadSameVarExt(def, nodeTo.(ExprNode).getControlFlowNode())
|
||||
or
|
||||
// Flow from read to next read
|
||||
localSsaFlowStepUseUse(def, nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo)
|
||||
or
|
||||
// Flow into phi/uncertain SSA definition node from def
|
||||
exists(Ssa::Definition next |
|
||||
localFlowSsaInputFromDef(nodeFrom, def, next) and
|
||||
next = nodeTo.(SsaDefinitionNode).getDefinition()
|
||||
|
|
||||
def = next.(Ssa::PhiNode).getAnInput()
|
||||
or
|
||||
def = next.(LocalFlow::UncertainExplicitSsaDefinition).getPriorDefinition()
|
||||
)
|
||||
// Flow into phi (read)/uncertain SSA definition node from def
|
||||
localFlowSsaInputFromDef(nodeFrom, def, nodeTo)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the source variable of SSA definition `def` is an instance field.
|
||||
*/
|
||||
predicate usesInstanceField(Ssa::Definition def) {
|
||||
predicate usesInstanceField(SsaImpl::DefinitionExt def) {
|
||||
exists(Ssa::SourceVariables::FieldOrPropSourceVariable fp | fp = def.getSourceVariable() |
|
||||
not fp.getAssignable().(Modifiable).isStatic()
|
||||
)
|
||||
@@ -389,25 +391,23 @@ module LocalFlow {
|
||||
predicate localFlowCapturedVarStep(Node nodeFrom, ImplicitCapturedArgumentNode nodeTo) {
|
||||
// Flow from SSA definition to implicit captured variable argument
|
||||
exists(Ssa::ExplicitDefinition def, ControlFlow::Nodes::ElementNode call |
|
||||
def = getSsaDefinition(nodeFrom) and
|
||||
def = getSsaDefinitionExt(nodeFrom) and
|
||||
def.isCapturedVariableDefinitionFlowIn(_, call, _) and
|
||||
nodeTo = TImplicitCapturedArgumentNode(call, def.getSourceVariable().getAssignable())
|
||||
)
|
||||
}
|
||||
|
||||
private module CilFlow {
|
||||
private import semmle.code.cil.internal.SsaImpl as CilSsaImpl
|
||||
|
||||
/**
|
||||
* Holds if `nodeFrom` is a last node referencing SSA definition `def`, which
|
||||
* can reach `next`.
|
||||
*/
|
||||
private predicate localFlowCilSsaInput(
|
||||
Node nodeFrom, CilSsa::Definition def, CilSsa::Definition next
|
||||
Node nodeFrom, CilSsaImpl::DefinitionExt def, CilSsaImpl::DefinitionExt next
|
||||
) {
|
||||
exists(CIL::BasicBlock bb, int i | CilSsaImpl::lastRefBeforeRedef(def, bb, i, next) |
|
||||
def.definesAt(_, bb, i) and
|
||||
def = nodeFrom.(CilSsaDefinitionNode).getDefinition()
|
||||
exists(CIL::BasicBlock bb, int i | CilSsaImpl::lastRefBeforeRedefExt(def, bb, i, next) |
|
||||
def.definesAt(_, bb, i, _) and
|
||||
def = nodeFrom.(CilSsaDefinitionExtNode).getDefinition()
|
||||
or
|
||||
nodeFrom = TCilExprNode(bb.getNode(i).(CIL::ReadAccess))
|
||||
)
|
||||
@@ -417,30 +417,33 @@ module LocalFlow {
|
||||
* Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving
|
||||
* CIL SSA definition `def`.
|
||||
*/
|
||||
private predicate localCilSsaFlowStep(CilSsa::Definition def, Node nodeFrom, Node nodeTo) {
|
||||
private predicate localCilSsaFlowStep(CilSsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
|
||||
// Flow into SSA definition
|
||||
exists(CIL::VariableUpdate vu |
|
||||
vu = def.getVariableUpdate() and
|
||||
vu = def.(CilSsa::Definition).getVariableUpdate() and
|
||||
vu.getSource() = asCilDataFlowNode(nodeFrom) and
|
||||
def = nodeTo.(CilSsaDefinitionNode).getDefinition()
|
||||
def = nodeTo.(CilSsaDefinitionExtNode).getDefinition()
|
||||
)
|
||||
or
|
||||
// Flow from SSA definition to first read
|
||||
def = nodeFrom.(CilSsaDefinitionNode).getDefinition() and
|
||||
nodeTo = TCilExprNode(CilSsaImpl::getAFirstRead(def))
|
||||
def = nodeFrom.(CilSsaDefinitionExtNode).getDefinition() and
|
||||
nodeTo = TCilExprNode(CilSsaImpl::getAFirstReadExt(def))
|
||||
or
|
||||
// Flow from read to next read
|
||||
exists(CIL::ReadAccess readFrom, CIL::ReadAccess readTo |
|
||||
CilSsaImpl::hasAdjacentReads(def, readFrom, readTo) and
|
||||
CilSsaImpl::hasAdjacentReadsExt(def, readFrom, readTo) and
|
||||
nodeTo = TCilExprNode(readTo) and
|
||||
nodeFrom = TCilExprNode(readFrom)
|
||||
)
|
||||
or
|
||||
// Flow into phi node
|
||||
exists(CilSsa::PhiNode phi |
|
||||
// Flow into phi (read) node
|
||||
exists(CilSsaImpl::DefinitionExt phi |
|
||||
localFlowCilSsaInput(nodeFrom, def, phi) and
|
||||
phi = nodeTo.(CilSsaDefinitionNode).getDefinition() and
|
||||
def = CilSsaImpl::getAPhiInput(phi)
|
||||
phi = nodeTo.(CilSsaDefinitionExtNode).getDefinition()
|
||||
|
|
||||
phi instanceof CilSsa::PhiNode
|
||||
or
|
||||
phi instanceof CilSsaImpl::PhiReadNode
|
||||
)
|
||||
}
|
||||
|
||||
@@ -466,7 +469,7 @@ module LocalFlow {
|
||||
}
|
||||
|
||||
predicate localFlowStepCommon(Node nodeFrom, Node nodeTo) {
|
||||
exists(Ssa::Definition def |
|
||||
exists(SsaImpl::DefinitionExt def |
|
||||
localSsaFlowStep(def, nodeFrom, nodeTo) and
|
||||
not usesInstanceField(def)
|
||||
)
|
||||
@@ -528,26 +531,20 @@ module LocalFlow {
|
||||
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
LocalFlow::localFlowStepCommon(nodeFrom, nodeTo)
|
||||
or
|
||||
exists(Ssa::Definition def |
|
||||
exists(SsaImpl::DefinitionExt def |
|
||||
LocalFlow::localSsaFlowStepUseUse(def, nodeFrom, nodeTo) and
|
||||
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _) and
|
||||
not LocalFlow::usesInstanceField(def)
|
||||
)
|
||||
or
|
||||
// Flow into phi/uncertain SSA definition node from read
|
||||
exists(Ssa::Definition def, ControlFlow::Node read, Ssa::Definition next |
|
||||
LocalFlow::localFlowSsaInputFromExpr(read, def, next) and
|
||||
next = nodeTo.(SsaDefinitionNode).getDefinition() and
|
||||
def =
|
||||
[
|
||||
next.(Ssa::PhiNode).getAnInput(),
|
||||
next.(LocalFlow::UncertainExplicitSsaDefinition).getPriorDefinition()
|
||||
]
|
||||
// Flow into phi (read)/uncertain SSA definition node from read
|
||||
exists(SsaImpl::DefinitionExt def, Node read |
|
||||
LocalFlow::localFlowSsaInputFromRead(read, def, nodeTo)
|
||||
|
|
||||
exists(nodeFrom.asExprAtNode(read)) and
|
||||
nodeFrom = read and
|
||||
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _)
|
||||
or
|
||||
exists(nodeFrom.(PostUpdateNode).getPreUpdateNode().asExprAtNode(read))
|
||||
nodeFrom.(PostUpdateNode).getPreUpdateNode() = read
|
||||
)
|
||||
or
|
||||
LocalFlow::localFlowCapturedVarStep(nodeFrom, nodeTo)
|
||||
@@ -813,8 +810,8 @@ private module Cached {
|
||||
cfn.getElement() instanceof Expr
|
||||
} or
|
||||
TCilExprNode(CIL::Expr e) { e.getImplementation() instanceof CIL::BestImplementation } or
|
||||
TCilSsaDefinitionNode(CilSsa::Definition def) or
|
||||
TSsaDefinitionNode(Ssa::Definition def) {
|
||||
TCilSsaDefinitionExtNode(CilSsaImpl::DefinitionExt def) or
|
||||
TSsaDefinitionExtNode(SsaImpl::DefinitionExt def) {
|
||||
// Handled by `TExplicitParameterNode` below
|
||||
not def.(Ssa::ExplicitDefinition).getADefinition() instanceof
|
||||
AssignableDefinitions::ImplicitParameterDefinition
|
||||
@@ -880,24 +877,18 @@ private module Cached {
|
||||
or
|
||||
LocalFlow::localSsaFlowStepUseUse(_, nodeFrom, nodeTo)
|
||||
or
|
||||
exists(Ssa::Definition def |
|
||||
exists(SsaImpl::DefinitionExt def |
|
||||
LocalFlow::localSsaFlowStep(def, nodeFrom, nodeTo) and
|
||||
LocalFlow::usesInstanceField(def)
|
||||
)
|
||||
or
|
||||
// Flow into phi/uncertain SSA definition node from read
|
||||
exists(Ssa::Definition def, ControlFlow::Node read, Ssa::Definition next |
|
||||
LocalFlow::localFlowSsaInputFromExpr(read, def, next) and
|
||||
next = nodeTo.(SsaDefinitionNode).getDefinition() and
|
||||
def =
|
||||
[
|
||||
next.(Ssa::PhiNode).getAnInput(),
|
||||
next.(LocalFlow::UncertainExplicitSsaDefinition).getPriorDefinition()
|
||||
]
|
||||
// Flow into phi (read)/uncertain SSA definition node from read
|
||||
exists(SsaImpl::DefinitionExt def, Node read |
|
||||
LocalFlow::localFlowSsaInputFromRead(read, def, nodeTo)
|
||||
|
|
||||
exists(nodeFrom.asExprAtNode(read))
|
||||
nodeFrom = read
|
||||
or
|
||||
exists(nodeFrom.(PostUpdateNode).getPreUpdateNode().asExprAtNode(read))
|
||||
nodeFrom.(PostUpdateNode).getPreUpdateNode() = read
|
||||
)
|
||||
or
|
||||
// Simple flow through library code is included in the exposed local
|
||||
@@ -945,9 +936,11 @@ import Cached
|
||||
|
||||
/** Holds if `n` should be hidden from path explanations. */
|
||||
predicate nodeIsHidden(Node n) {
|
||||
exists(Ssa::Definition def | def = n.(SsaDefinitionNode).getDefinition() |
|
||||
exists(SsaImpl::DefinitionExt def | def = n.(SsaDefinitionExtNode).getDefinitionExt() |
|
||||
def instanceof Ssa::PhiNode
|
||||
or
|
||||
def instanceof SsaImpl::PhiReadNode
|
||||
or
|
||||
def instanceof Ssa::ImplicitEntryDefinition
|
||||
or
|
||||
def instanceof Ssa::ImplicitCallDefinition
|
||||
@@ -978,13 +971,13 @@ predicate nodeIsHidden(Node n) {
|
||||
}
|
||||
|
||||
/** A CIL SSA definition, viewed as a node in a data flow graph. */
|
||||
class CilSsaDefinitionNode extends NodeImpl, TCilSsaDefinitionNode {
|
||||
CilSsa::Definition def;
|
||||
class CilSsaDefinitionExtNode extends NodeImpl, TCilSsaDefinitionExtNode {
|
||||
CilSsaImpl::DefinitionExt def;
|
||||
|
||||
CilSsaDefinitionNode() { this = TCilSsaDefinitionNode(def) }
|
||||
CilSsaDefinitionExtNode() { this = TCilSsaDefinitionExtNode(def) }
|
||||
|
||||
/** Gets the underlying SSA definition. */
|
||||
CilSsa::Definition getDefinition() { result = def }
|
||||
CilSsaImpl::DefinitionExt getDefinition() { result = def }
|
||||
|
||||
override DataFlowCallable getEnclosingCallableImpl() {
|
||||
result.asCallable() = def.getBasicBlock().getFirstNode().getImplementation().getMethod()
|
||||
@@ -1000,13 +993,13 @@ class CilSsaDefinitionNode extends NodeImpl, TCilSsaDefinitionNode {
|
||||
}
|
||||
|
||||
/** An SSA definition, viewed as a node in a data flow graph. */
|
||||
class SsaDefinitionNode extends NodeImpl, TSsaDefinitionNode {
|
||||
Ssa::Definition def;
|
||||
class SsaDefinitionExtNode extends NodeImpl, TSsaDefinitionExtNode {
|
||||
SsaImpl::DefinitionExt def;
|
||||
|
||||
SsaDefinitionNode() { this = TSsaDefinitionNode(def) }
|
||||
SsaDefinitionExtNode() { this = TSsaDefinitionExtNode(def) }
|
||||
|
||||
/** Gets the underlying SSA definition. */
|
||||
Ssa::Definition getDefinition() { result = def }
|
||||
SsaImpl::DefinitionExt getDefinitionExt() { result = def }
|
||||
|
||||
override DataFlowCallable getEnclosingCallableImpl() {
|
||||
result.asCallable() = def.getEnclosingCallable()
|
||||
@@ -1014,7 +1007,9 @@ class SsaDefinitionNode extends NodeImpl, TSsaDefinitionNode {
|
||||
|
||||
override Type getTypeImpl() { result = def.getSourceVariable().getType() }
|
||||
|
||||
override ControlFlow::Node getControlFlowNodeImpl() { result = def.getControlFlowNode() }
|
||||
override ControlFlow::Node getControlFlowNodeImpl() {
|
||||
result = def.(Ssa::Definition).getControlFlowNode()
|
||||
}
|
||||
|
||||
override Location getLocationImpl() { result = def.getLocation() }
|
||||
|
||||
@@ -1108,13 +1103,11 @@ private module ParameterNodes {
|
||||
* } }
|
||||
* ```
|
||||
*/
|
||||
class ImplicitCapturedParameterNode extends ParameterNodeImpl, SsaDefinitionNode {
|
||||
override SsaCapturedEntryDefinition def;
|
||||
|
||||
ImplicitCapturedParameterNode() { def = this.getDefinition() }
|
||||
class ImplicitCapturedParameterNode extends ParameterNodeImpl, SsaDefinitionExtNode {
|
||||
ImplicitCapturedParameterNode() { def instanceof SsaCapturedEntryDefinition }
|
||||
|
||||
/** Gets the captured variable that this implicit parameter models. */
|
||||
LocalScopeVariable getVariable() { result = def.getVariable() }
|
||||
LocalScopeVariable getVariable() { result = def.(SsaCapturedEntryDefinition).getVariable() }
|
||||
|
||||
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
pos.isImplicitCapturedParameterPosition(def.getSourceVariable().getAssignable()) and
|
||||
@@ -1349,12 +1342,12 @@ private module ReturnNodes {
|
||||
* A data-flow node that represents an assignment to an `out` or a `ref`
|
||||
* parameter.
|
||||
*/
|
||||
class OutRefReturnNode extends ReturnNode, SsaDefinitionNode {
|
||||
class OutRefReturnNode extends ReturnNode, SsaDefinitionExtNode {
|
||||
OutRefReturnKind kind;
|
||||
|
||||
OutRefReturnNode() {
|
||||
exists(Parameter p |
|
||||
this.getDefinition().isLiveOutRefParameterDefinition(p) and
|
||||
this.getDefinitionExt().(Ssa::Definition).isLiveOutRefParameterDefinition(p) and
|
||||
kind.getPosition() = p.getPosition()
|
||||
|
|
||||
p.isOut() and kind instanceof OutReturnKind
|
||||
@@ -1438,11 +1431,11 @@ private module ReturnNodes {
|
||||
* } }
|
||||
* ```
|
||||
*/
|
||||
class ImplicitCapturedReturnNode extends ReturnNode, SsaDefinitionNode {
|
||||
class ImplicitCapturedReturnNode extends ReturnNode, SsaDefinitionExtNode {
|
||||
private Ssa::ExplicitDefinition edef;
|
||||
|
||||
ImplicitCapturedReturnNode() {
|
||||
edef = this.getDefinition() and
|
||||
edef = this.getDefinitionExt() and
|
||||
edef.isCapturedVariableDefinitionFlowOut(_, _)
|
||||
}
|
||||
|
||||
@@ -1450,8 +1443,8 @@ private module ReturnNodes {
|
||||
* Holds if the value at this node may flow out to the implicit call definition
|
||||
* at `node`, using one or more calls.
|
||||
*/
|
||||
predicate flowsOutTo(SsaDefinitionNode node, boolean additionalCalls) {
|
||||
edef.isCapturedVariableDefinitionFlowOut(node.getDefinition(), additionalCalls)
|
||||
predicate flowsOutTo(SsaDefinitionExtNode node, boolean additionalCalls) {
|
||||
edef.isCapturedVariableDefinitionFlowOut(node.getDefinitionExt(), additionalCalls)
|
||||
}
|
||||
|
||||
override ImplicitCapturedReturnKind getKind() {
|
||||
@@ -1558,13 +1551,13 @@ private module OutNodes {
|
||||
* A data-flow node that reads a value returned implicitly by a callable
|
||||
* using a captured variable.
|
||||
*/
|
||||
class CapturedOutNode extends OutNode, SsaDefinitionNode {
|
||||
class CapturedOutNode extends OutNode, SsaDefinitionExtNode {
|
||||
private DataFlowCall call;
|
||||
|
||||
CapturedOutNode() {
|
||||
exists(ImplicitCapturedReturnNode n, boolean additionalCalls, ControlFlow::Node cfn |
|
||||
n.flowsOutTo(this, additionalCalls) and
|
||||
cfn = this.getDefinition().getControlFlowNode()
|
||||
cfn = this.getDefinitionExt().(Ssa::Definition).getControlFlowNode()
|
||||
|
|
||||
additionalCalls = false and call = csharpCall(_, cfn)
|
||||
or
|
||||
@@ -1576,7 +1569,7 @@ private module OutNodes {
|
||||
override DataFlowCall getCall(ReturnKind kind) {
|
||||
result = call and
|
||||
kind.(ImplicitCapturedReturnKind).getVariable() =
|
||||
this.getDefinition().getSourceVariable().getAssignable()
|
||||
this.getDefinitionExt().getSourceVariable().getAssignable()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1857,7 +1850,7 @@ predicate readStep(Node node1, Content c, Node node2) {
|
||||
exists(ForeachStmt fs, Ssa::ExplicitDefinition def |
|
||||
x.hasDefPath(fs.getIterableExpr(), node1.getControlFlowNode(), def.getADefinition(),
|
||||
def.getControlFlowNode()) and
|
||||
node2.(SsaDefinitionNode).getDefinition() = def and
|
||||
node2.(SsaDefinitionExtNode).getDefinitionExt() = def and
|
||||
c instanceof ElementContent
|
||||
)
|
||||
or
|
||||
@@ -1880,7 +1873,7 @@ predicate readStep(Node node1, Content c, Node node2) {
|
||||
or
|
||||
// item = variable in node1 = (..., variable, ...)
|
||||
exists(AssignableDefinitions::TupleAssignmentDefinition tad, Ssa::ExplicitDefinition def |
|
||||
node2.(SsaDefinitionNode).getDefinition() = def and
|
||||
node2.(SsaDefinitionExtNode).getDefinitionExt() = def and
|
||||
def.getADefinition() = tad and
|
||||
tad.getLeaf() = item and
|
||||
hasNodePath(x, node1, node2)
|
||||
@@ -1889,7 +1882,7 @@ predicate readStep(Node node1, Content c, Node node2) {
|
||||
// item = variable in node1 = (..., variable, ...) in a case/is var (..., ...)
|
||||
te = any(PatternExpr pe).getAChildExpr*() and
|
||||
exists(AssignableDefinitions::LocalVariableDefinition lvd, Ssa::ExplicitDefinition def |
|
||||
node2.(SsaDefinitionNode).getDefinition() = def and
|
||||
node2.(SsaDefinitionExtNode).getDefinitionExt() = def and
|
||||
def.getADefinition() = lvd and
|
||||
lvd.getDeclaration() = item and
|
||||
hasNodePath(x, node1, node2)
|
||||
@@ -2223,7 +2216,7 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
|
||||
|
||||
/** Extra data-flow steps needed for lambda flow analysis. */
|
||||
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) {
|
||||
exists(Ssa::Definition def |
|
||||
exists(SsaImpl::DefinitionExt def |
|
||||
LocalFlow::localSsaFlowStep(def, nodeFrom, nodeTo) and
|
||||
LocalFlow::usesInstanceField(def) and
|
||||
preservesValue = true
|
||||
|
||||
@@ -119,10 +119,10 @@ class ParameterNode extends Node instanceof ParameterNodeImpl {
|
||||
}
|
||||
|
||||
/** A definition, viewed as a node in a data flow graph. */
|
||||
class AssignableDefinitionNode extends Node, TSsaDefinitionNode {
|
||||
class AssignableDefinitionNode extends Node, TSsaDefinitionExtNode {
|
||||
private Ssa::ExplicitDefinition edef;
|
||||
|
||||
AssignableDefinitionNode() { this = TSsaDefinitionNode(edef) }
|
||||
AssignableDefinitionNode() { this = TSsaDefinitionExtNode(edef) }
|
||||
|
||||
/** Gets the underlying definition. */
|
||||
AssignableDefinition getDefinition() { result = this.getDefinitionAtNode(_) }
|
||||
|
||||
@@ -1093,35 +1093,79 @@ private predicate adjacentDefRead(
|
||||
}
|
||||
|
||||
private predicate adjacentDefReachesRead(
|
||||
Definition def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
|
||||
Definition def, SsaInput::SourceVariable v, SsaInput::BasicBlock bb1, int i1,
|
||||
SsaInput::BasicBlock bb2, int i2
|
||||
) {
|
||||
exists(SsaInput::SourceVariable v | adjacentDefRead(def, bb1, i1, bb2, i2, v) |
|
||||
adjacentDefRead(def, bb1, i1, bb2, i2, v) and
|
||||
(
|
||||
def.definesAt(v, bb1, i1)
|
||||
or
|
||||
SsaInput::variableRead(bb1, i1, v, true)
|
||||
)
|
||||
or
|
||||
exists(SsaInput::BasicBlock bb3, int i3 |
|
||||
adjacentDefReachesRead(def, bb1, i1, bb3, i3) and
|
||||
adjacentDefReachesRead(def, v, bb1, i1, bb3, i3) and
|
||||
SsaInput::variableRead(bb3, i3, _, false) and
|
||||
Impl::adjacentDefRead(def, bb3, i3, bb2, i2)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate adjacentDefReachesReadExt(
|
||||
DefinitionExt def, SsaInput::SourceVariable v, SsaInput::BasicBlock bb1, int i1,
|
||||
SsaInput::BasicBlock bb2, int i2
|
||||
) {
|
||||
Impl::adjacentDefReadExt(def, v, bb1, i1, bb2, i2) and
|
||||
(
|
||||
def.definesAt(v, bb1, i1, _)
|
||||
or
|
||||
SsaInput::variableRead(bb1, i1, v, true)
|
||||
)
|
||||
or
|
||||
exists(SsaInput::BasicBlock bb3, int i3 |
|
||||
adjacentDefReachesReadExt(def, v, bb1, i1, bb3, i3) and
|
||||
SsaInput::variableRead(bb3, i3, v, false) and
|
||||
Impl::adjacentDefReadExt(def, v, bb3, i3, bb2, i2)
|
||||
)
|
||||
}
|
||||
|
||||
/** Same as `adjacentDefRead`, but skips uncertain reads. */
|
||||
pragma[nomagic]
|
||||
private predicate adjacentDefSkipUncertainReads(
|
||||
Definition def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
|
||||
) {
|
||||
adjacentDefReachesRead(def, bb1, i1, bb2, i2) and
|
||||
SsaInput::variableRead(bb2, i2, _, true)
|
||||
exists(SsaInput::SourceVariable v |
|
||||
adjacentDefReachesRead(def, v, bb1, i1, bb2, i2) and
|
||||
SsaInput::variableRead(bb2, i2, v, true)
|
||||
)
|
||||
}
|
||||
|
||||
/** Same as `adjacentDefReadExt`, but skips uncertain reads. */
|
||||
pragma[nomagic]
|
||||
private predicate adjacentDefSkipUncertainReadsExt(
|
||||
DefinitionExt def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
|
||||
) {
|
||||
exists(SsaInput::SourceVariable v |
|
||||
adjacentDefReachesReadExt(def, v, bb1, i1, bb2, i2) and
|
||||
SsaInput::variableRead(bb2, i2, v, true)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate adjacentDefReachesUncertainRead(
|
||||
Definition def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
|
||||
) {
|
||||
adjacentDefReachesRead(def, bb1, i1, bb2, i2) and
|
||||
SsaInput::variableRead(bb2, i2, _, false)
|
||||
exists(SsaInput::SourceVariable v |
|
||||
adjacentDefReachesRead(def, v, bb1, i1, bb2, i2) and
|
||||
SsaInput::variableRead(bb2, i2, v, false)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate adjacentDefReachesUncertainReadExt(
|
||||
DefinitionExt def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
|
||||
) {
|
||||
exists(SsaInput::SourceVariable v |
|
||||
adjacentDefReachesReadExt(def, v, bb1, i1, bb2, i2) and
|
||||
SsaInput::variableRead(bb2, i2, v, false)
|
||||
)
|
||||
}
|
||||
|
||||
/** Same as `lastRefRedef`, but skips uncertain reads. */
|
||||
@@ -1311,6 +1355,19 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the value defined at SSA definition `def` can reach a read at `cfn`,
|
||||
* without passing through any other read.
|
||||
*/
|
||||
cached
|
||||
predicate firstReadSameVarExt(DefinitionExt def, ControlFlow::Node cfn) {
|
||||
exists(ControlFlow::BasicBlock bb1, int i1, ControlFlow::BasicBlock bb2, int i2 |
|
||||
def.definesAt(_, bb1, i1, _) and
|
||||
adjacentDefSkipUncertainReadsExt(def, bb1, i1, bb2, i2) and
|
||||
cfn = bb2.getNode(i2)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the read at `cfn2` is a read of the same SSA definition `def`
|
||||
* as the read at `cfn1`, and `cfn2` can be reached from `cfn1` without
|
||||
@@ -1326,7 +1383,23 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
/** Same as `lastRefRedef`, but skips uncertain reads. */
|
||||
/**
|
||||
* Holds if the read at `cfn2` is a read of the same SSA definition `def`
|
||||
* as the read at `cfn1`, and `cfn2` can be reached from `cfn1` without
|
||||
* passing through another read.
|
||||
*/
|
||||
cached
|
||||
predicate adjacentReadPairSameVarExt(
|
||||
DefinitionExt def, ControlFlow::Node cfn1, ControlFlow::Node cfn2
|
||||
) {
|
||||
exists(ControlFlow::BasicBlock bb1, int i1, ControlFlow::BasicBlock bb2, int i2 |
|
||||
cfn1 = bb1.getNode(i1) and
|
||||
variableReadActual(bb1, i1, _) and
|
||||
adjacentDefSkipUncertainReadsExt(def, bb1, i1, bb2, i2) and
|
||||
cfn2 = bb2.getNode(i2)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate lastRefBeforeRedef(Definition def, ControlFlow::BasicBlock bb, int i, Definition next) {
|
||||
Impl::lastRefRedef(def, bb, i, next) and
|
||||
@@ -1338,6 +1411,21 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate lastRefBeforeRedefExt(
|
||||
DefinitionExt def, ControlFlow::BasicBlock bb, int i, DefinitionExt next
|
||||
) {
|
||||
exists(SsaInput::SourceVariable v |
|
||||
Impl::lastRefRedefExt(def, v, bb, i, next) and
|
||||
not SsaInput::variableRead(bb, i, v, false)
|
||||
)
|
||||
or
|
||||
exists(SsaInput::BasicBlock bb0, int i0 |
|
||||
Impl::lastRefRedefExt(def, _, bb0, i0, next) and
|
||||
adjacentDefReachesUncertainReadExt(def, bb, i, bb0, i0)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate lastReadSameVar(Definition def, ControlFlow::Node cfn) {
|
||||
exists(ControlFlow::BasicBlock bb, int i |
|
||||
@@ -1399,6 +1487,9 @@ class DefinitionExt extends Impl::DefinitionExt {
|
||||
|
||||
/** Gets the location of this definition. */
|
||||
Location getLocation() { result = this.(Ssa::Definition).getLocation() }
|
||||
|
||||
/** Gets the enclosing callable of this definition. */
|
||||
Callable getEnclosingCallable() { result = this.(Ssa::Definition).getEnclosingCallable() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1412,4 +1503,8 @@ class PhiReadNode extends DefinitionExt, Impl::PhiReadNode {
|
||||
}
|
||||
|
||||
override Location getLocation() { result = this.getBasicBlock().getLocation() }
|
||||
|
||||
override Callable getEnclosingCallable() {
|
||||
result = this.getSourceVariable().getEnclosingCallable()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ private import semmle.code.csharp.frameworks.system.data.Entity
|
||||
private import semmle.code.csharp.frameworks.system.collections.Generic
|
||||
private import semmle.code.csharp.frameworks.Sql
|
||||
private import semmle.code.csharp.dataflow.FlowSummary
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate as DataFlowPrivate
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** Definitions relating to the `Json.NET` package. */
|
||||
module JsonNET {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** A class representing a Service */
|
||||
private class ServiceClass extends Class {
|
||||
|
||||
@@ -7,7 +7,6 @@ private import semmle.code.csharp.frameworks.EntityFramework
|
||||
private import semmle.code.csharp.frameworks.NHibernate
|
||||
private import semmle.code.csharp.frameworks.Dapper
|
||||
private import semmle.code.csharp.dataflow.DataFlow4
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** An expression containing a SQL command. */
|
||||
abstract class SqlExpr extends Expr {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import csharp
|
||||
private import system.Reflection
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** The `System` namespace. */
|
||||
class SystemNamespace extends Namespace {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.frameworks.System
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** The `System.CodeDome` namespace. */
|
||||
class SystemCodeDomNamespace extends Namespace {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.frameworks.System
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
private import semmle.code.csharp.dataflow.FlowSummary
|
||||
|
||||
/** The `System.Collections` namespace. */
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.frameworks.System
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** The `System.Data` namespace. */
|
||||
class SystemDataNamespace extends Namespace {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import semmle.code.csharp.Type
|
||||
private import semmle.code.csharp.frameworks.System
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** The `System.Diagnostics` namespace. */
|
||||
class SystemDiagnosticsNamespace extends Namespace {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.frameworks.System
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** The `System.IO` namespace. */
|
||||
class SystemIONamespace extends Namespace {
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
private import csharp as CSharp
|
||||
private import semmle.code.csharp.frameworks.System as System
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow as ExternalFlow
|
||||
|
||||
/** Definitions relating to the `System.Linq` namespace. */
|
||||
module SystemLinq {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.frameworks.System
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** The `System.Net` namespace. */
|
||||
class SystemNetNamespace extends Namespace {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/** Provides classes related to the namespace `System.Security`. */
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
private import semmle.code.csharp.frameworks.System
|
||||
|
||||
/** The `System.Security` namespace. */
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.frameworks.System
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
private import semmle.code.csharp.dataflow.FlowSummary
|
||||
|
||||
/** The `System.Text` namespace. */
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import csharp
|
||||
private import semmle.code.csharp.frameworks.System
|
||||
private import semmle.code.csharp.frameworks.system.collections.Specialized
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** The `System.Web` namespace. */
|
||||
class SystemWebNamespace extends Namespace {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import csharp
|
||||
private import semmle.code.csharp.frameworks.System
|
||||
private import semmle.code.csharp.dataflow.DataFlow3
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** The `System.Xml` namespace. */
|
||||
class SystemXmlNamespace extends Namespace {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.frameworks.system.Collections
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** The `System.Collections.Generic` namespace. */
|
||||
class SystemCollectionsGenericNamespace extends Namespace {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.frameworks.system.Collections
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** The `System.Collections.Specialized` namespace. */
|
||||
class SystemCollectionsSpecializedNamespace extends Namespace {
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
private import csharp as CSharp
|
||||
private import semmle.code.csharp.frameworks.system.Data as Data
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow as ExternalFlow
|
||||
|
||||
/** Definitions relating to the `System.Data.Common` namespace. */
|
||||
module SystemDataCommon {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.frameworks.system.IO
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** The `System.IO.Compression` namespace. */
|
||||
class SystemIOCompressionNamespace extends Namespace {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.frameworks.system.Net
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** The `System.Net.Mail` namespace. */
|
||||
class SystemNetMailNamespace extends Namespace {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import csharp
|
||||
private import semmle.code.csharp.frameworks.system.Runtime
|
||||
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** The `System.Runtime.CompilerServices` namespace. */
|
||||
class SystemRuntimeCompilerServicesNamespace extends Namespace {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.frameworks.system.Security
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** The `System.Security.Cryptography` namespace. */
|
||||
class SystemSecurityCryptographyNamespace extends Namespace {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.frameworks.system.security.Cryptography
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** The `System.Security.Cryptography.X509Certificates` namespace. */
|
||||
class SystemSecurityCryptographyX509CertificatesNamespace extends Namespace {
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
import default
|
||||
import semmle.code.csharp.frameworks.system.Text
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** The `System.Text.RegularExpressions` namespace. */
|
||||
class SystemTextRegularExpressionsNamespace extends Namespace {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import csharp
|
||||
private import semmle.code.csharp.frameworks.system.Threading
|
||||
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** The `System.Threading.Tasks` namespace. */
|
||||
class SystemThreadingTasksNamespace extends Namespace {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.frameworks.system.web.UI
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** The `System.Web.UI.WebControls` namespace. */
|
||||
class SystemWebUIWebControlsNamespace extends Namespace {
|
||||
|
||||
@@ -19,6 +19,13 @@ abstract class RemoteFlowSource extends DataFlow::Node {
|
||||
abstract string getSourceType();
|
||||
}
|
||||
|
||||
/**
|
||||
* A module for importing frameworks that defines remote flow sources.
|
||||
*/
|
||||
private module RemoteFlowSources {
|
||||
private import semmle.code.csharp.frameworks.ServiceStack
|
||||
}
|
||||
|
||||
/** A data flow source of remote user input (ASP.NET). */
|
||||
abstract class AspNetRemoteFlowSource extends RemoteFlowSource { }
|
||||
|
||||
|
||||
@@ -10,26 +10,26 @@ private predicate trivialPositiveIntValue(string s) {
|
||||
s =
|
||||
[
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16",
|
||||
"17", "18", "19", "20", "16", "32", "64", "128", "256", "512", "1024", "2048", "4096",
|
||||
"16384", "32768", "65536", "1048576", "2147483648", "4294967296", "15", "31", "63", "127",
|
||||
"255", "511", "1023", "2047", "4095", "16383", "32767", "65535", "1048577", "2147483647",
|
||||
"4294967295", "0x00000001", "0x00000002", "0x00000004", "0x00000008", "0x00000010",
|
||||
"0x00000020", "0x00000040", "0x00000080", "0x00000100", "0x00000200", "0x00000400",
|
||||
"0x00000800", "0x00001000", "0x00002000", "0x00004000", "0x00008000", "0x00010000",
|
||||
"0x00020000", "0x00040000", "0x00080000", "0x00100000", "0x00200000", "0x00400000",
|
||||
"0x00800000", "0x01000000", "0x02000000", "0x04000000", "0x08000000", "0x10000000",
|
||||
"0x20000000", "0x40000000", "0x80000000", "0x00000001", "0x00000003", "0x00000007",
|
||||
"0x0000000f", "0x0000001f", "0x0000003f", "0x0000007f", "0x000000ff", "0x000001ff",
|
||||
"0x000003ff", "0x000007ff", "0x00000fff", "0x00001fff", "0x00003fff", "0x00007fff",
|
||||
"0x0000ffff", "0x0001ffff", "0x0003ffff", "0x0007ffff", "0x000fffff", "0x001fffff",
|
||||
"0x003fffff", "0x007fffff", "0x00ffffff", "0x01ffffff", "0x03ffffff", "0x07ffffff",
|
||||
"0x0fffffff", "0x1fffffff", "0x3fffffff", "0x7fffffff", "0xffffffff", "0x0001", "0x0002",
|
||||
"0x0004", "0x0008", "0x0010", "0x0020", "0x0040", "0x0080", "0x0100", "0x0200", "0x0400",
|
||||
"0x0800", "0x1000", "0x2000", "0x4000", "0x8000", "0x0001", "0x0003", "0x0007", "0x000f",
|
||||
"0x001f", "0x003f", "0x007f", "0x00ff", "0x01ff", "0x03ff", "0x07ff", "0x0fff", "0x1fff",
|
||||
"0x3fff", "0x7fff", "0xffff", "0x01", "0x02", "0x04", "0x08", "0x10", "0x20", "0x40", "0x80",
|
||||
"0x01", "0x03", "0x07", "0x0f", "0x1f", "0x3f", "0x7f", "0xff", "0x00", "10", "100", "1000",
|
||||
"10000", "100000", "1000000", "10000000", "100000000", "1000000000"
|
||||
"17", "18", "19", "20", "32", "64", "128", "256", "512", "1024", "2048", "4096", "16384",
|
||||
"32768", "65536", "1048576", "2147483648", "4294967296", "31", "63", "127", "255", "511",
|
||||
"1023", "2047", "4095", "16383", "32767", "65535", "1048577", "2147483647", "4294967295",
|
||||
"0x00000001", "0x00000002", "0x00000004", "0x00000008", "0x00000010", "0x00000020",
|
||||
"0x00000040", "0x00000080", "0x00000100", "0x00000200", "0x00000400", "0x00000800",
|
||||
"0x00001000", "0x00002000", "0x00004000", "0x00008000", "0x00010000", "0x00020000",
|
||||
"0x00040000", "0x00080000", "0x00100000", "0x00200000", "0x00400000", "0x00800000",
|
||||
"0x01000000", "0x02000000", "0x04000000", "0x08000000", "0x10000000", "0x20000000",
|
||||
"0x40000000", "0x80000000", "0x00000003", "0x00000007", "0x0000000f", "0x0000001f",
|
||||
"0x0000003f", "0x0000007f", "0x000000ff", "0x000001ff", "0x000003ff", "0x000007ff",
|
||||
"0x00000fff", "0x00001fff", "0x00003fff", "0x00007fff", "0x0000ffff", "0x0001ffff",
|
||||
"0x0003ffff", "0x0007ffff", "0x000fffff", "0x001fffff", "0x003fffff", "0x007fffff",
|
||||
"0x00ffffff", "0x01ffffff", "0x03ffffff", "0x07ffffff", "0x0fffffff", "0x1fffffff",
|
||||
"0x3fffffff", "0x7fffffff", "0xffffffff", "0x0001", "0x0002", "0x0004", "0x0008", "0x0010",
|
||||
"0x0020", "0x0040", "0x0080", "0x0100", "0x0200", "0x0400", "0x0800", "0x1000", "0x2000",
|
||||
"0x4000", "0x8000", "0x0003", "0x0007", "0x000f", "0x001f", "0x003f", "0x007f", "0x00ff",
|
||||
"0x01ff", "0x03ff", "0x07ff", "0x0fff", "0x1fff", "0x3fff", "0x7fff", "0xffff", "0x02",
|
||||
"0x04", "0x08", "0x10", "0x20", "0x40", "0x80", "0x01", "0x03", "0x07", "0x0f", "0x1f",
|
||||
"0x3f", "0x7f", "0xff", "0x00", "100", "1000", "10000", "100000", "1000000", "10000000",
|
||||
"100000000", "1000000000"
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
* @tags model-generator
|
||||
*/
|
||||
|
||||
import semmle.code.csharp.dataflow.ExternalFlow
|
||||
import utils.modelgenerator.internal.CaptureTypeBasedSummaryModels
|
||||
|
||||
from TypeBasedFlowTargetApi api, string flow
|
||||
|
||||
@@ -34,7 +34,6 @@ where
|
||||
f.hasName("f") and
|
||||
g.hasName("g") and
|
||||
a.getDeclaringType() = class1 and
|
||||
a.getDeclaringType() = class1 and
|
||||
b.getDeclaringType() = class1 and
|
||||
c.getDeclaringType() = class1 and
|
||||
not exists(c.getParameter(0).getType().(KnownType)) and
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
| CSharp7.cs:232:20:232:23 | null | CSharp7.cs:232:16:232:23 | SSA def(o) |
|
||||
| CSharp7.cs:233:13:233:13 | access to local variable o | CSharp7.cs:233:18:233:23 | SSA def(i1) |
|
||||
| CSharp7.cs:233:13:233:13 | access to local variable o | CSharp7.cs:237:18:237:18 | access to local variable o |
|
||||
| CSharp7.cs:233:13:233:13 | access to local variable o | CSharp7.cs:248:17:248:17 | access to local variable o |
|
||||
| CSharp7.cs:233:13:233:13 | access to local variable o | CSharp7.cs:248:9:274:9 | SSA phi read(o) |
|
||||
| CSharp7.cs:233:13:233:23 | [false] ... is ... | CSharp7.cs:233:13:233:33 | [false] ... && ... |
|
||||
| CSharp7.cs:233:13:233:23 | [true] ... is ... | CSharp7.cs:233:13:233:33 | [false] ... && ... |
|
||||
| CSharp7.cs:233:13:233:23 | [true] ... is ... | CSharp7.cs:233:13:233:33 | [true] ... && ... |
|
||||
@@ -173,13 +173,14 @@
|
||||
| CSharp7.cs:235:38:235:39 | access to local variable i1 | CSharp7.cs:235:31:235:41 | $"..." |
|
||||
| CSharp7.cs:237:18:237:18 | access to local variable o | CSharp7.cs:237:23:237:31 | SSA def(s1) |
|
||||
| CSharp7.cs:237:18:237:18 | access to local variable o | CSharp7.cs:241:18:241:18 | access to local variable o |
|
||||
| CSharp7.cs:237:18:237:18 | access to local variable o | CSharp7.cs:248:17:248:17 | access to local variable o |
|
||||
| CSharp7.cs:237:18:237:18 | access to local variable o | CSharp7.cs:248:9:274:9 | SSA phi read(o) |
|
||||
| CSharp7.cs:237:23:237:31 | SSA def(s1) | CSharp7.cs:239:41:239:42 | access to local variable s1 |
|
||||
| CSharp7.cs:239:33:239:39 | "string " | CSharp7.cs:239:31:239:44 | $"..." |
|
||||
| CSharp7.cs:239:41:239:42 | access to local variable s1 | CSharp7.cs:239:31:239:44 | $"..." |
|
||||
| CSharp7.cs:241:18:241:18 | access to local variable o | CSharp7.cs:244:18:244:18 | access to local variable o |
|
||||
| CSharp7.cs:241:18:241:18 | access to local variable o | CSharp7.cs:248:17:248:17 | access to local variable o |
|
||||
| CSharp7.cs:244:18:244:18 | access to local variable o | CSharp7.cs:248:17:248:17 | access to local variable o |
|
||||
| CSharp7.cs:241:18:241:18 | access to local variable o | CSharp7.cs:248:9:274:9 | SSA phi read(o) |
|
||||
| CSharp7.cs:244:18:244:18 | access to local variable o | CSharp7.cs:248:9:274:9 | SSA phi read(o) |
|
||||
| CSharp7.cs:248:9:274:9 | SSA phi read(o) | CSharp7.cs:248:17:248:17 | access to local variable o |
|
||||
| CSharp7.cs:248:17:248:17 | access to local variable o | CSharp7.cs:254:27:254:27 | access to local variable o |
|
||||
| CSharp7.cs:248:17:248:17 | access to local variable o | CSharp7.cs:257:18:257:23 | SSA def(i2) |
|
||||
| CSharp7.cs:248:17:248:17 | access to local variable o | CSharp7.cs:260:18:260:23 | SSA def(i3) |
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
||||
class C
|
||||
{
|
||||
int Prop { get; set; }
|
||||
|
||||
// Should generate 100 + 100 local use-use flow steps for `x`, and not 100 * 100
|
||||
//
|
||||
// Generated by quick-evaling `gen/0` below:
|
||||
//
|
||||
// ```ql
|
||||
// string gen(int depth) {
|
||||
// depth in [0 .. 100] and
|
||||
// (
|
||||
// if depth = 0
|
||||
// then result = ""
|
||||
// else result = "if (Prop > " + depth + ") { " + gen(depth - 1) + " } else Use(x);"
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// string gen() { result = "var x = 0;\n" + gen(100) + "\n" + gen(100) }
|
||||
// ```
|
||||
void M()
|
||||
{
|
||||
var x = 0;
|
||||
if (Prop > 100) { if (Prop > 99) { if (Prop > 98) { if (Prop > 97) { if (Prop > 96) { if (Prop > 95) { if (Prop > 94) { if (Prop > 93) { if (Prop > 92) { if (Prop > 91) { if (Prop > 90) { if (Prop > 89) { if (Prop > 88) { if (Prop > 87) { if (Prop > 86) { if (Prop > 85) { if (Prop > 84) { if (Prop > 83) { if (Prop > 82) { if (Prop > 81) { if (Prop > 80) { if (Prop > 79) { if (Prop > 78) { if (Prop > 77) { if (Prop > 76) { if (Prop > 75) { if (Prop > 74) { if (Prop > 73) { if (Prop > 72) { if (Prop > 71) { if (Prop > 70) { if (Prop > 69) { if (Prop > 68) { if (Prop > 67) { if (Prop > 66) { if (Prop > 65) { if (Prop > 64) { if (Prop > 63) { if (Prop > 62) { if (Prop > 61) { if (Prop > 60) { if (Prop > 59) { if (Prop > 58) { if (Prop > 57) { if (Prop > 56) { if (Prop > 55) { if (Prop > 54) { if (Prop > 53) { if (Prop > 52) { if (Prop > 51) { if (Prop > 50) { if (Prop > 49) { if (Prop > 48) { if (Prop > 47) { if (Prop > 46) { if (Prop > 45) { if (Prop > 44) { if (Prop > 43) { if (Prop > 42) { if (Prop > 41) { if (Prop > 40) { if (Prop > 39) { if (Prop > 38) { if (Prop > 37) { if (Prop > 36) { if (Prop > 35) { if (Prop > 34) { if (Prop > 33) { if (Prop > 32) { if (Prop > 31) { if (Prop > 30) { if (Prop > 29) { if (Prop > 28) { if (Prop > 27) { if (Prop > 26) { if (Prop > 25) { if (Prop > 24) { if (Prop > 23) { if (Prop > 22) { if (Prop > 21) { if (Prop > 20) { if (Prop > 19) { if (Prop > 18) { if (Prop > 17) { if (Prop > 16) { if (Prop > 15) { if (Prop > 14) { if (Prop > 13) { if (Prop > 12) { if (Prop > 11) { if (Prop > 10) { if (Prop > 9) { if (Prop > 8) { if (Prop > 7) { if (Prop > 6) { if (Prop > 5) { if (Prop > 4) { if (Prop > 3) { if (Prop > 2) { if (Prop > 1) { } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x);
|
||||
if (Prop > 100) { if (Prop > 99) { if (Prop > 98) { if (Prop > 97) { if (Prop > 96) { if (Prop > 95) { if (Prop > 94) { if (Prop > 93) { if (Prop > 92) { if (Prop > 91) { if (Prop > 90) { if (Prop > 89) { if (Prop > 88) { if (Prop > 87) { if (Prop > 86) { if (Prop > 85) { if (Prop > 84) { if (Prop > 83) { if (Prop > 82) { if (Prop > 81) { if (Prop > 80) { if (Prop > 79) { if (Prop > 78) { if (Prop > 77) { if (Prop > 76) { if (Prop > 75) { if (Prop > 74) { if (Prop > 73) { if (Prop > 72) { if (Prop > 71) { if (Prop > 70) { if (Prop > 69) { if (Prop > 68) { if (Prop > 67) { if (Prop > 66) { if (Prop > 65) { if (Prop > 64) { if (Prop > 63) { if (Prop > 62) { if (Prop > 61) { if (Prop > 60) { if (Prop > 59) { if (Prop > 58) { if (Prop > 57) { if (Prop > 56) { if (Prop > 55) { if (Prop > 54) { if (Prop > 53) { if (Prop > 52) { if (Prop > 51) { if (Prop > 50) { if (Prop > 49) { if (Prop > 48) { if (Prop > 47) { if (Prop > 46) { if (Prop > 45) { if (Prop > 44) { if (Prop > 43) { if (Prop > 42) { if (Prop > 41) { if (Prop > 40) { if (Prop > 39) { if (Prop > 38) { if (Prop > 37) { if (Prop > 36) { if (Prop > 35) { if (Prop > 34) { if (Prop > 33) { if (Prop > 32) { if (Prop > 31) { if (Prop > 30) { if (Prop > 29) { if (Prop > 28) { if (Prop > 27) { if (Prop > 26) { if (Prop > 25) { if (Prop > 24) { if (Prop > 23) { if (Prop > 22) { if (Prop > 21) { if (Prop > 20) { if (Prop > 19) { if (Prop > 18) { if (Prop > 17) { if (Prop > 16) { if (Prop > 15) { if (Prop > 14) { if (Prop > 13) { if (Prop > 12) { if (Prop > 11) { if (Prop > 10) { if (Prop > 9) { if (Prop > 8) { if (Prop > 7) { if (Prop > 6) { if (Prop > 5) { if (Prop > 4) { if (Prop > 3) { if (Prop > 2) { if (Prop > 1) { } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x); } else Use(x);
|
||||
}
|
||||
|
||||
void Use(int i) { }
|
||||
}
|
||||
@@ -2886,7 +2886,7 @@ public class Large
|
||||
// (
|
||||
// if depth = 0
|
||||
// then result = ""
|
||||
// else else result = "if (Prop > " + depth + ") { " + gen(depth - 1, var) + " } else Use(" + var + ");"
|
||||
// else result = "if (Prop > " + depth + ") { " + gen(depth - 1, var) + " } else Use(" + var + ");"
|
||||
// )
|
||||
// }
|
||||
//
|
||||
|
||||
27
csharp/scripts/create-extractor-pack.sh
Executable file
27
csharp/scripts/create-extractor-pack.sh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
set -eux
|
||||
|
||||
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||
platform="linux64"
|
||||
dotnet_platform="linux-x64"
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
platform="osx64"
|
||||
dotnet_platform="osx-x64"
|
||||
else
|
||||
echo "Unknown OS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -rf extractor-pack
|
||||
mkdir -p extractor-pack
|
||||
mkdir -p extractor-pack/tools/${platform}
|
||||
|
||||
function dotnet_publish {
|
||||
dotnet publish --self-contained --configuration Release --runtime ${dotnet_platform} -p:RuntimeFrameworkVersion=6.0.4 $1 --output extractor-pack/tools/${platform}
|
||||
}
|
||||
|
||||
dotnet_publish extractor/Semmle.Extraction.CSharp.Standalone
|
||||
dotnet_publish extractor/Semmle.Extraction.CSharp.Driver
|
||||
dotnet_publish autobuilder/Semmle.Autobuild.CSharp
|
||||
|
||||
cp -r codeql-extractor.yml tools/* downgrades tools ql/lib/semmlecode.csharp.dbscheme ql/lib/semmlecode.csharp.dbscheme.stats extractor-pack/
|
||||
@@ -168,7 +168,9 @@ generate a database, therefore the build method must be available to the CLI.
|
||||
Detecting the build system
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The CodeQL CLI includes autobuilders for C/C++, C#, Go, and Java code. CodeQL
|
||||
.. include:: ../reusables/kotlin-beta-note.rst
|
||||
|
||||
The CodeQL CLI includes autobuilders for C/C++, C#, Go, Java and Kotlin code. CodeQL
|
||||
autobuilders allow you to build projects for compiled languages without
|
||||
specifying any build commands. When an autobuilder is invoked, CodeQL examines
|
||||
the source for evidence of a build system and attempts to run the optimal set of
|
||||
|
||||
@@ -30,7 +30,7 @@ You can then use the CodeQL CLI to publish your pack to share with others. For m
|
||||
Viewing CodeQL packs and their dependencies in Visual Studio Code
|
||||
-----------------------------------------------------------------
|
||||
To download a CodeQL pack that someone else has created, run the **CodeQL: Download Packs** command from the Command Palette.
|
||||
You can download all the core CodeQL query packs, or enter the full name of a specific pack to download. For example, to download the core queries for analyzing Java, enter ``codeql/java-queries``.
|
||||
You can download all the core CodeQL query packs, or enter the full name of a specific pack to download. For example, to download the core queries for analyzing Java or Kotlin, enter ``codeql/java-queries``.
|
||||
|
||||
Whether you have downloaded a CodeQL pack or created your own, you can open the ``qlpack.yml`` file in the root of a CodeQL pack directory in Visual Studio Code and view the dependencies section to see what libraries the pack depends on.
|
||||
|
||||
|
||||
@@ -7,6 +7,10 @@ CodeQL has a large selection of classes for representing the abstract syntax tre
|
||||
|
||||
.. include:: ../reusables/abstract-syntax-tree.rst
|
||||
|
||||
.. include:: ../reusables/kotlin-beta-note.rst
|
||||
|
||||
.. include:: ../reusables/kotlin-java-differences.rst
|
||||
|
||||
Statement classes
|
||||
-----------------
|
||||
|
||||
|
||||
@@ -5,6 +5,10 @@ Analyzing data flow in Java
|
||||
|
||||
You can use CodeQL to track the flow of data through a Java program to its use.
|
||||
|
||||
.. include:: ../reusables/kotlin-beta-note.rst
|
||||
|
||||
.. include:: ../reusables/kotlin-java-differences.rst
|
||||
|
||||
About this article
|
||||
------------------
|
||||
|
||||
|
||||
@@ -1,18 +1,33 @@
|
||||
.. _basic-query-for-java-code:
|
||||
|
||||
Basic query for Java code
|
||||
=========================
|
||||
Basic query for Java and Kotlin code
|
||||
====================================
|
||||
|
||||
Learn to write and run a simple CodeQL query using LGTM.
|
||||
|
||||
About the query
|
||||
---------------
|
||||
|
||||
The query we're going to run performs a basic search of the code for ``if`` statements that are redundant, in the sense that they have an empty then branch. For example, code such as:
|
||||
The query we're going to run searches for inefficient tests for empty strings. For example, Java code such as:
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
if (error) { }
|
||||
public class TestJava {
|
||||
void myJavaFun(String s) {
|
||||
boolean b = s.equals("");
|
||||
}
|
||||
}
|
||||
|
||||
or Kotlin code such as:
|
||||
|
||||
.. code-block:: kotlin
|
||||
|
||||
void myKotlinFun(s: String) {
|
||||
var b = s.equals("")
|
||||
}
|
||||
|
||||
In either case, replacing ``s.equals("")`` with ``s.isEmpty()``
|
||||
would be more efficient.
|
||||
|
||||
Running the query
|
||||
-----------------
|
||||
@@ -37,10 +52,13 @@ Running the query
|
||||
|
||||
import java
|
||||
|
||||
from IfStmt ifstmt, Block block
|
||||
where ifstmt.getThen() = block and
|
||||
block.getNumStmt() = 0
|
||||
select ifstmt, "This 'if' statement is redundant."
|
||||
from MethodAccess ma
|
||||
where
|
||||
ma.getMethod().hasName("equals") and
|
||||
ma.getArgument(0).(StringLiteral).getValue() = ""
|
||||
select ma, "This comparison to empty string is inefficient, use isEmpty() instead."
|
||||
|
||||
Note that CodeQL treats Java and Kotlin as part of the same language, so even though this query starts with ``import java``, it will work for both Java and Kotlin code.
|
||||
|
||||
LGTM checks whether your query compiles and, if all is well, the **Run** button changes to green to indicate that you can go ahead and run the query.
|
||||
|
||||
@@ -57,9 +75,9 @@ Running the query
|
||||
|
||||
Your query is always run against the most recently analyzed commit to the selected project.
|
||||
|
||||
The query will take a few moments to return results. When the query completes, the results are displayed below the project name. The query results are listed in two columns, corresponding to the two expressions in the ``select`` clause of the query. The first column corresponds to the expression ``ifstmt`` and is linked to the location in the source code of the project where ``ifstmt`` occurs. The second column is the alert message.
|
||||
The query will take a few moments to return results. When the query completes, the results are displayed below the project name. The query results are listed in two columns, corresponding to the two expressions in the ``select`` clause of the query. The first column corresponds to the expression ``ma`` and is linked to the location in the source code of the project where ``ma`` occurs. The second column is the alert message.
|
||||
|
||||
➤ `Example query results <https://lgtm.com/query/3235645104630320782/>`__
|
||||
➤ `Example query results <https://lgtm.com/query/6863787472564633674/>`__
|
||||
|
||||
.. pull-quote::
|
||||
|
||||
@@ -67,34 +85,33 @@ Running the query
|
||||
|
||||
An ellipsis (…) at the bottom of the table indicates that the entire list is not displayed—click it to show more results.
|
||||
|
||||
#. If any matching code is found, click a link in the ``ifstmt`` column to view the ``if`` statement in the code viewer.
|
||||
#. If any matching code is found, click a link in the ``ma`` column to view the ``.equals`` expression in the code viewer.
|
||||
|
||||
The matching ``if`` statement is highlighted with a yellow background in the code viewer. If any code in the file also matches a query from the standard query library for that language, you will see a red alert message at the appropriate point within the code.
|
||||
The matching ``.equals`` expression is highlighted with a yellow background in the code viewer. If any code in the file also matches a query from the standard query library for that language, you will see a red alert message at the appropriate point within the code.
|
||||
|
||||
About the query structure
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
After the initial ``import`` statement, this simple query comprises three parts that serve similar purposes to the FROM, WHERE, and SELECT parts of an SQL query.
|
||||
|
||||
+---------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+
|
||||
| Query part | Purpose | Details |
|
||||
+===============================================================+===================================================================================================================+========================================================================================================================+
|
||||
| ``import java`` | Imports the standard CodeQL libraries for Java. | Every query begins with one or more ``import`` statements. |
|
||||
+---------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+
|
||||
| ``from IfStmt ifstmt, Block block`` | Defines the variables for the query. | We use: |
|
||||
| | Declarations are of the form: | |
|
||||
| | ``<type> <variable name>`` | - an ``IfStmt`` variable for ``if`` statements |
|
||||
| | | - a ``Block`` variable for the then block |
|
||||
+---------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+
|
||||
| ``where ifstmt.getThen() = block and block.getNumStmt() = 0`` | Defines a condition on the variables. | ``ifstmt.getThen() = block`` relates the two variables. The block must be the ``then`` branch of the ``if`` statement. |
|
||||
| | | |
|
||||
| | | ``block.getNumStmt() = 0`` states that the block must be empty (that is, it contains no statements). |
|
||||
+---------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+
|
||||
| ``select ifstmt, "This 'if' statement is redundant."`` | Defines what to report for each match. | Reports the resulting ``if`` statement with a string that explains the problem. |
|
||||
| | | |
|
||||
| | ``select`` statements for queries that are used to find instances of poor coding practice are always in the form: | |
|
||||
| | ``select <program element>, "<alert message>"`` | |
|
||||
+---------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+
|
||||
+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+
|
||||
| Query part | Purpose | Details |
|
||||
+==================================================================================================+===================================================================================================================+===================================================================================================+
|
||||
| ``import java`` | Imports the standard CodeQL libraries for Java and Kotlin. | Every query begins with one or more ``import`` statements. |
|
||||
+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+
|
||||
| ``from MethodAccess ma`` | Defines the variables for the query. | We use: |
|
||||
| | Declarations are of the form: | |
|
||||
| | ``<type> <variable name>`` | - a ``MethodAccess`` variable for call expressions |
|
||||
+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+
|
||||
| ``where ma.getMethod().hasName("equals") and ma.getArgument(0).(StringLiteral).getValue() = ""`` | Defines a condition on the variables. | ``ma.getMethod().hasName("equals")`` restricts ``ma`` to only calls to methods call ``equals``. |
|
||||
| | | |
|
||||
| | | ``ma.getArgument(0).(StringLiteral).getValue() = ""`` says the argument must be literal ``""``. |
|
||||
+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+
|
||||
| ``select ma, "This comparison to empty string is inefficient, use isEmpty() instead."`` | Defines what to report for each match. | Reports the resulting ``.equals`` expression with a string that explains the problem. |
|
||||
| | | |
|
||||
| | ``select`` statements for queries that are used to find instances of poor coding practice are always in the form: | |
|
||||
| | ``select <program element>, "<alert message>"`` | |
|
||||
+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+
|
||||
|
||||
Extend the query
|
||||
----------------
|
||||
@@ -104,41 +121,38 @@ Query writing is an inherently iterative process. You write a simple query and t
|
||||
Remove false positive results
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Browsing the results of our basic query shows that it could be improved. Among the results you are likely to find examples of ``if`` statements with an ``else`` branch, where an empty ``then`` branch does serve a purpose. For example:
|
||||
Browsing the results of our basic query shows that it could be improved. For example, you may find results for code like:
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
if (...) {
|
||||
...
|
||||
} else if ("-verbose".equals(option)) {
|
||||
// nothing to do - handled earlier
|
||||
} else {
|
||||
error("unrecognized option");
|
||||
}
|
||||
public class TestJava {
|
||||
void myJavaFun(Object o) {
|
||||
boolean b = o.equals("");
|
||||
}
|
||||
}
|
||||
|
||||
In this case, identifying the ``if`` statement with the empty ``then`` branch as redundant is a false positive. One solution to this is to modify the query to ignore empty ``then`` branches if the ``if`` statement has an ``else`` branch.
|
||||
|
||||
To exclude ``if`` statements that have an ``else`` branch:
|
||||
In this case, it is not possible to simply use ``o.isEmpty()`` instead, as ``o`` has type ``Object`` rather than ``String``. One solution to this is to modify the query to only return results where the expression being tested has type ``String``:
|
||||
|
||||
#. Extend the where clause to include the following extra condition:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
and not exists(ifstmt.getElse())
|
||||
ma.getQualifier().getType() instanceof TypeString
|
||||
|
||||
The ``where`` clause is now:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
where ifstmt.getThen() = block and
|
||||
block.getNumStmt() = 0 and
|
||||
not exists(ifstmt.getElse())
|
||||
where
|
||||
ma.getQualifier().getType() instanceof TypeString and
|
||||
ma.getMethod().hasName("equals") and
|
||||
ma.getArgument(0).(StringLiteral).getValue() = ""
|
||||
|
||||
#. Click **Run**.
|
||||
|
||||
There are now fewer results because ``if`` statements with an ``else`` branch are no longer included.
|
||||
There are now fewer results because ``.equals`` expressions with different types are no longer included.
|
||||
|
||||
➤ `See this in the query console <https://lgtm.com/query/6382189874776576029/>`__
|
||||
➤ `See this in the query console <https://lgtm.com/query/3716567543394265485/>`__
|
||||
|
||||
Further reading
|
||||
---------------
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
.. _codeql-for-java:
|
||||
|
||||
CodeQL for Java
|
||||
===============
|
||||
CodeQL for Java and Kotlin
|
||||
==========================
|
||||
|
||||
Experiment and learn how to write effective and efficient queries for CodeQL databases generated from Java codebases.
|
||||
Experiment and learn how to write effective and efficient queries for CodeQL databases generated from Java and Kotlin codebases.
|
||||
|
||||
.. include:: ../reusables/kotlin-beta-note.rst
|
||||
|
||||
|
||||
.. pull-quote:: Enabling Kotlin support
|
||||
|
||||
CodeQL treats Java and Kotlin as parts of the same language, so to enable Kotlin support you should enable ``java`` as a language.
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
@@ -11,6 +11,8 @@ Supported platforms
|
||||
#######################
|
||||
|
||||
.. include:: ../support/reusables/platforms.rst
|
||||
|
||||
.. include:: ../reusables/kotlin-beta-note.rst
|
||||
|
||||
Additional software requirements
|
||||
################################
|
||||
|
||||
@@ -3,6 +3,8 @@ CodeQL CWE coverage
|
||||
|
||||
You can view the full coverage of MITRE's Common Weakness Enumeration (CWE) or coverage by language for the latest release of CodeQL.
|
||||
|
||||
.. include:: ../reusables/kotlin-beta-note.rst
|
||||
|
||||
About CWEs
|
||||
##########
|
||||
|
||||
|
||||
@@ -6,11 +6,13 @@ View the query help for the queries included in the ``code-scanning``, ``securit
|
||||
- :doc:`CodeQL query help for C and C++ <cpp>`
|
||||
- :doc:`CodeQL query help for C# <csharp>`
|
||||
- :doc:`CodeQL query help for Go <go>`
|
||||
- :doc:`CodeQL query help for Java <java>`
|
||||
- :doc:`CodeQL query help for Java and Kotlin <java>`
|
||||
- :doc:`CodeQL query help for JavaScript <javascript>`
|
||||
- :doc:`CodeQL query help for Python <python>`
|
||||
- :doc:`CodeQL query help for Ruby <ruby>`
|
||||
|
||||
.. include:: ../reusables/kotlin-beta-note.rst
|
||||
|
||||
.. pull-quote:: Information
|
||||
|
||||
Each query help article includes:
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
- ``csharp``
|
||||
* - Go
|
||||
- ``go``
|
||||
* - Java
|
||||
* - Java/Kotlin
|
||||
- ``java``
|
||||
* - JavaScript/TypeScript
|
||||
- ``javascript``
|
||||
|
||||
4
docs/codeql/reusables/kotlin-beta-note.rst
Normal file
4
docs/codeql/reusables/kotlin-beta-note.rst
Normal file
@@ -0,0 +1,4 @@
|
||||
.. pull-quote:: Note
|
||||
|
||||
CodeQL analysis for Kotlin is currently in beta. During the beta, analysis of Kotlin code,
|
||||
and the accompanying documentation, will not be as comprehensive as for other languages.
|
||||
20
docs/codeql/reusables/kotlin-java-differences.rst
Normal file
20
docs/codeql/reusables/kotlin-java-differences.rst
Normal file
@@ -0,0 +1,20 @@
|
||||
Writing CodeQL queries for Kotlin versus Java analysis
|
||||
------------------------------------------------------
|
||||
|
||||
Generally you use the same classes to write queries for Kotlin and for Java. You use the same libraries such as DataFlow, TaintTracking, or SSA, and the same classes such as ``MethodAccess`` or ``Class`` for both languages. When you want to access Kotlin-specific elements (such as a ``WhenExpr``) you’ll need to use Kotlin-specific CodeQL classes.
|
||||
|
||||
There are however some important cases where writing queries for Kotlin can produce surprising results compared to writing queries for Java, as CodeQL works with the JVM bytecode representation of the Kotlin source code.
|
||||
|
||||
Be careful when you model code elements that don’t exist in Java, such as ``NotNullExpr (expr!!)``, because they could interact in unexpected ways with common predicates. For example, ``MethodAccess.getQualifier()`` returns a ``NotNullExpr`` instead of a ``VarAccess`` in the following Kotlin code:
|
||||
|
||||
.. code-block:: kotlin
|
||||
|
||||
someVar!!.someMethodCall()
|
||||
|
||||
In that specific case, you can use the predicate ``Expr.getUnderlyingExpr()``. This goes directly to the underlying ``VarAccess`` to produce a more similar behavior to that in Java.
|
||||
|
||||
Nullable elements (``?``) can also produce unexpected behavior. To avoid a ``NullPointerException``, Kotlin may inline calls like ``expr.toString()`` to ``String.valueOf(expr)`` when ``expr`` is nullable. Make sure that you write CodeQL around the extracted code, which may not exactly match the code as written in the codebase.
|
||||
|
||||
Another example is that if-else expressions in Kotlin are translated into ``WhenExprs`` in CodeQL, instead of the more typical ``IfStmt`` seen in Java.
|
||||
|
||||
In general, you can debug these issues with the AST (you can use the ``CodeQL: View AST`` command from Visual Studio Code’s CodeQL extension, or run the ``PrintAst.ql`` query) and see exactly what CodeQL is extracting from your code.
|
||||
@@ -93,9 +93,11 @@ and the CodeQL library pack ``codeql/go-all`` (`changelog <https://github.com/gi
|
||||
`yaml <https://gopkg.in/yaml.v3>`_, Serialization
|
||||
`zap <https://go.uber.org/zap>`_, Logging library
|
||||
|
||||
Java built-in support
|
||||
Java and Kotlin built-in support
|
||||
==================================
|
||||
|
||||
.. include:: ../reusables/kotlin-beta-note.rst
|
||||
|
||||
Provided by the current versions of the
|
||||
CodeQL query pack ``codeql/java-queries`` (`changelog <https://github.com/github/codeql/tree/codeql-cli/latest/java/ql/src/CHANGELOG.md>`__, `source <https://github.com/github/codeql/tree/codeql-cli/latest/java/ql/src>`__)
|
||||
and the CodeQL library pack ``codeql/java-all`` (`changelog <https://github.com/github/codeql/tree/codeql-cli/latest/java/ql/lib/CHANGELOG.md>`__, `source <https://github.com/github/codeql/tree/codeql-cli/latest/java/ql/lib>`__).
|
||||
|
||||
@@ -128,7 +128,7 @@ private class SafeUrlSink extends SafeUrlFlow::Sink {
|
||||
private class UnsafeFieldReadSanitizer extends SafeUrlFlow::SanitizerEdge {
|
||||
UnsafeFieldReadSanitizer() {
|
||||
exists(DataFlow::FieldReadNode frn, string name |
|
||||
name = ["User", "RawQuery", "Fragment", "User"] and
|
||||
name = ["User", "RawQuery", "Fragment"] and
|
||||
frn.getField().hasQualifiedName("net/url", "URL")
|
||||
|
|
||||
this = frn.getBase()
|
||||
|
||||
@@ -147,18 +147,17 @@ def get_gradle_lib_folder():
|
||||
return gradle_home + '/lib'
|
||||
|
||||
|
||||
def find_jar(path, pattern):
|
||||
result = glob.glob(path + '/' + pattern + '*.jar')
|
||||
if len(result) == 0:
|
||||
raise Exception('Cannot find jar file %s under path %s' %
|
||||
(pattern, path))
|
||||
return result
|
||||
def find_jar(path, base):
|
||||
fn = path + '/' + base + '.jar'
|
||||
if not os.path.isfile(fn):
|
||||
raise Exception('Cannot find jar file at %s' % fn)
|
||||
return fn
|
||||
|
||||
|
||||
def patterns_to_classpath(path, patterns):
|
||||
def bases_to_classpath(path, bases):
|
||||
result = []
|
||||
for pattern in patterns:
|
||||
result += find_jar(path, pattern)
|
||||
for base in bases:
|
||||
result.append(find_jar(path, base))
|
||||
return os.path.pathsep.join(result)
|
||||
|
||||
|
||||
@@ -174,8 +173,8 @@ def transform_to_embeddable(srcs):
|
||||
|
||||
|
||||
def compile(jars, java_jars, dependency_folder, transform_to_embeddable, output, build_dir, current_version):
|
||||
classpath = patterns_to_classpath(dependency_folder, jars)
|
||||
java_classpath = patterns_to_classpath(dependency_folder, java_jars)
|
||||
classpath = bases_to_classpath(dependency_folder, jars)
|
||||
java_classpath = bases_to_classpath(dependency_folder, java_jars)
|
||||
|
||||
tmp_src_dir = build_dir + '/temp_src'
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ class LinesOfCode(
|
||||
val tw: FileTrapWriter,
|
||||
val file: IrFile
|
||||
) {
|
||||
val psi2Ir = getPsi2Ir(logger).also {
|
||||
val psi2Ir = getPsi2Ir().also {
|
||||
if (it == null) {
|
||||
logger.warn("Lines of code will not be populated as Kotlin version is too old (${KotlinCompilerVersion.getVersion()})")
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class CommentExtractor(private val fileExtractor: KotlinFileExtractor, private v
|
||||
private val logger = fileExtractor.logger
|
||||
|
||||
fun extract() {
|
||||
val psi2Ir = getPsi2Ir(logger)
|
||||
val psi2Ir = getPsi2Ir()
|
||||
if (psi2Ir == null) {
|
||||
logger.warn("Comments will not be extracted as Kotlin version is too old (${KotlinCompilerVersion.getVersion()})")
|
||||
return
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
package com.github.codeql.utils.versions
|
||||
|
||||
import com.github.codeql.FileLogger
|
||||
|
||||
fun getPsi2Ir(@Suppress("UNUSED_PARAMETER") logger: FileLogger): Psi2IrFacade? = null
|
||||
fun getPsi2Ir(): Psi2IrFacade? = null
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.github.codeql.utils.versions
|
||||
|
||||
import com.github.codeql.FileLogger
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.backend.common.psi.PsiSourceManager
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.getKtFile
|
||||
@@ -8,9 +7,9 @@ import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
fun getPsi2Ir(logger: FileLogger): Psi2IrFacade? = Psi2Ir(logger)
|
||||
fun getPsi2Ir(): Psi2IrFacade? = Psi2Ir()
|
||||
|
||||
private class Psi2Ir(private val logger: FileLogger): Psi2IrFacade {
|
||||
private class Psi2Ir(): Psi2IrFacade {
|
||||
override fun getKtFile(irFile: IrFile): KtFile? {
|
||||
return irFile.getKtFile()
|
||||
}
|
||||
|
||||
@@ -250,7 +250,6 @@ private class ContainerFlowSummaries extends SummaryModelCsv {
|
||||
"java.util;Scanner;true;Scanner;;;Argument[0];Argument[-1];taint;manual",
|
||||
"java.util;Scanner;true;findInLine;;;Argument[-1];ReturnValue;taint;manual",
|
||||
"java.util;Scanner;true;findWithinHorizon;;;Argument[-1];ReturnValue;taint;manual",
|
||||
"java.util;Scanner;true;findWithinHorizon;;;Argument[-1];ReturnValue;taint;manual",
|
||||
"java.util;Scanner;true;next;;;Argument[-1];ReturnValue;taint;manual",
|
||||
"java.util;Scanner;true;nextBigDecimal;;;Argument[-1];ReturnValue;taint;manual",
|
||||
"java.util;Scanner;true;nextBigInteger;;;Argument[-1];ReturnValue;taint;manual",
|
||||
|
||||
@@ -99,10 +99,12 @@ private module Dispatch {
|
||||
private predicate lowConfidenceDispatchType(SrcRefType t) {
|
||||
t instanceof TypeObject
|
||||
or
|
||||
t instanceof FunctionalInterface
|
||||
t instanceof Interface and not t.fromSource()
|
||||
or
|
||||
t.hasQualifiedName("java.io", "Serializable")
|
||||
or
|
||||
t.hasQualifiedName("java.lang", "Iterable")
|
||||
or
|
||||
t.hasQualifiedName("java.lang", "Cloneable")
|
||||
or
|
||||
t.getPackage().hasName("java.util") and t instanceof Interface
|
||||
|
||||
@@ -53,9 +53,11 @@ class MockitoInitedTest extends Class {
|
||||
MockitoInitedTest() {
|
||||
// Tests run with the Mockito runner.
|
||||
exists(RunWithAnnotation a | a = this.getAnAncestor().getAnAnnotation() |
|
||||
a.getRunner().(RefType).hasQualifiedName("org.mockito.junit", "MockitoJUnitRunner")
|
||||
or
|
||||
// Deprecated styles.
|
||||
a.getRunner().(RefType).hasQualifiedName("org.mockito.runners", "MockitoJUnitRunner")
|
||||
or
|
||||
// Deprecated style.
|
||||
a.getRunner().(RefType).hasQualifiedName("org.mockito.runners", "MockitoJUnit44Runner")
|
||||
)
|
||||
or
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* Definitions related to `java.util.Properties`. */
|
||||
/** Definitions related to `java.util.Properties`. */
|
||||
|
||||
import semmle.code.java.Type
|
||||
private import semmle.code.java.dataflow.FlowSteps
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* Remote Method Invocation. */
|
||||
/** Remote Method Invocation. */
|
||||
|
||||
import java
|
||||
|
||||
/** The interface `java.rmi.Remote`. */
|
||||
|
||||
@@ -56,7 +56,6 @@ private class SummaryModels extends SummaryModelCsv {
|
||||
"android.content;ContentValues;false;putAll;;;Argument[0].MapValue;Argument[-1].MapValue;value;manual",
|
||||
"android.content;ContentResolver;true;acquireContentProviderClient;;;Argument[0];ReturnValue;taint;manual",
|
||||
"android.content;ContentResolver;true;acquireUnstableContentProviderClient;;;Argument[0];ReturnValue;taint;manual",
|
||||
"android.content;ContentResolver;true;acquireUnstableContentProviderClient;;;Argument[0];ReturnValue;taint;manual",
|
||||
"android.content;ContentResolver;true;applyBatch;;;Argument[1];ReturnValue;taint;manual",
|
||||
"android.content;ContentResolver;true;call;;;Argument[0];ReturnValue;taint;manual",
|
||||
"android.content;ContentResolver;true;canonicalize;;;Argument[0];ReturnValue;taint;manual",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* Definitions related to the Apache Commons Exec library. */
|
||||
/** Definitions related to the Apache Commons Exec library. */
|
||||
|
||||
import semmle.code.java.Type
|
||||
import semmle.code.java.security.ExternalProcess
|
||||
|
||||
|
||||
@@ -503,7 +503,6 @@ private class GuavaCollectCsv extends SummaryModelCsv {
|
||||
"com.google.common.collect;Sets;false;filter;(SortedSet,Predicate);;Argument[0].Element;ReturnValue.Element;value;manual",
|
||||
"com.google.common.collect;Sets;false;intersection;(Set,Set);;Argument[0..1].Element;ReturnValue.Element;value;manual",
|
||||
"com.google.common.collect;Sets;false;newConcurrentHashSet;(Iterable);;Argument[0].Element;ReturnValue.Element;value;manual",
|
||||
"com.google.common.collect;Sets;false;newConcurrentHashSet;(Iterable);;Argument[0].Element;ReturnValue.Element;value;manual",
|
||||
"com.google.common.collect;Sets;false;newCopyOnWriteArraySet;(Iterable);;Argument[0].Element;ReturnValue.Element;value;manual",
|
||||
"com.google.common.collect;Sets;false;newHashSet;(Iterable);;Argument[0].Element;ReturnValue.Element;value;manual",
|
||||
"com.google.common.collect;Sets;false;newHashSet;(Iterator);;Argument[0].Element;ReturnValue.Element;value;manual",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user