Merge branch 'main' into redsun82/swift-integration-test-pack

This commit is contained in:
Paolo Tranquilli
2022-11-25 08:49:36 +01:00
committed by GitHub
258 changed files with 8185 additions and 2380 deletions

View File

@@ -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
View 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"

View File

@@ -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
View File

@@ -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

View File

@@ -1,3 +1,5 @@
{
"omnisharp.autoStart": false
"omnisharp.autoStart": false,
"cmake.sourceDirectory": "${workspaceFolder}/swift",
"cmake.buildDirectory": "${workspaceFolder}/bazel-cmake-build"
}

View File

@@ -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

View File

@@ -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:

View File

@@ -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;

View File

@@ -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()
{

View File

@@ -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);
}

View File

@@ -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.

View File

@@ -1,4 +1,4 @@
/*
/**
* Common functions for implementing naming conventions
*
* Naming rules are the following:

5
csharp/.gitignore vendored
View File

@@ -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

View 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

View File

@@ -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));

View File

@@ -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()
{

View File

@@ -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)).

View File

@@ -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");

View File

@@ -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)
{

View File

@@ -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;
}
}

View File

@@ -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>();
});

View File

@@ -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");

View File

@@ -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;

View File

@@ -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");

View File

@@ -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;
});

View File

@@ -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) ?? "";

View File

@@ -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();
}

View File

@@ -1,4 +1,4 @@
/*
/**
* Provides reusable predicates related to Solorigate
*/

View File

@@ -1,4 +1,4 @@
/*
/**
* Predicates that help detect potential non-cryptographic hash functions
*
* By themselves, non-cryptographic functions are common and not dangerous

View File

@@ -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

View File

@@ -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())

View File

@@ -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.
*

View File

@@ -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

View File

@@ -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

View File

@@ -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(_) }

View File

@@ -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()
}
}

View File

@@ -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
/**

View File

@@ -3,7 +3,6 @@
*/
import csharp
private import semmle.code.csharp.dataflow.ExternalFlow
/** Definitions relating to the `Json.NET` package. */
module JsonNET {

View File

@@ -6,7 +6,6 @@
*/
import csharp
private import semmle.code.csharp.dataflow.ExternalFlow
/** A class representing a Service */
private class ServiceClass extends Class {

View File

@@ -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 {

View File

@@ -2,7 +2,6 @@
import csharp
private import system.Reflection
private import semmle.code.csharp.dataflow.ExternalFlow
/** The `System` namespace. */
class SystemNamespace extends Namespace {

View File

@@ -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 {

View File

@@ -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. */

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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. */

View File

@@ -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. */

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 { }

View File

@@ -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"
]
}

View File

@@ -6,7 +6,6 @@
* @tags model-generator
*/
import semmle.code.csharp.dataflow.ExternalFlow
import utils.modelgenerator.internal.CaptureTypeBasedSummaryModels
from TypeBasedFlowTargetApi api, string flow

View File

@@ -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

View File

@@ -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) |

View File

@@ -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) { }
}

View File

@@ -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 + ");"
// )
// }
//

View 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/

View File

@@ -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

View File

@@ -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.

View File

@@ -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
-----------------

View File

@@ -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
------------------

View File

@@ -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
---------------

View File

@@ -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:

View File

@@ -11,6 +11,8 @@ Supported platforms
#######################
.. include:: ../support/reusables/platforms.rst
.. include:: ../reusables/kotlin-beta-note.rst
Additional software requirements
################################

View File

@@ -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
##########

View File

@@ -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:

View File

@@ -10,7 +10,7 @@
- ``csharp``
* - Go
- ``go``
* - Java
* - Java/Kotlin
- ``java``
* - JavaScript/TypeScript
- ``javascript``

View 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.

View 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``) youll 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 dont 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 Codes CodeQL extension, or run the ``PrintAst.ql`` query) and see exactly what CodeQL is extracting from your code.

View File

@@ -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>`__).

View File

@@ -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()

View File

@@ -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'

View File

@@ -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()})")
}

View File

@@ -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

View File

@@ -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

View File

@@ -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()
}

View File

@@ -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",

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,4 +1,5 @@
/* Remote Method Invocation. */
/** Remote Method Invocation. */
import java
/** The interface `java.rmi.Remote`. */

View File

@@ -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",

View File

@@ -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

View File

@@ -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