Merge branch 'main' into rc/3.7

This commit is contained in:
Andrew Eisenberg
2022-09-20 08:33:58 -07:00
2309 changed files with 133758 additions and 43219 deletions

View File

@@ -413,7 +413,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.RunProcess["cmd.exe /C dotnet --info"] = 0;
actions.RunProcess[@"cmd.exe /C dotnet clean C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C dotnet restore C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C dotnet build --no-incremental /p:UseSharedCompilation=false C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C dotnet build --no-incremental C:\Project\test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project\test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -440,7 +440,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.RunProcess["dotnet --info"] = 0;
actions.RunProcess[@"dotnet clean C:\Project/test.csproj"] = 0;
actions.RunProcess[@"dotnet restore C:\Project/test.csproj"] = 0;
actions.RunProcess[@"dotnet build --no-incremental /p:UseSharedCompilation=false C:\Project/test.csproj"] = 0;
actions.RunProcess[@"dotnet build --no-incremental C:\Project/test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project/test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -715,9 +715,9 @@ namespace Semmle.Autobuild.CSharp.Tests
public void TestWindowCSharpMsBuild()
{
actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\test1.sln -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\test2.sln -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.sln /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"] = false;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"] = false;
@@ -746,9 +746,9 @@ namespace Semmle.Autobuild.CSharp.Tests
public void TestWindowCSharpMsBuildMultipleSolutions()
{
actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test1.csproj -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.csproj /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.csproj /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test2.csproj -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.csproj /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.csproj /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project\test1.csproj"] = true;
actions.FileExists[@"C:\Project\test2.csproj"] = true;
@@ -791,7 +791,7 @@ namespace Semmle.Autobuild.CSharp.Tests
public void TestWindowCSharpMsBuildFailed()
{
actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test1.sln -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 1;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 1;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"] = false;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"] = false;
@@ -817,8 +817,8 @@ namespace Semmle.Autobuild.CSharp.Tests
[Fact]
public void TestSkipNugetMsBuild()
{
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.sln /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"] = false;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"] = false;
@@ -862,7 +862,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.RunProcess["dotnet --info"] = 0;
actions.RunProcess[@"dotnet clean C:\Project/test.csproj"] = 0;
actions.RunProcess[@"dotnet restore C:\Project/test.csproj"] = 0;
actions.RunProcess[@"dotnet build --no-incremental /p:UseSharedCompilation=false --no-restore C:\Project/test.csproj"] = 0;
actions.RunProcess[@"dotnet build --no-incremental --no-restore C:\Project/test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project/test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -894,7 +894,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.RunProcess[@"C:\Project/.dotnet/dotnet --info"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet clean C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet restore C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet build --no-incremental /p:UseSharedCompilation=false C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet build --no-incremental C:\Project/test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists["test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -929,7 +929,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.RunProcess[@"C:\Project/.dotnet/dotnet --info"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet clean C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet restore C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet build --no-incremental /p:UseSharedCompilation=false C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet build --no-incremental C:\Project/test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists["test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -960,7 +960,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet --info"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet clean C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet restore C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet build --no-incremental /p:UseSharedCompilation=false C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet build --no-incremental C:\Project\test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project\test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -1008,7 +1008,7 @@ namespace Semmle.Autobuild.CSharp.Tests
{
actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\dirs.proj -DisableParallelProcessing"] = 1;
actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\dirs.proj -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\dirs.proj /p:UseSharedCompilation=false /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /p:MvcBuildViews=true /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\dirs.proj /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project\a\test.csproj"] = true;
actions.FileExists[@"C:\Project\dirs.proj"] = true;
@@ -1052,7 +1052,7 @@ namespace Semmle.Autobuild.CSharp.Tests
{
actions.RunProcess[@"nuget restore C:\Project/dirs.proj -DisableParallelProcessing"] = 1;
actions.RunProcess[@"mono C:\Project/.nuget/nuget.exe restore C:\Project/dirs.proj -DisableParallelProcessing"] = 0;
actions.RunProcess[@"msbuild C:\Project/dirs.proj /p:UseSharedCompilation=false /t:rebuild /p:MvcBuildViews=true"] = 0;
actions.RunProcess[@"msbuild C:\Project/dirs.proj /t:rebuild"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project/a/test.csproj"] = true;
actions.FileExists[@"C:\Project/dirs.proj"] = true;

View File

@@ -5,7 +5,6 @@ using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.IO;
using Semmle.Util;
using System.Text.RegularExpressions;
using Semmle.Autobuild.Shared;
namespace Semmle.Autobuild.CSharp
@@ -81,9 +80,6 @@ namespace Semmle.Autobuild.CSharp
env = null;
}
if (env is null)
env = new Dictionary<string, string>();
env.Add("UseSharedCompilation", "false");
return f(installDir, env);
});
}
@@ -245,8 +241,7 @@ namespace Semmle.Autobuild.CSharp
Argument("--no-incremental");
return
script.Argument("/p:UseSharedCompilation=false").
Argument(builder.Options.DotNetArguments).
script.Argument(builder.Options.DotNetArguments).
QuoteArgument(projOrSln).
Script;
}

View File

@@ -98,8 +98,6 @@ namespace Semmle.Autobuild.Shared
command.RunCommand(msBuild);
command.QuoteArgument(projectOrSolution.FullPath);
command.Argument("/p:UseSharedCompilation=false");
var target = builder.Options.MsBuildTarget ?? "rebuild";
var platform = builder.Options.MsBuildPlatform ?? (projectOrSolution is ISolution s1 ? s1.DefaultPlatformName : null);
var configuration = builder.Options.MsBuildConfiguration ?? (projectOrSolution is ISolution s2 ? s2.DefaultConfigurationName : null);
@@ -109,7 +107,6 @@ namespace Semmle.Autobuild.Shared
command.Argument(string.Format("/p:Platform=\"{0}\"", platform));
if (configuration is not null)
command.Argument(string.Format("/p:Configuration=\"{0}\"", configuration));
command.Argument("/p:MvcBuildViews=true");
command.Argument(builder.Options.MsBuildArguments);

View File

@@ -35,3 +35,10 @@ options:
the code (for example if it uses inaccessible dependencies).
type: string
pattern: "^(false|true)$"
cil:
title: Whether to enable CIL extraction.
description: >
A value indicating, whether CIL extraction should be enabled.
The default is 'true'.
type: string
pattern: "^(false|true)$"

View File

@@ -9,7 +9,7 @@ Microsoft.Extensions.Caching.Memory,,,46,,,,,,,,,,,,45,1
Microsoft.Extensions.Configuration,,,83,,,,,,,,,,,,80,3
Microsoft.Extensions.DependencyInjection,,,62,,,,,,,,,,,,62,
Microsoft.Extensions.DependencyModel,,,12,,,,,,,,,,,,12,
Microsoft.Extensions.FileProviders,,,15,,,,,,,,,,,,15,
Microsoft.Extensions.FileProviders,,,16,,,,,,,,,,,,16,
Microsoft.Extensions.FileSystemGlobbing,,,15,,,,,,,,,,,,13,2
Microsoft.Extensions.Hosting,,,17,,,,,,,,,,,,16,1
Microsoft.Extensions.Http,,,10,,,,,,,,,,,,10,
@@ -19,10 +19,10 @@ Microsoft.Extensions.Primitives,,,63,,,,,,,,,,,,63,
Microsoft.Interop,,,27,,,,,,,,,,,,27,
Microsoft.NET.Build.Tasks,,,1,,,,,,,,,,,,1,
Microsoft.NETCore.Platforms.BuildTasks,,,4,,,,,,,,,,,,4,
Microsoft.VisualBasic,,,9,,,,,,,,,,,,5,4
Microsoft.VisualBasic,,,10,,,,,,,,,,,,5,5
Microsoft.Win32,,,8,,,,,,,,,,,,8,
MySql.Data.MySqlClient,48,,,,,,,,,,48,,,,,
Newtonsoft.Json,,,91,,,,,,,,,,,,73,18
ServiceStack,194,,7,27,,,,,,75,92,,,,7,
System,43,4,11809,,1,1,1,,4,,33,3,1,3,9867,1942
System,65,4,12131,,8,8,9,,4,,33,3,1,3,10139,1992
Windows.Security.Cryptography.Core,1,,,,,,,1,,,,,,,,
1 package sink source summary sink:code sink:encryption-decryptor sink:encryption-encryptor sink:encryption-keyprop sink:encryption-symmetrickey sink:html sink:remote sink:sql sink:xss source:file source:local summary:taint summary:value
9 Microsoft.Extensions.Configuration 83 80 3
10 Microsoft.Extensions.DependencyInjection 62 62
11 Microsoft.Extensions.DependencyModel 12 12
12 Microsoft.Extensions.FileProviders 15 16 15 16
13 Microsoft.Extensions.FileSystemGlobbing 15 13 2
14 Microsoft.Extensions.Hosting 17 16 1
15 Microsoft.Extensions.Http 10 10
19 Microsoft.Interop 27 27
20 Microsoft.NET.Build.Tasks 1 1
21 Microsoft.NETCore.Platforms.BuildTasks 4 4
22 Microsoft.VisualBasic 9 10 5 4 5
23 Microsoft.Win32 8 8
24 MySql.Data.MySqlClient 48 48
25 Newtonsoft.Json 91 73 18
26 ServiceStack 194 7 27 75 92 7
27 System 43 65 4 11809 12131 1 8 1 8 1 9 4 33 3 1 3 9867 10139 1942 1992
28 Windows.Security.Cryptography.Core 1 1

View File

@@ -8,7 +8,7 @@ C# framework & library support
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE-079` :sub:`Cross-site scripting`
`ServiceStack <https://servicestack.net/>`_,"``ServiceStack.*``, ``ServiceStack``",,7,194,
System,"``System.*``, ``System``",4,11809,43,7
Others,"``Dapper``, ``JsonToItemsTaskFactory``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.NETCore.Platforms.BuildTasks``, ``Microsoft.VisualBasic``, ``Microsoft.Win32``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``Windows.Security.Cryptography.Core``",,554,138,
Totals,,4,12370,375,7
System,"``System.*``, ``System``",4,12131,65,7
Others,"``Dapper``, ``JsonToItemsTaskFactory``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.NETCore.Platforms.BuildTasks``, ``Microsoft.VisualBasic``, ``Microsoft.Win32``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``Windows.Security.Cryptography.Core``",,556,138,
Totals,,4,12694,397,7

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Introduce '--cil' flag in the comments. This does not make any changes to the dbscheme.
compatibility: full

View File

@@ -13,31 +13,6 @@ namespace Semmle.Extraction.CSharp
{
Extractor.SetInvariantCulture();
Console.WriteLine($"Semmle.Extraction.CSharp.Driver: called with {string.Join(", ", args)}");
if (args.Length > 0 && args[0] == "--dotnetexec")
{
var compilerRegEx = new Regex(@"csc\.exe|mcs\.exe|csc\.dll", RegexOptions.Compiled);
var cil = args.Length > 1 && args[1] == "--cil";
for (var i = cil ? 2 : 1; i < args.Length; i++)
{
if (compilerRegEx.IsMatch(args[i]))
{
var argsList = new List<string>();
if (cil)
argsList.Add("--cil");
argsList.Add("--compiler");
argsList.Add(args[i]);
if (i + 1 < args.Length)
argsList.AddRange(args[(i + 1)..]);
return (int)Extractor.Run(argsList.ToArray());
}
}
Console.WriteLine($"Semmle.Extraction.CSharp.Driver: not a compiler invocation");
return 0;
}
return (int)Extractor.Run(args);
}
}

View File

@@ -56,7 +56,6 @@ namespace Semmle.Extraction.CSharp.Standalone
CSharp.Extractor.SetInvariantCulture();
var options = Options.Create(args);
// options.CIL = true; // To do: Enable this
if (options.Help)
{

View File

@@ -22,7 +22,7 @@ namespace Semmle.Extraction.Tests
{
options = CSharp.Options.CreateWithEnvironment(Array.Empty<string>());
Assert.True(options.Cache);
Assert.False(options.CIL);
Assert.True(options.CIL);
Assert.Null(options.Framework);
Assert.Null(options.CompilerName);
Assert.Empty(options.CompilerArguments);
@@ -51,10 +51,20 @@ namespace Semmle.Extraction.Tests
[Fact]
public void CIL()
{
options = CSharp.Options.CreateWithEnvironment(new string[] { "--cil" });
options = CSharp.Options.CreateWithEnvironment(Array.Empty<string>());
Assert.True(options.CIL);
options = CSharp.Options.CreateWithEnvironment(new string[] { "--cil", "--nocil" });
Environment.SetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_OPTION_CIL", "false");
options = CSharp.Options.CreateWithEnvironment(Array.Empty<string>());
Assert.False(options.CIL);
Environment.SetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_OPTION_CIL", "true");
options = CSharp.Options.CreateWithEnvironment(Array.Empty<string>());
Assert.True(options.CIL);
Environment.SetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_OPTION_CIL", null);
options = CSharp.Options.CreateWithEnvironment(Array.Empty<string>());
Assert.True(options.CIL);
}
[Fact]
@@ -121,22 +131,6 @@ namespace Semmle.Extraction.Tests
Assert.Equal("foo", options.Framework);
}
[Fact]
public void EnvironmentVariables()
{
Environment.SetEnvironmentVariable("LGTM_INDEX_EXTRACTOR", "--cil c");
options = CSharp.Options.CreateWithEnvironment(new string[] { "a", "b" });
Assert.True(options.CIL);
Assert.Equal("a", options.CompilerArguments[0]);
Assert.Equal("b", options.CompilerArguments[1]);
Assert.Equal("c", options.CompilerArguments[2]);
Environment.SetEnvironmentVariable("LGTM_INDEX_EXTRACTOR", "");
Environment.SetEnvironmentVariable("LGTM_INDEX_EXTRACTOR", "--nocil");
options = CSharp.Options.CreateWithEnvironment(new string[] { "--cil" });
Assert.False(options.CIL);
}
[Fact]
public void StandaloneDefaults()
{

View File

@@ -28,7 +28,7 @@ namespace Semmle.Extraction
/// <summary>
/// Holds if CIL should be extracted.
/// </summary>
public bool CIL { get; private set; } = false;
public bool CIL { get; private set; } = true;
/// <summary>
/// Holds if assemblies shouldn't be extracted twice.
@@ -50,7 +50,6 @@ namespace Semmle.Extraction
/// </summary>
public bool QlTest { get; private set; } = false;
/// <summary>
/// The compression algorithm used for trap files.
/// </summary>
@@ -73,6 +72,9 @@ namespace Semmle.Extraction
return true;
}
return false;
case "cil":
CIL = Boolean.Parse(value);
return true;
default:
return false;
}
@@ -97,9 +99,6 @@ namespace Semmle.Extraction
case "cache":
Cache = value;
return true;
case "cil":
CIL = value;
return true;
case "pdb":
PDB = value;
CIL = true;

View File

@@ -17,7 +17,7 @@ namespace Semmle.Util
bool HandleOption(string key, string value);
/// <summary>
/// Handle a flag of the form "--cil" or "--nocil"
/// Handle a flag of the form "--cache" or "--nocache"
/// </summary>
/// <param name="key">The name of the flag. This is case sensitive.</param>
/// <param name="value">True if set, or false if prefixed by "--no"</param>
@@ -40,6 +40,7 @@ namespace Semmle.Util
public static class OptionsExtensions
{
private static readonly string[] ExtractorOptions = new[] { "trap_compression", "cil" };
private static string? GetExtractorOption(string name) =>
Environment.GetEnvironmentVariable($"CODEQL_EXTRACTOR_CSHARP_OPTION_{name.ToUpper()}");
@@ -47,12 +48,14 @@ namespace Semmle.Util
{
var extractorOptions = new List<string>();
var trapCompression = GetExtractorOption("trap_compression");
if (!string.IsNullOrEmpty(trapCompression))
foreach (var option in ExtractorOptions)
{
extractorOptions.Add($"--trap_compression:{trapCompression}");
var value = GetExtractorOption(option);
if (!string.IsNullOrEmpty(value))
{
extractorOptions.Add($"--{option}:{value}");
}
}
return extractorOptions;
}

View File

@@ -15,7 +15,7 @@ import experimental.code.csharp.Cryptography.NonCryptographicHashes
from Variable v, Literal l, LoopStmt loop, Expr additional_xor
where
maybeUsedInFNVFunction(v, _, _, loop) and
maybeUsedInFnvFunction(v, _, _, loop) and
(
exists(BitwiseXorExpr xor2 | xor2.getAnOperand() = l and additional_xor = xor2 |
loop.getAControlFlowExitNode().getASuccessor*() = xor2.getAControlFlowNode() and

View File

@@ -1,8 +1,8 @@
import csharp
import semmle.code.csharp.dataflow.internal.SsaImplCommon::Consistency
import semmle.code.csharp.dataflow.internal.SsaImpl::Consistency as Consistency
import Ssa
class MyRelevantDefinition extends RelevantDefinition, Ssa::Definition {
class MyRelevantDefinition extends Consistency::RelevantDefinition, Ssa::Definition {
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
@@ -10,6 +10,14 @@ class MyRelevantDefinition extends RelevantDefinition, Ssa::Definition {
}
}
query predicate nonUniqueDef = Consistency::nonUniqueDef/4;
query predicate readWithoutDef = Consistency::readWithoutDef/3;
query predicate deadDef = Consistency::deadDef/2;
query predicate notDominatedByDef = Consistency::notDominatedByDef/4;
query predicate localDeclWithSsaDef(LocalVariableDeclExpr d) {
// Local variables in C# must be initialized before every use, so uninitialized
// local variables should not have an SSA definition, as that would imply that

View File

@@ -0,0 +1 @@
Console.WriteLine(args[0]);

View File

@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,3 @@
from create_database_utils import *
run_codeql_database_create(['dotnet build'], test_db="default-db", db=None, lang="csharp")

View File

@@ -0,0 +1,2 @@
libraryPathDependencies:
- codeql-csharp

View File

@@ -0,0 +1,4 @@
---
category: fix
---
* Fixed an issue in the taint tracking analysis where implicit reads were not allowed by default in sinks or additional taint steps that used flow states.

View File

@@ -0,0 +1,5 @@
---
category: deprecated
---
* Some classes/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
The old name still exists as a deprecated alias.

View File

@@ -13,7 +13,7 @@ private import semmle.code.csharp.dataflow.TaintTracking2
predicate maybeANonCryptogrphicHash(Callable callable, Variable v, Expr xor, Expr mul, LoopStmt loop) {
callable = loop.getEnclosingCallable() and
(
maybeUsedInFNVFunction(v, xor, mul, loop) or
maybeUsedInFnvFunction(v, xor, mul, loop) or
maybeUsedInElfHashFunction(v, xor, mul, loop)
)
}
@@ -23,7 +23,7 @@ predicate maybeANonCryptogrphicHash(Callable callable, Variable v, Expr xor, Exp
* where there is a loop statement `loop` where the variable `v` is used in an xor `xor` expression
* followed by a multiplication `mul` expression.
*/
predicate maybeUsedInFNVFunction(Variable v, Operation xor, Operation mul, LoopStmt loop) {
predicate maybeUsedInFnvFunction(Variable v, Operation xor, Operation mul, LoopStmt loop) {
exists(Expr e1, Expr e2 |
e1.getAChild*() = v.getAnAccess() and
e2.getAChild*() = v.getAnAccess() and
@@ -37,6 +37,9 @@ predicate maybeUsedInFNVFunction(Variable v, Operation xor, Operation mul, LoopS
loop.getAChild*() = xor.getEnclosingStmt()
}
/** DEPRECATED: Alias for maybeUsedInFnvFunction */
deprecated predicate maybeUsedInFNVFunction = maybeUsedInFnvFunction/4;
/**
* Holds if the arguments are used in a way that resembles an Elf-Hash hash function
* where there is a loop statement `loop` where the variable `v` is used in an xor `xor` expression

View File

@@ -5,3 +5,5 @@ dbscheme: semmlecode.csharp.dbscheme
extractor: csharp
library: true
upgrades: upgrades
dependencies:
codeql/ssa: 0.0.1

View File

@@ -56,7 +56,7 @@ private predicate alwaysNotNullVariableUpdate(VariableUpdate vu) {
/** Holds if expression `expr` always evaluates to non-null. */
private predicate alwaysNotNullExpr(Expr expr) {
expr instanceof Opcodes::Newobj
expr instanceof Opcodes::NewObj
or
expr instanceof Literal and not expr instanceof NullLiteral
or

View File

@@ -766,7 +766,7 @@ module Opcodes {
}
/** A `newobj` instruction. */
class Newobj extends Call, @cil_newobj {
class NewObj extends Call, @cil_newobj {
override string getOpcodeName() { result = "newobj" }
override int getPushCount() { result = 1 }
@@ -788,6 +788,9 @@ module Opcodes {
}
}
/** DEPRECATED: Alias for NewObj */
deprecated class Newobj = NewObj;
/** An `initobj` instruction. */
class Initobj extends Instruction, @cil_initobj {
override string getOpcodeName() { result = "initobj" }
@@ -847,10 +850,13 @@ module Opcodes {
}
/** A `rethrow` instruction. */
class Rethrow extends Throw, @cil_rethrow {
class ReThrow extends Throw, @cil_rethrow {
override string getOpcodeName() { result = "rethrow" }
}
/** DEPRECATED: Alias for ReThrow */
deprecated class Rethrow = ReThrow;
/** A `ldlen` instruction. */
class Ldlen extends UnaryExpr, @cil_ldlen {
override string getOpcodeName() { result = "ldlen" }

View File

@@ -8,13 +8,12 @@ private import CIL
* Provides classes for working with static single assignment (SSA) form.
*/
module Ssa {
private import internal.SsaImplCommon as SsaImpl
private import internal.SsaImpl
private import internal.SsaImpl as SsaImpl
/** An SSA definition. */
class Definition extends SsaImpl::Definition {
/** Gets a read of this SSA definition. */
final ReadAccess getARead() { result = getARead(this) }
final ReadAccess getARead() { result = SsaImpl::getARead(this) }
/** Gets the underlying variable update, if any. */
final VariableUpdate getVariableUpdate() {
@@ -25,11 +24,11 @@ module Ssa {
}
/** Gets a first read of this SSA definition. */
final ReadAccess getAFirstRead() { result = getAFirstRead(this) }
final ReadAccess getAFirstRead() { result = SsaImpl::getAFirstRead(this) }
/** Holds if `first` and `second` are adjacent reads of this SSA definition. */
final predicate hasAdjacentReads(ReadAccess first, ReadAccess second) {
hasAdjacentReads(this, first, second)
SsaImpl::hasAdjacentReads(this, first, second)
}
private Definition getAPhiInput() { result = this.(PhiNode).getAnInput() }
@@ -52,7 +51,7 @@ module Ssa {
final override Location getLocation() { result = this.getBasicBlock().getLocation() }
/** Gets an input to this phi node. */
final Definition getAnInput() { result = getAPhiInput(this) }
final Definition getAnInput() { result = SsaImpl::getAPhiInput(this) }
/**
* Holds if if `def` is an input to this phi node, and a reference to `def` at
@@ -60,7 +59,7 @@ module Ssa {
* other references.
*/
final predicate hasLastInputRef(Definition def, BasicBlock bb, int i) {
hasLastInputRef(this, def, bb, i)
SsaImpl::hasLastInputRef(this, def, bb, i)
}
}
}

View File

@@ -1,8 +1,40 @@
private import semmle.code.cil.CIL
private import SsaImplCommon
private import cil
private import codeql.ssa.Ssa as SsaImplCommon
private module SsaInput implements SsaImplCommon::InputSig {
class BasicBlock = CIL::BasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock = CIL::ExitBasicBlock;
class SourceVariable = CIL::StackVariable;
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
forceCachingInSameStage() and
exists(CIL::VariableUpdate vu |
vu.updatesAt(bb, i) and
v = vu.getVariable() and
certain = true
)
}
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(CIL::ReadAccess ra | bb.getNode(i) = ra |
ra.getTarget() = v and
certain = true
)
}
}
import SsaImplCommon::Make<SsaInput>
cached
private module Cached {
private import CIL
cached
predicate forceCachingInSameStage() { any() }

View File

@@ -1,795 +0,0 @@
/**
* Provides a language-independent implementation of static single assignment
* (SSA) form.
*/
private import SsaImplSpecific
private BasicBlock getABasicBlockPredecessor(BasicBlock bb) { getABasicBlockSuccessor(result) = bb }
/**
* Liveness analysis (based on source variables) to restrict the size of the
* SSA representation.
*/
private module Liveness {
/**
* A classification of variable references into reads (of a given kind) and
* (certain or uncertain) writes.
*/
private newtype TRefKind =
Read(boolean certain) { certain in [false, true] } or
Write(boolean certain) { certain in [false, true] }
private class RefKind extends TRefKind {
string toString() {
exists(boolean certain | this = Read(certain) and result = "read (" + certain + ")")
or
exists(boolean certain | this = Write(certain) and result = "write (" + certain + ")")
}
int getOrder() {
this = Read(_) and
result = 0
or
this = Write(_) and
result = 1
}
}
/**
* Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`.
*/
predicate ref(BasicBlock bb, int i, SourceVariable v, RefKind k) {
exists(boolean certain | variableRead(bb, i, v, certain) | k = Read(certain))
or
exists(boolean certain | variableWrite(bb, i, v, certain) | k = Write(certain))
}
private newtype OrderedRefIndex =
MkOrderedRefIndex(int i, int tag) {
exists(RefKind rk | ref(_, i, _, rk) | tag = rk.getOrder())
}
private OrderedRefIndex refOrd(BasicBlock bb, int i, SourceVariable v, RefKind k, int ord) {
ref(bb, i, v, k) and
result = MkOrderedRefIndex(i, ord) and
ord = k.getOrder()
}
/**
* Gets the (1-based) rank of the reference to `v` at the `i`th node of
* basic block `bb`, which has the given reference kind `k`.
*
* Reads are considered before writes when they happen at the same index.
*/
private int refRank(BasicBlock bb, int i, SourceVariable v, RefKind k) {
refOrd(bb, i, v, k, _) =
rank[result](int j, int ord, OrderedRefIndex res |
res = refOrd(bb, j, v, _, ord)
|
res order by j, ord
)
}
private int maxRefRank(BasicBlock bb, SourceVariable v) {
result = refRank(bb, _, v, _) and
not result + 1 = refRank(bb, _, v, _)
}
predicate lastRefIsRead(BasicBlock bb, SourceVariable v) {
maxRefRank(bb, v) = refRank(bb, _, v, Read(_))
}
/**
* Gets the (1-based) rank of the first reference to `v` inside basic block `bb`
* that is either a read or a certain write.
*/
private int firstReadOrCertainWrite(BasicBlock bb, SourceVariable v) {
result =
min(int r, RefKind k |
r = refRank(bb, _, v, k) and
k != Write(false)
|
r
)
}
/**
* Holds if source variable `v` is live at the beginning of basic block `bb`.
*/
predicate liveAtEntry(BasicBlock bb, SourceVariable v) {
// The first read or certain write to `v` inside `bb` is a read
refRank(bb, _, v, Read(_)) = firstReadOrCertainWrite(bb, v)
or
// There is no certain write to `v` inside `bb`, but `v` is live at entry
// to a successor basic block of `bb`
not exists(firstReadOrCertainWrite(bb, v)) and
liveAtExit(bb, v)
}
/**
* Holds if source variable `v` is live at the end of basic block `bb`.
*/
predicate liveAtExit(BasicBlock bb, SourceVariable v) {
liveAtEntry(getABasicBlockSuccessor(bb), v)
}
/**
* Holds if variable `v` is live in basic block `bb` at index `i`.
* The rank of `i` is `rnk` as defined by `refRank()`.
*/
private predicate liveAtRank(BasicBlock bb, int i, SourceVariable v, int rnk) {
exists(RefKind kind | rnk = refRank(bb, i, v, kind) |
rnk = maxRefRank(bb, v) and
liveAtExit(bb, v)
or
ref(bb, i, v, kind) and
kind = Read(_)
or
exists(RefKind nextKind |
liveAtRank(bb, _, v, rnk + 1) and
rnk + 1 = refRank(bb, _, v, nextKind) and
nextKind != Write(true)
)
)
}
/**
* Holds if variable `v` is live after the (certain or uncertain) write at
* index `i` inside basic block `bb`.
*/
predicate liveAfterWrite(BasicBlock bb, int i, SourceVariable v) {
exists(int rnk | rnk = refRank(bb, i, v, Write(_)) | liveAtRank(bb, i, v, rnk))
}
}
private import Liveness
/**
* Holds if `df` is in the dominance frontier of `bb`.
*
* This is equivalent to:
*
* ```ql
* bb = getImmediateBasicBlockDominator*(getABasicBlockPredecessor(df)) and
* not bb = getImmediateBasicBlockDominator+(df)
* ```
*/
private predicate inDominanceFrontier(BasicBlock bb, BasicBlock df) {
bb = getABasicBlockPredecessor(df) and not bb = getImmediateBasicBlockDominator(df)
or
exists(BasicBlock prev | inDominanceFrontier(prev, df) |
bb = getImmediateBasicBlockDominator(prev) and
not bb = getImmediateBasicBlockDominator(df)
)
}
/**
* Holds if `bb` is in the dominance frontier of a block containing a
* definition of `v`.
*/
pragma[noinline]
private predicate inDefDominanceFrontier(BasicBlock bb, SourceVariable v) {
exists(BasicBlock defbb, Definition def |
def.definesAt(v, defbb, _) and
inDominanceFrontier(defbb, bb)
)
}
cached
newtype TDefinition =
TWriteDef(SourceVariable v, BasicBlock bb, int i) {
variableWrite(bb, i, v, _) and
liveAfterWrite(bb, i, v)
} or
TPhiNode(SourceVariable v, BasicBlock bb) {
inDefDominanceFrontier(bb, v) and
liveAtEntry(bb, v)
}
private module SsaDefReaches {
newtype TSsaRefKind =
SsaActualRead() or
SsaPhiRead() or
SsaDef()
class SsaRead = SsaActualRead or SsaPhiRead;
/**
* A classification of SSA variable references into reads and definitions.
*/
class SsaRefKind extends TSsaRefKind {
string toString() {
this = SsaActualRead() and
result = "SsaActualRead"
or
this = SsaPhiRead() and
result = "SsaPhiRead"
or
this = SsaDef() and
result = "SsaDef"
}
int getOrder() {
this instanceof SsaRead and
result = 0
or
this = SsaDef() and
result = 1
}
}
/**
* Holds if `bb` is in the dominance frontier of a block containing a
* read of `v`.
*/
pragma[nomagic]
private predicate inReadDominanceFrontier(BasicBlock bb, SourceVariable v) {
exists(BasicBlock readbb | inDominanceFrontier(readbb, bb) |
lastRefIsRead(readbb, v)
or
phiRead(readbb, v)
)
}
/**
* Holds if a phi-read node should be inserted for variable `v` at the beginning
* of basic block `bb`.
*
* Phi-read nodes are like normal phi nodes, but they are inserted based on reads
* instead of writes, and only if the dominance-frontier block does not already
* contain a reference (read or write) to `v`. Unlike normal phi nodes, this is
* an internal implementation detail that is not exposed.
*
* The motivation for adding phi-reads is to improve performance of the use-use
* calculation in cases where there is a large number of reads that can reach the
* same join-point, and from there reach a large number of basic blocks. Example:
*
* ```cs
* if (a)
* use(x);
* else if (b)
* use(x);
* else if (c)
* use(x);
* else if (d)
* use(x);
* // many more ifs ...
*
* // phi-read for `x` inserted here
*
* // program not mentioning `x`, with large basic block graph
*
* use(x);
* ```
*
* Without phi-reads, the analysis has to replicate reachability for each of
* the guarded uses of `x`. However, with phi-reads, the analysis will limit
* each conditional use of `x` to reach the basic block containing the phi-read
* node for `x`, and only that basic block will have to compute reachability
* through the remainder of the large program.
*
* Like normal reads, each phi-read node `phi-read` can be reached from exactly
* one SSA definition (without passing through another definition): Assume, for
* the sake of contradiction, that there are two reaching definitions `def1` and
* `def2`. Now, if both `def1` and `def2` dominate `phi-read`, then the nearest
* dominating definition will prevent the other from reaching `phi-read`. So, at
* least one of `def1` and `def2` cannot dominate `phi-read`; assume it is `def1`.
* Then `def1` must go through one of its dominance-frontier blocks in order to
* reach `phi-read`. However, such a block will always start with a (normal) phi
* node, which contradicts reachability.
*
* Also, like normal reads, the unique SSA definition `def` that reaches `phi-read`,
* will dominate `phi-read`. Assuming it doesn't means that the path from `def`
* to `phi-read` goes through a dominance-frontier block, and hence a phi node,
* which contradicts reachability.
*/
pragma[nomagic]
predicate phiRead(BasicBlock bb, SourceVariable v) {
inReadDominanceFrontier(bb, v) and
liveAtEntry(bb, v) and
// only if there are no other references to `v` inside `bb`
not ref(bb, _, v, _) and
not exists(Definition def | def.definesAt(v, bb, _))
}
/**
* Holds if the `i`th node of basic block `bb` is a reference to `v`,
* either a read (when `k` is `SsaRead()`) or an SSA definition (when `k`
* is `SsaDef()`).
*
* Unlike `Liveness::ref`, this includes `phi` nodes.
*/
pragma[nomagic]
predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
variableRead(bb, i, v, _) and
k = SsaActualRead()
or
phiRead(bb, v) and
i = -1 and
k = SsaPhiRead()
or
any(Definition def).definesAt(v, bb, i) and
k = SsaDef()
}
private newtype OrderedSsaRefIndex =
MkOrderedSsaRefIndex(int i, SsaRefKind k) { ssaRef(_, i, _, k) }
private OrderedSsaRefIndex ssaRefOrd(BasicBlock bb, int i, SourceVariable v, SsaRefKind k, int ord) {
ssaRef(bb, i, v, k) and
result = MkOrderedSsaRefIndex(i, k) and
ord = k.getOrder()
}
/**
* Gets the (1-based) rank of the reference to `v` at the `i`th node of basic
* block `bb`, which has the given reference kind `k`.
*
* For example, if `bb` is a basic block with a phi node for `v` (considered
* to be at index -1), reads `v` at node 2, and defines it at node 5, we have:
*
* ```ql
* ssaRefRank(bb, -1, v, SsaDef()) = 1 // phi node
* ssaRefRank(bb, 2, v, Read()) = 2 // read at node 2
* ssaRefRank(bb, 5, v, SsaDef()) = 3 // definition at node 5
* ```
*
* Reads are considered before writes when they happen at the same index.
*/
int ssaRefRank(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
ssaRefOrd(bb, i, v, k, _) =
rank[result](int j, int ord, OrderedSsaRefIndex res |
res = ssaRefOrd(bb, j, v, _, ord)
|
res order by j, ord
)
}
int maxSsaRefRank(BasicBlock bb, SourceVariable v) {
result = ssaRefRank(bb, _, v, _) and
not result + 1 = ssaRefRank(bb, _, v, _)
}
/**
* Holds if the SSA definition `def` reaches rank index `rnk` in its own
* basic block `bb`.
*/
predicate ssaDefReachesRank(BasicBlock bb, Definition def, int rnk, SourceVariable v) {
exists(int i |
rnk = ssaRefRank(bb, i, v, SsaDef()) and
def.definesAt(v, bb, i)
)
or
ssaDefReachesRank(bb, def, rnk - 1, v) and
rnk = ssaRefRank(bb, _, v, any(SsaRead k))
}
/**
* Holds if the SSA definition of `v` at `def` reaches index `i` in the same
* basic block `bb`, without crossing another SSA definition of `v`.
*/
predicate ssaDefReachesReadWithinBlock(SourceVariable v, Definition def, BasicBlock bb, int i) {
exists(int rnk |
ssaDefReachesRank(bb, def, rnk, v) and
rnk = ssaRefRank(bb, i, v, any(SsaRead k))
)
}
/**
* Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`.
*/
int ssaDefRank(Definition def, SourceVariable v, BasicBlock bb, int i, SsaRefKind k) {
v = def.getSourceVariable() and
result = ssaRefRank(bb, i, v, k) and
(
ssaDefReachesRead(_, def, bb, i)
or
def.definesAt(_, bb, i)
)
}
/**
* Holds if the reference to `def` at index `i` in basic block `bb` is the
* last reference to `v` inside `bb`.
*/
pragma[noinline]
predicate lastSsaRef(Definition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v)
}
predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v, SsaRefKind k) {
exists(ssaDefRank(def, v, bb, _, k))
}
pragma[noinline]
private predicate ssaDefReachesThroughBlock(Definition def, BasicBlock bb) {
ssaDefReachesEndOfBlock(bb, def, _) and
not defOccursInBlock(_, bb, def.getSourceVariable(), _)
}
/**
* Holds if `def` is accessed in basic block `bb1` (either a read or a write),
* `bb2` is a transitive successor of `bb1`, `def` is live at the end of _some_
* predecessor of `bb2`, and the underlying variable for `def` is neither read
* nor written in any block on the path between `bb1` and `bb2`.
*
* Phi reads are considered as normal reads for this predicate.
*/
pragma[nomagic]
private predicate varBlockReachesInclPhiRead(Definition def, BasicBlock bb1, BasicBlock bb2) {
defOccursInBlock(def, bb1, _, _) and
bb2 = getABasicBlockSuccessor(bb1)
or
exists(BasicBlock mid |
varBlockReachesInclPhiRead(def, bb1, mid) and
ssaDefReachesThroughBlock(def, mid) and
bb2 = getABasicBlockSuccessor(mid)
)
}
pragma[nomagic]
private predicate phiReadStep(Definition def, SourceVariable v, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesInclPhiRead(def, bb1, bb2) and
defOccursInBlock(def, bb2, v, SsaPhiRead())
}
pragma[nomagic]
private predicate varBlockReachesExclPhiRead(Definition def, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesInclPhiRead(pragma[only_bind_into](def), bb1, pragma[only_bind_into](bb2)) and
ssaRef(bb2, _, def.getSourceVariable(), [SsaActualRead().(TSsaRefKind), SsaDef()])
or
exists(BasicBlock mid |
varBlockReachesExclPhiRead(def, mid, bb2) and
phiReadStep(def, _, bb1, mid)
)
}
/**
* Holds if `def` is accessed in basic block `bb1` (either a read or a write),
* the underlying variable `v` of `def` is accessed in basic block `bb2`
* (either a read or a write), `bb2` is a transitive successor of `bb1`, and
* `v` is neither read nor written in any block on the path between `bb1`
* and `bb2`.
*/
pragma[nomagic]
predicate varBlockReaches(Definition def, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesExclPhiRead(def, bb1, bb2) and
not defOccursInBlock(def, bb1, _, SsaPhiRead())
}
pragma[nomagic]
predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) {
varBlockReaches(def, bb1, bb2) and
ssaRefRank(bb2, i2, def.getSourceVariable(), SsaActualRead()) = 1
}
/**
* Holds if `def` is accessed in basic block `bb` (either a read or a write),
* `bb1` can reach a transitive successor `bb2` where `def` is no longer live,
* and `v` is neither read nor written in any block on the path between `bb`
* and `bb2`.
*/
pragma[nomagic]
predicate varBlockReachesExit(Definition def, BasicBlock bb) {
exists(BasicBlock bb2 | varBlockReachesInclPhiRead(def, bb, bb2) |
not defOccursInBlock(def, bb2, _, _) and
not ssaDefReachesEndOfBlock(bb2, def, _)
)
or
exists(BasicBlock mid |
varBlockReachesExit(def, mid) and
phiReadStep(def, _, bb, mid)
)
}
}
predicate phiReadExposedForTesting = phiRead/2;
private import SsaDefReaches
pragma[nomagic]
predicate liveThrough(BasicBlock bb, SourceVariable v) {
liveAtExit(bb, v) and
not ssaRef(bb, _, v, SsaDef())
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the SSA definition of `v` at `def` reaches the end of basic
* block `bb`, at which point it is still live, without crossing another
* SSA definition of `v`.
*/
pragma[nomagic]
predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) {
exists(int last |
last = maxSsaRefRank(pragma[only_bind_into](bb), pragma[only_bind_into](v)) and
ssaDefReachesRank(bb, def, last, v) and
liveAtExit(bb, v)
)
or
// The construction of SSA form ensures that each read of a variable is
// dominated by its definition. An SSA definition therefore reaches a
// control flow node if it is the _closest_ SSA definition that dominates
// the node. If two definitions dominate a node then one must dominate the
// other, so therefore the definition of _closest_ is given by the dominator
// tree. Thus, reaching definitions can be calculated in terms of dominance.
ssaDefReachesEndOfBlock(getImmediateBasicBlockDominator(bb), def, pragma[only_bind_into](v)) and
liveThrough(bb, pragma[only_bind_into](v))
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `inp` is an input to the phi node `phi` along the edge originating in `bb`.
*/
pragma[nomagic]
predicate phiHasInputFromBlock(PhiNode phi, Definition inp, BasicBlock bb) {
exists(SourceVariable v, BasicBlock bbDef |
phi.definesAt(v, bbDef, _) and
getABasicBlockPredecessor(bbDef) = bb and
ssaDefReachesEndOfBlock(bb, inp, v)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the SSA definition of `v` at `def` reaches a read at index `i` in
* basic block `bb`, without crossing another SSA definition of `v`. The read
* is of kind `rk`.
*/
pragma[nomagic]
predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int i) {
ssaDefReachesReadWithinBlock(v, def, bb, i)
or
ssaRef(bb, i, v, any(SsaRead k)) and
ssaDefReachesEndOfBlock(getABasicBlockPredecessor(bb), def, v) and
not ssaDefReachesReadWithinBlock(v, _, bb, i)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `def` is accessed at index `i1` in basic block `bb1` (either a read
* or a write), `def` is read at index `i2` in basic block `bb2`, and there is a
* path between them without any read of `def`.
*/
pragma[nomagic]
predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
exists(int rnk |
rnk = ssaDefRank(def, _, bb1, i1, _) and
rnk + 1 = ssaDefRank(def, _, bb1, i2, SsaActualRead()) and
variableRead(bb1, i2, _, _) and
bb2 = bb1
)
or
lastSsaRef(def, _, bb1, i1) and
defAdjacentRead(def, bb1, bb2, i2)
}
pragma[noinline]
private predicate adjacentDefRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2, SourceVariable v
) {
adjacentDefRead(def, bb1, i1, bb2, i2) and
v = def.getSourceVariable()
}
private predicate adjacentDefReachesRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2
) {
exists(SourceVariable v | adjacentDefRead(def, bb1, i1, bb2, i2, v) |
ssaRef(bb1, i1, v, SsaDef())
or
variableRead(bb1, i1, v, true)
)
or
exists(BasicBlock bb3, int i3 |
adjacentDefReachesRead(def, bb1, i1, bb3, i3) and
variableRead(bb3, i3, _, false) and
adjacentDefRead(def, bb3, i3, bb2, i2)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `adjacentDefRead`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate adjacentDefNoUncertainReads(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
adjacentDefReachesRead(def, bb1, i1, bb2, i2) and
variableRead(bb2, i2, _, true)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the node at index `i` in `bb` is a last reference to SSA definition
* `def`. The reference is last because it can reach another write `next`,
* without passing through another read or write.
*/
pragma[nomagic]
predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) {
exists(SourceVariable v |
// Next reference to `v` inside `bb` is a write
exists(int rnk, int j |
rnk = ssaDefRank(def, v, bb, i, _) and
next.definesAt(v, bb, j) and
rnk + 1 = ssaRefRank(bb, j, v, SsaDef())
)
or
// Can reach a write using one or more steps
lastSsaRef(def, v, bb, i) and
exists(BasicBlock bb2 |
varBlockReaches(def, bb, bb2) and
1 = ssaDefRank(next, v, bb2, _, SsaDef())
)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `inp` is an immediately preceding definition of uncertain definition
* `def`. Since `def` is uncertain, the value from the preceding definition might
* still be valid.
*/
pragma[nomagic]
predicate uncertainWriteDefinitionInput(UncertainWriteDefinition def, Definition inp) {
lastRefRedef(inp, _, _, def)
}
private predicate adjacentDefReachesUncertainRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2
) {
adjacentDefReachesRead(def, bb1, i1, bb2, i2) and
variableRead(bb2, i2, _, false)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `lastRefRedef`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate lastRefRedefNoUncertainReads(Definition def, BasicBlock bb, int i, Definition next) {
lastRefRedef(def, bb, i, next) and
not variableRead(bb, i, def.getSourceVariable(), false)
or
exists(BasicBlock bb0, int i0 |
lastRefRedef(def, bb0, i0, next) and
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the node at index `i` in `bb` is a last reference to SSA
* definition `def`.
*
* That is, the node can reach the end of the enclosing callable, or another
* SSA definition for the underlying source variable, without passing through
* another read.
*/
pragma[nomagic]
predicate lastRef(Definition def, BasicBlock bb, int i) {
// Can reach another definition
lastRefRedef(def, bb, i, _)
or
exists(SourceVariable v | lastSsaRef(def, v, bb, i) |
// Can reach exit directly
bb instanceof ExitBasicBlock
or
// Can reach a block using one or more steps, where `def` is no longer live
varBlockReachesExit(def, bb)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `lastRefRedef`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate lastRefNoUncertainReads(Definition def, BasicBlock bb, int i) {
lastRef(def, bb, i) and
not variableRead(bb, i, def.getSourceVariable(), false)
or
exists(BasicBlock bb0, int i0 |
lastRef(def, bb0, i0) and
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
)
}
/** A static single assignment (SSA) definition. */
class Definition extends TDefinition {
/** Gets the source variable underlying this SSA definition. */
SourceVariable getSourceVariable() { this.definesAt(result, _, _) }
/**
* Holds if this SSA definition defines `v` at index `i` in basic block `bb`.
* Phi nodes are considered to be at index `-1`, while normal variable writes
* are at the index of the control flow node they wrap.
*/
final predicate definesAt(SourceVariable v, BasicBlock bb, int i) {
this = TWriteDef(v, bb, i)
or
this = TPhiNode(v, bb) and i = -1
}
/** Gets the basic block to which this SSA definition belongs. */
final BasicBlock getBasicBlock() { this.definesAt(_, result, _) }
/** Gets a textual representation of this SSA definition. */
string toString() { none() }
}
/** An SSA definition that corresponds to a write. */
class WriteDefinition extends Definition, TWriteDef {
private SourceVariable v;
private BasicBlock bb;
private int i;
WriteDefinition() { this = TWriteDef(v, bb, i) }
override string toString() { result = "WriteDef" }
}
/** A phi node. */
class PhiNode extends Definition, TPhiNode {
override string toString() { result = "Phi" }
}
/**
* An SSA definition that represents an uncertain update of the underlying
* source variable.
*/
class UncertainWriteDefinition extends WriteDefinition {
UncertainWriteDefinition() {
exists(SourceVariable v, BasicBlock bb, int i |
this.definesAt(v, bb, i) and
variableWrite(bb, i, v, false)
)
}
}
/** Provides a set of consistency queries. */
module Consistency {
abstract class RelevantDefinition extends Definition {
abstract predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
);
}
query predicate nonUniqueDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefReachesRead(v, def, bb, i) and
not exists(unique(Definition def0 | ssaDefReachesRead(v, def0, bb, i)))
}
query predicate readWithoutDef(SourceVariable v, BasicBlock bb, int i) {
variableRead(bb, i, v, _) and
not ssaDefReachesRead(v, _, bb, i)
}
query predicate deadDef(RelevantDefinition def, SourceVariable v) {
v = def.getSourceVariable() and
not ssaDefReachesRead(_, def, _, _) and
not phiHasInputFromBlock(_, def, _) and
not uncertainWriteDefinitionInput(_, def)
}
query predicate notDominatedByDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
exists(BasicBlock bbDef, int iDef | def.definesAt(v, bbDef, iDef) |
ssaDefReachesReadWithinBlock(v, def, bb, i) and
(bb != bbDef or i < iDef)
or
ssaDefReachesRead(v, def, bb, i) and
not ssaDefReachesReadWithinBlock(v, def, bb, i) and
not def.definesAt(v, getImmediateBasicBlockDominator*(bb), _)
)
}
}

View File

@@ -1,30 +0,0 @@
/** Provides the CIL specific parameters for `SsaImplCommon.qll`. */
private import cil
private import SsaImpl
class BasicBlock = CIL::BasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock = CIL::ExitBasicBlock;
class SourceVariable = CIL::StackVariable;
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
forceCachingInSameStage() and
exists(CIL::VariableUpdate vu |
vu.updatesAt(bb, i) and
v = vu.getVariable() and
certain = true
)
}
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(CIL::ReadAccess ra | bb.getNode(i) = ra |
ra.getTarget() = v and
certain = true
)
}

View File

@@ -192,8 +192,7 @@ class BasicBlock extends TBasicBlockStart {
* Gets the basic block that immediately dominates this basic block, if any.
*
* That is, all paths reaching this basic block from some entry point
* basic block must go through the result, which is an immediate basic block
* predecessor of this basic block.
* basic block must go through the result.
*
* Example:
*
@@ -207,8 +206,7 @@ class BasicBlock extends TBasicBlockStart {
*
* The basic block starting on line 2 is an immediate dominator of
* the basic block online 4 (all paths from the entry point of `M`
* to `return s.Length;` must go through the null check, and the null check
* is an immediate predecessor of `return s.Length;`).
* to `return s.Length;` must go through the null check.
*/
BasicBlock getImmediateDominator() { bbIDominates(result, this) }

View File

@@ -6,26 +6,158 @@ import csharp
* scope variables.
*/
module PreSsa {
import pressa.SsaImplSpecific
private import pressa.SsaImplCommon as SsaImpl
private import AssignableDefinitions
private import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl
private import semmle.code.csharp.controlflow.internal.PreBasicBlocks as PreBasicBlocks
private import codeql.ssa.Ssa as SsaImplCommon
private predicate definitionAt(
AssignableDefinition def, SsaInput::BasicBlock bb, int i, SsaInput::SourceVariable v
) {
bb.getElement(i) = def.getExpr() and
v = def.getTarget() and
// In cases like `(x, x) = (0, 1)`, we discard the first (dead) definition of `x`
not exists(TupleAssignmentDefinition first, TupleAssignmentDefinition second | first = def |
second.getAssignment() = first.getAssignment() and
second.getEvaluationOrder() > first.getEvaluationOrder() and
second.getTarget() = v
)
or
def.(ImplicitParameterDefinition).getParameter() = v and
exists(Callable c | v = c.getAParameter() |
scopeFirst(c, bb) and
i = -1
)
}
predicate implicitEntryDef(Callable c, SsaInput::BasicBlock bb, SsaInput::SourceVariable v) {
not v instanceof LocalScopeVariable and
c = v.getACallable() and
scopeFirst(c, bb)
}
module SsaInput implements SsaImplCommon::InputSig {
class BasicBlock = PreBasicBlocks::PreBasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock extends BasicBlock {
ExitBasicBlock() { scopeLast(_, this.getLastElement(), _) }
}
/** Holds if `a` is assigned in non-constructor callable `c`. */
pragma[nomagic]
private predicate assignableDefinition(Assignable a, Callable c) {
exists(AssignableDefinition def | def.getTarget() = a |
c = def.getEnclosingCallable() and
not c instanceof Constructor
)
}
/** Holds if `a` is accessed in callable `c`. */
pragma[nomagic]
private predicate assignableAccess(Assignable a, Callable c) {
exists(AssignableAccess aa | aa.getTarget() = a | c = aa.getEnclosingCallable())
}
pragma[nomagic]
private predicate assignableNoCapturing(Assignable a, Callable c) {
assignableAccess(a, c) and
/*
* The code below is equivalent to
* ```ql
* not exists(Callable other | assignableDefinition(a, other) | other != c)
* ```
* but it avoids a Cartesian product in the compiler generated antijoin
* predicate.
*/
(
not assignableDefinition(a, _)
or
c = unique(Callable c0 | assignableDefinition(a, c0) | c0)
)
}
pragma[noinline]
private predicate assignableNoComplexQualifiers(Assignable a) {
forall(QualifiableExpr qe | qe.(AssignableAccess).getTarget() = a | qe.targetIsThisInstance())
}
/**
* A simple assignable. Either a local scope variable or a field/property
* that behaves like a local scope variable.
*/
class SourceVariable extends Assignable {
private Callable c;
SourceVariable() {
(
this instanceof LocalScopeVariable
or
this = any(Field f | not f.isVolatile())
or
this = any(TrivialProperty tp | not tp.isOverridableOrImplementable())
) and
assignableNoCapturing(this, c) and
assignableNoComplexQualifiers(this)
}
/** Gets a callable in which this simple assignable can be analyzed. */
Callable getACallable() { result = c }
}
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignableDefinition def |
definitionAt(def, bb, i, v) and
if def.getTargetAccess().isRefArgument() then certain = false else certain = true
)
or
exists(Callable c |
implicitEntryDef(c, bb, v) and
i = -1 and
certain = true
)
}
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignableRead read |
read = bb.getElement(i) and
read.getTarget() = v and
certain = true
)
or
v =
any(LocalScopeVariable lsv |
lsv.getCallable() = bb.(ExitBasicBlock).getEnclosingCallable() and
i = bb.length() and
(lsv.isRef() or v.(Parameter).isOut()) and
certain = false
)
}
}
private module SsaImpl = SsaImplCommon::Make<SsaInput>;
class Definition extends SsaImpl::Definition {
final AssignableRead getARead() {
exists(BasicBlock bb, int i |
exists(SsaInput::BasicBlock bb, int i |
SsaImpl::ssaDefReachesRead(_, this, bb, i) and
result = bb.getElement(i)
)
}
final AssignableDefinition getDefinition() {
exists(BasicBlock bb, int i, SourceVariable v |
exists(SsaInput::BasicBlock bb, int i, SsaInput::SourceVariable v |
this.definesAt(v, bb, i) and
definitionAt(result, bb, i, v)
)
}
final AssignableRead getAFirstRead() {
exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
exists(SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2 |
this.definesAt(_, bb1, i1) and
SsaImpl::adjacentDefRead(this, bb1, i1, bb2, i2) and
result = bb2.getElement(i2)
@@ -42,14 +174,14 @@ module PreSsa {
not result instanceof PhiNode
}
final predicate isLiveAtEndOfBlock(BasicBlock bb) {
final predicate isLiveAtEndOfBlock(SsaInput::BasicBlock bb) {
SsaImpl::ssaDefReachesEndOfBlock(bb, this, _)
}
Location getLocation() {
result = this.getDefinition().getLocation()
or
exists(Callable c, BasicBlock bb, SourceVariable v |
exists(Callable c, SsaInput::BasicBlock bb, SsaInput::SourceVariable v |
this.definesAt(v, bb, -1) and
implicitEntryDef(c, bb, v) and
result = c.getLocation()
@@ -64,9 +196,9 @@ module PreSsa {
}
predicate adjacentReadPairSameVar(AssignableRead read1, AssignableRead read2) {
exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
exists(SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2 |
read1 = bb1.getElement(i1) and
variableRead(bb1, i1, _, true) and
SsaInput::variableRead(bb1, i1, _, true) and
SsaImpl::adjacentDefRead(_, bb1, i1, bb2, i2) and
read2 = bb2.getElement(i2)
)

View File

@@ -1,795 +0,0 @@
/**
* Provides a language-independent implementation of static single assignment
* (SSA) form.
*/
private import SsaImplSpecific
private BasicBlock getABasicBlockPredecessor(BasicBlock bb) { getABasicBlockSuccessor(result) = bb }
/**
* Liveness analysis (based on source variables) to restrict the size of the
* SSA representation.
*/
private module Liveness {
/**
* A classification of variable references into reads (of a given kind) and
* (certain or uncertain) writes.
*/
private newtype TRefKind =
Read(boolean certain) { certain in [false, true] } or
Write(boolean certain) { certain in [false, true] }
private class RefKind extends TRefKind {
string toString() {
exists(boolean certain | this = Read(certain) and result = "read (" + certain + ")")
or
exists(boolean certain | this = Write(certain) and result = "write (" + certain + ")")
}
int getOrder() {
this = Read(_) and
result = 0
or
this = Write(_) and
result = 1
}
}
/**
* Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`.
*/
predicate ref(BasicBlock bb, int i, SourceVariable v, RefKind k) {
exists(boolean certain | variableRead(bb, i, v, certain) | k = Read(certain))
or
exists(boolean certain | variableWrite(bb, i, v, certain) | k = Write(certain))
}
private newtype OrderedRefIndex =
MkOrderedRefIndex(int i, int tag) {
exists(RefKind rk | ref(_, i, _, rk) | tag = rk.getOrder())
}
private OrderedRefIndex refOrd(BasicBlock bb, int i, SourceVariable v, RefKind k, int ord) {
ref(bb, i, v, k) and
result = MkOrderedRefIndex(i, ord) and
ord = k.getOrder()
}
/**
* Gets the (1-based) rank of the reference to `v` at the `i`th node of
* basic block `bb`, which has the given reference kind `k`.
*
* Reads are considered before writes when they happen at the same index.
*/
private int refRank(BasicBlock bb, int i, SourceVariable v, RefKind k) {
refOrd(bb, i, v, k, _) =
rank[result](int j, int ord, OrderedRefIndex res |
res = refOrd(bb, j, v, _, ord)
|
res order by j, ord
)
}
private int maxRefRank(BasicBlock bb, SourceVariable v) {
result = refRank(bb, _, v, _) and
not result + 1 = refRank(bb, _, v, _)
}
predicate lastRefIsRead(BasicBlock bb, SourceVariable v) {
maxRefRank(bb, v) = refRank(bb, _, v, Read(_))
}
/**
* Gets the (1-based) rank of the first reference to `v` inside basic block `bb`
* that is either a read or a certain write.
*/
private int firstReadOrCertainWrite(BasicBlock bb, SourceVariable v) {
result =
min(int r, RefKind k |
r = refRank(bb, _, v, k) and
k != Write(false)
|
r
)
}
/**
* Holds if source variable `v` is live at the beginning of basic block `bb`.
*/
predicate liveAtEntry(BasicBlock bb, SourceVariable v) {
// The first read or certain write to `v` inside `bb` is a read
refRank(bb, _, v, Read(_)) = firstReadOrCertainWrite(bb, v)
or
// There is no certain write to `v` inside `bb`, but `v` is live at entry
// to a successor basic block of `bb`
not exists(firstReadOrCertainWrite(bb, v)) and
liveAtExit(bb, v)
}
/**
* Holds if source variable `v` is live at the end of basic block `bb`.
*/
predicate liveAtExit(BasicBlock bb, SourceVariable v) {
liveAtEntry(getABasicBlockSuccessor(bb), v)
}
/**
* Holds if variable `v` is live in basic block `bb` at index `i`.
* The rank of `i` is `rnk` as defined by `refRank()`.
*/
private predicate liveAtRank(BasicBlock bb, int i, SourceVariable v, int rnk) {
exists(RefKind kind | rnk = refRank(bb, i, v, kind) |
rnk = maxRefRank(bb, v) and
liveAtExit(bb, v)
or
ref(bb, i, v, kind) and
kind = Read(_)
or
exists(RefKind nextKind |
liveAtRank(bb, _, v, rnk + 1) and
rnk + 1 = refRank(bb, _, v, nextKind) and
nextKind != Write(true)
)
)
}
/**
* Holds if variable `v` is live after the (certain or uncertain) write at
* index `i` inside basic block `bb`.
*/
predicate liveAfterWrite(BasicBlock bb, int i, SourceVariable v) {
exists(int rnk | rnk = refRank(bb, i, v, Write(_)) | liveAtRank(bb, i, v, rnk))
}
}
private import Liveness
/**
* Holds if `df` is in the dominance frontier of `bb`.
*
* This is equivalent to:
*
* ```ql
* bb = getImmediateBasicBlockDominator*(getABasicBlockPredecessor(df)) and
* not bb = getImmediateBasicBlockDominator+(df)
* ```
*/
private predicate inDominanceFrontier(BasicBlock bb, BasicBlock df) {
bb = getABasicBlockPredecessor(df) and not bb = getImmediateBasicBlockDominator(df)
or
exists(BasicBlock prev | inDominanceFrontier(prev, df) |
bb = getImmediateBasicBlockDominator(prev) and
not bb = getImmediateBasicBlockDominator(df)
)
}
/**
* Holds if `bb` is in the dominance frontier of a block containing a
* definition of `v`.
*/
pragma[noinline]
private predicate inDefDominanceFrontier(BasicBlock bb, SourceVariable v) {
exists(BasicBlock defbb, Definition def |
def.definesAt(v, defbb, _) and
inDominanceFrontier(defbb, bb)
)
}
cached
newtype TDefinition =
TWriteDef(SourceVariable v, BasicBlock bb, int i) {
variableWrite(bb, i, v, _) and
liveAfterWrite(bb, i, v)
} or
TPhiNode(SourceVariable v, BasicBlock bb) {
inDefDominanceFrontier(bb, v) and
liveAtEntry(bb, v)
}
private module SsaDefReaches {
newtype TSsaRefKind =
SsaActualRead() or
SsaPhiRead() or
SsaDef()
class SsaRead = SsaActualRead or SsaPhiRead;
/**
* A classification of SSA variable references into reads and definitions.
*/
class SsaRefKind extends TSsaRefKind {
string toString() {
this = SsaActualRead() and
result = "SsaActualRead"
or
this = SsaPhiRead() and
result = "SsaPhiRead"
or
this = SsaDef() and
result = "SsaDef"
}
int getOrder() {
this instanceof SsaRead and
result = 0
or
this = SsaDef() and
result = 1
}
}
/**
* Holds if `bb` is in the dominance frontier of a block containing a
* read of `v`.
*/
pragma[nomagic]
private predicate inReadDominanceFrontier(BasicBlock bb, SourceVariable v) {
exists(BasicBlock readbb | inDominanceFrontier(readbb, bb) |
lastRefIsRead(readbb, v)
or
phiRead(readbb, v)
)
}
/**
* Holds if a phi-read node should be inserted for variable `v` at the beginning
* of basic block `bb`.
*
* Phi-read nodes are like normal phi nodes, but they are inserted based on reads
* instead of writes, and only if the dominance-frontier block does not already
* contain a reference (read or write) to `v`. Unlike normal phi nodes, this is
* an internal implementation detail that is not exposed.
*
* The motivation for adding phi-reads is to improve performance of the use-use
* calculation in cases where there is a large number of reads that can reach the
* same join-point, and from there reach a large number of basic blocks. Example:
*
* ```cs
* if (a)
* use(x);
* else if (b)
* use(x);
* else if (c)
* use(x);
* else if (d)
* use(x);
* // many more ifs ...
*
* // phi-read for `x` inserted here
*
* // program not mentioning `x`, with large basic block graph
*
* use(x);
* ```
*
* Without phi-reads, the analysis has to replicate reachability for each of
* the guarded uses of `x`. However, with phi-reads, the analysis will limit
* each conditional use of `x` to reach the basic block containing the phi-read
* node for `x`, and only that basic block will have to compute reachability
* through the remainder of the large program.
*
* Like normal reads, each phi-read node `phi-read` can be reached from exactly
* one SSA definition (without passing through another definition): Assume, for
* the sake of contradiction, that there are two reaching definitions `def1` and
* `def2`. Now, if both `def1` and `def2` dominate `phi-read`, then the nearest
* dominating definition will prevent the other from reaching `phi-read`. So, at
* least one of `def1` and `def2` cannot dominate `phi-read`; assume it is `def1`.
* Then `def1` must go through one of its dominance-frontier blocks in order to
* reach `phi-read`. However, such a block will always start with a (normal) phi
* node, which contradicts reachability.
*
* Also, like normal reads, the unique SSA definition `def` that reaches `phi-read`,
* will dominate `phi-read`. Assuming it doesn't means that the path from `def`
* to `phi-read` goes through a dominance-frontier block, and hence a phi node,
* which contradicts reachability.
*/
pragma[nomagic]
predicate phiRead(BasicBlock bb, SourceVariable v) {
inReadDominanceFrontier(bb, v) and
liveAtEntry(bb, v) and
// only if there are no other references to `v` inside `bb`
not ref(bb, _, v, _) and
not exists(Definition def | def.definesAt(v, bb, _))
}
/**
* Holds if the `i`th node of basic block `bb` is a reference to `v`,
* either a read (when `k` is `SsaRead()`) or an SSA definition (when `k`
* is `SsaDef()`).
*
* Unlike `Liveness::ref`, this includes `phi` nodes.
*/
pragma[nomagic]
predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
variableRead(bb, i, v, _) and
k = SsaActualRead()
or
phiRead(bb, v) and
i = -1 and
k = SsaPhiRead()
or
any(Definition def).definesAt(v, bb, i) and
k = SsaDef()
}
private newtype OrderedSsaRefIndex =
MkOrderedSsaRefIndex(int i, SsaRefKind k) { ssaRef(_, i, _, k) }
private OrderedSsaRefIndex ssaRefOrd(BasicBlock bb, int i, SourceVariable v, SsaRefKind k, int ord) {
ssaRef(bb, i, v, k) and
result = MkOrderedSsaRefIndex(i, k) and
ord = k.getOrder()
}
/**
* Gets the (1-based) rank of the reference to `v` at the `i`th node of basic
* block `bb`, which has the given reference kind `k`.
*
* For example, if `bb` is a basic block with a phi node for `v` (considered
* to be at index -1), reads `v` at node 2, and defines it at node 5, we have:
*
* ```ql
* ssaRefRank(bb, -1, v, SsaDef()) = 1 // phi node
* ssaRefRank(bb, 2, v, Read()) = 2 // read at node 2
* ssaRefRank(bb, 5, v, SsaDef()) = 3 // definition at node 5
* ```
*
* Reads are considered before writes when they happen at the same index.
*/
int ssaRefRank(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
ssaRefOrd(bb, i, v, k, _) =
rank[result](int j, int ord, OrderedSsaRefIndex res |
res = ssaRefOrd(bb, j, v, _, ord)
|
res order by j, ord
)
}
int maxSsaRefRank(BasicBlock bb, SourceVariable v) {
result = ssaRefRank(bb, _, v, _) and
not result + 1 = ssaRefRank(bb, _, v, _)
}
/**
* Holds if the SSA definition `def` reaches rank index `rnk` in its own
* basic block `bb`.
*/
predicate ssaDefReachesRank(BasicBlock bb, Definition def, int rnk, SourceVariable v) {
exists(int i |
rnk = ssaRefRank(bb, i, v, SsaDef()) and
def.definesAt(v, bb, i)
)
or
ssaDefReachesRank(bb, def, rnk - 1, v) and
rnk = ssaRefRank(bb, _, v, any(SsaRead k))
}
/**
* Holds if the SSA definition of `v` at `def` reaches index `i` in the same
* basic block `bb`, without crossing another SSA definition of `v`.
*/
predicate ssaDefReachesReadWithinBlock(SourceVariable v, Definition def, BasicBlock bb, int i) {
exists(int rnk |
ssaDefReachesRank(bb, def, rnk, v) and
rnk = ssaRefRank(bb, i, v, any(SsaRead k))
)
}
/**
* Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`.
*/
int ssaDefRank(Definition def, SourceVariable v, BasicBlock bb, int i, SsaRefKind k) {
v = def.getSourceVariable() and
result = ssaRefRank(bb, i, v, k) and
(
ssaDefReachesRead(_, def, bb, i)
or
def.definesAt(_, bb, i)
)
}
/**
* Holds if the reference to `def` at index `i` in basic block `bb` is the
* last reference to `v` inside `bb`.
*/
pragma[noinline]
predicate lastSsaRef(Definition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v)
}
predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v, SsaRefKind k) {
exists(ssaDefRank(def, v, bb, _, k))
}
pragma[noinline]
private predicate ssaDefReachesThroughBlock(Definition def, BasicBlock bb) {
ssaDefReachesEndOfBlock(bb, def, _) and
not defOccursInBlock(_, bb, def.getSourceVariable(), _)
}
/**
* Holds if `def` is accessed in basic block `bb1` (either a read or a write),
* `bb2` is a transitive successor of `bb1`, `def` is live at the end of _some_
* predecessor of `bb2`, and the underlying variable for `def` is neither read
* nor written in any block on the path between `bb1` and `bb2`.
*
* Phi reads are considered as normal reads for this predicate.
*/
pragma[nomagic]
private predicate varBlockReachesInclPhiRead(Definition def, BasicBlock bb1, BasicBlock bb2) {
defOccursInBlock(def, bb1, _, _) and
bb2 = getABasicBlockSuccessor(bb1)
or
exists(BasicBlock mid |
varBlockReachesInclPhiRead(def, bb1, mid) and
ssaDefReachesThroughBlock(def, mid) and
bb2 = getABasicBlockSuccessor(mid)
)
}
pragma[nomagic]
private predicate phiReadStep(Definition def, SourceVariable v, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesInclPhiRead(def, bb1, bb2) and
defOccursInBlock(def, bb2, v, SsaPhiRead())
}
pragma[nomagic]
private predicate varBlockReachesExclPhiRead(Definition def, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesInclPhiRead(pragma[only_bind_into](def), bb1, pragma[only_bind_into](bb2)) and
ssaRef(bb2, _, def.getSourceVariable(), [SsaActualRead().(TSsaRefKind), SsaDef()])
or
exists(BasicBlock mid |
varBlockReachesExclPhiRead(def, mid, bb2) and
phiReadStep(def, _, bb1, mid)
)
}
/**
* Holds if `def` is accessed in basic block `bb1` (either a read or a write),
* the underlying variable `v` of `def` is accessed in basic block `bb2`
* (either a read or a write), `bb2` is a transitive successor of `bb1`, and
* `v` is neither read nor written in any block on the path between `bb1`
* and `bb2`.
*/
pragma[nomagic]
predicate varBlockReaches(Definition def, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesExclPhiRead(def, bb1, bb2) and
not defOccursInBlock(def, bb1, _, SsaPhiRead())
}
pragma[nomagic]
predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) {
varBlockReaches(def, bb1, bb2) and
ssaRefRank(bb2, i2, def.getSourceVariable(), SsaActualRead()) = 1
}
/**
* Holds if `def` is accessed in basic block `bb` (either a read or a write),
* `bb1` can reach a transitive successor `bb2` where `def` is no longer live,
* and `v` is neither read nor written in any block on the path between `bb`
* and `bb2`.
*/
pragma[nomagic]
predicate varBlockReachesExit(Definition def, BasicBlock bb) {
exists(BasicBlock bb2 | varBlockReachesInclPhiRead(def, bb, bb2) |
not defOccursInBlock(def, bb2, _, _) and
not ssaDefReachesEndOfBlock(bb2, def, _)
)
or
exists(BasicBlock mid |
varBlockReachesExit(def, mid) and
phiReadStep(def, _, bb, mid)
)
}
}
predicate phiReadExposedForTesting = phiRead/2;
private import SsaDefReaches
pragma[nomagic]
predicate liveThrough(BasicBlock bb, SourceVariable v) {
liveAtExit(bb, v) and
not ssaRef(bb, _, v, SsaDef())
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the SSA definition of `v` at `def` reaches the end of basic
* block `bb`, at which point it is still live, without crossing another
* SSA definition of `v`.
*/
pragma[nomagic]
predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) {
exists(int last |
last = maxSsaRefRank(pragma[only_bind_into](bb), pragma[only_bind_into](v)) and
ssaDefReachesRank(bb, def, last, v) and
liveAtExit(bb, v)
)
or
// The construction of SSA form ensures that each read of a variable is
// dominated by its definition. An SSA definition therefore reaches a
// control flow node if it is the _closest_ SSA definition that dominates
// the node. If two definitions dominate a node then one must dominate the
// other, so therefore the definition of _closest_ is given by the dominator
// tree. Thus, reaching definitions can be calculated in terms of dominance.
ssaDefReachesEndOfBlock(getImmediateBasicBlockDominator(bb), def, pragma[only_bind_into](v)) and
liveThrough(bb, pragma[only_bind_into](v))
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `inp` is an input to the phi node `phi` along the edge originating in `bb`.
*/
pragma[nomagic]
predicate phiHasInputFromBlock(PhiNode phi, Definition inp, BasicBlock bb) {
exists(SourceVariable v, BasicBlock bbDef |
phi.definesAt(v, bbDef, _) and
getABasicBlockPredecessor(bbDef) = bb and
ssaDefReachesEndOfBlock(bb, inp, v)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the SSA definition of `v` at `def` reaches a read at index `i` in
* basic block `bb`, without crossing another SSA definition of `v`. The read
* is of kind `rk`.
*/
pragma[nomagic]
predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int i) {
ssaDefReachesReadWithinBlock(v, def, bb, i)
or
ssaRef(bb, i, v, any(SsaRead k)) and
ssaDefReachesEndOfBlock(getABasicBlockPredecessor(bb), def, v) and
not ssaDefReachesReadWithinBlock(v, _, bb, i)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `def` is accessed at index `i1` in basic block `bb1` (either a read
* or a write), `def` is read at index `i2` in basic block `bb2`, and there is a
* path between them without any read of `def`.
*/
pragma[nomagic]
predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
exists(int rnk |
rnk = ssaDefRank(def, _, bb1, i1, _) and
rnk + 1 = ssaDefRank(def, _, bb1, i2, SsaActualRead()) and
variableRead(bb1, i2, _, _) and
bb2 = bb1
)
or
lastSsaRef(def, _, bb1, i1) and
defAdjacentRead(def, bb1, bb2, i2)
}
pragma[noinline]
private predicate adjacentDefRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2, SourceVariable v
) {
adjacentDefRead(def, bb1, i1, bb2, i2) and
v = def.getSourceVariable()
}
private predicate adjacentDefReachesRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2
) {
exists(SourceVariable v | adjacentDefRead(def, bb1, i1, bb2, i2, v) |
ssaRef(bb1, i1, v, SsaDef())
or
variableRead(bb1, i1, v, true)
)
or
exists(BasicBlock bb3, int i3 |
adjacentDefReachesRead(def, bb1, i1, bb3, i3) and
variableRead(bb3, i3, _, false) and
adjacentDefRead(def, bb3, i3, bb2, i2)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `adjacentDefRead`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate adjacentDefNoUncertainReads(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
adjacentDefReachesRead(def, bb1, i1, bb2, i2) and
variableRead(bb2, i2, _, true)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the node at index `i` in `bb` is a last reference to SSA definition
* `def`. The reference is last because it can reach another write `next`,
* without passing through another read or write.
*/
pragma[nomagic]
predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) {
exists(SourceVariable v |
// Next reference to `v` inside `bb` is a write
exists(int rnk, int j |
rnk = ssaDefRank(def, v, bb, i, _) and
next.definesAt(v, bb, j) and
rnk + 1 = ssaRefRank(bb, j, v, SsaDef())
)
or
// Can reach a write using one or more steps
lastSsaRef(def, v, bb, i) and
exists(BasicBlock bb2 |
varBlockReaches(def, bb, bb2) and
1 = ssaDefRank(next, v, bb2, _, SsaDef())
)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `inp` is an immediately preceding definition of uncertain definition
* `def`. Since `def` is uncertain, the value from the preceding definition might
* still be valid.
*/
pragma[nomagic]
predicate uncertainWriteDefinitionInput(UncertainWriteDefinition def, Definition inp) {
lastRefRedef(inp, _, _, def)
}
private predicate adjacentDefReachesUncertainRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2
) {
adjacentDefReachesRead(def, bb1, i1, bb2, i2) and
variableRead(bb2, i2, _, false)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `lastRefRedef`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate lastRefRedefNoUncertainReads(Definition def, BasicBlock bb, int i, Definition next) {
lastRefRedef(def, bb, i, next) and
not variableRead(bb, i, def.getSourceVariable(), false)
or
exists(BasicBlock bb0, int i0 |
lastRefRedef(def, bb0, i0, next) and
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the node at index `i` in `bb` is a last reference to SSA
* definition `def`.
*
* That is, the node can reach the end of the enclosing callable, or another
* SSA definition for the underlying source variable, without passing through
* another read.
*/
pragma[nomagic]
predicate lastRef(Definition def, BasicBlock bb, int i) {
// Can reach another definition
lastRefRedef(def, bb, i, _)
or
exists(SourceVariable v | lastSsaRef(def, v, bb, i) |
// Can reach exit directly
bb instanceof ExitBasicBlock
or
// Can reach a block using one or more steps, where `def` is no longer live
varBlockReachesExit(def, bb)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `lastRefRedef`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate lastRefNoUncertainReads(Definition def, BasicBlock bb, int i) {
lastRef(def, bb, i) and
not variableRead(bb, i, def.getSourceVariable(), false)
or
exists(BasicBlock bb0, int i0 |
lastRef(def, bb0, i0) and
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
)
}
/** A static single assignment (SSA) definition. */
class Definition extends TDefinition {
/** Gets the source variable underlying this SSA definition. */
SourceVariable getSourceVariable() { this.definesAt(result, _, _) }
/**
* Holds if this SSA definition defines `v` at index `i` in basic block `bb`.
* Phi nodes are considered to be at index `-1`, while normal variable writes
* are at the index of the control flow node they wrap.
*/
final predicate definesAt(SourceVariable v, BasicBlock bb, int i) {
this = TWriteDef(v, bb, i)
or
this = TPhiNode(v, bb) and i = -1
}
/** Gets the basic block to which this SSA definition belongs. */
final BasicBlock getBasicBlock() { this.definesAt(_, result, _) }
/** Gets a textual representation of this SSA definition. */
string toString() { none() }
}
/** An SSA definition that corresponds to a write. */
class WriteDefinition extends Definition, TWriteDef {
private SourceVariable v;
private BasicBlock bb;
private int i;
WriteDefinition() { this = TWriteDef(v, bb, i) }
override string toString() { result = "WriteDef" }
}
/** A phi node. */
class PhiNode extends Definition, TPhiNode {
override string toString() { result = "Phi" }
}
/**
* An SSA definition that represents an uncertain update of the underlying
* source variable.
*/
class UncertainWriteDefinition extends WriteDefinition {
UncertainWriteDefinition() {
exists(SourceVariable v, BasicBlock bb, int i |
this.definesAt(v, bb, i) and
variableWrite(bb, i, v, false)
)
}
}
/** Provides a set of consistency queries. */
module Consistency {
abstract class RelevantDefinition extends Definition {
abstract predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
);
}
query predicate nonUniqueDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefReachesRead(v, def, bb, i) and
not exists(unique(Definition def0 | ssaDefReachesRead(v, def0, bb, i)))
}
query predicate readWithoutDef(SourceVariable v, BasicBlock bb, int i) {
variableRead(bb, i, v, _) and
not ssaDefReachesRead(v, _, bb, i)
}
query predicate deadDef(RelevantDefinition def, SourceVariable v) {
v = def.getSourceVariable() and
not ssaDefReachesRead(_, def, _, _) and
not phiHasInputFromBlock(_, def, _) and
not uncertainWriteDefinitionInput(_, def)
}
query predicate notDominatedByDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
exists(BasicBlock bbDef, int iDef | def.definesAt(v, bbDef, iDef) |
ssaDefReachesReadWithinBlock(v, def, bb, i) and
(bb != bbDef or i < iDef)
or
ssaDefReachesRead(v, def, bb, i) and
not ssaDefReachesReadWithinBlock(v, def, bb, i) and
not def.definesAt(v, getImmediateBasicBlockDominator*(bb), _)
)
}
}

View File

@@ -1,130 +0,0 @@
/** Provides the C# specific parameters for `SsaImplCommon.qll`. */
private import csharp
private import AssignableDefinitions
private import semmle.code.csharp.controlflow.internal.PreBasicBlocks as PreBasicBlocks
private import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl
class BasicBlock = PreBasicBlocks::PreBasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock extends BasicBlock {
ExitBasicBlock() { scopeLast(_, this.getLastElement(), _) }
}
/** Holds if `a` is assigned in non-constructor callable `c`. */
pragma[nomagic]
private predicate assignableDefinition(Assignable a, Callable c) {
exists(AssignableDefinition def | def.getTarget() = a |
c = def.getEnclosingCallable() and
not c instanceof Constructor
)
}
/** Holds if `a` is accessed in callable `c`. */
pragma[nomagic]
private predicate assignableAccess(Assignable a, Callable c) {
exists(AssignableAccess aa | aa.getTarget() = a | c = aa.getEnclosingCallable())
}
pragma[nomagic]
private predicate assignableNoCapturing(Assignable a, Callable c) {
assignableAccess(a, c) and
/*
* The code below is equivalent to
* ```ql
* not exists(Callable other | assignableDefinition(a, other) | other != c)
* ```
* but it avoids a Cartesian product in the compiler generated antijoin
* predicate.
*/
(
not assignableDefinition(a, _)
or
c = unique(Callable c0 | assignableDefinition(a, c0) | c0)
)
}
pragma[noinline]
private predicate assignableNoComplexQualifiers(Assignable a) {
forall(QualifiableExpr qe | qe.(AssignableAccess).getTarget() = a | qe.targetIsThisInstance())
}
/**
* A simple assignable. Either a local scope variable or a field/property
* that behaves like a local scope variable.
*/
class SourceVariable extends Assignable {
private Callable c;
SourceVariable() {
(
this instanceof LocalScopeVariable
or
this = any(Field f | not f.isVolatile())
or
this = any(TrivialProperty tp | not tp.isOverridableOrImplementable())
) and
assignableNoCapturing(this, c) and
assignableNoComplexQualifiers(this)
}
/** Gets a callable in which this simple assignable can be analyzed. */
Callable getACallable() { result = c }
}
predicate definitionAt(AssignableDefinition def, BasicBlock bb, int i, SourceVariable v) {
bb.getElement(i) = def.getExpr() and
v = def.getTarget() and
// In cases like `(x, x) = (0, 1)`, we discard the first (dead) definition of `x`
not exists(TupleAssignmentDefinition first, TupleAssignmentDefinition second | first = def |
second.getAssignment() = first.getAssignment() and
second.getEvaluationOrder() > first.getEvaluationOrder() and
second.getTarget() = v
)
or
def.(ImplicitParameterDefinition).getParameter() = v and
exists(Callable c | v = c.getAParameter() |
scopeFirst(c, bb) and
i = -1
)
}
predicate implicitEntryDef(Callable c, BasicBlock bb, SourceVariable v) {
not v instanceof LocalScopeVariable and
c = v.getACallable() and
scopeFirst(c, bb)
}
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignableDefinition def |
definitionAt(def, bb, i, v) and
if def.getTargetAccess().isRefArgument() then certain = false else certain = true
)
or
exists(Callable c |
implicitEntryDef(c, bb, v) and
i = -1 and
certain = true
)
}
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignableRead read |
read = bb.getElement(i) and
read.getTarget() = v and
certain = true
)
or
v =
any(LocalScopeVariable lsv |
lsv.getCallable() = bb.(ExitBasicBlock).getEnclosingCallable() and
i = bb.length() and
(lsv.isRef() or v.(Parameter).isOut()) and
certain = false
)
}

View File

@@ -12,6 +12,8 @@
* `namespace; type; subtypes; name; signature; ext; input; output; kind; provenance`
* - Negative Summaries:
* `namespace; type; name; signature; provenance`
* A negative summary is used to indicate that there is no flow via a callable.
*
* The interpretation of a row is similar to API-graphs with a left-to-right
* reading.
* 1. The `namespace` column selects a namespace.
@@ -100,6 +102,7 @@ private module Frameworks {
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.Concurrent
private import semmle.code.csharp.frameworks.system.collections.Generic
@@ -108,6 +111,7 @@ private module Frameworks {
private import semmle.code.csharp.frameworks.system.collections.Specialized
private import semmle.code.csharp.frameworks.system.ComponentModel
private import semmle.code.csharp.frameworks.system.componentmodel.Design
private import semmle.code.csharp.frameworks.system.Configuration
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
@@ -119,6 +123,7 @@ private module Frameworks {
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

View File

@@ -4,19 +4,74 @@ import csharp
* Provides a simple SSA implementation for local scope variables.
*/
module BaseSsa {
import basessa.SsaImplSpecific
private import basessa.SsaImplCommon as SsaImpl
private import AssignableDefinitions
private import codeql.ssa.Ssa as SsaImplCommon
/**
* Holds if the `i`th node of basic block `bb` is assignable definition `def`,
* targeting local scope variable `v`.
*/
private predicate definitionAt(
AssignableDefinition def, ControlFlow::BasicBlock bb, int i, SsaInput::SourceVariable v
) {
bb.getNode(i) = def.getAControlFlowNode() and
v = def.getTarget() and
// In cases like `(x, x) = (0, 1)`, we discard the first (dead) definition of `x`
not exists(TupleAssignmentDefinition first, TupleAssignmentDefinition second | first = def |
second.getAssignment() = first.getAssignment() and
second.getEvaluationOrder() > first.getEvaluationOrder() and
second.getTarget() = v
)
}
private module SsaInput implements SsaImplCommon::InputSig {
class BasicBlock = ControlFlow::BasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) {
result = bb.getImmediateDominator()
}
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock = ControlFlow::BasicBlocks::ExitBlock;
pragma[noinline]
private Callable getAnAssigningCallable(LocalScopeVariable v) {
result = any(AssignableDefinition def | def.getTarget() = v).getEnclosingCallable()
}
class SourceVariable extends LocalScopeVariable {
SourceVariable() { not getAnAssigningCallable(this) != getAnAssigningCallable(this) }
}
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignableDefinition def |
definitionAt(def, bb, i, v) and
if def.isCertain() then certain = true else certain = false
)
}
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignableRead read |
read.getAControlFlowNode() = bb.getNode(i) and
read.getTarget() = v and
certain = true
)
}
}
private module SsaImpl = SsaImplCommon::Make<SsaInput>;
class Definition extends SsaImpl::Definition {
final AssignableRead getARead() {
exists(BasicBlock bb, int i |
exists(ControlFlow::BasicBlock bb, int i |
SsaImpl::ssaDefReachesRead(_, this, bb, i) and
result.getAControlFlowNode() = bb.getNode(i)
)
}
final AssignableDefinition getDefinition() {
exists(BasicBlock bb, int i, SourceVariable v |
exists(ControlFlow::BasicBlock bb, int i, SsaInput::SourceVariable v |
this.definesAt(v, bb, i) and
definitionAt(result, bb, i, v)
)

View File

@@ -226,15 +226,6 @@ module Public {
none()
}
/**
* Holds if values stored inside `content` are cleared on objects passed as
* arguments at position `pos` to this callable.
*
* TODO: Remove once all languages support `WithoutContent` tokens.
*/
pragma[nomagic]
predicate clearsContent(ParameterPosition pos, ContentSet content) { none() }
/**
* Holds if the summary is auto generated.
*/
@@ -328,23 +319,6 @@ module Private {
SummaryComponentStack::singleton(TArgumentSummaryComponent(_))) and
preservesValue = preservesValue1.booleanAnd(preservesValue2)
)
or
exists(ParameterPosition ppos, ContentSet cs |
c.clearsContent(ppos, cs) and
input = SummaryComponentStack::push(SummaryComponent::withoutContent(cs), output) and
output = SummaryComponentStack::argument(ppos) and
preservesValue = true
)
}
private class MkClearStack extends RequiredSummaryComponentStack {
override predicate required(SummaryComponent head, SummaryComponentStack tail) {
exists(SummarizedCallable sc, ParameterPosition ppos, ContentSet cs |
sc.clearsContent(ppos, cs) and
head = SummaryComponent::withoutContent(cs) and
tail = SummaryComponentStack::argument(ppos)
)
}
}
/**
@@ -945,8 +919,7 @@ module Private {
AccessPath inSpec, AccessPath outSpec, string kind
) {
summaryElement(this, inSpec, outSpec, kind, true) and
not summaryElement(this, _, _, _, false) and
not this.clearsContent(_, _)
not summaryElement(this, _, _, _, false)
}
private predicate relevantSummaryElement(AccessPath inSpec, AccessPath outSpec, string kind) {

View File

@@ -163,6 +163,10 @@ bindingset[c]
SummaryComponent interpretComponentSpecific(AccessPathToken c) {
c = "Element" and result = SummaryComponent::content(any(ElementContent ec))
or
c = "WithoutElement" and result = SummaryComponent::withoutContent(any(ElementContent ec))
or
c = "WithElement" and result = SummaryComponent::withContent(any(ElementContent ec))
or
// Qualified names may contain commas,such as in `Tuple<,>`, so get the entire argument list
// rather than an individual argument.
exists(Field f |
@@ -199,6 +203,10 @@ private string getContentSpecificCsv(Content c) {
string getComponentSpecificCsv(SummaryComponent sc) {
exists(Content c | sc = TContentSummaryComponent(c) and result = getContentSpecificCsv(c))
or
exists(Content c | sc = TWithoutContentSummaryComponent(c) and result = "WithoutElement")
or
exists(Content c | sc = TWithContentSummaryComponent(c) and result = "WithElement")
or
exists(ReturnKind rk |
sc = TReturnSummaryComponent(rk) and
result = "ReturnValue[" + rk + "]" and

View File

@@ -3,7 +3,53 @@
*/
import csharp
import SsaImplCommon
private import codeql.ssa.Ssa as SsaImplCommon
private import AssignableDefinitions
private module SsaInput implements SsaImplCommon::InputSig {
class BasicBlock = ControlFlow::BasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock = ControlFlow::BasicBlocks::ExitBlock;
class SourceVariable = Ssa::SourceVariable;
/**
* Holds if the `i`th node of basic block `bb` is a (potential) write to source
* variable `v`. The Boolean `certain` indicates whether the write is certain.
*
* This includes implicit writes via calls.
*/
predicate variableWrite(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, boolean certain) {
variableWriteDirect(bb, i, v, certain)
or
variableWriteQualifier(bb, i, v, certain)
or
updatesNamedFieldOrProp(bb, i, _, v, _) and
certain = false
or
updatesCapturedVariable(bb, i, _, v, _, _) and
certain = false
}
/**
* Holds if the `i`th of basic block `bb` reads source variable `v`.
*
* This includes implicit reads via calls.
*/
predicate variableRead(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, boolean certain) {
variableReadActual(bb, i, v) and
certain = true
or
variableReadPseudo(bb, i, v) and
certain = false
}
}
import SsaImplCommon::Make<SsaInput>
/**
* Holds if the `i`th node of basic block `bb` reads source variable `v`.
@@ -805,24 +851,6 @@ private module CapturedVariableImpl {
}
}
/**
* Holds if the `i`th node of basic block `bb` is a (potential) write to source
* variable `v`. The Boolean `certain` indicates whether the write is certain.
*
* This includes implicit writes via calls.
*/
predicate variableWrite(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, boolean certain) {
variableWriteDirect(bb, i, v, certain)
or
variableWriteQualifier(bb, i, v, certain)
or
updatesNamedFieldOrProp(bb, i, _, v, _) and
certain = false
or
updatesCapturedVariable(bb, i, _, v, _, _) and
certain = false
}
/**
* Liveness analysis to restrict the size of the SSA representation for
* captured variables.
@@ -1039,19 +1067,6 @@ private predicate variableReadPseudo(ControlFlow::BasicBlock bb, int i, Ssa::Sou
capturedReadIn(bb, i, v, _, _, _)
}
/**
* Holds if the `i`th of basic block `bb` reads source variable `v`.
*
* This includes implicit reads via calls.
*/
predicate variableRead(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, boolean certain) {
variableReadActual(bb, i, v) and
certain = true
or
variableReadPseudo(bb, i, v) and
certain = false
}
cached
private module Cached {
cached
@@ -1151,7 +1166,7 @@ private module Cached {
predicate variableWriteQualifier(
ControlFlow::BasicBlock bb, int i, QualifiedFieldOrPropSourceVariable v, boolean certain
) {
variableWrite(bb, i, v.getQualifier(), certain) and
SsaInput::variableWrite(bb, i, v.getQualifier(), certain) and
// Eliminate corner case where a call definition can overlap with a
// qualifier definition: if method `M` updates field `F`, then a call
// to `M` is both an update of `x.M` and `x.M.M`, so the former call

View File

@@ -1,795 +0,0 @@
/**
* Provides a language-independent implementation of static single assignment
* (SSA) form.
*/
private import SsaImplSpecific
private BasicBlock getABasicBlockPredecessor(BasicBlock bb) { getABasicBlockSuccessor(result) = bb }
/**
* Liveness analysis (based on source variables) to restrict the size of the
* SSA representation.
*/
private module Liveness {
/**
* A classification of variable references into reads (of a given kind) and
* (certain or uncertain) writes.
*/
private newtype TRefKind =
Read(boolean certain) { certain in [false, true] } or
Write(boolean certain) { certain in [false, true] }
private class RefKind extends TRefKind {
string toString() {
exists(boolean certain | this = Read(certain) and result = "read (" + certain + ")")
or
exists(boolean certain | this = Write(certain) and result = "write (" + certain + ")")
}
int getOrder() {
this = Read(_) and
result = 0
or
this = Write(_) and
result = 1
}
}
/**
* Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`.
*/
predicate ref(BasicBlock bb, int i, SourceVariable v, RefKind k) {
exists(boolean certain | variableRead(bb, i, v, certain) | k = Read(certain))
or
exists(boolean certain | variableWrite(bb, i, v, certain) | k = Write(certain))
}
private newtype OrderedRefIndex =
MkOrderedRefIndex(int i, int tag) {
exists(RefKind rk | ref(_, i, _, rk) | tag = rk.getOrder())
}
private OrderedRefIndex refOrd(BasicBlock bb, int i, SourceVariable v, RefKind k, int ord) {
ref(bb, i, v, k) and
result = MkOrderedRefIndex(i, ord) and
ord = k.getOrder()
}
/**
* Gets the (1-based) rank of the reference to `v` at the `i`th node of
* basic block `bb`, which has the given reference kind `k`.
*
* Reads are considered before writes when they happen at the same index.
*/
private int refRank(BasicBlock bb, int i, SourceVariable v, RefKind k) {
refOrd(bb, i, v, k, _) =
rank[result](int j, int ord, OrderedRefIndex res |
res = refOrd(bb, j, v, _, ord)
|
res order by j, ord
)
}
private int maxRefRank(BasicBlock bb, SourceVariable v) {
result = refRank(bb, _, v, _) and
not result + 1 = refRank(bb, _, v, _)
}
predicate lastRefIsRead(BasicBlock bb, SourceVariable v) {
maxRefRank(bb, v) = refRank(bb, _, v, Read(_))
}
/**
* Gets the (1-based) rank of the first reference to `v` inside basic block `bb`
* that is either a read or a certain write.
*/
private int firstReadOrCertainWrite(BasicBlock bb, SourceVariable v) {
result =
min(int r, RefKind k |
r = refRank(bb, _, v, k) and
k != Write(false)
|
r
)
}
/**
* Holds if source variable `v` is live at the beginning of basic block `bb`.
*/
predicate liveAtEntry(BasicBlock bb, SourceVariable v) {
// The first read or certain write to `v` inside `bb` is a read
refRank(bb, _, v, Read(_)) = firstReadOrCertainWrite(bb, v)
or
// There is no certain write to `v` inside `bb`, but `v` is live at entry
// to a successor basic block of `bb`
not exists(firstReadOrCertainWrite(bb, v)) and
liveAtExit(bb, v)
}
/**
* Holds if source variable `v` is live at the end of basic block `bb`.
*/
predicate liveAtExit(BasicBlock bb, SourceVariable v) {
liveAtEntry(getABasicBlockSuccessor(bb), v)
}
/**
* Holds if variable `v` is live in basic block `bb` at index `i`.
* The rank of `i` is `rnk` as defined by `refRank()`.
*/
private predicate liveAtRank(BasicBlock bb, int i, SourceVariable v, int rnk) {
exists(RefKind kind | rnk = refRank(bb, i, v, kind) |
rnk = maxRefRank(bb, v) and
liveAtExit(bb, v)
or
ref(bb, i, v, kind) and
kind = Read(_)
or
exists(RefKind nextKind |
liveAtRank(bb, _, v, rnk + 1) and
rnk + 1 = refRank(bb, _, v, nextKind) and
nextKind != Write(true)
)
)
}
/**
* Holds if variable `v` is live after the (certain or uncertain) write at
* index `i` inside basic block `bb`.
*/
predicate liveAfterWrite(BasicBlock bb, int i, SourceVariable v) {
exists(int rnk | rnk = refRank(bb, i, v, Write(_)) | liveAtRank(bb, i, v, rnk))
}
}
private import Liveness
/**
* Holds if `df` is in the dominance frontier of `bb`.
*
* This is equivalent to:
*
* ```ql
* bb = getImmediateBasicBlockDominator*(getABasicBlockPredecessor(df)) and
* not bb = getImmediateBasicBlockDominator+(df)
* ```
*/
private predicate inDominanceFrontier(BasicBlock bb, BasicBlock df) {
bb = getABasicBlockPredecessor(df) and not bb = getImmediateBasicBlockDominator(df)
or
exists(BasicBlock prev | inDominanceFrontier(prev, df) |
bb = getImmediateBasicBlockDominator(prev) and
not bb = getImmediateBasicBlockDominator(df)
)
}
/**
* Holds if `bb` is in the dominance frontier of a block containing a
* definition of `v`.
*/
pragma[noinline]
private predicate inDefDominanceFrontier(BasicBlock bb, SourceVariable v) {
exists(BasicBlock defbb, Definition def |
def.definesAt(v, defbb, _) and
inDominanceFrontier(defbb, bb)
)
}
cached
newtype TDefinition =
TWriteDef(SourceVariable v, BasicBlock bb, int i) {
variableWrite(bb, i, v, _) and
liveAfterWrite(bb, i, v)
} or
TPhiNode(SourceVariable v, BasicBlock bb) {
inDefDominanceFrontier(bb, v) and
liveAtEntry(bb, v)
}
private module SsaDefReaches {
newtype TSsaRefKind =
SsaActualRead() or
SsaPhiRead() or
SsaDef()
class SsaRead = SsaActualRead or SsaPhiRead;
/**
* A classification of SSA variable references into reads and definitions.
*/
class SsaRefKind extends TSsaRefKind {
string toString() {
this = SsaActualRead() and
result = "SsaActualRead"
or
this = SsaPhiRead() and
result = "SsaPhiRead"
or
this = SsaDef() and
result = "SsaDef"
}
int getOrder() {
this instanceof SsaRead and
result = 0
or
this = SsaDef() and
result = 1
}
}
/**
* Holds if `bb` is in the dominance frontier of a block containing a
* read of `v`.
*/
pragma[nomagic]
private predicate inReadDominanceFrontier(BasicBlock bb, SourceVariable v) {
exists(BasicBlock readbb | inDominanceFrontier(readbb, bb) |
lastRefIsRead(readbb, v)
or
phiRead(readbb, v)
)
}
/**
* Holds if a phi-read node should be inserted for variable `v` at the beginning
* of basic block `bb`.
*
* Phi-read nodes are like normal phi nodes, but they are inserted based on reads
* instead of writes, and only if the dominance-frontier block does not already
* contain a reference (read or write) to `v`. Unlike normal phi nodes, this is
* an internal implementation detail that is not exposed.
*
* The motivation for adding phi-reads is to improve performance of the use-use
* calculation in cases where there is a large number of reads that can reach the
* same join-point, and from there reach a large number of basic blocks. Example:
*
* ```cs
* if (a)
* use(x);
* else if (b)
* use(x);
* else if (c)
* use(x);
* else if (d)
* use(x);
* // many more ifs ...
*
* // phi-read for `x` inserted here
*
* // program not mentioning `x`, with large basic block graph
*
* use(x);
* ```
*
* Without phi-reads, the analysis has to replicate reachability for each of
* the guarded uses of `x`. However, with phi-reads, the analysis will limit
* each conditional use of `x` to reach the basic block containing the phi-read
* node for `x`, and only that basic block will have to compute reachability
* through the remainder of the large program.
*
* Like normal reads, each phi-read node `phi-read` can be reached from exactly
* one SSA definition (without passing through another definition): Assume, for
* the sake of contradiction, that there are two reaching definitions `def1` and
* `def2`. Now, if both `def1` and `def2` dominate `phi-read`, then the nearest
* dominating definition will prevent the other from reaching `phi-read`. So, at
* least one of `def1` and `def2` cannot dominate `phi-read`; assume it is `def1`.
* Then `def1` must go through one of its dominance-frontier blocks in order to
* reach `phi-read`. However, such a block will always start with a (normal) phi
* node, which contradicts reachability.
*
* Also, like normal reads, the unique SSA definition `def` that reaches `phi-read`,
* will dominate `phi-read`. Assuming it doesn't means that the path from `def`
* to `phi-read` goes through a dominance-frontier block, and hence a phi node,
* which contradicts reachability.
*/
pragma[nomagic]
predicate phiRead(BasicBlock bb, SourceVariable v) {
inReadDominanceFrontier(bb, v) and
liveAtEntry(bb, v) and
// only if there are no other references to `v` inside `bb`
not ref(bb, _, v, _) and
not exists(Definition def | def.definesAt(v, bb, _))
}
/**
* Holds if the `i`th node of basic block `bb` is a reference to `v`,
* either a read (when `k` is `SsaRead()`) or an SSA definition (when `k`
* is `SsaDef()`).
*
* Unlike `Liveness::ref`, this includes `phi` nodes.
*/
pragma[nomagic]
predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
variableRead(bb, i, v, _) and
k = SsaActualRead()
or
phiRead(bb, v) and
i = -1 and
k = SsaPhiRead()
or
any(Definition def).definesAt(v, bb, i) and
k = SsaDef()
}
private newtype OrderedSsaRefIndex =
MkOrderedSsaRefIndex(int i, SsaRefKind k) { ssaRef(_, i, _, k) }
private OrderedSsaRefIndex ssaRefOrd(BasicBlock bb, int i, SourceVariable v, SsaRefKind k, int ord) {
ssaRef(bb, i, v, k) and
result = MkOrderedSsaRefIndex(i, k) and
ord = k.getOrder()
}
/**
* Gets the (1-based) rank of the reference to `v` at the `i`th node of basic
* block `bb`, which has the given reference kind `k`.
*
* For example, if `bb` is a basic block with a phi node for `v` (considered
* to be at index -1), reads `v` at node 2, and defines it at node 5, we have:
*
* ```ql
* ssaRefRank(bb, -1, v, SsaDef()) = 1 // phi node
* ssaRefRank(bb, 2, v, Read()) = 2 // read at node 2
* ssaRefRank(bb, 5, v, SsaDef()) = 3 // definition at node 5
* ```
*
* Reads are considered before writes when they happen at the same index.
*/
int ssaRefRank(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
ssaRefOrd(bb, i, v, k, _) =
rank[result](int j, int ord, OrderedSsaRefIndex res |
res = ssaRefOrd(bb, j, v, _, ord)
|
res order by j, ord
)
}
int maxSsaRefRank(BasicBlock bb, SourceVariable v) {
result = ssaRefRank(bb, _, v, _) and
not result + 1 = ssaRefRank(bb, _, v, _)
}
/**
* Holds if the SSA definition `def` reaches rank index `rnk` in its own
* basic block `bb`.
*/
predicate ssaDefReachesRank(BasicBlock bb, Definition def, int rnk, SourceVariable v) {
exists(int i |
rnk = ssaRefRank(bb, i, v, SsaDef()) and
def.definesAt(v, bb, i)
)
or
ssaDefReachesRank(bb, def, rnk - 1, v) and
rnk = ssaRefRank(bb, _, v, any(SsaRead k))
}
/**
* Holds if the SSA definition of `v` at `def` reaches index `i` in the same
* basic block `bb`, without crossing another SSA definition of `v`.
*/
predicate ssaDefReachesReadWithinBlock(SourceVariable v, Definition def, BasicBlock bb, int i) {
exists(int rnk |
ssaDefReachesRank(bb, def, rnk, v) and
rnk = ssaRefRank(bb, i, v, any(SsaRead k))
)
}
/**
* Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`.
*/
int ssaDefRank(Definition def, SourceVariable v, BasicBlock bb, int i, SsaRefKind k) {
v = def.getSourceVariable() and
result = ssaRefRank(bb, i, v, k) and
(
ssaDefReachesRead(_, def, bb, i)
or
def.definesAt(_, bb, i)
)
}
/**
* Holds if the reference to `def` at index `i` in basic block `bb` is the
* last reference to `v` inside `bb`.
*/
pragma[noinline]
predicate lastSsaRef(Definition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v)
}
predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v, SsaRefKind k) {
exists(ssaDefRank(def, v, bb, _, k))
}
pragma[noinline]
private predicate ssaDefReachesThroughBlock(Definition def, BasicBlock bb) {
ssaDefReachesEndOfBlock(bb, def, _) and
not defOccursInBlock(_, bb, def.getSourceVariable(), _)
}
/**
* Holds if `def` is accessed in basic block `bb1` (either a read or a write),
* `bb2` is a transitive successor of `bb1`, `def` is live at the end of _some_
* predecessor of `bb2`, and the underlying variable for `def` is neither read
* nor written in any block on the path between `bb1` and `bb2`.
*
* Phi reads are considered as normal reads for this predicate.
*/
pragma[nomagic]
private predicate varBlockReachesInclPhiRead(Definition def, BasicBlock bb1, BasicBlock bb2) {
defOccursInBlock(def, bb1, _, _) and
bb2 = getABasicBlockSuccessor(bb1)
or
exists(BasicBlock mid |
varBlockReachesInclPhiRead(def, bb1, mid) and
ssaDefReachesThroughBlock(def, mid) and
bb2 = getABasicBlockSuccessor(mid)
)
}
pragma[nomagic]
private predicate phiReadStep(Definition def, SourceVariable v, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesInclPhiRead(def, bb1, bb2) and
defOccursInBlock(def, bb2, v, SsaPhiRead())
}
pragma[nomagic]
private predicate varBlockReachesExclPhiRead(Definition def, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesInclPhiRead(pragma[only_bind_into](def), bb1, pragma[only_bind_into](bb2)) and
ssaRef(bb2, _, def.getSourceVariable(), [SsaActualRead().(TSsaRefKind), SsaDef()])
or
exists(BasicBlock mid |
varBlockReachesExclPhiRead(def, mid, bb2) and
phiReadStep(def, _, bb1, mid)
)
}
/**
* Holds if `def` is accessed in basic block `bb1` (either a read or a write),
* the underlying variable `v` of `def` is accessed in basic block `bb2`
* (either a read or a write), `bb2` is a transitive successor of `bb1`, and
* `v` is neither read nor written in any block on the path between `bb1`
* and `bb2`.
*/
pragma[nomagic]
predicate varBlockReaches(Definition def, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesExclPhiRead(def, bb1, bb2) and
not defOccursInBlock(def, bb1, _, SsaPhiRead())
}
pragma[nomagic]
predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) {
varBlockReaches(def, bb1, bb2) and
ssaRefRank(bb2, i2, def.getSourceVariable(), SsaActualRead()) = 1
}
/**
* Holds if `def` is accessed in basic block `bb` (either a read or a write),
* `bb1` can reach a transitive successor `bb2` where `def` is no longer live,
* and `v` is neither read nor written in any block on the path between `bb`
* and `bb2`.
*/
pragma[nomagic]
predicate varBlockReachesExit(Definition def, BasicBlock bb) {
exists(BasicBlock bb2 | varBlockReachesInclPhiRead(def, bb, bb2) |
not defOccursInBlock(def, bb2, _, _) and
not ssaDefReachesEndOfBlock(bb2, def, _)
)
or
exists(BasicBlock mid |
varBlockReachesExit(def, mid) and
phiReadStep(def, _, bb, mid)
)
}
}
predicate phiReadExposedForTesting = phiRead/2;
private import SsaDefReaches
pragma[nomagic]
predicate liveThrough(BasicBlock bb, SourceVariable v) {
liveAtExit(bb, v) and
not ssaRef(bb, _, v, SsaDef())
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the SSA definition of `v` at `def` reaches the end of basic
* block `bb`, at which point it is still live, without crossing another
* SSA definition of `v`.
*/
pragma[nomagic]
predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) {
exists(int last |
last = maxSsaRefRank(pragma[only_bind_into](bb), pragma[only_bind_into](v)) and
ssaDefReachesRank(bb, def, last, v) and
liveAtExit(bb, v)
)
or
// The construction of SSA form ensures that each read of a variable is
// dominated by its definition. An SSA definition therefore reaches a
// control flow node if it is the _closest_ SSA definition that dominates
// the node. If two definitions dominate a node then one must dominate the
// other, so therefore the definition of _closest_ is given by the dominator
// tree. Thus, reaching definitions can be calculated in terms of dominance.
ssaDefReachesEndOfBlock(getImmediateBasicBlockDominator(bb), def, pragma[only_bind_into](v)) and
liveThrough(bb, pragma[only_bind_into](v))
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `inp` is an input to the phi node `phi` along the edge originating in `bb`.
*/
pragma[nomagic]
predicate phiHasInputFromBlock(PhiNode phi, Definition inp, BasicBlock bb) {
exists(SourceVariable v, BasicBlock bbDef |
phi.definesAt(v, bbDef, _) and
getABasicBlockPredecessor(bbDef) = bb and
ssaDefReachesEndOfBlock(bb, inp, v)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the SSA definition of `v` at `def` reaches a read at index `i` in
* basic block `bb`, without crossing another SSA definition of `v`. The read
* is of kind `rk`.
*/
pragma[nomagic]
predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int i) {
ssaDefReachesReadWithinBlock(v, def, bb, i)
or
ssaRef(bb, i, v, any(SsaRead k)) and
ssaDefReachesEndOfBlock(getABasicBlockPredecessor(bb), def, v) and
not ssaDefReachesReadWithinBlock(v, _, bb, i)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `def` is accessed at index `i1` in basic block `bb1` (either a read
* or a write), `def` is read at index `i2` in basic block `bb2`, and there is a
* path between them without any read of `def`.
*/
pragma[nomagic]
predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
exists(int rnk |
rnk = ssaDefRank(def, _, bb1, i1, _) and
rnk + 1 = ssaDefRank(def, _, bb1, i2, SsaActualRead()) and
variableRead(bb1, i2, _, _) and
bb2 = bb1
)
or
lastSsaRef(def, _, bb1, i1) and
defAdjacentRead(def, bb1, bb2, i2)
}
pragma[noinline]
private predicate adjacentDefRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2, SourceVariable v
) {
adjacentDefRead(def, bb1, i1, bb2, i2) and
v = def.getSourceVariable()
}
private predicate adjacentDefReachesRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2
) {
exists(SourceVariable v | adjacentDefRead(def, bb1, i1, bb2, i2, v) |
ssaRef(bb1, i1, v, SsaDef())
or
variableRead(bb1, i1, v, true)
)
or
exists(BasicBlock bb3, int i3 |
adjacentDefReachesRead(def, bb1, i1, bb3, i3) and
variableRead(bb3, i3, _, false) and
adjacentDefRead(def, bb3, i3, bb2, i2)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `adjacentDefRead`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate adjacentDefNoUncertainReads(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
adjacentDefReachesRead(def, bb1, i1, bb2, i2) and
variableRead(bb2, i2, _, true)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the node at index `i` in `bb` is a last reference to SSA definition
* `def`. The reference is last because it can reach another write `next`,
* without passing through another read or write.
*/
pragma[nomagic]
predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) {
exists(SourceVariable v |
// Next reference to `v` inside `bb` is a write
exists(int rnk, int j |
rnk = ssaDefRank(def, v, bb, i, _) and
next.definesAt(v, bb, j) and
rnk + 1 = ssaRefRank(bb, j, v, SsaDef())
)
or
// Can reach a write using one or more steps
lastSsaRef(def, v, bb, i) and
exists(BasicBlock bb2 |
varBlockReaches(def, bb, bb2) and
1 = ssaDefRank(next, v, bb2, _, SsaDef())
)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `inp` is an immediately preceding definition of uncertain definition
* `def`. Since `def` is uncertain, the value from the preceding definition might
* still be valid.
*/
pragma[nomagic]
predicate uncertainWriteDefinitionInput(UncertainWriteDefinition def, Definition inp) {
lastRefRedef(inp, _, _, def)
}
private predicate adjacentDefReachesUncertainRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2
) {
adjacentDefReachesRead(def, bb1, i1, bb2, i2) and
variableRead(bb2, i2, _, false)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `lastRefRedef`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate lastRefRedefNoUncertainReads(Definition def, BasicBlock bb, int i, Definition next) {
lastRefRedef(def, bb, i, next) and
not variableRead(bb, i, def.getSourceVariable(), false)
or
exists(BasicBlock bb0, int i0 |
lastRefRedef(def, bb0, i0, next) and
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the node at index `i` in `bb` is a last reference to SSA
* definition `def`.
*
* That is, the node can reach the end of the enclosing callable, or another
* SSA definition for the underlying source variable, without passing through
* another read.
*/
pragma[nomagic]
predicate lastRef(Definition def, BasicBlock bb, int i) {
// Can reach another definition
lastRefRedef(def, bb, i, _)
or
exists(SourceVariable v | lastSsaRef(def, v, bb, i) |
// Can reach exit directly
bb instanceof ExitBasicBlock
or
// Can reach a block using one or more steps, where `def` is no longer live
varBlockReachesExit(def, bb)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `lastRefRedef`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate lastRefNoUncertainReads(Definition def, BasicBlock bb, int i) {
lastRef(def, bb, i) and
not variableRead(bb, i, def.getSourceVariable(), false)
or
exists(BasicBlock bb0, int i0 |
lastRef(def, bb0, i0) and
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
)
}
/** A static single assignment (SSA) definition. */
class Definition extends TDefinition {
/** Gets the source variable underlying this SSA definition. */
SourceVariable getSourceVariable() { this.definesAt(result, _, _) }
/**
* Holds if this SSA definition defines `v` at index `i` in basic block `bb`.
* Phi nodes are considered to be at index `-1`, while normal variable writes
* are at the index of the control flow node they wrap.
*/
final predicate definesAt(SourceVariable v, BasicBlock bb, int i) {
this = TWriteDef(v, bb, i)
or
this = TPhiNode(v, bb) and i = -1
}
/** Gets the basic block to which this SSA definition belongs. */
final BasicBlock getBasicBlock() { this.definesAt(_, result, _) }
/** Gets a textual representation of this SSA definition. */
string toString() { none() }
}
/** An SSA definition that corresponds to a write. */
class WriteDefinition extends Definition, TWriteDef {
private SourceVariable v;
private BasicBlock bb;
private int i;
WriteDefinition() { this = TWriteDef(v, bb, i) }
override string toString() { result = "WriteDef" }
}
/** A phi node. */
class PhiNode extends Definition, TPhiNode {
override string toString() { result = "Phi" }
}
/**
* An SSA definition that represents an uncertain update of the underlying
* source variable.
*/
class UncertainWriteDefinition extends WriteDefinition {
UncertainWriteDefinition() {
exists(SourceVariable v, BasicBlock bb, int i |
this.definesAt(v, bb, i) and
variableWrite(bb, i, v, false)
)
}
}
/** Provides a set of consistency queries. */
module Consistency {
abstract class RelevantDefinition extends Definition {
abstract predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
);
}
query predicate nonUniqueDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefReachesRead(v, def, bb, i) and
not exists(unique(Definition def0 | ssaDefReachesRead(v, def0, bb, i)))
}
query predicate readWithoutDef(SourceVariable v, BasicBlock bb, int i) {
variableRead(bb, i, v, _) and
not ssaDefReachesRead(v, _, bb, i)
}
query predicate deadDef(RelevantDefinition def, SourceVariable v) {
v = def.getSourceVariable() and
not ssaDefReachesRead(_, def, _, _) and
not phiHasInputFromBlock(_, def, _) and
not uncertainWriteDefinitionInput(_, def)
}
query predicate notDominatedByDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
exists(BasicBlock bbDef, int iDef | def.definesAt(v, bbDef, iDef) |
ssaDefReachesReadWithinBlock(v, def, bb, i) and
(bb != bbDef or i < iDef)
or
ssaDefReachesRead(v, def, bb, i) and
not ssaDefReachesReadWithinBlock(v, def, bb, i) and
not def.definesAt(v, getImmediateBasicBlockDominator*(bb), _)
)
}
}

View File

@@ -1,19 +0,0 @@
/** Provides the C# specific parameters for `SsaImplCommon.qll`. */
private import csharp
private import AssignableDefinitions
private import SsaImpl as SsaImpl
class BasicBlock = ControlFlow::BasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock = ControlFlow::BasicBlocks::ExitBlock;
class SourceVariable = Ssa::SourceVariable;
predicate variableWrite = SsaImpl::variableWrite/4;
predicate variableRead = SsaImpl::variableRead/4;

View File

@@ -1,795 +0,0 @@
/**
* Provides a language-independent implementation of static single assignment
* (SSA) form.
*/
private import SsaImplSpecific
private BasicBlock getABasicBlockPredecessor(BasicBlock bb) { getABasicBlockSuccessor(result) = bb }
/**
* Liveness analysis (based on source variables) to restrict the size of the
* SSA representation.
*/
private module Liveness {
/**
* A classification of variable references into reads (of a given kind) and
* (certain or uncertain) writes.
*/
private newtype TRefKind =
Read(boolean certain) { certain in [false, true] } or
Write(boolean certain) { certain in [false, true] }
private class RefKind extends TRefKind {
string toString() {
exists(boolean certain | this = Read(certain) and result = "read (" + certain + ")")
or
exists(boolean certain | this = Write(certain) and result = "write (" + certain + ")")
}
int getOrder() {
this = Read(_) and
result = 0
or
this = Write(_) and
result = 1
}
}
/**
* Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`.
*/
predicate ref(BasicBlock bb, int i, SourceVariable v, RefKind k) {
exists(boolean certain | variableRead(bb, i, v, certain) | k = Read(certain))
or
exists(boolean certain | variableWrite(bb, i, v, certain) | k = Write(certain))
}
private newtype OrderedRefIndex =
MkOrderedRefIndex(int i, int tag) {
exists(RefKind rk | ref(_, i, _, rk) | tag = rk.getOrder())
}
private OrderedRefIndex refOrd(BasicBlock bb, int i, SourceVariable v, RefKind k, int ord) {
ref(bb, i, v, k) and
result = MkOrderedRefIndex(i, ord) and
ord = k.getOrder()
}
/**
* Gets the (1-based) rank of the reference to `v` at the `i`th node of
* basic block `bb`, which has the given reference kind `k`.
*
* Reads are considered before writes when they happen at the same index.
*/
private int refRank(BasicBlock bb, int i, SourceVariable v, RefKind k) {
refOrd(bb, i, v, k, _) =
rank[result](int j, int ord, OrderedRefIndex res |
res = refOrd(bb, j, v, _, ord)
|
res order by j, ord
)
}
private int maxRefRank(BasicBlock bb, SourceVariable v) {
result = refRank(bb, _, v, _) and
not result + 1 = refRank(bb, _, v, _)
}
predicate lastRefIsRead(BasicBlock bb, SourceVariable v) {
maxRefRank(bb, v) = refRank(bb, _, v, Read(_))
}
/**
* Gets the (1-based) rank of the first reference to `v` inside basic block `bb`
* that is either a read or a certain write.
*/
private int firstReadOrCertainWrite(BasicBlock bb, SourceVariable v) {
result =
min(int r, RefKind k |
r = refRank(bb, _, v, k) and
k != Write(false)
|
r
)
}
/**
* Holds if source variable `v` is live at the beginning of basic block `bb`.
*/
predicate liveAtEntry(BasicBlock bb, SourceVariable v) {
// The first read or certain write to `v` inside `bb` is a read
refRank(bb, _, v, Read(_)) = firstReadOrCertainWrite(bb, v)
or
// There is no certain write to `v` inside `bb`, but `v` is live at entry
// to a successor basic block of `bb`
not exists(firstReadOrCertainWrite(bb, v)) and
liveAtExit(bb, v)
}
/**
* Holds if source variable `v` is live at the end of basic block `bb`.
*/
predicate liveAtExit(BasicBlock bb, SourceVariable v) {
liveAtEntry(getABasicBlockSuccessor(bb), v)
}
/**
* Holds if variable `v` is live in basic block `bb` at index `i`.
* The rank of `i` is `rnk` as defined by `refRank()`.
*/
private predicate liveAtRank(BasicBlock bb, int i, SourceVariable v, int rnk) {
exists(RefKind kind | rnk = refRank(bb, i, v, kind) |
rnk = maxRefRank(bb, v) and
liveAtExit(bb, v)
or
ref(bb, i, v, kind) and
kind = Read(_)
or
exists(RefKind nextKind |
liveAtRank(bb, _, v, rnk + 1) and
rnk + 1 = refRank(bb, _, v, nextKind) and
nextKind != Write(true)
)
)
}
/**
* Holds if variable `v` is live after the (certain or uncertain) write at
* index `i` inside basic block `bb`.
*/
predicate liveAfterWrite(BasicBlock bb, int i, SourceVariable v) {
exists(int rnk | rnk = refRank(bb, i, v, Write(_)) | liveAtRank(bb, i, v, rnk))
}
}
private import Liveness
/**
* Holds if `df` is in the dominance frontier of `bb`.
*
* This is equivalent to:
*
* ```ql
* bb = getImmediateBasicBlockDominator*(getABasicBlockPredecessor(df)) and
* not bb = getImmediateBasicBlockDominator+(df)
* ```
*/
private predicate inDominanceFrontier(BasicBlock bb, BasicBlock df) {
bb = getABasicBlockPredecessor(df) and not bb = getImmediateBasicBlockDominator(df)
or
exists(BasicBlock prev | inDominanceFrontier(prev, df) |
bb = getImmediateBasicBlockDominator(prev) and
not bb = getImmediateBasicBlockDominator(df)
)
}
/**
* Holds if `bb` is in the dominance frontier of a block containing a
* definition of `v`.
*/
pragma[noinline]
private predicate inDefDominanceFrontier(BasicBlock bb, SourceVariable v) {
exists(BasicBlock defbb, Definition def |
def.definesAt(v, defbb, _) and
inDominanceFrontier(defbb, bb)
)
}
cached
newtype TDefinition =
TWriteDef(SourceVariable v, BasicBlock bb, int i) {
variableWrite(bb, i, v, _) and
liveAfterWrite(bb, i, v)
} or
TPhiNode(SourceVariable v, BasicBlock bb) {
inDefDominanceFrontier(bb, v) and
liveAtEntry(bb, v)
}
private module SsaDefReaches {
newtype TSsaRefKind =
SsaActualRead() or
SsaPhiRead() or
SsaDef()
class SsaRead = SsaActualRead or SsaPhiRead;
/**
* A classification of SSA variable references into reads and definitions.
*/
class SsaRefKind extends TSsaRefKind {
string toString() {
this = SsaActualRead() and
result = "SsaActualRead"
or
this = SsaPhiRead() and
result = "SsaPhiRead"
or
this = SsaDef() and
result = "SsaDef"
}
int getOrder() {
this instanceof SsaRead and
result = 0
or
this = SsaDef() and
result = 1
}
}
/**
* Holds if `bb` is in the dominance frontier of a block containing a
* read of `v`.
*/
pragma[nomagic]
private predicate inReadDominanceFrontier(BasicBlock bb, SourceVariable v) {
exists(BasicBlock readbb | inDominanceFrontier(readbb, bb) |
lastRefIsRead(readbb, v)
or
phiRead(readbb, v)
)
}
/**
* Holds if a phi-read node should be inserted for variable `v` at the beginning
* of basic block `bb`.
*
* Phi-read nodes are like normal phi nodes, but they are inserted based on reads
* instead of writes, and only if the dominance-frontier block does not already
* contain a reference (read or write) to `v`. Unlike normal phi nodes, this is
* an internal implementation detail that is not exposed.
*
* The motivation for adding phi-reads is to improve performance of the use-use
* calculation in cases where there is a large number of reads that can reach the
* same join-point, and from there reach a large number of basic blocks. Example:
*
* ```cs
* if (a)
* use(x);
* else if (b)
* use(x);
* else if (c)
* use(x);
* else if (d)
* use(x);
* // many more ifs ...
*
* // phi-read for `x` inserted here
*
* // program not mentioning `x`, with large basic block graph
*
* use(x);
* ```
*
* Without phi-reads, the analysis has to replicate reachability for each of
* the guarded uses of `x`. However, with phi-reads, the analysis will limit
* each conditional use of `x` to reach the basic block containing the phi-read
* node for `x`, and only that basic block will have to compute reachability
* through the remainder of the large program.
*
* Like normal reads, each phi-read node `phi-read` can be reached from exactly
* one SSA definition (without passing through another definition): Assume, for
* the sake of contradiction, that there are two reaching definitions `def1` and
* `def2`. Now, if both `def1` and `def2` dominate `phi-read`, then the nearest
* dominating definition will prevent the other from reaching `phi-read`. So, at
* least one of `def1` and `def2` cannot dominate `phi-read`; assume it is `def1`.
* Then `def1` must go through one of its dominance-frontier blocks in order to
* reach `phi-read`. However, such a block will always start with a (normal) phi
* node, which contradicts reachability.
*
* Also, like normal reads, the unique SSA definition `def` that reaches `phi-read`,
* will dominate `phi-read`. Assuming it doesn't means that the path from `def`
* to `phi-read` goes through a dominance-frontier block, and hence a phi node,
* which contradicts reachability.
*/
pragma[nomagic]
predicate phiRead(BasicBlock bb, SourceVariable v) {
inReadDominanceFrontier(bb, v) and
liveAtEntry(bb, v) and
// only if there are no other references to `v` inside `bb`
not ref(bb, _, v, _) and
not exists(Definition def | def.definesAt(v, bb, _))
}
/**
* Holds if the `i`th node of basic block `bb` is a reference to `v`,
* either a read (when `k` is `SsaRead()`) or an SSA definition (when `k`
* is `SsaDef()`).
*
* Unlike `Liveness::ref`, this includes `phi` nodes.
*/
pragma[nomagic]
predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
variableRead(bb, i, v, _) and
k = SsaActualRead()
or
phiRead(bb, v) and
i = -1 and
k = SsaPhiRead()
or
any(Definition def).definesAt(v, bb, i) and
k = SsaDef()
}
private newtype OrderedSsaRefIndex =
MkOrderedSsaRefIndex(int i, SsaRefKind k) { ssaRef(_, i, _, k) }
private OrderedSsaRefIndex ssaRefOrd(BasicBlock bb, int i, SourceVariable v, SsaRefKind k, int ord) {
ssaRef(bb, i, v, k) and
result = MkOrderedSsaRefIndex(i, k) and
ord = k.getOrder()
}
/**
* Gets the (1-based) rank of the reference to `v` at the `i`th node of basic
* block `bb`, which has the given reference kind `k`.
*
* For example, if `bb` is a basic block with a phi node for `v` (considered
* to be at index -1), reads `v` at node 2, and defines it at node 5, we have:
*
* ```ql
* ssaRefRank(bb, -1, v, SsaDef()) = 1 // phi node
* ssaRefRank(bb, 2, v, Read()) = 2 // read at node 2
* ssaRefRank(bb, 5, v, SsaDef()) = 3 // definition at node 5
* ```
*
* Reads are considered before writes when they happen at the same index.
*/
int ssaRefRank(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
ssaRefOrd(bb, i, v, k, _) =
rank[result](int j, int ord, OrderedSsaRefIndex res |
res = ssaRefOrd(bb, j, v, _, ord)
|
res order by j, ord
)
}
int maxSsaRefRank(BasicBlock bb, SourceVariable v) {
result = ssaRefRank(bb, _, v, _) and
not result + 1 = ssaRefRank(bb, _, v, _)
}
/**
* Holds if the SSA definition `def` reaches rank index `rnk` in its own
* basic block `bb`.
*/
predicate ssaDefReachesRank(BasicBlock bb, Definition def, int rnk, SourceVariable v) {
exists(int i |
rnk = ssaRefRank(bb, i, v, SsaDef()) and
def.definesAt(v, bb, i)
)
or
ssaDefReachesRank(bb, def, rnk - 1, v) and
rnk = ssaRefRank(bb, _, v, any(SsaRead k))
}
/**
* Holds if the SSA definition of `v` at `def` reaches index `i` in the same
* basic block `bb`, without crossing another SSA definition of `v`.
*/
predicate ssaDefReachesReadWithinBlock(SourceVariable v, Definition def, BasicBlock bb, int i) {
exists(int rnk |
ssaDefReachesRank(bb, def, rnk, v) and
rnk = ssaRefRank(bb, i, v, any(SsaRead k))
)
}
/**
* Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`.
*/
int ssaDefRank(Definition def, SourceVariable v, BasicBlock bb, int i, SsaRefKind k) {
v = def.getSourceVariable() and
result = ssaRefRank(bb, i, v, k) and
(
ssaDefReachesRead(_, def, bb, i)
or
def.definesAt(_, bb, i)
)
}
/**
* Holds if the reference to `def` at index `i` in basic block `bb` is the
* last reference to `v` inside `bb`.
*/
pragma[noinline]
predicate lastSsaRef(Definition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v)
}
predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v, SsaRefKind k) {
exists(ssaDefRank(def, v, bb, _, k))
}
pragma[noinline]
private predicate ssaDefReachesThroughBlock(Definition def, BasicBlock bb) {
ssaDefReachesEndOfBlock(bb, def, _) and
not defOccursInBlock(_, bb, def.getSourceVariable(), _)
}
/**
* Holds if `def` is accessed in basic block `bb1` (either a read or a write),
* `bb2` is a transitive successor of `bb1`, `def` is live at the end of _some_
* predecessor of `bb2`, and the underlying variable for `def` is neither read
* nor written in any block on the path between `bb1` and `bb2`.
*
* Phi reads are considered as normal reads for this predicate.
*/
pragma[nomagic]
private predicate varBlockReachesInclPhiRead(Definition def, BasicBlock bb1, BasicBlock bb2) {
defOccursInBlock(def, bb1, _, _) and
bb2 = getABasicBlockSuccessor(bb1)
or
exists(BasicBlock mid |
varBlockReachesInclPhiRead(def, bb1, mid) and
ssaDefReachesThroughBlock(def, mid) and
bb2 = getABasicBlockSuccessor(mid)
)
}
pragma[nomagic]
private predicate phiReadStep(Definition def, SourceVariable v, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesInclPhiRead(def, bb1, bb2) and
defOccursInBlock(def, bb2, v, SsaPhiRead())
}
pragma[nomagic]
private predicate varBlockReachesExclPhiRead(Definition def, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesInclPhiRead(pragma[only_bind_into](def), bb1, pragma[only_bind_into](bb2)) and
ssaRef(bb2, _, def.getSourceVariable(), [SsaActualRead().(TSsaRefKind), SsaDef()])
or
exists(BasicBlock mid |
varBlockReachesExclPhiRead(def, mid, bb2) and
phiReadStep(def, _, bb1, mid)
)
}
/**
* Holds if `def` is accessed in basic block `bb1` (either a read or a write),
* the underlying variable `v` of `def` is accessed in basic block `bb2`
* (either a read or a write), `bb2` is a transitive successor of `bb1`, and
* `v` is neither read nor written in any block on the path between `bb1`
* and `bb2`.
*/
pragma[nomagic]
predicate varBlockReaches(Definition def, BasicBlock bb1, BasicBlock bb2) {
varBlockReachesExclPhiRead(def, bb1, bb2) and
not defOccursInBlock(def, bb1, _, SsaPhiRead())
}
pragma[nomagic]
predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) {
varBlockReaches(def, bb1, bb2) and
ssaRefRank(bb2, i2, def.getSourceVariable(), SsaActualRead()) = 1
}
/**
* Holds if `def` is accessed in basic block `bb` (either a read or a write),
* `bb1` can reach a transitive successor `bb2` where `def` is no longer live,
* and `v` is neither read nor written in any block on the path between `bb`
* and `bb2`.
*/
pragma[nomagic]
predicate varBlockReachesExit(Definition def, BasicBlock bb) {
exists(BasicBlock bb2 | varBlockReachesInclPhiRead(def, bb, bb2) |
not defOccursInBlock(def, bb2, _, _) and
not ssaDefReachesEndOfBlock(bb2, def, _)
)
or
exists(BasicBlock mid |
varBlockReachesExit(def, mid) and
phiReadStep(def, _, bb, mid)
)
}
}
predicate phiReadExposedForTesting = phiRead/2;
private import SsaDefReaches
pragma[nomagic]
predicate liveThrough(BasicBlock bb, SourceVariable v) {
liveAtExit(bb, v) and
not ssaRef(bb, _, v, SsaDef())
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the SSA definition of `v` at `def` reaches the end of basic
* block `bb`, at which point it is still live, without crossing another
* SSA definition of `v`.
*/
pragma[nomagic]
predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) {
exists(int last |
last = maxSsaRefRank(pragma[only_bind_into](bb), pragma[only_bind_into](v)) and
ssaDefReachesRank(bb, def, last, v) and
liveAtExit(bb, v)
)
or
// The construction of SSA form ensures that each read of a variable is
// dominated by its definition. An SSA definition therefore reaches a
// control flow node if it is the _closest_ SSA definition that dominates
// the node. If two definitions dominate a node then one must dominate the
// other, so therefore the definition of _closest_ is given by the dominator
// tree. Thus, reaching definitions can be calculated in terms of dominance.
ssaDefReachesEndOfBlock(getImmediateBasicBlockDominator(bb), def, pragma[only_bind_into](v)) and
liveThrough(bb, pragma[only_bind_into](v))
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `inp` is an input to the phi node `phi` along the edge originating in `bb`.
*/
pragma[nomagic]
predicate phiHasInputFromBlock(PhiNode phi, Definition inp, BasicBlock bb) {
exists(SourceVariable v, BasicBlock bbDef |
phi.definesAt(v, bbDef, _) and
getABasicBlockPredecessor(bbDef) = bb and
ssaDefReachesEndOfBlock(bb, inp, v)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the SSA definition of `v` at `def` reaches a read at index `i` in
* basic block `bb`, without crossing another SSA definition of `v`. The read
* is of kind `rk`.
*/
pragma[nomagic]
predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int i) {
ssaDefReachesReadWithinBlock(v, def, bb, i)
or
ssaRef(bb, i, v, any(SsaRead k)) and
ssaDefReachesEndOfBlock(getABasicBlockPredecessor(bb), def, v) and
not ssaDefReachesReadWithinBlock(v, _, bb, i)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `def` is accessed at index `i1` in basic block `bb1` (either a read
* or a write), `def` is read at index `i2` in basic block `bb2`, and there is a
* path between them without any read of `def`.
*/
pragma[nomagic]
predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
exists(int rnk |
rnk = ssaDefRank(def, _, bb1, i1, _) and
rnk + 1 = ssaDefRank(def, _, bb1, i2, SsaActualRead()) and
variableRead(bb1, i2, _, _) and
bb2 = bb1
)
or
lastSsaRef(def, _, bb1, i1) and
defAdjacentRead(def, bb1, bb2, i2)
}
pragma[noinline]
private predicate adjacentDefRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2, SourceVariable v
) {
adjacentDefRead(def, bb1, i1, bb2, i2) and
v = def.getSourceVariable()
}
private predicate adjacentDefReachesRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2
) {
exists(SourceVariable v | adjacentDefRead(def, bb1, i1, bb2, i2, v) |
ssaRef(bb1, i1, v, SsaDef())
or
variableRead(bb1, i1, v, true)
)
or
exists(BasicBlock bb3, int i3 |
adjacentDefReachesRead(def, bb1, i1, bb3, i3) and
variableRead(bb3, i3, _, false) and
adjacentDefRead(def, bb3, i3, bb2, i2)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `adjacentDefRead`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate adjacentDefNoUncertainReads(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
adjacentDefReachesRead(def, bb1, i1, bb2, i2) and
variableRead(bb2, i2, _, true)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the node at index `i` in `bb` is a last reference to SSA definition
* `def`. The reference is last because it can reach another write `next`,
* without passing through another read or write.
*/
pragma[nomagic]
predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) {
exists(SourceVariable v |
// Next reference to `v` inside `bb` is a write
exists(int rnk, int j |
rnk = ssaDefRank(def, v, bb, i, _) and
next.definesAt(v, bb, j) and
rnk + 1 = ssaRefRank(bb, j, v, SsaDef())
)
or
// Can reach a write using one or more steps
lastSsaRef(def, v, bb, i) and
exists(BasicBlock bb2 |
varBlockReaches(def, bb, bb2) and
1 = ssaDefRank(next, v, bb2, _, SsaDef())
)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if `inp` is an immediately preceding definition of uncertain definition
* `def`. Since `def` is uncertain, the value from the preceding definition might
* still be valid.
*/
pragma[nomagic]
predicate uncertainWriteDefinitionInput(UncertainWriteDefinition def, Definition inp) {
lastRefRedef(inp, _, _, def)
}
private predicate adjacentDefReachesUncertainRead(
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2
) {
adjacentDefReachesRead(def, bb1, i1, bb2, i2) and
variableRead(bb2, i2, _, false)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `lastRefRedef`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate lastRefRedefNoUncertainReads(Definition def, BasicBlock bb, int i, Definition next) {
lastRefRedef(def, bb, i, next) and
not variableRead(bb, i, def.getSourceVariable(), false)
or
exists(BasicBlock bb0, int i0 |
lastRefRedef(def, bb0, i0, next) and
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Holds if the node at index `i` in `bb` is a last reference to SSA
* definition `def`.
*
* That is, the node can reach the end of the enclosing callable, or another
* SSA definition for the underlying source variable, without passing through
* another read.
*/
pragma[nomagic]
predicate lastRef(Definition def, BasicBlock bb, int i) {
// Can reach another definition
lastRefRedef(def, bb, i, _)
or
exists(SourceVariable v | lastSsaRef(def, v, bb, i) |
// Can reach exit directly
bb instanceof ExitBasicBlock
or
// Can reach a block using one or more steps, where `def` is no longer live
varBlockReachesExit(def, bb)
)
}
/**
* NB: If this predicate is exposed, it should be cached.
*
* Same as `lastRefRedef`, but ignores uncertain reads.
*/
pragma[nomagic]
predicate lastRefNoUncertainReads(Definition def, BasicBlock bb, int i) {
lastRef(def, bb, i) and
not variableRead(bb, i, def.getSourceVariable(), false)
or
exists(BasicBlock bb0, int i0 |
lastRef(def, bb0, i0) and
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
)
}
/** A static single assignment (SSA) definition. */
class Definition extends TDefinition {
/** Gets the source variable underlying this SSA definition. */
SourceVariable getSourceVariable() { this.definesAt(result, _, _) }
/**
* Holds if this SSA definition defines `v` at index `i` in basic block `bb`.
* Phi nodes are considered to be at index `-1`, while normal variable writes
* are at the index of the control flow node they wrap.
*/
final predicate definesAt(SourceVariable v, BasicBlock bb, int i) {
this = TWriteDef(v, bb, i)
or
this = TPhiNode(v, bb) and i = -1
}
/** Gets the basic block to which this SSA definition belongs. */
final BasicBlock getBasicBlock() { this.definesAt(_, result, _) }
/** Gets a textual representation of this SSA definition. */
string toString() { none() }
}
/** An SSA definition that corresponds to a write. */
class WriteDefinition extends Definition, TWriteDef {
private SourceVariable v;
private BasicBlock bb;
private int i;
WriteDefinition() { this = TWriteDef(v, bb, i) }
override string toString() { result = "WriteDef" }
}
/** A phi node. */
class PhiNode extends Definition, TPhiNode {
override string toString() { result = "Phi" }
}
/**
* An SSA definition that represents an uncertain update of the underlying
* source variable.
*/
class UncertainWriteDefinition extends WriteDefinition {
UncertainWriteDefinition() {
exists(SourceVariable v, BasicBlock bb, int i |
this.definesAt(v, bb, i) and
variableWrite(bb, i, v, false)
)
}
}
/** Provides a set of consistency queries. */
module Consistency {
abstract class RelevantDefinition extends Definition {
abstract predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
);
}
query predicate nonUniqueDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
ssaDefReachesRead(v, def, bb, i) and
not exists(unique(Definition def0 | ssaDefReachesRead(v, def0, bb, i)))
}
query predicate readWithoutDef(SourceVariable v, BasicBlock bb, int i) {
variableRead(bb, i, v, _) and
not ssaDefReachesRead(v, _, bb, i)
}
query predicate deadDef(RelevantDefinition def, SourceVariable v) {
v = def.getSourceVariable() and
not ssaDefReachesRead(_, def, _, _) and
not phiHasInputFromBlock(_, def, _) and
not uncertainWriteDefinitionInput(_, def)
}
query predicate notDominatedByDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
exists(BasicBlock bbDef, int iDef | def.definesAt(v, bbDef, iDef) |
ssaDefReachesReadWithinBlock(v, def, bb, i) and
(bb != bbDef or i < iDef)
or
ssaDefReachesRead(v, def, bb, i) and
not ssaDefReachesReadWithinBlock(v, def, bb, i) and
not def.definesAt(v, getImmediateBasicBlockDominator*(bb), _)
)
}
}

View File

@@ -1,51 +0,0 @@
/** Provides the C# specific parameters for `SsaImplCommon.qll`. */
private import csharp
private import AssignableDefinitions
class BasicBlock = ControlFlow::BasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock = ControlFlow::BasicBlocks::ExitBlock;
pragma[noinline]
private Callable getAnAssigningCallable(LocalScopeVariable v) {
result = any(AssignableDefinition def | def.getTarget() = v).getEnclosingCallable()
}
class SourceVariable extends LocalScopeVariable {
SourceVariable() { not getAnAssigningCallable(this) != getAnAssigningCallable(this) }
}
/**
* Holds if the `i`th node of basic block `bb` is assignable definition `def`,
* targeting local scope variable `v`.
*/
predicate definitionAt(AssignableDefinition def, BasicBlock bb, int i, SourceVariable v) {
bb.getNode(i) = def.getAControlFlowNode() and
v = def.getTarget() and
// In cases like `(x, x) = (0, 1)`, we discard the first (dead) definition of `x`
not exists(TupleAssignmentDefinition first, TupleAssignmentDefinition second | first = def |
second.getAssignment() = first.getAssignment() and
second.getEvaluationOrder() > first.getEvaluationOrder() and
second.getTarget() = v
)
}
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignableDefinition def |
definitionAt(def, bb, i, v) and
if def.isCertain() then certain = true else certain = false
)
}
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignableRead read |
read.getAControlFlowNode() = bb.getNode(i) and
read.getTarget() = v and
certain = true
)
}

View File

@@ -172,7 +172,12 @@ abstract class Configuration extends DataFlow::Configuration {
}
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
(
this.isSink(node) or
this.isSink(node, _) or
this.isAdditionalTaintStep(node, _) or
this.isAdditionalTaintStep(node, _, _, _)
) and
defaultImplicitTaintRead(node, c)
}

View File

@@ -172,7 +172,12 @@ abstract class Configuration extends DataFlow::Configuration {
}
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
(
this.isSink(node) or
this.isSink(node, _) or
this.isAdditionalTaintStep(node, _) or
this.isAdditionalTaintStep(node, _, _, _)
) and
defaultImplicitTaintRead(node, c)
}

View File

@@ -172,7 +172,12 @@ abstract class Configuration extends DataFlow::Configuration {
}
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
(
this.isSink(node) or
this.isSink(node, _) or
this.isAdditionalTaintStep(node, _) or
this.isAdditionalTaintStep(node, _, _, _)
) and
defaultImplicitTaintRead(node, c)
}

View File

@@ -172,7 +172,12 @@ abstract class Configuration extends DataFlow::Configuration {
}
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
(
this.isSink(node) or
this.isSink(node, _) or
this.isAdditionalTaintStep(node, _) or
this.isAdditionalTaintStep(node, _, _, _)
) and
defaultImplicitTaintRead(node, c)
}

View File

@@ -172,7 +172,12 @@ abstract class Configuration extends DataFlow::Configuration {
}
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
(
this.isSink(node) or
this.isSink(node, _) or
this.isAdditionalTaintStep(node, _) or
this.isAdditionalTaintStep(node, _, _, _)
) and
defaultImplicitTaintRead(node, c)
}

View File

@@ -1,9 +1,8 @@
/** Provides a module for importing negative models. */
/**
* A module importing all generated negative Models as Data models.
*/
import csharp
private module GeneratedFrameworks {
private import generated.dotnet.NegativeRuntime
}

View File

@@ -71,6 +71,8 @@ private class SystemArrayFlowModelCsv extends SummaryModelCsv {
row =
[
"System;Array;false;AsReadOnly<>;(T[]);;Argument[0].Element;ReturnValue.Element;value;manual",
"System;Array;false;Clear;(System.Array,System.Int32,System.Int32);;Argument[0].WithoutElement;Argument[0];value;manual",
"System;Array;false;Clear;(System.Array);;Argument[0].WithoutElement;Argument[0];value;manual",
"System;Array;false;Clone;();;Argument[0].Element;ReturnValue.Element;value;manual",
"System;Array;false;CopyTo;(System.Array,System.Int64);;Argument[this].Element;Argument[0].Element;value;manual",
"System;Array;false;Find<>;(T[],System.Predicate<T>);;Argument[0].Element;Argument[1].Parameter[0];value;manual",

View File

@@ -3237,7 +3237,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.CodeDom.Compiler;IndentedTextWriter;Close;();generated",
"System.CodeDom.Compiler;IndentedTextWriter;DisposeAsync;();generated",
"System.CodeDom.Compiler;IndentedTextWriter;Flush;();generated",
"System.CodeDom.Compiler;IndentedTextWriter;FlushAsync;();generated",
"System.CodeDom.Compiler;IndentedTextWriter;IndentedTextWriter;(System.IO.TextWriter);generated",
"System.CodeDom.Compiler;IndentedTextWriter;OutputTabs;();generated",
"System.CodeDom.Compiler;IndentedTextWriter;OutputTabsAsync;();generated",
@@ -3281,7 +3280,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.CodeDom.Compiler;IndentedTextWriter;WriteLineAsync;(System.String);generated",
"System.CodeDom.Compiler;IndentedTextWriter;WriteLineAsync;(System.Text.StringBuilder,System.Threading.CancellationToken);generated",
"System.CodeDom.Compiler;IndentedTextWriter;WriteLineNoTabs;(System.String);generated",
"System.CodeDom.Compiler;IndentedTextWriter;WriteLineNoTabsAsync;(System.String);generated",
"System.CodeDom.Compiler;IndentedTextWriter;get_Indent;();generated",
"System.CodeDom.Compiler;IndentedTextWriter;set_Indent;(System.Int32);generated",
"System.CodeDom.Compiler;TempFileCollection;AddFile;(System.String,System.Boolean);generated",
@@ -3459,7 +3457,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.CodeDom;CodeNamespaceImport;set_LinePragma;(System.CodeDom.CodeLinePragma);generated",
"System.CodeDom;CodeNamespaceImportCollection;Clear;();generated",
"System.CodeDom;CodeNamespaceImportCollection;Contains;(System.Object);generated",
"System.CodeDom;CodeNamespaceImportCollection;GetEnumerator;();generated",
"System.CodeDom;CodeNamespaceImportCollection;IndexOf;(System.Object);generated",
"System.CodeDom;CodeNamespaceImportCollection;Remove;(System.Object);generated",
"System.CodeDom;CodeNamespaceImportCollection;RemoveAt;(System.Int32);generated",
@@ -3612,7 +3609,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Concurrent;ConcurrentDictionary<,>;Contains;(System.Collections.Generic.KeyValuePair<TKey,TValue>);generated",
"System.Collections.Concurrent;ConcurrentDictionary<,>;Contains;(System.Object);generated",
"System.Collections.Concurrent;ConcurrentDictionary<,>;ContainsKey;(TKey);generated",
"System.Collections.Concurrent;ConcurrentDictionary<,>;GetEnumerator;();generated",
"System.Collections.Concurrent;ConcurrentDictionary<,>;Remove;(System.Collections.Generic.KeyValuePair<TKey,TValue>);generated",
"System.Collections.Concurrent;ConcurrentDictionary<,>;Remove;(System.Object);generated",
"System.Collections.Concurrent;ConcurrentDictionary<,>;Remove;(TKey);generated",
@@ -3676,9 +3672,7 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Generic;ByteEqualityComparer;Equals;(System.Object);generated",
"System.Collections.Generic;ByteEqualityComparer;GetHashCode;();generated",
"System.Collections.Generic;ByteEqualityComparer;GetHashCode;(System.Byte);generated",
"System.Collections.Generic;CollectionExtensions;AsReadOnly<,>;(System.Collections.Generic.IDictionary<TKey,TValue>);generated",
"System.Collections.Generic;CollectionExtensions;GetValueOrDefault<,>;(System.Collections.Generic.IReadOnlyDictionary<TKey,TValue>,TKey);generated",
"System.Collections.Generic;CollectionExtensions;TryAdd<,>;(System.Collections.Generic.IDictionary<TKey,TValue>,TKey,TValue);generated",
"System.Collections.Generic;Comparer<>;Compare;(System.Object,System.Object);generated",
"System.Collections.Generic;Comparer<>;Compare;(T,T);generated",
"System.Collections.Generic;Comparer<>;get_Default;();generated",
@@ -3819,7 +3813,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Generic;KeyNotFoundException;KeyNotFoundException;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated",
"System.Collections.Generic;KeyNotFoundException;KeyNotFoundException;(System.String);generated",
"System.Collections.Generic;KeyNotFoundException;KeyNotFoundException;(System.String,System.Exception);generated",
"System.Collections.Generic;KeyValuePair;Create<,>;(TKey,TValue);generated",
"System.Collections.Generic;KeyValuePair<,>;ToString;();generated",
"System.Collections.Generic;LinkedList<>+Enumerator;Dispose;();generated",
"System.Collections.Generic;LinkedList<>+Enumerator;GetObjectData;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated",
@@ -4172,9 +4165,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Immutable;ImmutableDictionary;CreateBuilder<,>;();generated",
"System.Collections.Immutable;ImmutableDictionary;CreateBuilder<,>;(System.Collections.Generic.IEqualityComparer<TKey>);generated",
"System.Collections.Immutable;ImmutableDictionary;CreateBuilder<,>;(System.Collections.Generic.IEqualityComparer<TKey>,System.Collections.Generic.IEqualityComparer<TValue>);generated",
"System.Collections.Immutable;ImmutableDictionary;CreateRange<,>;(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>);generated",
"System.Collections.Immutable;ImmutableDictionary;CreateRange<,>;(System.Collections.Generic.IEqualityComparer<TKey>,System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>);generated",
"System.Collections.Immutable;ImmutableDictionary;CreateRange<,>;(System.Collections.Generic.IEqualityComparer<TKey>,System.Collections.Generic.IEqualityComparer<TValue>,System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>);generated",
"System.Collections.Immutable;ImmutableDictionary;GetValueOrDefault<,>;(System.Collections.Immutable.IImmutableDictionary<TKey,TValue>,TKey);generated",
"System.Collections.Immutable;ImmutableDictionary<,>+Builder;Clear;();generated",
"System.Collections.Immutable;ImmutableDictionary<,>+Builder;Contains;(System.Collections.Generic.KeyValuePair<TKey,TValue>);generated",
@@ -4264,10 +4254,8 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Immutable;ImmutableInterlocked;TryRemove<,>;(System.Collections.Immutable.ImmutableDictionary<TKey,TValue>,TKey,TValue);generated",
"System.Collections.Immutable;ImmutableInterlocked;TryUpdate<,>;(System.Collections.Immutable.ImmutableDictionary<TKey,TValue>,TKey,TValue,TValue);generated",
"System.Collections.Immutable;ImmutableList;Create<>;();generated",
"System.Collections.Immutable;ImmutableList;Create<>;(T);generated",
"System.Collections.Immutable;ImmutableList;Create<>;(T[]);generated",
"System.Collections.Immutable;ImmutableList;CreateBuilder<>;();generated",
"System.Collections.Immutable;ImmutableList;CreateRange<>;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableList;IndexOf<>;(System.Collections.Immutable.IImmutableList<T>,T);generated",
"System.Collections.Immutable;ImmutableList;IndexOf<>;(System.Collections.Immutable.IImmutableList<T>,T,System.Collections.Generic.IEqualityComparer<T>);generated",
"System.Collections.Immutable;ImmutableList;IndexOf<>;(System.Collections.Immutable.IImmutableList<T>,T,System.Int32);generated",
@@ -4331,9 +4319,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Immutable;ImmutableQueue<>;get_IsEmpty;();generated",
"System.Collections.Immutable;ImmutableSortedDictionary;Create<,>;();generated",
"System.Collections.Immutable;ImmutableSortedDictionary;CreateBuilder<,>;();generated",
"System.Collections.Immutable;ImmutableSortedDictionary;CreateRange<,>;(System.Collections.Generic.IComparer<TKey>,System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>);generated",
"System.Collections.Immutable;ImmutableSortedDictionary;CreateRange<,>;(System.Collections.Generic.IComparer<TKey>,System.Collections.Generic.IEqualityComparer<TValue>,System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>);generated",
"System.Collections.Immutable;ImmutableSortedDictionary;CreateRange<,>;(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>);generated",
"System.Collections.Immutable;ImmutableSortedDictionary<,>+Builder;Clear;();generated",
"System.Collections.Immutable;ImmutableSortedDictionary<,>+Builder;Contains;(System.Collections.Generic.KeyValuePair<TKey,TValue>);generated",
"System.Collections.Immutable;ImmutableSortedDictionary<,>+Builder;Contains;(System.Object);generated",
@@ -4353,7 +4338,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Immutable;ImmutableSortedDictionary<,>+Enumerator;Dispose;();generated",
"System.Collections.Immutable;ImmutableSortedDictionary<,>+Enumerator;MoveNext;();generated",
"System.Collections.Immutable;ImmutableSortedDictionary<,>+Enumerator;Reset;();generated",
"System.Collections.Immutable;ImmutableSortedDictionary<,>+Enumerator;get_Current;();generated",
"System.Collections.Immutable;ImmutableSortedDictionary<,>;Clear;();generated",
"System.Collections.Immutable;ImmutableSortedDictionary<,>;Contains;(System.Collections.Generic.KeyValuePair<TKey,TValue>);generated",
"System.Collections.Immutable;ImmutableSortedDictionary<,>;Contains;(System.Object);generated",
@@ -4370,8 +4354,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Immutable;ImmutableSortedDictionary<,>;get_IsReadOnly;();generated",
"System.Collections.Immutable;ImmutableSortedDictionary<,>;get_IsSynchronized;();generated",
"System.Collections.Immutable;ImmutableSortedSet;Create<>;();generated",
"System.Collections.Immutable;ImmutableSortedSet;Create<>;(System.Collections.Generic.IComparer<T>,T);generated",
"System.Collections.Immutable;ImmutableSortedSet;Create<>;(T);generated",
"System.Collections.Immutable;ImmutableSortedSet;Create<>;(T[]);generated",
"System.Collections.Immutable;ImmutableSortedSet;CreateBuilder<>;();generated",
"System.Collections.Immutable;ImmutableSortedSet<>+Builder;Clear;();generated",
@@ -4385,7 +4367,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Immutable;ImmutableSortedSet<>+Builder;Overlaps;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>+Builder;Remove;(T);generated",
"System.Collections.Immutable;ImmutableSortedSet<>+Builder;SetEquals;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>+Builder;SymmetricExceptWith;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>+Builder;get_Count;();generated",
"System.Collections.Immutable;ImmutableSortedSet<>+Builder;get_IsReadOnly;();generated",
"System.Collections.Immutable;ImmutableSortedSet<>+Builder;get_IsSynchronized;();generated",
@@ -4399,7 +4380,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Immutable;ImmutableSortedSet<>;ExceptWith;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;IndexOf;(System.Object);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;IndexOf;(T);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;Intersect;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;IntersectWith;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;IsProperSubsetOf;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;IsProperSupersetOf;(System.Collections.Generic.IEnumerable<T>);generated",
@@ -4411,7 +4391,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Collections.Immutable;ImmutableSortedSet<>;Remove;(T);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;RemoveAt;(System.Int32);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;SetEquals;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;SymmetricExcept;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;SymmetricExceptWith;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;UnionWith;(System.Collections.Generic.IEnumerable<T>);generated",
"System.Collections.Immutable;ImmutableSortedSet<>;get_Count;();generated",
@@ -4819,7 +4798,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.ComponentModel.Composition.Hosting;AggregateCatalog;AggregateCatalog;(System.Collections.Generic.IEnumerable<System.ComponentModel.Composition.Primitives.ComposablePartCatalog>);generated",
"System.ComponentModel.Composition.Hosting;AggregateCatalog;AggregateCatalog;(System.ComponentModel.Composition.Primitives.ComposablePartCatalog[]);generated",
"System.ComponentModel.Composition.Hosting;AggregateCatalog;Dispose;(System.Boolean);generated",
"System.ComponentModel.Composition.Hosting;AggregateCatalog;GetExports;(System.ComponentModel.Composition.Primitives.ImportDefinition);generated",
"System.ComponentModel.Composition.Hosting;AggregateCatalog;OnChanged;(System.ComponentModel.Composition.Hosting.ComposablePartCatalogChangeEventArgs);generated",
"System.ComponentModel.Composition.Hosting;AggregateCatalog;OnChanging;(System.ComponentModel.Composition.Hosting.ComposablePartCatalogChangeEventArgs);generated",
"System.ComponentModel.Composition.Hosting;AggregateExportProvider;AggregateExportProvider;(System.Collections.Generic.IEnumerable<System.ComponentModel.Composition.Hosting.ExportProvider>);generated",
@@ -4827,13 +4805,11 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.ComponentModel.Composition.Hosting;AggregateExportProvider;Dispose;(System.Boolean);generated",
"System.ComponentModel.Composition.Hosting;ApplicationCatalog;ApplicationCatalog;();generated",
"System.ComponentModel.Composition.Hosting;ApplicationCatalog;Dispose;(System.Boolean);generated",
"System.ComponentModel.Composition.Hosting;ApplicationCatalog;GetExports;(System.ComponentModel.Composition.Primitives.ImportDefinition);generated",
"System.ComponentModel.Composition.Hosting;ApplicationCatalog;ToString;();generated",
"System.ComponentModel.Composition.Hosting;ApplicationCatalog;get_DisplayName;();generated",
"System.ComponentModel.Composition.Hosting;ApplicationCatalog;get_Origin;();generated",
"System.ComponentModel.Composition.Hosting;AssemblyCatalog;AssemblyCatalog;(System.String);generated",
"System.ComponentModel.Composition.Hosting;AssemblyCatalog;Dispose;(System.Boolean);generated",
"System.ComponentModel.Composition.Hosting;AssemblyCatalog;GetExports;(System.ComponentModel.Composition.Primitives.ImportDefinition);generated",
"System.ComponentModel.Composition.Hosting;AssemblyCatalog;get_Origin;();generated",
"System.ComponentModel.Composition.Hosting;AtomicComposition;AtomicComposition;();generated",
"System.ComponentModel.Composition.Hosting;AtomicComposition;Complete;();generated",
@@ -4869,7 +4845,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.ComponentModel.Composition.Hosting;CompositionContainer;SatisfyImportsOnce;(System.ComponentModel.Composition.Primitives.ComposablePart);generated",
"System.ComponentModel.Composition.Hosting;CompositionScopeDefinition;CompositionScopeDefinition;();generated",
"System.ComponentModel.Composition.Hosting;CompositionScopeDefinition;Dispose;(System.Boolean);generated",
"System.ComponentModel.Composition.Hosting;CompositionScopeDefinition;GetExports;(System.ComponentModel.Composition.Primitives.ImportDefinition);generated",
"System.ComponentModel.Composition.Hosting;CompositionScopeDefinition;OnChanged;(System.ComponentModel.Composition.Hosting.ComposablePartCatalogChangeEventArgs);generated",
"System.ComponentModel.Composition.Hosting;CompositionScopeDefinition;OnChanging;(System.ComponentModel.Composition.Hosting.ComposablePartCatalogChangeEventArgs);generated",
"System.ComponentModel.Composition.Hosting;CompositionService;Dispose;();generated",
@@ -4879,7 +4854,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.ComponentModel.Composition.Hosting;DirectoryCatalog;DirectoryCatalog;(System.String,System.Reflection.ReflectionContext);generated",
"System.ComponentModel.Composition.Hosting;DirectoryCatalog;DirectoryCatalog;(System.String,System.Reflection.ReflectionContext,System.ComponentModel.Composition.Primitives.ICompositionElement);generated",
"System.ComponentModel.Composition.Hosting;DirectoryCatalog;Dispose;(System.Boolean);generated",
"System.ComponentModel.Composition.Hosting;DirectoryCatalog;GetExports;(System.ComponentModel.Composition.Primitives.ImportDefinition);generated",
"System.ComponentModel.Composition.Hosting;DirectoryCatalog;OnChanged;(System.ComponentModel.Composition.Hosting.ComposablePartCatalogChangeEventArgs);generated",
"System.ComponentModel.Composition.Hosting;DirectoryCatalog;OnChanging;(System.ComponentModel.Composition.Hosting.ComposablePartCatalogChangeEventArgs);generated",
"System.ComponentModel.Composition.Hosting;DirectoryCatalog;Refresh;();generated",
@@ -4902,7 +4876,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.ComponentModel.Composition.Hosting;ExportsChangeEventArgs;get_AtomicComposition;();generated",
"System.ComponentModel.Composition.Hosting;ExportsChangeEventArgs;set_AtomicComposition;(System.ComponentModel.Composition.Hosting.AtomicComposition);generated",
"System.ComponentModel.Composition.Hosting;FilteredCatalog;Dispose;(System.Boolean);generated",
"System.ComponentModel.Composition.Hosting;FilteredCatalog;GetExports;(System.ComponentModel.Composition.Primitives.ImportDefinition);generated",
"System.ComponentModel.Composition.Hosting;FilteredCatalog;IncludeDependencies;();generated",
"System.ComponentModel.Composition.Hosting;FilteredCatalog;IncludeDependents;();generated",
"System.ComponentModel.Composition.Hosting;FilteredCatalog;OnChanged;(System.ComponentModel.Composition.Hosting.ComposablePartCatalogChangeEventArgs);generated",
@@ -4936,7 +4909,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.ComponentModel.Composition.Primitives;ComposablePartCatalog;ComposablePartCatalog;();generated",
"System.ComponentModel.Composition.Primitives;ComposablePartCatalog;Dispose;();generated",
"System.ComponentModel.Composition.Primitives;ComposablePartCatalog;Dispose;(System.Boolean);generated",
"System.ComponentModel.Composition.Primitives;ComposablePartCatalog;GetExports;(System.ComponentModel.Composition.Primitives.ImportDefinition);generated",
"System.ComponentModel.Composition.Primitives;ComposablePartDefinition;ComposablePartDefinition;();generated",
"System.ComponentModel.Composition.Primitives;ComposablePartDefinition;CreatePart;();generated",
"System.ComponentModel.Composition.Primitives;ComposablePartDefinition;get_ExportDefinitions;();generated",
@@ -6364,7 +6336,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.ComponentModel;TypeConverter+SimplePropertyDescriptor;get_ComponentType;();generated",
"System.ComponentModel;TypeConverter+SimplePropertyDescriptor;get_IsReadOnly;();generated",
"System.ComponentModel;TypeConverter+SimplePropertyDescriptor;get_PropertyType;();generated",
"System.ComponentModel;TypeConverter+StandardValuesCollection;GetEnumerator;();generated",
"System.ComponentModel;TypeConverter+StandardValuesCollection;get_Count;();generated",
"System.ComponentModel;TypeConverter+StandardValuesCollection;get_IsSynchronized;();generated",
"System.ComponentModel;TypeConverter+StandardValuesCollection;get_SyncRoot;();generated",
@@ -7511,14 +7482,9 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Data.Common;DbCommand;DbCommand;();generated",
"System.Data.Common;DbCommand;DisposeAsync;();generated",
"System.Data.Common;DbCommand;ExecuteDbDataReader;(System.Data.CommandBehavior);generated",
"System.Data.Common;DbCommand;ExecuteDbDataReaderAsync;(System.Data.CommandBehavior,System.Threading.CancellationToken);generated",
"System.Data.Common;DbCommand;ExecuteNonQuery;();generated",
"System.Data.Common;DbCommand;ExecuteNonQueryAsync;();generated",
"System.Data.Common;DbCommand;ExecuteNonQueryAsync;(System.Threading.CancellationToken);generated",
"System.Data.Common;DbCommand;ExecuteReaderAsync;();generated",
"System.Data.Common;DbCommand;ExecuteReaderAsync;(System.Data.CommandBehavior);generated",
"System.Data.Common;DbCommand;ExecuteReaderAsync;(System.Data.CommandBehavior,System.Threading.CancellationToken);generated",
"System.Data.Common;DbCommand;ExecuteReaderAsync;(System.Threading.CancellationToken);generated",
"System.Data.Common;DbCommand;ExecuteScalar;();generated",
"System.Data.Common;DbCommand;ExecuteScalarAsync;();generated",
"System.Data.Common;DbCommand;ExecuteScalarAsync;(System.Threading.CancellationToken);generated",
@@ -7602,7 +7568,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Data.Common;DbConnectionStringBuilder;GetDefaultEvent;();generated",
"System.Data.Common;DbConnectionStringBuilder;GetDefaultProperty;();generated",
"System.Data.Common;DbConnectionStringBuilder;GetEditor;(System.Type);generated",
"System.Data.Common;DbConnectionStringBuilder;GetEnumerator;();generated",
"System.Data.Common;DbConnectionStringBuilder;GetEvents;();generated",
"System.Data.Common;DbConnectionStringBuilder;GetEvents;(System.Attribute[]);generated",
"System.Data.Common;DbConnectionStringBuilder;GetProperties;(System.Collections.Hashtable);generated",
@@ -7670,8 +7635,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Data.Common;DbDataReader;GetDecimal;(System.Int32);generated",
"System.Data.Common;DbDataReader;GetDouble;(System.Int32);generated",
"System.Data.Common;DbDataReader;GetFieldType;(System.Int32);generated",
"System.Data.Common;DbDataReader;GetFieldValueAsync<>;(System.Int32);generated",
"System.Data.Common;DbDataReader;GetFieldValueAsync<>;(System.Int32,System.Threading.CancellationToken);generated",
"System.Data.Common;DbDataReader;GetFloat;(System.Int32);generated",
"System.Data.Common;DbDataReader;GetGuid;(System.Int32);generated",
"System.Data.Common;DbDataReader;GetInt16;(System.Int32);generated",
@@ -7681,7 +7644,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Data.Common;DbDataReader;GetOrdinal;(System.String);generated",
"System.Data.Common;DbDataReader;GetProviderSpecificFieldType;(System.Int32);generated",
"System.Data.Common;DbDataReader;GetSchemaTable;();generated",
"System.Data.Common;DbDataReader;GetSchemaTableAsync;(System.Threading.CancellationToken);generated",
"System.Data.Common;DbDataReader;GetStream;(System.Int32);generated",
"System.Data.Common;DbDataReader;GetString;(System.Int32);generated",
"System.Data.Common;DbDataReader;GetValue;(System.Int32);generated",
@@ -8993,9 +8955,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Data;DataColumnChangeEventArgs;get_ProposedValue;();generated",
"System.Data;DataColumnChangeEventArgs;get_Row;();generated",
"System.Data;DataColumnChangeEventArgs;set_ProposedValue;(System.Object);generated",
"System.Data;DataColumnCollection;Add;();generated",
"System.Data;DataColumnCollection;Add;(System.String,System.Type);generated",
"System.Data;DataColumnCollection;Add;(System.String,System.Type,System.String);generated",
"System.Data;DataColumnCollection;CanRemove;(System.Data.DataColumn);generated",
"System.Data;DataColumnCollection;Clear;();generated",
"System.Data;DataColumnCollection;Contains;(System.String);generated",
@@ -9018,7 +8977,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Data;DataReaderExtensions;GetDecimal;(System.Data.Common.DbDataReader,System.String);generated",
"System.Data;DataReaderExtensions;GetDouble;(System.Data.Common.DbDataReader,System.String);generated",
"System.Data;DataReaderExtensions;GetFieldType;(System.Data.Common.DbDataReader,System.String);generated",
"System.Data;DataReaderExtensions;GetFieldValueAsync<>;(System.Data.Common.DbDataReader,System.String,System.Threading.CancellationToken);generated",
"System.Data;DataReaderExtensions;GetFloat;(System.Data.Common.DbDataReader,System.String);generated",
"System.Data;DataReaderExtensions;GetInt16;(System.Data.Common.DbDataReader,System.String);generated",
"System.Data;DataReaderExtensions;GetInt32;(System.Data.Common.DbDataReader,System.String);generated",
@@ -9036,10 +8994,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Data;DataRelation;get_Nested;();generated",
"System.Data;DataRelation;get_ParentTable;();generated",
"System.Data;DataRelation;set_Nested;(System.Boolean);generated",
"System.Data;DataRelationCollection;Add;(System.Data.DataColumn,System.Data.DataColumn);generated",
"System.Data;DataRelationCollection;Add;(System.Data.DataColumn[],System.Data.DataColumn[]);generated",
"System.Data;DataRelationCollection;Add;(System.String,System.Data.DataColumn,System.Data.DataColumn);generated",
"System.Data;DataRelationCollection;Add;(System.String,System.Data.DataColumn[],System.Data.DataColumn[]);generated",
"System.Data;DataRelationCollection;AddCore;(System.Data.DataRelation);generated",
"System.Data;DataRelationCollection;CanRemove;(System.Data.DataRelation);generated",
"System.Data;DataRelationCollection;Clear;();generated",
@@ -9286,7 +9240,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Data;DataTableClearEventArgs;get_Table;();generated",
"System.Data;DataTableClearEventArgs;get_TableName;();generated",
"System.Data;DataTableClearEventArgs;get_TableNamespace;();generated",
"System.Data;DataTableCollection;Add;();generated",
"System.Data;DataTableCollection;CanRemove;(System.Data.DataTable);generated",
"System.Data;DataTableCollection;Clear;();generated",
"System.Data;DataTableCollection;Contains;(System.String);generated",
@@ -13442,19 +13395,15 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Drawing.Printing;PrinterResolution;set_X;(System.Int32);generated",
"System.Drawing.Printing;PrinterResolution;set_Y;(System.Int32);generated",
"System.Drawing.Printing;PrinterSettings+PaperSizeCollection;CopyTo;(System.Drawing.Printing.PaperSize[],System.Int32);generated",
"System.Drawing.Printing;PrinterSettings+PaperSizeCollection;GetEnumerator;();generated",
"System.Drawing.Printing;PrinterSettings+PaperSizeCollection;get_Count;();generated",
"System.Drawing.Printing;PrinterSettings+PaperSizeCollection;get_IsSynchronized;();generated",
"System.Drawing.Printing;PrinterSettings+PaperSourceCollection;CopyTo;(System.Drawing.Printing.PaperSource[],System.Int32);generated",
"System.Drawing.Printing;PrinterSettings+PaperSourceCollection;GetEnumerator;();generated",
"System.Drawing.Printing;PrinterSettings+PaperSourceCollection;get_Count;();generated",
"System.Drawing.Printing;PrinterSettings+PaperSourceCollection;get_IsSynchronized;();generated",
"System.Drawing.Printing;PrinterSettings+PrinterResolutionCollection;CopyTo;(System.Drawing.Printing.PrinterResolution[],System.Int32);generated",
"System.Drawing.Printing;PrinterSettings+PrinterResolutionCollection;GetEnumerator;();generated",
"System.Drawing.Printing;PrinterSettings+PrinterResolutionCollection;get_Count;();generated",
"System.Drawing.Printing;PrinterSettings+PrinterResolutionCollection;get_IsSynchronized;();generated",
"System.Drawing.Printing;PrinterSettings+StringCollection;CopyTo;(System.String[],System.Int32);generated",
"System.Drawing.Printing;PrinterSettings+StringCollection;GetEnumerator;();generated",
"System.Drawing.Printing;PrinterSettings+StringCollection;get_Count;();generated",
"System.Drawing.Printing;PrinterSettings+StringCollection;get_IsSynchronized;();generated",
"System.Drawing.Printing;PrinterSettings;Clone;();generated",
@@ -15785,12 +15734,10 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.IO.Compression;DeflateStream;EndWrite;(System.IAsyncResult);generated",
"System.IO.Compression;DeflateStream;Flush;();generated",
"System.IO.Compression;DeflateStream;Read;(System.Span<System.Byte>);generated",
"System.IO.Compression;DeflateStream;ReadAsync;(System.Memory<System.Byte>,System.Threading.CancellationToken);generated",
"System.IO.Compression;DeflateStream;ReadByte;();generated",
"System.IO.Compression;DeflateStream;Seek;(System.Int64,System.IO.SeekOrigin);generated",
"System.IO.Compression;DeflateStream;SetLength;(System.Int64);generated",
"System.IO.Compression;DeflateStream;Write;(System.ReadOnlySpan<System.Byte>);generated",
"System.IO.Compression;DeflateStream;WriteAsync;(System.ReadOnlyMemory<System.Byte>,System.Threading.CancellationToken);generated",
"System.IO.Compression;DeflateStream;WriteByte;(System.Byte);generated",
"System.IO.Compression;DeflateStream;get_CanRead;();generated",
"System.IO.Compression;DeflateStream;get_CanSeek;();generated",
@@ -15806,12 +15753,10 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.IO.Compression;GZipStream;GZipStream;(System.IO.Stream,System.IO.Compression.CompressionLevel);generated",
"System.IO.Compression;GZipStream;GZipStream;(System.IO.Stream,System.IO.Compression.CompressionMode);generated",
"System.IO.Compression;GZipStream;Read;(System.Span<System.Byte>);generated",
"System.IO.Compression;GZipStream;ReadAsync;(System.Memory<System.Byte>,System.Threading.CancellationToken);generated",
"System.IO.Compression;GZipStream;ReadByte;();generated",
"System.IO.Compression;GZipStream;Seek;(System.Int64,System.IO.SeekOrigin);generated",
"System.IO.Compression;GZipStream;SetLength;(System.Int64);generated",
"System.IO.Compression;GZipStream;Write;(System.ReadOnlySpan<System.Byte>);generated",
"System.IO.Compression;GZipStream;WriteAsync;(System.ReadOnlyMemory<System.Byte>,System.Threading.CancellationToken);generated",
"System.IO.Compression;GZipStream;WriteByte;(System.Byte);generated",
"System.IO.Compression;GZipStream;get_CanRead;();generated",
"System.IO.Compression;GZipStream;get_CanSeek;();generated",
@@ -16383,7 +16328,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.IO;BinaryWriter;BinaryWriter;(System.IO.Stream,System.Text.Encoding);generated",
"System.IO;BinaryWriter;Close;();generated", "System.IO;BinaryWriter;Dispose;();generated",
"System.IO;BinaryWriter;Dispose;(System.Boolean);generated",
"System.IO;BinaryWriter;DisposeAsync;();generated",
"System.IO;BinaryWriter;Flush;();generated",
"System.IO;BinaryWriter;Seek;(System.Int32,System.IO.SeekOrigin);generated",
"System.IO;BinaryWriter;Write7BitEncodedInt64;(System.Int64);generated",
@@ -16774,18 +16718,14 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.IO;Stream;DisposeAsync;();generated",
"System.IO;Stream;EndRead;(System.IAsyncResult);generated",
"System.IO;Stream;EndWrite;(System.IAsyncResult);generated",
"System.IO;Stream;Flush;();generated", "System.IO;Stream;FlushAsync;();generated",
"System.IO;Stream;FlushAsync;(System.Threading.CancellationToken);generated",
"System.IO;Stream;ObjectInvariant;();generated",
"System.IO;Stream;Flush;();generated", "System.IO;Stream;ObjectInvariant;();generated",
"System.IO;Stream;Read;(System.Span<System.Byte>);generated",
"System.IO;Stream;ReadAsync;(System.Memory<System.Byte>,System.Threading.CancellationToken);generated",
"System.IO;Stream;ReadByte;();generated",
"System.IO;Stream;Seek;(System.Int64,System.IO.SeekOrigin);generated",
"System.IO;Stream;SetLength;(System.Int64);generated",
"System.IO;Stream;ValidateBufferArguments;(System.Byte[],System.Int32,System.Int32);generated",
"System.IO;Stream;ValidateCopyToArguments;(System.IO.Stream,System.Int32);generated",
"System.IO;Stream;Write;(System.ReadOnlySpan<System.Byte>);generated",
"System.IO;Stream;WriteAsync;(System.ReadOnlyMemory<System.Byte>,System.Threading.CancellationToken);generated",
"System.IO;Stream;WriteByte;(System.Byte);generated",
"System.IO;Stream;get_CanRead;();generated", "System.IO;Stream;get_CanSeek;();generated",
"System.IO;Stream;get_CanTimeout;();generated",
@@ -16805,7 +16745,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.IO;StreamWriter;Dispose;(System.Boolean);generated",
"System.IO;StreamWriter;DisposeAsync;();generated",
"System.IO;StreamWriter;Flush;();generated",
"System.IO;StreamWriter;FlushAsync;();generated",
"System.IO;StreamWriter;StreamWriter;(System.IO.Stream);generated",
"System.IO;StreamWriter;StreamWriter;(System.IO.Stream,System.Text.Encoding);generated",
"System.IO;StreamWriter;StreamWriter;(System.IO.Stream,System.Text.Encoding,System.Int32);generated",
@@ -16824,15 +16763,8 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.IO;StreamWriter;Write;(System.String,System.Object,System.Object);generated",
"System.IO;StreamWriter;Write;(System.String,System.Object,System.Object,System.Object);generated",
"System.IO;StreamWriter;Write;(System.String,System.Object[]);generated",
"System.IO;StreamWriter;WriteAsync;(System.Char);generated",
"System.IO;StreamWriter;WriteAsync;(System.Char[],System.Int32,System.Int32);generated",
"System.IO;StreamWriter;WriteAsync;(System.String);generated",
"System.IO;StreamWriter;WriteLine;(System.ReadOnlySpan<System.Char>);generated",
"System.IO;StreamWriter;WriteLine;(System.String);generated",
"System.IO;StreamWriter;WriteLineAsync;();generated",
"System.IO;StreamWriter;WriteLineAsync;(System.Char);generated",
"System.IO;StreamWriter;WriteLineAsync;(System.Char[],System.Int32,System.Int32);generated",
"System.IO;StreamWriter;WriteLineAsync;(System.String);generated",
"System.IO;StreamWriter;get_AutoFlush;();generated",
"System.IO;StreamWriter;set_AutoFlush;(System.Boolean);generated",
"System.IO;StringReader;Close;();generated",
@@ -16845,10 +16777,8 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.IO;StringWriter;StringWriter;(System.Text.StringBuilder);generated",
"System.IO;StringWriter;Write;(System.Char);generated",
"System.IO;StringWriter;Write;(System.ReadOnlySpan<System.Char>);generated",
"System.IO;StringWriter;Write;(System.Text.StringBuilder);generated",
"System.IO;StringWriter;WriteAsync;(System.Char);generated",
"System.IO;StringWriter;WriteLine;(System.ReadOnlySpan<System.Char>);generated",
"System.IO;StringWriter;WriteLine;(System.Text.StringBuilder);generated",
"System.IO;StringWriter;WriteLineAsync;(System.Char);generated",
"System.IO;StringWriter;get_Encoding;();generated",
"System.IO;TextReader;Close;();generated", "System.IO;TextReader;Dispose;();generated",
@@ -16857,7 +16787,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.IO;TextWriter;Close;();generated", "System.IO;TextWriter;Dispose;();generated",
"System.IO;TextWriter;Dispose;(System.Boolean);generated",
"System.IO;TextWriter;DisposeAsync;();generated", "System.IO;TextWriter;Flush;();generated",
"System.IO;TextWriter;FlushAsync;();generated",
"System.IO;TextWriter;TextWriter;();generated",
"System.IO;TextWriter;Write;(System.Boolean);generated",
"System.IO;TextWriter;Write;(System.Char);generated",
@@ -16872,9 +16801,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.IO;TextWriter;Write;(System.Text.StringBuilder);generated",
"System.IO;TextWriter;Write;(System.UInt32);generated",
"System.IO;TextWriter;Write;(System.UInt64);generated",
"System.IO;TextWriter;WriteAsync;(System.Char);generated",
"System.IO;TextWriter;WriteAsync;(System.Char[],System.Int32,System.Int32);generated",
"System.IO;TextWriter;WriteAsync;(System.String);generated",
"System.IO;TextWriter;WriteLine;();generated",
"System.IO;TextWriter;WriteLine;(System.Boolean);generated",
"System.IO;TextWriter;WriteLine;(System.Char);generated",
@@ -16884,13 +16810,8 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.IO;TextWriter;WriteLine;(System.Int64);generated",
"System.IO;TextWriter;WriteLine;(System.ReadOnlySpan<System.Char>);generated",
"System.IO;TextWriter;WriteLine;(System.Single);generated",
"System.IO;TextWriter;WriteLine;(System.Text.StringBuilder);generated",
"System.IO;TextWriter;WriteLine;(System.UInt32);generated",
"System.IO;TextWriter;WriteLine;(System.UInt64);generated",
"System.IO;TextWriter;WriteLineAsync;();generated",
"System.IO;TextWriter;WriteLineAsync;(System.Char);generated",
"System.IO;TextWriter;WriteLineAsync;(System.Char[],System.Int32,System.Int32);generated",
"System.IO;TextWriter;WriteLineAsync;(System.String);generated",
"System.IO;TextWriter;get_Encoding;();generated",
"System.IO;UnmanagedMemoryAccessor;Dispose;();generated",
"System.IO;UnmanagedMemoryAccessor;Dispose;(System.Boolean);generated",
@@ -18094,7 +18015,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net.Http.Headers;HttpHeadersNonValidated+Enumerator;Reset;();generated",
"System.Net.Http.Headers;HttpHeadersNonValidated;Contains;(System.String);generated",
"System.Net.Http.Headers;HttpHeadersNonValidated;ContainsKey;(System.String);generated",
"System.Net.Http.Headers;HttpHeadersNonValidated;GetEnumerator;();generated",
"System.Net.Http.Headers;HttpHeadersNonValidated;get_Count;();generated",
"System.Net.Http.Headers;HttpRequestHeaders;get_Accept;();generated",
"System.Net.Http.Headers;HttpRequestHeaders;get_AcceptCharset;();generated",
@@ -18283,7 +18203,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net.Http.Json;JsonContent;TryComputeLength;(System.Int64);generated",
"System.Net.Http.Json;JsonContent;get_ObjectType;();generated",
"System.Net.Http.Json;JsonContent;get_Value;();generated",
"System.Net.Http;ByteArrayContent;CreateContentReadStreamAsync;();generated",
"System.Net.Http;ByteArrayContent;TryComputeLength;(System.Int64);generated",
"System.Net.Http;DelegatingHandler;DelegatingHandler;();generated",
"System.Net.Http;DelegatingHandler;Dispose;(System.Boolean);generated",
@@ -18383,7 +18302,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net.Http;HttpClientHandler;set_UseDefaultCredentials;(System.Boolean);generated",
"System.Net.Http;HttpClientHandler;set_UseProxy;(System.Boolean);generated",
"System.Net.Http;HttpContent;CreateContentReadStreamAsync;();generated",
"System.Net.Http;HttpContent;CreateContentReadStreamAsync;(System.Threading.CancellationToken);generated",
"System.Net.Http;HttpContent;Dispose;();generated",
"System.Net.Http;HttpContent;Dispose;(System.Boolean);generated",
"System.Net.Http;HttpContent;HttpContent;();generated",
@@ -18472,7 +18390,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net.Http;MultipartContent;get_HeaderEncodingSelector;();generated",
"System.Net.Http;MultipartFormDataContent;MultipartFormDataContent;();generated",
"System.Net.Http;MultipartFormDataContent;MultipartFormDataContent;(System.String);generated",
"System.Net.Http;ReadOnlyMemoryContent;CreateContentReadStreamAsync;();generated",
"System.Net.Http;ReadOnlyMemoryContent;SerializeToStream;(System.IO.Stream,System.Net.TransportContext,System.Threading.CancellationToken);generated",
"System.Net.Http;ReadOnlyMemoryContent;SerializeToStreamAsync;(System.IO.Stream,System.Net.TransportContext);generated",
"System.Net.Http;ReadOnlyMemoryContent;SerializeToStreamAsync;(System.IO.Stream,System.Net.TransportContext,System.Threading.CancellationToken);generated",
@@ -19103,7 +19020,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net.Quic;QuicStreamAbortedException;QuicStreamAbortedException;(System.String,System.Int64);generated",
"System.Net.Quic;QuicStreamAbortedException;get_ErrorCode;();generated",
"System.Net.Security;AuthenticatedStream;Dispose;(System.Boolean);generated",
"System.Net.Security;AuthenticatedStream;DisposeAsync;();generated",
"System.Net.Security;AuthenticatedStream;get_IsAuthenticated;();generated",
"System.Net.Security;AuthenticatedStream;get_IsEncrypted;();generated",
"System.Net.Security;AuthenticatedStream;get_IsMutuallyAuthenticated;();generated",
@@ -19328,7 +19244,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net.Sockets;SendPacketsElement;set_MemoryBuffer;(System.Nullable<System.ReadOnlyMemory<System.Byte>>);generated",
"System.Net.Sockets;SendPacketsElement;set_OffsetLong;(System.Int64);generated",
"System.Net.Sockets;Socket;AcceptAsync;();generated",
"System.Net.Sockets;Socket;AcceptAsync;(System.Net.Sockets.Socket);generated",
"System.Net.Sockets;Socket;CancelConnectAsync;(System.Net.Sockets.SocketAsyncEventArgs);generated",
"System.Net.Sockets;Socket;Close;();generated",
"System.Net.Sockets;Socket;Close;(System.Int32);generated",
@@ -19343,7 +19258,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net.Sockets;Socket;DuplicateAndClose;(System.Int32);generated",
"System.Net.Sockets;Socket;EndAccept;(System.Byte[],System.IAsyncResult);generated",
"System.Net.Sockets;Socket;EndAccept;(System.Byte[],System.Int32,System.IAsyncResult);generated",
"System.Net.Sockets;Socket;EndAccept;(System.IAsyncResult);generated",
"System.Net.Sockets;Socket;EndConnect;(System.IAsyncResult);generated",
"System.Net.Sockets;Socket;EndDisconnect;(System.IAsyncResult);generated",
"System.Net.Sockets;Socket;EndReceive;(System.IAsyncResult);generated",
@@ -19378,10 +19292,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net.Sockets;Socket;ReceiveAsync;(System.ArraySegment<System.Byte>,System.Net.Sockets.SocketFlags);generated",
"System.Net.Sockets;Socket;ReceiveAsync;(System.Collections.Generic.IList<System.ArraySegment<System.Byte>>);generated",
"System.Net.Sockets;Socket;ReceiveAsync;(System.Collections.Generic.IList<System.ArraySegment<System.Byte>>,System.Net.Sockets.SocketFlags);generated",
"System.Net.Sockets;Socket;ReceiveFromAsync;(System.ArraySegment<System.Byte>,System.Net.EndPoint);generated",
"System.Net.Sockets;Socket;ReceiveFromAsync;(System.ArraySegment<System.Byte>,System.Net.Sockets.SocketFlags,System.Net.EndPoint);generated",
"System.Net.Sockets;Socket;ReceiveMessageFromAsync;(System.ArraySegment<System.Byte>,System.Net.EndPoint);generated",
"System.Net.Sockets;Socket;ReceiveMessageFromAsync;(System.ArraySegment<System.Byte>,System.Net.Sockets.SocketFlags,System.Net.EndPoint);generated",
"System.Net.Sockets;Socket;Select;(System.Collections.IList,System.Collections.IList,System.Collections.IList,System.Int32);generated",
"System.Net.Sockets;Socket;Send;(System.Byte[]);generated",
"System.Net.Sockets;Socket;Send;(System.Byte[],System.Int32,System.Int32,System.Net.Sockets.SocketFlags);generated",
@@ -19481,14 +19391,11 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net.Sockets;SocketInformation;set_Options;(System.Net.Sockets.SocketInformationOptions);generated",
"System.Net.Sockets;SocketInformation;set_ProtocolInformation;(System.Byte[]);generated",
"System.Net.Sockets;SocketTaskExtensions;AcceptAsync;(System.Net.Sockets.Socket);generated",
"System.Net.Sockets;SocketTaskExtensions;AcceptAsync;(System.Net.Sockets.Socket,System.Net.Sockets.Socket);generated",
"System.Net.Sockets;SocketTaskExtensions;ConnectAsync;(System.Net.Sockets.Socket,System.Net.IPAddress[],System.Int32);generated",
"System.Net.Sockets;SocketTaskExtensions;ConnectAsync;(System.Net.Sockets.Socket,System.Net.IPAddress[],System.Int32,System.Threading.CancellationToken);generated",
"System.Net.Sockets;SocketTaskExtensions;ConnectAsync;(System.Net.Sockets.Socket,System.String,System.Int32);generated",
"System.Net.Sockets;SocketTaskExtensions;ReceiveAsync;(System.Net.Sockets.Socket,System.ArraySegment<System.Byte>,System.Net.Sockets.SocketFlags);generated",
"System.Net.Sockets;SocketTaskExtensions;ReceiveAsync;(System.Net.Sockets.Socket,System.Collections.Generic.IList<System.ArraySegment<System.Byte>>,System.Net.Sockets.SocketFlags);generated",
"System.Net.Sockets;SocketTaskExtensions;ReceiveFromAsync;(System.Net.Sockets.Socket,System.ArraySegment<System.Byte>,System.Net.Sockets.SocketFlags,System.Net.EndPoint);generated",
"System.Net.Sockets;SocketTaskExtensions;ReceiveMessageFromAsync;(System.Net.Sockets.Socket,System.ArraySegment<System.Byte>,System.Net.Sockets.SocketFlags,System.Net.EndPoint);generated",
"System.Net.Sockets;SocketTaskExtensions;SendAsync;(System.Net.Sockets.Socket,System.ArraySegment<System.Byte>,System.Net.Sockets.SocketFlags);generated",
"System.Net.Sockets;SocketTaskExtensions;SendAsync;(System.Net.Sockets.Socket,System.Collections.Generic.IList<System.ArraySegment<System.Byte>>,System.Net.Sockets.SocketFlags);generated",
"System.Net.Sockets;TcpClient;Close;();generated",
@@ -19530,8 +19437,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net.Sockets;TcpListener;AcceptTcpClientAsync;(System.Threading.CancellationToken);generated",
"System.Net.Sockets;TcpListener;AllowNatTraversal;(System.Boolean);generated",
"System.Net.Sockets;TcpListener;Create;(System.Int32);generated",
"System.Net.Sockets;TcpListener;EndAcceptSocket;(System.IAsyncResult);generated",
"System.Net.Sockets;TcpListener;EndAcceptTcpClient;(System.IAsyncResult);generated",
"System.Net.Sockets;TcpListener;Pending;();generated",
"System.Net.Sockets;TcpListener;Start;();generated",
"System.Net.Sockets;TcpListener;Start;(System.Int32);generated",
@@ -19748,10 +19653,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net;CredentialCache;Remove;(System.Uri,System.String);generated",
"System.Net;CredentialCache;get_DefaultCredentials;();generated",
"System.Net;CredentialCache;get_DefaultNetworkCredentials;();generated",
"System.Net;Dns;EndGetHostAddresses;(System.IAsyncResult);generated",
"System.Net;Dns;EndGetHostByName;(System.IAsyncResult);generated",
"System.Net;Dns;EndGetHostEntry;(System.IAsyncResult);generated",
"System.Net;Dns;EndResolve;(System.IAsyncResult);generated",
"System.Net;Dns;GetHostAddresses;(System.String);generated",
"System.Net;Dns;GetHostAddresses;(System.String,System.Net.Sockets.AddressFamily);generated",
"System.Net;Dns;GetHostAddressesAsync;(System.String);generated",
@@ -19795,8 +19696,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net;EndpointPermission;get_Port;();generated",
"System.Net;EndpointPermission;get_Transport;();generated",
"System.Net;FileWebRequest;Abort;();generated",
"System.Net;FileWebRequest;EndGetRequestStream;(System.IAsyncResult);generated",
"System.Net;FileWebRequest;EndGetResponse;(System.IAsyncResult);generated",
"System.Net;FileWebRequest;FileWebRequest;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated",
"System.Net;FileWebRequest;GetObjectData;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated",
"System.Net;FileWebRequest;GetRequestStreamAsync;();generated",
@@ -19951,9 +19850,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net;HttpWebRequest;AddRange;(System.String,System.Int32,System.Int32);generated",
"System.Net;HttpWebRequest;AddRange;(System.String,System.Int64);generated",
"System.Net;HttpWebRequest;AddRange;(System.String,System.Int64,System.Int64);generated",
"System.Net;HttpWebRequest;EndGetRequestStream;(System.IAsyncResult);generated",
"System.Net;HttpWebRequest;EndGetRequestStream;(System.IAsyncResult,System.Net.TransportContext);generated",
"System.Net;HttpWebRequest;EndGetResponse;(System.IAsyncResult);generated",
"System.Net;HttpWebRequest;GetObjectData;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated",
"System.Net;HttpWebRequest;HttpWebRequest;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated",
"System.Net;HttpWebRequest;get_AllowAutoRedirect;();generated",
@@ -20102,7 +19998,7 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Net;NetworkCredential;get_SecurePassword;();generated",
"System.Net;NetworkCredential;set_SecurePassword;(System.Security.SecureString);generated",
"System.Net;PathList;GetCookiesCount;();generated",
"System.Net;PathList;get_Count;();generated", "System.Net;PathList;get_Values;();generated",
"System.Net;PathList;get_Count;();generated",
"System.Net;PathList;set_Item;(System.String,System.Object);generated",
"System.Net;ProtocolViolationException;ProtocolViolationException;();generated",
"System.Net;ProtocolViolationException;ProtocolViolationException;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated",
@@ -20488,6 +20384,7 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Numerics;BigInteger;Log;(System.Numerics.BigInteger,System.Double);generated",
"System.Numerics;BigInteger;ModPow;(System.Numerics.BigInteger,System.Numerics.BigInteger,System.Numerics.BigInteger);generated",
"System.Numerics;BigInteger;Multiply;(System.Numerics.BigInteger,System.Numerics.BigInteger);generated",
"System.Numerics;BigInteger;Negate;(System.Numerics.BigInteger);generated",
"System.Numerics;BigInteger;Parse;(System.ReadOnlySpan<System.Char>,System.Globalization.NumberStyles,System.IFormatProvider);generated",
"System.Numerics;BigInteger;Parse;(System.String);generated",
"System.Numerics;BigInteger;Parse;(System.String,System.Globalization.NumberStyles);generated",
@@ -20553,6 +20450,7 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Numerics;BigInteger;op_Multiply;(System.Numerics.BigInteger,System.Numerics.BigInteger);generated",
"System.Numerics;BigInteger;op_OnesComplement;(System.Numerics.BigInteger);generated",
"System.Numerics;BigInteger;op_Subtraction;(System.Numerics.BigInteger,System.Numerics.BigInteger);generated",
"System.Numerics;BigInteger;op_UnaryNegation;(System.Numerics.BigInteger);generated",
"System.Numerics;BitOperations;IsPow2;(System.Int32);generated",
"System.Numerics;BitOperations;IsPow2;(System.Int64);generated",
"System.Numerics;BitOperations;IsPow2;(System.IntPtr);generated",
@@ -23476,7 +23374,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Resources;ResourceSet;Dispose;(System.Boolean);generated",
"System.Resources;ResourceSet;GetDefaultReader;();generated",
"System.Resources;ResourceSet;GetDefaultWriter;();generated",
"System.Resources;ResourceSet;GetEnumerator;();generated",
"System.Resources;ResourceSet;GetObject;(System.String);generated",
"System.Resources;ResourceSet;GetObject;(System.String,System.Boolean);generated",
"System.Resources;ResourceSet;GetString;(System.String);generated",
@@ -23691,6 +23588,8 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Runtime.CompilerServices;DisablePrivateReflectionAttribute;DisablePrivateReflectionAttribute;();generated",
"System.Runtime.CompilerServices;DiscardableAttribute;DiscardableAttribute;();generated",
"System.Runtime.CompilerServices;DynamicAttribute;DynamicAttribute;();generated",
"System.Runtime.CompilerServices;DynamicAttribute;DynamicAttribute;(System.Boolean[]);generated",
"System.Runtime.CompilerServices;DynamicAttribute;get_TransformFlags;();generated",
"System.Runtime.CompilerServices;EnumeratorCancellationAttribute;EnumeratorCancellationAttribute;();generated",
"System.Runtime.CompilerServices;FixedAddressValueTypeAttribute;FixedAddressValueTypeAttribute;();generated",
"System.Runtime.CompilerServices;FixedBufferAttribute;FixedBufferAttribute;(System.Type,System.Int32);generated",
@@ -29676,7 +29575,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Security.Cryptography.Pkcs;Pkcs12SafeContents;Decrypt;(System.ReadOnlySpan<System.Byte>);generated",
"System.Security.Cryptography.Pkcs;Pkcs12SafeContents;Decrypt;(System.ReadOnlySpan<System.Char>);generated",
"System.Security.Cryptography.Pkcs;Pkcs12SafeContents;Decrypt;(System.String);generated",
"System.Security.Cryptography.Pkcs;Pkcs12SafeContents;GetBags;();generated",
"System.Security.Cryptography.Pkcs;Pkcs12SafeContents;Pkcs12SafeContents;();generated",
"System.Security.Cryptography.Pkcs;Pkcs12SafeContents;get_ConfidentialityMode;();generated",
"System.Security.Cryptography.Pkcs;Pkcs12SafeContents;get_IsReadOnly;();generated",
@@ -29984,7 +29882,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Security.Cryptography.X509Certificates;X509Certificate;get_Handle;();generated",
"System.Security.Cryptography.X509Certificates;X509CertificateCollection+X509CertificateEnumerator;MoveNext;();generated",
"System.Security.Cryptography.X509Certificates;X509CertificateCollection+X509CertificateEnumerator;Reset;();generated",
"System.Security.Cryptography.X509Certificates;X509CertificateCollection+X509CertificateEnumerator;X509CertificateEnumerator;(System.Security.Cryptography.X509Certificates.X509CertificateCollection);generated",
"System.Security.Cryptography.X509Certificates;X509CertificateCollection;Contains;(System.Security.Cryptography.X509Certificates.X509Certificate);generated",
"System.Security.Cryptography.X509Certificates;X509CertificateCollection;GetHashCode;();generated",
"System.Security.Cryptography.X509Certificates;X509CertificateCollection;IndexOf;(System.Security.Cryptography.X509Certificates.X509Certificate);generated",
@@ -30154,7 +30051,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Security.Cryptography.Xml;EncryptionPropertyCollection;get_IsReadOnly;();generated",
"System.Security.Cryptography.Xml;EncryptionPropertyCollection;get_IsSynchronized;();generated",
"System.Security.Cryptography.Xml;IRelDecryptor;Decrypt;(System.Security.Cryptography.Xml.EncryptionMethod,System.Security.Cryptography.Xml.KeyInfo,System.IO.Stream);generated",
"System.Security.Cryptography.Xml;KeyInfo;GetEnumerator;(System.Type);generated",
"System.Security.Cryptography.Xml;KeyInfo;GetXml;();generated",
"System.Security.Cryptography.Xml;KeyInfo;KeyInfo;();generated",
"System.Security.Cryptography.Xml;KeyInfo;get_Count;();generated",
@@ -30221,7 +30117,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Security.Cryptography.Xml;Transform;Transform;();generated",
"System.Security.Cryptography.Xml;Transform;get_InputTypes;();generated",
"System.Security.Cryptography.Xml;Transform;get_OutputTypes;();generated",
"System.Security.Cryptography.Xml;TransformChain;GetEnumerator;();generated",
"System.Security.Cryptography.Xml;TransformChain;TransformChain;();generated",
"System.Security.Cryptography.Xml;TransformChain;get_Count;();generated",
"System.Security.Cryptography.Xml;X509IssuerSerial;get_IssuerName;();generated",
@@ -34394,7 +34289,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Text.Json.Serialization;ReferenceResolver;GetReference;(System.Object,System.Boolean);generated",
"System.Text.Json.Serialization;ReferenceResolver;ResolveReference;(System.String);generated",
"System.Text.Json.SourceGeneration;JsonSourceGenerator;Execute;(Microsoft.CodeAnalysis.GeneratorExecutionContext);generated",
"System.Text.Json.SourceGeneration;JsonSourceGenerator;GetSerializableTypes;();generated",
"System.Text.Json.SourceGeneration;JsonSourceGenerator;Initialize;(Microsoft.CodeAnalysis.GeneratorInitializationContext);generated",
"System.Text.Json.SourceGeneration;JsonSourceGenerator;Initialize;(Microsoft.CodeAnalysis.IncrementalGeneratorInitializationContext);generated",
"System.Text.Json;JsonDocument;Dispose;();generated",
@@ -35424,7 +35318,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Threading.RateLimiting;MetadataName<>;op_Inequality;(System.Threading.RateLimiting.MetadataName<>,System.Threading.RateLimiting.MetadataName<>);generated",
"System.Threading.RateLimiting;RateLimitLease;Dispose;();generated",
"System.Threading.RateLimiting;RateLimitLease;Dispose;(System.Boolean);generated",
"System.Threading.RateLimiting;RateLimitLease;GetAllMetadata;();generated",
"System.Threading.RateLimiting;RateLimitLease;TryGetMetadata;(System.String,System.Object);generated",
"System.Threading.RateLimiting;RateLimitLease;get_IsAcquired;();generated",
"System.Threading.RateLimiting;RateLimitLease;get_MetadataNames;();generated",
@@ -35507,10 +35400,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Threading.Tasks.Dataflow;DataflowBlock;OutputAvailableAsync<>;(System.Threading.Tasks.Dataflow.ISourceBlock<TOutput>);generated",
"System.Threading.Tasks.Dataflow;DataflowBlock;OutputAvailableAsync<>;(System.Threading.Tasks.Dataflow.ISourceBlock<TOutput>,System.Threading.CancellationToken);generated",
"System.Threading.Tasks.Dataflow;DataflowBlock;ReceiveAllAsync<>;(System.Threading.Tasks.Dataflow.IReceivableSourceBlock<TOutput>,System.Threading.CancellationToken);generated",
"System.Threading.Tasks.Dataflow;DataflowBlock;ReceiveAsync<>;(System.Threading.Tasks.Dataflow.ISourceBlock<TOutput>);generated",
"System.Threading.Tasks.Dataflow;DataflowBlock;ReceiveAsync<>;(System.Threading.Tasks.Dataflow.ISourceBlock<TOutput>,System.Threading.CancellationToken);generated",
"System.Threading.Tasks.Dataflow;DataflowBlock;ReceiveAsync<>;(System.Threading.Tasks.Dataflow.ISourceBlock<TOutput>,System.TimeSpan);generated",
"System.Threading.Tasks.Dataflow;DataflowBlock;ReceiveAsync<>;(System.Threading.Tasks.Dataflow.ISourceBlock<TOutput>,System.TimeSpan,System.Threading.CancellationToken);generated",
"System.Threading.Tasks.Dataflow;DataflowBlock;SendAsync<>;(System.Threading.Tasks.Dataflow.ITargetBlock<TInput>,TInput);generated",
"System.Threading.Tasks.Dataflow;DataflowBlockOptions;DataflowBlockOptions;();generated",
"System.Threading.Tasks.Dataflow;DataflowBlockOptions;get_BoundedCapacity;();generated",
@@ -36723,13 +36612,10 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Xml.Schema;XmlSchemaParticle;set_MinOccursString;(System.String);generated",
"System.Xml.Schema;XmlSchemaPatternFacet;XmlSchemaPatternFacet;();generated",
"System.Xml.Schema;XmlSchemaRedefine;XmlSchemaRedefine;();generated",
"System.Xml.Schema;XmlSchemaSet;Add;(System.Xml.Schema.XmlSchemaSet);generated",
"System.Xml.Schema;XmlSchemaSet;Compile;();generated",
"System.Xml.Schema;XmlSchemaSet;Contains;(System.String);generated",
"System.Xml.Schema;XmlSchemaSet;Contains;(System.Xml.Schema.XmlSchema);generated",
"System.Xml.Schema;XmlSchemaSet;CopyTo;(System.Xml.Schema.XmlSchema[],System.Int32);generated",
"System.Xml.Schema;XmlSchemaSet;RemoveRecursive;(System.Xml.Schema.XmlSchema);generated",
"System.Xml.Schema;XmlSchemaSet;Schemas;();generated",
"System.Xml.Schema;XmlSchemaSet;Schemas;(System.String);generated",
"System.Xml.Schema;XmlSchemaSet;XmlSchemaSet;();generated",
"System.Xml.Schema;XmlSchemaSet;get_Count;();generated",
@@ -36982,7 +36868,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Xml.Serialization;XmlSerializationWriter;WriteEmptyTag;(System.String,System.String);generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteEndElement;();generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteEndElement;(System.Object);generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteId;(System.Object);generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteNamespaceDeclarations;(System.Xml.Serialization.XmlSerializerNamespaces);generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteNullTagEncoded;(System.String);generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteNullTagEncoded;(System.String,System.String);generated",
@@ -36991,8 +36876,6 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System.Xml.Serialization;XmlSerializationWriter;WriteNullableQualifiedNameEncoded;(System.String,System.String,System.Xml.XmlQualifiedName,System.Xml.XmlQualifiedName);generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteNullableQualifiedNameLiteral;(System.String,System.String,System.Xml.XmlQualifiedName);generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteReferencedElements;();generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteReferencingElement;(System.String,System.String,System.Object);generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteReferencingElement;(System.String,System.String,System.Object,System.Boolean);generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteStartDocument;();generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteStartElement;(System.String);generated",
"System.Xml.Serialization;XmlSerializationWriter;WriteStartElement;(System.String,System.String);generated",
@@ -41163,29 +41046,7 @@ private class RuntimeNegativesummaryCsv extends NegativeSummaryModelCsv {
"System;Tuple<>;Equals;(System.Object,System.Collections.IEqualityComparer);generated",
"System;Tuple<>;GetHashCode;();generated",
"System;Tuple<>;GetHashCode;(System.Collections.IEqualityComparer);generated",
"System;Tuple<>;get_Length;();generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11,T12,T13,T14,System.ValueTuple<T15,T16,T17,T18,T19,T20,T21>>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11,T12,T13,T14,System.ValueTuple<T15,T16,T17,T18,T19,T20>>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11,T12,T13,T14,System.ValueTuple<T15,T16,T17,T18,T19>>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11,T12,T13,T14,System.ValueTuple<T15,T16,T17,T18>>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11,T12,T13,T14,System.ValueTuple<T15,T16,T17>>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11,T12,T13,T14,System.ValueTuple<T15,T16>>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11,T12,T13,T14,System.ValueTuple<T15>>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11,T12,T13,T14>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11,T12,T13>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11,T12>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10,T11>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9,T10>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8,T9>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,System.ValueTuple<T8>>);generated",
"System;TupleExtensions;ToTuple<,,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6,T7>);generated",
"System;TupleExtensions;ToTuple<,,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5,T6>);generated",
"System;TupleExtensions;ToTuple<,,,,>;(System.ValueTuple<T1,T2,T3,T4,T5>);generated",
"System;TupleExtensions;ToTuple<,,,>;(System.ValueTuple<T1,T2,T3,T4>);generated",
"System;TupleExtensions;ToTuple<,,>;(System.ValueTuple<T1,T2,T3>);generated",
"System;TupleExtensions;ToTuple<,>;(System.ValueTuple<T1,T2>);generated",
"System;TupleExtensions;ToTuple<>;(System.ValueTuple<T1>);generated",
"System;Type;Equals;(System.Object);generated",
"System;Tuple<>;get_Length;();generated", "System;Type;Equals;(System.Object);generated",
"System;Type;Equals;(System.Type);generated", "System;Type;GetArrayRank;();generated",
"System;Type;GetAttributeFlagsImpl;();generated",
"System;Type;GetConstructorImpl;(System.Reflection.BindingFlags,System.Reflection.Binder,System.Reflection.CallingConventions,System.Type[],System.Reflection.ParameterModifier[]);generated",

View File

@@ -7,6 +7,7 @@ private class MicrosoftVisualBasicCollectionFlowModelCsv extends SummaryModelCsv
override predicate row(string row) {
row =
[
"Microsoft.VisualBasic;Collection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"Microsoft.VisualBasic;Collection;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual",
"Microsoft.VisualBasic;Collection;false;get_Item;(System.Int32);;Argument[this].Element;ReturnValue;value;manual",
"Microsoft.VisualBasic;Collection;false;get_Item;(System.Object);;Argument[this].Element;ReturnValue;value;manual",

View File

@@ -2,6 +2,7 @@
import csharp
private import semmle.code.csharp.frameworks.System
private import semmle.code.csharp.dataflow.ExternalFlow
/** The `System.CodeDome` namespace. */
class SystemCodeDomNamespace extends Namespace {
@@ -10,3 +11,11 @@ class SystemCodeDomNamespace extends Namespace {
this.hasName("CodeDom")
}
}
/** Data flow for `System.CodeDom.CodeNamespaceImportCollection`. */
private class SystemCodeDomCodeNamespaceImportCollectionFlowModelCsv extends SummaryModelCsv {
override predicate row(string row) {
row =
"System.CodeDom;CodeNamespaceImportCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual"
}
}

View File

@@ -46,20 +46,6 @@ private class SystemCollectionIEnumerableFlowModelCsv extends SummaryModelCsv {
}
}
/** Clear content for Clear methods in all subtypes of `System.Collections.IEnumerable`. */
private class SystemCollectionsIEnumerableClearFlow extends SummarizedCallable {
SystemCollectionsIEnumerableClearFlow() {
this.getDeclaringType().(RefType).getABaseType*() instanceof
SystemCollectionsIEnumerableInterface and
this.hasName("Clear")
}
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
(if this.(Modifiable).isStatic() then pos.getPosition() = 0 else pos.isThisParameter()) and
content instanceof DataFlow::ElementContent
}
}
/** The `System.Collections.IEnumerator` interface. */
class SystemCollectionsIEnumeratorInterface extends SystemCollectionsInterface {
SystemCollectionsIEnumeratorInterface() { this.hasName("IEnumerator") }
@@ -96,6 +82,7 @@ private class SystemCollectionsIListFlowModelCsv extends SummaryModelCsv {
row =
[
"System.Collections;IList;true;Add;(System.Object);;Argument[0];Argument[this].Element;value;manual",
"System.Collections;IList;true;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Collections;IList;true;Insert;(System.Int32,System.Object);;Argument[1];Argument[this].Element;value;manual",
"System.Collections;IList;true;get_Item;(System.Int32);;Argument[this].Element;ReturnValue;value;manual",
"System.Collections;IList;true;set_Item;(System.Int32,System.Object);;Argument[1];Argument[this].Element;value;manual",
@@ -115,6 +102,7 @@ private class SystemCollectionsIDictionaryFlowModelCsv extends SummaryModelCsv {
[
"System.Collections;IDictionary;true;Add;(System.Object,System.Object);;Argument[0];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key];value;manual",
"System.Collections;IDictionary;true;Add;(System.Object,System.Object);;Argument[1];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value];value;manual",
"System.Collections;IDictionary;true;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Collections;IDictionary;true;get_Item;(System.Object);;Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value];ReturnValue;value;manual",
"System.Collections;IDictionary;true;get_Keys;();;Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key];ReturnValue.Element;value;manual",
"System.Collections;IDictionary;true;get_Values;();;Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value];ReturnValue.Element;value;manual",
@@ -194,6 +182,7 @@ private class SystemCollectionsQueueFlowModelCsv extends SummaryModelCsv {
override predicate row(string row) {
row =
[
"System.Collections;Queue;true;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Collections;Queue;false;Clone;();;Argument[0].Element;ReturnValue.Element;value;manual",
"System.Collections;Queue;false;Peek;();;Argument[this].Element;ReturnValue;value;manual",
]
@@ -205,6 +194,7 @@ private class SystemCollectionsStackFlowModelCsv extends SummaryModelCsv {
override predicate row(string row) {
row =
[
"System.Collections;Stack;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Collections;Stack;false;Clone;();;Argument[0].Element;ReturnValue.Element;value;manual",
"System.Collections;Stack;false;Peek;();;Argument[this].Element;ReturnValue;value;manual",
"System.Collections;Stack;false;Pop;();;Argument[this].Element;ReturnValue;value;manual",

View File

@@ -12,6 +12,7 @@ private class SystemComponentModelPropertyDescriptorCollectionFlowModelCsv exten
"System.ComponentModel;PropertyDescriptorCollection;false;Add;(System.ComponentModel.PropertyDescriptor);;Argument[0].Property[System.Collections.Generic.KeyValuePair<,>.Value];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value];value;manual",
"System.ComponentModel;PropertyDescriptorCollection;false;Add;(System.Object);;Argument[0].Property[System.Collections.Generic.KeyValuePair<,>.Key];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key];value;manual",
"System.ComponentModel;PropertyDescriptorCollection;false;Add;(System.Object);;Argument[0].Property[System.Collections.Generic.KeyValuePair<,>.Value];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value];value;manual",
"System.ComponentModel;PropertyDescriptorCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.ComponentModel;PropertyDescriptorCollection;false;Find;(System.String,System.Boolean);;Argument[this].Element;ReturnValue;value;manual",
"System.ComponentModel;PropertyDescriptorCollection;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual",
"System.ComponentModel;PropertyDescriptorCollection;false;Insert;(System.Int32,System.ComponentModel.PropertyDescriptor);;Argument[1];Argument[this].Element;value;manual",
@@ -37,6 +38,7 @@ private class SystemComponentModelEventDescriptorCollectionFlowModelCsv extends
row =
[
"System.ComponentModel;EventDescriptorCollection;false;Add;(System.ComponentModel.EventDescriptor);;Argument[0];Argument[this].Element;value;manual",
"System.ComponentModel;EventDescriptorCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.ComponentModel;EventDescriptorCollection;false;Find;(System.String,System.Boolean);;Argument[this].Element;ReturnValue;value;manual",
"System.ComponentModel;EventDescriptorCollection;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual",
"System.ComponentModel;EventDescriptorCollection;false;Insert;(System.Int32,System.ComponentModel.EventDescriptor);;Argument[1];Argument[this].Element;value;manual",

View File

@@ -0,0 +1,26 @@
/** Provides definitions related to the namespace `System.Configuration`. */
import csharp
private import semmle.code.csharp.dataflow.ExternalFlow
/** Data flow for some collection classes in `System.Configuration.*`. */
private class SystemClearFlowModelCsv extends SummaryModelCsv {
override predicate row(string row) {
row =
[
"System.Configuration;CommaDelimitedStringCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Configuration;ConfigurationLockCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Configuration;ConfigurationPropertyCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Configuration;ConfigurationSectionCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Configuration;ConfigurationSectionGroupCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Configuration;ConnectionStringSettingsCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Configuration;KeyValueConfigurationCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Configuration;NameValueConfigurationCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Configuration;ProviderSettingsCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Configuration;SettingElementCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Configuration;SettingsPropertyCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Configuration;SettingsPropertyValueCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Configuration.Provider;ProviderCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
]
}
}

View File

@@ -150,6 +150,7 @@ private class SystemDataConstraintCollectionFlowModelCsv extends SummaryModelCsv
[
"System.Data;ConstraintCollection;false;Add;(System.Data.Constraint);;Argument[0];Argument[this].Element;value;manual",
"System.Data;ConstraintCollection;false;AddRange;(System.Data.Constraint[]);;Argument[0].Element;Argument[this].Element;value;manual",
"System.Data;ConstraintCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Data;ConstraintCollection;false;CopyTo;(System.Data.Constraint[],System.Int32);;Argument[this].Element;Argument[0].Element;value;manual",
]
}
@@ -163,6 +164,7 @@ private class SystemDataDataColumnCollectionFlowModelCsv extends SummaryModelCsv
"System.Data;DataColumnCollection;false;Add;(System.Data.DataColumn);;Argument[0];Argument[this].Element;value;manual",
"System.Data;DataColumnCollection;false;Add;(System.String);;Argument[0];Argument[this].Element;value;manual",
"System.Data;DataColumnCollection;false;AddRange;(System.Data.DataColumn[]);;Argument[0].Element;Argument[this].Element;value;manual",
"System.Data;DataColumnCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Data;DataColumnCollection;false;CopyTo;(System.Data.DataColumn[],System.Int32);;Argument[this].Element;Argument[0].Element;value;manual",
]
}
@@ -174,6 +176,7 @@ private class SystemDataDataRelationCollectionFlowModelCsv extends SummaryModelC
row =
[
"System.Data;DataRelationCollection;false;Add;(System.Data.DataRelation);;Argument[0];Argument[this].Element;value;manual",
"System.Data;DataRelationCollection;true;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Data;DataRelationCollection;false;CopyTo;(System.Data.DataRelation[],System.Int32);;Argument[this].Element;Argument[0].Element;value;manual",
"System.Data;DataRelationCollection;true;AddRange;(System.Data.DataRelation[]);;Argument[0].Element;Argument[this].Element;value;manual",
]
@@ -187,6 +190,7 @@ private class SystemDataDataRawCollectionFlowModelCsv extends SummaryModelCsv {
[
"System.Data;DataRowCollection;false;Add;(System.Data.DataRow);;Argument[0];Argument[this].Element;value;manual",
"System.Data;DataRowCollection;false;Add;(System.Object[]);;Argument[0];Argument[this].Element;value;manual",
"System.Data;DataRowCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Data;DataRowCollection;false;CopyTo;(System.Data.DataRow[],System.Int32);;Argument[this].Element;Argument[0].Element;value;manual",
"System.Data;DataRowCollection;false;Find;(System.Object);;Argument[this].Element;ReturnValue;value;manual",
"System.Data;DataRowCollection;false;Find;(System.Object[]);;Argument[this].Element;ReturnValue;value;manual",
@@ -202,6 +206,7 @@ private class SystemDataDataTableCollectionFlowModelCsv extends SummaryModelCsv
"System.Data;DataTableCollection;false;Add;(System.Data.DataTable);;Argument[0];Argument[this].Element;value;manual",
"System.Data;DataTableCollection;false;Add;(System.String);;Argument[0];Argument[this].Element;value;manual",
"System.Data;DataTableCollection;false;AddRange;(System.Data.DataTable[]);;Argument[0].Element;Argument[this].Element;value;manual",
"System.Data;DataTableCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Data;DataTableCollection;false;CopyTo;(System.Data.DataTable[],System.Int32);;Argument[this].Element;Argument[0].Element;value;manual",
]
}

View File

@@ -1,6 +1,7 @@
/** 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. */
@@ -15,3 +16,15 @@ class SystemSecurityNamespace extends Namespace {
class SystemSecurityClass extends Class {
SystemSecurityClass() { this.getNamespace() instanceof SystemSecurityNamespace }
}
/** Data flow for some collection like classes in `System.Security.*`. */
private class SystemSecurityPolicyApplicationTrustCollectionFlowModelCsv extends SummaryModelCsv {
override predicate row(string row) {
row =
[
"System.Security.Permissions;KeyContainerPermissionAccessEntryCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Security.Policy;ApplicationTrustCollection;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Security.Policy;Evidence;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
]
}
}

View File

@@ -26,18 +26,6 @@ class SystemTextStringBuilderClass extends SystemTextClass {
Method getAppendFormatMethod() { result = this.getAMethod("AppendFormat") }
}
/** Clear content for `System.Text.StringBuilder.Clear`. */
private class SystemTextStringBuilderClearFlow extends SummarizedCallable {
SystemTextStringBuilderClearFlow() {
this = any(SystemTextStringBuilderClass s).getAMethod("Clear")
}
override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
pos.isThisParameter() and
content instanceof DataFlow::ElementContent
}
}
/** Data flow for `System.Text.StringBuilder`. */
private class SystemTextStringBuilderFlowModelCsv extends SummaryModelCsv {
override predicate row(string row) {
@@ -120,6 +108,7 @@ private class SystemTextStringBuilderFlowModelCsv extends SummaryModelCsv {
"System.Text;StringBuilder;false;AppendLine;();;Argument[this];ReturnValue;value;manual",
"System.Text;StringBuilder;false;AppendLine;(System.String);;Argument[0];Argument[this].Element;value;manual",
"System.Text;StringBuilder;false;AppendLine;(System.String);;Argument[this];ReturnValue;value;manual",
"System.Text;StringBuilder;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Text;StringBuilder;false;StringBuilder;(System.String);;Argument[0];Argument[this].Element;value;manual",
"System.Text;StringBuilder;false;StringBuilder;(System.String,System.Int32);;Argument[0];Argument[this].Element;value;manual",
"System.Text;StringBuilder;false;StringBuilder;(System.String,System.Int32,System.Int32,System.Int32);;Argument[0];Argument[this].Element;value;manual",

View File

@@ -44,6 +44,25 @@ private class SystemCollectionsConcurrentIProducerConsumerCollectionFlowModelCsv
private class SystemCollectionsConcurrentConcurrentBagFlowModelCsv extends SummaryModelCsv {
override predicate row(string row) {
row =
"System.Collections.Concurrent;ConcurrentBag<>;false;Add;(T);;Argument[0];Argument[this].Element;value;manual"
[
"System.Collections.Concurrent;ConcurrentBag<>;false;Add;(T);;Argument[0];Argument[this].Element;value;manual",
"System.Collections.Concurrent;ConcurrentBag<>;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
]
}
}
/** Data flow for `System.Collections.Concurrent.ConcurrentQueue<>`. */
private class SystemCollectionsConcurrentConcurrentQueueFlowModelCsv extends SummaryModelCsv {
override predicate row(string row) {
row =
"System.Collections.Concurrent;ConcurrentQueue<>;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual"
}
}
/** Data flow for `System.Collections.Concurrent.ConcurrentStack<>`. */
private class SystemCollectionsConcurrentConcurrentStackFlowModelCsv extends SummaryModelCsv {
override predicate row(string row) {
row =
"System.Collections.Concurrent;ConcurrentStack<>;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual"
}
}

View File

@@ -197,6 +197,7 @@ private class SystemCollectionsGenericICollectionFlowModelCsv extends SummaryMod
row =
[
"System.Collections.Generic;ICollection<>;true;Add;(T);;Argument[0];Argument[this].Element;value;manual",
"System.Collections.Generic;ICollection<>;true;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Collections.Generic;ICollection<>;true;CopyTo;(T[],System.Int32);;Argument[this].Element;Argument[0].Element;value;manual",
]
}
@@ -289,6 +290,8 @@ private class SystemCollectionsGenericSortedListFlowModelCsv extends SummaryMode
"System.Collections.Generic;SortedList<,>;false;SortedList;(System.Collections.Generic.IDictionary<TKey,TValue>,System.Collections.Generic.IComparer<TKey>);;Argument[0].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value];value;manual",
"System.Collections.Generic;SortedList<,>;false;get_Keys;();;Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key];ReturnValue.Element;value;manual",
"System.Collections.Generic;SortedList<,>;false;get_Values;();;Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value];ReturnValue.Element;value;manual",
"System.Collections.Generic;SortedList<,>+KeyList;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Collections.Generic;SortedList<,>+ValueList;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
]
}
}
@@ -298,6 +301,7 @@ private class SystemCollectionsGenericQueueFlowModelCsv extends SummaryModelCsv
override predicate row(string row) {
row =
[
"System.Collections.Generic;Queue<>;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Collections.Generic;Queue<>;false;CopyTo;(T[],System.Int32);;Argument[this].Element;Argument[0].Element;value;manual",
"System.Collections.Generic;Queue<>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Generic.Queue<>+Enumerator.Current];value;manual",
"System.Collections.Generic;Queue<>;false;Peek;();;Argument[this].Element;ReturnValue;value;manual",
@@ -310,6 +314,7 @@ private class SystemCollectionsGenericStackFlowModelCsv extends SummaryModelCsv
override predicate row(string row) {
row =
[
"System.Collections.Generic;Stack<>;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Collections.Generic;Stack<>;false;CopyTo;(T[],System.Int32);;Argument[this].Element;Argument[0].Element;value;manual",
"System.Collections.Generic;Stack<>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Generic.Stack<>+Enumerator.Current];value;manual",
"System.Collections.Generic;Stack<>;false;Peek;();;Argument[this].Element;ReturnValue;value;manual",

View File

@@ -6,7 +6,10 @@ private import semmle.code.csharp.dataflow.ExternalFlow
private class SystemCollectionsImmutableIImmutableDictionaryFlowModelCsv extends SummaryModelCsv {
override predicate row(string row) {
row =
"System.Collections.Immutable;IImmutableDictionary<,>;true;AddRange;(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>);;Argument[0].Element;Argument[this].Element;value;manual"
[
"System.Collections.Immutable;IImmutableDictionary<,>;true;AddRange;(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>);;Argument[0].Element;Argument[this].Element;value;manual",
"System.Collections.Immutable;IImmutableDictionary<,>;true;Clear;();;Argument[this].WithoutElement;ReturnValue;value;manual",
]
}
}
@@ -65,6 +68,7 @@ private class SystemCollectionsImmutableIImmutableListFlowModelCsv extends Summa
[
"System.Collections.Immutable;IImmutableList<>;true;Add;(T);;Argument[0];Argument[this].Element;value;manual",
"System.Collections.Immutable;IImmutableList<>;true;AddRange;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;Argument[this].Element;value;manual",
"System.Collections.Immutable;IImmutableList<>;true;Clear;();;Argument[this].WithoutElement;ReturnValue;value;manual",
]
}
}
@@ -124,7 +128,10 @@ private class SystemCollectionsImmutableImmutableSortedSetFlowModelCsv extends S
private class SystemCollectionsImmutableIImmutableSetFlowModelCsv extends SummaryModelCsv {
override predicate row(string row) {
row =
"System.Collections.Immutable;IImmutableSet<>;true;Add;(T);;Argument[0];Argument[this].Element;value;manual"
[
"System.Collections.Immutable;IImmutableSet<>;true;Add;(T);;Argument[0];Argument[this].Element;value;manual",
"System.Collections.Immutable;IImmutableSet<>;true;Clear;();;Argument[this].WithoutElement;ReturnValue;value;manual",
]
}
}
@@ -153,6 +160,7 @@ private class SystemCollectionsImmutableImmutableHashSetFlowModelCsv extends Sum
[
"System.Collections.Immutable;ImmutableHashSet<>+Builder;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Immutable.ImmutableHashSet<>+Enumerator.Current];value;manual",
"System.Collections.Immutable;ImmutableHashSet<>;false;Add;(T);;Argument[0];Argument[this].Element;value;manual",
"System.Collections.Immutable;ImmutableHashSet<>;false;Clear;();;Argument[this].WithoutElement;ReturnValue;value;manual",
"System.Collections.Immutable;ImmutableHashSet<>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Immutable.ImmutableHashSet<>+Enumerator.Current];value;manual",
]
}
@@ -162,7 +170,10 @@ private class SystemCollectionsImmutableImmutableHashSetFlowModelCsv extends Sum
private class SystemCollectionsImmutableImmutableQueueFlowModelCsv extends SummaryModelCsv {
override predicate row(string row) {
row =
"System.Collections.Immutable;ImmutableQueue<>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Immutable.ImmutableQueue<>+Enumerator.Current];value;manual"
[
"System.Collections.Immutable;IImmutableQueue<>;true;Clear;();;Argument[this].WithoutElement;ReturnValue;value;manual",
"System.Collections.Immutable;ImmutableQueue<>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Immutable.ImmutableQueue<>+Enumerator.Current];value;manual",
]
}
}
@@ -170,6 +181,9 @@ private class SystemCollectionsImmutableImmutableQueueFlowModelCsv extends Summa
private class SystemCollectionsImmutableImmutableStackFlowModelCsv extends SummaryModelCsv {
override predicate row(string row) {
row =
"System.Collections.Immutable;ImmutableStack<>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Immutable.ImmutableStack<>+Enumerator.Current];value;manual"
[
"System.Collections.Immutable;IImmutableStack<>;true;Clear;();;Argument[this].WithoutElement;ReturnValue;value;manual",
"System.Collections.Immutable;ImmutableStack<>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Immutable.ImmutableStack<>+Enumerator.Current];value;manual",
]
}
}

View File

@@ -30,6 +30,7 @@ private class SystemCollectionsSpecializedNameValueCollectionFlowModelCsv extend
row =
[
"System.Collections.Specialized;NameValueCollection;false;Add;(System.Collections.Specialized.NameValueCollection);;Argument[0];Argument[this].Element;value;manual",
"System.Collections.Specialized;NameValueCollection;true;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual",
"System.Collections.Specialized;NameValueCollection;false;CopyTo;(System.Array,System.Int32);;Argument[this].Element;Argument[0].Element;value;manual",
]
}
@@ -70,3 +71,11 @@ private class SystemCollectionsSpecializedStringCollectionFlowModelCsv extends S
]
}
}
/** Data flow for `System.Collections.Specialized.StringDictionary`. */
private class SystemCollectionsSpecializedStringDictionaryFlowModelCsv extends SummaryModelCsv {
override predicate row(string row) {
row =
"System.Collections.Specialized;StringDictionary;true;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual"
}
}

View File

@@ -95,3 +95,11 @@ private class SystemDataCommonDbParameterCollectionFlowModelCsv extends External
]
}
}
/** Data flow for `System.Data.Common.DbBatchCommandCollection`. */
private class SystemDataCommonDbBatchCommandCollectionFlowModelCsv extends ExternalFlow::SummaryModelCsv {
override predicate row(string row) {
row =
"System.Data.Common;DbBatchCommandCollection;true;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual"
}
}

View File

@@ -28,3 +28,11 @@ private class SystemNetHttpMultipartFormDataContentFlowModelCsv extends SummaryM
"System.Net.Http;MultipartFormDataContent;false;Add;(System.Net.Http.HttpContent);;Argument[0];Argument[this].Element;value;manual"
}
}
/** Data flow for `System.Net.Http.Headers.HttpHeaders`. */
private class SystemNetHttpHeadersHttpHeadersFlowModelCsv extends SummaryModelCsv {
override predicate row(string row) {
row =
"System.Net.Http.Headers;HttpHeaders;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual"
}
}

View File

@@ -103,3 +103,11 @@ private class SystemRuntimeCompilerServicesReadOnlyCollectionBuilderFlowModelCsv
]
}
}
/** Data flow for `System.Runtime.CompilerServices.ConditionalWeakTable<,>`. */
private class SystemRuntimeCompilerServicesConditionalWeakTableFlowModelCsv extends SummaryModelCsv {
override predicate row(string row) {
row =
"System.Runtime.CompilerServices;ConditionalWeakTable<,>;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual"
}
}

View File

@@ -6,7 +6,7 @@ import csharp
private import Email::Email
private import ExternalLocationSink
private import Html
private import semmle.code.csharp.security.dataflow.XSSSinks as XSSSinks
private import semmle.code.csharp.security.dataflow.XSSSinks as XssSinks
private import semmle.code.csharp.frameworks.system.web.UI
/** A data flow sink of remote user output. */

View File

@@ -36,10 +36,9 @@ compilations(
* --- | ---
* 0 | --compiler
* 1 | *path to compiler*
* 2 | --cil
* 3 | f1.cs
* 4 | f2.cs
* 5 | f3.cs
* 2 | f1.cs
* 3 | f2.cs
* 4 | f3.cs
*/
#keyset[id, num]
compilation_args(

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Remove '--cil' flag from the comments. This does not make any changes to the dbscheme.
compatibility: full

View File

@@ -14,4 +14,4 @@ import csharp
from CommentLine c
where c.getText().regexpMatch("(?s).*FIXME.*|.*TODO.*|.*(?<!=)\\s*XXX.*")
select c, "TODO comment."
select c, "TODO comments should be addressed."

View File

@@ -72,5 +72,5 @@ where
) and
m1.fromSource()
select m1,
"confusing to have methods " + m1.getName() + " in " + m1.getDeclaringType().getName() + " and " +
m2.getName() + " in " + m2.getDeclaringType().getName() + "."
"It is confusing to have methods " + m1.getName() + " in " + m1.getDeclaringType().getName() +
" and " + m2.getName() + " in " + m2.getDeclaringType().getName() + "."

View File

@@ -64,6 +64,5 @@ where
validGuard.controls(array, index) and
validGuard.guards(indexAccess, _)
)
select incorrectGuard,
"Off-by-one index comparison against length leads to possible out of bounds $@.", ea,
ea.toString()
select incorrectGuard, "Off-by-one index comparison against length may lead to out-of-bounds $@.",
ea, ea.toString()

View File

@@ -1,6 +1,8 @@
/**
* @name Equality check on floating point values
* @description Equality checks on floating point values can yield unexpected results.
* @description Comparing results of floating-point computations with '==' or
* '!=' is likely to yield surprising results since floating-point
* computation does not follow the standard rules of algebra.
* @kind problem
* @problem.severity warning
* @precision medium

View File

@@ -42,4 +42,4 @@ where
(loopStmtWithEmptyBlock(s) or conditionalWithEmptyBlock(s)) and
not exists(CommentBlock c | c.getParent() = s) and
not exists(ForStmt fs | fs.getBody() = s and exists(fs.getAnUpdate()))
select s, "Empty block."
select s, "Empty block without comment."

View File

@@ -35,4 +35,4 @@ where
access = cast.getAChild() and
access.getTarget().getDeclaringElement() = access.getEnclosingCallable() and
nodeBeforeParameterAccess(access.getAControlFlowNode())
select cast, "Missing type-check before casting parameter to 'Equals'."
select cast, "Equals() method does not check argument type."

View File

@@ -23,5 +23,5 @@ where
c.hasFlowPath(source, sink) and
// No global timeout set
not exists(RegexGlobalTimeout r)
select sink.getNode(), source, sink, "$@ flows to the construction of a regular expression.",
source.getNode(), "User-provided value"
select sink.getNode(), source, sink, "This regular expression is constructed from a $@.",
source.getNode(), "user-provided value"

View File

@@ -24,7 +24,7 @@ predicate incorrectUseOfRC2(Assignment e, string msg) {
msg = "Key size should be at least 128 bits for RC2 encryption."
}
predicate incorrectUseOfDSA(ObjectCreation e, string msg) {
predicate incorrectUseOfDsa(ObjectCreation e, string msg) {
e.getTarget()
.getDeclaringType()
.hasQualifiedName("System.Security.Cryptography", "DSACryptoServiceProvider") and
@@ -32,7 +32,7 @@ predicate incorrectUseOfDSA(ObjectCreation e, string msg) {
msg = "Key size should be at least 2048 bits for DSA encryption."
}
predicate incorrectUseOfRSA(ObjectCreation e, string msg) {
predicate incorrectUseOfRsa(ObjectCreation e, string msg) {
e.getTarget()
.getDeclaringType()
.hasQualifiedName("System.Security.Cryptography", "RSACryptoServiceProvider") and
@@ -43,6 +43,6 @@ predicate incorrectUseOfRSA(ObjectCreation e, string msg) {
from Expr e, string msg
where
incorrectUseOfRC2(e, msg) or
incorrectUseOfDSA(e, msg) or
incorrectUseOfRSA(e, msg)
incorrectUseOfDsa(e, msg) or
incorrectUseOfRsa(e, msg)
select e, msg

View File

@@ -77,7 +77,7 @@ run_cmd(['dotnet', 'new', 'globaljson', '--force', '--sdk-version', sdk_version,
print("\n* Creating DB")
run_cmd(['codeql', 'database', 'create', dbDir, '--language=csharp',
'--command', 'dotnet build /t:rebuild /p:UseSharedCompilation=false ' + projectDirIn])
'--command', 'dotnet build /t:rebuild ' + projectDirIn])
if not os.path.isdir(dbDir):
print("Expected database directory " + dbDir + " not found.")

View File

@@ -18,4 +18,4 @@ from MethodCall mc
where
mc instanceof ImplicitToStringExpr and
mc.getTarget() instanceof ToStringMethod
select mc, "Redundant call to 'ToString'."
select mc, "Redundant call to 'ToString' on a String object."

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The alert message of many queries have been changed to make the message consistent with other languages.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* A new extractor option has been introduced for disabling CIL extraction. Either pass `-Ocil=false` to the `codeql` CLI or set the environment variable `CODEQL_EXTRACTOR_CSHARP_OPTION_CIL=false`.

View File

@@ -0,0 +1,259 @@
import csharp
import DataFlow
/**
* A sensitive property for `TokenValidationParameters` that updates the underlying value.
*/
class TokenValidationParametersPropertySensitiveValidation extends Property {
TokenValidationParametersPropertySensitiveValidation() {
exists(Class c |
c.hasQualifiedName("Microsoft.IdentityModel.Tokens.TokenValidationParameters")
|
c.getAProperty() = this and
this.getName() in [
"ValidateIssuer", "ValidateAudience", "ValidateLifetime", "RequireExpirationTime",
"RequireAudience"
]
)
}
}
/**
* A dataflow from a `false` value to a write sensitive property for `TokenValidationParameters`.
*/
class FalseValueFlowsToTokenValidationParametersPropertyWriteToBypassValidation extends DataFlow::Configuration {
FalseValueFlowsToTokenValidationParametersPropertyWriteToBypassValidation() {
this = "FalseValueFlowsToTokenValidationParametersPropertyWriteToBypassValidation"
}
override predicate isSource(DataFlow::Node source) {
source.asExpr().getValue() = "false" and
source.asExpr().getType() instanceof BoolType
}
override predicate isSink(DataFlow::Node sink) {
sink.asExpr() = any(TokenValidationParametersPropertySensitiveValidation p).getAnAssignedValue()
}
}
/**
* Holds if `assemblyName` is older than version `ver`
*/
bindingset[ver]
predicate isAssemblyOlderVersion(string assemblyName, string ver) {
exists(Assembly a |
a.getName() = assemblyName and
a.getVersion().isEarlierThan(ver)
)
}
/**
* A method `ValidateToken` for `Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler` or other Token handler that shares the same behavior characteristics
*/
class JsonWebTokenHandlerValidateTokenMethod extends Method {
JsonWebTokenHandlerValidateTokenMethod() {
this.hasQualifiedName("Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateToken") or
this.hasQualifiedName("Microsoft.AzureAD.DeviceIdentification.Common.Tokens.JwtValidator.ValidateEncryptedToken")
}
}
/**
* A Call to `Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateToken`
*/
class JsonWebTokenHandlerValidateTokenCall extends MethodCall {
JsonWebTokenHandlerValidateTokenCall() {
this.getTarget() instanceof JsonWebTokenHandlerValidateTokenMethod
}
}
/**
* A read access for properties `IsValid` or `Exception` for `Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateToken`
*/
private class TokenValidationResultIsValidCall extends PropertyRead {
TokenValidationResultIsValidCall() {
exists(Property p | p.getAnAccess() = this |
p.hasName("IsValid") or
p.hasName("Exception")
)
}
}
/**
* Dataflow from the output of `Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateToken` call to access the `IsValid` or `Exception` property
*/
private class FlowsToTokenValidationResultIsValidCall extends DataFlow::Configuration {
FlowsToTokenValidationResultIsValidCall() { this = "FlowsToTokenValidationResultIsValidCall" }
override predicate isSource(DataFlow::Node source) {
source.asExpr() instanceof JsonWebTokenHandlerValidateTokenCall
}
override predicate isSink(DataFlow::Node sink) {
exists(TokenValidationResultIsValidCall call | sink.asExpr() = call.getQualifier())
}
}
/**
* A security-sensitive property for `Microsoft.IdentityModel.Tokens.TokenValidationParameters`
*/
class TokenValidationParametersProperty extends Property {
TokenValidationParametersProperty() {
exists(Class c |
c.hasQualifiedName("Microsoft.IdentityModel.Tokens.TokenValidationParameters")
|
c.getAProperty() = this and
this.getName() in [
"SignatureValidator", "TokenReplayValidator", "AlgorithmValidator", "AudienceValidator",
"IssuerSigningKeyValidator", "LifetimeValidator"
]
)
}
}
/**
* Holds if the callable has a return statement and it always returns true for all such statements
*/
predicate callableHasAReturnStmtAndAlwaysReturnsTrue(Callable c) {
c.getReturnType() instanceof BoolType and
not callableMayThrowException(c) and
forall(ReturnStmt rs | rs.getEnclosingCallable() = c |
rs.getNumberOfChildren() = 1 and
isExpressionAlwaysTrue(rs.getChildExpr(0))
) and
exists(ReturnStmt rs | rs.getEnclosingCallable() = c)
}
/**
* Holds if the lambda expression `le` always returns true
*/
predicate lambdaExprReturnsOnlyLiteralTrue(AnonymousFunctionExpr le) {
le.getExpressionBody().(BoolLiteral).getBoolValue() = true
or
// special scenarios where the expression is not a `BoolLiteral`, but it will evaluatue to `true`
exists(Expr e | le.getExpressionBody() = e |
not e instanceof Call and
not e instanceof Literal and
e.getType() instanceof BoolType and
e.getValue() = "true"
)
}
class CallableAlwaysReturnsTrue extends Callable {
CallableAlwaysReturnsTrue() {
callableHasAReturnStmtAndAlwaysReturnsTrue(this)
or
lambdaExprReturnsOnlyLiteralTrue(this)
or
exists(AnonymousFunctionExpr le, Call call, Callable callable | this = le |
callable.getACall() = call and
call = le.getExpressionBody() and
callableHasAReturnStmtAndAlwaysReturnsTrue(callable)
)
}
}
/**
* Holds if any exception being thrown by the callable is of type `System.ArgumentNullException`
* It will also hold if no exceptions are thrown by the callable
*/
predicate callableOnlyThrowsArgumentNullException(Callable c) {
forall(ThrowElement thre | c = thre.getEnclosingCallable() |
thre.getThrownExceptionType().hasQualifiedName("System.ArgumentNullException")
)
}
/**
* A specialization of `CallableAlwaysReturnsTrue` that takes into consideration exceptions being thrown for higher precision.
*/
class CallableAlwaysReturnsTrueHigherPrecision extends CallableAlwaysReturnsTrue {
CallableAlwaysReturnsTrueHigherPrecision() {
callableOnlyThrowsArgumentNullException(this) and
(
forall(Call call, Callable callable | call.getEnclosingCallable() = this |
callable.getACall() = call and
callable instanceof CallableAlwaysReturnsTrueHigherPrecision
)
or
exists(AnonymousFunctionExpr le, Call call, CallableAlwaysReturnsTrueHigherPrecision cat |
this = le
|
le.canReturn(call) and
cat.getACall() = call
)
or
exists(LambdaExpr le | le = this |
le.getBody() instanceof CallableAlwaysReturnsTrueHigherPrecision
)
)
}
}
/**
* A callable that returns a `string` and has a `string` as 1st argument
*/
private class CallableReturnsStringAndArg0IsString extends Callable {
CallableReturnsStringAndArg0IsString() {
this.getReturnType() instanceof StringType and
this.getParameter(0).getType() instanceof StringType
}
}
/**
* A Callable that always return the 1st argument, both of `string` type
*/
class CallableAlwaysReturnsParameter0 extends CallableReturnsStringAndArg0IsString {
CallableAlwaysReturnsParameter0() {
forex(Expr ret | this.canReturn(ret) |
ret = this.getParameter(0).getAnAccess()
or
exists(CallableAlwaysReturnsParameter0 c |
ret = c.getACall() and
ret.(Call).getArgument(0) = this.getParameter(0).getAnAccess()
)
)
}
}
/**
* A Callable that always return the 1st argument, both of `string` type. Higher precision
*/
class CallableAlwaysReturnsParameter0MayThrowExceptions extends CallableReturnsStringAndArg0IsString {
CallableAlwaysReturnsParameter0MayThrowExceptions() {
forex(Expr ret | this.canReturn(ret) |
ret = this.getParameter(0).getAnAccess()
or
exists(CallableAlwaysReturnsParameter0MayThrowExceptions c |
ret = c.getACall() and
ret.(Call).getArgument(0) = this.getParameter(0).getAnAccess()
)
)
}
}
/**
* Hold if the `Expr` e is a `BoolLiteral` with value true,
* the expression has a predictable value == `true`,
* or if it is a `ConditionalExpr` where the `then` and `else` expressions meet `isExpressionAlwaysTrue` criteria
*/
predicate isExpressionAlwaysTrue(Expr e) {
e.(BoolLiteral).getBoolValue() = true
or
e.getValue() = "true"
or
e instanceof ConditionalExpr and
isExpressionAlwaysTrue(e.(ConditionalExpr).getThen()) and
isExpressionAlwaysTrue(e.(ConditionalExpr).getElse())
or
exists(Callable callable |
callableHasAReturnStmtAndAlwaysReturnsTrue(callable) and
callable.getACall() = e
)
}
/**
* Holds if the `Callable` c throws any exception other than `ThrowsArgumentNullException`
*/
predicate callableMayThrowException(Callable c) {
exists(ThrowStmt thre | c = thre.getEnclosingCallable()) and
not callableOnlyThrowsArgumentNullException(c)
}

View File

@@ -0,0 +1,10 @@
using System;
using Microsoft.IdentityModel.Tokens;
class TestClass
{
public void TestMethod()
{
TokenValidationParameters parameters = new TokenValidationParameters();
parameters.AudienceValidator = (audiences, token, tvp) => { return true; };
}
}

View File

@@ -0,0 +1,17 @@
using System;
using Microsoft.IdentityModel.Tokens;
class TestClass
{
public void TestMethod()
{
TokenValidationParameters parameters = new TokenValidationParameters();
parameters.AudienceValidator = (audiences, token, tvp) =>
{
// Implement your own custom audience validation
if (PerformCustomAudienceValidation(audiences, token))
return true;
else
return false;
};
}
}

View File

@@ -0,0 +1,28 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>By setting critical <code>TokenValidationParameter</code> validation delegates to always return <code>true</code>, important authentication safeguards are disabled. Disabling safeguards can lead to incorrect validation of tokens from any issuer or expired tokens.</p>
</overview>
<recommendation>
<p>Improve the logic of the delegate so not all code paths return <code>true</code>, which effectively disables that type of validation; or throw <code>SecurityTokenInvalidAudienceException</code> or <code>SecurityTokenInvalidLifetimeException</code> in failure cases when you want to fail validation and have other cases pass by returning <code>true</code>.
</p>
</recommendation>
<example>
<p>This example delegates <code>AudienceValidator</code> to a callable that always returns true.</p>
<sample src="delegated-security-validations-always-return-true-bad.cs" />
<p>To fix it, use a callable that performs a validation, and fails when appropriate.</p>
<sample src="delegated-security-validations-always-return-true-good.cs" />
</example>
<references>
<li><a href="https://aka.ms/wilson/tokenvalidation">azure-activedirectory-identitymodel-extensions-for-dotnet ValidatingTokens wiki</a></li>
</references>
</qhelp>

View File

@@ -0,0 +1,21 @@
/**
* @name Delegated security sensitive validations for JsonWebTokenHandler always return true, medium precision
* @description Security sensitive validations for `JsonWebTokenHandler` are being delegated to a function that seems to always return true.
* Higher precision version checks for exception throws, so less false positives are expected.
* @kind problem
* @tags security
* JsonWebTokenHandler
* manual-verification-required
* @id cs/json-webtoken-handler/delegated-security-validations-always-return-true
* @problem.severity error
* @precision high
*/
import csharp
import DataFlow
import JsonWebTokenHandlerLib
from TokenValidationParametersProperty p, CallableAlwaysReturnsTrueHigherPrecision e
where e = p.getAnAssignedValue()
select e, "JsonWebTokenHandler security-sensitive property $@ is being delegated to $@.", p,
p.getQualifiedName().toString(), e, "a callable that always returns \"true\""

View File

@@ -0,0 +1,13 @@
using System;
using Microsoft.IdentityModel.Tokens;
class TestClass
{
public void TestMethod()
{
TokenValidationParameters parameters = new TokenValidationParameters();
parameters.RequireExpirationTime = false;
parameters.ValidateAudience = false;
parameters.ValidateIssuer = false;
parameters.ValidateLifetime = false;
}
}

View File

@@ -0,0 +1,13 @@
using System;
using Microsoft.IdentityModel.Tokens;
class TestClass
{
public void TestMethod()
{
TokenValidationParameters parameters = new TokenValidationParameters();
parameters.RequireExpirationTime = true;
parameters.ValidateAudience = true;
parameters.ValidateIssuer = true;
parameters.ValidateLifetime = true;
}
}

View File

@@ -0,0 +1,27 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Token validation checks ensure that while validating tokens, all aspects are analyzed and verified. Turning off validation can lead to security holes by allowing untrusted tokens to make it through validation.</p>
</overview>
<recommendation>
<p>Set <code>Microsoft.IdentityModel.Tokens.TokenValidationParameters</code> properties <code>RequireExpirationTime</code>, <code>ValidateAudience</code>, <code>ValidateIssuer</code>, or <code>ValidateLifetime</code> to <code>true</code>. Or, remove the assignment to <code>false</code> because the default value is <code>true</code>.</p>
</recommendation>
<example>
<p>This example disabled the validation.</p>
<sample src="security-validation-disabled-bad.cs" />
<p>To fix it, do not disable the validations or use the default value.</p>
<sample src="security-validation-disabled-good.cs" />
</example>
<references>
<li><a href="https://aka.ms/wilson/tokenvalidation">azure-activedirectory-identitymodel-extensions-for-dotnet ValidatingTokens wiki</a></li>
</references>
</qhelp>

View File

@@ -0,0 +1,24 @@
/**
* @name Security sensitive JsonWebTokenHandler validations are disabled
* @description Check if secruity sensitive token validations for `JsonWebTokenHandler` are being disabled.
* @kind problem
* @tags security
* JsonWebTokenHandler
* manual-verification-required
* @id cs/json-webtoken-handler/security-validations-disabled
* @problem.severity error
* @precision high
*/
import csharp
import JsonWebTokenHandlerLib
from
FalseValueFlowsToTokenValidationParametersPropertyWriteToBypassValidation config,
DataFlow::Node source, DataFlow::Node sink,
TokenValidationParametersPropertySensitiveValidation pw
where
config.hasFlow(source, sink) and
sink.asExpr() = pw.getAnAssignedValue()
select sink, "The security sensitive property $@ is being disabled by the following value: $@.", pw,
pw.getQualifiedName().toString(), source, "false"

View File

@@ -6,7 +6,7 @@
private import IRFunctionBase
private import TInstruction
module SSA {
module Ssa {
class MemoryLocation = boolean;
predicate hasPhiInstruction(TRawInstruction blockStartInstr, MemoryLocation memoryLocation) {
@@ -17,3 +17,6 @@ module SSA {
predicate hasUnreachedInstruction(IRFunctionBase irFunc) { none() }
}
/** DEPRECATED: Alias for Ssa */
deprecated module SSA = Ssa;

View File

@@ -20,24 +20,24 @@ newtype TInstruction =
IRConstruction::Raw::hasInstruction(tag1, tag2)
} or
TUnaliasedSsaPhiInstruction(
TRawInstruction blockStartInstr, UnaliasedSsa::SSA::MemoryLocation memoryLocation
TRawInstruction blockStartInstr, UnaliasedSsa::Ssa::MemoryLocation memoryLocation
) {
UnaliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
UnaliasedSsa::Ssa::hasPhiInstruction(blockStartInstr, memoryLocation)
} or
TUnaliasedSsaChiInstruction(TRawInstruction primaryInstruction) { none() } or
TUnaliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
UnaliasedSsa::SSA::hasUnreachedInstruction(irFunc)
UnaliasedSsa::Ssa::hasUnreachedInstruction(irFunc)
} or
TAliasedSsaPhiInstruction(
TRawInstruction blockStartInstr, AliasedSsa::SSA::MemoryLocation memoryLocation
TRawInstruction blockStartInstr, AliasedSsa::Ssa::MemoryLocation memoryLocation
) {
AliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
AliasedSsa::Ssa::hasPhiInstruction(blockStartInstr, memoryLocation)
} or
TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) {
AliasedSsa::SSA::hasChiInstruction(primaryInstruction)
AliasedSsa::Ssa::hasChiInstruction(primaryInstruction)
} or
TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
AliasedSsa::SSA::hasUnreachedInstruction(irFunc)
AliasedSsa::Ssa::hasUnreachedInstruction(irFunc)
}
/**
@@ -50,7 +50,7 @@ module UnaliasedSsaInstructions {
class TPhiInstruction = TUnaliasedSsaPhiInstruction;
TPhiInstruction phiInstruction(
TRawInstruction blockStartInstr, UnaliasedSsa::SSA::MemoryLocation memoryLocation
TRawInstruction blockStartInstr, UnaliasedSsa::Ssa::MemoryLocation memoryLocation
) {
result = TUnaliasedSsaPhiInstruction(blockStartInstr, memoryLocation)
}
@@ -83,7 +83,7 @@ module AliasedSsaInstructions {
class TPhiInstruction = TAliasedSsaPhiInstruction or TUnaliasedSsaPhiInstruction;
TPhiInstruction phiInstruction(
TRawInstruction blockStartInstr, AliasedSsa::SSA::MemoryLocation memoryLocation
TRawInstruction blockStartInstr, AliasedSsa::Ssa::MemoryLocation memoryLocation
) {
result = TAliasedSsaPhiInstruction(blockStartInstr, memoryLocation)
}

View File

@@ -65,7 +65,7 @@ newtype TInstructionTag =
PointerAddTag(int index) { index in [0 .. 255] } or
ElementsAddressTag(int index) { index in [0 .. 255] } or
ConvertTag() or
GeneratedNEQTag() or
GeneratedNeqTag() or
GeneratedConstantTag() or
GeneratedBranchTag()
@@ -181,7 +181,7 @@ string getInstructionTagId(TInstructionTag tag) {
or
tag = ConvertTag() and result = "Convert"
or
tag = GeneratedNEQTag() and result = "GeneratedNEQTag"
tag = GeneratedNeqTag() and result = "GeneratedNEQTag"
or
tag = GeneratedConstantTag() and result = "GeneratedConstantTag"
or

View File

@@ -1710,7 +1710,7 @@ class TranslatedIsExpr extends TranslatedNonConstantExpr {
result = this.getParent().getChildSuccessor(this)
or
(
tag = GeneratedNEQTag() and
tag = GeneratedNeqTag() and
kind instanceof GotoEdge and
if this.hasVar()
then result = this.getInstruction(GeneratedBranchTag())
@@ -1733,7 +1733,7 @@ class TranslatedIsExpr extends TranslatedNonConstantExpr {
kind instanceof GotoEdge and
if this.hasVar()
then result = this.getPatternVarDecl().getFirstInstruction()
else result = this.getInstruction(GeneratedNEQTag())
else result = this.getInstruction(GeneratedNeqTag())
}
override Instruction getChildSuccessor(TranslatedElement child) {
@@ -1742,7 +1742,7 @@ class TranslatedIsExpr extends TranslatedNonConstantExpr {
or
this.hasVar() and
child = this.getPatternVarDecl() and
result = this.getInstruction(GeneratedNEQTag())
result = this.getInstruction(GeneratedNeqTag())
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CSharpType resultType) {
@@ -1755,7 +1755,7 @@ class TranslatedIsExpr extends TranslatedNonConstantExpr {
opcode instanceof Opcode::CheckedConvertOrNull and
resultType = getTypeForPRValue(expr.getPattern().getType())
or
tag = GeneratedNEQTag() and
tag = GeneratedNeqTag() and
opcode instanceof Opcode::CompareNE and
resultType = getTypeForPRValue(expr.getType())
or
@@ -1775,7 +1775,7 @@ class TranslatedIsExpr extends TranslatedNonConstantExpr {
result = "0"
}
override Instruction getResult() { result = this.getInstruction(GeneratedNEQTag()) }
override Instruction getResult() { result = this.getInstruction(GeneratedNeqTag()) }
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
tag = ConvertTag() and
@@ -1792,7 +1792,7 @@ class TranslatedIsExpr extends TranslatedNonConstantExpr {
result = this.getPatternVarDecl().getTargetAddress()
)
or
tag = GeneratedNEQTag() and
tag = GeneratedNeqTag() and
(
operandTag instanceof LeftOperandTag and
result = this.getInstruction(ConvertTag())
@@ -1804,7 +1804,7 @@ class TranslatedIsExpr extends TranslatedNonConstantExpr {
this.hasVar() and
tag = GeneratedBranchTag() and
operandTag instanceof ConditionOperandTag and
result = this.getInstruction(GeneratedNEQTag())
result = this.getInstruction(GeneratedNeqTag())
}
private TranslatedExpr getIsExpr() { result = getTranslatedExpr(expr.getExpr()) }

View File

@@ -1,2 +1,2 @@
private import SSAConstruction as SSA
import SSA::SsaConsistency
private import SSAConstruction as Ssa
import Ssa::SsaConsistency

View File

@@ -1135,7 +1135,7 @@ deprecated module SSAConsistency = SsaConsistency;
* These predicates are all just aliases for predicates defined in the `Cached` module. This ensures
* that all of SSA construction will be evaluated in the same stage.
*/
module SSA {
module Ssa {
class MemoryLocation = Alias::MemoryLocation;
predicate hasPhiInstruction = Cached::hasPhiInstructionCached/2;
@@ -1144,3 +1144,6 @@ module SSA {
predicate hasUnreachedInstruction = Cached::hasUnreachedInstructionCached/1;
}
/** DEPRECATED: Alias for Ssa */
deprecated module SSA = Ssa;

View File

@@ -4,10 +4,10 @@
* @id csharp/utils/model-generator/discarded-summary-models
*/
private import semmle.code.csharp.dataflow.ExternalFlow
private import internal.CaptureModels
private import internal.CaptureSummaryFlow
import semmle.code.csharp.dataflow.ExternalFlow
import internal.CaptureModels
import internal.CaptureSummaryFlow
from TargetApi api, string flow
from DataFlowTargetApi api, string flow
where flow = captureFlow(api) and hasSummary(api, false)
select flow order by flow

Some files were not shown because too many files have changed in this diff Show More