mirror of
https://github.com/github/codeql.git
synced 2026-06-25 06:37:07 +02:00
Compare commits
32 Commits
yoff/pytho
...
copilot/cr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29eba2f38e | ||
|
|
a24d222d96 | ||
|
|
bcfee987f0 | ||
|
|
e1d4fe8605 | ||
|
|
11725e8921 | ||
|
|
41297c588c | ||
|
|
53cae687f7 | ||
|
|
cfbf4a3927 | ||
|
|
b254aa7e0b | ||
|
|
d26102b263 | ||
|
|
73ab3e6888 | ||
|
|
15cbbb82eb | ||
|
|
7d95024487 | ||
|
|
06fa46f664 | ||
|
|
f6dce466a0 | ||
|
|
ec91865a7f | ||
|
|
f0576046b1 | ||
|
|
9e0e1bde28 | ||
|
|
8c24acc99d | ||
|
|
18f49ed1a2 | ||
|
|
5f31632445 | ||
|
|
6a2a337ffe | ||
|
|
cf896f243f | ||
|
|
bae2d18446 | ||
|
|
2fb5321a50 | ||
|
|
0a41157d77 | ||
|
|
07cf89568f | ||
|
|
42ebe56023 | ||
|
|
721070a191 | ||
|
|
b86cb6df63 | ||
|
|
3aaeb68553 | ||
|
|
e8923b7688 |
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,413 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Semmle.Util;
|
||||||
|
using Semmle.Util.Logging;
|
||||||
|
|
||||||
|
namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||||
|
{
|
||||||
|
internal sealed partial class FeedManager : IDisposable
|
||||||
|
{
|
||||||
|
internal const string PublicNugetOrgFeed = "https://api.nuget.org/v3/index.json";
|
||||||
|
|
||||||
|
private readonly ILogger logger;
|
||||||
|
private readonly IDotNet dotnet;
|
||||||
|
private readonly FileProvider fileProvider;
|
||||||
|
private readonly DependabotProxy? dependabotProxy;
|
||||||
|
private readonly DependencyDirectory emptyPackageDirectory;
|
||||||
|
|
||||||
|
public ImmutableHashSet<string> PrivateRegistryFeeds { get; }
|
||||||
|
public bool HasPrivateRegistryFeeds { get; }
|
||||||
|
public bool CheckNugetFeedResponsiveness { get; } = EnvironmentVariables.GetBooleanOptOut(EnvironmentVariableNames.CheckNugetFeedResponsiveness);
|
||||||
|
|
||||||
|
public FeedManager(ILogger logger, IDotNet dotnet, DependabotProxy? dependabotProxy, FileProvider fileProvider)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
this.dotnet = dotnet;
|
||||||
|
this.dependabotProxy = dependabotProxy;
|
||||||
|
this.fileProvider = fileProvider;
|
||||||
|
PrivateRegistryFeeds = dependabotProxy?.RegistryURLs.ToImmutableHashSet() ?? [];
|
||||||
|
HasPrivateRegistryFeeds = PrivateRegistryFeeds.Count > 0;
|
||||||
|
emptyPackageDirectory = new DependencyDirectory("empty", "empty package", logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string? GetDirectoryName(string path)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return new FileInfo(path).Directory?.FullName;
|
||||||
|
}
|
||||||
|
catch (Exception exc)
|
||||||
|
{
|
||||||
|
logger.LogWarning($"Failed to get directory of '{path}': {exc}");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<string> GetFeeds(Func<IList<string>> getNugetFeeds)
|
||||||
|
{
|
||||||
|
var results = getNugetFeeds();
|
||||||
|
var regex = EnabledNugetFeed();
|
||||||
|
foreach (var result in results)
|
||||||
|
{
|
||||||
|
var match = regex.Match(result);
|
||||||
|
if (!match.Success)
|
||||||
|
{
|
||||||
|
logger.LogError($"Failed to parse feed from '{result}'");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var url = match.Groups[1].Value;
|
||||||
|
if (!url.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase) &&
|
||||||
|
!url.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
logger.LogInfo($"Skipping feed '{url}' as it is not a valid URL.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(url))
|
||||||
|
{
|
||||||
|
yield return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<string> GetFeedsFromFolder(string folderPath) =>
|
||||||
|
GetFeeds(() => dotnet.GetNugetFeedsFromFolder(folderPath));
|
||||||
|
|
||||||
|
|
||||||
|
private IEnumerable<string> GetFeedsFromNugetConfig(string nugetConfigPath) =>
|
||||||
|
GetFeeds(() => dotnet.GetNugetFeeds(nugetConfigPath));
|
||||||
|
|
||||||
|
private string FeedsToRestoreArgument(IEnumerable<string> feeds)
|
||||||
|
{
|
||||||
|
// If there are no feeds, we want to override any default feeds that `dotnet restore` would use by passing a dummy source argument.
|
||||||
|
if (!feeds.Any())
|
||||||
|
{
|
||||||
|
return $" -s \"{emptyPackageDirectory.DirInfo.FullName}\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add package sources. If any are present, they override all sources specified in
|
||||||
|
// the configuration file(s).
|
||||||
|
var feedArgs = new StringBuilder();
|
||||||
|
foreach (var feed in feeds)
|
||||||
|
{
|
||||||
|
feedArgs.Append($" -s \"{feed}\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
return feedArgs.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs the list of NuGet sources to use for this restore.
|
||||||
|
/// (1) Use the feeds we get from `dotnet nuget list source`
|
||||||
|
/// (2) Use private registries, if they are configured
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">Path to project/solution</param>
|
||||||
|
/// <param name="reachableFeeds">The set of reachable NuGet feeds.</param>
|
||||||
|
/// <returns>A string representing the NuGet sources argument for the restore command.</returns>
|
||||||
|
public string? MakeRestoreSourcesArgument(string path, HashSet<string> reachableFeeds)
|
||||||
|
{
|
||||||
|
// Do not construct a set of explicit NuGet sources to use for restore.
|
||||||
|
if (!CheckNugetFeedResponsiveness && !HasPrivateRegistryFeeds)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the path specific feeds.
|
||||||
|
var folder = GetDirectoryName(path);
|
||||||
|
var feedsToConsider = folder is not null ? GetFeedsFromFolder(folder).ToHashSet() : new HashSet<string>();
|
||||||
|
|
||||||
|
if (HasPrivateRegistryFeeds)
|
||||||
|
{
|
||||||
|
feedsToConsider.UnionWith(PrivateRegistryFeeds);
|
||||||
|
}
|
||||||
|
|
||||||
|
var feedsToUse = CheckNugetFeedResponsiveness
|
||||||
|
? feedsToConsider.Where(reachableFeeds.Contains)
|
||||||
|
: feedsToConsider;
|
||||||
|
|
||||||
|
return FeedsToRestoreArgument(feedsToUse);
|
||||||
|
}
|
||||||
|
|
||||||
|
private (int initialTimeout, int tryCount) GetFeedRequestSettings(bool isFallback)
|
||||||
|
{
|
||||||
|
int timeoutMilliSeconds = isFallback && int.TryParse(Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetFeedResponsivenessInitialTimeoutForFallback), out timeoutMilliSeconds)
|
||||||
|
? timeoutMilliSeconds
|
||||||
|
: int.TryParse(Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetFeedResponsivenessInitialTimeout), out timeoutMilliSeconds)
|
||||||
|
? timeoutMilliSeconds
|
||||||
|
: 1000;
|
||||||
|
logger.LogDebug($"Initial timeout for NuGet feed reachability check is {timeoutMilliSeconds}ms.");
|
||||||
|
|
||||||
|
int tryCount = isFallback && int.TryParse(Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetFeedResponsivenessRequestCountForFallback), out tryCount)
|
||||||
|
? tryCount
|
||||||
|
: int.TryParse(Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetFeedResponsivenessRequestCount), out tryCount)
|
||||||
|
? tryCount
|
||||||
|
: 4;
|
||||||
|
logger.LogDebug($"Number of tries for NuGet feed reachability check is {tryCount}.");
|
||||||
|
|
||||||
|
return (timeoutMilliSeconds, tryCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<HttpResponseMessage> ExecuteGetRequest(string address, HttpClient httpClient, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return await httpClient.GetAsync(address, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsFeedReachable(string feed, int timeoutMilliSeconds, int tryCount, out bool isTimeout)
|
||||||
|
{
|
||||||
|
logger.LogInfo($"Checking if NuGet feed '{feed}' is reachable...");
|
||||||
|
|
||||||
|
// Configure the HttpClient to be aware of the Dependabot Proxy, if used.
|
||||||
|
HttpClientHandler httpClientHandler = new();
|
||||||
|
if (dependabotProxy != null)
|
||||||
|
{
|
||||||
|
httpClientHandler.Proxy = new WebProxy(dependabotProxy.Address);
|
||||||
|
|
||||||
|
if (dependabotProxy.Certificate != null)
|
||||||
|
{
|
||||||
|
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, _) =>
|
||||||
|
{
|
||||||
|
if (chain is null || cert is null)
|
||||||
|
{
|
||||||
|
var msg = cert is null && chain is null
|
||||||
|
? "certificate and chain"
|
||||||
|
: chain is null
|
||||||
|
? "chain"
|
||||||
|
: "certificate";
|
||||||
|
logger.LogWarning($"Dependabot proxy certificate validation failed due to missing {msg}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust;
|
||||||
|
chain.ChainPolicy.CustomTrustStore.Add(dependabotProxy.Certificate);
|
||||||
|
return chain.Build(cert);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using HttpClient client = new(httpClientHandler);
|
||||||
|
|
||||||
|
isTimeout = false;
|
||||||
|
|
||||||
|
for (var i = 0; i < tryCount; i++)
|
||||||
|
{
|
||||||
|
using var cts = new CancellationTokenSource();
|
||||||
|
cts.CancelAfter(timeoutMilliSeconds);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
logger.LogInfo($"Attempt {i + 1}/{tryCount} to reach NuGet feed '{feed}'.");
|
||||||
|
using var response = ExecuteGetRequest(feed, client, cts.Token).GetAwaiter().GetResult();
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
logger.LogInfo($"Querying NuGet feed '{feed}' succeeded.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception exc)
|
||||||
|
{
|
||||||
|
if (exc is TaskCanceledException tce &&
|
||||||
|
tce.CancellationToken == cts.Token &&
|
||||||
|
cts.Token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
logger.LogInfo($"Didn't receive answer from NuGet feed '{feed}' in {timeoutMilliSeconds}ms.");
|
||||||
|
timeoutMilliSeconds *= 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.LogInfo($"Querying NuGet feed '{feed}' failed. The reason for the failure: {exc.Message}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.LogWarning($"Didn't receive answer from NuGet feed '{feed}'. Tried it {tryCount} times.");
|
||||||
|
isTimeout = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves a list of excluded NuGet feeds from the corresponding environment variable.
|
||||||
|
/// </summary>
|
||||||
|
private HashSet<string> GetExcludedFeeds()
|
||||||
|
{
|
||||||
|
var excludedFeeds = EnvironmentVariables.GetURLs(EnvironmentVariableNames.ExcludedNugetFeedsFromResponsivenessCheck)
|
||||||
|
.ToHashSet();
|
||||||
|
|
||||||
|
if (excludedFeeds.Count > 0)
|
||||||
|
{
|
||||||
|
logger.LogInfo($"Excluded NuGet feeds from responsiveness check: {string.Join(", ", excludedFeeds.OrderBy(f => f))}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return excludedFeeds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks that we can connect to the specified NuGet feeds.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="feeds">The set of package feeds to check.</param>
|
||||||
|
/// <param name="reachableFeeds">The list of feeds that were reachable.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// True if there is a timeout when trying to reach the feeds (excluding any feeds that are configured
|
||||||
|
/// to be excluded from the check) or false otherwise.
|
||||||
|
/// </returns>
|
||||||
|
public bool CheckSpecifiedFeeds(HashSet<string> feeds, out HashSet<string> reachableFeeds)
|
||||||
|
{
|
||||||
|
// Exclude any feeds from the feed check that are configured by the corresponding environment variable.
|
||||||
|
// These feeds are always assumed to be reachable.
|
||||||
|
var excludedFeeds = GetExcludedFeeds();
|
||||||
|
|
||||||
|
HashSet<string> feedsToCheck = feeds.Where(feed =>
|
||||||
|
{
|
||||||
|
if (excludedFeeds.Contains(feed))
|
||||||
|
{
|
||||||
|
logger.LogInfo($"Not checking reachability of NuGet feed '{feed}' as it is in the list of excluded feeds.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}).ToHashSet();
|
||||||
|
|
||||||
|
reachableFeeds = GetReachableNuGetFeeds(feedsToCheck, isFallback: false, out var isTimeout).ToHashSet();
|
||||||
|
|
||||||
|
// Always consider feeds excluded for the reachability check as reachable.
|
||||||
|
reachableFeeds.UnionWith(feeds.Where(feed => excludedFeeds.Contains(feed)));
|
||||||
|
|
||||||
|
return isTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsDefaultFeedReachable()
|
||||||
|
{
|
||||||
|
if (CheckNugetFeedResponsiveness)
|
||||||
|
{
|
||||||
|
var (initialTimeout, tryCount) = GetFeedRequestSettings(isFallback: false);
|
||||||
|
return IsFeedReachable(PublicNugetOrgFeed, initialTimeout, tryCount, out var _);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests which of the feeds given by <paramref name="feedsToCheck"/> are reachable.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="feedsToCheck">The feeds to check.</param>
|
||||||
|
/// <param name="isFallback">Whether the feeds are fallback feeds or not.</param>
|
||||||
|
/// <param name="isTimeout">Whether a timeout occurred while checking the feeds.</param>
|
||||||
|
/// <returns>The list of feeds that could be reached.</returns>
|
||||||
|
private List<string> GetReachableNuGetFeeds(HashSet<string> feedsToCheck, bool isFallback, out bool isTimeout)
|
||||||
|
{
|
||||||
|
var fallbackStr = isFallback ? "fallback " : "";
|
||||||
|
logger.LogInfo($"Checking {fallbackStr}NuGet feed reachability on feeds: {string.Join(", ", feedsToCheck.OrderBy(f => f))}");
|
||||||
|
|
||||||
|
var (initialTimeout, tryCount) = GetFeedRequestSettings(isFallback);
|
||||||
|
var timeout = false;
|
||||||
|
var reachableFeeds = feedsToCheck
|
||||||
|
.Where(feed =>
|
||||||
|
{
|
||||||
|
var reachable = IsFeedReachable(feed, initialTimeout, tryCount, out var feedTimeout);
|
||||||
|
timeout |= feedTimeout;
|
||||||
|
return reachable;
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (reachableFeeds.Count == 0)
|
||||||
|
{
|
||||||
|
logger.LogWarning($"No {fallbackStr}NuGet feeds are reachable.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.LogInfo($"Reachable {fallbackStr}NuGet feeds: {string.Join(", ", reachableFeeds.OrderBy(f => f))}");
|
||||||
|
}
|
||||||
|
|
||||||
|
isTimeout = timeout;
|
||||||
|
return reachableFeeds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<string> GetReachableFallbackNugetFeeds(HashSet<string>? feedsFromNugetConfigs)
|
||||||
|
{
|
||||||
|
var fallbackFeeds = EnvironmentVariables.GetURLs(EnvironmentVariableNames.FallbackNugetFeeds).ToHashSet();
|
||||||
|
if (fallbackFeeds.Count == 0)
|
||||||
|
{
|
||||||
|
fallbackFeeds.Add(PublicNugetOrgFeed);
|
||||||
|
logger.LogInfo($"No fallback NuGet feeds specified. Adding default feed: {PublicNugetOrgFeed}");
|
||||||
|
|
||||||
|
var shouldAddNugetConfigFeeds = EnvironmentVariables.GetBooleanOptOut(EnvironmentVariableNames.AddNugetConfigFeedsToFallback);
|
||||||
|
logger.LogInfo($"Adding feeds from nuget.config to fallback restore: {shouldAddNugetConfigFeeds}");
|
||||||
|
|
||||||
|
if (shouldAddNugetConfigFeeds && feedsFromNugetConfigs?.Count > 0)
|
||||||
|
{
|
||||||
|
// There are some feeds in `feedsFromNugetConfigs` that have already been checked for reachability, we could skip those.
|
||||||
|
// But we might use different responsiveness testing settings when we try them in the fallback logic, so checking them again is safer.
|
||||||
|
fallbackFeeds.UnionWith(feedsFromNugetConfigs);
|
||||||
|
logger.LogInfo($"Using NuGet feeds from nuget.config files as fallback feeds: {string.Join(", ", feedsFromNugetConfigs.OrderBy(f => f))}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetReachableNuGetFeeds(fallbackFeeds, isFallback: true, out var _);
|
||||||
|
}
|
||||||
|
|
||||||
|
public (HashSet<string> explicitFeeds, HashSet<string> allFeeds) GetAllFeeds()
|
||||||
|
{
|
||||||
|
var nugetConfigs = fileProvider.NugetConfigs;
|
||||||
|
|
||||||
|
// Find feeds that are explicitly configured in the NuGet configuration files that we found.
|
||||||
|
var explicitFeeds = nugetConfigs
|
||||||
|
.SelectMany(GetFeedsFromNugetConfig)
|
||||||
|
.ToHashSet();
|
||||||
|
|
||||||
|
if (explicitFeeds.Count > 0)
|
||||||
|
{
|
||||||
|
logger.LogInfo($"Found {explicitFeeds.Count} NuGet feeds in nuget.config files: {string.Join(", ", explicitFeeds.OrderBy(f => f))}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.LogDebug("No NuGet feeds found in nuget.config files.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If private package registries are configured for C#, then consider those
|
||||||
|
// in addition to the ones that are configured in `nuget.config` files.
|
||||||
|
if (HasPrivateRegistryFeeds)
|
||||||
|
{
|
||||||
|
logger.LogInfo($"Found {PrivateRegistryFeeds.Count} private registry feeds configured for C#: {string.Join(", ", PrivateRegistryFeeds.OrderBy(f => f))}");
|
||||||
|
explicitFeeds.UnionWith(PrivateRegistryFeeds);
|
||||||
|
}
|
||||||
|
|
||||||
|
HashSet<string> allFeeds = [];
|
||||||
|
|
||||||
|
// Add all explicitFeeds to the set of all feeds.
|
||||||
|
allFeeds.UnionWith(explicitFeeds);
|
||||||
|
|
||||||
|
// Obtain the list of feeds from the root source directory.
|
||||||
|
// If a NuGet file is present it will be respected, otherwise we will just get the machine/environment specific feeds.
|
||||||
|
var nugetFeedsFromRoot = GetFeedsFromFolder(fileProvider.SourceDir.FullName);
|
||||||
|
allFeeds.UnionWith(nugetFeedsFromRoot);
|
||||||
|
|
||||||
|
if (nugetConfigs.Count > 0)
|
||||||
|
{
|
||||||
|
var nugetConfigFeeds = nugetConfigs
|
||||||
|
.Select(GetDirectoryName)
|
||||||
|
.Where(folder => folder != null)
|
||||||
|
.SelectMany(folder => GetFeedsFromFolder(folder!))
|
||||||
|
.ToHashSet();
|
||||||
|
|
||||||
|
allFeeds.UnionWith(nugetConfigFeeds);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.LogInfo($"Found {allFeeds.Count} NuGet feeds (with inherited ones) in nuget.config files: {string.Join(", ", allFeeds.OrderBy(f => f))}");
|
||||||
|
|
||||||
|
return (explicitFeeds, allFeeds);
|
||||||
|
}
|
||||||
|
|
||||||
|
[GeneratedRegex(@"^E\s(.*)$", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)]
|
||||||
|
private static partial Regex EnabledNugetFeed();
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
emptyPackageDirectory.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,9 +4,6 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Security.Cryptography.X509Certificates;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -19,24 +16,19 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
{
|
{
|
||||||
internal sealed partial class NugetPackageRestorer : IDisposable
|
internal sealed partial class NugetPackageRestorer : IDisposable
|
||||||
{
|
{
|
||||||
internal const string PublicNugetOrgFeed = "https://api.nuget.org/v3/index.json";
|
|
||||||
|
|
||||||
private readonly FileProvider fileProvider;
|
private readonly FileProvider fileProvider;
|
||||||
private readonly FileContent fileContent;
|
private readonly FileContent fileContent;
|
||||||
private readonly IDotNet dotnet;
|
private readonly IDotNet dotnet;
|
||||||
private readonly DependabotProxy? dependabotProxy;
|
|
||||||
private readonly IDiagnosticsWriter diagnosticsWriter;
|
private readonly IDiagnosticsWriter diagnosticsWriter;
|
||||||
private readonly DependencyDirectory legacyPackageDirectory;
|
private readonly DependencyDirectory legacyPackageDirectory;
|
||||||
private readonly DependencyDirectory missingPackageDirectory;
|
private readonly DependencyDirectory missingPackageDirectory;
|
||||||
private readonly DependencyDirectory emptyPackageDirectory;
|
|
||||||
private readonly ILogger logger;
|
private readonly ILogger logger;
|
||||||
private readonly ICompilationInfoContainer compilationInfoContainer;
|
private readonly ICompilationInfoContainer compilationInfoContainer;
|
||||||
private readonly bool checkNugetFeedResponsiveness = EnvironmentVariables.GetBooleanOptOut(EnvironmentVariableNames.CheckNugetFeedResponsiveness);
|
private readonly FeedManager feedManager;
|
||||||
private readonly ImmutableHashSet<string> privateRegistryFeeds;
|
|
||||||
private readonly bool hasPrivateRegistryFeeds;
|
|
||||||
|
|
||||||
public DependencyDirectory PackageDirectory { get; }
|
public DependencyDirectory PackageDirectory { get; }
|
||||||
|
|
||||||
|
|
||||||
public NugetPackageRestorer(
|
public NugetPackageRestorer(
|
||||||
FileProvider fileProvider,
|
FileProvider fileProvider,
|
||||||
FileContent fileContent,
|
FileContent fileContent,
|
||||||
@@ -49,9 +41,6 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
this.fileProvider = fileProvider;
|
this.fileProvider = fileProvider;
|
||||||
this.fileContent = fileContent;
|
this.fileContent = fileContent;
|
||||||
this.dotnet = dotnet;
|
this.dotnet = dotnet;
|
||||||
this.dependabotProxy = dependabotProxy;
|
|
||||||
this.privateRegistryFeeds = dependabotProxy?.RegistryURLs.ToImmutableHashSet() ?? [];
|
|
||||||
this.hasPrivateRegistryFeeds = privateRegistryFeeds.Count > 0;
|
|
||||||
this.diagnosticsWriter = diagnosticsWriter;
|
this.diagnosticsWriter = diagnosticsWriter;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.compilationInfoContainer = compilationInfoContainer;
|
this.compilationInfoContainer = compilationInfoContainer;
|
||||||
@@ -59,7 +48,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
PackageDirectory = new DependencyDirectory("packages", "package", logger);
|
PackageDirectory = new DependencyDirectory("packages", "package", logger);
|
||||||
legacyPackageDirectory = new DependencyDirectory("legacypackages", "legacy package", logger);
|
legacyPackageDirectory = new DependencyDirectory("legacypackages", "legacy package", logger);
|
||||||
missingPackageDirectory = new DependencyDirectory("missingpackages", "missing package", logger);
|
missingPackageDirectory = new DependencyDirectory("missingpackages", "missing package", logger);
|
||||||
emptyPackageDirectory = new DependencyDirectory("empty", "empty package", logger);
|
feedManager = new FeedManager(logger, dotnet, dependabotProxy, fileProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string? TryRestore(string package)
|
public string? TryRestore(string package)
|
||||||
@@ -118,20 +107,22 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
public HashSet<AssemblyLookupLocation> Restore()
|
public HashSet<AssemblyLookupLocation> Restore()
|
||||||
{
|
{
|
||||||
var assemblyLookupLocations = new HashSet<AssemblyLookupLocation>();
|
var assemblyLookupLocations = new HashSet<AssemblyLookupLocation>();
|
||||||
logger.LogInfo($"Checking NuGet feed responsiveness: {checkNugetFeedResponsiveness}");
|
logger.LogInfo($"Checking NuGet feed responsiveness: {feedManager.CheckNugetFeedResponsiveness}");
|
||||||
compilationInfoContainer.CompilationInfos.Add(("NuGet feed responsiveness checked", checkNugetFeedResponsiveness ? "1" : "0"));
|
compilationInfoContainer.CompilationInfos.Add(("NuGet feed responsiveness checked", feedManager.CheckNugetFeedResponsiveness ? "1" : "0"));
|
||||||
|
|
||||||
HashSet<string> explicitFeeds = [];
|
HashSet<string> explicitFeeds = [];
|
||||||
HashSet<string> reachableFeeds = [];
|
HashSet<string> reachableFeeds = [];
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
EmitNugetConfigDiagnostics();
|
||||||
|
|
||||||
// Find feeds that are configured in NuGet.config files and divide them into ones that
|
// Find feeds that are configured in NuGet.config files and divide them into ones that
|
||||||
// are explicitly configured for the project or by a private registry, and "all feeds"
|
// are explicitly configured for the project or by a private registry, and "all feeds"
|
||||||
// (including inherited ones) from other locations on the host outside of the working directory.
|
// (including inherited ones) from other locations on the host outside of the working directory.
|
||||||
(explicitFeeds, var allFeeds) = GetAllFeeds();
|
(explicitFeeds, var allFeeds) = feedManager.GetAllFeeds();
|
||||||
|
|
||||||
if (checkNugetFeedResponsiveness)
|
if (feedManager.CheckNugetFeedResponsiveness)
|
||||||
{
|
{
|
||||||
var inheritedFeeds = allFeeds.Except(explicitFeeds).ToHashSet();
|
var inheritedFeeds = allFeeds.Except(explicitFeeds).ToHashSet();
|
||||||
|
|
||||||
@@ -140,7 +131,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
compilationInfoContainer.CompilationInfos.Add(("Inherited NuGet feed count", inheritedFeeds.Count.ToString()));
|
compilationInfoContainer.CompilationInfos.Add(("Inherited NuGet feed count", inheritedFeeds.Count.ToString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
var timeout = CheckSpecifiedFeeds(explicitFeeds, out var reachableExplicitFeeds);
|
var timeout = feedManager.CheckSpecifiedFeeds(explicitFeeds, out var reachableExplicitFeeds);
|
||||||
reachableFeeds.UnionWith(reachableExplicitFeeds);
|
reachableFeeds.UnionWith(reachableExplicitFeeds);
|
||||||
|
|
||||||
var allExplicitReachable = explicitFeeds.Count == reachableExplicitFeeds.Count;
|
var allExplicitReachable = explicitFeeds.Count == reachableExplicitFeeds.Count;
|
||||||
@@ -157,11 +148,11 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Inherited feeds should only be used, if they are indeed reachable (as they may be environment specific).
|
// Inherited feeds should only be used, if they are indeed reachable (as they may be environment specific).
|
||||||
CheckSpecifiedFeeds(inheritedFeeds, out var reachableInheritedFeeds);
|
feedManager.CheckSpecifiedFeeds(inheritedFeeds, out var reachableInheritedFeeds);
|
||||||
reachableFeeds.UnionWith(reachableInheritedFeeds);
|
reachableFeeds.UnionWith(reachableInheritedFeeds);
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var packagesConfigRestore = PackagesConfigRestoreFactory.Create(fileProvider, legacyPackageDirectory, logger, IsDefaultFeedReachable))
|
using (var packagesConfigRestore = PackagesConfigRestoreFactory.Create(fileProvider, legacyPackageDirectory, logger, feedManager.IsDefaultFeedReachable))
|
||||||
{
|
{
|
||||||
var count = packagesConfigRestore.InstallPackages();
|
var count = packagesConfigRestore.InstallPackages();
|
||||||
|
|
||||||
@@ -215,7 +206,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
|
|
||||||
var usedPackageNames = GetAllUsedPackageDirNames(dependencies);
|
var usedPackageNames = GetAllUsedPackageDirNames(dependencies);
|
||||||
|
|
||||||
var missingPackageLocation = checkNugetFeedResponsiveness
|
var missingPackageLocation = feedManager.CheckNugetFeedResponsiveness
|
||||||
? DownloadMissingPackagesFromSpecificFeeds(usedPackageNames, explicitFeeds)
|
? DownloadMissingPackagesFromSpecificFeeds(usedPackageNames, explicitFeeds)
|
||||||
: DownloadMissingPackages(usedPackageNames);
|
: DownloadMissingPackages(usedPackageNames);
|
||||||
|
|
||||||
@@ -226,79 +217,6 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
return assemblyLookupLocations;
|
return assemblyLookupLocations;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tests which of the feeds given by <paramref name="feedsToCheck"/> are reachable.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="feedsToCheck">The feeds to check.</param>
|
|
||||||
/// <param name="isFallback">Whether the feeds are fallback feeds or not.</param>
|
|
||||||
/// <param name="isTimeout">Whether a timeout occurred while checking the feeds.</param>
|
|
||||||
/// <returns>The list of feeds that could be reached.</returns>
|
|
||||||
private List<string> GetReachableNuGetFeeds(HashSet<string> feedsToCheck, bool isFallback, out bool isTimeout)
|
|
||||||
{
|
|
||||||
var fallbackStr = isFallback ? "fallback " : "";
|
|
||||||
logger.LogInfo($"Checking {fallbackStr}NuGet feed reachability on feeds: {string.Join(", ", feedsToCheck.OrderBy(f => f))}");
|
|
||||||
|
|
||||||
var (initialTimeout, tryCount) = GetFeedRequestSettings(isFallback);
|
|
||||||
var timeout = false;
|
|
||||||
var reachableFeeds = feedsToCheck
|
|
||||||
.Where(feed =>
|
|
||||||
{
|
|
||||||
var reachable = IsFeedReachable(feed, initialTimeout, tryCount, out var feedTimeout);
|
|
||||||
timeout |= feedTimeout;
|
|
||||||
return reachable;
|
|
||||||
})
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (reachableFeeds.Count == 0)
|
|
||||||
{
|
|
||||||
logger.LogWarning($"No {fallbackStr}NuGet feeds are reachable.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logger.LogInfo($"Reachable {fallbackStr}NuGet feeds: {string.Join(", ", reachableFeeds.OrderBy(f => f))}");
|
|
||||||
}
|
|
||||||
|
|
||||||
isTimeout = timeout;
|
|
||||||
return reachableFeeds;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsDefaultFeedReachable()
|
|
||||||
{
|
|
||||||
if (checkNugetFeedResponsiveness)
|
|
||||||
{
|
|
||||||
var (initialTimeout, tryCount) = GetFeedRequestSettings(isFallback: false);
|
|
||||||
return IsFeedReachable(PublicNugetOrgFeed, initialTimeout, tryCount, out var _);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<string> GetReachableFallbackNugetFeeds(HashSet<string>? feedsFromNugetConfigs)
|
|
||||||
{
|
|
||||||
var fallbackFeeds = EnvironmentVariables.GetURLs(EnvironmentVariableNames.FallbackNugetFeeds).ToHashSet();
|
|
||||||
if (fallbackFeeds.Count == 0)
|
|
||||||
{
|
|
||||||
fallbackFeeds.Add(PublicNugetOrgFeed);
|
|
||||||
logger.LogInfo($"No fallback NuGet feeds specified. Adding default feed: {PublicNugetOrgFeed}");
|
|
||||||
|
|
||||||
var shouldAddNugetConfigFeeds = EnvironmentVariables.GetBooleanOptOut(EnvironmentVariableNames.AddNugetConfigFeedsToFallback);
|
|
||||||
logger.LogInfo($"Adding feeds from nuget.config to fallback restore: {shouldAddNugetConfigFeeds}");
|
|
||||||
|
|
||||||
if (shouldAddNugetConfigFeeds && feedsFromNugetConfigs?.Count > 0)
|
|
||||||
{
|
|
||||||
// There are some feeds in `feedsFromNugetConfigs` that have already been checked for reachability, we could skip those.
|
|
||||||
// But we might use different responsiveness testing settings when we try them in the fallback logic, so checking them again is safer.
|
|
||||||
fallbackFeeds.UnionWith(feedsFromNugetConfigs);
|
|
||||||
logger.LogInfo($"Using NuGet feeds from nuget.config files as fallback feeds: {string.Join(", ", feedsFromNugetConfigs.OrderBy(f => f))}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var reachableFallbackFeeds = GetReachableNuGetFeeds(fallbackFeeds, isFallback: true, out var _);
|
|
||||||
|
|
||||||
compilationInfoContainer.CompilationInfos.Add(("Reachable fallback NuGet feed count", reachableFallbackFeeds.Count.ToString()));
|
|
||||||
|
|
||||||
return reachableFallbackFeeds;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Executes `dotnet restore` on all solution files in solutions.
|
/// Executes `dotnet restore` on all solution files in solutions.
|
||||||
@@ -321,7 +239,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
var projects = fileProvider.Solutions.SelectMany(solution =>
|
var projects = fileProvider.Solutions.SelectMany(solution =>
|
||||||
{
|
{
|
||||||
logger.LogInfo($"Restoring solution {solution}...");
|
logger.LogInfo($"Restoring solution {solution}...");
|
||||||
var nugetSources = MakeRestoreSourcesArgument(solution, reachableFeeds);
|
var nugetSources = feedManager.MakeRestoreSourcesArgument(solution, reachableFeeds);
|
||||||
var res = dotnet.Restore(new(solution, PackageDirectory.DirInfo.FullName, ForceDotnetRefAssemblyFetching: true, NugetSources: nugetSources, TargetWindows: isWindows));
|
var res = dotnet.Restore(new(solution, PackageDirectory.DirInfo.FullName, ForceDotnetRefAssemblyFetching: true, NugetSources: nugetSources, TargetWindows: isWindows));
|
||||||
if (res.Success)
|
if (res.Success)
|
||||||
{
|
{
|
||||||
@@ -346,57 +264,6 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
return projects;
|
return projects;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string FeedsToRestoreArgument(IEnumerable<string> feeds)
|
|
||||||
{
|
|
||||||
// If there are no feeds, we want to override any default feeds that `dotnet restore` would use by passing a dummy source argument.
|
|
||||||
if (!feeds.Any())
|
|
||||||
{
|
|
||||||
return $" -s \"{emptyPackageDirectory.DirInfo.FullName}\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add package sources. If any are present, they override all sources specified in
|
|
||||||
// the configuration file(s).
|
|
||||||
var feedArgs = new StringBuilder();
|
|
||||||
foreach (var feed in feeds)
|
|
||||||
{
|
|
||||||
feedArgs.Append($" -s \"{feed}\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
return feedArgs.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructs the list of NuGet sources to use for this restore.
|
|
||||||
/// (1) Use the feeds we get from `dotnet nuget list source`
|
|
||||||
/// (2) Use private registries, if they are configured
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">Path to project/solution</param>
|
|
||||||
/// <param name="reachableFeeds">The set of reachable NuGet feeds.</param>
|
|
||||||
/// <returns>A string representing the NuGet sources argument for the restore command.</returns>
|
|
||||||
private string? MakeRestoreSourcesArgument(string path, HashSet<string> reachableFeeds)
|
|
||||||
{
|
|
||||||
// Do not construct an set of explicit NuGet sources to use for restore.
|
|
||||||
if (!checkNugetFeedResponsiveness && !hasPrivateRegistryFeeds)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the path specific feeds.
|
|
||||||
var folder = GetDirectoryName(path);
|
|
||||||
var feedsToConsider = folder is not null ? GetFeeds(() => dotnet.GetNugetFeedsFromFolder(folder)).ToHashSet() : [];
|
|
||||||
|
|
||||||
if (hasPrivateRegistryFeeds)
|
|
||||||
{
|
|
||||||
feedsToConsider.UnionWith(privateRegistryFeeds);
|
|
||||||
}
|
|
||||||
|
|
||||||
var feedsToUse = checkNugetFeedResponsiveness
|
|
||||||
? feedsToConsider.Where(reachableFeeds.Contains)
|
|
||||||
: feedsToConsider;
|
|
||||||
|
|
||||||
return FeedsToRestoreArgument(feedsToUse);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Executes `dotnet restore` on all projects in projects.
|
/// Executes `dotnet restore` on all projects in projects.
|
||||||
/// This is done in parallel for performance reasons.
|
/// This is done in parallel for performance reasons.
|
||||||
@@ -421,7 +288,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
foreach (var project in projectGroup)
|
foreach (var project in projectGroup)
|
||||||
{
|
{
|
||||||
logger.LogInfo($"Restoring project {project}...");
|
logger.LogInfo($"Restoring project {project}...");
|
||||||
var nugetSources = MakeRestoreSourcesArgument(project, reachableFeeds);
|
var nugetSources = feedManager.MakeRestoreSourcesArgument(project, reachableFeeds);
|
||||||
var res = dotnet.Restore(new(project, PackageDirectory.DirInfo.FullName, ForceDotnetRefAssemblyFetching: true, NugetSources: nugetSources, TargetWindows: isWindows));
|
var res = dotnet.Restore(new(project, PackageDirectory.DirInfo.FullName, ForceDotnetRefAssemblyFetching: true, NugetSources: nugetSources, TargetWindows: isWindows));
|
||||||
assets.AddDependenciesRange(res.AssetsFilePaths);
|
assets.AddDependenciesRange(res.AssetsFilePaths);
|
||||||
lock (sync)
|
lock (sync)
|
||||||
@@ -450,7 +317,9 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
|
|
||||||
private AssemblyLookupLocation? DownloadMissingPackagesFromSpecificFeeds(IEnumerable<string> usedPackageNames, HashSet<string>? feedsFromNugetConfigs)
|
private AssemblyLookupLocation? DownloadMissingPackagesFromSpecificFeeds(IEnumerable<string> usedPackageNames, HashSet<string>? feedsFromNugetConfigs)
|
||||||
{
|
{
|
||||||
var reachableFallbackFeeds = GetReachableFallbackNugetFeeds(feedsFromNugetConfigs);
|
var reachableFallbackFeeds = feedManager.GetReachableFallbackNugetFeeds(feedsFromNugetConfigs);
|
||||||
|
compilationInfoContainer.CompilationInfos.Add(("Reachable fallback NuGet feed count", reachableFallbackFeeds.Count.ToString()));
|
||||||
|
|
||||||
if (reachableFallbackFeeds.Count > 0)
|
if (reachableFallbackFeeds.Count > 0)
|
||||||
{
|
{
|
||||||
return DownloadMissingPackages(usedPackageNames, fallbackNugetFeeds: reachableFallbackFeeds);
|
return DownloadMissingPackages(usedPackageNames, fallbackNugetFeeds: reachableFallbackFeeds);
|
||||||
@@ -736,147 +605,6 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<HttpResponseMessage> ExecuteGetRequest(string address, HttpClient httpClient, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return await httpClient.GetAsync(address, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsFeedReachable(string feed, int timeoutMilliSeconds, int tryCount, out bool isTimeout)
|
|
||||||
{
|
|
||||||
logger.LogInfo($"Checking if NuGet feed '{feed}' is reachable...");
|
|
||||||
|
|
||||||
// Configure the HttpClient to be aware of the Dependabot Proxy, if used.
|
|
||||||
HttpClientHandler httpClientHandler = new();
|
|
||||||
if (dependabotProxy != null)
|
|
||||||
{
|
|
||||||
httpClientHandler.Proxy = new WebProxy(dependabotProxy.Address);
|
|
||||||
|
|
||||||
if (dependabotProxy.Certificate != null)
|
|
||||||
{
|
|
||||||
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, _) =>
|
|
||||||
{
|
|
||||||
if (chain is null || cert is null)
|
|
||||||
{
|
|
||||||
var msg = cert is null && chain is null
|
|
||||||
? "certificate and chain"
|
|
||||||
: chain is null
|
|
||||||
? "chain"
|
|
||||||
: "certificate";
|
|
||||||
logger.LogWarning($"Dependabot proxy certificate validation failed due to missing {msg}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust;
|
|
||||||
chain.ChainPolicy.CustomTrustStore.Add(dependabotProxy.Certificate);
|
|
||||||
return chain.Build(cert);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
using HttpClient client = new(httpClientHandler);
|
|
||||||
|
|
||||||
isTimeout = false;
|
|
||||||
|
|
||||||
for (var i = 0; i < tryCount; i++)
|
|
||||||
{
|
|
||||||
using var cts = new CancellationTokenSource();
|
|
||||||
cts.CancelAfter(timeoutMilliSeconds);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
logger.LogInfo($"Attempt {i + 1}/{tryCount} to reach NuGet feed '{feed}'.");
|
|
||||||
using var response = ExecuteGetRequest(feed, client, cts.Token).GetAwaiter().GetResult();
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
logger.LogInfo($"Querying NuGet feed '{feed}' succeeded.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (Exception exc)
|
|
||||||
{
|
|
||||||
if (exc is TaskCanceledException tce &&
|
|
||||||
tce.CancellationToken == cts.Token &&
|
|
||||||
cts.Token.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
logger.LogInfo($"Didn't receive answer from NuGet feed '{feed}' in {timeoutMilliSeconds}ms.");
|
|
||||||
timeoutMilliSeconds *= 2;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.LogInfo($"Querying NuGet feed '{feed}' failed. The reason for the failure: {exc.Message}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.LogWarning($"Didn't receive answer from NuGet feed '{feed}'. Tried it {tryCount} times.");
|
|
||||||
isTimeout = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private (int initialTimeout, int tryCount) GetFeedRequestSettings(bool isFallback)
|
|
||||||
{
|
|
||||||
int timeoutMilliSeconds = isFallback && int.TryParse(Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetFeedResponsivenessInitialTimeoutForFallback), out timeoutMilliSeconds)
|
|
||||||
? timeoutMilliSeconds
|
|
||||||
: int.TryParse(Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetFeedResponsivenessInitialTimeout), out timeoutMilliSeconds)
|
|
||||||
? timeoutMilliSeconds
|
|
||||||
: 1000;
|
|
||||||
logger.LogDebug($"Initial timeout for NuGet feed reachability check is {timeoutMilliSeconds}ms.");
|
|
||||||
|
|
||||||
int tryCount = isFallback && int.TryParse(Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetFeedResponsivenessRequestCountForFallback), out tryCount)
|
|
||||||
? tryCount
|
|
||||||
: int.TryParse(Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetFeedResponsivenessRequestCount), out tryCount)
|
|
||||||
? tryCount
|
|
||||||
: 4;
|
|
||||||
logger.LogDebug($"Number of tries for NuGet feed reachability check is {tryCount}.");
|
|
||||||
|
|
||||||
return (timeoutMilliSeconds, tryCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieves a list of excluded NuGet feeds from the corresponding environment variable.
|
|
||||||
/// </summary>
|
|
||||||
private HashSet<string> GetExcludedFeeds()
|
|
||||||
{
|
|
||||||
var excludedFeeds = EnvironmentVariables.GetURLs(EnvironmentVariableNames.ExcludedNugetFeedsFromResponsivenessCheck)
|
|
||||||
.ToHashSet();
|
|
||||||
|
|
||||||
if (excludedFeeds.Count > 0)
|
|
||||||
{
|
|
||||||
logger.LogInfo($"Excluded NuGet feeds from responsiveness check: {string.Join(", ", excludedFeeds.OrderBy(f => f))}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return excludedFeeds;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks that we can connect to the specified NuGet feeds.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="feeds">The set of package feeds to check.</param>
|
|
||||||
/// <param name="reachableFeeds">The list of feeds that were reachable.</param>
|
|
||||||
/// <returns>
|
|
||||||
/// True if there is a timeout when trying to reach the feeds (excluding any feeds that are configured
|
|
||||||
/// to be excluded from the check) or false otherwise.
|
|
||||||
/// </returns>
|
|
||||||
private bool CheckSpecifiedFeeds(HashSet<string> feeds, out HashSet<string> reachableFeeds)
|
|
||||||
{
|
|
||||||
// Exclude any feeds from the feed check that are configured by the corresponding environment variable.
|
|
||||||
// These feeds are always assumed to be reachable.
|
|
||||||
var excludedFeeds = GetExcludedFeeds();
|
|
||||||
|
|
||||||
HashSet<string> feedsToCheck = feeds.Where(feed =>
|
|
||||||
{
|
|
||||||
if (excludedFeeds.Contains(feed))
|
|
||||||
{
|
|
||||||
logger.LogInfo($"Not checking reachability of NuGet feed '{feed}' as it is in the list of excluded feeds.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}).ToHashSet();
|
|
||||||
|
|
||||||
reachableFeeds = GetReachableNuGetFeeds(feedsToCheck, isFallback: false, out var isTimeout).ToHashSet();
|
|
||||||
|
|
||||||
// Always consider feeds excluded for the reachability check as reachable.
|
|
||||||
reachableFeeds.UnionWith(feeds.Where(feed => excludedFeeds.Contains(feed)));
|
|
||||||
|
|
||||||
return isTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If <paramref name="allFeedsReachable"/> is `false`, logs this and emits a diagnostic.
|
/// If <paramref name="allFeedsReachable"/> is `false`, logs this and emits a diagnostic.
|
||||||
/// Adds a `CompilationInfos` entry either way.
|
/// Adds a `CompilationInfos` entry either way.
|
||||||
@@ -899,56 +627,15 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
compilationInfoContainer.CompilationInfos.Add(("All NuGet feeds reachable", allFeedsReachable ? "1" : "0"));
|
compilationInfoContainer.CompilationInfos.Add(("All NuGet feeds reachable", allFeedsReachable ? "1" : "0"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<string> GetFeeds(Func<IList<string>> getNugetFeeds)
|
private void EmitNugetConfigDiagnostics()
|
||||||
{
|
{
|
||||||
var results = getNugetFeeds();
|
|
||||||
var regex = EnabledNugetFeed();
|
|
||||||
foreach (var result in results)
|
|
||||||
{
|
|
||||||
var match = regex.Match(result);
|
|
||||||
if (!match.Success)
|
|
||||||
{
|
|
||||||
logger.LogError($"Failed to parse feed from '{result}'");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var url = match.Groups[1].Value;
|
|
||||||
if (!url.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase) &&
|
|
||||||
!url.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase))
|
|
||||||
{
|
|
||||||
logger.LogInfo($"Skipping feed '{url}' as it is not a valid URL.");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(url))
|
|
||||||
{
|
|
||||||
yield return url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string? GetDirectoryName(string path)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return new FileInfo(path).Directory?.FullName;
|
|
||||||
}
|
|
||||||
catch (Exception exc)
|
|
||||||
{
|
|
||||||
logger.LogWarning($"Failed to get directory of '{path}': {exc}");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private (HashSet<string> explicitFeeds, HashSet<string> allFeeds) GetAllFeeds()
|
|
||||||
{
|
|
||||||
var nugetConfigs = fileProvider.NugetConfigs;
|
|
||||||
|
|
||||||
// On systems with case-sensitive file systems (for simplicity, we assume that is Linux), the
|
// On systems with case-sensitive file systems (for simplicity, we assume that is Linux), the
|
||||||
// filenames of NuGet configuration files must be named correctly. For compatibility with projects
|
// filenames of NuGet configuration files must be named correctly. For compatibility with projects
|
||||||
// that are typically built on Windows or macOS where this doesn't matter, we accept all variants
|
// that are typically built on Windows or macOS where this doesn't matter, we accept all variants
|
||||||
// of `nuget.config` ourselves. However, `dotnet` does not. If we detect that incorrectly-named
|
// of `nuget.config` ourselves. However, `dotnet` does not. If we detect that incorrectly-named
|
||||||
// files are present, we emit a diagnostic to warn the user.
|
// files are present, we emit a diagnostic to warn the user.
|
||||||
|
var nugetConfigs = fileProvider.NugetConfigs;
|
||||||
|
|
||||||
if (SystemBuildActions.Instance.IsLinux())
|
if (SystemBuildActions.Instance.IsLinux())
|
||||||
{
|
{
|
||||||
string[] acceptedNugetConfigNames = ["nuget.config", "NuGet.config", "NuGet.Config"];
|
string[] acceptedNugetConfigNames = ["nuget.config", "NuGet.config", "NuGet.Config"];
|
||||||
@@ -978,53 +665,6 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find feeds that are explicitly configured in the NuGet configuration files that we found.
|
|
||||||
var explicitFeeds = nugetConfigs
|
|
||||||
.SelectMany(config => GetFeeds(() => dotnet.GetNugetFeeds(config)))
|
|
||||||
.ToHashSet();
|
|
||||||
|
|
||||||
if (explicitFeeds.Count > 0)
|
|
||||||
{
|
|
||||||
logger.LogInfo($"Found {explicitFeeds.Count} NuGet feeds in nuget.config files: {string.Join(", ", explicitFeeds.OrderBy(f => f))}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logger.LogDebug("No NuGet feeds found in nuget.config files.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// If private package registries are configured for C#, then consider those
|
|
||||||
// in addition to the ones that are configured in `nuget.config` files.
|
|
||||||
if (hasPrivateRegistryFeeds)
|
|
||||||
{
|
|
||||||
logger.LogInfo($"Found {privateRegistryFeeds.Count} private registry feeds configured for C#: {string.Join(", ", privateRegistryFeeds.OrderBy(f => f))}");
|
|
||||||
explicitFeeds.UnionWith(privateRegistryFeeds);
|
|
||||||
}
|
|
||||||
|
|
||||||
HashSet<string> allFeeds = [];
|
|
||||||
|
|
||||||
// Add all explicitFeeds to the set of all feeds.
|
|
||||||
allFeeds.UnionWith(explicitFeeds);
|
|
||||||
|
|
||||||
// Obtain the list of feeds from the root source directory.
|
|
||||||
// If a NuGet file is present it will be respected, otherwise we will just get the machine/environment specific feeds.
|
|
||||||
var nugetFeedsFromRoot = GetFeeds(() => dotnet.GetNugetFeedsFromFolder(fileProvider.SourceDir.FullName));
|
|
||||||
allFeeds.UnionWith(nugetFeedsFromRoot);
|
|
||||||
|
|
||||||
if (nugetConfigs.Count > 0)
|
|
||||||
{
|
|
||||||
var nugetConfigFeeds = nugetConfigs
|
|
||||||
.Select(GetDirectoryName)
|
|
||||||
.Where(folder => folder != null)
|
|
||||||
.SelectMany(folder => GetFeeds(() => dotnet.GetNugetFeedsFromFolder(folder!)))
|
|
||||||
.ToHashSet();
|
|
||||||
|
|
||||||
allFeeds.UnionWith(nugetConfigFeeds);
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.LogInfo($"Found {allFeeds.Count} NuGet feeds (with inherited ones) in nuget.config files: {string.Join(", ", allFeeds.OrderBy(f => f))}");
|
|
||||||
|
|
||||||
return (explicitFeeds, allFeeds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[GeneratedRegex(@"<TargetFramework>.*</TargetFramework>", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)]
|
[GeneratedRegex(@"<TargetFramework>.*</TargetFramework>", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)]
|
||||||
@@ -1036,15 +676,12 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
[GeneratedRegex(@"^(.+)\.(\d+\.\d+\.\d+(-(.+))?)$", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)]
|
[GeneratedRegex(@"^(.+)\.(\d+\.\d+\.\d+(-(.+))?)$", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)]
|
||||||
private static partial Regex LegacyNugetPackage();
|
private static partial Regex LegacyNugetPackage();
|
||||||
|
|
||||||
[GeneratedRegex(@"^E\s(.*)$", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)]
|
|
||||||
private static partial Regex EnabledNugetFeed();
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
PackageDirectory?.Dispose();
|
PackageDirectory?.Dispose();
|
||||||
legacyPackageDirectory?.Dispose();
|
legacyPackageDirectory?.Dispose();
|
||||||
missingPackageDirectory?.Dispose();
|
missingPackageDirectory?.Dispose();
|
||||||
emptyPackageDirectory?.Dispose();
|
feedManager.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
return new NugetExeWrapper(fileProvider, packageDirectory, logger, useDefaultFeed);
|
return new NugetExeWrapper(fileProvider, packageDirectory, logger, useDefaultFeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NoOpPackagesConfig(fileProvider, logger);
|
return new NoOpPackagesConfig(fileProvider.PackagesConfigs, logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -302,7 +302,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
private void AddDefaultPackageSource(string nugetConfig)
|
private void AddDefaultPackageSource(string nugetConfig)
|
||||||
{
|
{
|
||||||
logger.LogInfo("Adding default package source...");
|
logger.LogInfo("Adding default package source...");
|
||||||
RunMonoNugetCommand($"sources add -Name DefaultNugetOrg -Source {NugetPackageRestorer.PublicNugetOrgFeed} -ConfigFile \"{nugetConfig}\"", out _);
|
RunMonoNugetCommand($"sources add -Name DefaultNugetOrg -Source {FeedManager.PublicNugetOrgFeed} -ConfigFile \"{nugetConfig}\"", out _);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@@ -343,15 +343,15 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
|||||||
private class NoOpPackagesConfig : IPackagesConfigRestore
|
private class NoOpPackagesConfig : IPackagesConfigRestore
|
||||||
{
|
{
|
||||||
private readonly Semmle.Util.Logging.ILogger logger;
|
private readonly Semmle.Util.Logging.ILogger logger;
|
||||||
private readonly FileProvider fileProvider;
|
private readonly ICollection<string> packagesConfigs;
|
||||||
|
|
||||||
public NoOpPackagesConfig(FileProvider fileProvider, Semmle.Util.Logging.ILogger logger)
|
public NoOpPackagesConfig(ICollection<string> packagesConfigs, Semmle.Util.Logging.ILogger logger)
|
||||||
{
|
{
|
||||||
this.fileProvider = fileProvider;
|
this.packagesConfigs = packagesConfigs;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int PackageCount => fileProvider.PackagesConfigs.Count;
|
public int PackageCount => packagesConfigs.Count;
|
||||||
|
|
||||||
public int InstallPackages()
|
public int InstallPackages()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
|
|||||||
{
|
{
|
||||||
var type = Type.Create(Context, Context.GetType(Stmt.Declaration!.Type));
|
var type = Type.Create(Context, Context.GetType(Stmt.Declaration!.Type));
|
||||||
trapFile.catch_type(this, type.TypeRef, true);
|
trapFile.catch_type(this, type.TypeRef, true);
|
||||||
TypeMention.Create(Context, Stmt.Declaration!.Type, this, type);
|
Expression.Create(Context, Stmt.Declaration!.Type, this, 0);
|
||||||
}
|
}
|
||||||
else // A catch clause of the form 'catch { ... }'
|
else // A catch clause of the form 'catch { ... }'
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -995,6 +995,23 @@ class SpecificCatchClause extends CatchClause {
|
|||||||
/** Gets the local variable declaration of this catch clause, if any. */
|
/** Gets the local variable declaration of this catch clause, if any. */
|
||||||
LocalVariableDeclExpr getVariableDeclExpr() { result.getParent() = this }
|
LocalVariableDeclExpr getVariableDeclExpr() { result.getParent() = this }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the type access of this catch clause, if it has no variable declaration.
|
||||||
|
*
|
||||||
|
* For example, the type access in
|
||||||
|
*
|
||||||
|
* ```csharp
|
||||||
|
* try { ... }
|
||||||
|
* catch (IOException) { ... }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* is `IOException`.
|
||||||
|
*/
|
||||||
|
TypeAccess getTypeAccess() {
|
||||||
|
not exists(this.getVariableDeclExpr()) and
|
||||||
|
result = this.getChild(0)
|
||||||
|
}
|
||||||
|
|
||||||
override string toString() { result = "catch (...) {...}" }
|
override string toString() { result = "catch (...) {...}" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "SpecificCatchClause" }
|
override string getAPrimaryQlClass() { result = "SpecificCatchClause" }
|
||||||
|
|||||||
@@ -75,7 +75,8 @@ module Ast implements AstSig<Location> {
|
|||||||
|
|
||||||
additional predicate skipControlFlow(AstNode e) {
|
additional predicate skipControlFlow(AstNode e) {
|
||||||
e instanceof TypeAccess and
|
e instanceof TypeAccess and
|
||||||
not e instanceof TypeAccessPatternExpr
|
not e instanceof TypeAccessPatternExpr and
|
||||||
|
not any(CS::SpecificCatchClause sc).getTypeAccess() = e
|
||||||
or
|
or
|
||||||
not e.getFile().fromSource()
|
not e.getFile().fromSource()
|
||||||
}
|
}
|
||||||
@@ -90,6 +91,7 @@ module Ast implements AstSig<Location> {
|
|||||||
private AstNode getStmtChild0(Stmt s, int i) {
|
private AstNode getStmtChild0(Stmt s, int i) {
|
||||||
not s instanceof FixedStmt and
|
not s instanceof FixedStmt and
|
||||||
not s instanceof UsingBlockStmt and
|
not s instanceof UsingBlockStmt and
|
||||||
|
not skipControlFlow(result) and
|
||||||
result = s.getChild(i)
|
result = s.getChild(i)
|
||||||
or
|
or
|
||||||
s =
|
s =
|
||||||
@@ -219,7 +221,12 @@ module Ast implements AstSig<Location> {
|
|||||||
final private class FinalCatchClause = CS::CatchClause;
|
final private class FinalCatchClause = CS::CatchClause;
|
||||||
|
|
||||||
class CatchClause extends FinalCatchClause {
|
class CatchClause extends FinalCatchClause {
|
||||||
AstNode getVariable() { result = this.(CS::SpecificCatchClause).getVariableDeclExpr() }
|
AstNode getPattern() {
|
||||||
|
result = this.(CS::SpecificCatchClause).getVariableDeclExpr() or
|
||||||
|
result = this.(CS::SpecificCatchClause).getTypeAccess()
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNode getVariable() { none() }
|
||||||
|
|
||||||
Expr getCondition() { result = this.getFilterClause() }
|
Expr getCondition() { result = this.getFilterClause() }
|
||||||
|
|
||||||
|
|||||||
@@ -447,13 +447,13 @@
|
|||||||
| ExitMethods.cs:20:10:20:11 | Entry | ExitMethods.cs:20:10:20:11 | Exit | 8 |
|
| ExitMethods.cs:20:10:20:11 | Entry | ExitMethods.cs:20:10:20:11 | Exit | 8 |
|
||||||
| ExitMethods.cs:26:10:26:11 | Entry | ExitMethods.cs:26:10:26:11 | Exit | 8 |
|
| ExitMethods.cs:26:10:26:11 | Entry | ExitMethods.cs:26:10:26:11 | Exit | 8 |
|
||||||
| ExitMethods.cs:32:10:32:11 | Entry | ExitMethods.cs:32:10:32:11 | Exit | 8 |
|
| ExitMethods.cs:32:10:32:11 | Entry | ExitMethods.cs:32:10:32:11 | Exit | 8 |
|
||||||
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:44:9:47:9 | catch (...) {...} | 9 |
|
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:44:16:44:32 | access to type ArgumentException | 10 |
|
||||||
| ExitMethods.cs:38:10:38:11 | Exit | ExitMethods.cs:38:10:38:11 | Exit | 1 |
|
| ExitMethods.cs:38:10:38:11 | Exit | ExitMethods.cs:38:10:38:11 | Exit | 1 |
|
||||||
| ExitMethods.cs:38:10:38:11 | Normal Exit | ExitMethods.cs:38:10:38:11 | Normal Exit | 1 |
|
| ExitMethods.cs:38:10:38:11 | Normal Exit | ExitMethods.cs:38:10:38:11 | Normal Exit | 1 |
|
||||||
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [match] | ExitMethods.cs:46:13:46:19 | return ...; | 4 |
|
| ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [match] | ExitMethods.cs:46:13:46:19 | return ...; | 4 |
|
||||||
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] | ExitMethods.cs:48:9:51:9 | catch (...) {...} | 2 |
|
| ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [no-match] | ExitMethods.cs:48:16:48:24 | access to type Exception | 4 |
|
||||||
| ExitMethods.cs:48:9:51:9 | After catch (...) {...} [match] | ExitMethods.cs:50:13:50:19 | return ...; | 4 |
|
| ExitMethods.cs:48:16:48:24 | After access to type Exception [match] | ExitMethods.cs:50:13:50:19 | return ...; | 4 |
|
||||||
| ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] | ExitMethods.cs:38:10:38:11 | Exceptional Exit | 2 |
|
| ExitMethods.cs:48:16:48:24 | After access to type Exception [no-match] | ExitMethods.cs:38:10:38:11 | Exceptional Exit | 3 |
|
||||||
| ExitMethods.cs:54:10:54:11 | Entry | ExitMethods.cs:54:10:54:11 | Exit | 7 |
|
| ExitMethods.cs:54:10:54:11 | Entry | ExitMethods.cs:54:10:54:11 | Exit | 7 |
|
||||||
| ExitMethods.cs:60:10:60:11 | Entry | ExitMethods.cs:60:10:60:11 | Exit | 7 |
|
| ExitMethods.cs:60:10:60:11 | Entry | ExitMethods.cs:60:10:60:11 | Exit | 7 |
|
||||||
| ExitMethods.cs:66:17:66:26 | Entry | ExitMethods.cs:68:13:68:13 | access to parameter b | 5 |
|
| ExitMethods.cs:66:17:66:26 | Entry | ExitMethods.cs:68:13:68:13 | access to parameter b | 5 |
|
||||||
@@ -508,13 +508,13 @@
|
|||||||
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:19:10:19:11 | Normal Exit | 1 |
|
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:19:10:19:11 | Normal Exit | 1 |
|
||||||
| Finally.cs:21:9:51:9 | After try {...} ... | Finally.cs:20:5:52:5 | After {...} | 2 |
|
| Finally.cs:21:9:51:9 | After try {...} ... | Finally.cs:20:5:52:5 | After {...} | 2 |
|
||||||
| Finally.cs:23:13:23:37 | After call to method WriteLine | Finally.cs:24:13:24:19 | return ...; | 4 |
|
| Finally.cs:23:13:23:37 | After call to method WriteLine | Finally.cs:24:13:24:19 | return ...; | 4 |
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [match] | Finally.cs:28:13:28:18 | throw ...; | 7 |
|
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:38:26:39 | IOException ex | 2 |
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | Finally.cs:30:9:40:9 | catch (...) {...} | 2 |
|
| Finally.cs:26:38:26:39 | After IOException ex [match] | Finally.cs:28:13:28:18 | throw ...; | 6 |
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:9:29:9 | catch (...) {...} | 1 |
|
| Finally.cs:26:38:26:39 | After IOException ex [no-match] | Finally.cs:30:41:30:42 | ArgumentException ex | 4 |
|
||||||
| Finally.cs:30:9:40:9 | After catch (...) {...} [match] | Finally.cs:38:17:38:44 | throw ...; | 17 |
|
| Finally.cs:30:41:30:42 | After ArgumentException ex [match] | Finally.cs:38:17:38:44 | throw ...; | 16 |
|
||||||
| Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] | Finally.cs:41:9:43:9 | catch (...) {...} | 2 |
|
| Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] | Finally.cs:41:16:41:24 | access to type Exception | 4 |
|
||||||
| Finally.cs:41:9:43:9 | After catch (...) {...} [match] | Finally.cs:42:9:43:9 | {...} | 2 |
|
| Finally.cs:41:16:41:24 | After access to type Exception [match] | Finally.cs:42:9:43:9 | {...} | 2 |
|
||||||
| Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] | Finally.cs:46:13:46:19 | return ...; | 6 |
|
| Finally.cs:41:16:41:24 | After access to type Exception [no-match] | Finally.cs:46:13:46:19 | return ...; | 6 |
|
||||||
| Finally.cs:49:9:51:9 | {...} | Finally.cs:49:9:51:9 | After {...} | 8 |
|
| Finally.cs:49:9:51:9 | {...} | Finally.cs:49:9:51:9 | After {...} | 8 |
|
||||||
| Finally.cs:54:10:54:11 | Entry | Finally.cs:58:13:58:37 | call to method WriteLine | 8 |
|
| Finally.cs:54:10:54:11 | Entry | Finally.cs:58:13:58:37 | call to method WriteLine | 8 |
|
||||||
| Finally.cs:54:10:54:11 | Exceptional Exit | Finally.cs:54:10:54:11 | Exceptional Exit | 1 |
|
| Finally.cs:54:10:54:11 | Exceptional Exit | Finally.cs:54:10:54:11 | Exceptional Exit | 1 |
|
||||||
@@ -522,11 +522,12 @@
|
|||||||
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:54:10:54:11 | Normal Exit | 1 |
|
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:54:10:54:11 | Normal Exit | 1 |
|
||||||
| Finally.cs:56:9:71:9 | After try {...} ... | Finally.cs:55:5:72:5 | After {...} | 2 |
|
| Finally.cs:56:9:71:9 | After try {...} ... | Finally.cs:55:5:72:5 | After {...} | 2 |
|
||||||
| Finally.cs:58:13:58:37 | After call to method WriteLine | Finally.cs:59:13:59:19 | return ...; | 4 |
|
| Finally.cs:58:13:58:37 | After call to method WriteLine | Finally.cs:59:13:59:19 | return ...; | 4 |
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [match] | Finally.cs:63:13:63:18 | throw ...; | 7 |
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:38:61:39 | IOException ex | 2 |
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | Finally.cs:65:9:67:9 | catch (...) {...} | 2 |
|
| Finally.cs:61:38:61:39 | After IOException ex [match] | Finally.cs:63:13:63:18 | throw ...; | 6 |
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:9:64:9 | catch (...) {...} | 1 |
|
| Finally.cs:61:38:61:39 | After IOException ex [no-match] | Finally.cs:65:26:65:26 | Exception e | 4 |
|
||||||
| Finally.cs:65:9:67:9 | After catch (...) {...} [match] | Finally.cs:65:35:65:51 | ... != ... | 9 |
|
|
||||||
| Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | 1 |
|
| Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | 1 |
|
||||||
|
| Finally.cs:65:26:65:26 | After Exception e [match] | Finally.cs:65:35:65:51 | ... != ... | 8 |
|
||||||
|
| Finally.cs:65:26:65:26 | After Exception e [no-match] | Finally.cs:65:26:65:26 | After Exception e [no-match] | 1 |
|
||||||
| Finally.cs:65:35:65:51 | After ... != ... [false] | Finally.cs:65:35:65:51 | After ... != ... [false] | 1 |
|
| Finally.cs:65:35:65:51 | After ... != ... [false] | Finally.cs:65:35:65:51 | After ... != ... [false] | 1 |
|
||||||
| Finally.cs:65:35:65:51 | After ... != ... [true] | Finally.cs:66:9:67:9 | {...} | 2 |
|
| Finally.cs:65:35:65:51 | After ... != ... [true] | Finally.cs:66:9:67:9 | {...} | 2 |
|
||||||
| Finally.cs:69:9:71:9 | {...} | Finally.cs:69:9:71:9 | After {...} | 8 |
|
| Finally.cs:69:9:71:9 | {...} | Finally.cs:69:9:71:9 | After {...} | 8 |
|
||||||
@@ -589,9 +590,10 @@
|
|||||||
| Finally.cs:158:21:158:36 | After ... == ... [false] | Finally.cs:157:13:160:13 | After {...} | 3 |
|
| Finally.cs:158:21:158:36 | After ... == ... [false] | Finally.cs:157:13:160:13 | After {...} | 3 |
|
||||||
| Finally.cs:158:21:158:36 | After ... == ... [true] | Finally.cs:159:27:159:44 | object creation of type Exception | 5 |
|
| Finally.cs:158:21:158:36 | After ... == ... [true] | Finally.cs:159:27:159:44 | object creation of type Exception | 5 |
|
||||||
| Finally.cs:159:27:159:44 | After object creation of type Exception | Finally.cs:159:21:159:45 | throw ...; | 2 |
|
| Finally.cs:159:27:159:44 | After object creation of type Exception | Finally.cs:159:21:159:45 | throw ...; | 2 |
|
||||||
| Finally.cs:161:13:164:13 | After catch (...) {...} [match] | Finally.cs:161:39:161:54 | ... == ... | 9 |
|
| Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | Finally.cs:166:13:168:13 | After {...} | 10 |
|
||||||
| Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | Finally.cs:166:13:168:13 | After {...} | 11 |
|
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:30:161:30 | Exception e | 2 |
|
||||||
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:13:164:13 | catch (...) {...} | 1 |
|
| Finally.cs:161:30:161:30 | After Exception e [match] | Finally.cs:161:39:161:54 | ... == ... | 8 |
|
||||||
|
| Finally.cs:161:30:161:30 | After Exception e [no-match] | Finally.cs:161:30:161:30 | After Exception e [no-match] | 1 |
|
||||||
| Finally.cs:161:39:161:54 | After ... == ... [false] | Finally.cs:161:39:161:54 | After ... == ... [false] | 1 |
|
| Finally.cs:161:39:161:54 | After ... == ... [false] | Finally.cs:161:39:161:54 | After ... == ... [false] | 1 |
|
||||||
| Finally.cs:161:39:161:54 | After ... == ... [true] | Finally.cs:162:13:164:13 | After {...} | 13 |
|
| Finally.cs:161:39:161:54 | After ... == ... [true] | Finally.cs:162:13:164:13 | After {...} | 13 |
|
||||||
| Finally.cs:172:11:172:20 | Entry | Finally.cs:172:11:172:20 | Exit | 11 |
|
| Finally.cs:172:11:172:20 | Entry | Finally.cs:172:11:172:20 | Exit | 11 |
|
||||||
@@ -609,9 +611,10 @@
|
|||||||
| Finally.cs:186:21:186:22 | After access to parameter b2 [false] | Finally.cs:185:13:187:13 | After {...} | 3 |
|
| Finally.cs:186:21:186:22 | After access to parameter b2 [false] | Finally.cs:185:13:187:13 | After {...} | 3 |
|
||||||
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:186:31:186:46 | object creation of type ExceptionB | 4 |
|
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:186:31:186:46 | object creation of type ExceptionB | 4 |
|
||||||
| Finally.cs:186:31:186:46 | After object creation of type ExceptionB | Finally.cs:186:25:186:47 | throw ...; | 2 |
|
| Finally.cs:186:31:186:46 | After object creation of type ExceptionB | Finally.cs:186:25:186:47 | throw ...; | 2 |
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [match] | Finally.cs:188:38:188:39 | access to parameter b2 | 2 |
|
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] | 1 |
|
| Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] | 1 |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:13:191:13 | catch (...) {...} | 1 |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:20:188:29 | access to type ExceptionB | 2 |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | Finally.cs:188:38:188:39 | access to parameter b2 | 2 |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [no-match] | Finally.cs:188:20:188:29 | After access to type ExceptionB [no-match] | 1 |
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [false] | Finally.cs:188:38:188:39 | After access to parameter b2 [false] | 1 |
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [false] | Finally.cs:188:38:188:39 | After access to parameter b2 [false] | 1 |
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:190:21:190:22 | access to parameter b1 | 4 |
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:190:21:190:22 | access to parameter b1 | 4 |
|
||||||
| Finally.cs:190:21:190:22 | After access to parameter b1 [false] | Finally.cs:189:13:191:13 | After {...} | 3 |
|
| Finally.cs:190:21:190:22 | After access to parameter b1 [false] | Finally.cs:189:13:191:13 | After {...} | 3 |
|
||||||
@@ -633,7 +636,7 @@
|
|||||||
| Finally.cs:209:21:209:22 | After access to parameter b3 [true] | Finally.cs:209:25:209:47 | throw ...; | 6 |
|
| Finally.cs:209:21:209:22 | After access to parameter b3 [true] | Finally.cs:209:25:209:47 | throw ...; | 6 |
|
||||||
| Finally.cs:216:10:216:12 | Entry | Finally.cs:220:13:220:36 | call to method WriteLine | 8 |
|
| Finally.cs:216:10:216:12 | Entry | Finally.cs:220:13:220:36 | call to method WriteLine | 8 |
|
||||||
| Finally.cs:220:13:220:36 | After call to method WriteLine | Finally.cs:219:9:221:9 | After {...} | 3 |
|
| Finally.cs:220:13:220:36 | After call to method WriteLine | Finally.cs:219:9:221:9 | After {...} | 3 |
|
||||||
| Finally.cs:222:9:225:9 | catch {...} | Finally.cs:223:9:225:9 | After {...} | 10 |
|
| Finally.cs:222:9:225:9 | catch {...} | Finally.cs:223:9:225:9 | After {...} | 9 |
|
||||||
| Finally.cs:227:9:229:9 | {...} | Finally.cs:216:10:216:12 | Exit | 18 |
|
| Finally.cs:227:9:229:9 | {...} | Finally.cs:216:10:216:12 | Exit | 18 |
|
||||||
| Finally.cs:233:10:233:12 | Entry | Finally.cs:239:21:239:22 | access to parameter b1 | 10 |
|
| Finally.cs:233:10:233:12 | Entry | Finally.cs:239:21:239:22 | access to parameter b1 | 10 |
|
||||||
| Finally.cs:233:10:233:12 | Exceptional Exit | Finally.cs:233:10:233:12 | Exceptional Exit | 1 |
|
| Finally.cs:233:10:233:12 | Exceptional Exit | Finally.cs:233:10:233:12 | Exceptional Exit | 1 |
|
||||||
|
|||||||
@@ -264,12 +264,12 @@ conditionBlock
|
|||||||
| DefaultParam.cs:3:12:3:13 | Entry | DefaultParam.cs:3:30:3:30 | After s [no-match] | false |
|
| DefaultParam.cs:3:12:3:13 | Entry | DefaultParam.cs:3:30:3:30 | After s [no-match] | false |
|
||||||
| DefaultParam.cs:3:42:3:42 | i | DefaultParam.cs:3:42:3:42 | After i [match] | true |
|
| DefaultParam.cs:3:42:3:42 | i | DefaultParam.cs:3:42:3:42 | After i [match] | true |
|
||||||
| DefaultParam.cs:3:42:3:42 | i | DefaultParam.cs:3:42:3:42 | After i [no-match] | false |
|
| DefaultParam.cs:3:42:3:42 | i | DefaultParam.cs:3:42:3:42 | After i [no-match] | false |
|
||||||
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:44:9:47:9 | After catch (...) {...} [match] | true |
|
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [match] | true |
|
||||||
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] | false |
|
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [no-match] | false |
|
||||||
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:48:9:51:9 | After catch (...) {...} [match] | false |
|
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:48:16:48:24 | After access to type Exception [match] | false |
|
||||||
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] | false |
|
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:48:16:48:24 | After access to type Exception [no-match] | false |
|
||||||
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] | ExitMethods.cs:48:9:51:9 | After catch (...) {...} [match] | true |
|
| ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [no-match] | ExitMethods.cs:48:16:48:24 | After access to type Exception [match] | true |
|
||||||
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] | ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] | false |
|
| ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [no-match] | ExitMethods.cs:48:16:48:24 | After access to type Exception [no-match] | false |
|
||||||
| ExitMethods.cs:66:17:66:26 | Entry | ExitMethods.cs:68:13:68:13 | After access to parameter b [false] | false |
|
| ExitMethods.cs:66:17:66:26 | Entry | ExitMethods.cs:68:13:68:13 | After access to parameter b [false] | false |
|
||||||
| ExitMethods.cs:66:17:66:26 | Entry | ExitMethods.cs:68:13:68:13 | After access to parameter b [true] | true |
|
| ExitMethods.cs:66:17:66:26 | Entry | ExitMethods.cs:68:13:68:13 | After access to parameter b [true] | true |
|
||||||
| ExitMethods.cs:72:17:72:27 | Entry | ExitMethods.cs:74:13:74:13 | After access to parameter b [false] | false |
|
| ExitMethods.cs:72:17:72:27 | Entry | ExitMethods.cs:74:13:74:13 | After access to parameter b [false] | false |
|
||||||
@@ -280,29 +280,31 @@ conditionBlock
|
|||||||
| ExitMethods.cs:115:16:115:34 | Entry | ExitMethods.cs:117:16:117:30 | After call to method Contains [true] | true |
|
| ExitMethods.cs:115:16:115:34 | Entry | ExitMethods.cs:117:16:117:30 | After call to method Contains [true] | true |
|
||||||
| ExitMethods.cs:140:17:140:42 | Entry | ExitMethods.cs:142:13:142:13 | After access to parameter b [false] | false |
|
| ExitMethods.cs:140:17:140:42 | Entry | ExitMethods.cs:142:13:142:13 | After access to parameter b [false] | false |
|
||||||
| ExitMethods.cs:140:17:140:42 | Entry | ExitMethods.cs:142:13:142:13 | After access to parameter b [true] | true |
|
| ExitMethods.cs:140:17:140:42 | Entry | ExitMethods.cs:142:13:142:13 | After access to parameter b [true] | true |
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | Finally.cs:30:9:40:9 | After catch (...) {...} [match] | true |
|
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:38:26:39 | After IOException ex [match] | true |
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] | false |
|
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:38:26:39 | After IOException ex [no-match] | false |
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | Finally.cs:41:9:43:9 | After catch (...) {...} [match] | false |
|
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:30:41:30:42 | After ArgumentException ex [match] | false |
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] | false |
|
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] | false |
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:9:29:9 | After catch (...) {...} [match] | true |
|
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:41:16:41:24 | After access to type Exception [match] | false |
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | false |
|
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:41:16:41:24 | After access to type Exception [no-match] | false |
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:30:9:40:9 | After catch (...) {...} [match] | false |
|
| Finally.cs:26:38:26:39 | After IOException ex [no-match] | Finally.cs:30:41:30:42 | After ArgumentException ex [match] | true |
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] | false |
|
| Finally.cs:26:38:26:39 | After IOException ex [no-match] | Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] | false |
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:41:9:43:9 | After catch (...) {...} [match] | false |
|
| Finally.cs:26:38:26:39 | After IOException ex [no-match] | Finally.cs:41:16:41:24 | After access to type Exception [match] | false |
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] | false |
|
| Finally.cs:26:38:26:39 | After IOException ex [no-match] | Finally.cs:41:16:41:24 | After access to type Exception [no-match] | false |
|
||||||
| Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] | Finally.cs:41:9:43:9 | After catch (...) {...} [match] | true |
|
| Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] | Finally.cs:41:16:41:24 | After access to type Exception [match] | true |
|
||||||
| Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] | Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] | false |
|
| Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] | Finally.cs:41:16:41:24 | After access to type Exception [no-match] | false |
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | Finally.cs:65:9:67:9 | After catch (...) {...} [match] | true |
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:38:61:39 | After IOException ex [match] | true |
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | Finally.cs:65:35:65:51 | After ... != ... [false] | true |
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:38:61:39 | After IOException ex [no-match] | false |
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | Finally.cs:65:35:65:51 | After ... != ... [true] | true |
|
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:9:64:9 | After catch (...) {...} [match] | true |
|
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | false |
|
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:65:9:67:9 | After catch (...) {...} [match] | false |
|
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | false |
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | false |
|
||||||
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:65:26:65:26 | After Exception e [match] | false |
|
||||||
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:65:26:65:26 | After Exception e [no-match] | false |
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:65:35:65:51 | After ... != ... [false] | false |
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:65:35:65:51 | After ... != ... [false] | false |
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:65:35:65:51 | After ... != ... [true] | false |
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:65:35:65:51 | After ... != ... [true] | false |
|
||||||
| Finally.cs:65:9:67:9 | After catch (...) {...} [match] | Finally.cs:65:35:65:51 | After ... != ... [false] | false |
|
| Finally.cs:61:38:61:39 | After IOException ex [no-match] | Finally.cs:65:26:65:26 | After Exception e [match] | true |
|
||||||
| Finally.cs:65:9:67:9 | After catch (...) {...} [match] | Finally.cs:65:35:65:51 | After ... != ... [true] | true |
|
| Finally.cs:61:38:61:39 | After IOException ex [no-match] | Finally.cs:65:26:65:26 | After Exception e [no-match] | false |
|
||||||
|
| Finally.cs:61:38:61:39 | After IOException ex [no-match] | Finally.cs:65:35:65:51 | After ... != ... [false] | true |
|
||||||
|
| Finally.cs:61:38:61:39 | After IOException ex [no-match] | Finally.cs:65:35:65:51 | After ... != ... [true] | true |
|
||||||
|
| Finally.cs:65:26:65:26 | After Exception e [match] | Finally.cs:65:35:65:51 | After ... != ... [false] | false |
|
||||||
|
| Finally.cs:65:26:65:26 | After Exception e [match] | Finally.cs:65:35:65:51 | After ... != ... [true] | true |
|
||||||
| Finally.cs:77:9:100:9 | [LoopHeader] while (...) ... | Finally.cs:74:10:74:11 | Exceptional Exit | true |
|
| Finally.cs:77:9:100:9 | [LoopHeader] while (...) ... | Finally.cs:74:10:74:11 | Exceptional Exit | true |
|
||||||
| Finally.cs:77:9:100:9 | [LoopHeader] while (...) ... | Finally.cs:77:16:77:20 | After ... > ... [false] | false |
|
| Finally.cs:77:9:100:9 | [LoopHeader] while (...) ... | Finally.cs:77:16:77:20 | After ... > ... [false] | false |
|
||||||
| Finally.cs:77:9:100:9 | [LoopHeader] while (...) ... | Finally.cs:77:16:77:20 | After ... > ... [true] | true |
|
| Finally.cs:77:9:100:9 | [LoopHeader] while (...) ... | Finally.cs:77:16:77:20 | After ... > ... [true] | true |
|
||||||
@@ -354,33 +356,36 @@ conditionBlock
|
|||||||
| Finally.cs:158:21:158:31 | After access to property Length | Finally.cs:158:21:158:36 | After ... == ... [false] | false |
|
| Finally.cs:158:21:158:31 | After access to property Length | Finally.cs:158:21:158:36 | After ... == ... [false] | false |
|
||||||
| Finally.cs:158:21:158:31 | After access to property Length | Finally.cs:158:21:158:36 | After ... == ... [true] | true |
|
| Finally.cs:158:21:158:31 | After access to property Length | Finally.cs:158:21:158:36 | After ... == ... [true] | true |
|
||||||
| Finally.cs:158:21:158:31 | After access to property Length | Finally.cs:159:27:159:44 | After object creation of type Exception | true |
|
| Finally.cs:158:21:158:31 | After access to property Length | Finally.cs:159:27:159:44 | After object creation of type Exception | true |
|
||||||
| Finally.cs:161:13:164:13 | After catch (...) {...} [match] | Finally.cs:161:39:161:54 | After ... == ... [false] | false |
|
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:30:161:30 | After Exception e [match] | true |
|
||||||
| Finally.cs:161:13:164:13 | After catch (...) {...} [match] | Finally.cs:161:39:161:54 | After ... == ... [true] | true |
|
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:30:161:30 | After Exception e [no-match] | false |
|
||||||
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:13:164:13 | After catch (...) {...} [match] | true |
|
|
||||||
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:39:161:54 | After ... == ... [false] | true |
|
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:39:161:54 | After ... == ... [false] | true |
|
||||||
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:39:161:54 | After ... == ... [true] | true |
|
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:39:161:54 | After ... == ... [true] | true |
|
||||||
|
| Finally.cs:161:30:161:30 | After Exception e [match] | Finally.cs:161:39:161:54 | After ... == ... [false] | false |
|
||||||
|
| Finally.cs:161:30:161:30 | After Exception e [match] | Finally.cs:161:39:161:54 | After ... == ... [true] | true |
|
||||||
| Finally.cs:176:10:176:11 | Entry | Finally.cs:180:17:180:18 | After access to parameter b1 [false] | false |
|
| Finally.cs:176:10:176:11 | Entry | Finally.cs:180:17:180:18 | After access to parameter b1 [false] | false |
|
||||||
| Finally.cs:176:10:176:11 | Entry | Finally.cs:180:17:180:18 | After access to parameter b1 [true] | true |
|
| Finally.cs:176:10:176:11 | Entry | Finally.cs:180:17:180:18 | After access to parameter b1 [true] | true |
|
||||||
| Finally.cs:176:10:176:11 | Entry | Finally.cs:180:27:180:42 | After object creation of type ExceptionA | true |
|
| Finally.cs:176:10:176:11 | Entry | Finally.cs:180:27:180:42 | After object creation of type ExceptionA | true |
|
||||||
| Finally.cs:183:9:192:9 | {...} | Finally.cs:186:21:186:22 | After access to parameter b2 [false] | false |
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:186:21:186:22 | After access to parameter b2 [false] | false |
|
||||||
| Finally.cs:183:9:192:9 | {...} | Finally.cs:186:21:186:22 | After access to parameter b2 [true] | true |
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:186:21:186:22 | After access to parameter b2 [true] | true |
|
||||||
| Finally.cs:183:9:192:9 | {...} | Finally.cs:186:31:186:46 | After object creation of type ExceptionB | true |
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:186:31:186:46 | After object creation of type ExceptionB | true |
|
||||||
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:13:191:13 | After catch (...) {...} [match] | true |
|
|
||||||
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] | true |
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] | true |
|
||||||
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:13:191:13 | catch (...) {...} | true |
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:13:191:13 | catch (...) {...} | true |
|
||||||
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | true |
|
||||||
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:20:188:29 | After access to type ExceptionB [no-match] | true |
|
||||||
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:38:188:39 | After access to parameter b2 [false] | true |
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:38:188:39 | After access to parameter b2 [false] | true |
|
||||||
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:38:188:39 | After access to parameter b2 [true] | true |
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:38:188:39 | After access to parameter b2 [true] | true |
|
||||||
| Finally.cs:183:9:192:9 | {...} | Finally.cs:190:21:190:22 | After access to parameter b1 [false] | true |
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:190:21:190:22 | After access to parameter b1 [false] | true |
|
||||||
| Finally.cs:183:9:192:9 | {...} | Finally.cs:190:21:190:22 | After access to parameter b1 [true] | true |
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:190:21:190:22 | After access to parameter b1 [true] | true |
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [match] | Finally.cs:188:38:188:39 | After access to parameter b2 [false] | false |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | true |
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [match] | Finally.cs:188:38:188:39 | After access to parameter b2 [true] | true |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:20:188:29 | After access to type ExceptionB [no-match] | false |
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [match] | Finally.cs:190:21:190:22 | After access to parameter b1 [false] | true |
|
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [match] | Finally.cs:190:21:190:22 | After access to parameter b1 [true] | true |
|
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:13:191:13 | After catch (...) {...} [match] | true |
|
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:38:188:39 | After access to parameter b2 [false] | true |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:38:188:39 | After access to parameter b2 [false] | true |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:38:188:39 | After access to parameter b2 [true] | true |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:38:188:39 | After access to parameter b2 [true] | true |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:190:21:190:22 | After access to parameter b1 [false] | true |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:190:21:190:22 | After access to parameter b1 [false] | true |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:190:21:190:22 | After access to parameter b1 [true] | true |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:190:21:190:22 | After access to parameter b1 [true] | true |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | Finally.cs:188:38:188:39 | After access to parameter b2 [false] | false |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | Finally.cs:188:38:188:39 | After access to parameter b2 [true] | true |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | Finally.cs:190:21:190:22 | After access to parameter b1 [false] | true |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | Finally.cs:190:21:190:22 | After access to parameter b1 [true] | true |
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:190:21:190:22 | After access to parameter b1 [false] | false |
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:190:21:190:22 | After access to parameter b1 [false] | false |
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:190:21:190:22 | After access to parameter b1 [true] | true |
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:190:21:190:22 | After access to parameter b1 [true] | true |
|
||||||
| Finally.cs:195:10:195:12 | Entry | Finally.cs:199:17:199:18 | After access to parameter b1 [false] | false |
|
| Finally.cs:195:10:195:12 | Entry | Finally.cs:199:17:199:18 | After access to parameter b1 [false] | false |
|
||||||
|
|||||||
@@ -2816,16 +2816,20 @@ dominance
|
|||||||
| ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | ExitMethods.cs:44:9:47:9 | catch (...) {...} |
|
| ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | ExitMethods.cs:44:9:47:9 | catch (...) {...} |
|
||||||
| ExitMethods.cs:42:13:42:31 | ...; | ExitMethods.cs:42:13:42:30 | Before call to method ErrorAlways |
|
| ExitMethods.cs:42:13:42:31 | ...; | ExitMethods.cs:42:13:42:30 | Before call to method ErrorAlways |
|
||||||
| ExitMethods.cs:42:25:42:29 | false | ExitMethods.cs:42:13:42:30 | call to method ErrorAlways |
|
| ExitMethods.cs:42:25:42:29 | false | ExitMethods.cs:42:13:42:30 | call to method ErrorAlways |
|
||||||
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [match] | ExitMethods.cs:45:9:47:9 | {...} |
|
|
||||||
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] | ExitMethods.cs:48:9:51:9 | catch (...) {...} |
|
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] | ExitMethods.cs:48:9:51:9 | catch (...) {...} |
|
||||||
| ExitMethods.cs:44:9:47:9 | catch (...) {...} | ExitMethods.cs:44:9:47:9 | After catch (...) {...} [match] |
|
| ExitMethods.cs:44:9:47:9 | catch (...) {...} | ExitMethods.cs:44:16:44:32 | access to type ArgumentException |
|
||||||
| ExitMethods.cs:44:9:47:9 | catch (...) {...} | ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] |
|
| ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [match] | ExitMethods.cs:45:9:47:9 | {...} |
|
||||||
|
| ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [no-match] | ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] |
|
||||||
|
| ExitMethods.cs:44:16:44:32 | access to type ArgumentException | ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [match] |
|
||||||
|
| ExitMethods.cs:44:16:44:32 | access to type ArgumentException | ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [no-match] |
|
||||||
| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:46:13:46:19 | Before return ...; |
|
| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:46:13:46:19 | Before return ...; |
|
||||||
| ExitMethods.cs:46:13:46:19 | Before return ...; | ExitMethods.cs:46:13:46:19 | return ...; |
|
| ExitMethods.cs:46:13:46:19 | Before return ...; | ExitMethods.cs:46:13:46:19 | return ...; |
|
||||||
| ExitMethods.cs:48:9:51:9 | After catch (...) {...} [match] | ExitMethods.cs:49:9:51:9 | {...} |
|
|
||||||
| ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] | ExitMethods.cs:38:10:38:11 | Exceptional Exit |
|
| ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] | ExitMethods.cs:38:10:38:11 | Exceptional Exit |
|
||||||
| ExitMethods.cs:48:9:51:9 | catch (...) {...} | ExitMethods.cs:48:9:51:9 | After catch (...) {...} [match] |
|
| ExitMethods.cs:48:9:51:9 | catch (...) {...} | ExitMethods.cs:48:16:48:24 | access to type Exception |
|
||||||
| ExitMethods.cs:48:9:51:9 | catch (...) {...} | ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] |
|
| ExitMethods.cs:48:16:48:24 | After access to type Exception [match] | ExitMethods.cs:49:9:51:9 | {...} |
|
||||||
|
| ExitMethods.cs:48:16:48:24 | After access to type Exception [no-match] | ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] |
|
||||||
|
| ExitMethods.cs:48:16:48:24 | access to type Exception | ExitMethods.cs:48:16:48:24 | After access to type Exception [match] |
|
||||||
|
| ExitMethods.cs:48:16:48:24 | access to type Exception | ExitMethods.cs:48:16:48:24 | After access to type Exception [no-match] |
|
||||||
| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:50:13:50:19 | Before return ...; |
|
| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:50:13:50:19 | Before return ...; |
|
||||||
| ExitMethods.cs:50:13:50:19 | Before return ...; | ExitMethods.cs:50:13:50:19 | return ...; |
|
| ExitMethods.cs:50:13:50:19 | Before return ...; | ExitMethods.cs:50:13:50:19 | return ...; |
|
||||||
| ExitMethods.cs:54:10:54:11 | Entry | ExitMethods.cs:55:5:58:5 | {...} |
|
| ExitMethods.cs:54:10:54:11 | Entry | ExitMethods.cs:55:5:58:5 | {...} |
|
||||||
@@ -3124,20 +3128,22 @@ dominance
|
|||||||
| Finally.cs:23:13:23:38 | After ...; | Finally.cs:24:13:24:19 | Before return ...; |
|
| Finally.cs:23:13:23:38 | After ...; | Finally.cs:24:13:24:19 | Before return ...; |
|
||||||
| Finally.cs:23:31:23:36 | "Try2" | Finally.cs:23:13:23:37 | call to method WriteLine |
|
| Finally.cs:23:31:23:36 | "Try2" | Finally.cs:23:13:23:37 | call to method WriteLine |
|
||||||
| Finally.cs:24:13:24:19 | Before return ...; | Finally.cs:24:13:24:19 | return ...; |
|
| Finally.cs:24:13:24:19 | Before return ...; | Finally.cs:24:13:24:19 | return ...; |
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [match] | Finally.cs:26:38:26:39 | IOException ex |
|
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | Finally.cs:30:9:40:9 | catch (...) {...} |
|
| Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | Finally.cs:30:9:40:9 | catch (...) {...} |
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:9:29:9 | After catch (...) {...} [match] |
|
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:38:26:39 | IOException ex |
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:26:38:26:39 | After IOException ex [match] | Finally.cs:26:48:26:51 | true |
|
||||||
| Finally.cs:26:38:26:39 | IOException ex | Finally.cs:26:48:26:51 | true |
|
| Finally.cs:26:38:26:39 | After IOException ex [no-match] | Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] |
|
||||||
|
| Finally.cs:26:38:26:39 | IOException ex | Finally.cs:26:38:26:39 | After IOException ex [match] |
|
||||||
|
| Finally.cs:26:38:26:39 | IOException ex | Finally.cs:26:38:26:39 | After IOException ex [no-match] |
|
||||||
| Finally.cs:26:48:26:51 | After true [true] | Finally.cs:27:9:29:9 | {...} |
|
| Finally.cs:26:48:26:51 | After true [true] | Finally.cs:27:9:29:9 | {...} |
|
||||||
| Finally.cs:26:48:26:51 | true | Finally.cs:26:48:26:51 | After true [true] |
|
| Finally.cs:26:48:26:51 | true | Finally.cs:26:48:26:51 | After true [true] |
|
||||||
| Finally.cs:27:9:29:9 | {...} | Finally.cs:28:13:28:18 | Before throw ...; |
|
| Finally.cs:27:9:29:9 | {...} | Finally.cs:28:13:28:18 | Before throw ...; |
|
||||||
| Finally.cs:28:13:28:18 | Before throw ...; | Finally.cs:28:13:28:18 | throw ...; |
|
| Finally.cs:28:13:28:18 | Before throw ...; | Finally.cs:28:13:28:18 | throw ...; |
|
||||||
| Finally.cs:30:9:40:9 | After catch (...) {...} [match] | Finally.cs:30:41:30:42 | ArgumentException ex |
|
|
||||||
| Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] | Finally.cs:41:9:43:9 | catch (...) {...} |
|
| Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] | Finally.cs:41:9:43:9 | catch (...) {...} |
|
||||||
| Finally.cs:30:9:40:9 | catch (...) {...} | Finally.cs:30:9:40:9 | After catch (...) {...} [match] |
|
| Finally.cs:30:9:40:9 | catch (...) {...} | Finally.cs:30:41:30:42 | ArgumentException ex |
|
||||||
| Finally.cs:30:9:40:9 | catch (...) {...} | Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:30:41:30:42 | After ArgumentException ex [match] | Finally.cs:31:9:40:9 | {...} |
|
||||||
| Finally.cs:30:41:30:42 | ArgumentException ex | Finally.cs:31:9:40:9 | {...} |
|
| Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] | Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] |
|
||||||
|
| Finally.cs:30:41:30:42 | ArgumentException ex | Finally.cs:30:41:30:42 | After ArgumentException ex [match] |
|
||||||
|
| Finally.cs:30:41:30:42 | ArgumentException ex | Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] |
|
||||||
| Finally.cs:31:9:40:9 | {...} | Finally.cs:32:13:39:13 | try {...} ... |
|
| Finally.cs:31:9:40:9 | {...} | Finally.cs:32:13:39:13 | try {...} ... |
|
||||||
| Finally.cs:32:13:39:13 | try {...} ... | Finally.cs:33:13:35:13 | {...} |
|
| Finally.cs:32:13:39:13 | try {...} ... | Finally.cs:33:13:35:13 | {...} |
|
||||||
| Finally.cs:33:13:35:13 | {...} | Finally.cs:34:17:34:32 | if (...) ... |
|
| Finally.cs:33:13:35:13 | {...} | Finally.cs:34:17:34:32 | if (...) ... |
|
||||||
@@ -3152,12 +3158,13 @@ dominance
|
|||||||
| Finally.cs:38:23:38:43 | Before object creation of type Exception | Finally.cs:38:37:38:42 | "Boo!" |
|
| Finally.cs:38:23:38:43 | Before object creation of type Exception | Finally.cs:38:37:38:42 | "Boo!" |
|
||||||
| Finally.cs:38:23:38:43 | object creation of type Exception | Finally.cs:38:23:38:43 | After object creation of type Exception |
|
| Finally.cs:38:23:38:43 | object creation of type Exception | Finally.cs:38:23:38:43 | After object creation of type Exception |
|
||||||
| Finally.cs:38:37:38:42 | "Boo!" | Finally.cs:38:23:38:43 | object creation of type Exception |
|
| Finally.cs:38:37:38:42 | "Boo!" | Finally.cs:38:23:38:43 | object creation of type Exception |
|
||||||
| Finally.cs:41:9:43:9 | After catch (...) {...} [match] | Finally.cs:42:9:43:9 | {...} |
|
|
||||||
| Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] | Finally.cs:44:9:47:9 | catch {...} |
|
| Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] | Finally.cs:44:9:47:9 | catch {...} |
|
||||||
| Finally.cs:41:9:43:9 | catch (...) {...} | Finally.cs:41:9:43:9 | After catch (...) {...} [match] |
|
| Finally.cs:41:9:43:9 | catch (...) {...} | Finally.cs:41:16:41:24 | access to type Exception |
|
||||||
| Finally.cs:41:9:43:9 | catch (...) {...} | Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:41:16:41:24 | After access to type Exception [match] | Finally.cs:42:9:43:9 | {...} |
|
||||||
| Finally.cs:44:9:47:9 | After catch {...} [match] | Finally.cs:45:9:47:9 | {...} |
|
| Finally.cs:41:16:41:24 | After access to type Exception [no-match] | Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] |
|
||||||
| Finally.cs:44:9:47:9 | catch {...} | Finally.cs:44:9:47:9 | After catch {...} [match] |
|
| Finally.cs:41:16:41:24 | access to type Exception | Finally.cs:41:16:41:24 | After access to type Exception [match] |
|
||||||
|
| Finally.cs:41:16:41:24 | access to type Exception | Finally.cs:41:16:41:24 | After access to type Exception [no-match] |
|
||||||
|
| Finally.cs:44:9:47:9 | catch {...} | Finally.cs:45:9:47:9 | {...} |
|
||||||
| Finally.cs:45:9:47:9 | {...} | Finally.cs:46:13:46:19 | Before return ...; |
|
| Finally.cs:45:9:47:9 | {...} | Finally.cs:46:13:46:19 | Before return ...; |
|
||||||
| Finally.cs:46:13:46:19 | Before return ...; | Finally.cs:46:13:46:19 | return ...; |
|
| Finally.cs:46:13:46:19 | Before return ...; | Finally.cs:46:13:46:19 | return ...; |
|
||||||
| Finally.cs:49:9:51:9 | After {...} | Finally.cs:19:10:19:11 | Exceptional Exit |
|
| Finally.cs:49:9:51:9 | After {...} | Finally.cs:19:10:19:11 | Exceptional Exit |
|
||||||
@@ -3183,19 +3190,20 @@ dominance
|
|||||||
| Finally.cs:58:13:58:38 | After ...; | Finally.cs:59:13:59:19 | Before return ...; |
|
| Finally.cs:58:13:58:38 | After ...; | Finally.cs:59:13:59:19 | Before return ...; |
|
||||||
| Finally.cs:58:31:58:36 | "Try3" | Finally.cs:58:13:58:37 | call to method WriteLine |
|
| Finally.cs:58:31:58:36 | "Try3" | Finally.cs:58:13:58:37 | call to method WriteLine |
|
||||||
| Finally.cs:59:13:59:19 | Before return ...; | Finally.cs:59:13:59:19 | return ...; |
|
| Finally.cs:59:13:59:19 | Before return ...; | Finally.cs:59:13:59:19 | return ...; |
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [match] | Finally.cs:61:38:61:39 | IOException ex |
|
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | Finally.cs:65:9:67:9 | catch (...) {...} |
|
| Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | Finally.cs:65:9:67:9 | catch (...) {...} |
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:9:64:9 | After catch (...) {...} [match] |
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:38:61:39 | IOException ex |
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:61:38:61:39 | After IOException ex [match] | Finally.cs:61:48:61:51 | true |
|
||||||
| Finally.cs:61:38:61:39 | IOException ex | Finally.cs:61:48:61:51 | true |
|
| Finally.cs:61:38:61:39 | After IOException ex [no-match] | Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] |
|
||||||
|
| Finally.cs:61:38:61:39 | IOException ex | Finally.cs:61:38:61:39 | After IOException ex [match] |
|
||||||
|
| Finally.cs:61:38:61:39 | IOException ex | Finally.cs:61:38:61:39 | After IOException ex [no-match] |
|
||||||
| Finally.cs:61:48:61:51 | After true [true] | Finally.cs:62:9:64:9 | {...} |
|
| Finally.cs:61:48:61:51 | After true [true] | Finally.cs:62:9:64:9 | {...} |
|
||||||
| Finally.cs:61:48:61:51 | true | Finally.cs:61:48:61:51 | After true [true] |
|
| Finally.cs:61:48:61:51 | true | Finally.cs:61:48:61:51 | After true [true] |
|
||||||
| Finally.cs:62:9:64:9 | {...} | Finally.cs:63:13:63:18 | Before throw ...; |
|
| Finally.cs:62:9:64:9 | {...} | Finally.cs:63:13:63:18 | Before throw ...; |
|
||||||
| Finally.cs:63:13:63:18 | Before throw ...; | Finally.cs:63:13:63:18 | throw ...; |
|
| Finally.cs:63:13:63:18 | Before throw ...; | Finally.cs:63:13:63:18 | throw ...; |
|
||||||
| Finally.cs:65:9:67:9 | After catch (...) {...} [match] | Finally.cs:65:26:65:26 | Exception e |
|
| Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:65:26:65:26 | Exception e |
|
||||||
| Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:65:9:67:9 | After catch (...) {...} [match] |
|
| Finally.cs:65:26:65:26 | After Exception e [match] | Finally.cs:65:35:65:51 | Before ... != ... |
|
||||||
| Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:65:26:65:26 | Exception e | Finally.cs:65:26:65:26 | After Exception e [match] |
|
||||||
| Finally.cs:65:26:65:26 | Exception e | Finally.cs:65:35:65:51 | Before ... != ... |
|
| Finally.cs:65:26:65:26 | Exception e | Finally.cs:65:26:65:26 | After Exception e [no-match] |
|
||||||
| Finally.cs:65:35:65:35 | access to local variable e | Finally.cs:65:35:65:43 | access to property Message |
|
| Finally.cs:65:35:65:35 | access to local variable e | Finally.cs:65:35:65:43 | access to property Message |
|
||||||
| Finally.cs:65:35:65:43 | After access to property Message | Finally.cs:65:48:65:51 | null |
|
| Finally.cs:65:35:65:43 | After access to property Message | Finally.cs:65:48:65:51 | null |
|
||||||
| Finally.cs:65:35:65:43 | Before access to property Message | Finally.cs:65:35:65:35 | access to local variable e |
|
| Finally.cs:65:35:65:43 | Before access to property Message | Finally.cs:65:35:65:35 | access to local variable e |
|
||||||
@@ -3468,11 +3476,11 @@ dominance
|
|||||||
| Finally.cs:159:27:159:44 | Before object creation of type Exception | Finally.cs:159:41:159:43 | "1" |
|
| Finally.cs:159:27:159:44 | Before object creation of type Exception | Finally.cs:159:41:159:43 | "1" |
|
||||||
| Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:159:27:159:44 | After object creation of type Exception |
|
| Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:159:27:159:44 | After object creation of type Exception |
|
||||||
| Finally.cs:159:41:159:43 | "1" | Finally.cs:159:27:159:44 | object creation of type Exception |
|
| Finally.cs:159:41:159:43 | "1" | Finally.cs:159:27:159:44 | object creation of type Exception |
|
||||||
| Finally.cs:161:13:164:13 | After catch (...) {...} [match] | Finally.cs:161:30:161:30 | Exception e |
|
|
||||||
| Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | Finally.cs:165:13:168:13 | catch {...} |
|
| Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | Finally.cs:165:13:168:13 | catch {...} |
|
||||||
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:13:164:13 | After catch (...) {...} [match] |
|
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:30:161:30 | Exception e |
|
||||||
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] |
|
| Finally.cs:161:30:161:30 | After Exception e [match] | Finally.cs:161:39:161:54 | Before ... == ... |
|
||||||
| Finally.cs:161:30:161:30 | Exception e | Finally.cs:161:39:161:54 | Before ... == ... |
|
| Finally.cs:161:30:161:30 | Exception e | Finally.cs:161:30:161:30 | After Exception e [match] |
|
||||||
|
| Finally.cs:161:30:161:30 | Exception e | Finally.cs:161:30:161:30 | After Exception e [no-match] |
|
||||||
| Finally.cs:161:39:161:39 | access to local variable e | Finally.cs:161:39:161:47 | access to property Message |
|
| Finally.cs:161:39:161:39 | access to local variable e | Finally.cs:161:39:161:47 | access to property Message |
|
||||||
| Finally.cs:161:39:161:47 | After access to property Message | Finally.cs:161:52:161:54 | "1" |
|
| Finally.cs:161:39:161:47 | After access to property Message | Finally.cs:161:52:161:54 | "1" |
|
||||||
| Finally.cs:161:39:161:47 | Before access to property Message | Finally.cs:161:39:161:39 | access to local variable e |
|
| Finally.cs:161:39:161:47 | Before access to property Message | Finally.cs:161:39:161:39 | access to local variable e |
|
||||||
@@ -3493,8 +3501,7 @@ dominance
|
|||||||
| Finally.cs:163:35:163:41 | Before access to array element | Finally.cs:163:35:163:38 | access to parameter args |
|
| Finally.cs:163:35:163:41 | Before access to array element | Finally.cs:163:35:163:38 | access to parameter args |
|
||||||
| Finally.cs:163:35:163:41 | access to array element | Finally.cs:163:35:163:41 | After access to array element |
|
| Finally.cs:163:35:163:41 | access to array element | Finally.cs:163:35:163:41 | After access to array element |
|
||||||
| Finally.cs:163:40:163:40 | 0 | Finally.cs:163:35:163:41 | access to array element |
|
| Finally.cs:163:40:163:40 | 0 | Finally.cs:163:35:163:41 | access to array element |
|
||||||
| Finally.cs:165:13:168:13 | After catch {...} [match] | Finally.cs:166:13:168:13 | {...} |
|
| Finally.cs:165:13:168:13 | catch {...} | Finally.cs:166:13:168:13 | {...} |
|
||||||
| Finally.cs:165:13:168:13 | catch {...} | Finally.cs:165:13:168:13 | After catch {...} [match] |
|
|
||||||
| Finally.cs:166:13:168:13 | {...} | Finally.cs:167:17:167:38 | ...; |
|
| Finally.cs:166:13:168:13 | {...} | Finally.cs:167:17:167:38 | ...; |
|
||||||
| Finally.cs:167:17:167:37 | After call to method WriteLine | Finally.cs:167:17:167:38 | After ...; |
|
| Finally.cs:167:17:167:37 | After call to method WriteLine | Finally.cs:167:17:167:38 | After ...; |
|
||||||
| Finally.cs:167:17:167:37 | Before call to method WriteLine | Finally.cs:167:35:167:36 | "" |
|
| Finally.cs:167:17:167:37 | Before call to method WriteLine | Finally.cs:167:35:167:36 | "" |
|
||||||
@@ -3566,9 +3573,10 @@ dominance
|
|||||||
| Finally.cs:186:31:186:46 | Before object creation of type ExceptionB | Finally.cs:186:31:186:46 | object creation of type ExceptionB |
|
| Finally.cs:186:31:186:46 | Before object creation of type ExceptionB | Finally.cs:186:31:186:46 | object creation of type ExceptionB |
|
||||||
| Finally.cs:186:31:186:46 | object creation of type ExceptionB | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
| Finally.cs:186:31:186:46 | object creation of type ExceptionB | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
||||||
| Finally.cs:186:31:186:46 | object creation of type ExceptionB | Finally.cs:188:13:191:13 | catch (...) {...} |
|
| Finally.cs:186:31:186:46 | object creation of type ExceptionB | Finally.cs:188:13:191:13 | catch (...) {...} |
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [match] | Finally.cs:188:38:188:39 | access to parameter b2 |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:20:188:29 | access to type ExceptionB |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:13:191:13 | After catch (...) {...} [match] |
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | Finally.cs:188:38:188:39 | access to parameter b2 |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] |
|
| Finally.cs:188:20:188:29 | access to type ExceptionB | Finally.cs:188:20:188:29 | After access to type ExceptionB [match] |
|
||||||
|
| Finally.cs:188:20:188:29 | access to type ExceptionB | Finally.cs:188:20:188:29 | After access to type ExceptionB [no-match] |
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:189:13:191:13 | {...} |
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:189:13:191:13 | {...} |
|
||||||
| Finally.cs:188:38:188:39 | access to parameter b2 | Finally.cs:188:38:188:39 | After access to parameter b2 [false] |
|
| Finally.cs:188:38:188:39 | access to parameter b2 | Finally.cs:188:38:188:39 | After access to parameter b2 [false] |
|
||||||
| Finally.cs:188:38:188:39 | access to parameter b2 | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
| Finally.cs:188:38:188:39 | access to parameter b2 | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
||||||
@@ -3663,8 +3671,7 @@ dominance
|
|||||||
| Finally.cs:220:13:220:37 | ...; | Finally.cs:220:13:220:36 | Before call to method WriteLine |
|
| Finally.cs:220:13:220:37 | ...; | Finally.cs:220:13:220:36 | Before call to method WriteLine |
|
||||||
| Finally.cs:220:13:220:37 | After ...; | Finally.cs:219:9:221:9 | After {...} |
|
| Finally.cs:220:13:220:37 | After ...; | Finally.cs:219:9:221:9 | After {...} |
|
||||||
| Finally.cs:220:31:220:35 | "Try" | Finally.cs:220:13:220:36 | call to method WriteLine |
|
| Finally.cs:220:31:220:35 | "Try" | Finally.cs:220:13:220:36 | call to method WriteLine |
|
||||||
| Finally.cs:222:9:225:9 | After catch {...} [match] | Finally.cs:223:9:225:9 | {...} |
|
| Finally.cs:222:9:225:9 | catch {...} | Finally.cs:223:9:225:9 | {...} |
|
||||||
| Finally.cs:222:9:225:9 | catch {...} | Finally.cs:222:9:225:9 | After catch {...} [match] |
|
|
||||||
| Finally.cs:223:9:225:9 | {...} | Finally.cs:224:13:224:39 | ...; |
|
| Finally.cs:223:9:225:9 | {...} | Finally.cs:224:13:224:39 | ...; |
|
||||||
| Finally.cs:224:13:224:38 | After call to method WriteLine | Finally.cs:224:13:224:39 | After ...; |
|
| Finally.cs:224:13:224:38 | After call to method WriteLine | Finally.cs:224:13:224:39 | After ...; |
|
||||||
| Finally.cs:224:13:224:38 | Before call to method WriteLine | Finally.cs:224:31:224:37 | "Catch" |
|
| Finally.cs:224:13:224:38 | Before call to method WriteLine | Finally.cs:224:31:224:37 | "Catch" |
|
||||||
@@ -10615,13 +10622,17 @@ postDominance
|
|||||||
| ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | ExitMethods.cs:42:25:42:29 | false |
|
| ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | ExitMethods.cs:42:25:42:29 | false |
|
||||||
| ExitMethods.cs:42:13:42:31 | ...; | ExitMethods.cs:41:9:43:9 | {...} |
|
| ExitMethods.cs:42:13:42:31 | ...; | ExitMethods.cs:41:9:43:9 | {...} |
|
||||||
| ExitMethods.cs:42:25:42:29 | false | ExitMethods.cs:42:13:42:30 | Before call to method ErrorAlways |
|
| ExitMethods.cs:42:25:42:29 | false | ExitMethods.cs:42:13:42:30 | Before call to method ErrorAlways |
|
||||||
|
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] | ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [no-match] |
|
||||||
| ExitMethods.cs:44:9:47:9 | catch (...) {...} | ExitMethods.cs:42:13:42:30 | call to method ErrorAlways |
|
| ExitMethods.cs:44:9:47:9 | catch (...) {...} | ExitMethods.cs:42:13:42:30 | call to method ErrorAlways |
|
||||||
| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:44:9:47:9 | After catch (...) {...} [match] |
|
| ExitMethods.cs:44:16:44:32 | access to type ArgumentException | ExitMethods.cs:44:9:47:9 | catch (...) {...} |
|
||||||
|
| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [match] |
|
||||||
| ExitMethods.cs:46:13:46:19 | Before return ...; | ExitMethods.cs:45:9:47:9 | {...} |
|
| ExitMethods.cs:46:13:46:19 | Before return ...; | ExitMethods.cs:45:9:47:9 | {...} |
|
||||||
| ExitMethods.cs:46:13:46:19 | return ...; | ExitMethods.cs:46:13:46:19 | Before return ...; |
|
| ExitMethods.cs:46:13:46:19 | return ...; | ExitMethods.cs:46:13:46:19 | Before return ...; |
|
||||||
| ExitMethods.cs:48:9:51:9 | After catch (...) {...} [match] | ExitMethods.cs:48:9:51:9 | catch (...) {...} |
|
| ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] | ExitMethods.cs:48:16:48:24 | After access to type Exception [no-match] |
|
||||||
| ExitMethods.cs:48:9:51:9 | catch (...) {...} | ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] |
|
| ExitMethods.cs:48:9:51:9 | catch (...) {...} | ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] |
|
||||||
| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:48:9:51:9 | After catch (...) {...} [match] |
|
| ExitMethods.cs:48:16:48:24 | After access to type Exception [match] | ExitMethods.cs:48:16:48:24 | access to type Exception |
|
||||||
|
| ExitMethods.cs:48:16:48:24 | access to type Exception | ExitMethods.cs:48:9:51:9 | catch (...) {...} |
|
||||||
|
| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:48:16:48:24 | After access to type Exception [match] |
|
||||||
| ExitMethods.cs:50:13:50:19 | Before return ...; | ExitMethods.cs:49:9:51:9 | {...} |
|
| ExitMethods.cs:50:13:50:19 | Before return ...; | ExitMethods.cs:49:9:51:9 | {...} |
|
||||||
| ExitMethods.cs:50:13:50:19 | return ...; | ExitMethods.cs:50:13:50:19 | Before return ...; |
|
| ExitMethods.cs:50:13:50:19 | return ...; | ExitMethods.cs:50:13:50:19 | Before return ...; |
|
||||||
| ExitMethods.cs:54:10:54:11 | Exceptional Exit | ExitMethods.cs:56:9:56:22 | call to method ErrorAlways2 |
|
| ExitMethods.cs:54:10:54:11 | Exceptional Exit | ExitMethods.cs:56:9:56:22 | call to method ErrorAlways2 |
|
||||||
@@ -10911,15 +10922,17 @@ postDominance
|
|||||||
| Finally.cs:23:31:23:36 | "Try2" | Finally.cs:23:13:23:37 | Before call to method WriteLine |
|
| Finally.cs:23:31:23:36 | "Try2" | Finally.cs:23:13:23:37 | Before call to method WriteLine |
|
||||||
| Finally.cs:24:13:24:19 | Before return ...; | Finally.cs:23:13:23:38 | After ...; |
|
| Finally.cs:24:13:24:19 | Before return ...; | Finally.cs:23:13:23:38 | After ...; |
|
||||||
| Finally.cs:24:13:24:19 | return ...; | Finally.cs:24:13:24:19 | Before return ...; |
|
| Finally.cs:24:13:24:19 | return ...; | Finally.cs:24:13:24:19 | Before return ...; |
|
||||||
| Finally.cs:26:38:26:39 | IOException ex | Finally.cs:26:9:29:9 | After catch (...) {...} [match] |
|
| Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | Finally.cs:26:38:26:39 | After IOException ex [no-match] |
|
||||||
|
| Finally.cs:26:38:26:39 | IOException ex | Finally.cs:26:9:29:9 | catch (...) {...} |
|
||||||
| Finally.cs:26:48:26:51 | After true [true] | Finally.cs:26:48:26:51 | true |
|
| Finally.cs:26:48:26:51 | After true [true] | Finally.cs:26:48:26:51 | true |
|
||||||
| Finally.cs:26:48:26:51 | true | Finally.cs:26:38:26:39 | IOException ex |
|
| Finally.cs:26:48:26:51 | true | Finally.cs:26:38:26:39 | After IOException ex [match] |
|
||||||
| Finally.cs:27:9:29:9 | {...} | Finally.cs:26:48:26:51 | After true [true] |
|
| Finally.cs:27:9:29:9 | {...} | Finally.cs:26:48:26:51 | After true [true] |
|
||||||
| Finally.cs:28:13:28:18 | Before throw ...; | Finally.cs:27:9:29:9 | {...} |
|
| Finally.cs:28:13:28:18 | Before throw ...; | Finally.cs:27:9:29:9 | {...} |
|
||||||
| Finally.cs:28:13:28:18 | throw ...; | Finally.cs:28:13:28:18 | Before throw ...; |
|
| Finally.cs:28:13:28:18 | throw ...; | Finally.cs:28:13:28:18 | Before throw ...; |
|
||||||
|
| Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] | Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] |
|
||||||
| Finally.cs:30:9:40:9 | catch (...) {...} | Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:30:9:40:9 | catch (...) {...} | Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] |
|
||||||
| Finally.cs:30:41:30:42 | ArgumentException ex | Finally.cs:30:9:40:9 | After catch (...) {...} [match] |
|
| Finally.cs:30:41:30:42 | ArgumentException ex | Finally.cs:30:9:40:9 | catch (...) {...} |
|
||||||
| Finally.cs:31:9:40:9 | {...} | Finally.cs:30:41:30:42 | ArgumentException ex |
|
| Finally.cs:31:9:40:9 | {...} | Finally.cs:30:41:30:42 | After ArgumentException ex [match] |
|
||||||
| Finally.cs:32:13:39:13 | try {...} ... | Finally.cs:31:9:40:9 | {...} |
|
| Finally.cs:32:13:39:13 | try {...} ... | Finally.cs:31:9:40:9 | {...} |
|
||||||
| Finally.cs:33:13:35:13 | {...} | Finally.cs:32:13:39:13 | try {...} ... |
|
| Finally.cs:33:13:35:13 | {...} | Finally.cs:32:13:39:13 | try {...} ... |
|
||||||
| Finally.cs:34:17:34:32 | if (...) ... | Finally.cs:33:13:35:13 | {...} |
|
| Finally.cs:34:17:34:32 | if (...) ... | Finally.cs:33:13:35:13 | {...} |
|
||||||
@@ -10934,11 +10947,12 @@ postDominance
|
|||||||
| Finally.cs:38:23:38:43 | Before object creation of type Exception | Finally.cs:38:17:38:44 | Before throw ...; |
|
| Finally.cs:38:23:38:43 | Before object creation of type Exception | Finally.cs:38:17:38:44 | Before throw ...; |
|
||||||
| Finally.cs:38:23:38:43 | object creation of type Exception | Finally.cs:38:37:38:42 | "Boo!" |
|
| Finally.cs:38:23:38:43 | object creation of type Exception | Finally.cs:38:37:38:42 | "Boo!" |
|
||||||
| Finally.cs:38:37:38:42 | "Boo!" | Finally.cs:38:23:38:43 | Before object creation of type Exception |
|
| Finally.cs:38:37:38:42 | "Boo!" | Finally.cs:38:23:38:43 | Before object creation of type Exception |
|
||||||
|
| Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] | Finally.cs:41:16:41:24 | After access to type Exception [no-match] |
|
||||||
| Finally.cs:41:9:43:9 | catch (...) {...} | Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:41:9:43:9 | catch (...) {...} | Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] |
|
||||||
| Finally.cs:42:9:43:9 | {...} | Finally.cs:41:9:43:9 | After catch (...) {...} [match] |
|
| Finally.cs:41:16:41:24 | access to type Exception | Finally.cs:41:9:43:9 | catch (...) {...} |
|
||||||
| Finally.cs:44:9:47:9 | After catch {...} [match] | Finally.cs:44:9:47:9 | catch {...} |
|
| Finally.cs:42:9:43:9 | {...} | Finally.cs:41:16:41:24 | After access to type Exception [match] |
|
||||||
| Finally.cs:44:9:47:9 | catch {...} | Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:44:9:47:9 | catch {...} | Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] |
|
||||||
| Finally.cs:45:9:47:9 | {...} | Finally.cs:44:9:47:9 | After catch {...} [match] |
|
| Finally.cs:45:9:47:9 | {...} | Finally.cs:44:9:47:9 | catch {...} |
|
||||||
| Finally.cs:46:13:46:19 | Before return ...; | Finally.cs:45:9:47:9 | {...} |
|
| Finally.cs:46:13:46:19 | Before return ...; | Finally.cs:45:9:47:9 | {...} |
|
||||||
| Finally.cs:46:13:46:19 | return ...; | Finally.cs:46:13:46:19 | Before return ...; |
|
| Finally.cs:46:13:46:19 | return ...; | Finally.cs:46:13:46:19 | Before return ...; |
|
||||||
| Finally.cs:49:9:51:9 | After {...} | Finally.cs:50:13:50:41 | After ...; |
|
| Finally.cs:49:9:51:9 | After {...} | Finally.cs:50:13:50:41 | After ...; |
|
||||||
@@ -10966,21 +10980,23 @@ postDominance
|
|||||||
| Finally.cs:58:31:58:36 | "Try3" | Finally.cs:58:13:58:37 | Before call to method WriteLine |
|
| Finally.cs:58:31:58:36 | "Try3" | Finally.cs:58:13:58:37 | Before call to method WriteLine |
|
||||||
| Finally.cs:59:13:59:19 | Before return ...; | Finally.cs:58:13:58:38 | After ...; |
|
| Finally.cs:59:13:59:19 | Before return ...; | Finally.cs:58:13:58:38 | After ...; |
|
||||||
| Finally.cs:59:13:59:19 | return ...; | Finally.cs:59:13:59:19 | Before return ...; |
|
| Finally.cs:59:13:59:19 | return ...; | Finally.cs:59:13:59:19 | Before return ...; |
|
||||||
| Finally.cs:61:38:61:39 | IOException ex | Finally.cs:61:9:64:9 | After catch (...) {...} [match] |
|
| Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | Finally.cs:61:38:61:39 | After IOException ex [no-match] |
|
||||||
|
| Finally.cs:61:38:61:39 | IOException ex | Finally.cs:61:9:64:9 | catch (...) {...} |
|
||||||
| Finally.cs:61:48:61:51 | After true [true] | Finally.cs:61:48:61:51 | true |
|
| Finally.cs:61:48:61:51 | After true [true] | Finally.cs:61:48:61:51 | true |
|
||||||
| Finally.cs:61:48:61:51 | true | Finally.cs:61:38:61:39 | IOException ex |
|
| Finally.cs:61:48:61:51 | true | Finally.cs:61:38:61:39 | After IOException ex [match] |
|
||||||
| Finally.cs:62:9:64:9 | {...} | Finally.cs:61:48:61:51 | After true [true] |
|
| Finally.cs:62:9:64:9 | {...} | Finally.cs:61:48:61:51 | After true [true] |
|
||||||
| Finally.cs:63:13:63:18 | Before throw ...; | Finally.cs:62:9:64:9 | {...} |
|
| Finally.cs:63:13:63:18 | Before throw ...; | Finally.cs:62:9:64:9 | {...} |
|
||||||
| Finally.cs:63:13:63:18 | throw ...; | Finally.cs:63:13:63:18 | Before throw ...; |
|
| Finally.cs:63:13:63:18 | throw ...; | Finally.cs:63:13:63:18 | Before throw ...; |
|
||||||
|
| Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | Finally.cs:65:26:65:26 | After Exception e [no-match] |
|
||||||
| Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | Finally.cs:65:35:65:51 | After ... != ... [false] |
|
| Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | Finally.cs:65:35:65:51 | After ... != ... [false] |
|
||||||
| Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] |
|
||||||
| Finally.cs:65:26:65:26 | Exception e | Finally.cs:65:9:67:9 | After catch (...) {...} [match] |
|
| Finally.cs:65:26:65:26 | Exception e | Finally.cs:65:9:67:9 | catch (...) {...} |
|
||||||
| Finally.cs:65:35:65:35 | access to local variable e | Finally.cs:65:35:65:43 | Before access to property Message |
|
| Finally.cs:65:35:65:35 | access to local variable e | Finally.cs:65:35:65:43 | Before access to property Message |
|
||||||
| Finally.cs:65:35:65:43 | After access to property Message | Finally.cs:65:35:65:43 | access to property Message |
|
| Finally.cs:65:35:65:43 | After access to property Message | Finally.cs:65:35:65:43 | access to property Message |
|
||||||
| Finally.cs:65:35:65:43 | Before access to property Message | Finally.cs:65:35:65:51 | Before ... != ... |
|
| Finally.cs:65:35:65:43 | Before access to property Message | Finally.cs:65:35:65:51 | Before ... != ... |
|
||||||
| Finally.cs:65:35:65:43 | access to property Message | Finally.cs:65:35:65:35 | access to local variable e |
|
| Finally.cs:65:35:65:43 | access to property Message | Finally.cs:65:35:65:35 | access to local variable e |
|
||||||
| Finally.cs:65:35:65:51 | ... != ... | Finally.cs:65:48:65:51 | null |
|
| Finally.cs:65:35:65:51 | ... != ... | Finally.cs:65:48:65:51 | null |
|
||||||
| Finally.cs:65:35:65:51 | Before ... != ... | Finally.cs:65:26:65:26 | Exception e |
|
| Finally.cs:65:35:65:51 | Before ... != ... | Finally.cs:65:26:65:26 | After Exception e [match] |
|
||||||
| Finally.cs:65:48:65:51 | null | Finally.cs:65:35:65:43 | After access to property Message |
|
| Finally.cs:65:48:65:51 | null | Finally.cs:65:35:65:43 | After access to property Message |
|
||||||
| Finally.cs:66:9:67:9 | {...} | Finally.cs:65:35:65:51 | After ... != ... [true] |
|
| Finally.cs:66:9:67:9 | {...} | Finally.cs:65:35:65:51 | After ... != ... [true] |
|
||||||
| Finally.cs:69:9:71:9 | After {...} | Finally.cs:70:13:70:41 | After ...; |
|
| Finally.cs:69:9:71:9 | After {...} | Finally.cs:70:13:70:41 | After ...; |
|
||||||
@@ -11237,16 +11253,17 @@ postDominance
|
|||||||
| Finally.cs:159:27:159:44 | Before object creation of type Exception | Finally.cs:159:21:159:45 | Before throw ...; |
|
| Finally.cs:159:27:159:44 | Before object creation of type Exception | Finally.cs:159:21:159:45 | Before throw ...; |
|
||||||
| Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:159:41:159:43 | "1" |
|
| Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:159:41:159:43 | "1" |
|
||||||
| Finally.cs:159:41:159:43 | "1" | Finally.cs:159:27:159:44 | Before object creation of type Exception |
|
| Finally.cs:159:41:159:43 | "1" | Finally.cs:159:27:159:44 | Before object creation of type Exception |
|
||||||
|
| Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | Finally.cs:161:30:161:30 | After Exception e [no-match] |
|
||||||
| Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | Finally.cs:161:39:161:54 | After ... == ... [false] |
|
| Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | Finally.cs:161:39:161:54 | After ... == ... [false] |
|
||||||
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:159:21:159:45 | throw ...; |
|
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:159:21:159:45 | throw ...; |
|
||||||
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:159:27:159:44 | object creation of type Exception |
|
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:159:27:159:44 | object creation of type Exception |
|
||||||
| Finally.cs:161:30:161:30 | Exception e | Finally.cs:161:13:164:13 | After catch (...) {...} [match] |
|
| Finally.cs:161:30:161:30 | Exception e | Finally.cs:161:13:164:13 | catch (...) {...} |
|
||||||
| Finally.cs:161:39:161:39 | access to local variable e | Finally.cs:161:39:161:47 | Before access to property Message |
|
| Finally.cs:161:39:161:39 | access to local variable e | Finally.cs:161:39:161:47 | Before access to property Message |
|
||||||
| Finally.cs:161:39:161:47 | After access to property Message | Finally.cs:161:39:161:47 | access to property Message |
|
| Finally.cs:161:39:161:47 | After access to property Message | Finally.cs:161:39:161:47 | access to property Message |
|
||||||
| Finally.cs:161:39:161:47 | Before access to property Message | Finally.cs:161:39:161:54 | Before ... == ... |
|
| Finally.cs:161:39:161:47 | Before access to property Message | Finally.cs:161:39:161:54 | Before ... == ... |
|
||||||
| Finally.cs:161:39:161:47 | access to property Message | Finally.cs:161:39:161:39 | access to local variable e |
|
| Finally.cs:161:39:161:47 | access to property Message | Finally.cs:161:39:161:39 | access to local variable e |
|
||||||
| Finally.cs:161:39:161:54 | ... == ... | Finally.cs:161:52:161:54 | "1" |
|
| Finally.cs:161:39:161:54 | ... == ... | Finally.cs:161:52:161:54 | "1" |
|
||||||
| Finally.cs:161:39:161:54 | Before ... == ... | Finally.cs:161:30:161:30 | Exception e |
|
| Finally.cs:161:39:161:54 | Before ... == ... | Finally.cs:161:30:161:30 | After Exception e [match] |
|
||||||
| Finally.cs:161:52:161:54 | "1" | Finally.cs:161:39:161:47 | After access to property Message |
|
| Finally.cs:161:52:161:54 | "1" | Finally.cs:161:39:161:47 | After access to property Message |
|
||||||
| Finally.cs:162:13:164:13 | After {...} | Finally.cs:163:17:163:43 | After ...; |
|
| Finally.cs:162:13:164:13 | After {...} | Finally.cs:163:17:163:43 | After ...; |
|
||||||
| Finally.cs:162:13:164:13 | {...} | Finally.cs:161:39:161:54 | After ... == ... [true] |
|
| Finally.cs:162:13:164:13 | {...} | Finally.cs:161:39:161:54 | After ... == ... [true] |
|
||||||
@@ -11260,10 +11277,9 @@ postDominance
|
|||||||
| Finally.cs:163:35:163:41 | Before access to array element | Finally.cs:163:17:163:42 | Before call to method WriteLine |
|
| Finally.cs:163:35:163:41 | Before access to array element | Finally.cs:163:17:163:42 | Before call to method WriteLine |
|
||||||
| Finally.cs:163:35:163:41 | access to array element | Finally.cs:163:40:163:40 | 0 |
|
| Finally.cs:163:35:163:41 | access to array element | Finally.cs:163:40:163:40 | 0 |
|
||||||
| Finally.cs:163:40:163:40 | 0 | Finally.cs:163:35:163:38 | access to parameter args |
|
| Finally.cs:163:40:163:40 | 0 | Finally.cs:163:35:163:38 | access to parameter args |
|
||||||
| Finally.cs:165:13:168:13 | After catch {...} [match] | Finally.cs:165:13:168:13 | catch {...} |
|
|
||||||
| Finally.cs:165:13:168:13 | catch {...} | Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] |
|
| Finally.cs:165:13:168:13 | catch {...} | Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] |
|
||||||
| Finally.cs:166:13:168:13 | After {...} | Finally.cs:167:17:167:38 | After ...; |
|
| Finally.cs:166:13:168:13 | After {...} | Finally.cs:167:17:167:38 | After ...; |
|
||||||
| Finally.cs:166:13:168:13 | {...} | Finally.cs:165:13:168:13 | After catch {...} [match] |
|
| Finally.cs:166:13:168:13 | {...} | Finally.cs:165:13:168:13 | catch {...} |
|
||||||
| Finally.cs:167:17:167:37 | After call to method WriteLine | Finally.cs:167:17:167:37 | call to method WriteLine |
|
| Finally.cs:167:17:167:37 | After call to method WriteLine | Finally.cs:167:17:167:37 | call to method WriteLine |
|
||||||
| Finally.cs:167:17:167:37 | Before call to method WriteLine | Finally.cs:167:17:167:38 | ...; |
|
| Finally.cs:167:17:167:37 | Before call to method WriteLine | Finally.cs:167:17:167:38 | ...; |
|
||||||
| Finally.cs:167:17:167:37 | call to method WriteLine | Finally.cs:167:35:167:36 | "" |
|
| Finally.cs:167:17:167:37 | call to method WriteLine | Finally.cs:167:35:167:36 | "" |
|
||||||
@@ -11332,11 +11348,12 @@ postDominance
|
|||||||
| Finally.cs:186:25:186:47 | throw ...; | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
| Finally.cs:186:25:186:47 | throw ...; | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
||||||
| Finally.cs:186:31:186:46 | Before object creation of type ExceptionB | Finally.cs:186:25:186:47 | Before throw ...; |
|
| Finally.cs:186:31:186:46 | Before object creation of type ExceptionB | Finally.cs:186:25:186:47 | Before throw ...; |
|
||||||
| Finally.cs:186:31:186:46 | object creation of type ExceptionB | Finally.cs:186:31:186:46 | Before object creation of type ExceptionB |
|
| Finally.cs:186:31:186:46 | object creation of type ExceptionB | Finally.cs:186:31:186:46 | Before object creation of type ExceptionB |
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [match] | Finally.cs:188:13:191:13 | catch (...) {...} |
|
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:186:25:186:47 | throw ...; |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:186:25:186:47 | throw ...; |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:186:31:186:46 | object creation of type ExceptionB |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:186:31:186:46 | object creation of type ExceptionB |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | Finally.cs:188:20:188:29 | access to type ExceptionB |
|
||||||
|
| Finally.cs:188:20:188:29 | access to type ExceptionB | Finally.cs:188:13:191:13 | catch (...) {...} |
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:188:38:188:39 | access to parameter b2 |
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:188:38:188:39 | access to parameter b2 |
|
||||||
| Finally.cs:188:38:188:39 | access to parameter b2 | Finally.cs:188:13:191:13 | After catch (...) {...} [match] |
|
| Finally.cs:188:38:188:39 | access to parameter b2 | Finally.cs:188:20:188:29 | After access to type ExceptionB [match] |
|
||||||
| Finally.cs:189:13:191:13 | After {...} | Finally.cs:190:17:190:47 | After if (...) ... |
|
| Finally.cs:189:13:191:13 | After {...} | Finally.cs:190:17:190:47 | After if (...) ... |
|
||||||
| Finally.cs:189:13:191:13 | {...} | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
| Finally.cs:189:13:191:13 | {...} | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
||||||
| Finally.cs:190:17:190:47 | After if (...) ... | Finally.cs:190:21:190:22 | After access to parameter b1 [false] |
|
| Finally.cs:190:17:190:47 | After if (...) ... | Finally.cs:190:21:190:22 | After access to parameter b1 [false] |
|
||||||
@@ -11426,9 +11443,8 @@ postDominance
|
|||||||
| Finally.cs:220:13:220:37 | ...; | Finally.cs:219:9:221:9 | {...} |
|
| Finally.cs:220:13:220:37 | ...; | Finally.cs:219:9:221:9 | {...} |
|
||||||
| Finally.cs:220:13:220:37 | After ...; | Finally.cs:220:13:220:36 | After call to method WriteLine |
|
| Finally.cs:220:13:220:37 | After ...; | Finally.cs:220:13:220:36 | After call to method WriteLine |
|
||||||
| Finally.cs:220:31:220:35 | "Try" | Finally.cs:220:13:220:36 | Before call to method WriteLine |
|
| Finally.cs:220:31:220:35 | "Try" | Finally.cs:220:13:220:36 | Before call to method WriteLine |
|
||||||
| Finally.cs:222:9:225:9 | After catch {...} [match] | Finally.cs:222:9:225:9 | catch {...} |
|
|
||||||
| Finally.cs:223:9:225:9 | After {...} | Finally.cs:224:13:224:39 | After ...; |
|
| Finally.cs:223:9:225:9 | After {...} | Finally.cs:224:13:224:39 | After ...; |
|
||||||
| Finally.cs:223:9:225:9 | {...} | Finally.cs:222:9:225:9 | After catch {...} [match] |
|
| Finally.cs:223:9:225:9 | {...} | Finally.cs:222:9:225:9 | catch {...} |
|
||||||
| Finally.cs:224:13:224:38 | After call to method WriteLine | Finally.cs:224:13:224:38 | call to method WriteLine |
|
| Finally.cs:224:13:224:38 | After call to method WriteLine | Finally.cs:224:13:224:38 | call to method WriteLine |
|
||||||
| Finally.cs:224:13:224:38 | Before call to method WriteLine | Finally.cs:224:13:224:39 | ...; |
|
| Finally.cs:224:13:224:38 | Before call to method WriteLine | Finally.cs:224:13:224:39 | ...; |
|
||||||
| Finally.cs:224:13:224:38 | call to method WriteLine | Finally.cs:224:31:224:37 | "Catch" |
|
| Finally.cs:224:13:224:38 | call to method WriteLine | Finally.cs:224:31:224:37 | "Catch" |
|
||||||
@@ -17407,18 +17423,18 @@ blockDominance
|
|||||||
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:38:10:38:11 | Entry |
|
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:38:10:38:11 | Entry |
|
||||||
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:38:10:38:11 | Exit |
|
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:38:10:38:11 | Exit |
|
||||||
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:38:10:38:11 | Normal Exit |
|
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:38:10:38:11 | Normal Exit |
|
||||||
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:44:9:47:9 | After catch (...) {...} [match] |
|
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [match] |
|
||||||
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] |
|
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [no-match] |
|
||||||
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:48:9:51:9 | After catch (...) {...} [match] |
|
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:48:16:48:24 | After access to type Exception [match] |
|
||||||
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] |
|
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:48:16:48:24 | After access to type Exception [no-match] |
|
||||||
| ExitMethods.cs:38:10:38:11 | Exit | ExitMethods.cs:38:10:38:11 | Exit |
|
| ExitMethods.cs:38:10:38:11 | Exit | ExitMethods.cs:38:10:38:11 | Exit |
|
||||||
| ExitMethods.cs:38:10:38:11 | Normal Exit | ExitMethods.cs:38:10:38:11 | Normal Exit |
|
| ExitMethods.cs:38:10:38:11 | Normal Exit | ExitMethods.cs:38:10:38:11 | Normal Exit |
|
||||||
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [match] | ExitMethods.cs:44:9:47:9 | After catch (...) {...} [match] |
|
| ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [match] | ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [match] |
|
||||||
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] | ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] |
|
| ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [no-match] | ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [no-match] |
|
||||||
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] | ExitMethods.cs:48:9:51:9 | After catch (...) {...} [match] |
|
| ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [no-match] | ExitMethods.cs:48:16:48:24 | After access to type Exception [match] |
|
||||||
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] | ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] |
|
| ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [no-match] | ExitMethods.cs:48:16:48:24 | After access to type Exception [no-match] |
|
||||||
| ExitMethods.cs:48:9:51:9 | After catch (...) {...} [match] | ExitMethods.cs:48:9:51:9 | After catch (...) {...} [match] |
|
| ExitMethods.cs:48:16:48:24 | After access to type Exception [match] | ExitMethods.cs:48:16:48:24 | After access to type Exception [match] |
|
||||||
| ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] | ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] |
|
| ExitMethods.cs:48:16:48:24 | After access to type Exception [no-match] | ExitMethods.cs:48:16:48:24 | After access to type Exception [no-match] |
|
||||||
| ExitMethods.cs:54:10:54:11 | Entry | ExitMethods.cs:54:10:54:11 | Entry |
|
| ExitMethods.cs:54:10:54:11 | Entry | ExitMethods.cs:54:10:54:11 | Entry |
|
||||||
| ExitMethods.cs:60:10:60:11 | Entry | ExitMethods.cs:60:10:60:11 | Entry |
|
| ExitMethods.cs:60:10:60:11 | Entry | ExitMethods.cs:60:10:60:11 | Entry |
|
||||||
| ExitMethods.cs:66:17:66:26 | Entry | ExitMethods.cs:66:17:66:26 | Entry |
|
| ExitMethods.cs:66:17:66:26 | Entry | ExitMethods.cs:66:17:66:26 | Entry |
|
||||||
@@ -17502,38 +17518,38 @@ blockDominance
|
|||||||
| Finally.cs:19:10:19:11 | Entry | Finally.cs:19:10:19:11 | Normal Exit |
|
| Finally.cs:19:10:19:11 | Entry | Finally.cs:19:10:19:11 | Normal Exit |
|
||||||
| Finally.cs:19:10:19:11 | Entry | Finally.cs:21:9:51:9 | After try {...} ... |
|
| Finally.cs:19:10:19:11 | Entry | Finally.cs:21:9:51:9 | After try {...} ... |
|
||||||
| Finally.cs:19:10:19:11 | Entry | Finally.cs:23:13:23:37 | After call to method WriteLine |
|
| Finally.cs:19:10:19:11 | Entry | Finally.cs:23:13:23:37 | After call to method WriteLine |
|
||||||
| Finally.cs:19:10:19:11 | Entry | Finally.cs:26:9:29:9 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:19:10:19:11 | Entry | Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] |
|
|
||||||
| Finally.cs:19:10:19:11 | Entry | Finally.cs:26:9:29:9 | catch (...) {...} |
|
| Finally.cs:19:10:19:11 | Entry | Finally.cs:26:9:29:9 | catch (...) {...} |
|
||||||
| Finally.cs:19:10:19:11 | Entry | Finally.cs:30:9:40:9 | After catch (...) {...} [match] |
|
| Finally.cs:19:10:19:11 | Entry | Finally.cs:26:38:26:39 | After IOException ex [match] |
|
||||||
| Finally.cs:19:10:19:11 | Entry | Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:19:10:19:11 | Entry | Finally.cs:26:38:26:39 | After IOException ex [no-match] |
|
||||||
| Finally.cs:19:10:19:11 | Entry | Finally.cs:41:9:43:9 | After catch (...) {...} [match] |
|
| Finally.cs:19:10:19:11 | Entry | Finally.cs:30:41:30:42 | After ArgumentException ex [match] |
|
||||||
| Finally.cs:19:10:19:11 | Entry | Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:19:10:19:11 | Entry | Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] |
|
||||||
|
| Finally.cs:19:10:19:11 | Entry | Finally.cs:41:16:41:24 | After access to type Exception [match] |
|
||||||
|
| Finally.cs:19:10:19:11 | Entry | Finally.cs:41:16:41:24 | After access to type Exception [no-match] |
|
||||||
| Finally.cs:19:10:19:11 | Entry | Finally.cs:49:9:51:9 | {...} |
|
| Finally.cs:19:10:19:11 | Entry | Finally.cs:49:9:51:9 | {...} |
|
||||||
| Finally.cs:19:10:19:11 | Exceptional Exit | Finally.cs:19:10:19:11 | Exceptional Exit |
|
| Finally.cs:19:10:19:11 | Exceptional Exit | Finally.cs:19:10:19:11 | Exceptional Exit |
|
||||||
| Finally.cs:19:10:19:11 | Exit | Finally.cs:19:10:19:11 | Exit |
|
| Finally.cs:19:10:19:11 | Exit | Finally.cs:19:10:19:11 | Exit |
|
||||||
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:19:10:19:11 | Normal Exit |
|
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:19:10:19:11 | Normal Exit |
|
||||||
| Finally.cs:21:9:51:9 | After try {...} ... | Finally.cs:21:9:51:9 | After try {...} ... |
|
| Finally.cs:21:9:51:9 | After try {...} ... | Finally.cs:21:9:51:9 | After try {...} ... |
|
||||||
| Finally.cs:23:13:23:37 | After call to method WriteLine | Finally.cs:23:13:23:37 | After call to method WriteLine |
|
| Finally.cs:23:13:23:37 | After call to method WriteLine | Finally.cs:23:13:23:37 | After call to method WriteLine |
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [match] | Finally.cs:26:9:29:9 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] |
|
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | Finally.cs:30:9:40:9 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] |
|
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | Finally.cs:41:9:43:9 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] |
|
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:9:29:9 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] |
|
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:9:29:9 | catch (...) {...} |
|
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:9:29:9 | catch (...) {...} |
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:30:9:40:9 | After catch (...) {...} [match] |
|
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:38:26:39 | After IOException ex [match] |
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:38:26:39 | After IOException ex [no-match] |
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:41:9:43:9 | After catch (...) {...} [match] |
|
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:30:41:30:42 | After ArgumentException ex [match] |
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] |
|
||||||
| Finally.cs:30:9:40:9 | After catch (...) {...} [match] | Finally.cs:30:9:40:9 | After catch (...) {...} [match] |
|
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:41:16:41:24 | After access to type Exception [match] |
|
||||||
| Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] | Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:41:16:41:24 | After access to type Exception [no-match] |
|
||||||
| Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] | Finally.cs:41:9:43:9 | After catch (...) {...} [match] |
|
| Finally.cs:26:38:26:39 | After IOException ex [match] | Finally.cs:26:38:26:39 | After IOException ex [match] |
|
||||||
| Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] | Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:26:38:26:39 | After IOException ex [no-match] | Finally.cs:26:38:26:39 | After IOException ex [no-match] |
|
||||||
| Finally.cs:41:9:43:9 | After catch (...) {...} [match] | Finally.cs:41:9:43:9 | After catch (...) {...} [match] |
|
| Finally.cs:26:38:26:39 | After IOException ex [no-match] | Finally.cs:30:41:30:42 | After ArgumentException ex [match] |
|
||||||
| Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] | Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:26:38:26:39 | After IOException ex [no-match] | Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] |
|
||||||
|
| Finally.cs:26:38:26:39 | After IOException ex [no-match] | Finally.cs:41:16:41:24 | After access to type Exception [match] |
|
||||||
|
| Finally.cs:26:38:26:39 | After IOException ex [no-match] | Finally.cs:41:16:41:24 | After access to type Exception [no-match] |
|
||||||
|
| Finally.cs:30:41:30:42 | After ArgumentException ex [match] | Finally.cs:30:41:30:42 | After ArgumentException ex [match] |
|
||||||
|
| Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] | Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] |
|
||||||
|
| Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] | Finally.cs:41:16:41:24 | After access to type Exception [match] |
|
||||||
|
| Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] | Finally.cs:41:16:41:24 | After access to type Exception [no-match] |
|
||||||
|
| Finally.cs:41:16:41:24 | After access to type Exception [match] | Finally.cs:41:16:41:24 | After access to type Exception [match] |
|
||||||
|
| Finally.cs:41:16:41:24 | After access to type Exception [no-match] | Finally.cs:41:16:41:24 | After access to type Exception [no-match] |
|
||||||
| Finally.cs:49:9:51:9 | {...} | Finally.cs:19:10:19:11 | Exceptional Exit |
|
| Finally.cs:49:9:51:9 | {...} | Finally.cs:19:10:19:11 | Exceptional Exit |
|
||||||
| Finally.cs:49:9:51:9 | {...} | Finally.cs:19:10:19:11 | Exit |
|
| Finally.cs:49:9:51:9 | {...} | Finally.cs:19:10:19:11 | Exit |
|
||||||
| Finally.cs:49:9:51:9 | {...} | Finally.cs:19:10:19:11 | Normal Exit |
|
| Finally.cs:49:9:51:9 | {...} | Finally.cs:19:10:19:11 | Normal Exit |
|
||||||
@@ -17545,11 +17561,12 @@ blockDominance
|
|||||||
| Finally.cs:54:10:54:11 | Entry | Finally.cs:54:10:54:11 | Normal Exit |
|
| Finally.cs:54:10:54:11 | Entry | Finally.cs:54:10:54:11 | Normal Exit |
|
||||||
| Finally.cs:54:10:54:11 | Entry | Finally.cs:56:9:71:9 | After try {...} ... |
|
| Finally.cs:54:10:54:11 | Entry | Finally.cs:56:9:71:9 | After try {...} ... |
|
||||||
| Finally.cs:54:10:54:11 | Entry | Finally.cs:58:13:58:37 | After call to method WriteLine |
|
| Finally.cs:54:10:54:11 | Entry | Finally.cs:58:13:58:37 | After call to method WriteLine |
|
||||||
| Finally.cs:54:10:54:11 | Entry | Finally.cs:61:9:64:9 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:54:10:54:11 | Entry | Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] |
|
|
||||||
| Finally.cs:54:10:54:11 | Entry | Finally.cs:61:9:64:9 | catch (...) {...} |
|
| Finally.cs:54:10:54:11 | Entry | Finally.cs:61:9:64:9 | catch (...) {...} |
|
||||||
| Finally.cs:54:10:54:11 | Entry | Finally.cs:65:9:67:9 | After catch (...) {...} [match] |
|
| Finally.cs:54:10:54:11 | Entry | Finally.cs:61:38:61:39 | After IOException ex [match] |
|
||||||
|
| Finally.cs:54:10:54:11 | Entry | Finally.cs:61:38:61:39 | After IOException ex [no-match] |
|
||||||
| Finally.cs:54:10:54:11 | Entry | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:54:10:54:11 | Entry | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] |
|
||||||
|
| Finally.cs:54:10:54:11 | Entry | Finally.cs:65:26:65:26 | After Exception e [match] |
|
||||||
|
| Finally.cs:54:10:54:11 | Entry | Finally.cs:65:26:65:26 | After Exception e [no-match] |
|
||||||
| Finally.cs:54:10:54:11 | Entry | Finally.cs:65:35:65:51 | After ... != ... [false] |
|
| Finally.cs:54:10:54:11 | Entry | Finally.cs:65:35:65:51 | After ... != ... [false] |
|
||||||
| Finally.cs:54:10:54:11 | Entry | Finally.cs:65:35:65:51 | After ... != ... [true] |
|
| Finally.cs:54:10:54:11 | Entry | Finally.cs:65:35:65:51 | After ... != ... [true] |
|
||||||
| Finally.cs:54:10:54:11 | Entry | Finally.cs:69:9:71:9 | {...} |
|
| Finally.cs:54:10:54:11 | Entry | Finally.cs:69:9:71:9 | {...} |
|
||||||
@@ -17558,23 +17575,26 @@ blockDominance
|
|||||||
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:54:10:54:11 | Normal Exit |
|
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:54:10:54:11 | Normal Exit |
|
||||||
| Finally.cs:56:9:71:9 | After try {...} ... | Finally.cs:56:9:71:9 | After try {...} ... |
|
| Finally.cs:56:9:71:9 | After try {...} ... | Finally.cs:56:9:71:9 | After try {...} ... |
|
||||||
| Finally.cs:58:13:58:37 | After call to method WriteLine | Finally.cs:58:13:58:37 | After call to method WriteLine |
|
| Finally.cs:58:13:58:37 | After call to method WriteLine | Finally.cs:58:13:58:37 | After call to method WriteLine |
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [match] | Finally.cs:61:9:64:9 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] |
|
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | Finally.cs:65:9:67:9 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] |
|
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | Finally.cs:65:35:65:51 | After ... != ... [false] |
|
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | Finally.cs:65:35:65:51 | After ... != ... [true] |
|
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:9:64:9 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] |
|
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:9:64:9 | catch (...) {...} |
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:9:64:9 | catch (...) {...} |
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:65:9:67:9 | After catch (...) {...} [match] |
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:38:61:39 | After IOException ex [match] |
|
||||||
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:38:61:39 | After IOException ex [no-match] |
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] |
|
||||||
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:65:26:65:26 | After Exception e [match] |
|
||||||
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:65:26:65:26 | After Exception e [no-match] |
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:65:35:65:51 | After ... != ... [false] |
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:65:35:65:51 | After ... != ... [false] |
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:65:35:65:51 | After ... != ... [true] |
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:65:35:65:51 | After ... != ... [true] |
|
||||||
| Finally.cs:65:9:67:9 | After catch (...) {...} [match] | Finally.cs:65:9:67:9 | After catch (...) {...} [match] |
|
| Finally.cs:61:38:61:39 | After IOException ex [match] | Finally.cs:61:38:61:39 | After IOException ex [match] |
|
||||||
| Finally.cs:65:9:67:9 | After catch (...) {...} [match] | Finally.cs:65:35:65:51 | After ... != ... [false] |
|
| Finally.cs:61:38:61:39 | After IOException ex [no-match] | Finally.cs:61:38:61:39 | After IOException ex [no-match] |
|
||||||
| Finally.cs:65:9:67:9 | After catch (...) {...} [match] | Finally.cs:65:35:65:51 | After ... != ... [true] |
|
| Finally.cs:61:38:61:39 | After IOException ex [no-match] | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] |
|
||||||
|
| Finally.cs:61:38:61:39 | After IOException ex [no-match] | Finally.cs:65:26:65:26 | After Exception e [match] |
|
||||||
|
| Finally.cs:61:38:61:39 | After IOException ex [no-match] | Finally.cs:65:26:65:26 | After Exception e [no-match] |
|
||||||
|
| Finally.cs:61:38:61:39 | After IOException ex [no-match] | Finally.cs:65:35:65:51 | After ... != ... [false] |
|
||||||
|
| Finally.cs:61:38:61:39 | After IOException ex [no-match] | Finally.cs:65:35:65:51 | After ... != ... [true] |
|
||||||
| Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] |
|
||||||
|
| Finally.cs:65:26:65:26 | After Exception e [match] | Finally.cs:65:26:65:26 | After Exception e [match] |
|
||||||
|
| Finally.cs:65:26:65:26 | After Exception e [match] | Finally.cs:65:35:65:51 | After ... != ... [false] |
|
||||||
|
| Finally.cs:65:26:65:26 | After Exception e [match] | Finally.cs:65:35:65:51 | After ... != ... [true] |
|
||||||
|
| Finally.cs:65:26:65:26 | After Exception e [no-match] | Finally.cs:65:26:65:26 | After Exception e [no-match] |
|
||||||
| Finally.cs:65:35:65:51 | After ... != ... [false] | Finally.cs:65:35:65:51 | After ... != ... [false] |
|
| Finally.cs:65:35:65:51 | After ... != ... [false] | Finally.cs:65:35:65:51 | After ... != ... [false] |
|
||||||
| Finally.cs:65:35:65:51 | After ... != ... [true] | Finally.cs:65:35:65:51 | After ... != ... [true] |
|
| Finally.cs:65:35:65:51 | After ... != ... [true] | Finally.cs:65:35:65:51 | After ... != ... [true] |
|
||||||
| Finally.cs:69:9:71:9 | {...} | Finally.cs:54:10:54:11 | Exceptional Exit |
|
| Finally.cs:69:9:71:9 | {...} | Finally.cs:54:10:54:11 | Exceptional Exit |
|
||||||
@@ -17783,9 +17803,10 @@ blockDominance
|
|||||||
| Finally.cs:147:10:147:11 | Entry | Finally.cs:158:21:158:36 | After ... == ... [false] |
|
| Finally.cs:147:10:147:11 | Entry | Finally.cs:158:21:158:36 | After ... == ... [false] |
|
||||||
| Finally.cs:147:10:147:11 | Entry | Finally.cs:158:21:158:36 | After ... == ... [true] |
|
| Finally.cs:147:10:147:11 | Entry | Finally.cs:158:21:158:36 | After ... == ... [true] |
|
||||||
| Finally.cs:147:10:147:11 | Entry | Finally.cs:159:27:159:44 | After object creation of type Exception |
|
| Finally.cs:147:10:147:11 | Entry | Finally.cs:159:27:159:44 | After object creation of type Exception |
|
||||||
| Finally.cs:147:10:147:11 | Entry | Finally.cs:161:13:164:13 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:147:10:147:11 | Entry | Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] |
|
| Finally.cs:147:10:147:11 | Entry | Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] |
|
||||||
| Finally.cs:147:10:147:11 | Entry | Finally.cs:161:13:164:13 | catch (...) {...} |
|
| Finally.cs:147:10:147:11 | Entry | Finally.cs:161:13:164:13 | catch (...) {...} |
|
||||||
|
| Finally.cs:147:10:147:11 | Entry | Finally.cs:161:30:161:30 | After Exception e [match] |
|
||||||
|
| Finally.cs:147:10:147:11 | Entry | Finally.cs:161:30:161:30 | After Exception e [no-match] |
|
||||||
| Finally.cs:147:10:147:11 | Entry | Finally.cs:161:39:161:54 | After ... == ... [false] |
|
| Finally.cs:147:10:147:11 | Entry | Finally.cs:161:39:161:54 | After ... == ... [false] |
|
||||||
| Finally.cs:147:10:147:11 | Entry | Finally.cs:161:39:161:54 | After ... == ... [true] |
|
| Finally.cs:147:10:147:11 | Entry | Finally.cs:161:39:161:54 | After ... == ... [true] |
|
||||||
| Finally.cs:147:10:147:11 | Exceptional Exit | Finally.cs:147:10:147:11 | Exceptional Exit |
|
| Finally.cs:147:10:147:11 | Exceptional Exit | Finally.cs:147:10:147:11 | Exceptional Exit |
|
||||||
@@ -17804,9 +17825,10 @@ blockDominance
|
|||||||
| Finally.cs:155:9:169:9 | {...} | Finally.cs:158:21:158:36 | After ... == ... [false] |
|
| Finally.cs:155:9:169:9 | {...} | Finally.cs:158:21:158:36 | After ... == ... [false] |
|
||||||
| Finally.cs:155:9:169:9 | {...} | Finally.cs:158:21:158:36 | After ... == ... [true] |
|
| Finally.cs:155:9:169:9 | {...} | Finally.cs:158:21:158:36 | After ... == ... [true] |
|
||||||
| Finally.cs:155:9:169:9 | {...} | Finally.cs:159:27:159:44 | After object creation of type Exception |
|
| Finally.cs:155:9:169:9 | {...} | Finally.cs:159:27:159:44 | After object creation of type Exception |
|
||||||
| Finally.cs:155:9:169:9 | {...} | Finally.cs:161:13:164:13 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:155:9:169:9 | {...} | Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] |
|
| Finally.cs:155:9:169:9 | {...} | Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] |
|
||||||
| Finally.cs:155:9:169:9 | {...} | Finally.cs:161:13:164:13 | catch (...) {...} |
|
| Finally.cs:155:9:169:9 | {...} | Finally.cs:161:13:164:13 | catch (...) {...} |
|
||||||
|
| Finally.cs:155:9:169:9 | {...} | Finally.cs:161:30:161:30 | After Exception e [match] |
|
||||||
|
| Finally.cs:155:9:169:9 | {...} | Finally.cs:161:30:161:30 | After Exception e [no-match] |
|
||||||
| Finally.cs:155:9:169:9 | {...} | Finally.cs:161:39:161:54 | After ... == ... [false] |
|
| Finally.cs:155:9:169:9 | {...} | Finally.cs:161:39:161:54 | After ... == ... [false] |
|
||||||
| Finally.cs:155:9:169:9 | {...} | Finally.cs:161:39:161:54 | After ... == ... [true] |
|
| Finally.cs:155:9:169:9 | {...} | Finally.cs:161:39:161:54 | After ... == ... [true] |
|
||||||
| Finally.cs:156:13:168:13 | After try {...} ... | Finally.cs:147:10:147:11 | Exceptional Exit |
|
| Finally.cs:156:13:168:13 | After try {...} ... | Finally.cs:147:10:147:11 | Exceptional Exit |
|
||||||
@@ -17821,15 +17843,17 @@ blockDominance
|
|||||||
| Finally.cs:158:21:158:36 | After ... == ... [true] | Finally.cs:158:21:158:36 | After ... == ... [true] |
|
| Finally.cs:158:21:158:36 | After ... == ... [true] | Finally.cs:158:21:158:36 | After ... == ... [true] |
|
||||||
| Finally.cs:158:21:158:36 | After ... == ... [true] | Finally.cs:159:27:159:44 | After object creation of type Exception |
|
| Finally.cs:158:21:158:36 | After ... == ... [true] | Finally.cs:159:27:159:44 | After object creation of type Exception |
|
||||||
| Finally.cs:159:27:159:44 | After object creation of type Exception | Finally.cs:159:27:159:44 | After object creation of type Exception |
|
| Finally.cs:159:27:159:44 | After object creation of type Exception | Finally.cs:159:27:159:44 | After object creation of type Exception |
|
||||||
| Finally.cs:161:13:164:13 | After catch (...) {...} [match] | Finally.cs:161:13:164:13 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:161:13:164:13 | After catch (...) {...} [match] | Finally.cs:161:39:161:54 | After ... == ... [false] |
|
|
||||||
| Finally.cs:161:13:164:13 | After catch (...) {...} [match] | Finally.cs:161:39:161:54 | After ... == ... [true] |
|
|
||||||
| Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] |
|
| Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] |
|
||||||
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:13:164:13 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] |
|
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] |
|
||||||
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:13:164:13 | catch (...) {...} |
|
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:13:164:13 | catch (...) {...} |
|
||||||
|
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:30:161:30 | After Exception e [match] |
|
||||||
|
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:30:161:30 | After Exception e [no-match] |
|
||||||
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:39:161:54 | After ... == ... [false] |
|
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:39:161:54 | After ... == ... [false] |
|
||||||
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:39:161:54 | After ... == ... [true] |
|
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:39:161:54 | After ... == ... [true] |
|
||||||
|
| Finally.cs:161:30:161:30 | After Exception e [match] | Finally.cs:161:30:161:30 | After Exception e [match] |
|
||||||
|
| Finally.cs:161:30:161:30 | After Exception e [match] | Finally.cs:161:39:161:54 | After ... == ... [false] |
|
||||||
|
| Finally.cs:161:30:161:30 | After Exception e [match] | Finally.cs:161:39:161:54 | After ... == ... [true] |
|
||||||
|
| Finally.cs:161:30:161:30 | After Exception e [no-match] | Finally.cs:161:30:161:30 | After Exception e [no-match] |
|
||||||
| Finally.cs:161:39:161:54 | After ... == ... [false] | Finally.cs:161:39:161:54 | After ... == ... [false] |
|
| Finally.cs:161:39:161:54 | After ... == ... [false] | Finally.cs:161:39:161:54 | After ... == ... [false] |
|
||||||
| Finally.cs:161:39:161:54 | After ... == ... [true] | Finally.cs:161:39:161:54 | After ... == ... [true] |
|
| Finally.cs:161:39:161:54 | After ... == ... [true] | Finally.cs:161:39:161:54 | After ... == ... [true] |
|
||||||
| Finally.cs:172:11:172:20 | Entry | Finally.cs:172:11:172:20 | Entry |
|
| Finally.cs:172:11:172:20 | Entry | Finally.cs:172:11:172:20 | Entry |
|
||||||
@@ -17847,9 +17871,10 @@ blockDominance
|
|||||||
| Finally.cs:176:10:176:11 | Entry | Finally.cs:186:21:186:22 | After access to parameter b2 [false] |
|
| Finally.cs:176:10:176:11 | Entry | Finally.cs:186:21:186:22 | After access to parameter b2 [false] |
|
||||||
| Finally.cs:176:10:176:11 | Entry | Finally.cs:186:21:186:22 | After access to parameter b2 [true] |
|
| Finally.cs:176:10:176:11 | Entry | Finally.cs:186:21:186:22 | After access to parameter b2 [true] |
|
||||||
| Finally.cs:176:10:176:11 | Entry | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
| Finally.cs:176:10:176:11 | Entry | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
||||||
| Finally.cs:176:10:176:11 | Entry | Finally.cs:188:13:191:13 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:176:10:176:11 | Entry | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] |
|
| Finally.cs:176:10:176:11 | Entry | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] |
|
||||||
| Finally.cs:176:10:176:11 | Entry | Finally.cs:188:13:191:13 | catch (...) {...} |
|
| Finally.cs:176:10:176:11 | Entry | Finally.cs:188:13:191:13 | catch (...) {...} |
|
||||||
|
| Finally.cs:176:10:176:11 | Entry | Finally.cs:188:20:188:29 | After access to type ExceptionB [match] |
|
||||||
|
| Finally.cs:176:10:176:11 | Entry | Finally.cs:188:20:188:29 | After access to type ExceptionB [no-match] |
|
||||||
| Finally.cs:176:10:176:11 | Entry | Finally.cs:188:38:188:39 | After access to parameter b2 [false] |
|
| Finally.cs:176:10:176:11 | Entry | Finally.cs:188:38:188:39 | After access to parameter b2 [false] |
|
||||||
| Finally.cs:176:10:176:11 | Entry | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
| Finally.cs:176:10:176:11 | Entry | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
||||||
| Finally.cs:176:10:176:11 | Entry | Finally.cs:190:21:190:22 | After access to parameter b1 [false] |
|
| Finally.cs:176:10:176:11 | Entry | Finally.cs:190:21:190:22 | After access to parameter b1 [false] |
|
||||||
@@ -17869,9 +17894,10 @@ blockDominance
|
|||||||
| Finally.cs:183:9:192:9 | {...} | Finally.cs:186:21:186:22 | After access to parameter b2 [false] |
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:186:21:186:22 | After access to parameter b2 [false] |
|
||||||
| Finally.cs:183:9:192:9 | {...} | Finally.cs:186:21:186:22 | After access to parameter b2 [true] |
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:186:21:186:22 | After access to parameter b2 [true] |
|
||||||
| Finally.cs:183:9:192:9 | {...} | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
||||||
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:13:191:13 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] |
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] |
|
||||||
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:13:191:13 | catch (...) {...} |
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:13:191:13 | catch (...) {...} |
|
||||||
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:20:188:29 | After access to type ExceptionB [match] |
|
||||||
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:20:188:29 | After access to type ExceptionB [no-match] |
|
||||||
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:38:188:39 | After access to parameter b2 [false] |
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:38:188:39 | After access to parameter b2 [false] |
|
||||||
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
||||||
| Finally.cs:183:9:192:9 | {...} | Finally.cs:190:21:190:22 | After access to parameter b1 [false] |
|
| Finally.cs:183:9:192:9 | {...} | Finally.cs:190:21:190:22 | After access to parameter b1 [false] |
|
||||||
@@ -17881,27 +17907,30 @@ blockDominance
|
|||||||
| Finally.cs:186:21:186:22 | After access to parameter b2 [false] | Finally.cs:186:21:186:22 | After access to parameter b2 [false] |
|
| Finally.cs:186:21:186:22 | After access to parameter b2 [false] | Finally.cs:186:21:186:22 | After access to parameter b2 [false] |
|
||||||
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:186:21:186:22 | After access to parameter b2 [true] |
|
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:186:21:186:22 | After access to parameter b2 [true] |
|
||||||
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
||||||
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:188:13:191:13 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] |
|
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] |
|
||||||
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:188:13:191:13 | catch (...) {...} |
|
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:188:13:191:13 | catch (...) {...} |
|
||||||
|
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:188:20:188:29 | After access to type ExceptionB [match] |
|
||||||
|
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:188:20:188:29 | After access to type ExceptionB [no-match] |
|
||||||
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:188:38:188:39 | After access to parameter b2 [false] |
|
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:188:38:188:39 | After access to parameter b2 [false] |
|
||||||
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
||||||
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:190:21:190:22 | After access to parameter b1 [false] |
|
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:190:21:190:22 | After access to parameter b1 [false] |
|
||||||
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:190:21:190:22 | After access to parameter b1 [true] |
|
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:190:21:190:22 | After access to parameter b1 [true] |
|
||||||
| Finally.cs:186:31:186:46 | After object creation of type ExceptionB | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
| Finally.cs:186:31:186:46 | After object creation of type ExceptionB | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [match] | Finally.cs:188:13:191:13 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [match] | Finally.cs:188:38:188:39 | After access to parameter b2 [false] |
|
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [match] | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [match] | Finally.cs:190:21:190:22 | After access to parameter b1 [false] |
|
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [match] | Finally.cs:190:21:190:22 | After access to parameter b1 [true] |
|
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] |
|
| Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:13:191:13 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:13:191:13 | catch (...) {...} |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:13:191:13 | catch (...) {...} |
|
||||||
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:20:188:29 | After access to type ExceptionB [match] |
|
||||||
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:20:188:29 | After access to type ExceptionB [no-match] |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:38:188:39 | After access to parameter b2 [false] |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:38:188:39 | After access to parameter b2 [false] |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:190:21:190:22 | After access to parameter b1 [false] |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:190:21:190:22 | After access to parameter b1 [false] |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:190:21:190:22 | After access to parameter b1 [true] |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:190:21:190:22 | After access to parameter b1 [true] |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | Finally.cs:188:20:188:29 | After access to type ExceptionB [match] |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | Finally.cs:188:38:188:39 | After access to parameter b2 [false] |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | Finally.cs:190:21:190:22 | After access to parameter b1 [false] |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | Finally.cs:190:21:190:22 | After access to parameter b1 [true] |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [no-match] | Finally.cs:188:20:188:29 | After access to type ExceptionB [no-match] |
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [false] | Finally.cs:188:38:188:39 | After access to parameter b2 [false] |
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [false] | Finally.cs:188:38:188:39 | After access to parameter b2 [false] |
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:190:21:190:22 | After access to parameter b1 [false] |
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:190:21:190:22 | After access to parameter b1 [false] |
|
||||||
@@ -21668,14 +21697,14 @@ postBlockDominance
|
|||||||
| ExitMethods.cs:38:10:38:11 | Exit | ExitMethods.cs:38:10:38:11 | Exit |
|
| ExitMethods.cs:38:10:38:11 | Exit | ExitMethods.cs:38:10:38:11 | Exit |
|
||||||
| ExitMethods.cs:38:10:38:11 | Normal Exit | ExitMethods.cs:38:10:38:11 | Entry |
|
| ExitMethods.cs:38:10:38:11 | Normal Exit | ExitMethods.cs:38:10:38:11 | Entry |
|
||||||
| ExitMethods.cs:38:10:38:11 | Normal Exit | ExitMethods.cs:38:10:38:11 | Normal Exit |
|
| ExitMethods.cs:38:10:38:11 | Normal Exit | ExitMethods.cs:38:10:38:11 | Normal Exit |
|
||||||
| ExitMethods.cs:38:10:38:11 | Normal Exit | ExitMethods.cs:44:9:47:9 | After catch (...) {...} [match] |
|
| ExitMethods.cs:38:10:38:11 | Normal Exit | ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [match] |
|
||||||
| ExitMethods.cs:38:10:38:11 | Normal Exit | ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] |
|
| ExitMethods.cs:38:10:38:11 | Normal Exit | ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [no-match] |
|
||||||
| ExitMethods.cs:38:10:38:11 | Normal Exit | ExitMethods.cs:48:9:51:9 | After catch (...) {...} [match] |
|
| ExitMethods.cs:38:10:38:11 | Normal Exit | ExitMethods.cs:48:16:48:24 | After access to type Exception [match] |
|
||||||
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [match] | ExitMethods.cs:44:9:47:9 | After catch (...) {...} [match] |
|
| ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [match] | ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [match] |
|
||||||
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] | ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] |
|
| ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [no-match] | ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [no-match] |
|
||||||
| ExitMethods.cs:48:9:51:9 | After catch (...) {...} [match] | ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] |
|
| ExitMethods.cs:48:16:48:24 | After access to type Exception [match] | ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [no-match] |
|
||||||
| ExitMethods.cs:48:9:51:9 | After catch (...) {...} [match] | ExitMethods.cs:48:9:51:9 | After catch (...) {...} [match] |
|
| ExitMethods.cs:48:16:48:24 | After access to type Exception [match] | ExitMethods.cs:48:16:48:24 | After access to type Exception [match] |
|
||||||
| ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] | ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] |
|
| ExitMethods.cs:48:16:48:24 | After access to type Exception [no-match] | ExitMethods.cs:48:16:48:24 | After access to type Exception [no-match] |
|
||||||
| ExitMethods.cs:54:10:54:11 | Entry | ExitMethods.cs:54:10:54:11 | Entry |
|
| ExitMethods.cs:54:10:54:11 | Entry | ExitMethods.cs:54:10:54:11 | Entry |
|
||||||
| ExitMethods.cs:60:10:60:11 | Entry | ExitMethods.cs:60:10:60:11 | Entry |
|
| ExitMethods.cs:60:10:60:11 | Entry | ExitMethods.cs:60:10:60:11 | Entry |
|
||||||
| ExitMethods.cs:66:17:66:26 | Entry | ExitMethods.cs:66:17:66:26 | Entry |
|
| ExitMethods.cs:66:17:66:26 | Entry | ExitMethods.cs:66:17:66:26 | Entry |
|
||||||
@@ -21743,32 +21772,32 @@ postBlockDominance
|
|||||||
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:19:10:19:11 | Normal Exit |
|
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:19:10:19:11 | Normal Exit |
|
||||||
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:21:9:51:9 | After try {...} ... |
|
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:21:9:51:9 | After try {...} ... |
|
||||||
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:23:13:23:37 | After call to method WriteLine |
|
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:23:13:23:37 | After call to method WriteLine |
|
||||||
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:26:9:29:9 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] |
|
|
||||||
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:26:9:29:9 | catch (...) {...} |
|
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:26:9:29:9 | catch (...) {...} |
|
||||||
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:30:9:40:9 | After catch (...) {...} [match] |
|
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:26:38:26:39 | After IOException ex [match] |
|
||||||
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:26:38:26:39 | After IOException ex [no-match] |
|
||||||
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:41:9:43:9 | After catch (...) {...} [match] |
|
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:30:41:30:42 | After ArgumentException ex [match] |
|
||||||
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] |
|
||||||
|
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:41:16:41:24 | After access to type Exception [match] |
|
||||||
|
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:41:16:41:24 | After access to type Exception [no-match] |
|
||||||
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:49:9:51:9 | {...} |
|
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:49:9:51:9 | {...} |
|
||||||
| Finally.cs:21:9:51:9 | After try {...} ... | Finally.cs:21:9:51:9 | After try {...} ... |
|
| Finally.cs:21:9:51:9 | After try {...} ... | Finally.cs:21:9:51:9 | After try {...} ... |
|
||||||
| Finally.cs:23:13:23:37 | After call to method WriteLine | Finally.cs:23:13:23:37 | After call to method WriteLine |
|
| Finally.cs:23:13:23:37 | After call to method WriteLine | Finally.cs:23:13:23:37 | After call to method WriteLine |
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [match] | Finally.cs:26:9:29:9 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] |
|
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:9:29:9 | catch (...) {...} |
|
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:9:29:9 | catch (...) {...} |
|
||||||
| Finally.cs:30:9:40:9 | After catch (...) {...} [match] | Finally.cs:30:9:40:9 | After catch (...) {...} [match] |
|
| Finally.cs:26:38:26:39 | After IOException ex [match] | Finally.cs:26:38:26:39 | After IOException ex [match] |
|
||||||
| Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] | Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:26:38:26:39 | After IOException ex [no-match] | Finally.cs:26:38:26:39 | After IOException ex [no-match] |
|
||||||
| Finally.cs:41:9:43:9 | After catch (...) {...} [match] | Finally.cs:41:9:43:9 | After catch (...) {...} [match] |
|
| Finally.cs:30:41:30:42 | After ArgumentException ex [match] | Finally.cs:30:41:30:42 | After ArgumentException ex [match] |
|
||||||
| Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] | Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] | Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] |
|
||||||
|
| Finally.cs:41:16:41:24 | After access to type Exception [match] | Finally.cs:41:16:41:24 | After access to type Exception [match] |
|
||||||
|
| Finally.cs:41:16:41:24 | After access to type Exception [no-match] | Finally.cs:41:16:41:24 | After access to type Exception [no-match] |
|
||||||
| Finally.cs:49:9:51:9 | {...} | Finally.cs:19:10:19:11 | Entry |
|
| Finally.cs:49:9:51:9 | {...} | Finally.cs:19:10:19:11 | Entry |
|
||||||
| Finally.cs:49:9:51:9 | {...} | Finally.cs:23:13:23:37 | After call to method WriteLine |
|
| Finally.cs:49:9:51:9 | {...} | Finally.cs:23:13:23:37 | After call to method WriteLine |
|
||||||
| Finally.cs:49:9:51:9 | {...} | Finally.cs:26:9:29:9 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:49:9:51:9 | {...} | Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] |
|
|
||||||
| Finally.cs:49:9:51:9 | {...} | Finally.cs:26:9:29:9 | catch (...) {...} |
|
| Finally.cs:49:9:51:9 | {...} | Finally.cs:26:9:29:9 | catch (...) {...} |
|
||||||
| Finally.cs:49:9:51:9 | {...} | Finally.cs:30:9:40:9 | After catch (...) {...} [match] |
|
| Finally.cs:49:9:51:9 | {...} | Finally.cs:26:38:26:39 | After IOException ex [match] |
|
||||||
| Finally.cs:49:9:51:9 | {...} | Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:49:9:51:9 | {...} | Finally.cs:26:38:26:39 | After IOException ex [no-match] |
|
||||||
| Finally.cs:49:9:51:9 | {...} | Finally.cs:41:9:43:9 | After catch (...) {...} [match] |
|
| Finally.cs:49:9:51:9 | {...} | Finally.cs:30:41:30:42 | After ArgumentException ex [match] |
|
||||||
| Finally.cs:49:9:51:9 | {...} | Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:49:9:51:9 | {...} | Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] |
|
||||||
|
| Finally.cs:49:9:51:9 | {...} | Finally.cs:41:16:41:24 | After access to type Exception [match] |
|
||||||
|
| Finally.cs:49:9:51:9 | {...} | Finally.cs:41:16:41:24 | After access to type Exception [no-match] |
|
||||||
| Finally.cs:49:9:51:9 | {...} | Finally.cs:49:9:51:9 | {...} |
|
| Finally.cs:49:9:51:9 | {...} | Finally.cs:49:9:51:9 | {...} |
|
||||||
| Finally.cs:54:10:54:11 | Entry | Finally.cs:54:10:54:11 | Entry |
|
| Finally.cs:54:10:54:11 | Entry | Finally.cs:54:10:54:11 | Entry |
|
||||||
| Finally.cs:54:10:54:11 | Exceptional Exit | Finally.cs:54:10:54:11 | Exceptional Exit |
|
| Finally.cs:54:10:54:11 | Exceptional Exit | Finally.cs:54:10:54:11 | Exceptional Exit |
|
||||||
@@ -21777,31 +21806,35 @@ postBlockDominance
|
|||||||
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:54:10:54:11 | Normal Exit |
|
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:54:10:54:11 | Normal Exit |
|
||||||
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:56:9:71:9 | After try {...} ... |
|
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:56:9:71:9 | After try {...} ... |
|
||||||
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:58:13:58:37 | After call to method WriteLine |
|
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:58:13:58:37 | After call to method WriteLine |
|
||||||
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:61:9:64:9 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] |
|
|
||||||
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:61:9:64:9 | catch (...) {...} |
|
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:61:9:64:9 | catch (...) {...} |
|
||||||
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:65:9:67:9 | After catch (...) {...} [match] |
|
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:61:38:61:39 | After IOException ex [match] |
|
||||||
|
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:61:38:61:39 | After IOException ex [no-match] |
|
||||||
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] |
|
||||||
|
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:65:26:65:26 | After Exception e [match] |
|
||||||
|
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:65:26:65:26 | After Exception e [no-match] |
|
||||||
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:65:35:65:51 | After ... != ... [false] |
|
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:65:35:65:51 | After ... != ... [false] |
|
||||||
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:65:35:65:51 | After ... != ... [true] |
|
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:65:35:65:51 | After ... != ... [true] |
|
||||||
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:69:9:71:9 | {...} |
|
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:69:9:71:9 | {...} |
|
||||||
| Finally.cs:56:9:71:9 | After try {...} ... | Finally.cs:56:9:71:9 | After try {...} ... |
|
| Finally.cs:56:9:71:9 | After try {...} ... | Finally.cs:56:9:71:9 | After try {...} ... |
|
||||||
| Finally.cs:58:13:58:37 | After call to method WriteLine | Finally.cs:58:13:58:37 | After call to method WriteLine |
|
| Finally.cs:58:13:58:37 | After call to method WriteLine | Finally.cs:58:13:58:37 | After call to method WriteLine |
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [match] | Finally.cs:61:9:64:9 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] |
|
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:9:64:9 | catch (...) {...} |
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:9:64:9 | catch (...) {...} |
|
||||||
| Finally.cs:65:9:67:9 | After catch (...) {...} [match] | Finally.cs:65:9:67:9 | After catch (...) {...} [match] |
|
| Finally.cs:61:38:61:39 | After IOException ex [match] | Finally.cs:61:38:61:39 | After IOException ex [match] |
|
||||||
|
| Finally.cs:61:38:61:39 | After IOException ex [no-match] | Finally.cs:61:38:61:39 | After IOException ex [no-match] |
|
||||||
| Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] |
|
||||||
|
| Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | Finally.cs:65:26:65:26 | After Exception e [no-match] |
|
||||||
| Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | Finally.cs:65:35:65:51 | After ... != ... [false] |
|
| Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | Finally.cs:65:35:65:51 | After ... != ... [false] |
|
||||||
|
| Finally.cs:65:26:65:26 | After Exception e [match] | Finally.cs:65:26:65:26 | After Exception e [match] |
|
||||||
|
| Finally.cs:65:26:65:26 | After Exception e [no-match] | Finally.cs:65:26:65:26 | After Exception e [no-match] |
|
||||||
| Finally.cs:65:35:65:51 | After ... != ... [false] | Finally.cs:65:35:65:51 | After ... != ... [false] |
|
| Finally.cs:65:35:65:51 | After ... != ... [false] | Finally.cs:65:35:65:51 | After ... != ... [false] |
|
||||||
| Finally.cs:65:35:65:51 | After ... != ... [true] | Finally.cs:65:35:65:51 | After ... != ... [true] |
|
| Finally.cs:65:35:65:51 | After ... != ... [true] | Finally.cs:65:35:65:51 | After ... != ... [true] |
|
||||||
| Finally.cs:69:9:71:9 | {...} | Finally.cs:54:10:54:11 | Entry |
|
| Finally.cs:69:9:71:9 | {...} | Finally.cs:54:10:54:11 | Entry |
|
||||||
| Finally.cs:69:9:71:9 | {...} | Finally.cs:58:13:58:37 | After call to method WriteLine |
|
| Finally.cs:69:9:71:9 | {...} | Finally.cs:58:13:58:37 | After call to method WriteLine |
|
||||||
| Finally.cs:69:9:71:9 | {...} | Finally.cs:61:9:64:9 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:69:9:71:9 | {...} | Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] |
|
|
||||||
| Finally.cs:69:9:71:9 | {...} | Finally.cs:61:9:64:9 | catch (...) {...} |
|
| Finally.cs:69:9:71:9 | {...} | Finally.cs:61:9:64:9 | catch (...) {...} |
|
||||||
| Finally.cs:69:9:71:9 | {...} | Finally.cs:65:9:67:9 | After catch (...) {...} [match] |
|
| Finally.cs:69:9:71:9 | {...} | Finally.cs:61:38:61:39 | After IOException ex [match] |
|
||||||
|
| Finally.cs:69:9:71:9 | {...} | Finally.cs:61:38:61:39 | After IOException ex [no-match] |
|
||||||
| Finally.cs:69:9:71:9 | {...} | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] |
|
| Finally.cs:69:9:71:9 | {...} | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] |
|
||||||
|
| Finally.cs:69:9:71:9 | {...} | Finally.cs:65:26:65:26 | After Exception e [match] |
|
||||||
|
| Finally.cs:69:9:71:9 | {...} | Finally.cs:65:26:65:26 | After Exception e [no-match] |
|
||||||
| Finally.cs:69:9:71:9 | {...} | Finally.cs:65:35:65:51 | After ... != ... [false] |
|
| Finally.cs:69:9:71:9 | {...} | Finally.cs:65:35:65:51 | After ... != ... [false] |
|
||||||
| Finally.cs:69:9:71:9 | {...} | Finally.cs:65:35:65:51 | After ... != ... [true] |
|
| Finally.cs:69:9:71:9 | {...} | Finally.cs:65:35:65:51 | After ... != ... [true] |
|
||||||
| Finally.cs:69:9:71:9 | {...} | Finally.cs:69:9:71:9 | {...} |
|
| Finally.cs:69:9:71:9 | {...} | Finally.cs:69:9:71:9 | {...} |
|
||||||
@@ -21973,9 +22006,10 @@ postBlockDominance
|
|||||||
| Finally.cs:149:9:169:9 | After try {...} ... | Finally.cs:158:21:158:36 | After ... == ... [false] |
|
| Finally.cs:149:9:169:9 | After try {...} ... | Finally.cs:158:21:158:36 | After ... == ... [false] |
|
||||||
| Finally.cs:149:9:169:9 | After try {...} ... | Finally.cs:158:21:158:36 | After ... == ... [true] |
|
| Finally.cs:149:9:169:9 | After try {...} ... | Finally.cs:158:21:158:36 | After ... == ... [true] |
|
||||||
| Finally.cs:149:9:169:9 | After try {...} ... | Finally.cs:159:27:159:44 | After object creation of type Exception |
|
| Finally.cs:149:9:169:9 | After try {...} ... | Finally.cs:159:27:159:44 | After object creation of type Exception |
|
||||||
| Finally.cs:149:9:169:9 | After try {...} ... | Finally.cs:161:13:164:13 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:149:9:169:9 | After try {...} ... | Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] |
|
| Finally.cs:149:9:169:9 | After try {...} ... | Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] |
|
||||||
| Finally.cs:149:9:169:9 | After try {...} ... | Finally.cs:161:13:164:13 | catch (...) {...} |
|
| Finally.cs:149:9:169:9 | After try {...} ... | Finally.cs:161:13:164:13 | catch (...) {...} |
|
||||||
|
| Finally.cs:149:9:169:9 | After try {...} ... | Finally.cs:161:30:161:30 | After Exception e [match] |
|
||||||
|
| Finally.cs:149:9:169:9 | After try {...} ... | Finally.cs:161:30:161:30 | After Exception e [no-match] |
|
||||||
| Finally.cs:149:9:169:9 | After try {...} ... | Finally.cs:161:39:161:54 | After ... == ... [false] |
|
| Finally.cs:149:9:169:9 | After try {...} ... | Finally.cs:161:39:161:54 | After ... == ... [false] |
|
||||||
| Finally.cs:149:9:169:9 | After try {...} ... | Finally.cs:161:39:161:54 | After ... == ... [true] |
|
| Finally.cs:149:9:169:9 | After try {...} ... | Finally.cs:161:39:161:54 | After ... == ... [true] |
|
||||||
| Finally.cs:151:17:151:28 | After ... == ... [false] | Finally.cs:151:17:151:28 | After ... == ... [false] |
|
| Finally.cs:151:17:151:28 | After ... == ... [false] | Finally.cs:151:17:151:28 | After ... == ... [false] |
|
||||||
@@ -21996,21 +22030,24 @@ postBlockDominance
|
|||||||
| Finally.cs:156:13:168:13 | After try {...} ... | Finally.cs:158:21:158:36 | After ... == ... [false] |
|
| Finally.cs:156:13:168:13 | After try {...} ... | Finally.cs:158:21:158:36 | After ... == ... [false] |
|
||||||
| Finally.cs:156:13:168:13 | After try {...} ... | Finally.cs:158:21:158:36 | After ... == ... [true] |
|
| Finally.cs:156:13:168:13 | After try {...} ... | Finally.cs:158:21:158:36 | After ... == ... [true] |
|
||||||
| Finally.cs:156:13:168:13 | After try {...} ... | Finally.cs:159:27:159:44 | After object creation of type Exception |
|
| Finally.cs:156:13:168:13 | After try {...} ... | Finally.cs:159:27:159:44 | After object creation of type Exception |
|
||||||
| Finally.cs:156:13:168:13 | After try {...} ... | Finally.cs:161:13:164:13 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:156:13:168:13 | After try {...} ... | Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] |
|
| Finally.cs:156:13:168:13 | After try {...} ... | Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] |
|
||||||
| Finally.cs:156:13:168:13 | After try {...} ... | Finally.cs:161:13:164:13 | catch (...) {...} |
|
| Finally.cs:156:13:168:13 | After try {...} ... | Finally.cs:161:13:164:13 | catch (...) {...} |
|
||||||
|
| Finally.cs:156:13:168:13 | After try {...} ... | Finally.cs:161:30:161:30 | After Exception e [match] |
|
||||||
|
| Finally.cs:156:13:168:13 | After try {...} ... | Finally.cs:161:30:161:30 | After Exception e [no-match] |
|
||||||
| Finally.cs:156:13:168:13 | After try {...} ... | Finally.cs:161:39:161:54 | After ... == ... [false] |
|
| Finally.cs:156:13:168:13 | After try {...} ... | Finally.cs:161:39:161:54 | After ... == ... [false] |
|
||||||
| Finally.cs:156:13:168:13 | After try {...} ... | Finally.cs:161:39:161:54 | After ... == ... [true] |
|
| Finally.cs:156:13:168:13 | After try {...} ... | Finally.cs:161:39:161:54 | After ... == ... [true] |
|
||||||
| Finally.cs:158:21:158:31 | After access to property Length | Finally.cs:158:21:158:31 | After access to property Length |
|
| Finally.cs:158:21:158:31 | After access to property Length | Finally.cs:158:21:158:31 | After access to property Length |
|
||||||
| Finally.cs:158:21:158:36 | After ... == ... [false] | Finally.cs:158:21:158:36 | After ... == ... [false] |
|
| Finally.cs:158:21:158:36 | After ... == ... [false] | Finally.cs:158:21:158:36 | After ... == ... [false] |
|
||||||
| Finally.cs:158:21:158:36 | After ... == ... [true] | Finally.cs:158:21:158:36 | After ... == ... [true] |
|
| Finally.cs:158:21:158:36 | After ... == ... [true] | Finally.cs:158:21:158:36 | After ... == ... [true] |
|
||||||
| Finally.cs:159:27:159:44 | After object creation of type Exception | Finally.cs:159:27:159:44 | After object creation of type Exception |
|
| Finally.cs:159:27:159:44 | After object creation of type Exception | Finally.cs:159:27:159:44 | After object creation of type Exception |
|
||||||
| Finally.cs:161:13:164:13 | After catch (...) {...} [match] | Finally.cs:161:13:164:13 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] |
|
| Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] |
|
||||||
|
| Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | Finally.cs:161:30:161:30 | After Exception e [no-match] |
|
||||||
| Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | Finally.cs:161:39:161:54 | After ... == ... [false] |
|
| Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | Finally.cs:161:39:161:54 | After ... == ... [false] |
|
||||||
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:158:21:158:36 | After ... == ... [true] |
|
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:158:21:158:36 | After ... == ... [true] |
|
||||||
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:159:27:159:44 | After object creation of type Exception |
|
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:159:27:159:44 | After object creation of type Exception |
|
||||||
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:13:164:13 | catch (...) {...} |
|
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:13:164:13 | catch (...) {...} |
|
||||||
|
| Finally.cs:161:30:161:30 | After Exception e [match] | Finally.cs:161:30:161:30 | After Exception e [match] |
|
||||||
|
| Finally.cs:161:30:161:30 | After Exception e [no-match] | Finally.cs:161:30:161:30 | After Exception e [no-match] |
|
||||||
| Finally.cs:161:39:161:54 | After ... == ... [false] | Finally.cs:161:39:161:54 | After ... == ... [false] |
|
| Finally.cs:161:39:161:54 | After ... == ... [false] | Finally.cs:161:39:161:54 | After ... == ... [false] |
|
||||||
| Finally.cs:161:39:161:54 | After ... == ... [true] | Finally.cs:161:39:161:54 | After ... == ... [true] |
|
| Finally.cs:161:39:161:54 | After ... == ... [true] | Finally.cs:161:39:161:54 | After ... == ... [true] |
|
||||||
| Finally.cs:172:11:172:20 | Entry | Finally.cs:172:11:172:20 | Entry |
|
| Finally.cs:172:11:172:20 | Entry | Finally.cs:172:11:172:20 | Entry |
|
||||||
@@ -22029,8 +22066,8 @@ postBlockDominance
|
|||||||
| Finally.cs:178:9:192:9 | After try {...} ... | Finally.cs:186:21:186:22 | After access to parameter b2 [false] |
|
| Finally.cs:178:9:192:9 | After try {...} ... | Finally.cs:186:21:186:22 | After access to parameter b2 [false] |
|
||||||
| Finally.cs:178:9:192:9 | After try {...} ... | Finally.cs:186:21:186:22 | After access to parameter b2 [true] |
|
| Finally.cs:178:9:192:9 | After try {...} ... | Finally.cs:186:21:186:22 | After access to parameter b2 [true] |
|
||||||
| Finally.cs:178:9:192:9 | After try {...} ... | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
| Finally.cs:178:9:192:9 | After try {...} ... | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
||||||
| Finally.cs:178:9:192:9 | After try {...} ... | Finally.cs:188:13:191:13 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:178:9:192:9 | After try {...} ... | Finally.cs:188:13:191:13 | catch (...) {...} |
|
| Finally.cs:178:9:192:9 | After try {...} ... | Finally.cs:188:13:191:13 | catch (...) {...} |
|
||||||
|
| Finally.cs:178:9:192:9 | After try {...} ... | Finally.cs:188:20:188:29 | After access to type ExceptionB [match] |
|
||||||
| Finally.cs:178:9:192:9 | After try {...} ... | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
| Finally.cs:178:9:192:9 | After try {...} ... | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
||||||
| Finally.cs:178:9:192:9 | After try {...} ... | Finally.cs:190:21:190:22 | After access to parameter b1 [false] |
|
| Finally.cs:178:9:192:9 | After try {...} ... | Finally.cs:190:21:190:22 | After access to parameter b1 [false] |
|
||||||
| Finally.cs:180:17:180:18 | After access to parameter b1 [false] | Finally.cs:180:17:180:18 | After access to parameter b1 [false] |
|
| Finally.cs:180:17:180:18 | After access to parameter b1 [false] | Finally.cs:180:17:180:18 | After access to parameter b1 [false] |
|
||||||
@@ -22050,31 +22087,32 @@ postBlockDominance
|
|||||||
| Finally.cs:184:13:191:13 | After try {...} ... | Finally.cs:186:21:186:22 | After access to parameter b2 [false] |
|
| Finally.cs:184:13:191:13 | After try {...} ... | Finally.cs:186:21:186:22 | After access to parameter b2 [false] |
|
||||||
| Finally.cs:184:13:191:13 | After try {...} ... | Finally.cs:186:21:186:22 | After access to parameter b2 [true] |
|
| Finally.cs:184:13:191:13 | After try {...} ... | Finally.cs:186:21:186:22 | After access to parameter b2 [true] |
|
||||||
| Finally.cs:184:13:191:13 | After try {...} ... | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
| Finally.cs:184:13:191:13 | After try {...} ... | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
||||||
| Finally.cs:184:13:191:13 | After try {...} ... | Finally.cs:188:13:191:13 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:184:13:191:13 | After try {...} ... | Finally.cs:188:13:191:13 | catch (...) {...} |
|
| Finally.cs:184:13:191:13 | After try {...} ... | Finally.cs:188:13:191:13 | catch (...) {...} |
|
||||||
|
| Finally.cs:184:13:191:13 | After try {...} ... | Finally.cs:188:20:188:29 | After access to type ExceptionB [match] |
|
||||||
| Finally.cs:184:13:191:13 | After try {...} ... | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
| Finally.cs:184:13:191:13 | After try {...} ... | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
||||||
| Finally.cs:184:13:191:13 | After try {...} ... | Finally.cs:190:21:190:22 | After access to parameter b1 [false] |
|
| Finally.cs:184:13:191:13 | After try {...} ... | Finally.cs:190:21:190:22 | After access to parameter b1 [false] |
|
||||||
| Finally.cs:186:21:186:22 | After access to parameter b2 [false] | Finally.cs:186:21:186:22 | After access to parameter b2 [false] |
|
| Finally.cs:186:21:186:22 | After access to parameter b2 [false] | Finally.cs:186:21:186:22 | After access to parameter b2 [false] |
|
||||||
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:186:21:186:22 | After access to parameter b2 [true] |
|
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:186:21:186:22 | After access to parameter b2 [true] |
|
||||||
| Finally.cs:186:31:186:46 | After object creation of type ExceptionB | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
| Finally.cs:186:31:186:46 | After object creation of type ExceptionB | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [match] | Finally.cs:186:21:186:22 | After access to parameter b2 [true] |
|
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [match] | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [match] | Finally.cs:188:13:191:13 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [match] | Finally.cs:188:13:191:13 | catch (...) {...} |
|
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] |
|
| Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:186:21:186:22 | After access to parameter b2 [true] |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:186:21:186:22 | After access to parameter b2 [true] |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:13:191:13 | catch (...) {...} |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:13:191:13 | catch (...) {...} |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | Finally.cs:186:21:186:22 | After access to parameter b2 [true] |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | Finally.cs:188:13:191:13 | catch (...) {...} |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | Finally.cs:188:20:188:29 | After access to type ExceptionB [match] |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [no-match] | Finally.cs:188:20:188:29 | After access to type ExceptionB [no-match] |
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [false] | Finally.cs:188:38:188:39 | After access to parameter b2 [false] |
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [false] | Finally.cs:188:38:188:39 | After access to parameter b2 [false] |
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:186:21:186:22 | After access to parameter b2 [true] |
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:186:21:186:22 | After access to parameter b2 [true] |
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:188:13:191:13 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:188:13:191:13 | catch (...) {...} |
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:188:13:191:13 | catch (...) {...} |
|
||||||
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:188:20:188:29 | After access to type ExceptionB [match] |
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
||||||
| Finally.cs:190:21:190:22 | After access to parameter b1 [false] | Finally.cs:186:21:186:22 | After access to parameter b2 [true] |
|
| Finally.cs:190:21:190:22 | After access to parameter b1 [false] | Finally.cs:186:21:186:22 | After access to parameter b2 [true] |
|
||||||
| Finally.cs:190:21:190:22 | After access to parameter b1 [false] | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
| Finally.cs:190:21:190:22 | After access to parameter b1 [false] | Finally.cs:186:31:186:46 | After object creation of type ExceptionB |
|
||||||
| Finally.cs:190:21:190:22 | After access to parameter b1 [false] | Finally.cs:188:13:191:13 | After catch (...) {...} [match] |
|
|
||||||
| Finally.cs:190:21:190:22 | After access to parameter b1 [false] | Finally.cs:188:13:191:13 | catch (...) {...} |
|
| Finally.cs:190:21:190:22 | After access to parameter b1 [false] | Finally.cs:188:13:191:13 | catch (...) {...} |
|
||||||
|
| Finally.cs:190:21:190:22 | After access to parameter b1 [false] | Finally.cs:188:20:188:29 | After access to type ExceptionB [match] |
|
||||||
| Finally.cs:190:21:190:22 | After access to parameter b1 [false] | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
| Finally.cs:190:21:190:22 | After access to parameter b1 [false] | Finally.cs:188:38:188:39 | After access to parameter b2 [true] |
|
||||||
| Finally.cs:190:21:190:22 | After access to parameter b1 [false] | Finally.cs:190:21:190:22 | After access to parameter b1 [false] |
|
| Finally.cs:190:21:190:22 | After access to parameter b1 [false] | Finally.cs:190:21:190:22 | After access to parameter b1 [false] |
|
||||||
| Finally.cs:190:21:190:22 | After access to parameter b1 [true] | Finally.cs:190:21:190:22 | After access to parameter b1 [true] |
|
| Finally.cs:190:21:190:22 | After access to parameter b1 [true] | Finally.cs:190:21:190:22 | After access to parameter b1 [true] |
|
||||||
|
|||||||
@@ -3016,15 +3016,19 @@ nodeEnclosing
|
|||||||
| ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | ExitMethods.cs:38:10:38:11 | M6 |
|
| ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
| ExitMethods.cs:42:13:42:31 | ...; | ExitMethods.cs:38:10:38:11 | M6 |
|
| ExitMethods.cs:42:13:42:31 | ...; | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
| ExitMethods.cs:42:25:42:29 | false | ExitMethods.cs:38:10:38:11 | M6 |
|
| ExitMethods.cs:42:25:42:29 | false | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [match] | ExitMethods.cs:38:10:38:11 | M6 |
|
|
||||||
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] | ExitMethods.cs:38:10:38:11 | M6 |
|
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
| ExitMethods.cs:44:9:47:9 | catch (...) {...} | ExitMethods.cs:38:10:38:11 | M6 |
|
| ExitMethods.cs:44:9:47:9 | catch (...) {...} | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
|
| ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [match] | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
|
| ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [no-match] | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
|
| ExitMethods.cs:44:16:44:32 | access to type ArgumentException | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:38:10:38:11 | M6 |
|
| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
| ExitMethods.cs:46:13:46:19 | Before return ...; | ExitMethods.cs:38:10:38:11 | M6 |
|
| ExitMethods.cs:46:13:46:19 | Before return ...; | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
| ExitMethods.cs:46:13:46:19 | return ...; | ExitMethods.cs:38:10:38:11 | M6 |
|
| ExitMethods.cs:46:13:46:19 | return ...; | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
| ExitMethods.cs:48:9:51:9 | After catch (...) {...} [match] | ExitMethods.cs:38:10:38:11 | M6 |
|
|
||||||
| ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] | ExitMethods.cs:38:10:38:11 | M6 |
|
| ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
| ExitMethods.cs:48:9:51:9 | catch (...) {...} | ExitMethods.cs:38:10:38:11 | M6 |
|
| ExitMethods.cs:48:9:51:9 | catch (...) {...} | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
|
| ExitMethods.cs:48:16:48:24 | After access to type Exception [match] | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
|
| ExitMethods.cs:48:16:48:24 | After access to type Exception [no-match] | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
|
| ExitMethods.cs:48:16:48:24 | access to type Exception | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:38:10:38:11 | M6 |
|
| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
| ExitMethods.cs:50:13:50:19 | Before return ...; | ExitMethods.cs:38:10:38:11 | M6 |
|
| ExitMethods.cs:50:13:50:19 | Before return ...; | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
| ExitMethods.cs:50:13:50:19 | return ...; | ExitMethods.cs:38:10:38:11 | M6 |
|
| ExitMethods.cs:50:13:50:19 | return ...; | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
@@ -3358,18 +3362,20 @@ nodeEnclosing
|
|||||||
| Finally.cs:23:31:23:36 | "Try2" | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:23:31:23:36 | "Try2" | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:24:13:24:19 | Before return ...; | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:24:13:24:19 | Before return ...; | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:24:13:24:19 | return ...; | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:24:13:24:19 | return ...; | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [match] | Finally.cs:19:10:19:11 | M2 |
|
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:19:10:19:11 | M2 |
|
||||||
|
| Finally.cs:26:38:26:39 | After IOException ex [match] | Finally.cs:19:10:19:11 | M2 |
|
||||||
|
| Finally.cs:26:38:26:39 | After IOException ex [no-match] | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:26:38:26:39 | IOException ex | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:26:38:26:39 | IOException ex | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:26:48:26:51 | After true [true] | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:26:48:26:51 | After true [true] | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:26:48:26:51 | true | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:26:48:26:51 | true | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:27:9:29:9 | {...} | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:27:9:29:9 | {...} | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:28:13:28:18 | Before throw ...; | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:28:13:28:18 | Before throw ...; | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:28:13:28:18 | throw ...; | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:28:13:28:18 | throw ...; | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:30:9:40:9 | After catch (...) {...} [match] | Finally.cs:19:10:19:11 | M2 |
|
|
||||||
| Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:30:9:40:9 | catch (...) {...} | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:30:9:40:9 | catch (...) {...} | Finally.cs:19:10:19:11 | M2 |
|
||||||
|
| Finally.cs:30:41:30:42 | After ArgumentException ex [match] | Finally.cs:19:10:19:11 | M2 |
|
||||||
|
| Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:30:41:30:42 | ArgumentException ex | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:30:41:30:42 | ArgumentException ex | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:31:9:40:9 | {...} | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:31:9:40:9 | {...} | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:32:13:39:13 | try {...} ... | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:32:13:39:13 | try {...} ... | Finally.cs:19:10:19:11 | M2 |
|
||||||
@@ -3386,11 +3392,12 @@ nodeEnclosing
|
|||||||
| Finally.cs:38:23:38:43 | Before object creation of type Exception | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:38:23:38:43 | Before object creation of type Exception | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:38:23:38:43 | object creation of type Exception | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:38:23:38:43 | object creation of type Exception | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:38:37:38:42 | "Boo!" | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:38:37:38:42 | "Boo!" | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:41:9:43:9 | After catch (...) {...} [match] | Finally.cs:19:10:19:11 | M2 |
|
|
||||||
| Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:41:9:43:9 | catch (...) {...} | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:41:9:43:9 | catch (...) {...} | Finally.cs:19:10:19:11 | M2 |
|
||||||
|
| Finally.cs:41:16:41:24 | After access to type Exception [match] | Finally.cs:19:10:19:11 | M2 |
|
||||||
|
| Finally.cs:41:16:41:24 | After access to type Exception [no-match] | Finally.cs:19:10:19:11 | M2 |
|
||||||
|
| Finally.cs:41:16:41:24 | access to type Exception | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:42:9:43:9 | {...} | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:42:9:43:9 | {...} | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:44:9:47:9 | After catch {...} [match] | Finally.cs:19:10:19:11 | M2 |
|
|
||||||
| Finally.cs:44:9:47:9 | catch {...} | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:44:9:47:9 | catch {...} | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:45:9:47:9 | {...} | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:45:9:47:9 | {...} | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:46:13:46:19 | Before return ...; | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:46:13:46:19 | Before return ...; | Finally.cs:19:10:19:11 | M2 |
|
||||||
@@ -3420,18 +3427,20 @@ nodeEnclosing
|
|||||||
| Finally.cs:58:31:58:36 | "Try3" | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:58:31:58:36 | "Try3" | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:59:13:59:19 | Before return ...; | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:59:13:59:19 | Before return ...; | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:59:13:59:19 | return ...; | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:59:13:59:19 | return ...; | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [match] | Finally.cs:54:10:54:11 | M3 |
|
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:54:10:54:11 | M3 |
|
||||||
|
| Finally.cs:61:38:61:39 | After IOException ex [match] | Finally.cs:54:10:54:11 | M3 |
|
||||||
|
| Finally.cs:61:38:61:39 | After IOException ex [no-match] | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:61:38:61:39 | IOException ex | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:61:38:61:39 | IOException ex | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:61:48:61:51 | After true [true] | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:61:48:61:51 | After true [true] | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:61:48:61:51 | true | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:61:48:61:51 | true | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:62:9:64:9 | {...} | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:62:9:64:9 | {...} | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:63:13:63:18 | Before throw ...; | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:63:13:63:18 | Before throw ...; | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:63:13:63:18 | throw ...; | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:63:13:63:18 | throw ...; | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:65:9:67:9 | After catch (...) {...} [match] | Finally.cs:54:10:54:11 | M3 |
|
|
||||||
| Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:54:10:54:11 | M3 |
|
||||||
|
| Finally.cs:65:26:65:26 | After Exception e [match] | Finally.cs:54:10:54:11 | M3 |
|
||||||
|
| Finally.cs:65:26:65:26 | After Exception e [no-match] | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:65:26:65:26 | Exception e | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:65:26:65:26 | Exception e | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:65:35:65:35 | access to local variable e | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:65:35:65:35 | access to local variable e | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:65:35:65:43 | After access to property Message | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:65:35:65:43 | After access to property Message | Finally.cs:54:10:54:11 | M3 |
|
||||||
@@ -3719,9 +3728,10 @@ nodeEnclosing
|
|||||||
| Finally.cs:159:27:159:44 | Before object creation of type Exception | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:159:27:159:44 | Before object creation of type Exception | Finally.cs:147:10:147:11 | M8 |
|
||||||
| Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:147:10:147:11 | M8 |
|
||||||
| Finally.cs:159:41:159:43 | "1" | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:159:41:159:43 | "1" | Finally.cs:147:10:147:11 | M8 |
|
||||||
| Finally.cs:161:13:164:13 | After catch (...) {...} [match] | Finally.cs:147:10:147:11 | M8 |
|
|
||||||
| Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | Finally.cs:147:10:147:11 | M8 |
|
||||||
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:147:10:147:11 | M8 |
|
||||||
|
| Finally.cs:161:30:161:30 | After Exception e [match] | Finally.cs:147:10:147:11 | M8 |
|
||||||
|
| Finally.cs:161:30:161:30 | After Exception e [no-match] | Finally.cs:147:10:147:11 | M8 |
|
||||||
| Finally.cs:161:30:161:30 | Exception e | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:161:30:161:30 | Exception e | Finally.cs:147:10:147:11 | M8 |
|
||||||
| Finally.cs:161:39:161:39 | access to local variable e | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:161:39:161:39 | access to local variable e | Finally.cs:147:10:147:11 | M8 |
|
||||||
| Finally.cs:161:39:161:47 | After access to property Message | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:161:39:161:47 | After access to property Message | Finally.cs:147:10:147:11 | M8 |
|
||||||
@@ -3744,7 +3754,6 @@ nodeEnclosing
|
|||||||
| Finally.cs:163:35:163:41 | Before access to array element | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:163:35:163:41 | Before access to array element | Finally.cs:147:10:147:11 | M8 |
|
||||||
| Finally.cs:163:35:163:41 | access to array element | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:163:35:163:41 | access to array element | Finally.cs:147:10:147:11 | M8 |
|
||||||
| Finally.cs:163:40:163:40 | 0 | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:163:40:163:40 | 0 | Finally.cs:147:10:147:11 | M8 |
|
||||||
| Finally.cs:165:13:168:13 | After catch {...} [match] | Finally.cs:147:10:147:11 | M8 |
|
|
||||||
| Finally.cs:165:13:168:13 | catch {...} | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:165:13:168:13 | catch {...} | Finally.cs:147:10:147:11 | M8 |
|
||||||
| Finally.cs:166:13:168:13 | After {...} | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:166:13:168:13 | After {...} | Finally.cs:147:10:147:11 | M8 |
|
||||||
| Finally.cs:166:13:168:13 | {...} | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:166:13:168:13 | {...} | Finally.cs:147:10:147:11 | M8 |
|
||||||
@@ -3825,9 +3834,11 @@ nodeEnclosing
|
|||||||
| Finally.cs:186:31:186:46 | After object creation of type ExceptionB | Finally.cs:176:10:176:11 | M9 |
|
| Finally.cs:186:31:186:46 | After object creation of type ExceptionB | Finally.cs:176:10:176:11 | M9 |
|
||||||
| Finally.cs:186:31:186:46 | Before object creation of type ExceptionB | Finally.cs:176:10:176:11 | M9 |
|
| Finally.cs:186:31:186:46 | Before object creation of type ExceptionB | Finally.cs:176:10:176:11 | M9 |
|
||||||
| Finally.cs:186:31:186:46 | object creation of type ExceptionB | Finally.cs:176:10:176:11 | M9 |
|
| Finally.cs:186:31:186:46 | object creation of type ExceptionB | Finally.cs:176:10:176:11 | M9 |
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [match] | Finally.cs:176:10:176:11 | M9 |
|
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] | Finally.cs:176:10:176:11 | M9 |
|
| Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] | Finally.cs:176:10:176:11 | M9 |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:176:10:176:11 | M9 |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:176:10:176:11 | M9 |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | Finally.cs:176:10:176:11 | M9 |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [no-match] | Finally.cs:176:10:176:11 | M9 |
|
||||||
|
| Finally.cs:188:20:188:29 | access to type ExceptionB | Finally.cs:176:10:176:11 | M9 |
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [false] | Finally.cs:176:10:176:11 | M9 |
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [false] | Finally.cs:176:10:176:11 | M9 |
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:176:10:176:11 | M9 |
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:176:10:176:11 | M9 |
|
||||||
| Finally.cs:188:38:188:39 | access to parameter b2 | Finally.cs:176:10:176:11 | M9 |
|
| Finally.cs:188:38:188:39 | access to parameter b2 | Finally.cs:176:10:176:11 | M9 |
|
||||||
@@ -3929,7 +3940,6 @@ nodeEnclosing
|
|||||||
| Finally.cs:220:13:220:37 | ...; | Finally.cs:216:10:216:12 | M11 |
|
| Finally.cs:220:13:220:37 | ...; | Finally.cs:216:10:216:12 | M11 |
|
||||||
| Finally.cs:220:13:220:37 | After ...; | Finally.cs:216:10:216:12 | M11 |
|
| Finally.cs:220:13:220:37 | After ...; | Finally.cs:216:10:216:12 | M11 |
|
||||||
| Finally.cs:220:31:220:35 | "Try" | Finally.cs:216:10:216:12 | M11 |
|
| Finally.cs:220:31:220:35 | "Try" | Finally.cs:216:10:216:12 | M11 |
|
||||||
| Finally.cs:222:9:225:9 | After catch {...} [match] | Finally.cs:216:10:216:12 | M11 |
|
|
||||||
| Finally.cs:222:9:225:9 | catch {...} | Finally.cs:216:10:216:12 | M11 |
|
| Finally.cs:222:9:225:9 | catch {...} | Finally.cs:216:10:216:12 | M11 |
|
||||||
| Finally.cs:223:9:225:9 | After {...} | Finally.cs:216:10:216:12 | M11 |
|
| Finally.cs:223:9:225:9 | After {...} | Finally.cs:216:10:216:12 | M11 |
|
||||||
| Finally.cs:223:9:225:9 | {...} | Finally.cs:216:10:216:12 | M11 |
|
| Finally.cs:223:9:225:9 | {...} | Finally.cs:216:10:216:12 | M11 |
|
||||||
@@ -8830,10 +8840,10 @@ blockEnclosing
|
|||||||
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:38:10:38:11 | M6 |
|
| ExitMethods.cs:38:10:38:11 | Entry | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
| ExitMethods.cs:38:10:38:11 | Exit | ExitMethods.cs:38:10:38:11 | M6 |
|
| ExitMethods.cs:38:10:38:11 | Exit | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
| ExitMethods.cs:38:10:38:11 | Normal Exit | ExitMethods.cs:38:10:38:11 | M6 |
|
| ExitMethods.cs:38:10:38:11 | Normal Exit | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [match] | ExitMethods.cs:38:10:38:11 | M6 |
|
| ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [match] | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] | ExitMethods.cs:38:10:38:11 | M6 |
|
| ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [no-match] | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
| ExitMethods.cs:48:9:51:9 | After catch (...) {...} [match] | ExitMethods.cs:38:10:38:11 | M6 |
|
| ExitMethods.cs:48:16:48:24 | After access to type Exception [match] | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
| ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] | ExitMethods.cs:38:10:38:11 | M6 |
|
| ExitMethods.cs:48:16:48:24 | After access to type Exception [no-match] | ExitMethods.cs:38:10:38:11 | M6 |
|
||||||
| ExitMethods.cs:54:10:54:11 | Entry | ExitMethods.cs:54:10:54:11 | M7 |
|
| ExitMethods.cs:54:10:54:11 | Entry | ExitMethods.cs:54:10:54:11 | M7 |
|
||||||
| ExitMethods.cs:60:10:60:11 | Entry | ExitMethods.cs:60:10:60:11 | M8 |
|
| ExitMethods.cs:60:10:60:11 | Entry | ExitMethods.cs:60:10:60:11 | M8 |
|
||||||
| ExitMethods.cs:66:17:66:26 | Entry | ExitMethods.cs:66:17:66:26 | ErrorMaybe |
|
| ExitMethods.cs:66:17:66:26 | Entry | ExitMethods.cs:66:17:66:26 | ErrorMaybe |
|
||||||
@@ -8888,13 +8898,13 @@ blockEnclosing
|
|||||||
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:19:10:19:11 | Normal Exit | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:21:9:51:9 | After try {...} ... | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:21:9:51:9 | After try {...} ... | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:23:13:23:37 | After call to method WriteLine | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:23:13:23:37 | After call to method WriteLine | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [match] | Finally.cs:19:10:19:11 | M2 |
|
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | Finally.cs:19:10:19:11 | M2 |
|
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:30:9:40:9 | After catch (...) {...} [match] | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:26:38:26:39 | After IOException ex [match] | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:26:38:26:39 | After IOException ex [no-match] | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:41:9:43:9 | After catch (...) {...} [match] | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:30:41:30:42 | After ArgumentException ex [match] | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] | Finally.cs:19:10:19:11 | M2 |
|
||||||
|
| Finally.cs:41:16:41:24 | After access to type Exception [match] | Finally.cs:19:10:19:11 | M2 |
|
||||||
|
| Finally.cs:41:16:41:24 | After access to type Exception [no-match] | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:49:9:51:9 | {...} | Finally.cs:19:10:19:11 | M2 |
|
| Finally.cs:49:9:51:9 | {...} | Finally.cs:19:10:19:11 | M2 |
|
||||||
| Finally.cs:54:10:54:11 | Entry | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:54:10:54:11 | Entry | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:54:10:54:11 | Exceptional Exit | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:54:10:54:11 | Exceptional Exit | Finally.cs:54:10:54:11 | M3 |
|
||||||
@@ -8902,11 +8912,12 @@ blockEnclosing
|
|||||||
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:54:10:54:11 | Normal Exit | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:56:9:71:9 | After try {...} ... | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:56:9:71:9 | After try {...} ... | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:58:13:58:37 | After call to method WriteLine | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:58:13:58:37 | After call to method WriteLine | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [match] | Finally.cs:54:10:54:11 | M3 |
|
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | Finally.cs:54:10:54:11 | M3 |
|
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:65:9:67:9 | After catch (...) {...} [match] | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:61:38:61:39 | After IOException ex [match] | Finally.cs:54:10:54:11 | M3 |
|
||||||
|
| Finally.cs:61:38:61:39 | After IOException ex [no-match] | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | Finally.cs:54:10:54:11 | M3 |
|
||||||
|
| Finally.cs:65:26:65:26 | After Exception e [match] | Finally.cs:54:10:54:11 | M3 |
|
||||||
|
| Finally.cs:65:26:65:26 | After Exception e [no-match] | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:65:35:65:51 | After ... != ... [false] | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:65:35:65:51 | After ... != ... [false] | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:65:35:65:51 | After ... != ... [true] | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:65:35:65:51 | After ... != ... [true] | Finally.cs:54:10:54:11 | M3 |
|
||||||
| Finally.cs:69:9:71:9 | {...} | Finally.cs:54:10:54:11 | M3 |
|
| Finally.cs:69:9:71:9 | {...} | Finally.cs:54:10:54:11 | M3 |
|
||||||
@@ -8969,9 +8980,10 @@ blockEnclosing
|
|||||||
| Finally.cs:158:21:158:36 | After ... == ... [false] | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:158:21:158:36 | After ... == ... [false] | Finally.cs:147:10:147:11 | M8 |
|
||||||
| Finally.cs:158:21:158:36 | After ... == ... [true] | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:158:21:158:36 | After ... == ... [true] | Finally.cs:147:10:147:11 | M8 |
|
||||||
| Finally.cs:159:27:159:44 | After object creation of type Exception | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:159:27:159:44 | After object creation of type Exception | Finally.cs:147:10:147:11 | M8 |
|
||||||
| Finally.cs:161:13:164:13 | After catch (...) {...} [match] | Finally.cs:147:10:147:11 | M8 |
|
|
||||||
| Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | Finally.cs:147:10:147:11 | M8 |
|
||||||
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:147:10:147:11 | M8 |
|
||||||
|
| Finally.cs:161:30:161:30 | After Exception e [match] | Finally.cs:147:10:147:11 | M8 |
|
||||||
|
| Finally.cs:161:30:161:30 | After Exception e [no-match] | Finally.cs:147:10:147:11 | M8 |
|
||||||
| Finally.cs:161:39:161:54 | After ... == ... [false] | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:161:39:161:54 | After ... == ... [false] | Finally.cs:147:10:147:11 | M8 |
|
||||||
| Finally.cs:161:39:161:54 | After ... == ... [true] | Finally.cs:147:10:147:11 | M8 |
|
| Finally.cs:161:39:161:54 | After ... == ... [true] | Finally.cs:147:10:147:11 | M8 |
|
||||||
| Finally.cs:172:11:172:20 | Entry | Finally.cs:172:11:172:20 | ExceptionA |
|
| Finally.cs:172:11:172:20 | Entry | Finally.cs:172:11:172:20 | ExceptionA |
|
||||||
@@ -8989,9 +9001,10 @@ blockEnclosing
|
|||||||
| Finally.cs:186:21:186:22 | After access to parameter b2 [false] | Finally.cs:176:10:176:11 | M9 |
|
| Finally.cs:186:21:186:22 | After access to parameter b2 [false] | Finally.cs:176:10:176:11 | M9 |
|
||||||
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:176:10:176:11 | M9 |
|
| Finally.cs:186:21:186:22 | After access to parameter b2 [true] | Finally.cs:176:10:176:11 | M9 |
|
||||||
| Finally.cs:186:31:186:46 | After object creation of type ExceptionB | Finally.cs:176:10:176:11 | M9 |
|
| Finally.cs:186:31:186:46 | After object creation of type ExceptionB | Finally.cs:176:10:176:11 | M9 |
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [match] | Finally.cs:176:10:176:11 | M9 |
|
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] | Finally.cs:176:10:176:11 | M9 |
|
| Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] | Finally.cs:176:10:176:11 | M9 |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:176:10:176:11 | M9 |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:176:10:176:11 | M9 |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | Finally.cs:176:10:176:11 | M9 |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [no-match] | Finally.cs:176:10:176:11 | M9 |
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [false] | Finally.cs:176:10:176:11 | M9 |
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [false] | Finally.cs:176:10:176:11 | M9 |
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:176:10:176:11 | M9 |
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:176:10:176:11 | M9 |
|
||||||
| Finally.cs:190:21:190:22 | After access to parameter b1 [false] | Finally.cs:176:10:176:11 | M9 |
|
| Finally.cs:190:21:190:22 | After access to parameter b1 [false] | Finally.cs:176:10:176:11 | M9 |
|
||||||
|
|||||||
@@ -1398,9 +1398,11 @@
|
|||||||
| ExitMethods.cs:42:13:42:31 | ...; | ExitMethods.cs:42:13:42:31 | ...; |
|
| ExitMethods.cs:42:13:42:31 | ...; | ExitMethods.cs:42:13:42:31 | ...; |
|
||||||
| ExitMethods.cs:42:25:42:29 | false | ExitMethods.cs:42:25:42:29 | false |
|
| ExitMethods.cs:42:25:42:29 | false | ExitMethods.cs:42:25:42:29 | false |
|
||||||
| ExitMethods.cs:44:9:47:9 | catch (...) {...} | ExitMethods.cs:44:9:47:9 | catch (...) {...} |
|
| ExitMethods.cs:44:9:47:9 | catch (...) {...} | ExitMethods.cs:44:9:47:9 | catch (...) {...} |
|
||||||
|
| ExitMethods.cs:44:16:44:32 | access to type ArgumentException | ExitMethods.cs:44:16:44:32 | access to type ArgumentException |
|
||||||
| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:45:9:47:9 | {...} |
|
| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:45:9:47:9 | {...} |
|
||||||
| ExitMethods.cs:46:13:46:19 | return ...; | ExitMethods.cs:46:13:46:19 | return ...; |
|
| ExitMethods.cs:46:13:46:19 | return ...; | ExitMethods.cs:46:13:46:19 | return ...; |
|
||||||
| ExitMethods.cs:48:9:51:9 | catch (...) {...} | ExitMethods.cs:48:9:51:9 | catch (...) {...} |
|
| ExitMethods.cs:48:9:51:9 | catch (...) {...} | ExitMethods.cs:48:9:51:9 | catch (...) {...} |
|
||||||
|
| ExitMethods.cs:48:16:48:24 | access to type Exception | ExitMethods.cs:48:16:48:24 | access to type Exception |
|
||||||
| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:49:9:51:9 | {...} |
|
| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:49:9:51:9 | {...} |
|
||||||
| ExitMethods.cs:50:13:50:19 | return ...; | ExitMethods.cs:50:13:50:19 | return ...; |
|
| ExitMethods.cs:50:13:50:19 | return ...; | ExitMethods.cs:50:13:50:19 | return ...; |
|
||||||
| ExitMethods.cs:55:5:58:5 | {...} | ExitMethods.cs:55:5:58:5 | {...} |
|
| ExitMethods.cs:55:5:58:5 | {...} | ExitMethods.cs:55:5:58:5 | {...} |
|
||||||
@@ -1569,6 +1571,7 @@
|
|||||||
| Finally.cs:38:23:38:43 | object creation of type Exception | Finally.cs:38:37:38:42 | "Boo!" |
|
| Finally.cs:38:23:38:43 | object creation of type Exception | Finally.cs:38:37:38:42 | "Boo!" |
|
||||||
| Finally.cs:38:37:38:42 | "Boo!" | Finally.cs:38:37:38:42 | "Boo!" |
|
| Finally.cs:38:37:38:42 | "Boo!" | Finally.cs:38:37:38:42 | "Boo!" |
|
||||||
| Finally.cs:41:9:43:9 | catch (...) {...} | Finally.cs:41:9:43:9 | catch (...) {...} |
|
| Finally.cs:41:9:43:9 | catch (...) {...} | Finally.cs:41:9:43:9 | catch (...) {...} |
|
||||||
|
| Finally.cs:41:16:41:24 | access to type Exception | Finally.cs:41:16:41:24 | access to type Exception |
|
||||||
| Finally.cs:42:9:43:9 | {...} | Finally.cs:42:9:43:9 | {...} |
|
| Finally.cs:42:9:43:9 | {...} | Finally.cs:42:9:43:9 | {...} |
|
||||||
| Finally.cs:44:9:47:9 | catch {...} | Finally.cs:44:9:47:9 | catch {...} |
|
| Finally.cs:44:9:47:9 | catch {...} | Finally.cs:44:9:47:9 | catch {...} |
|
||||||
| Finally.cs:45:9:47:9 | {...} | Finally.cs:45:9:47:9 | {...} |
|
| Finally.cs:45:9:47:9 | {...} | Finally.cs:45:9:47:9 | {...} |
|
||||||
@@ -1766,6 +1769,7 @@
|
|||||||
| Finally.cs:186:25:186:47 | throw ...; | Finally.cs:186:31:186:46 | object creation of type ExceptionB |
|
| Finally.cs:186:25:186:47 | throw ...; | Finally.cs:186:31:186:46 | object creation of type ExceptionB |
|
||||||
| Finally.cs:186:31:186:46 | object creation of type ExceptionB | Finally.cs:186:31:186:46 | object creation of type ExceptionB |
|
| Finally.cs:186:31:186:46 | object creation of type ExceptionB | Finally.cs:186:31:186:46 | object creation of type ExceptionB |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:13:191:13 | catch (...) {...} |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:13:191:13 | catch (...) {...} |
|
||||||
|
| Finally.cs:188:20:188:29 | access to type ExceptionB | Finally.cs:188:20:188:29 | access to type ExceptionB |
|
||||||
| Finally.cs:188:38:188:39 | access to parameter b2 | Finally.cs:188:38:188:39 | access to parameter b2 |
|
| Finally.cs:188:38:188:39 | access to parameter b2 | Finally.cs:188:38:188:39 | access to parameter b2 |
|
||||||
| Finally.cs:189:13:191:13 | {...} | Finally.cs:189:13:191:13 | {...} |
|
| Finally.cs:189:13:191:13 | {...} | Finally.cs:189:13:191:13 | {...} |
|
||||||
| Finally.cs:190:17:190:47 | if (...) ... | Finally.cs:190:17:190:47 | if (...) ... |
|
| Finally.cs:190:17:190:47 | if (...) ... | Finally.cs:190:17:190:47 | if (...) ... |
|
||||||
|
|||||||
@@ -3062,17 +3062,21 @@
|
|||||||
| ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | ExitMethods.cs:44:9:47:9 | catch (...) {...} | exception |
|
| ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | ExitMethods.cs:44:9:47:9 | catch (...) {...} | exception |
|
||||||
| ExitMethods.cs:42:13:42:31 | ...; | ExitMethods.cs:42:13:42:30 | Before call to method ErrorAlways | |
|
| ExitMethods.cs:42:13:42:31 | ...; | ExitMethods.cs:42:13:42:30 | Before call to method ErrorAlways | |
|
||||||
| ExitMethods.cs:42:25:42:29 | false | ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | |
|
| ExitMethods.cs:42:25:42:29 | false | ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | |
|
||||||
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [match] | ExitMethods.cs:45:9:47:9 | {...} | |
|
|
||||||
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] | ExitMethods.cs:48:9:51:9 | catch (...) {...} | |
|
| ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] | ExitMethods.cs:48:9:51:9 | catch (...) {...} | |
|
||||||
| ExitMethods.cs:44:9:47:9 | catch (...) {...} | ExitMethods.cs:44:9:47:9 | After catch (...) {...} [match] | match |
|
| ExitMethods.cs:44:9:47:9 | catch (...) {...} | ExitMethods.cs:44:16:44:32 | access to type ArgumentException | |
|
||||||
| ExitMethods.cs:44:9:47:9 | catch (...) {...} | ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] | no-match |
|
| ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [match] | ExitMethods.cs:45:9:47:9 | {...} | |
|
||||||
|
| ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [no-match] | ExitMethods.cs:44:9:47:9 | After catch (...) {...} [no-match] | no-match |
|
||||||
|
| ExitMethods.cs:44:16:44:32 | access to type ArgumentException | ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [match] | match |
|
||||||
|
| ExitMethods.cs:44:16:44:32 | access to type ArgumentException | ExitMethods.cs:44:16:44:32 | After access to type ArgumentException [no-match] | no-match |
|
||||||
| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:46:13:46:19 | Before return ...; | |
|
| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:46:13:46:19 | Before return ...; | |
|
||||||
| ExitMethods.cs:46:13:46:19 | Before return ...; | ExitMethods.cs:46:13:46:19 | return ...; | |
|
| ExitMethods.cs:46:13:46:19 | Before return ...; | ExitMethods.cs:46:13:46:19 | return ...; | |
|
||||||
| ExitMethods.cs:46:13:46:19 | return ...; | ExitMethods.cs:38:10:38:11 | Normal Exit | return |
|
| ExitMethods.cs:46:13:46:19 | return ...; | ExitMethods.cs:38:10:38:11 | Normal Exit | return |
|
||||||
| ExitMethods.cs:48:9:51:9 | After catch (...) {...} [match] | ExitMethods.cs:49:9:51:9 | {...} | |
|
|
||||||
| ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] | ExitMethods.cs:38:10:38:11 | Exceptional Exit | exception |
|
| ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] | ExitMethods.cs:38:10:38:11 | Exceptional Exit | exception |
|
||||||
| ExitMethods.cs:48:9:51:9 | catch (...) {...} | ExitMethods.cs:48:9:51:9 | After catch (...) {...} [match] | match |
|
| ExitMethods.cs:48:9:51:9 | catch (...) {...} | ExitMethods.cs:48:16:48:24 | access to type Exception | |
|
||||||
| ExitMethods.cs:48:9:51:9 | catch (...) {...} | ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] | no-match |
|
| ExitMethods.cs:48:16:48:24 | After access to type Exception [match] | ExitMethods.cs:49:9:51:9 | {...} | |
|
||||||
|
| ExitMethods.cs:48:16:48:24 | After access to type Exception [no-match] | ExitMethods.cs:48:9:51:9 | After catch (...) {...} [no-match] | no-match |
|
||||||
|
| ExitMethods.cs:48:16:48:24 | access to type Exception | ExitMethods.cs:48:16:48:24 | After access to type Exception [match] | match |
|
||||||
|
| ExitMethods.cs:48:16:48:24 | access to type Exception | ExitMethods.cs:48:16:48:24 | After access to type Exception [no-match] | no-match |
|
||||||
| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:50:13:50:19 | Before return ...; | |
|
| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:50:13:50:19 | Before return ...; | |
|
||||||
| ExitMethods.cs:50:13:50:19 | Before return ...; | ExitMethods.cs:50:13:50:19 | return ...; | |
|
| ExitMethods.cs:50:13:50:19 | Before return ...; | ExitMethods.cs:50:13:50:19 | return ...; | |
|
||||||
| ExitMethods.cs:50:13:50:19 | return ...; | ExitMethods.cs:38:10:38:11 | Normal Exit | return |
|
| ExitMethods.cs:50:13:50:19 | return ...; | ExitMethods.cs:38:10:38:11 | Normal Exit | return |
|
||||||
@@ -3393,21 +3397,23 @@
|
|||||||
| Finally.cs:23:31:23:36 | "Try2" | Finally.cs:23:13:23:37 | call to method WriteLine | |
|
| Finally.cs:23:31:23:36 | "Try2" | Finally.cs:23:13:23:37 | call to method WriteLine | |
|
||||||
| Finally.cs:24:13:24:19 | Before return ...; | Finally.cs:24:13:24:19 | return ...; | |
|
| Finally.cs:24:13:24:19 | Before return ...; | Finally.cs:24:13:24:19 | return ...; | |
|
||||||
| Finally.cs:24:13:24:19 | return ...; | Finally.cs:49:9:51:9 | {...} | return |
|
| Finally.cs:24:13:24:19 | return ...; | Finally.cs:49:9:51:9 | {...} | return |
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [match] | Finally.cs:26:38:26:39 | IOException ex | |
|
|
||||||
| Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | Finally.cs:30:9:40:9 | catch (...) {...} | |
|
| Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | Finally.cs:30:9:40:9 | catch (...) {...} | |
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:9:29:9 | After catch (...) {...} [match] | match |
|
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:38:26:39 | IOException ex | |
|
||||||
| Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | no-match |
|
| Finally.cs:26:38:26:39 | After IOException ex [match] | Finally.cs:26:48:26:51 | true | |
|
||||||
| Finally.cs:26:38:26:39 | IOException ex | Finally.cs:26:48:26:51 | true | |
|
| Finally.cs:26:38:26:39 | After IOException ex [no-match] | Finally.cs:26:9:29:9 | After catch (...) {...} [no-match] | no-match |
|
||||||
|
| Finally.cs:26:38:26:39 | IOException ex | Finally.cs:26:38:26:39 | After IOException ex [match] | match |
|
||||||
|
| Finally.cs:26:38:26:39 | IOException ex | Finally.cs:26:38:26:39 | After IOException ex [no-match] | no-match |
|
||||||
| Finally.cs:26:48:26:51 | After true [true] | Finally.cs:27:9:29:9 | {...} | |
|
| Finally.cs:26:48:26:51 | After true [true] | Finally.cs:27:9:29:9 | {...} | |
|
||||||
| Finally.cs:26:48:26:51 | true | Finally.cs:26:48:26:51 | After true [true] | true |
|
| Finally.cs:26:48:26:51 | true | Finally.cs:26:48:26:51 | After true [true] | true |
|
||||||
| Finally.cs:27:9:29:9 | {...} | Finally.cs:28:13:28:18 | Before throw ...; | |
|
| Finally.cs:27:9:29:9 | {...} | Finally.cs:28:13:28:18 | Before throw ...; | |
|
||||||
| Finally.cs:28:13:28:18 | Before throw ...; | Finally.cs:28:13:28:18 | throw ...; | |
|
| Finally.cs:28:13:28:18 | Before throw ...; | Finally.cs:28:13:28:18 | throw ...; | |
|
||||||
| Finally.cs:28:13:28:18 | throw ...; | Finally.cs:49:9:51:9 | {...} | exception |
|
| Finally.cs:28:13:28:18 | throw ...; | Finally.cs:49:9:51:9 | {...} | exception |
|
||||||
| Finally.cs:30:9:40:9 | After catch (...) {...} [match] | Finally.cs:30:41:30:42 | ArgumentException ex | |
|
|
||||||
| Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] | Finally.cs:41:9:43:9 | catch (...) {...} | |
|
| Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] | Finally.cs:41:9:43:9 | catch (...) {...} | |
|
||||||
| Finally.cs:30:9:40:9 | catch (...) {...} | Finally.cs:30:9:40:9 | After catch (...) {...} [match] | match |
|
| Finally.cs:30:9:40:9 | catch (...) {...} | Finally.cs:30:41:30:42 | ArgumentException ex | |
|
||||||
| Finally.cs:30:9:40:9 | catch (...) {...} | Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] | no-match |
|
| Finally.cs:30:41:30:42 | After ArgumentException ex [match] | Finally.cs:31:9:40:9 | {...} | |
|
||||||
| Finally.cs:30:41:30:42 | ArgumentException ex | Finally.cs:31:9:40:9 | {...} | |
|
| Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] | Finally.cs:30:9:40:9 | After catch (...) {...} [no-match] | no-match |
|
||||||
|
| Finally.cs:30:41:30:42 | ArgumentException ex | Finally.cs:30:41:30:42 | After ArgumentException ex [match] | match |
|
||||||
|
| Finally.cs:30:41:30:42 | ArgumentException ex | Finally.cs:30:41:30:42 | After ArgumentException ex [no-match] | no-match |
|
||||||
| Finally.cs:31:9:40:9 | {...} | Finally.cs:32:13:39:13 | try {...} ... | |
|
| Finally.cs:31:9:40:9 | {...} | Finally.cs:32:13:39:13 | try {...} ... | |
|
||||||
| Finally.cs:32:13:39:13 | try {...} ... | Finally.cs:33:13:35:13 | {...} | |
|
| Finally.cs:32:13:39:13 | try {...} ... | Finally.cs:33:13:35:13 | {...} | |
|
||||||
| Finally.cs:33:13:35:13 | {...} | Finally.cs:34:17:34:32 | if (...) ... | |
|
| Finally.cs:33:13:35:13 | {...} | Finally.cs:34:17:34:32 | if (...) ... | |
|
||||||
@@ -3423,13 +3429,14 @@
|
|||||||
| Finally.cs:38:23:38:43 | Before object creation of type Exception | Finally.cs:38:37:38:42 | "Boo!" | |
|
| Finally.cs:38:23:38:43 | Before object creation of type Exception | Finally.cs:38:37:38:42 | "Boo!" | |
|
||||||
| Finally.cs:38:23:38:43 | object creation of type Exception | Finally.cs:38:23:38:43 | After object creation of type Exception | |
|
| Finally.cs:38:23:38:43 | object creation of type Exception | Finally.cs:38:23:38:43 | After object creation of type Exception | |
|
||||||
| Finally.cs:38:37:38:42 | "Boo!" | Finally.cs:38:23:38:43 | object creation of type Exception | |
|
| Finally.cs:38:37:38:42 | "Boo!" | Finally.cs:38:23:38:43 | object creation of type Exception | |
|
||||||
| Finally.cs:41:9:43:9 | After catch (...) {...} [match] | Finally.cs:42:9:43:9 | {...} | |
|
|
||||||
| Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] | Finally.cs:44:9:47:9 | catch {...} | |
|
| Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] | Finally.cs:44:9:47:9 | catch {...} | |
|
||||||
| Finally.cs:41:9:43:9 | catch (...) {...} | Finally.cs:41:9:43:9 | After catch (...) {...} [match] | match |
|
| Finally.cs:41:9:43:9 | catch (...) {...} | Finally.cs:41:16:41:24 | access to type Exception | |
|
||||||
| Finally.cs:41:9:43:9 | catch (...) {...} | Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] | no-match |
|
| Finally.cs:41:16:41:24 | After access to type Exception [match] | Finally.cs:42:9:43:9 | {...} | |
|
||||||
|
| Finally.cs:41:16:41:24 | After access to type Exception [no-match] | Finally.cs:41:9:43:9 | After catch (...) {...} [no-match] | no-match |
|
||||||
|
| Finally.cs:41:16:41:24 | access to type Exception | Finally.cs:41:16:41:24 | After access to type Exception [match] | match |
|
||||||
|
| Finally.cs:41:16:41:24 | access to type Exception | Finally.cs:41:16:41:24 | After access to type Exception [no-match] | no-match |
|
||||||
| Finally.cs:42:9:43:9 | {...} | Finally.cs:49:9:51:9 | {...} | |
|
| Finally.cs:42:9:43:9 | {...} | Finally.cs:49:9:51:9 | {...} | |
|
||||||
| Finally.cs:44:9:47:9 | After catch {...} [match] | Finally.cs:45:9:47:9 | {...} | |
|
| Finally.cs:44:9:47:9 | catch {...} | Finally.cs:45:9:47:9 | {...} | |
|
||||||
| Finally.cs:44:9:47:9 | catch {...} | Finally.cs:44:9:47:9 | After catch {...} [match] | match |
|
|
||||||
| Finally.cs:45:9:47:9 | {...} | Finally.cs:46:13:46:19 | Before return ...; | |
|
| Finally.cs:45:9:47:9 | {...} | Finally.cs:46:13:46:19 | Before return ...; | |
|
||||||
| Finally.cs:46:13:46:19 | Before return ...; | Finally.cs:46:13:46:19 | return ...; | |
|
| Finally.cs:46:13:46:19 | Before return ...; | Finally.cs:46:13:46:19 | return ...; | |
|
||||||
| Finally.cs:46:13:46:19 | return ...; | Finally.cs:49:9:51:9 | {...} | return |
|
| Finally.cs:46:13:46:19 | return ...; | Finally.cs:49:9:51:9 | {...} | return |
|
||||||
@@ -3460,21 +3467,23 @@
|
|||||||
| Finally.cs:58:31:58:36 | "Try3" | Finally.cs:58:13:58:37 | call to method WriteLine | |
|
| Finally.cs:58:31:58:36 | "Try3" | Finally.cs:58:13:58:37 | call to method WriteLine | |
|
||||||
| Finally.cs:59:13:59:19 | Before return ...; | Finally.cs:59:13:59:19 | return ...; | |
|
| Finally.cs:59:13:59:19 | Before return ...; | Finally.cs:59:13:59:19 | return ...; | |
|
||||||
| Finally.cs:59:13:59:19 | return ...; | Finally.cs:69:9:71:9 | {...} | return |
|
| Finally.cs:59:13:59:19 | return ...; | Finally.cs:69:9:71:9 | {...} | return |
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [match] | Finally.cs:61:38:61:39 | IOException ex | |
|
|
||||||
| Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | Finally.cs:65:9:67:9 | catch (...) {...} | |
|
| Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | Finally.cs:65:9:67:9 | catch (...) {...} | |
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:9:64:9 | After catch (...) {...} [match] | match |
|
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:38:61:39 | IOException ex | |
|
||||||
| Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | no-match |
|
| Finally.cs:61:38:61:39 | After IOException ex [match] | Finally.cs:61:48:61:51 | true | |
|
||||||
| Finally.cs:61:38:61:39 | IOException ex | Finally.cs:61:48:61:51 | true | |
|
| Finally.cs:61:38:61:39 | After IOException ex [no-match] | Finally.cs:61:9:64:9 | After catch (...) {...} [no-match] | no-match |
|
||||||
|
| Finally.cs:61:38:61:39 | IOException ex | Finally.cs:61:38:61:39 | After IOException ex [match] | match |
|
||||||
|
| Finally.cs:61:38:61:39 | IOException ex | Finally.cs:61:38:61:39 | After IOException ex [no-match] | no-match |
|
||||||
| Finally.cs:61:48:61:51 | After true [true] | Finally.cs:62:9:64:9 | {...} | |
|
| Finally.cs:61:48:61:51 | After true [true] | Finally.cs:62:9:64:9 | {...} | |
|
||||||
| Finally.cs:61:48:61:51 | true | Finally.cs:61:48:61:51 | After true [true] | true |
|
| Finally.cs:61:48:61:51 | true | Finally.cs:61:48:61:51 | After true [true] | true |
|
||||||
| Finally.cs:62:9:64:9 | {...} | Finally.cs:63:13:63:18 | Before throw ...; | |
|
| Finally.cs:62:9:64:9 | {...} | Finally.cs:63:13:63:18 | Before throw ...; | |
|
||||||
| Finally.cs:63:13:63:18 | Before throw ...; | Finally.cs:63:13:63:18 | throw ...; | |
|
| Finally.cs:63:13:63:18 | Before throw ...; | Finally.cs:63:13:63:18 | throw ...; | |
|
||||||
| Finally.cs:63:13:63:18 | throw ...; | Finally.cs:69:9:71:9 | {...} | exception |
|
| Finally.cs:63:13:63:18 | throw ...; | Finally.cs:69:9:71:9 | {...} | exception |
|
||||||
| Finally.cs:65:9:67:9 | After catch (...) {...} [match] | Finally.cs:65:26:65:26 | Exception e | |
|
|
||||||
| Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | Finally.cs:69:9:71:9 | {...} | exception |
|
| Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | Finally.cs:69:9:71:9 | {...} | exception |
|
||||||
| Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:65:9:67:9 | After catch (...) {...} [match] | match |
|
| Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:65:26:65:26 | Exception e | |
|
||||||
| Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | no-match |
|
| Finally.cs:65:26:65:26 | After Exception e [match] | Finally.cs:65:35:65:51 | Before ... != ... | |
|
||||||
| Finally.cs:65:26:65:26 | Exception e | Finally.cs:65:35:65:51 | Before ... != ... | |
|
| Finally.cs:65:26:65:26 | After Exception e [no-match] | Finally.cs:65:9:67:9 | After catch (...) {...} [no-match] | no-match |
|
||||||
|
| Finally.cs:65:26:65:26 | Exception e | Finally.cs:65:26:65:26 | After Exception e [match] | match |
|
||||||
|
| Finally.cs:65:26:65:26 | Exception e | Finally.cs:65:26:65:26 | After Exception e [no-match] | no-match |
|
||||||
| Finally.cs:65:35:65:35 | access to local variable e | Finally.cs:65:35:65:43 | access to property Message | |
|
| Finally.cs:65:35:65:35 | access to local variable e | Finally.cs:65:35:65:43 | access to property Message | |
|
||||||
| Finally.cs:65:35:65:43 | After access to property Message | Finally.cs:65:48:65:51 | null | |
|
| Finally.cs:65:35:65:43 | After access to property Message | Finally.cs:65:48:65:51 | null | |
|
||||||
| Finally.cs:65:35:65:43 | Before access to property Message | Finally.cs:65:35:65:35 | access to local variable e | |
|
| Finally.cs:65:35:65:43 | Before access to property Message | Finally.cs:65:35:65:35 | access to local variable e | |
|
||||||
@@ -3787,11 +3796,12 @@
|
|||||||
| Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:159:27:159:44 | After object creation of type Exception | |
|
| Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:159:27:159:44 | After object creation of type Exception | |
|
||||||
| Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:161:13:164:13 | catch (...) {...} | exception |
|
| Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:161:13:164:13 | catch (...) {...} | exception |
|
||||||
| Finally.cs:159:41:159:43 | "1" | Finally.cs:159:27:159:44 | object creation of type Exception | |
|
| Finally.cs:159:41:159:43 | "1" | Finally.cs:159:27:159:44 | object creation of type Exception | |
|
||||||
| Finally.cs:161:13:164:13 | After catch (...) {...} [match] | Finally.cs:161:30:161:30 | Exception e | |
|
|
||||||
| Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | Finally.cs:165:13:168:13 | catch {...} | |
|
| Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | Finally.cs:165:13:168:13 | catch {...} | |
|
||||||
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:13:164:13 | After catch (...) {...} [match] | match |
|
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:30:161:30 | Exception e | |
|
||||||
| Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | no-match |
|
| Finally.cs:161:30:161:30 | After Exception e [match] | Finally.cs:161:39:161:54 | Before ... == ... | |
|
||||||
| Finally.cs:161:30:161:30 | Exception e | Finally.cs:161:39:161:54 | Before ... == ... | |
|
| Finally.cs:161:30:161:30 | After Exception e [no-match] | Finally.cs:161:13:164:13 | After catch (...) {...} [no-match] | no-match |
|
||||||
|
| Finally.cs:161:30:161:30 | Exception e | Finally.cs:161:30:161:30 | After Exception e [match] | match |
|
||||||
|
| Finally.cs:161:30:161:30 | Exception e | Finally.cs:161:30:161:30 | After Exception e [no-match] | no-match |
|
||||||
| Finally.cs:161:39:161:39 | access to local variable e | Finally.cs:161:39:161:47 | access to property Message | |
|
| Finally.cs:161:39:161:39 | access to local variable e | Finally.cs:161:39:161:47 | access to property Message | |
|
||||||
| Finally.cs:161:39:161:47 | After access to property Message | Finally.cs:161:52:161:54 | "1" | |
|
| Finally.cs:161:39:161:47 | After access to property Message | Finally.cs:161:52:161:54 | "1" | |
|
||||||
| Finally.cs:161:39:161:47 | Before access to property Message | Finally.cs:161:39:161:39 | access to local variable e | |
|
| Finally.cs:161:39:161:47 | Before access to property Message | Finally.cs:161:39:161:39 | access to local variable e | |
|
||||||
@@ -3814,8 +3824,7 @@
|
|||||||
| Finally.cs:163:35:163:41 | Before access to array element | Finally.cs:163:35:163:38 | access to parameter args | |
|
| Finally.cs:163:35:163:41 | Before access to array element | Finally.cs:163:35:163:38 | access to parameter args | |
|
||||||
| Finally.cs:163:35:163:41 | access to array element | Finally.cs:163:35:163:41 | After access to array element | |
|
| Finally.cs:163:35:163:41 | access to array element | Finally.cs:163:35:163:41 | After access to array element | |
|
||||||
| Finally.cs:163:40:163:40 | 0 | Finally.cs:163:35:163:41 | access to array element | |
|
| Finally.cs:163:40:163:40 | 0 | Finally.cs:163:35:163:41 | access to array element | |
|
||||||
| Finally.cs:165:13:168:13 | After catch {...} [match] | Finally.cs:166:13:168:13 | {...} | |
|
| Finally.cs:165:13:168:13 | catch {...} | Finally.cs:166:13:168:13 | {...} | |
|
||||||
| Finally.cs:165:13:168:13 | catch {...} | Finally.cs:165:13:168:13 | After catch {...} [match] | match |
|
|
||||||
| Finally.cs:166:13:168:13 | After {...} | Finally.cs:156:13:168:13 | After try {...} ... | |
|
| Finally.cs:166:13:168:13 | After {...} | Finally.cs:156:13:168:13 | After try {...} ... | |
|
||||||
| Finally.cs:166:13:168:13 | {...} | Finally.cs:167:17:167:38 | ...; | |
|
| Finally.cs:166:13:168:13 | {...} | Finally.cs:167:17:167:38 | ...; | |
|
||||||
| Finally.cs:167:17:167:37 | After call to method WriteLine | Finally.cs:167:17:167:38 | After ...; | |
|
| Finally.cs:167:17:167:37 | After call to method WriteLine | Finally.cs:167:17:167:38 | After ...; | |
|
||||||
@@ -3896,10 +3905,12 @@
|
|||||||
| Finally.cs:186:31:186:46 | Before object creation of type ExceptionB | Finally.cs:186:31:186:46 | object creation of type ExceptionB | |
|
| Finally.cs:186:31:186:46 | Before object creation of type ExceptionB | Finally.cs:186:31:186:46 | object creation of type ExceptionB | |
|
||||||
| Finally.cs:186:31:186:46 | object creation of type ExceptionB | Finally.cs:186:31:186:46 | After object creation of type ExceptionB | |
|
| Finally.cs:186:31:186:46 | object creation of type ExceptionB | Finally.cs:186:31:186:46 | After object creation of type ExceptionB | |
|
||||||
| Finally.cs:186:31:186:46 | object creation of type ExceptionB | Finally.cs:188:13:191:13 | catch (...) {...} | exception |
|
| Finally.cs:186:31:186:46 | object creation of type ExceptionB | Finally.cs:188:13:191:13 | catch (...) {...} | exception |
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [match] | Finally.cs:188:38:188:39 | access to parameter b2 | |
|
|
||||||
| Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] | Finally.cs:176:10:176:11 | Exceptional Exit | exception |
|
| Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] | Finally.cs:176:10:176:11 | Exceptional Exit | exception |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:13:191:13 | After catch (...) {...} [match] | match |
|
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:20:188:29 | access to type ExceptionB | |
|
||||||
| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] | no-match |
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | Finally.cs:188:38:188:39 | access to parameter b2 | |
|
||||||
|
| Finally.cs:188:20:188:29 | After access to type ExceptionB [no-match] | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] | no-match |
|
||||||
|
| Finally.cs:188:20:188:29 | access to type ExceptionB | Finally.cs:188:20:188:29 | After access to type ExceptionB [match] | match |
|
||||||
|
| Finally.cs:188:20:188:29 | access to type ExceptionB | Finally.cs:188:20:188:29 | After access to type ExceptionB [no-match] | no-match |
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [false] | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] | no-match |
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [false] | Finally.cs:188:13:191:13 | After catch (...) {...} [no-match] | no-match |
|
||||||
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:189:13:191:13 | {...} | |
|
| Finally.cs:188:38:188:39 | After access to parameter b2 [true] | Finally.cs:189:13:191:13 | {...} | |
|
||||||
| Finally.cs:188:38:188:39 | access to parameter b2 | Finally.cs:188:38:188:39 | After access to parameter b2 [false] | false |
|
| Finally.cs:188:38:188:39 | access to parameter b2 | Finally.cs:188:38:188:39 | After access to parameter b2 [false] | false |
|
||||||
@@ -4009,8 +4020,7 @@
|
|||||||
| Finally.cs:220:13:220:37 | ...; | Finally.cs:220:13:220:36 | Before call to method WriteLine | |
|
| Finally.cs:220:13:220:37 | ...; | Finally.cs:220:13:220:36 | Before call to method WriteLine | |
|
||||||
| Finally.cs:220:13:220:37 | After ...; | Finally.cs:219:9:221:9 | After {...} | |
|
| Finally.cs:220:13:220:37 | After ...; | Finally.cs:219:9:221:9 | After {...} | |
|
||||||
| Finally.cs:220:31:220:35 | "Try" | Finally.cs:220:13:220:36 | call to method WriteLine | |
|
| Finally.cs:220:31:220:35 | "Try" | Finally.cs:220:13:220:36 | call to method WriteLine | |
|
||||||
| Finally.cs:222:9:225:9 | After catch {...} [match] | Finally.cs:223:9:225:9 | {...} | |
|
| Finally.cs:222:9:225:9 | catch {...} | Finally.cs:223:9:225:9 | {...} | |
|
||||||
| Finally.cs:222:9:225:9 | catch {...} | Finally.cs:222:9:225:9 | After catch {...} [match] | match |
|
|
||||||
| Finally.cs:223:9:225:9 | After {...} | Finally.cs:227:9:229:9 | {...} | |
|
| Finally.cs:223:9:225:9 | After {...} | Finally.cs:227:9:229:9 | {...} | |
|
||||||
| Finally.cs:223:9:225:9 | {...} | Finally.cs:224:13:224:39 | ...; | |
|
| Finally.cs:223:9:225:9 | {...} | Finally.cs:224:13:224:39 | ...; | |
|
||||||
| Finally.cs:224:13:224:38 | After call to method WriteLine | Finally.cs:224:13:224:39 | After ...; | |
|
| Finally.cs:224:13:224:38 | After call to method WriteLine | Finally.cs:224:13:224:39 | After ...; | |
|
||||||
|
|||||||
@@ -101,7 +101,8 @@ csharp6.cs:
|
|||||||
# 32| 0: [IntLiteral] 2
|
# 32| 0: [IntLiteral] 2
|
||||||
# 32| 0: [IntLiteral] 1
|
# 32| 0: [IntLiteral] 1
|
||||||
# 34| 1: [SpecificCatchClause] catch (...) {...}
|
# 34| 1: [SpecificCatchClause] catch (...) {...}
|
||||||
# 34| 0: [TypeMention] IndexOutOfRangeException
|
# 34| 0: [TypeAccess] access to type IndexOutOfRangeException
|
||||||
|
# 34| 0: [TypeMention] IndexOutOfRangeException
|
||||||
# 35| 1: [BlockStmt] {...}
|
# 35| 1: [BlockStmt] {...}
|
||||||
# 34| 2: [EQExpr] ... == ...
|
# 34| 2: [EQExpr] ... == ...
|
||||||
# 34| 0: [PropertyCall] access to property Value
|
# 34| 0: [PropertyCall] access to property Value
|
||||||
|
|||||||
@@ -336,11 +336,12 @@
|
|||||||
| patterns.cs:142:26:142:34 | { ... } | patterns.cs:142:26:142:34 | After { ... } | semmle.label | successor |
|
| patterns.cs:142:26:142:34 | { ... } | patterns.cs:142:26:142:34 | After { ... } | semmle.label | successor |
|
||||||
| patterns.cs:142:31:142:32 | 10 | patterns.cs:142:26:142:34 | { ... } | semmle.label | successor |
|
| patterns.cs:142:31:142:32 | 10 | patterns.cs:142:26:142:34 | { ... } | semmle.label | successor |
|
||||||
| patterns.cs:142:41:142:41 | 6 | patterns.cs:136:17:143:13 | After ... switch { ... } | semmle.label | successor |
|
| patterns.cs:142:41:142:41 | 6 | patterns.cs:136:17:143:13 | After ... switch { ... } | semmle.label | successor |
|
||||||
| patterns.cs:145:9:148:9 | After catch (...) {...} [match] | patterns.cs:145:41:145:42 | InvalidOperationException ex | semmle.label | successor |
|
|
||||||
| patterns.cs:145:9:148:9 | After catch (...) {...} [no-match] | patterns.cs:123:10:123:21 | Exceptional Exit | semmle.label | exception |
|
| patterns.cs:145:9:148:9 | After catch (...) {...} [no-match] | patterns.cs:123:10:123:21 | Exceptional Exit | semmle.label | exception |
|
||||||
| patterns.cs:145:9:148:9 | catch (...) {...} | patterns.cs:145:9:148:9 | After catch (...) {...} [match] | semmle.label | match |
|
| patterns.cs:145:9:148:9 | catch (...) {...} | patterns.cs:145:41:145:42 | InvalidOperationException ex | semmle.label | successor |
|
||||||
| patterns.cs:145:9:148:9 | catch (...) {...} | patterns.cs:145:9:148:9 | After catch (...) {...} [no-match] | semmle.label | no-match |
|
| patterns.cs:145:41:145:42 | After InvalidOperationException ex [match] | patterns.cs:146:9:148:9 | {...} | semmle.label | successor |
|
||||||
| patterns.cs:145:41:145:42 | InvalidOperationException ex | patterns.cs:146:9:148:9 | {...} | semmle.label | successor |
|
| patterns.cs:145:41:145:42 | After InvalidOperationException ex [no-match] | patterns.cs:145:9:148:9 | After catch (...) {...} [no-match] | semmle.label | no-match |
|
||||||
|
| patterns.cs:145:41:145:42 | InvalidOperationException ex | patterns.cs:145:41:145:42 | After InvalidOperationException ex [match] | semmle.label | match |
|
||||||
|
| patterns.cs:145:41:145:42 | InvalidOperationException ex | patterns.cs:145:41:145:42 | After InvalidOperationException ex [no-match] | semmle.label | no-match |
|
||||||
| patterns.cs:146:9:148:9 | After {...} | patterns.cs:134:9:148:9 | After try {...} ... | semmle.label | successor |
|
| patterns.cs:146:9:148:9 | After {...} | patterns.cs:134:9:148:9 | After try {...} ... | semmle.label | successor |
|
||||||
| patterns.cs:146:9:148:9 | {...} | patterns.cs:147:13:147:51 | ...; | semmle.label | successor |
|
| patterns.cs:146:9:148:9 | {...} | patterns.cs:147:13:147:51 | ...; | semmle.label | successor |
|
||||||
| patterns.cs:147:13:147:50 | After call to method WriteLine | patterns.cs:147:13:147:51 | After ...; | semmle.label | successor |
|
| patterns.cs:147:13:147:50 | After call to method WriteLine | patterns.cs:147:13:147:51 | After ...; | semmle.label | successor |
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ func logSomething(entry *logrus.Entry) {
|
|||||||
entry.Traceln(text) // $ logger=text
|
entry.Traceln(text) // $ logger=text
|
||||||
}
|
}
|
||||||
|
|
||||||
func logrusCalls() {
|
func logrusCalls(selector int) {
|
||||||
err := errors.New("Error")
|
err := errors.New("Error")
|
||||||
var fields logrus.Fields = nil
|
var fields logrus.Fields = nil
|
||||||
var fn logrus.LogFunction = nil
|
var fn logrus.LogFunction = nil
|
||||||
@@ -27,11 +27,15 @@ func logrusCalls() {
|
|||||||
tmp = logrus.WithFields(fields) // $ logger=fields
|
tmp = logrus.WithFields(fields) // $ logger=fields
|
||||||
logSomething(tmp)
|
logSomething(tmp)
|
||||||
|
|
||||||
logrus.Error(text) // $ logger=text
|
logrus.Error(text) // $ logger=text
|
||||||
logrus.Fatalf(fmt, text) // $ logger=fmt logger=text
|
logrus.Infof(fmt, text) // $ logger=fmt logger=text
|
||||||
logrus.Panicln(text) // $ logger=text
|
if selector == 0 {
|
||||||
logrus.Infof(fmt, text) // $ logger=fmt logger=text
|
logrus.Fatalf(fmt, text) // $ logger=fmt logger=text
|
||||||
logrus.FatalFn(fn) // $ logger=fn
|
} else if selector == 1 {
|
||||||
|
logrus.Panicln(text) // $ logger=text
|
||||||
|
} else if selector == 2 {
|
||||||
|
logrus.FatalFn(fn) // $ logger=fn
|
||||||
|
}
|
||||||
|
|
||||||
// components corresponding to the format specifier "%T" are not considered vulnerable
|
// components corresponding to the format specifier "%T" are not considered vulnerable
|
||||||
logrus.Infof("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
logrus.Infof("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||||
|
|||||||
@@ -8,6 +8,6 @@ var v []byte
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
glogTest(len(v))
|
glogTest(len(v))
|
||||||
stdlib()
|
stdlib(len(v))
|
||||||
slogTest()
|
slogTest()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,37 +4,69 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func stdlib() {
|
func stdlib(selector int) {
|
||||||
var logger log.Logger
|
var logger log.Logger
|
||||||
logger.SetPrefix("prefix: ")
|
logger.SetPrefix("prefix: ")
|
||||||
logger.Fatal(text) // $ logger=text
|
switch selector {
|
||||||
logger.Fatalf(fmt, text) // $ logger=fmt logger=text
|
case 0:
|
||||||
logger.Fatalln(text) // $ logger=text
|
logger.Fatal(text) // $ logger=text
|
||||||
logger.Panic(text) // $ logger=text
|
case 1:
|
||||||
logger.Panicf(fmt, text) // $ logger=fmt logger=text
|
logger.Fatalf(fmt, text) // $ logger=fmt logger=text
|
||||||
logger.Panicln(text) // $ logger=text
|
case 2:
|
||||||
logger.Print(text) // $ logger=text
|
logger.Fatalln(text) // $ logger=text
|
||||||
logger.Printf(fmt, text) // $ logger=fmt logger=text
|
case 3:
|
||||||
logger.Println(text) // $ logger=text
|
logger.Panic(text) // $ logger=text
|
||||||
|
case 4:
|
||||||
|
logger.Panicf(fmt, text) // $ logger=fmt logger=text
|
||||||
|
case 5:
|
||||||
|
logger.Panicln(text) // $ logger=text
|
||||||
|
case 6:
|
||||||
|
logger.Print(text) // $ logger=text
|
||||||
|
case 7:
|
||||||
|
logger.Printf(fmt, text) // $ logger=fmt logger=text
|
||||||
|
case 8:
|
||||||
|
logger.Println(text) // $ logger=text
|
||||||
|
}
|
||||||
|
|
||||||
// components corresponding to the format specifier "%T" are not considered vulnerable
|
// components corresponding to the format specifier "%T" are not considered vulnerable
|
||||||
logger.Fatalf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
switch selector {
|
||||||
logger.Panicf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
case 9:
|
||||||
logger.Printf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
logger.Fatalf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||||
|
case 10:
|
||||||
|
logger.Panicf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||||
|
case 11:
|
||||||
|
logger.Printf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||||
|
}
|
||||||
|
|
||||||
log.SetPrefix("prefix: ")
|
log.SetPrefix("prefix: ")
|
||||||
log.Fatal(text) // $ logger=text
|
switch selector {
|
||||||
log.Fatalf(fmt, text) // $ logger=fmt logger=text
|
case 12:
|
||||||
log.Fatalln(text) // $ logger=text
|
log.Fatal(text) // $ logger=text
|
||||||
log.Panic(text) // $ logger=text
|
case 13:
|
||||||
log.Panicf(fmt, text) // $ logger=fmt logger=text
|
log.Fatalf(fmt, text) // $ logger=fmt logger=text
|
||||||
log.Panicln(text) // $ logger=text
|
case 14:
|
||||||
log.Print(text) // $ logger=text
|
log.Fatalln(text) // $ logger=text
|
||||||
log.Printf(fmt, text) // $ logger=fmt logger=text
|
case 15:
|
||||||
log.Println(text) // $ logger=text
|
log.Panic(text) // $ logger=text
|
||||||
|
case 16:
|
||||||
|
log.Panicf(fmt, text) // $ logger=fmt logger=text
|
||||||
|
case 17:
|
||||||
|
log.Panicln(text) // $ logger=text
|
||||||
|
case 18:
|
||||||
|
log.Print(text) // $ logger=text
|
||||||
|
case 19:
|
||||||
|
log.Printf(fmt, text) // $ logger=fmt logger=text
|
||||||
|
case 20:
|
||||||
|
log.Println(text) // $ logger=text
|
||||||
|
}
|
||||||
|
|
||||||
// components corresponding to the format specifier "%T" are not considered vulnerable
|
// components corresponding to the format specifier "%T" are not considered vulnerable
|
||||||
log.Fatalf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
switch selector {
|
||||||
log.Panicf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
case 21:
|
||||||
log.Printf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
log.Fatalf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||||
|
case 22:
|
||||||
|
log.Panicf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||||
|
case 23:
|
||||||
|
log.Printf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,265 @@
|
|||||||
| DuplicateSwitchCase.go:16:1:16:14 | function declaration | DuplicateSwitchCase.go:0:0:0:0 | exit |
|
| DuplicateSwitchCase.go:16:1:16:14 | function declaration | DuplicateSwitchCase.go:0:0:0:0 | exit |
|
||||||
| DuplicateSwitchCase.go:16:6:16:9 | skip | DuplicateSwitchCase.go:16:1:16:14 | function declaration |
|
| DuplicateSwitchCase.go:16:6:16:9 | skip | DuplicateSwitchCase.go:16:1:16:14 | function declaration |
|
||||||
| DuplicateSwitchCase.go:16:13:16:14 | skip | DuplicateSwitchCase.go:16:1:16:14 | exit |
|
| DuplicateSwitchCase.go:16:13:16:14 | skip | DuplicateSwitchCase.go:16:1:16:14 | exit |
|
||||||
|
| epilogues.go:0:0:0:0 | entry | epilogues.go:3:1:3:12 | skip |
|
||||||
|
| epilogues.go:3:1:3:12 | skip | epilogues.go:8:1:10:1 | skip |
|
||||||
|
| epilogues.go:8:1:10:1 | skip | epilogues.go:12:21:12:23 | skip |
|
||||||
|
| epilogues.go:12:1:14:1 | entry | epilogues.go:12:7:12:7 | argument corresponding to l |
|
||||||
|
| epilogues.go:12:1:14:1 | function declaration | epilogues.go:16:20:16:27 | skip |
|
||||||
|
| epilogues.go:12:7:12:7 | argument corresponding to l | epilogues.go:12:7:12:7 | initialization of l |
|
||||||
|
| epilogues.go:12:7:12:7 | initialization of l | epilogues.go:12:25:12:27 | argument corresponding to msg |
|
||||||
|
| epilogues.go:12:21:12:23 | skip | epilogues.go:12:1:14:1 | function declaration |
|
||||||
|
| epilogues.go:12:25:12:27 | argument corresponding to msg | epilogues.go:12:25:12:27 | initialization of msg |
|
||||||
|
| epilogues.go:12:25:12:27 | initialization of msg | epilogues.go:12:37:12:40 | argument corresponding to code |
|
||||||
|
| epilogues.go:12:37:12:40 | argument corresponding to code | epilogues.go:12:37:12:40 | initialization of code |
|
||||||
|
| epilogues.go:12:37:12:40 | initialization of code | epilogues.go:13:2:13:12 | selection of Println |
|
||||||
|
| epilogues.go:13:2:13:12 | selection of Println | epilogues.go:13:14:13:14 | l |
|
||||||
|
| epilogues.go:13:2:13:33 | call to Println | epilogues.go:12:1:14:1 | exit |
|
||||||
|
| epilogues.go:13:14:13:14 | implicit dereference | epilogues.go:12:1:14:1 | exit |
|
||||||
|
| epilogues.go:13:14:13:14 | implicit dereference | epilogues.go:13:14:13:21 | selection of prefix |
|
||||||
|
| epilogues.go:13:14:13:14 | l | epilogues.go:13:14:13:14 | implicit dereference |
|
||||||
|
| epilogues.go:13:14:13:21 | selection of prefix | epilogues.go:13:24:13:26 | msg |
|
||||||
|
| epilogues.go:13:24:13:26 | msg | epilogues.go:13:29:13:32 | code |
|
||||||
|
| epilogues.go:13:29:13:32 | code | epilogues.go:13:2:13:33 | call to Println |
|
||||||
|
| epilogues.go:16:1:18:1 | entry | epilogues.go:16:7:16:7 | argument corresponding to l |
|
||||||
|
| epilogues.go:16:1:18:1 | function declaration | epilogues.go:23:6:23:15 | skip |
|
||||||
|
| epilogues.go:16:7:16:7 | argument corresponding to l | epilogues.go:16:7:16:7 | initialization of l |
|
||||||
|
| epilogues.go:16:7:16:7 | initialization of l | epilogues.go:16:29:16:31 | argument corresponding to msg |
|
||||||
|
| epilogues.go:16:20:16:27 | skip | epilogues.go:16:1:18:1 | function declaration |
|
||||||
|
| epilogues.go:16:29:16:31 | argument corresponding to msg | epilogues.go:16:29:16:31 | initialization of msg |
|
||||||
|
| epilogues.go:16:29:16:31 | initialization of msg | epilogues.go:17:2:17:12 | selection of Println |
|
||||||
|
| epilogues.go:17:2:17:12 | selection of Println | epilogues.go:17:14:17:14 | l |
|
||||||
|
| epilogues.go:17:2:17:27 | call to Println | epilogues.go:16:1:18:1 | exit |
|
||||||
|
| epilogues.go:17:14:17:14 | l | epilogues.go:17:14:17:21 | selection of prefix |
|
||||||
|
| epilogues.go:17:14:17:21 | selection of prefix | epilogues.go:17:24:17:26 | msg |
|
||||||
|
| epilogues.go:17:24:17:26 | msg | epilogues.go:17:2:17:27 | call to Println |
|
||||||
|
| epilogues.go:23:1:27:1 | entry | epilogues.go:24:5:24:5 | skip |
|
||||||
|
| epilogues.go:23:1:27:1 | function declaration | epilogues.go:31:6:31:13 | skip |
|
||||||
|
| epilogues.go:23:6:23:15 | skip | epilogues.go:23:1:27:1 | function declaration |
|
||||||
|
| epilogues.go:24:5:24:5 | assignment to r | epilogues.go:24:21:24:21 | r |
|
||||||
|
| epilogues.go:24:5:24:5 | skip | epilogues.go:24:10:24:16 | recover |
|
||||||
|
| epilogues.go:24:10:24:16 | recover | epilogues.go:24:10:24:18 | call to recover |
|
||||||
|
| epilogues.go:24:10:24:18 | call to recover | epilogues.go:24:5:24:5 | assignment to r |
|
||||||
|
| epilogues.go:24:21:24:21 | r | epilogues.go:24:26:24:28 | nil |
|
||||||
|
| epilogues.go:24:21:24:28 | ...!=... | epilogues.go:23:1:27:1 | exit |
|
||||||
|
| epilogues.go:24:21:24:28 | ...!=... | epilogues.go:24:21:24:28 | ...!=... is false |
|
||||||
|
| epilogues.go:24:21:24:28 | ...!=... | epilogues.go:24:21:24:28 | ...!=... is true |
|
||||||
|
| epilogues.go:24:21:24:28 | ...!=... is false | epilogues.go:23:1:27:1 | exit |
|
||||||
|
| epilogues.go:24:21:24:28 | ...!=... is true | epilogues.go:25:3:25:13 | selection of Println |
|
||||||
|
| epilogues.go:24:26:24:28 | nil | epilogues.go:24:21:24:28 | ...!=... |
|
||||||
|
| epilogues.go:25:3:25:13 | selection of Println | epilogues.go:25:15:25:26 | "recovered:" |
|
||||||
|
| epilogues.go:25:3:25:30 | call to Println | epilogues.go:23:1:27:1 | exit |
|
||||||
|
| epilogues.go:25:15:25:26 | "recovered:" | epilogues.go:25:29:25:29 | r |
|
||||||
|
| epilogues.go:25:29:25:29 | r | epilogues.go:25:3:25:30 | call to Println |
|
||||||
|
| epilogues.go:31:1:33:1 | entry | epilogues.go:31:15:31:15 | argument corresponding to x |
|
||||||
|
| epilogues.go:31:1:33:1 | function declaration | epilogues.go:36:6:36:12 | skip |
|
||||||
|
| epilogues.go:31:6:31:13 | skip | epilogues.go:31:1:33:1 | function declaration |
|
||||||
|
| epilogues.go:31:15:31:15 | argument corresponding to x | epilogues.go:31:15:31:15 | initialization of x |
|
||||||
|
| epilogues.go:31:15:31:15 | initialization of x | epilogues.go:32:9:32:9 | x |
|
||||||
|
| epilogues.go:32:2:32:13 | return statement | epilogues.go:31:1:33:1 | exit |
|
||||||
|
| epilogues.go:32:9:32:9 | x | epilogues.go:32:13:32:13 | 2 |
|
||||||
|
| epilogues.go:32:9:32:13 | ...*... | epilogues.go:32:2:32:13 | return statement |
|
||||||
|
| epilogues.go:32:13:32:13 | 2 | epilogues.go:32:9:32:13 | ...*... |
|
||||||
|
| epilogues.go:36:1:38:1 | entry | epilogues.go:37:2:37:12 | selection of Println |
|
||||||
|
| epilogues.go:36:1:38:1 | function declaration | epilogues.go:42:6:42:18 | skip |
|
||||||
|
| epilogues.go:36:6:36:12 | skip | epilogues.go:36:1:38:1 | function declaration |
|
||||||
|
| epilogues.go:37:2:37:12 | selection of Println | epilogues.go:37:14:37:19 | "void" |
|
||||||
|
| epilogues.go:37:2:37:20 | call to Println | epilogues.go:36:1:38:1 | exit |
|
||||||
|
| epilogues.go:37:14:37:19 | "void" | epilogues.go:37:2:37:20 | call to Println |
|
||||||
|
| epilogues.go:42:1:48:1 | entry | epilogues.go:42:20:42:20 | argument corresponding to x |
|
||||||
|
| epilogues.go:42:1:48:1 | function declaration | epilogues.go:51:6:51:21 | skip |
|
||||||
|
| epilogues.go:42:6:42:18 | skip | epilogues.go:42:1:48:1 | function declaration |
|
||||||
|
| epilogues.go:42:20:42:20 | argument corresponding to x | epilogues.go:42:20:42:20 | initialization of x |
|
||||||
|
| epilogues.go:42:20:42:20 | initialization of x | epilogues.go:42:28:42:33 | zero value for result |
|
||||||
|
| epilogues.go:42:28:42:33 | implicit read of result | epilogues.go:42:40:42:42 | implicit read of err |
|
||||||
|
| epilogues.go:42:28:42:33 | initialization of result | epilogues.go:42:40:42:42 | zero value for err |
|
||||||
|
| epilogues.go:42:28:42:33 | zero value for result | epilogues.go:42:28:42:33 | initialization of result |
|
||||||
|
| epilogues.go:42:40:42:42 | implicit read of err | epilogues.go:42:1:48:1 | exit |
|
||||||
|
| epilogues.go:42:40:42:42 | initialization of err | epilogues.go:43:5:43:5 | x |
|
||||||
|
| epilogues.go:42:40:42:42 | zero value for err | epilogues.go:42:40:42:42 | initialization of err |
|
||||||
|
| epilogues.go:43:5:43:5 | x | epilogues.go:43:9:43:9 | 0 |
|
||||||
|
| epilogues.go:43:5:43:9 | ...<... | epilogues.go:43:5:43:9 | ...<... is false |
|
||||||
|
| epilogues.go:43:5:43:9 | ...<... | epilogues.go:43:5:43:9 | ...<... is true |
|
||||||
|
| epilogues.go:43:5:43:9 | ...<... is false | epilogues.go:47:9:47:9 | x |
|
||||||
|
| epilogues.go:43:5:43:9 | ...<... is true | epilogues.go:44:3:44:8 | skip |
|
||||||
|
| epilogues.go:43:9:43:9 | 0 | epilogues.go:43:5:43:9 | ...<... |
|
||||||
|
| epilogues.go:44:3:44:8 | assignment to result | epilogues.go:45:3:45:8 | return statement |
|
||||||
|
| epilogues.go:44:3:44:8 | skip | epilogues.go:44:13:44:13 | x |
|
||||||
|
| epilogues.go:44:12:44:13 | -... | epilogues.go:44:3:44:8 | assignment to result |
|
||||||
|
| epilogues.go:44:13:44:13 | x | epilogues.go:44:12:44:13 | -... |
|
||||||
|
| epilogues.go:45:3:45:8 | return statement | epilogues.go:42:28:42:33 | implicit read of result |
|
||||||
|
| epilogues.go:47:2:47:14 | return statement | epilogues.go:42:28:42:33 | implicit read of result |
|
||||||
|
| epilogues.go:47:9:47:9 | implicit write of result | epilogues.go:47:12:47:14 | nil |
|
||||||
|
| epilogues.go:47:9:47:9 | x | epilogues.go:47:9:47:9 | implicit write of result |
|
||||||
|
| epilogues.go:47:12:47:14 | implicit write of err | epilogues.go:47:2:47:14 | return statement |
|
||||||
|
| epilogues.go:47:12:47:14 | nil | epilogues.go:47:12:47:14 | implicit write of err |
|
||||||
|
| epilogues.go:51:1:54:1 | entry | epilogues.go:51:23:51:23 | argument corresponding to x |
|
||||||
|
| epilogues.go:51:1:54:1 | function declaration | epilogues.go:59:6:59:25 | skip |
|
||||||
|
| epilogues.go:51:6:51:21 | skip | epilogues.go:51:1:54:1 | function declaration |
|
||||||
|
| epilogues.go:51:23:51:23 | argument corresponding to x | epilogues.go:51:23:51:23 | initialization of x |
|
||||||
|
| epilogues.go:51:23:51:23 | initialization of x | epilogues.go:51:31:51:31 | zero value for n |
|
||||||
|
| epilogues.go:51:31:51:31 | implicit read of n | epilogues.go:51:1:54:1 | exit |
|
||||||
|
| epilogues.go:51:31:51:31 | initialization of n | epilogues.go:52:2:52:2 | skip |
|
||||||
|
| epilogues.go:51:31:51:31 | zero value for n | epilogues.go:51:31:51:31 | initialization of n |
|
||||||
|
| epilogues.go:52:2:52:2 | assignment to n | epilogues.go:53:2:53:7 | return statement |
|
||||||
|
| epilogues.go:52:2:52:2 | skip | epilogues.go:52:6:52:6 | x |
|
||||||
|
| epilogues.go:52:6:52:6 | x | epilogues.go:52:10:52:10 | 1 |
|
||||||
|
| epilogues.go:52:6:52:10 | ...+... | epilogues.go:52:2:52:2 | assignment to n |
|
||||||
|
| epilogues.go:52:10:52:10 | 1 | epilogues.go:52:6:52:10 | ...+... |
|
||||||
|
| epilogues.go:53:2:53:7 | return statement | epilogues.go:51:31:51:31 | implicit read of n |
|
||||||
|
| epilogues.go:59:1:62:1 | entry | epilogues.go:59:27:59:27 | argument corresponding to l |
|
||||||
|
| epilogues.go:59:1:62:1 | function declaration | epilogues.go:66:6:66:26 | skip |
|
||||||
|
| epilogues.go:59:6:59:25 | skip | epilogues.go:59:1:62:1 | function declaration |
|
||||||
|
| epilogues.go:59:27:59:27 | argument corresponding to l | epilogues.go:59:27:59:27 | initialization of l |
|
||||||
|
| epilogues.go:59:27:59:27 | initialization of l | epilogues.go:59:41:59:45 | argument corresponding to items |
|
||||||
|
| epilogues.go:59:41:59:45 | argument corresponding to items | epilogues.go:59:41:59:45 | initialization of items |
|
||||||
|
| epilogues.go:59:41:59:45 | initialization of items | epilogues.go:60:8:60:8 | l |
|
||||||
|
| epilogues.go:60:2:60:33 | defer statement | epilogues.go:61:2:61:12 | selection of Println |
|
||||||
|
| epilogues.go:60:8:60:8 | l | epilogues.go:60:8:60:12 | selection of log |
|
||||||
|
| epilogues.go:60:8:60:12 | selection of log | epilogues.go:60:14:60:20 | "count" |
|
||||||
|
| epilogues.go:60:8:60:33 | call to log | epilogues.go:59:1:62:1 | exit |
|
||||||
|
| epilogues.go:60:14:60:20 | "count" | epilogues.go:60:23:60:25 | len |
|
||||||
|
| epilogues.go:60:23:60:25 | len | epilogues.go:60:27:60:31 | items |
|
||||||
|
| epilogues.go:60:23:60:32 | call to len | epilogues.go:60:2:60:33 | defer statement |
|
||||||
|
| epilogues.go:60:27:60:31 | items | epilogues.go:60:23:60:32 | call to len |
|
||||||
|
| epilogues.go:61:2:61:12 | selection of Println | epilogues.go:61:14:61:25 | "processing" |
|
||||||
|
| epilogues.go:61:2:61:38 | call to Println | epilogues.go:60:8:60:33 | call to log |
|
||||||
|
| epilogues.go:61:14:61:25 | "processing" | epilogues.go:61:28:61:30 | len |
|
||||||
|
| epilogues.go:61:28:61:30 | len | epilogues.go:61:32:61:36 | items |
|
||||||
|
| epilogues.go:61:28:61:37 | call to len | epilogues.go:61:2:61:38 | call to Println |
|
||||||
|
| epilogues.go:61:32:61:36 | items | epilogues.go:61:28:61:37 | call to len |
|
||||||
|
| epilogues.go:66:1:71:1 | entry | epilogues.go:66:28:66:33 | argument corresponding to prefix |
|
||||||
|
| epilogues.go:66:1:71:1 | function declaration | epilogues.go:77:6:77:20 | skip |
|
||||||
|
| epilogues.go:66:6:66:26 | skip | epilogues.go:66:1:71:1 | function declaration |
|
||||||
|
| epilogues.go:66:28:66:33 | argument corresponding to prefix | epilogues.go:66:28:66:33 | initialization of prefix |
|
||||||
|
| epilogues.go:66:28:66:33 | initialization of prefix | epilogues.go:67:2:67:2 | skip |
|
||||||
|
| epilogues.go:67:2:67:2 | assignment to l | epilogues.go:68:8:68:8 | l |
|
||||||
|
| epilogues.go:67:2:67:2 | skip | epilogues.go:67:7:67:31 | struct literal |
|
||||||
|
| epilogues.go:67:7:67:31 | struct literal | epilogues.go:67:25:67:30 | prefix |
|
||||||
|
| epilogues.go:67:17:67:30 | init of key-value pair | epilogues.go:67:2:67:2 | assignment to l |
|
||||||
|
| epilogues.go:67:25:67:30 | prefix | epilogues.go:67:17:67:30 | init of key-value pair |
|
||||||
|
| epilogues.go:68:2:68:24 | defer statement | epilogues.go:69:10:69:10 | l |
|
||||||
|
| epilogues.go:68:8:68:8 | l | epilogues.go:68:8:68:17 | selection of logValue |
|
||||||
|
| epilogues.go:68:8:68:17 | selection of logValue | epilogues.go:68:19:68:23 | "bye" |
|
||||||
|
| epilogues.go:68:8:68:24 | call to logValue | epilogues.go:66:1:71:1 | exit |
|
||||||
|
| epilogues.go:68:19:68:23 | "bye" | epilogues.go:68:2:68:24 | defer statement |
|
||||||
|
| epilogues.go:69:2:69:25 | defer statement | epilogues.go:70:2:70:12 | selection of Println |
|
||||||
|
| epilogues.go:69:8:69:15 | selection of log | epilogues.go:69:17:69:21 | "ptr" |
|
||||||
|
| epilogues.go:69:8:69:25 | call to log | epilogues.go:68:8:68:24 | call to logValue |
|
||||||
|
| epilogues.go:69:9:69:10 | &... | epilogues.go:69:8:69:15 | selection of log |
|
||||||
|
| epilogues.go:69:10:69:10 | l | epilogues.go:69:9:69:10 | &... |
|
||||||
|
| epilogues.go:69:17:69:21 | "ptr" | epilogues.go:69:24:69:24 | 7 |
|
||||||
|
| epilogues.go:69:24:69:24 | 7 | epilogues.go:69:2:69:25 | defer statement |
|
||||||
|
| epilogues.go:70:2:70:12 | selection of Println | epilogues.go:70:14:70:19 | "body" |
|
||||||
|
| epilogues.go:70:2:70:20 | call to Println | epilogues.go:69:8:69:25 | call to log |
|
||||||
|
| epilogues.go:70:14:70:19 | "body" | epilogues.go:70:2:70:20 | call to Println |
|
||||||
|
| epilogues.go:77:1:82:1 | entry | epilogues.go:77:22:77:22 | argument corresponding to x |
|
||||||
|
| epilogues.go:77:1:82:1 | function declaration | epilogues.go:87:6:87:20 | skip |
|
||||||
|
| epilogues.go:77:6:77:20 | skip | epilogues.go:77:1:82:1 | function declaration |
|
||||||
|
| epilogues.go:77:22:77:22 | argument corresponding to x | epilogues.go:77:22:77:22 | initialization of x |
|
||||||
|
| epilogues.go:77:22:77:22 | initialization of x | epilogues.go:78:8:80:2 | function literal |
|
||||||
|
| epilogues.go:78:2:80:15 | defer statement | epilogues.go:81:2:81:12 | selection of Println |
|
||||||
|
| epilogues.go:78:8:80:2 | entry | epilogues.go:78:13:78:17 | argument corresponding to label |
|
||||||
|
| epilogues.go:78:8:80:2 | function literal | epilogues.go:80:4:80:9 | "done" |
|
||||||
|
| epilogues.go:78:8:80:15 | function call | epilogues.go:77:1:82:1 | exit |
|
||||||
|
| epilogues.go:78:13:78:17 | argument corresponding to label | epilogues.go:78:13:78:17 | initialization of label |
|
||||||
|
| epilogues.go:78:13:78:17 | initialization of label | epilogues.go:78:27:78:27 | argument corresponding to n |
|
||||||
|
| epilogues.go:78:27:78:27 | argument corresponding to n | epilogues.go:78:27:78:27 | initialization of n |
|
||||||
|
| epilogues.go:78:27:78:27 | initialization of n | epilogues.go:79:3:79:13 | selection of Println |
|
||||||
|
| epilogues.go:79:3:79:13 | selection of Println | epilogues.go:79:15:79:19 | label |
|
||||||
|
| epilogues.go:79:3:79:23 | call to Println | epilogues.go:78:8:80:2 | exit |
|
||||||
|
| epilogues.go:79:15:79:19 | label | epilogues.go:79:22:79:22 | n |
|
||||||
|
| epilogues.go:79:22:79:22 | n | epilogues.go:79:3:79:23 | call to Println |
|
||||||
|
| epilogues.go:80:4:80:9 | "done" | epilogues.go:80:12:80:12 | x |
|
||||||
|
| epilogues.go:80:12:80:12 | x | epilogues.go:80:14:80:14 | 1 |
|
||||||
|
| epilogues.go:80:12:80:14 | ...+... | epilogues.go:78:2:80:15 | defer statement |
|
||||||
|
| epilogues.go:80:14:80:14 | 1 | epilogues.go:80:12:80:14 | ...+... |
|
||||||
|
| epilogues.go:81:2:81:12 | selection of Println | epilogues.go:81:14:81:19 | "body" |
|
||||||
|
| epilogues.go:81:2:81:23 | call to Println | epilogues.go:78:8:80:15 | function call |
|
||||||
|
| epilogues.go:81:14:81:19 | "body" | epilogues.go:81:22:81:22 | x |
|
||||||
|
| epilogues.go:81:22:81:22 | x | epilogues.go:81:2:81:23 | call to Println |
|
||||||
|
| epilogues.go:87:1:98:1 | entry | epilogues.go:87:22:87:22 | argument corresponding to x |
|
||||||
|
| epilogues.go:87:1:98:1 | function declaration | epilogues.go:102:6:102:24 | skip |
|
||||||
|
| epilogues.go:87:6:87:20 | skip | epilogues.go:87:1:98:1 | function declaration |
|
||||||
|
| epilogues.go:87:22:87:22 | argument corresponding to x | epilogues.go:87:22:87:22 | initialization of x |
|
||||||
|
| epilogues.go:87:22:87:22 | initialization of x | epilogues.go:87:30:87:35 | zero value for result |
|
||||||
|
| epilogues.go:87:30:87:35 | implicit read of result | epilogues.go:87:1:98:1 | exit |
|
||||||
|
| epilogues.go:87:30:87:35 | initialization of result | epilogues.go:88:8:92:2 | function literal |
|
||||||
|
| epilogues.go:87:30:87:35 | zero value for result | epilogues.go:87:30:87:35 | initialization of result |
|
||||||
|
| epilogues.go:88:2:92:4 | defer statement | epilogues.go:93:5:93:5 | x |
|
||||||
|
| epilogues.go:88:8:92:2 | entry | epilogues.go:89:6:89:6 | skip |
|
||||||
|
| epilogues.go:88:8:92:2 | function literal | epilogues.go:88:2:92:4 | defer statement |
|
||||||
|
| epilogues.go:88:8:92:4 | function call | epilogues.go:87:1:98:1 | exit |
|
||||||
|
| epilogues.go:88:8:92:4 | function call | epilogues.go:87:30:87:35 | implicit read of result |
|
||||||
|
| epilogues.go:89:6:89:6 | assignment to r | epilogues.go:89:22:89:22 | r |
|
||||||
|
| epilogues.go:89:6:89:6 | skip | epilogues.go:89:11:89:17 | recover |
|
||||||
|
| epilogues.go:89:11:89:17 | recover | epilogues.go:89:11:89:19 | call to recover |
|
||||||
|
| epilogues.go:89:11:89:19 | call to recover | epilogues.go:89:6:89:6 | assignment to r |
|
||||||
|
| epilogues.go:89:22:89:22 | r | epilogues.go:89:27:89:29 | nil |
|
||||||
|
| epilogues.go:89:22:89:29 | ...!=... | epilogues.go:88:8:92:2 | exit |
|
||||||
|
| epilogues.go:89:22:89:29 | ...!=... | epilogues.go:89:22:89:29 | ...!=... is false |
|
||||||
|
| epilogues.go:89:22:89:29 | ...!=... | epilogues.go:89:22:89:29 | ...!=... is true |
|
||||||
|
| epilogues.go:89:22:89:29 | ...!=... is false | epilogues.go:88:8:92:2 | exit |
|
||||||
|
| epilogues.go:89:22:89:29 | ...!=... is true | epilogues.go:90:4:90:9 | skip |
|
||||||
|
| epilogues.go:89:27:89:29 | nil | epilogues.go:89:22:89:29 | ...!=... |
|
||||||
|
| epilogues.go:90:4:90:9 | assignment to result | epilogues.go:88:8:92:2 | exit |
|
||||||
|
| epilogues.go:90:4:90:9 | skip | epilogues.go:90:13:90:14 | -... |
|
||||||
|
| epilogues.go:90:13:90:14 | -... | epilogues.go:90:4:90:9 | assignment to result |
|
||||||
|
| epilogues.go:93:5:93:5 | x | epilogues.go:93:9:93:9 | 0 |
|
||||||
|
| epilogues.go:93:5:93:9 | ...<... | epilogues.go:93:5:93:9 | ...<... is false |
|
||||||
|
| epilogues.go:93:5:93:9 | ...<... | epilogues.go:93:5:93:9 | ...<... is true |
|
||||||
|
| epilogues.go:93:5:93:9 | ...<... is false | epilogues.go:96:2:96:7 | skip |
|
||||||
|
| epilogues.go:93:5:93:9 | ...<... is true | epilogues.go:94:3:94:7 | panic |
|
||||||
|
| epilogues.go:93:9:93:9 | 0 | epilogues.go:93:5:93:9 | ...<... |
|
||||||
|
| epilogues.go:94:3:94:7 | panic | epilogues.go:94:9:94:13 | "neg" |
|
||||||
|
| epilogues.go:94:3:94:14 | call to panic | epilogues.go:88:8:92:4 | function call |
|
||||||
|
| epilogues.go:94:9:94:13 | "neg" | epilogues.go:94:3:94:14 | call to panic |
|
||||||
|
| epilogues.go:96:2:96:7 | assignment to result | epilogues.go:97:9:97:14 | result |
|
||||||
|
| epilogues.go:96:2:96:7 | skip | epilogues.go:96:11:96:11 | x |
|
||||||
|
| epilogues.go:96:11:96:11 | x | epilogues.go:96:15:96:15 | x |
|
||||||
|
| epilogues.go:96:11:96:15 | ...*... | epilogues.go:96:2:96:7 | assignment to result |
|
||||||
|
| epilogues.go:96:15:96:15 | x | epilogues.go:96:11:96:15 | ...*... |
|
||||||
|
| epilogues.go:97:2:97:14 | return statement | epilogues.go:88:8:92:4 | function call |
|
||||||
|
| epilogues.go:97:9:97:14 | implicit write of result | epilogues.go:97:2:97:14 | return statement |
|
||||||
|
| epilogues.go:97:9:97:14 | result | epilogues.go:97:9:97:14 | implicit write of result |
|
||||||
|
| epilogues.go:102:1:110:1 | entry | epilogues.go:102:26:102:26 | argument corresponding to x |
|
||||||
|
| epilogues.go:102:1:110:1 | function declaration | epilogues.go:115:6:115:22 | skip |
|
||||||
|
| epilogues.go:102:6:102:24 | skip | epilogues.go:102:1:110:1 | function declaration |
|
||||||
|
| epilogues.go:102:26:102:26 | argument corresponding to x | epilogues.go:102:26:102:26 | initialization of x |
|
||||||
|
| epilogues.go:102:26:102:26 | initialization of x | epilogues.go:102:34:102:35 | zero value for ok |
|
||||||
|
| epilogues.go:102:34:102:35 | implicit read of ok | epilogues.go:102:43:102:43 | implicit read of n |
|
||||||
|
| epilogues.go:102:34:102:35 | initialization of ok | epilogues.go:102:43:102:43 | zero value for n |
|
||||||
|
| epilogues.go:102:34:102:35 | zero value for ok | epilogues.go:102:34:102:35 | initialization of ok |
|
||||||
|
| epilogues.go:102:43:102:43 | implicit read of n | epilogues.go:102:1:110:1 | exit |
|
||||||
|
| epilogues.go:102:43:102:43 | initialization of n | epilogues.go:103:8:103:17 | epiRecover |
|
||||||
|
| epilogues.go:102:43:102:43 | zero value for n | epilogues.go:102:43:102:43 | initialization of n |
|
||||||
|
| epilogues.go:103:2:103:19 | defer statement | epilogues.go:104:5:104:5 | x |
|
||||||
|
| epilogues.go:103:8:103:17 | epiRecover | epilogues.go:103:2:103:19 | defer statement |
|
||||||
|
| epilogues.go:103:8:103:19 | call to epiRecover | epilogues.go:102:1:110:1 | exit |
|
||||||
|
| epilogues.go:103:8:103:19 | call to epiRecover | epilogues.go:102:34:102:35 | implicit read of ok |
|
||||||
|
| epilogues.go:104:5:104:5 | x | epilogues.go:104:10:104:10 | 0 |
|
||||||
|
| epilogues.go:104:5:104:10 | ...==... | epilogues.go:104:5:104:10 | ...==... is false |
|
||||||
|
| epilogues.go:104:5:104:10 | ...==... | epilogues.go:104:5:104:10 | ...==... is true |
|
||||||
|
| epilogues.go:104:5:104:10 | ...==... is false | epilogues.go:107:2:107:2 | skip |
|
||||||
|
| epilogues.go:104:5:104:10 | ...==... is true | epilogues.go:105:3:105:8 | return statement |
|
||||||
|
| epilogues.go:104:10:104:10 | 0 | epilogues.go:104:5:104:10 | ...==... |
|
||||||
|
| epilogues.go:105:3:105:8 | return statement | epilogues.go:103:8:103:19 | call to epiRecover |
|
||||||
|
| epilogues.go:107:2:107:2 | assignment to n | epilogues.go:108:2:108:3 | skip |
|
||||||
|
| epilogues.go:107:2:107:2 | skip | epilogues.go:107:6:107:6 | x |
|
||||||
|
| epilogues.go:107:6:107:6 | x | epilogues.go:107:2:107:2 | assignment to n |
|
||||||
|
| epilogues.go:108:2:108:3 | assignment to ok | epilogues.go:109:2:109:7 | return statement |
|
||||||
|
| epilogues.go:108:2:108:3 | skip | epilogues.go:108:7:108:10 | true |
|
||||||
|
| epilogues.go:108:7:108:10 | true | epilogues.go:108:2:108:3 | assignment to ok |
|
||||||
|
| epilogues.go:109:2:109:7 | return statement | epilogues.go:103:8:103:19 | call to epiRecover |
|
||||||
|
| epilogues.go:115:1:118:1 | entry | epilogues.go:116:8:116:17 | epiRecover |
|
||||||
|
| epilogues.go:115:1:118:1 | function declaration | epilogues.go:0:0:0:0 | exit |
|
||||||
|
| epilogues.go:115:6:115:22 | skip | epilogues.go:115:1:118:1 | function declaration |
|
||||||
|
| epilogues.go:116:2:116:19 | defer statement | epilogues.go:117:2:117:6 | panic |
|
||||||
|
| epilogues.go:116:8:116:17 | epiRecover | epilogues.go:116:2:116:19 | defer statement |
|
||||||
|
| epilogues.go:116:8:116:19 | call to epiRecover | epilogues.go:115:1:118:1 | exit |
|
||||||
|
| epilogues.go:117:2:117:6 | panic | epilogues.go:117:8:117:13 | "boom" |
|
||||||
|
| epilogues.go:117:2:117:14 | call to panic | epilogues.go:116:8:116:19 | call to epiRecover |
|
||||||
|
| epilogues.go:117:8:117:13 | "boom" | epilogues.go:117:2:117:14 | call to panic |
|
||||||
| equalitytests.go:0:0:0:0 | entry | equalitytests.go:3:1:5:1 | skip |
|
| equalitytests.go:0:0:0:0 | entry | equalitytests.go:3:1:5:1 | skip |
|
||||||
| equalitytests.go:3:1:5:1 | skip | equalitytests.go:7:1:9:1 | skip |
|
| equalitytests.go:3:1:5:1 | skip | equalitytests.go:7:1:9:1 | skip |
|
||||||
| equalitytests.go:7:1:9:1 | skip | equalitytests.go:11:6:11:18 | skip |
|
| equalitytests.go:7:1:9:1 | skip | equalitytests.go:11:6:11:18 | skip |
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
| epilogues.go:115:6:115:22 | epiRecoverUnnamed | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.epiRecoverUnnamed |
|
||||||
| file://:0:0:0:0 | Exit | os.Exit |
|
| file://:0:0:0:0 | Exit | os.Exit |
|
||||||
| file://:0:0:0:0 | Fatal | log.Fatal |
|
| file://:0:0:0:0 | Fatal | log.Fatal |
|
||||||
| file://:0:0:0:0 | Fatal | log.Logger.Fatal |
|
| file://:0:0:0:0 | Fatal | log.Logger.Fatal |
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// epiLogger has methods with both pointer and value receivers, used to check
|
||||||
|
// that the receiver and arguments of a deferred call are evaluated at the
|
||||||
|
// `defer` statement rather than in the function epilogue.
|
||||||
|
type epiLogger struct {
|
||||||
|
prefix string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *epiLogger) log(msg string, code int) {
|
||||||
|
fmt.Println(l.prefix, msg, code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l epiLogger) logValue(msg string) {
|
||||||
|
fmt.Println(l.prefix, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// epiRecover recovers from a panic. It is used as a deferred function so we can
|
||||||
|
// check that control flow returns to the result-read nodes and the normal exit
|
||||||
|
// node after recovering.
|
||||||
|
func epiRecover() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
fmt.Println("recovered:", r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// epiPlain has no named result variable and a single `return` with a child
|
||||||
|
// expression.
|
||||||
|
func epiPlain(x int) int {
|
||||||
|
return x * 2
|
||||||
|
}
|
||||||
|
|
||||||
|
// epiVoid has no named result variable and no `return` statement at all.
|
||||||
|
func epiVoid() {
|
||||||
|
fmt.Println("void")
|
||||||
|
}
|
||||||
|
|
||||||
|
// epiNamedMixed has named result variables and a mix of a bare `return` (no
|
||||||
|
// child expressions) and a `return` with child expressions.
|
||||||
|
func epiNamedMixed(x int) (result int, err error) {
|
||||||
|
if x < 0 {
|
||||||
|
result = -x
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return x, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// epiNamedBareOnly has a named result variable and only a bare `return`.
|
||||||
|
func epiNamedBareOnly(x int) (n int) {
|
||||||
|
n = x + 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// epiDeferReceiverArgs has a deferred call with a (pointer) receiver and
|
||||||
|
// arguments that are expressions, so we can check the receiver `l` and the
|
||||||
|
// arguments `"count"` and `len(items)` are evaluated at the `defer` statement.
|
||||||
|
func epiDeferReceiverArgs(l *epiLogger, items []int) {
|
||||||
|
defer l.log("count", len(items))
|
||||||
|
fmt.Println("processing", len(items))
|
||||||
|
}
|
||||||
|
|
||||||
|
// epiDeferValueReceiver has deferred calls with a value receiver and an
|
||||||
|
// address-of receiver, both with arguments evaluated at the `defer` statement.
|
||||||
|
func epiDeferValueReceiver(prefix string) {
|
||||||
|
l := epiLogger{prefix: prefix}
|
||||||
|
defer l.logValue("bye")
|
||||||
|
defer (&l).log("ptr", 7)
|
||||||
|
fmt.Println("body")
|
||||||
|
}
|
||||||
|
|
||||||
|
// epiDeferFuncLit has a deferred function literal with parameters, so we can
|
||||||
|
// check that the arguments `"done"` and `x+1` are evaluated at the `defer`
|
||||||
|
// statement and that control flow enters the function literal body when it is
|
||||||
|
// invoked at the function epilogue.
|
||||||
|
func epiDeferFuncLit(x int) {
|
||||||
|
defer func(label string, n int) {
|
||||||
|
fmt.Println(label, n)
|
||||||
|
}("done", x+1)
|
||||||
|
fmt.Println("body", x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// epiRecoverNamed has a named result variable and a deferred closure containing
|
||||||
|
// `recover()`. After recovering on the panic path, control flow should return
|
||||||
|
// to the result-read nodes and the normal exit node.
|
||||||
|
func epiRecoverNamed(x int) (result int) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
result = -1
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if x < 0 {
|
||||||
|
panic("neg")
|
||||||
|
}
|
||||||
|
result = x * x
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// epiRecoverNamedBare has named result variables, a deferred function
|
||||||
|
// containing `recover()`, and only bare `return` statements.
|
||||||
|
func epiRecoverNamedBare(x int) (ok bool, n int) {
|
||||||
|
defer epiRecover()
|
||||||
|
if x == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n = x
|
||||||
|
ok = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// epiRecoverUnnamed has no named result variables and a deferred function
|
||||||
|
// containing `recover()`; after recovering, control flow should reach the
|
||||||
|
// normal exit node directly (there are no result-read nodes).
|
||||||
|
func epiRecoverUnnamed() {
|
||||||
|
defer epiRecover()
|
||||||
|
panic("boom")
|
||||||
|
}
|
||||||
@@ -138,7 +138,9 @@ private module Ast implements AstSig<Location> {
|
|||||||
final private class FinalCatchClause = J::CatchClause;
|
final private class FinalCatchClause = J::CatchClause;
|
||||||
|
|
||||||
class CatchClause extends FinalCatchClause {
|
class CatchClause extends FinalCatchClause {
|
||||||
AstNode getVariable() { result = super.getVariable() }
|
AstNode getPattern() { result = super.getVariable() }
|
||||||
|
|
||||||
|
AstNode getVariable() { none() }
|
||||||
|
|
||||||
Expr getCondition() { none() }
|
Expr getCondition() { none() }
|
||||||
|
|
||||||
|
|||||||
@@ -235,15 +235,16 @@
|
|||||||
| Test.kt:84:11:84:18 | After (...)... | 4 | Test.kt:85:3:85:10 | Before return ... |
|
| Test.kt:84:11:84:18 | After (...)... | 4 | Test.kt:85:3:85:10 | Before return ... |
|
||||||
| Test.kt:84:11:84:18 | After (...)... | 5 | Test.kt:85:10:85:10 | 1 |
|
| Test.kt:84:11:84:18 | After (...)... | 5 | Test.kt:85:10:85:10 | 1 |
|
||||||
| Test.kt:84:11:84:18 | After (...)... | 6 | Test.kt:85:3:85:10 | return ... |
|
| Test.kt:84:11:84:18 | After (...)... | 6 | Test.kt:85:3:85:10 | return ... |
|
||||||
| Test.kt:86:4:88:2 | After catch (...) [match] | 0 | Test.kt:86:4:88:2 | After catch (...) [match] |
|
|
||||||
| Test.kt:86:4:88:2 | After catch (...) [match] | 1 | Test.kt:86:11:86:31 | e |
|
|
||||||
| Test.kt:86:4:88:2 | After catch (...) [match] | 2 | Test.kt:86:34:88:2 | { ... } |
|
|
||||||
| Test.kt:86:4:88:2 | After catch (...) [match] | 3 | Test.kt:87:3:87:10 | Before return ... |
|
|
||||||
| Test.kt:86:4:88:2 | After catch (...) [match] | 4 | Test.kt:87:10:87:10 | 2 |
|
|
||||||
| Test.kt:86:4:88:2 | After catch (...) [match] | 5 | Test.kt:87:3:87:10 | return ... |
|
|
||||||
| Test.kt:86:4:88:2 | After catch (...) [no-match] | 0 | Test.kt:86:4:88:2 | After catch (...) [no-match] |
|
|
||||||
| Test.kt:86:4:88:2 | After catch (...) [no-match] | 1 | Test.kt:82:1:89:1 | Exceptional Exit |
|
|
||||||
| Test.kt:86:4:88:2 | catch (...) | 0 | Test.kt:86:4:88:2 | catch (...) |
|
| Test.kt:86:4:88:2 | catch (...) | 0 | Test.kt:86:4:88:2 | catch (...) |
|
||||||
|
| Test.kt:86:4:88:2 | catch (...) | 1 | Test.kt:86:11:86:31 | e |
|
||||||
|
| Test.kt:86:11:86:31 | After e [match] | 0 | Test.kt:86:11:86:31 | After e [match] |
|
||||||
|
| Test.kt:86:11:86:31 | After e [match] | 1 | Test.kt:86:34:88:2 | { ... } |
|
||||||
|
| Test.kt:86:11:86:31 | After e [match] | 2 | Test.kt:87:3:87:10 | Before return ... |
|
||||||
|
| Test.kt:86:11:86:31 | After e [match] | 3 | Test.kt:87:10:87:10 | 2 |
|
||||||
|
| Test.kt:86:11:86:31 | After e [match] | 4 | Test.kt:87:3:87:10 | return ... |
|
||||||
|
| Test.kt:86:11:86:31 | After e [no-match] | 0 | Test.kt:86:11:86:31 | After e [no-match] |
|
||||||
|
| Test.kt:86:11:86:31 | After e [no-match] | 1 | Test.kt:86:4:88:2 | After catch (...) [no-match] |
|
||||||
|
| Test.kt:86:11:86:31 | After e [no-match] | 2 | Test.kt:82:1:89:1 | Exceptional Exit |
|
||||||
| Test.kt:91:1:98:1 | Entry | 0 | Test.kt:91:1:98:1 | Entry |
|
| Test.kt:91:1:98:1 | Entry | 0 | Test.kt:91:1:98:1 | Entry |
|
||||||
| Test.kt:91:1:98:1 | Entry | 1 | Test.kt:91:22:98:1 | { ... } |
|
| Test.kt:91:1:98:1 | Entry | 1 | Test.kt:91:22:98:1 | { ... } |
|
||||||
| Test.kt:91:1:98:1 | Entry | 2 | Test.kt:92:2:97:2 | try ... |
|
| Test.kt:91:1:98:1 | Entry | 2 | Test.kt:92:2:97:2 | try ... |
|
||||||
@@ -262,15 +263,16 @@
|
|||||||
| Test.kt:93:12:93:13 | After ...!! | 4 | Test.kt:94:3:94:10 | Before return ... |
|
| Test.kt:93:12:93:13 | After ...!! | 4 | Test.kt:94:3:94:10 | Before return ... |
|
||||||
| Test.kt:93:12:93:13 | After ...!! | 5 | Test.kt:94:10:94:10 | 1 |
|
| Test.kt:93:12:93:13 | After ...!! | 5 | Test.kt:94:10:94:10 | 1 |
|
||||||
| Test.kt:93:12:93:13 | After ...!! | 6 | Test.kt:94:3:94:10 | return ... |
|
| Test.kt:93:12:93:13 | After ...!! | 6 | Test.kt:94:3:94:10 | return ... |
|
||||||
| Test.kt:95:4:97:2 | After catch (...) [match] | 0 | Test.kt:95:4:97:2 | After catch (...) [match] |
|
|
||||||
| Test.kt:95:4:97:2 | After catch (...) [match] | 1 | Test.kt:95:11:95:33 | e |
|
|
||||||
| Test.kt:95:4:97:2 | After catch (...) [match] | 2 | Test.kt:95:36:97:2 | { ... } |
|
|
||||||
| Test.kt:95:4:97:2 | After catch (...) [match] | 3 | Test.kt:96:3:96:10 | Before return ... |
|
|
||||||
| Test.kt:95:4:97:2 | After catch (...) [match] | 4 | Test.kt:96:10:96:10 | 2 |
|
|
||||||
| Test.kt:95:4:97:2 | After catch (...) [match] | 5 | Test.kt:96:3:96:10 | return ... |
|
|
||||||
| Test.kt:95:4:97:2 | After catch (...) [no-match] | 0 | Test.kt:95:4:97:2 | After catch (...) [no-match] |
|
|
||||||
| Test.kt:95:4:97:2 | After catch (...) [no-match] | 1 | Test.kt:91:1:98:1 | Exceptional Exit |
|
|
||||||
| Test.kt:95:4:97:2 | catch (...) | 0 | Test.kt:95:4:97:2 | catch (...) |
|
| Test.kt:95:4:97:2 | catch (...) | 0 | Test.kt:95:4:97:2 | catch (...) |
|
||||||
|
| Test.kt:95:4:97:2 | catch (...) | 1 | Test.kt:95:11:95:33 | e |
|
||||||
|
| Test.kt:95:11:95:33 | After e [match] | 0 | Test.kt:95:11:95:33 | After e [match] |
|
||||||
|
| Test.kt:95:11:95:33 | After e [match] | 1 | Test.kt:95:36:97:2 | { ... } |
|
||||||
|
| Test.kt:95:11:95:33 | After e [match] | 2 | Test.kt:96:3:96:10 | Before return ... |
|
||||||
|
| Test.kt:95:11:95:33 | After e [match] | 3 | Test.kt:96:10:96:10 | 2 |
|
||||||
|
| Test.kt:95:11:95:33 | After e [match] | 4 | Test.kt:96:3:96:10 | return ... |
|
||||||
|
| Test.kt:95:11:95:33 | After e [no-match] | 0 | Test.kt:95:11:95:33 | After e [no-match] |
|
||||||
|
| Test.kt:95:11:95:33 | After e [no-match] | 1 | Test.kt:95:4:97:2 | After catch (...) [no-match] |
|
||||||
|
| Test.kt:95:11:95:33 | After e [no-match] | 2 | Test.kt:91:1:98:1 | Exceptional Exit |
|
||||||
| Test.kt:100:1:110:1 | Entry | 0 | Test.kt:100:1:110:1 | Entry |
|
| Test.kt:100:1:110:1 | Entry | 0 | Test.kt:100:1:110:1 | Entry |
|
||||||
| Test.kt:100:1:110:1 | Entry | 1 | Test.kt:100:25:110:1 | { ... } |
|
| Test.kt:100:1:110:1 | Entry | 1 | Test.kt:100:25:110:1 | { ... } |
|
||||||
| Test.kt:100:1:110:1 | Entry | 2 | Test.kt:101:5:103:5 | <Expr>; |
|
| Test.kt:100:1:110:1 | Entry | 2 | Test.kt:101:5:103:5 | <Expr>; |
|
||||||
|
|||||||
@@ -32,17 +32,17 @@
|
|||||||
| Test.kt:82:21:89:1 | { ... } | Test.kt:82:1:89:1 | Normal Exit |
|
| Test.kt:82:21:89:1 | { ... } | Test.kt:82:1:89:1 | Normal Exit |
|
||||||
| Test.kt:82:21:89:1 | { ... } | Test.kt:84:7:84:7 | x |
|
| Test.kt:82:21:89:1 | { ... } | Test.kt:84:7:84:7 | x |
|
||||||
| Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) |
|
| Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) |
|
||||||
| Test.kt:82:21:89:1 | { ... } | Test.kt:86:11:86:31 | e |
|
| Test.kt:82:21:89:1 | { ... } | Test.kt:86:34:88:2 | { ... } |
|
||||||
| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Exceptional Exit |
|
| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Exceptional Exit |
|
||||||
| Test.kt:86:4:88:2 | catch (...) | Test.kt:86:11:86:31 | e |
|
| Test.kt:86:4:88:2 | catch (...) | Test.kt:86:34:88:2 | { ... } |
|
||||||
| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Exceptional Exit |
|
| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Exceptional Exit |
|
||||||
| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Exit |
|
| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Exit |
|
||||||
| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Normal Exit |
|
| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Normal Exit |
|
||||||
| Test.kt:91:22:98:1 | { ... } | Test.kt:93:7:93:7 | x |
|
| Test.kt:91:22:98:1 | { ... } | Test.kt:93:7:93:7 | x |
|
||||||
| Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) |
|
| Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) |
|
||||||
| Test.kt:91:22:98:1 | { ... } | Test.kt:95:11:95:33 | e |
|
| Test.kt:91:22:98:1 | { ... } | Test.kt:95:36:97:2 | { ... } |
|
||||||
| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Exceptional Exit |
|
| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Exceptional Exit |
|
||||||
| Test.kt:95:4:97:2 | catch (...) | Test.kt:95:11:95:33 | e |
|
| Test.kt:95:4:97:2 | catch (...) | Test.kt:95:36:97:2 | { ... } |
|
||||||
| Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | Exit |
|
| Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | Exit |
|
||||||
| Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | Normal Exit |
|
| Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | Normal Exit |
|
||||||
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y |
|
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y |
|
||||||
|
|||||||
@@ -20,16 +20,16 @@
|
|||||||
| Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) |
|
| Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) |
|
||||||
| Test.kt:84:7:84:7 | x | Test.kt:82:1:89:1 | Normal Exit |
|
| Test.kt:84:7:84:7 | x | Test.kt:82:1:89:1 | Normal Exit |
|
||||||
| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Exceptional Exit |
|
| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Exceptional Exit |
|
||||||
| Test.kt:86:4:88:2 | catch (...) | Test.kt:86:11:86:31 | e |
|
| Test.kt:86:4:88:2 | catch (...) | Test.kt:86:34:88:2 | { ... } |
|
||||||
| Test.kt:86:11:86:31 | e | Test.kt:82:1:89:1 | Normal Exit |
|
| Test.kt:86:34:88:2 | { ... } | Test.kt:82:1:89:1 | Normal Exit |
|
||||||
| Test.kt:91:1:98:1 | Exceptional Exit | Test.kt:91:1:98:1 | Exit |
|
| Test.kt:91:1:98:1 | Exceptional Exit | Test.kt:91:1:98:1 | Exit |
|
||||||
| Test.kt:91:1:98:1 | Normal Exit | Test.kt:91:1:98:1 | Exit |
|
| Test.kt:91:1:98:1 | Normal Exit | Test.kt:91:1:98:1 | Exit |
|
||||||
| Test.kt:91:22:98:1 | { ... } | Test.kt:93:7:93:7 | x |
|
| Test.kt:91:22:98:1 | { ... } | Test.kt:93:7:93:7 | x |
|
||||||
| Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) |
|
| Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) |
|
||||||
| Test.kt:93:7:93:7 | x | Test.kt:91:1:98:1 | Normal Exit |
|
| Test.kt:93:7:93:7 | x | Test.kt:91:1:98:1 | Normal Exit |
|
||||||
| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Exceptional Exit |
|
| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Exceptional Exit |
|
||||||
| Test.kt:95:4:97:2 | catch (...) | Test.kt:95:11:95:33 | e |
|
| Test.kt:95:4:97:2 | catch (...) | Test.kt:95:36:97:2 | { ... } |
|
||||||
| Test.kt:95:11:95:33 | e | Test.kt:91:1:98:1 | Normal Exit |
|
| Test.kt:95:36:97:2 | { ... } | Test.kt:91:1:98:1 | Normal Exit |
|
||||||
| Test.kt:100:1:110:1 | Normal Exit | Test.kt:100:1:110:1 | Exit |
|
| Test.kt:100:1:110:1 | Normal Exit | Test.kt:100:1:110:1 | Exit |
|
||||||
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:9:101:17 | After ... (value equals) ... [false] |
|
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:9:101:17 | After ... (value equals) ... [false] |
|
||||||
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y |
|
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y |
|
||||||
|
|||||||
@@ -136,8 +136,8 @@
|
|||||||
| Test.kt:84:11:84:18 | (...)... | CastExpr | Test.kt:86:4:88:2 | catch (...) | CatchClause |
|
| Test.kt:84:11:84:18 | (...)... | CastExpr | Test.kt:86:4:88:2 | catch (...) | CatchClause |
|
||||||
| Test.kt:85:3:85:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Normal Exit | Method |
|
| Test.kt:85:3:85:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Normal Exit | Method |
|
||||||
| Test.kt:85:10:85:10 | 1 | IntegerLiteral | Test.kt:85:3:85:10 | return ... | ReturnStmt |
|
| Test.kt:85:10:85:10 | 1 | IntegerLiteral | Test.kt:85:3:85:10 | return ... | ReturnStmt |
|
||||||
| Test.kt:86:4:88:2 | catch (...) | CatchClause | Test.kt:82:1:89:1 | Exceptional Exit | Method |
|
|
||||||
| Test.kt:86:4:88:2 | catch (...) | CatchClause | Test.kt:86:11:86:31 | e | LocalVariableDeclExpr |
|
| Test.kt:86:4:88:2 | catch (...) | CatchClause | Test.kt:86:11:86:31 | e | LocalVariableDeclExpr |
|
||||||
|
| Test.kt:86:11:86:31 | e | LocalVariableDeclExpr | Test.kt:82:1:89:1 | Exceptional Exit | Method |
|
||||||
| Test.kt:86:11:86:31 | e | LocalVariableDeclExpr | Test.kt:86:34:88:2 | { ... } | BlockStmt |
|
| Test.kt:86:11:86:31 | e | LocalVariableDeclExpr | Test.kt:86:34:88:2 | { ... } | BlockStmt |
|
||||||
| Test.kt:86:34:88:2 | { ... } | BlockStmt | Test.kt:87:10:87:10 | 2 | IntegerLiteral |
|
| Test.kt:86:34:88:2 | { ... } | BlockStmt | Test.kt:87:10:87:10 | 2 | IntegerLiteral |
|
||||||
| Test.kt:87:3:87:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Normal Exit | Method |
|
| Test.kt:87:3:87:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Normal Exit | Method |
|
||||||
@@ -155,8 +155,8 @@
|
|||||||
| Test.kt:93:12:93:13 | ...!! | NotNullExpr | Test.kt:95:4:97:2 | catch (...) | CatchClause |
|
| Test.kt:93:12:93:13 | ...!! | NotNullExpr | Test.kt:95:4:97:2 | catch (...) | CatchClause |
|
||||||
| Test.kt:94:3:94:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Normal Exit | Method |
|
| Test.kt:94:3:94:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Normal Exit | Method |
|
||||||
| Test.kt:94:10:94:10 | 1 | IntegerLiteral | Test.kt:94:3:94:10 | return ... | ReturnStmt |
|
| Test.kt:94:10:94:10 | 1 | IntegerLiteral | Test.kt:94:3:94:10 | return ... | ReturnStmt |
|
||||||
| Test.kt:95:4:97:2 | catch (...) | CatchClause | Test.kt:91:1:98:1 | Exceptional Exit | Method |
|
|
||||||
| Test.kt:95:4:97:2 | catch (...) | CatchClause | Test.kt:95:11:95:33 | e | LocalVariableDeclExpr |
|
| Test.kt:95:4:97:2 | catch (...) | CatchClause | Test.kt:95:11:95:33 | e | LocalVariableDeclExpr |
|
||||||
|
| Test.kt:95:11:95:33 | e | LocalVariableDeclExpr | Test.kt:91:1:98:1 | Exceptional Exit | Method |
|
||||||
| Test.kt:95:11:95:33 | e | LocalVariableDeclExpr | Test.kt:95:36:97:2 | { ... } | BlockStmt |
|
| Test.kt:95:11:95:33 | e | LocalVariableDeclExpr | Test.kt:95:36:97:2 | { ... } | BlockStmt |
|
||||||
| Test.kt:95:36:97:2 | { ... } | BlockStmt | Test.kt:96:10:96:10 | 2 | IntegerLiteral |
|
| Test.kt:95:36:97:2 | { ... } | BlockStmt | Test.kt:96:10:96:10 | 2 | IntegerLiteral |
|
||||||
| Test.kt:96:3:96:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Normal Exit | Method |
|
| Test.kt:96:3:96:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Normal Exit | Method |
|
||||||
|
|||||||
@@ -235,15 +235,16 @@
|
|||||||
| Test.kt:84:11:84:18 | After (...)... | 4 | Test.kt:85:3:85:10 | Before return ... |
|
| Test.kt:84:11:84:18 | After (...)... | 4 | Test.kt:85:3:85:10 | Before return ... |
|
||||||
| Test.kt:84:11:84:18 | After (...)... | 5 | Test.kt:85:10:85:10 | 1 |
|
| Test.kt:84:11:84:18 | After (...)... | 5 | Test.kt:85:10:85:10 | 1 |
|
||||||
| Test.kt:84:11:84:18 | After (...)... | 6 | Test.kt:85:3:85:10 | return ... |
|
| Test.kt:84:11:84:18 | After (...)... | 6 | Test.kt:85:3:85:10 | return ... |
|
||||||
| Test.kt:86:4:88:2 | After catch (...) [match] | 0 | Test.kt:86:4:88:2 | After catch (...) [match] |
|
|
||||||
| Test.kt:86:4:88:2 | After catch (...) [match] | 1 | Test.kt:86:11:86:31 | e |
|
|
||||||
| Test.kt:86:4:88:2 | After catch (...) [match] | 2 | Test.kt:86:34:88:2 | { ... } |
|
|
||||||
| Test.kt:86:4:88:2 | After catch (...) [match] | 3 | Test.kt:87:3:87:10 | Before return ... |
|
|
||||||
| Test.kt:86:4:88:2 | After catch (...) [match] | 4 | Test.kt:87:10:87:10 | 2 |
|
|
||||||
| Test.kt:86:4:88:2 | After catch (...) [match] | 5 | Test.kt:87:3:87:10 | return ... |
|
|
||||||
| Test.kt:86:4:88:2 | After catch (...) [no-match] | 0 | Test.kt:86:4:88:2 | After catch (...) [no-match] |
|
|
||||||
| Test.kt:86:4:88:2 | After catch (...) [no-match] | 1 | Test.kt:82:1:89:1 | Exceptional Exit |
|
|
||||||
| Test.kt:86:4:88:2 | catch (...) | 0 | Test.kt:86:4:88:2 | catch (...) |
|
| Test.kt:86:4:88:2 | catch (...) | 0 | Test.kt:86:4:88:2 | catch (...) |
|
||||||
|
| Test.kt:86:4:88:2 | catch (...) | 1 | Test.kt:86:11:86:31 | e |
|
||||||
|
| Test.kt:86:11:86:31 | After e [match] | 0 | Test.kt:86:11:86:31 | After e [match] |
|
||||||
|
| Test.kt:86:11:86:31 | After e [match] | 1 | Test.kt:86:34:88:2 | { ... } |
|
||||||
|
| Test.kt:86:11:86:31 | After e [match] | 2 | Test.kt:87:3:87:10 | Before return ... |
|
||||||
|
| Test.kt:86:11:86:31 | After e [match] | 3 | Test.kt:87:10:87:10 | 2 |
|
||||||
|
| Test.kt:86:11:86:31 | After e [match] | 4 | Test.kt:87:3:87:10 | return ... |
|
||||||
|
| Test.kt:86:11:86:31 | After e [no-match] | 0 | Test.kt:86:11:86:31 | After e [no-match] |
|
||||||
|
| Test.kt:86:11:86:31 | After e [no-match] | 1 | Test.kt:86:4:88:2 | After catch (...) [no-match] |
|
||||||
|
| Test.kt:86:11:86:31 | After e [no-match] | 2 | Test.kt:82:1:89:1 | Exceptional Exit |
|
||||||
| Test.kt:91:1:98:1 | Entry | 0 | Test.kt:91:1:98:1 | Entry |
|
| Test.kt:91:1:98:1 | Entry | 0 | Test.kt:91:1:98:1 | Entry |
|
||||||
| Test.kt:91:1:98:1 | Entry | 1 | Test.kt:91:22:98:1 | { ... } |
|
| Test.kt:91:1:98:1 | Entry | 1 | Test.kt:91:22:98:1 | { ... } |
|
||||||
| Test.kt:91:1:98:1 | Entry | 2 | Test.kt:92:2:97:2 | try ... |
|
| Test.kt:91:1:98:1 | Entry | 2 | Test.kt:92:2:97:2 | try ... |
|
||||||
@@ -262,15 +263,16 @@
|
|||||||
| Test.kt:93:11:93:13 | After ...!! | 4 | Test.kt:94:3:94:10 | Before return ... |
|
| Test.kt:93:11:93:13 | After ...!! | 4 | Test.kt:94:3:94:10 | Before return ... |
|
||||||
| Test.kt:93:11:93:13 | After ...!! | 5 | Test.kt:94:10:94:10 | 1 |
|
| Test.kt:93:11:93:13 | After ...!! | 5 | Test.kt:94:10:94:10 | 1 |
|
||||||
| Test.kt:93:11:93:13 | After ...!! | 6 | Test.kt:94:3:94:10 | return ... |
|
| Test.kt:93:11:93:13 | After ...!! | 6 | Test.kt:94:3:94:10 | return ... |
|
||||||
| Test.kt:95:4:97:2 | After catch (...) [match] | 0 | Test.kt:95:4:97:2 | After catch (...) [match] |
|
|
||||||
| Test.kt:95:4:97:2 | After catch (...) [match] | 1 | Test.kt:95:11:95:33 | e |
|
|
||||||
| Test.kt:95:4:97:2 | After catch (...) [match] | 2 | Test.kt:95:36:97:2 | { ... } |
|
|
||||||
| Test.kt:95:4:97:2 | After catch (...) [match] | 3 | Test.kt:96:3:96:10 | Before return ... |
|
|
||||||
| Test.kt:95:4:97:2 | After catch (...) [match] | 4 | Test.kt:96:10:96:10 | 2 |
|
|
||||||
| Test.kt:95:4:97:2 | After catch (...) [match] | 5 | Test.kt:96:3:96:10 | return ... |
|
|
||||||
| Test.kt:95:4:97:2 | After catch (...) [no-match] | 0 | Test.kt:95:4:97:2 | After catch (...) [no-match] |
|
|
||||||
| Test.kt:95:4:97:2 | After catch (...) [no-match] | 1 | Test.kt:91:1:98:1 | Exceptional Exit |
|
|
||||||
| Test.kt:95:4:97:2 | catch (...) | 0 | Test.kt:95:4:97:2 | catch (...) |
|
| Test.kt:95:4:97:2 | catch (...) | 0 | Test.kt:95:4:97:2 | catch (...) |
|
||||||
|
| Test.kt:95:4:97:2 | catch (...) | 1 | Test.kt:95:11:95:33 | e |
|
||||||
|
| Test.kt:95:11:95:33 | After e [match] | 0 | Test.kt:95:11:95:33 | After e [match] |
|
||||||
|
| Test.kt:95:11:95:33 | After e [match] | 1 | Test.kt:95:36:97:2 | { ... } |
|
||||||
|
| Test.kt:95:11:95:33 | After e [match] | 2 | Test.kt:96:3:96:10 | Before return ... |
|
||||||
|
| Test.kt:95:11:95:33 | After e [match] | 3 | Test.kt:96:10:96:10 | 2 |
|
||||||
|
| Test.kt:95:11:95:33 | After e [match] | 4 | Test.kt:96:3:96:10 | return ... |
|
||||||
|
| Test.kt:95:11:95:33 | After e [no-match] | 0 | Test.kt:95:11:95:33 | After e [no-match] |
|
||||||
|
| Test.kt:95:11:95:33 | After e [no-match] | 1 | Test.kt:95:4:97:2 | After catch (...) [no-match] |
|
||||||
|
| Test.kt:95:11:95:33 | After e [no-match] | 2 | Test.kt:91:1:98:1 | Exceptional Exit |
|
||||||
| Test.kt:100:1:110:1 | Entry | 0 | Test.kt:100:1:110:1 | Entry |
|
| Test.kt:100:1:110:1 | Entry | 0 | Test.kt:100:1:110:1 | Entry |
|
||||||
| Test.kt:100:1:110:1 | Entry | 1 | Test.kt:100:25:110:1 | { ... } |
|
| Test.kt:100:1:110:1 | Entry | 1 | Test.kt:100:25:110:1 | { ... } |
|
||||||
| Test.kt:100:1:110:1 | Entry | 2 | Test.kt:101:5:103:5 | <Expr>; |
|
| Test.kt:100:1:110:1 | Entry | 2 | Test.kt:101:5:103:5 | <Expr>; |
|
||||||
|
|||||||
@@ -32,17 +32,17 @@
|
|||||||
| Test.kt:82:21:89:1 | { ... } | Test.kt:82:1:89:1 | Normal Exit |
|
| Test.kt:82:21:89:1 | { ... } | Test.kt:82:1:89:1 | Normal Exit |
|
||||||
| Test.kt:82:21:89:1 | { ... } | Test.kt:84:3:84:18 | x |
|
| Test.kt:82:21:89:1 | { ... } | Test.kt:84:3:84:18 | x |
|
||||||
| Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) |
|
| Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) |
|
||||||
| Test.kt:82:21:89:1 | { ... } | Test.kt:86:11:86:31 | e |
|
| Test.kt:82:21:89:1 | { ... } | Test.kt:86:34:88:2 | { ... } |
|
||||||
| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Exceptional Exit |
|
| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Exceptional Exit |
|
||||||
| Test.kt:86:4:88:2 | catch (...) | Test.kt:86:11:86:31 | e |
|
| Test.kt:86:4:88:2 | catch (...) | Test.kt:86:34:88:2 | { ... } |
|
||||||
| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Exceptional Exit |
|
| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Exceptional Exit |
|
||||||
| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Exit |
|
| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Exit |
|
||||||
| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Normal Exit |
|
| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Normal Exit |
|
||||||
| Test.kt:91:22:98:1 | { ... } | Test.kt:93:3:93:13 | x |
|
| Test.kt:91:22:98:1 | { ... } | Test.kt:93:3:93:13 | x |
|
||||||
| Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) |
|
| Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) |
|
||||||
| Test.kt:91:22:98:1 | { ... } | Test.kt:95:11:95:33 | e |
|
| Test.kt:91:22:98:1 | { ... } | Test.kt:95:36:97:2 | { ... } |
|
||||||
| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Exceptional Exit |
|
| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Exceptional Exit |
|
||||||
| Test.kt:95:4:97:2 | catch (...) | Test.kt:95:11:95:33 | e |
|
| Test.kt:95:4:97:2 | catch (...) | Test.kt:95:36:97:2 | { ... } |
|
||||||
| Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | Exit |
|
| Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | Exit |
|
||||||
| Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | Normal Exit |
|
| Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | Normal Exit |
|
||||||
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y |
|
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y |
|
||||||
|
|||||||
@@ -20,16 +20,16 @@
|
|||||||
| Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) |
|
| Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) |
|
||||||
| Test.kt:84:3:84:18 | x | Test.kt:82:1:89:1 | Normal Exit |
|
| Test.kt:84:3:84:18 | x | Test.kt:82:1:89:1 | Normal Exit |
|
||||||
| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Exceptional Exit |
|
| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Exceptional Exit |
|
||||||
| Test.kt:86:4:88:2 | catch (...) | Test.kt:86:11:86:31 | e |
|
| Test.kt:86:4:88:2 | catch (...) | Test.kt:86:34:88:2 | { ... } |
|
||||||
| Test.kt:86:11:86:31 | e | Test.kt:82:1:89:1 | Normal Exit |
|
| Test.kt:86:34:88:2 | { ... } | Test.kt:82:1:89:1 | Normal Exit |
|
||||||
| Test.kt:91:1:98:1 | Exceptional Exit | Test.kt:91:1:98:1 | Exit |
|
| Test.kt:91:1:98:1 | Exceptional Exit | Test.kt:91:1:98:1 | Exit |
|
||||||
| Test.kt:91:1:98:1 | Normal Exit | Test.kt:91:1:98:1 | Exit |
|
| Test.kt:91:1:98:1 | Normal Exit | Test.kt:91:1:98:1 | Exit |
|
||||||
| Test.kt:91:22:98:1 | { ... } | Test.kt:93:3:93:13 | x |
|
| Test.kt:91:22:98:1 | { ... } | Test.kt:93:3:93:13 | x |
|
||||||
| Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) |
|
| Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) |
|
||||||
| Test.kt:93:3:93:13 | x | Test.kt:91:1:98:1 | Normal Exit |
|
| Test.kt:93:3:93:13 | x | Test.kt:91:1:98:1 | Normal Exit |
|
||||||
| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Exceptional Exit |
|
| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Exceptional Exit |
|
||||||
| Test.kt:95:4:97:2 | catch (...) | Test.kt:95:11:95:33 | e |
|
| Test.kt:95:4:97:2 | catch (...) | Test.kt:95:36:97:2 | { ... } |
|
||||||
| Test.kt:95:11:95:33 | e | Test.kt:91:1:98:1 | Normal Exit |
|
| Test.kt:95:36:97:2 | { ... } | Test.kt:91:1:98:1 | Normal Exit |
|
||||||
| Test.kt:100:1:110:1 | Normal Exit | Test.kt:100:1:110:1 | Exit |
|
| Test.kt:100:1:110:1 | Normal Exit | Test.kt:100:1:110:1 | Exit |
|
||||||
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:9:101:17 | After ... (value equals) ... [false] |
|
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:9:101:17 | After ... (value equals) ... [false] |
|
||||||
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y |
|
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y |
|
||||||
|
|||||||
@@ -136,8 +136,8 @@
|
|||||||
| Test.kt:84:11:84:18 | (...)... | CastExpr | Test.kt:86:4:88:2 | catch (...) | CatchClause |
|
| Test.kt:84:11:84:18 | (...)... | CastExpr | Test.kt:86:4:88:2 | catch (...) | CatchClause |
|
||||||
| Test.kt:85:3:85:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Normal Exit | Method |
|
| Test.kt:85:3:85:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Normal Exit | Method |
|
||||||
| Test.kt:85:10:85:10 | 1 | IntegerLiteral | Test.kt:85:3:85:10 | return ... | ReturnStmt |
|
| Test.kt:85:10:85:10 | 1 | IntegerLiteral | Test.kt:85:3:85:10 | return ... | ReturnStmt |
|
||||||
| Test.kt:86:4:88:2 | catch (...) | CatchClause | Test.kt:82:1:89:1 | Exceptional Exit | Method |
|
|
||||||
| Test.kt:86:4:88:2 | catch (...) | CatchClause | Test.kt:86:11:86:31 | e | LocalVariableDeclExpr |
|
| Test.kt:86:4:88:2 | catch (...) | CatchClause | Test.kt:86:11:86:31 | e | LocalVariableDeclExpr |
|
||||||
|
| Test.kt:86:11:86:31 | e | LocalVariableDeclExpr | Test.kt:82:1:89:1 | Exceptional Exit | Method |
|
||||||
| Test.kt:86:11:86:31 | e | LocalVariableDeclExpr | Test.kt:86:34:88:2 | { ... } | BlockStmt |
|
| Test.kt:86:11:86:31 | e | LocalVariableDeclExpr | Test.kt:86:34:88:2 | { ... } | BlockStmt |
|
||||||
| Test.kt:86:34:88:2 | { ... } | BlockStmt | Test.kt:87:10:87:10 | 2 | IntegerLiteral |
|
| Test.kt:86:34:88:2 | { ... } | BlockStmt | Test.kt:87:10:87:10 | 2 | IntegerLiteral |
|
||||||
| Test.kt:87:3:87:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Normal Exit | Method |
|
| Test.kt:87:3:87:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Normal Exit | Method |
|
||||||
@@ -155,8 +155,8 @@
|
|||||||
| Test.kt:93:11:93:13 | ...!! | NotNullExpr | Test.kt:95:4:97:2 | catch (...) | CatchClause |
|
| Test.kt:93:11:93:13 | ...!! | NotNullExpr | Test.kt:95:4:97:2 | catch (...) | CatchClause |
|
||||||
| Test.kt:94:3:94:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Normal Exit | Method |
|
| Test.kt:94:3:94:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Normal Exit | Method |
|
||||||
| Test.kt:94:10:94:10 | 1 | IntegerLiteral | Test.kt:94:3:94:10 | return ... | ReturnStmt |
|
| Test.kt:94:10:94:10 | 1 | IntegerLiteral | Test.kt:94:3:94:10 | return ... | ReturnStmt |
|
||||||
| Test.kt:95:4:97:2 | catch (...) | CatchClause | Test.kt:91:1:98:1 | Exceptional Exit | Method |
|
|
||||||
| Test.kt:95:4:97:2 | catch (...) | CatchClause | Test.kt:95:11:95:33 | e | LocalVariableDeclExpr |
|
| Test.kt:95:4:97:2 | catch (...) | CatchClause | Test.kt:95:11:95:33 | e | LocalVariableDeclExpr |
|
||||||
|
| Test.kt:95:11:95:33 | e | LocalVariableDeclExpr | Test.kt:91:1:98:1 | Exceptional Exit | Method |
|
||||||
| Test.kt:95:11:95:33 | e | LocalVariableDeclExpr | Test.kt:95:36:97:2 | { ... } | BlockStmt |
|
| Test.kt:95:11:95:33 | e | LocalVariableDeclExpr | Test.kt:95:36:97:2 | { ... } | BlockStmt |
|
||||||
| Test.kt:95:36:97:2 | { ... } | BlockStmt | Test.kt:96:10:96:10 | 2 | IntegerLiteral |
|
| Test.kt:95:36:97:2 | { ... } | BlockStmt | Test.kt:96:10:96:10 | 2 | IntegerLiteral |
|
||||||
| Test.kt:96:3:96:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Normal Exit | Method |
|
| Test.kt:96:3:96:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Normal Exit | Method |
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
| MultiCatch.java:12:11:12:27 | new IOException(...) | MultiCatch.java:12:5:12:28 | throw ... |
|
| MultiCatch.java:12:11:12:27 | new IOException(...) | MultiCatch.java:12:5:12:28 | throw ... |
|
||||||
| MultiCatch.java:14:5:14:29 | throw ... | MultiCatch.java:15:5:15:37 | catch (...) |
|
| MultiCatch.java:14:5:14:29 | throw ... | MultiCatch.java:15:5:15:37 | catch (...) |
|
||||||
| MultiCatch.java:14:11:14:28 | new SQLException(...) | MultiCatch.java:14:5:14:29 | throw ... |
|
| MultiCatch.java:14:11:14:28 | new SQLException(...) | MultiCatch.java:14:5:14:29 | throw ... |
|
||||||
| MultiCatch.java:15:5:15:37 | catch (...) | MultiCatch.java:7:14:7:23 | Exceptional Exit |
|
|
||||||
| MultiCatch.java:15:5:15:37 | catch (...) | MultiCatch.java:15:36:15:36 | e |
|
| MultiCatch.java:15:5:15:37 | catch (...) | MultiCatch.java:15:36:15:36 | e |
|
||||||
|
| MultiCatch.java:15:36:15:36 | e | MultiCatch.java:7:14:7:23 | Exceptional Exit |
|
||||||
| MultiCatch.java:15:36:15:36 | e | MultiCatch.java:16:3:19:3 | { ... } |
|
| MultiCatch.java:15:36:15:36 | e | MultiCatch.java:16:3:19:3 | { ... } |
|
||||||
| MultiCatch.java:16:3:19:3 | { ... } | MultiCatch.java:17:4:17:23 | <Expr>; |
|
| MultiCatch.java:16:3:19:3 | { ... } | MultiCatch.java:17:4:17:23 | <Expr>; |
|
||||||
| MultiCatch.java:17:4:17:4 | e | MultiCatch.java:17:4:17:22 | printStackTrace(...) |
|
| MultiCatch.java:17:4:17:4 | e | MultiCatch.java:17:4:17:22 | printStackTrace(...) |
|
||||||
@@ -41,8 +41,8 @@
|
|||||||
| MultiCatch.java:29:11:29:28 | new SQLException(...) | MultiCatch.java:29:5:29:29 | throw ... |
|
| MultiCatch.java:29:11:29:28 | new SQLException(...) | MultiCatch.java:29:5:29:29 | throw ... |
|
||||||
| MultiCatch.java:30:4:30:25 | throw ... | MultiCatch.java:31:5:31:37 | catch (...) |
|
| MultiCatch.java:30:4:30:25 | throw ... | MultiCatch.java:31:5:31:37 | catch (...) |
|
||||||
| MultiCatch.java:30:10:30:24 | new Exception(...) | MultiCatch.java:30:4:30:25 | throw ... |
|
| MultiCatch.java:30:10:30:24 | new Exception(...) | MultiCatch.java:30:4:30:25 | throw ... |
|
||||||
| MultiCatch.java:31:5:31:37 | catch (...) | MultiCatch.java:22:14:22:24 | Exceptional Exit |
|
|
||||||
| MultiCatch.java:31:5:31:37 | catch (...) | MultiCatch.java:31:36:31:36 | e |
|
| MultiCatch.java:31:5:31:37 | catch (...) | MultiCatch.java:31:36:31:36 | e |
|
||||||
|
| MultiCatch.java:31:36:31:36 | e | MultiCatch.java:22:14:22:24 | Exceptional Exit |
|
||||||
| MultiCatch.java:31:36:31:36 | e | MultiCatch.java:32:3:32:4 | { ... } |
|
| MultiCatch.java:31:36:31:36 | e | MultiCatch.java:32:3:32:4 | { ... } |
|
||||||
| MultiCatch.java:32:3:32:4 | { ... } | MultiCatch.java:22:14:22:24 | Normal Exit |
|
| MultiCatch.java:32:3:32:4 | { ... } | MultiCatch.java:22:14:22:24 | Normal Exit |
|
||||||
| MultiCatch.java:35:14:35:26 | Entry | MultiCatch.java:36:2:42:2 | { ... } |
|
| MultiCatch.java:35:14:35:26 | Entry | MultiCatch.java:36:2:42:2 | { ... } |
|
||||||
|
|||||||
@@ -28,8 +28,8 @@
|
|||||||
| CloseReaderTest.java:19:11:19:15 | stdin | CloseReaderTest.java:19:11:19:26 | readLine(...) |
|
| CloseReaderTest.java:19:11:19:15 | stdin | CloseReaderTest.java:19:11:19:26 | readLine(...) |
|
||||||
| CloseReaderTest.java:19:11:19:26 | readLine(...) | CloseReaderTest.java:19:4:19:27 | return ... |
|
| CloseReaderTest.java:19:11:19:26 | readLine(...) | CloseReaderTest.java:19:4:19:27 | return ... |
|
||||||
| CloseReaderTest.java:19:11:19:26 | readLine(...) | CloseReaderTest.java:20:5:20:26 | catch (...) |
|
| CloseReaderTest.java:19:11:19:26 | readLine(...) | CloseReaderTest.java:20:5:20:26 | catch (...) |
|
||||||
| CloseReaderTest.java:20:5:20:26 | catch (...) | CloseReaderTest.java:9:23:9:34 | Exceptional Exit |
|
|
||||||
| CloseReaderTest.java:20:5:20:26 | catch (...) | CloseReaderTest.java:20:24:20:25 | ex |
|
| CloseReaderTest.java:20:5:20:26 | catch (...) | CloseReaderTest.java:20:24:20:25 | ex |
|
||||||
|
| CloseReaderTest.java:20:24:20:25 | ex | CloseReaderTest.java:9:23:9:34 | Exceptional Exit |
|
||||||
| CloseReaderTest.java:20:24:20:25 | ex | CloseReaderTest.java:21:3:23:3 | { ... } |
|
| CloseReaderTest.java:20:24:20:25 | ex | CloseReaderTest.java:21:3:23:3 | { ... } |
|
||||||
| CloseReaderTest.java:21:3:23:3 | { ... } | CloseReaderTest.java:22:11:22:14 | null |
|
| CloseReaderTest.java:21:3:23:3 | { ... } | CloseReaderTest.java:22:11:22:14 | null |
|
||||||
| CloseReaderTest.java:22:4:22:15 | return ... | CloseReaderTest.java:9:23:9:34 | Normal Exit |
|
| CloseReaderTest.java:22:4:22:15 | return ... | CloseReaderTest.java:9:23:9:34 | Normal Exit |
|
||||||
|
|||||||
@@ -50,16 +50,16 @@
|
|||||||
| SchackTest.java:16:4:16:41 | <Expr>; | SchackTest.java:16:4:16:13 | System.out |
|
| SchackTest.java:16:4:16:41 | <Expr>; | SchackTest.java:16:4:16:13 | System.out |
|
||||||
| SchackTest.java:16:23:16:39 | "false successor" | SchackTest.java:16:4:16:40 | println(...) |
|
| SchackTest.java:16:23:16:39 | "false successor" | SchackTest.java:16:4:16:40 | println(...) |
|
||||||
| SchackTest.java:17:5:17:17 | catch (...) | SchackTest.java:17:16:17:16 | e |
|
| SchackTest.java:17:5:17:17 | catch (...) | SchackTest.java:17:16:17:16 | e |
|
||||||
| SchackTest.java:17:5:17:17 | catch (...) | SchackTest.java:19:5:19:17 | catch (...) |
|
|
||||||
| SchackTest.java:17:16:17:16 | e | SchackTest.java:17:19:19:3 | { ... } |
|
| SchackTest.java:17:16:17:16 | e | SchackTest.java:17:19:19:3 | { ... } |
|
||||||
|
| SchackTest.java:17:16:17:16 | e | SchackTest.java:19:5:19:17 | catch (...) |
|
||||||
| SchackTest.java:17:19:19:3 | { ... } | SchackTest.java:18:4:18:41 | <Expr>; |
|
| SchackTest.java:17:19:19:3 | { ... } | SchackTest.java:18:4:18:41 | <Expr>; |
|
||||||
| SchackTest.java:18:4:18:13 | System.out | SchackTest.java:18:23:18:39 | "false successor" |
|
| SchackTest.java:18:4:18:13 | System.out | SchackTest.java:18:23:18:39 | "false successor" |
|
||||||
| SchackTest.java:18:4:18:40 | println(...) | SchackTest.java:21:13:23:3 | { ... } |
|
| SchackTest.java:18:4:18:40 | println(...) | SchackTest.java:21:13:23:3 | { ... } |
|
||||||
| SchackTest.java:18:4:18:41 | <Expr>; | SchackTest.java:18:4:18:13 | System.out |
|
| SchackTest.java:18:4:18:41 | <Expr>; | SchackTest.java:18:4:18:13 | System.out |
|
||||||
| SchackTest.java:18:23:18:39 | "false successor" | SchackTest.java:18:4:18:40 | println(...) |
|
| SchackTest.java:18:23:18:39 | "false successor" | SchackTest.java:18:4:18:40 | println(...) |
|
||||||
| SchackTest.java:19:5:19:17 | catch (...) | SchackTest.java:19:16:19:16 | e |
|
| SchackTest.java:19:5:19:17 | catch (...) | SchackTest.java:19:16:19:16 | e |
|
||||||
| SchackTest.java:19:5:19:17 | catch (...) | SchackTest.java:21:13:23:3 | { ... } |
|
|
||||||
| SchackTest.java:19:16:19:16 | e | SchackTest.java:19:19:21:3 | { ... } |
|
| SchackTest.java:19:16:19:16 | e | SchackTest.java:19:19:21:3 | { ... } |
|
||||||
|
| SchackTest.java:19:16:19:16 | e | SchackTest.java:21:13:23:3 | { ... } |
|
||||||
| SchackTest.java:19:19:21:3 | { ... } | SchackTest.java:20:4:20:74 | <Expr>; |
|
| SchackTest.java:19:19:21:3 | { ... } | SchackTest.java:20:4:20:74 | <Expr>; |
|
||||||
| SchackTest.java:20:4:20:13 | System.out | SchackTest.java:20:23:20:72 | "successor (but neither true nor false successor)" |
|
| SchackTest.java:20:4:20:13 | System.out | SchackTest.java:20:23:20:72 | "successor (but neither true nor false successor)" |
|
||||||
| SchackTest.java:20:4:20:73 | println(...) | SchackTest.java:21:13:23:3 | { ... } |
|
| SchackTest.java:20:4:20:73 | println(...) | SchackTest.java:21:13:23:3 | { ... } |
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
| TestThrow.java:20:10:20:31 | new RuntimeException(...) | TestThrow.java:20:4:20:32 | throw ... |
|
| TestThrow.java:20:10:20:31 | new RuntimeException(...) | TestThrow.java:20:4:20:32 | throw ... |
|
||||||
| TestThrow.java:20:10:20:31 | new RuntimeException(...) | TestThrow.java:21:5:21:30 | catch (...) |
|
| TestThrow.java:20:10:20:31 | new RuntimeException(...) | TestThrow.java:21:5:21:30 | catch (...) |
|
||||||
| TestThrow.java:21:5:21:30 | catch (...) | TestThrow.java:21:29:21:29 | e |
|
| TestThrow.java:21:5:21:30 | catch (...) | TestThrow.java:21:29:21:29 | e |
|
||||||
| TestThrow.java:21:5:21:30 | catch (...) | TestThrow.java:24:5:24:23 | catch (...) |
|
|
||||||
| TestThrow.java:21:29:21:29 | e | TestThrow.java:22:3:24:3 | { ... } |
|
| TestThrow.java:21:29:21:29 | e | TestThrow.java:22:3:24:3 | { ... } |
|
||||||
|
| TestThrow.java:21:29:21:29 | e | TestThrow.java:24:5:24:23 | catch (...) |
|
||||||
| TestThrow.java:22:3:24:3 | { ... } | TestThrow.java:23:4:23:9 | <Expr>; |
|
| TestThrow.java:22:3:24:3 | { ... } | TestThrow.java:23:4:23:9 | <Expr>; |
|
||||||
| TestThrow.java:23:4:23:4 | z | TestThrow.java:23:8:23:8 | 1 |
|
| TestThrow.java:23:4:23:4 | z | TestThrow.java:23:8:23:8 | 1 |
|
||||||
| TestThrow.java:23:4:23:8 | ...=... | TestThrow.java:29:3:29:9 | <Expr>; |
|
| TestThrow.java:23:4:23:8 | ...=... | TestThrow.java:29:3:29:9 | <Expr>; |
|
||||||
@@ -71,8 +71,8 @@
|
|||||||
| TestThrow.java:44:5:44:13 | thrower(...) | TestThrow.java:50:3:52:3 | { ... } |
|
| TestThrow.java:44:5:44:13 | thrower(...) | TestThrow.java:50:3:52:3 | { ... } |
|
||||||
| TestThrow.java:44:5:44:14 | <Expr>; | TestThrow.java:44:5:44:13 | thrower(...) |
|
| TestThrow.java:44:5:44:14 | <Expr>; | TestThrow.java:44:5:44:13 | thrower(...) |
|
||||||
| TestThrow.java:46:5:46:30 | catch (...) | TestThrow.java:46:29:46:29 | e |
|
| TestThrow.java:46:5:46:30 | catch (...) | TestThrow.java:46:29:46:29 | e |
|
||||||
| TestThrow.java:46:5:46:30 | catch (...) | TestThrow.java:50:3:52:3 | { ... } |
|
|
||||||
| TestThrow.java:46:29:46:29 | e | TestThrow.java:47:3:49:3 | { ... } |
|
| TestThrow.java:46:29:46:29 | e | TestThrow.java:47:3:49:3 | { ... } |
|
||||||
|
| TestThrow.java:46:29:46:29 | e | TestThrow.java:50:3:52:3 | { ... } |
|
||||||
| TestThrow.java:47:3:49:3 | { ... } | TestThrow.java:48:4:48:9 | <Expr>; |
|
| TestThrow.java:47:3:49:3 | { ... } | TestThrow.java:48:4:48:9 | <Expr>; |
|
||||||
| TestThrow.java:48:4:48:4 | z | TestThrow.java:48:8:48:8 | 1 |
|
| TestThrow.java:48:4:48:4 | z | TestThrow.java:48:8:48:8 | 1 |
|
||||||
| TestThrow.java:48:4:48:8 | ...=... | TestThrow.java:50:3:52:3 | { ... } |
|
| TestThrow.java:48:4:48:8 | ...=... | TestThrow.java:50:3:52:3 | { ... } |
|
||||||
@@ -113,8 +113,8 @@
|
|||||||
| TestThrow.java:67:5:67:13 | thrower(...) | TestThrow.java:69:5:69:30 | catch (...) |
|
| TestThrow.java:67:5:67:13 | thrower(...) | TestThrow.java:69:5:69:30 | catch (...) |
|
||||||
| TestThrow.java:67:5:67:13 | thrower(...) | TestThrow.java:74:3:74:9 | <Expr>; |
|
| TestThrow.java:67:5:67:13 | thrower(...) | TestThrow.java:74:3:74:9 | <Expr>; |
|
||||||
| TestThrow.java:67:5:67:14 | <Expr>; | TestThrow.java:67:5:67:13 | thrower(...) |
|
| TestThrow.java:67:5:67:14 | <Expr>; | TestThrow.java:67:5:67:13 | thrower(...) |
|
||||||
| TestThrow.java:69:5:69:30 | catch (...) | TestThrow.java:15:14:15:14 | Exceptional Exit |
|
|
||||||
| TestThrow.java:69:5:69:30 | catch (...) | TestThrow.java:69:29:69:29 | e |
|
| TestThrow.java:69:5:69:30 | catch (...) | TestThrow.java:69:29:69:29 | e |
|
||||||
|
| TestThrow.java:69:29:69:29 | e | TestThrow.java:15:14:15:14 | Exceptional Exit |
|
||||||
| TestThrow.java:69:29:69:29 | e | TestThrow.java:70:3:72:3 | { ... } |
|
| TestThrow.java:69:29:69:29 | e | TestThrow.java:70:3:72:3 | { ... } |
|
||||||
| TestThrow.java:70:3:72:3 | { ... } | TestThrow.java:71:4:71:9 | <Expr>; |
|
| TestThrow.java:70:3:72:3 | { ... } | TestThrow.java:71:4:71:9 | <Expr>; |
|
||||||
| TestThrow.java:71:4:71:4 | z | TestThrow.java:71:8:71:8 | 1 |
|
| TestThrow.java:71:4:71:4 | z | TestThrow.java:71:8:71:8 | 1 |
|
||||||
@@ -171,8 +171,8 @@
|
|||||||
| TestThrow.java:97:28:97:36 | "Foo bar" | TestThrow.java:97:39:97:42 | null |
|
| TestThrow.java:97:28:97:36 | "Foo bar" | TestThrow.java:97:39:97:42 | null |
|
||||||
| TestThrow.java:97:39:97:42 | null | TestThrow.java:97:12:97:43 | new IOException(...) |
|
| TestThrow.java:97:39:97:42 | null | TestThrow.java:97:12:97:43 | new IOException(...) |
|
||||||
| TestThrow.java:99:6:99:31 | catch (...) | TestThrow.java:99:30:99:30 | e |
|
| TestThrow.java:99:6:99:31 | catch (...) | TestThrow.java:99:30:99:30 | e |
|
||||||
| TestThrow.java:99:6:99:31 | catch (...) | TestThrow.java:119:5:119:25 | catch (...) |
|
|
||||||
| TestThrow.java:99:30:99:30 | e | TestThrow.java:100:4:102:4 | { ... } |
|
| TestThrow.java:99:30:99:30 | e | TestThrow.java:100:4:102:4 | { ... } |
|
||||||
|
| TestThrow.java:99:30:99:30 | e | TestThrow.java:119:5:119:25 | catch (...) |
|
||||||
| TestThrow.java:100:4:102:4 | { ... } | TestThrow.java:101:5:101:10 | <Expr>; |
|
| TestThrow.java:100:4:102:4 | { ... } | TestThrow.java:101:5:101:10 | <Expr>; |
|
||||||
| TestThrow.java:101:5:101:5 | z | TestThrow.java:101:9:101:9 | 1 |
|
| TestThrow.java:101:5:101:5 | z | TestThrow.java:101:9:101:9 | 1 |
|
||||||
| TestThrow.java:101:5:101:9 | ...=... | TestThrow.java:103:4:118:4 | try ... |
|
| TestThrow.java:101:5:101:9 | ...=... | TestThrow.java:103:4:118:4 | try ... |
|
||||||
@@ -216,8 +216,8 @@
|
|||||||
| TestThrow.java:116:28:116:36 | "Foo bar" | TestThrow.java:116:39:116:42 | null |
|
| TestThrow.java:116:28:116:36 | "Foo bar" | TestThrow.java:116:39:116:42 | null |
|
||||||
| TestThrow.java:116:39:116:42 | null | TestThrow.java:116:12:116:43 | new IOException(...) |
|
| TestThrow.java:116:39:116:42 | null | TestThrow.java:116:12:116:43 | new IOException(...) |
|
||||||
| TestThrow.java:119:5:119:25 | catch (...) | TestThrow.java:119:24:119:24 | e |
|
| TestThrow.java:119:5:119:25 | catch (...) | TestThrow.java:119:24:119:24 | e |
|
||||||
| TestThrow.java:119:5:119:25 | catch (...) | TestThrow.java:124:3:126:3 | { ... } |
|
|
||||||
| TestThrow.java:119:24:119:24 | e | TestThrow.java:120:3:122:3 | { ... } |
|
| TestThrow.java:119:24:119:24 | e | TestThrow.java:120:3:122:3 | { ... } |
|
||||||
|
| TestThrow.java:119:24:119:24 | e | TestThrow.java:124:3:126:3 | { ... } |
|
||||||
| TestThrow.java:120:3:122:3 | { ... } | TestThrow.java:121:4:121:9 | <Expr>; |
|
| TestThrow.java:120:3:122:3 | { ... } | TestThrow.java:121:4:121:9 | <Expr>; |
|
||||||
| TestThrow.java:121:4:121:4 | z | TestThrow.java:121:8:121:8 | 2 |
|
| TestThrow.java:121:4:121:4 | z | TestThrow.java:121:8:121:8 | 2 |
|
||||||
| TestThrow.java:121:4:121:8 | ...=... | TestThrow.java:124:3:126:3 | { ... } |
|
| TestThrow.java:121:4:121:8 | ...=... | TestThrow.java:124:3:126:3 | { ... } |
|
||||||
|
|||||||
@@ -105,8 +105,8 @@
|
|||||||
| TestTryCatch.java:34:9:34:9 | y | TestTryCatch.java:34:13:34:13 | 1 |
|
| TestTryCatch.java:34:9:34:9 | y | TestTryCatch.java:34:13:34:13 | 1 |
|
||||||
| TestTryCatch.java:34:9:34:13 | ... + ... | TestTryCatch.java:34:5:34:13 | ...=... |
|
| TestTryCatch.java:34:9:34:13 | ... + ... | TestTryCatch.java:34:5:34:13 | ...=... |
|
||||||
| TestTryCatch.java:34:13:34:13 | 1 | TestTryCatch.java:34:9:34:13 | ... + ... |
|
| TestTryCatch.java:34:13:34:13 | 1 | TestTryCatch.java:34:9:34:13 | ... + ... |
|
||||||
| TestTryCatch.java:35:6:35:31 | catch (...) | TestTryCatch.java:4:14:4:14 | Exceptional Exit |
|
|
||||||
| TestTryCatch.java:35:6:35:31 | catch (...) | TestTryCatch.java:35:30:35:30 | e |
|
| TestTryCatch.java:35:6:35:31 | catch (...) | TestTryCatch.java:35:30:35:30 | e |
|
||||||
|
| TestTryCatch.java:35:30:35:30 | e | TestTryCatch.java:4:14:4:14 | Exceptional Exit |
|
||||||
| TestTryCatch.java:35:30:35:30 | e | TestTryCatch.java:36:4:40:4 | { ... } |
|
| TestTryCatch.java:35:30:35:30 | e | TestTryCatch.java:36:4:40:4 | { ... } |
|
||||||
| TestTryCatch.java:36:4:40:4 | { ... } | TestTryCatch.java:37:5:37:14 | var ...; |
|
| TestTryCatch.java:36:4:40:4 | { ... } | TestTryCatch.java:37:5:37:14 | var ...; |
|
||||||
| TestTryCatch.java:37:5:37:14 | var ...; | TestTryCatch.java:37:13:37:13 | 1 |
|
| TestTryCatch.java:37:5:37:14 | var ...; | TestTryCatch.java:37:13:37:13 | 1 |
|
||||||
|
|||||||
@@ -28,8 +28,8 @@
|
|||||||
| TestTryWithResources.java:10:4:10:32 | <Expr>; | TestTryWithResources.java:10:4:10:13 | System.out |
|
| TestTryWithResources.java:10:4:10:32 | <Expr>; | TestTryWithResources.java:10:4:10:13 | System.out |
|
||||||
| TestTryWithResources.java:10:23:10:30 | "worked" | TestTryWithResources.java:10:4:10:31 | println(...) |
|
| TestTryWithResources.java:10:23:10:30 | "worked" | TestTryWithResources.java:10:4:10:31 | println(...) |
|
||||||
| TestTryWithResources.java:11:5:11:35 | catch (...) | TestTryWithResources.java:11:34:11:34 | e |
|
| TestTryWithResources.java:11:5:11:35 | catch (...) | TestTryWithResources.java:11:34:11:34 | e |
|
||||||
| TestTryWithResources.java:11:5:11:35 | catch (...) | TestTryWithResources.java:13:13:15:3 | { ... } |
|
|
||||||
| TestTryWithResources.java:11:34:11:34 | e | TestTryWithResources.java:11:37:13:3 | { ... } |
|
| TestTryWithResources.java:11:34:11:34 | e | TestTryWithResources.java:11:37:13:3 | { ... } |
|
||||||
|
| TestTryWithResources.java:11:34:11:34 | e | TestTryWithResources.java:13:13:15:3 | { ... } |
|
||||||
| TestTryWithResources.java:11:37:13:3 | { ... } | TestTryWithResources.java:12:4:12:40 | <Expr>; |
|
| TestTryWithResources.java:11:37:13:3 | { ... } | TestTryWithResources.java:12:4:12:40 | <Expr>; |
|
||||||
| TestTryWithResources.java:12:4:12:13 | System.out | TestTryWithResources.java:12:23:12:38 | "file not found" |
|
| TestTryWithResources.java:12:4:12:13 | System.out | TestTryWithResources.java:12:23:12:38 | "file not found" |
|
||||||
| TestTryWithResources.java:12:4:12:39 | println(...) | TestTryWithResources.java:13:13:15:3 | { ... } |
|
| TestTryWithResources.java:12:4:12:39 | println(...) | TestTryWithResources.java:13:13:15:3 | { ... } |
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
import semmle.python.controlflow.internal.AstNodeImpl
|
|
||||||
import ControlFlow::Consistency
|
|
||||||
@@ -9,7 +9,6 @@ private import semmle.python.dataflow.new.internal.DataFlowImplSpecific
|
|||||||
private import semmle.python.dataflow.new.internal.DataFlowDispatch
|
private import semmle.python.dataflow.new.internal.DataFlowDispatch
|
||||||
private import semmle.python.dataflow.new.internal.TaintTrackingImplSpecific
|
private import semmle.python.dataflow.new.internal.TaintTrackingImplSpecific
|
||||||
private import codeql.dataflow.internal.DataFlowImplConsistency
|
private import codeql.dataflow.internal.DataFlowImplConsistency
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
|
|
||||||
private module Input implements InputSig<Location, PythonDataFlow> {
|
private module Input implements InputSig<Location, PythonDataFlow> {
|
||||||
private import Private
|
private import Private
|
||||||
@@ -75,7 +74,7 @@ private module Input implements InputSig<Location, PythonDataFlow> {
|
|||||||
// resolve to multiple functions), but we only make _one_ ArgumentNode for each
|
// resolve to multiple functions), but we only make _one_ ArgumentNode for each
|
||||||
// argument in the CallNode, we end up violating this consistency check in those
|
// argument in the CallNode, we end up violating this consistency check in those
|
||||||
// cases. (see `getCallArg` in DataFlowDispatch.qll)
|
// cases. (see `getCallArg` in DataFlowDispatch.qll)
|
||||||
exists(DataFlowCall other, Cfg::CallNode cfgCall | other != call |
|
exists(DataFlowCall other, CallNode cfgCall | other != call |
|
||||||
call.getNode() = cfgCall and
|
call.getNode() = cfgCall and
|
||||||
other.getNode() = cfgCall and
|
other.getNode() = cfgCall and
|
||||||
isArgumentNode(arg, call, _) and
|
isArgumentNode(arg, call, _) and
|
||||||
@@ -91,16 +90,16 @@ private module Input implements InputSig<Location, PythonDataFlow> {
|
|||||||
// allow it instead.
|
// allow it instead.
|
||||||
(
|
(
|
||||||
call.getScope() = attr.getScope() and
|
call.getScope() = attr.getScope() and
|
||||||
any(CfgNode n | n.asCfgNode() = call.getNode().(Cfg::CallNode).getFunction())
|
any(CfgNode n | n.asCfgNode() = call.getNode().(CallNode).getFunction()).getALocalSource() =
|
||||||
.getALocalSource() = attr
|
attr
|
||||||
or
|
or
|
||||||
not exists(call.getScope().(Function).getDefinition()) and
|
not exists(call.getScope().(Function).getDefinition()) and
|
||||||
call.getScope().getScope+() = attr.getScope()
|
call.getScope().getScope+() = attr.getScope()
|
||||||
) and
|
) and
|
||||||
(
|
(
|
||||||
other.getScope() = attr.getScope() and
|
other.getScope() = attr.getScope() and
|
||||||
any(CfgNode n | n.asCfgNode() = other.getNode().(Cfg::CallNode).getFunction())
|
any(CfgNode n | n.asCfgNode() = other.getNode().(CallNode).getFunction()).getALocalSource() =
|
||||||
.getALocalSource() = attr
|
attr
|
||||||
or
|
or
|
||||||
not exists(other.getScope().(Function).getDefinition()) and
|
not exists(other.getScope().(Function).getDefinition()) and
|
||||||
other.getScope().getScope+() = attr.getScope()
|
other.getScope().getScope+() = attr.getScope()
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
category: minorAnalysis
|
|
||||||
---
|
|
||||||
* A new Python control flow graph implementation has been added under `semmle.python.controlflow.internal.Cfg` (backed by `AstNodeImpl.qll`), built on the shared `codeql.controlflow.ControlFlowGraph` library. It is not yet used by the dataflow library or any production query; the legacy CFG in `semmle/python/Flow.qll` remains the default. The new library is exposed for tests and for upcoming migrations.
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
category: minorAnalysis
|
|
||||||
---
|
|
||||||
* A new SSA adapter has been added under `semmle.python.dataflow.new.internal.SsaImpl`, built on the shared `codeql.ssa.Ssa` library and the new shared CFG (`semmle.python.controlflow.internal.Cfg`). It is not yet used by the dataflow library or any production query; the legacy ESSA SSA in `semmle/python/essa/*` remains the default. The new SSA adapter is exposed for tests and for the upcoming dataflow migration.
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
category: breaking
|
|
||||||
---
|
|
||||||
* The deprecated `AstNode.getAFlowNode()` and `Function.getAReturnValueFlowNode()` predicates now return nodes from the new shared CFG (`Cfg::ControlFlowNode`) rather than from the legacy CFG (`ControlFlowNode`). Callers that still rely on these deprecated APIs and feed the result into legacy-CFG-aware predicates will no longer type-check; migrate to `n.getNode() = e` (or, for return values, the explicit `Return` pattern shown in the deprecation message) to get nodes from the dataflow library's current CFG.
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
/**
|
|
||||||
* @name Print CFG (New)
|
|
||||||
* @description Produces a representation of a file's Control Flow Graph
|
|
||||||
* using the new shared control flow library.
|
|
||||||
* This query is used by the VS Code extension.
|
|
||||||
* @id python/print-cfg
|
|
||||||
* @kind graph
|
|
||||||
* @tags ide-contextual-queries/print-cfg
|
|
||||||
*/
|
|
||||||
|
|
||||||
private import python as Py
|
|
||||||
import semmle.python.controlflow.internal.AstNodeImpl
|
|
||||||
|
|
||||||
external string selectedSourceFile();
|
|
||||||
|
|
||||||
private predicate selectedSourceFileAlias = selectedSourceFile/0;
|
|
||||||
|
|
||||||
external int selectedSourceLine();
|
|
||||||
|
|
||||||
private predicate selectedSourceLineAlias = selectedSourceLine/0;
|
|
||||||
|
|
||||||
external int selectedSourceColumn();
|
|
||||||
|
|
||||||
private predicate selectedSourceColumnAlias = selectedSourceColumn/0;
|
|
||||||
|
|
||||||
module ViewCfgQueryInput implements ControlFlow::ViewCfgQueryInputSig<Py::File> {
|
|
||||||
predicate selectedSourceFile = selectedSourceFileAlias/0;
|
|
||||||
|
|
||||||
predicate selectedSourceLine = selectedSourceLineAlias/0;
|
|
||||||
|
|
||||||
predicate selectedSourceColumn = selectedSourceColumnAlias/0;
|
|
||||||
|
|
||||||
predicate cfgScopeSpan(
|
|
||||||
Ast::Callable callable, Py::File file, int startLine, int startColumn, int endLine,
|
|
||||||
int endColumn
|
|
||||||
) {
|
|
||||||
exists(Py::Scope scope |
|
|
||||||
scope = callable.asScope() and
|
|
||||||
file = scope.getLocation().getFile() and
|
|
||||||
scope.getLocation().hasLocationInfo(_, startLine, startColumn, endLine, endColumn)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
import ControlFlow::ViewCfgQuery<Py::File, ViewCfgQueryInput>
|
|
||||||
@@ -6,9 +6,8 @@
|
|||||||
* directed and labeled; they specify how the components represented by nodes relate to each other.
|
* directed and labeled; they specify how the components represented by nodes relate to each other.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Importing python under the `PY` namespace to avoid pulling in `CallNode` from `Flow.qll` (via `import python`) and thereby having a naming conflict with `API::CallNode`.
|
// Importing python under the `py` namespace to avoid importing `CallNode` from `Flow.qll` and thereby having a naming conflict with `API::CallNode`.
|
||||||
private import python as PY
|
private import python as PY
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
import semmle.python.dataflow.new.DataFlow
|
import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.internal.CachedStages
|
private import semmle.python.internal.CachedStages
|
||||||
|
|
||||||
@@ -283,7 +282,7 @@ module API {
|
|||||||
index = this.getIndex() and
|
index = this.getIndex() and
|
||||||
(
|
(
|
||||||
// subscripting
|
// subscripting
|
||||||
exists(Cfg::SubscriptNode subscript |
|
exists(PY::SubscriptNode subscript |
|
||||||
subscript.getObject() = this.getAValueReachableFromSource().asCfgNode() and
|
subscript.getObject() = this.getAValueReachableFromSource().asCfgNode() and
|
||||||
subscript.getIndex() = index.asSink().asCfgNode()
|
subscript.getIndex() = index.asSink().asCfgNode()
|
||||||
|
|
|
|
||||||
@@ -291,7 +290,7 @@ module API {
|
|||||||
subscript = result.asSource().asCfgNode()
|
subscript = result.asSource().asCfgNode()
|
||||||
or
|
or
|
||||||
// writing
|
// writing
|
||||||
subscript.(Cfg::DefinitionNode).getValue() = result.asSink().asCfgNode()
|
subscript.(PY::DefinitionNode).getValue() = result.asSink().asCfgNode()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// dictionary literals
|
// dictionary literals
|
||||||
@@ -685,7 +684,7 @@ module API {
|
|||||||
* Ignores relative imports, such as `from ..foo.bar import baz`.
|
* Ignores relative imports, such as `from ..foo.bar import baz`.
|
||||||
*/
|
*/
|
||||||
private predicate imports(DataFlow::CfgNode imp, string name) {
|
private predicate imports(DataFlow::CfgNode imp, string name) {
|
||||||
exists(Cfg::ImportExprNode iexpr |
|
exists(PY::ImportExprNode iexpr |
|
||||||
imp.getNode() = iexpr and
|
imp.getNode() = iexpr and
|
||||||
not iexpr.getNode().isRelative() and
|
not iexpr.getNode().isRelative() and
|
||||||
name = iexpr.getNode().getImportedModuleName()
|
name = iexpr.getNode().getImportedModuleName()
|
||||||
@@ -776,7 +775,7 @@ module API {
|
|||||||
// list literals, from `x` to `[x]`
|
// list literals, from `x` to `[x]`
|
||||||
// TODO: once convenient, this should be done at a higher level than the AST,
|
// TODO: once convenient, this should be done at a higher level than the AST,
|
||||||
// at least at the CFG layer, to take splitting into account.
|
// at least at the CFG layer, to take splitting into account.
|
||||||
// Also consider `Cfg::SequenceNode` for generality.
|
// Also consider `SequenceNode for generality.
|
||||||
exists(PY::List list | list = pred.(DataFlow::ExprNode).getNode().getNode() |
|
exists(PY::List list | list = pred.(DataFlow::ExprNode).getNode().getNode() |
|
||||||
rhs.(DataFlow::ExprNode).getNode().getNode() = list.getAnElt() and
|
rhs.(DataFlow::ExprNode).getNode().getNode() = list.getAnElt() and
|
||||||
lbl = Label::subscript()
|
lbl = Label::subscript()
|
||||||
@@ -806,7 +805,7 @@ module API {
|
|||||||
subscript = trackUseNode(src).getSubscript(index)
|
subscript = trackUseNode(src).getSubscript(index)
|
||||||
|
|
|
|
||||||
// from `x` to a definition of `x[...]`
|
// from `x` to a definition of `x[...]`
|
||||||
rhs.asCfgNode() = subscript.asCfgNode().(Cfg::DefinitionNode).getValue() and
|
rhs.asCfgNode() = subscript.asCfgNode().(PY::DefinitionNode).getValue() and
|
||||||
lbl = Label::subscript()
|
lbl = Label::subscript()
|
||||||
or
|
or
|
||||||
// from `x` to `"key"` in `x["key"]`
|
// from `x` to `"key"` in `x["key"]`
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ module;
|
|||||||
|
|
||||||
import python
|
import python
|
||||||
private import semmle.python.internal.CachedStages
|
private import semmle.python.internal.CachedStages
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
|
|
||||||
/** A syntactic node (Class, Function, Module, Expr, Stmt or Comprehension) corresponding to a flow node */
|
/** A syntactic node (Class, Function, Module, Expr, Stmt or Comprehension) corresponding to a flow node */
|
||||||
abstract class AstNode extends AstNode_ {
|
abstract class AstNode extends AstNode_ {
|
||||||
@@ -20,16 +19,17 @@ abstract class AstNode extends AstNode_ {
|
|||||||
/**
|
/**
|
||||||
* DEPRECATED: use `ControlFlowNode.getNode()` from the other direction instead;
|
* DEPRECATED: use `ControlFlowNode.getNode()` from the other direction instead;
|
||||||
* that is, replace `e.getAFlowNode() = n` with `n.getNode() = e`. This API is
|
* that is, replace `e.getAFlowNode() = n` with `n.getNode() = e`. This API is
|
||||||
* being removed to untangle the AST and CFG hierarchies.
|
* being removed to untangle the AST and CFG hierarchies in preparation for
|
||||||
|
* migrating the dataflow library off the legacy CFG.
|
||||||
*
|
*
|
||||||
* Gets a flow node corresponding directly to this node, from the new
|
* Gets a flow node corresponding directly to this node.
|
||||||
* (shared) CFG. NOTE: For some statements and other purely syntactic
|
* NOTE: For some statements and other purely syntactic elements,
|
||||||
* elements, there may not be a `ControlFlowNode`.
|
* there may not be a `ControlFlowNode`.
|
||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
deprecated Cfg::ControlFlowNode getAFlowNode() {
|
deprecated ControlFlowNode getAFlowNode() {
|
||||||
Stages::AST::ref() and
|
Stages::AST::ref() and
|
||||||
result.getNode() = this
|
py_flow_bb_node(result, this, _, _)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the location for this AST node */
|
/** Gets the location for this AST node */
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.dataflow.new.internal.DataFlowImplSpecific
|
private import semmle.python.dataflow.new.internal.DataFlowImplSpecific
|
||||||
private import semmle.python.dataflow.new.RemoteFlowSources
|
private import semmle.python.dataflow.new.RemoteFlowSources
|
||||||
@@ -215,7 +214,7 @@ module Path {
|
|||||||
SafeAccessCheck() { this = DataFlow::BarrierGuard<safeAccessCheck/3>::getABarrierNode() }
|
SafeAccessCheck() { this = DataFlow::BarrierGuard<safeAccessCheck/3>::getABarrierNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate safeAccessCheck(DataFlow::GuardNode g, Cfg::ControlFlowNode node, boolean branch) {
|
private predicate safeAccessCheck(DataFlow::GuardNode g, ControlFlowNode node, boolean branch) {
|
||||||
g.(SafeAccessCheck::Range).checks(node, branch)
|
g.(SafeAccessCheck::Range).checks(node, branch)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,7 +223,7 @@ module Path {
|
|||||||
/** A data-flow node that checks that a path is safe to access in some way, for example by having a controlled prefix. */
|
/** A data-flow node that checks that a path is safe to access in some way, for example by having a controlled prefix. */
|
||||||
abstract class Range extends DataFlow::GuardNode {
|
abstract class Range extends DataFlow::GuardNode {
|
||||||
/** Holds if this guard validates `node` upon evaluating to `branch`. */
|
/** Holds if this guard validates `node` upon evaluating to `branch`. */
|
||||||
abstract predicate checks(Cfg::ControlFlowNode node, boolean branch);
|
abstract predicate checks(ControlFlowNode node, boolean branch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ module;
|
|||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.internal.CachedStages
|
private import semmle.python.internal.CachedStages
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
|
|
||||||
/** An expression */
|
/** An expression */
|
||||||
class Expr extends Expr_, AstNode {
|
class Expr extends Expr_, AstNode {
|
||||||
@@ -71,7 +70,7 @@ class Attribute extends Attribute_ {
|
|||||||
/* syntax: Expr.name */
|
/* syntax: Expr.name */
|
||||||
override Expr getASubExpression() { result = this.getObject() }
|
override Expr getASubExpression() { result = this.getObject() }
|
||||||
|
|
||||||
deprecated override Cfg::AttrNode getAFlowNode() { result = super.getAFlowNode() }
|
deprecated override AttrNode getAFlowNode() { result = super.getAFlowNode() }
|
||||||
|
|
||||||
/** Gets the name of this attribute. That is the `name` in `obj.name` */
|
/** Gets the name of this attribute. That is the `name` in `obj.name` */
|
||||||
string getName() { result = Attribute_.super.getAttr() }
|
string getName() { result = Attribute_.super.getAttr() }
|
||||||
@@ -100,7 +99,7 @@ class Subscript extends Subscript_ {
|
|||||||
|
|
||||||
Expr getObject() { result = Subscript_.super.getValue() }
|
Expr getObject() { result = Subscript_.super.getValue() }
|
||||||
|
|
||||||
deprecated override Cfg::SubscriptNode getAFlowNode() { result = super.getAFlowNode() }
|
deprecated override SubscriptNode getAFlowNode() { result = super.getAFlowNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A call expression, such as `func(...)` */
|
/** A call expression, such as `func(...)` */
|
||||||
@@ -116,7 +115,7 @@ class Call extends Call_ {
|
|||||||
|
|
||||||
override string toString() { result = this.getFunc().toString() + "()" }
|
override string toString() { result = this.getFunc().toString() + "()" }
|
||||||
|
|
||||||
deprecated override Cfg::CallNode getAFlowNode() { result = super.getAFlowNode() }
|
deprecated override CallNode getAFlowNode() { result = super.getAFlowNode() }
|
||||||
|
|
||||||
/** Gets a tuple (*) argument of this call. */
|
/** Gets a tuple (*) argument of this call. */
|
||||||
Expr getStarargs() { result = this.getAPositionalArg().(Starred).getValue() }
|
Expr getStarargs() { result = this.getAPositionalArg().(Starred).getValue() }
|
||||||
@@ -204,7 +203,7 @@ class IfExp extends IfExp_ {
|
|||||||
result = this.getTest() or result = this.getBody() or result = this.getOrelse()
|
result = this.getTest() or result = this.getBody() or result = this.getOrelse()
|
||||||
}
|
}
|
||||||
|
|
||||||
deprecated override Cfg::IfExprNode getAFlowNode() { result = super.getAFlowNode() }
|
deprecated override IfExprNode getAFlowNode() { result = super.getAFlowNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A starred expression, such as the `*rest` in the assignment `first, *rest = seq` */
|
/** A starred expression, such as the `*rest` in the assignment `first, *rest = seq` */
|
||||||
@@ -414,7 +413,7 @@ class PlaceHolder extends PlaceHolder_ {
|
|||||||
|
|
||||||
override string toString() { result = "$" + this.getId() }
|
override string toString() { result = "$" + this.getId() }
|
||||||
|
|
||||||
deprecated override Cfg::NameNode getAFlowNode() { result = super.getAFlowNode() }
|
deprecated override NameNode getAFlowNode() { result = super.getAFlowNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A tuple expression such as `( 1, 3, 5, 7, 9 )` */
|
/** A tuple expression such as `( 1, 3, 5, 7, 9 )` */
|
||||||
@@ -481,7 +480,7 @@ class Name extends Name_ {
|
|||||||
|
|
||||||
override string toString() { result = this.getId() }
|
override string toString() { result = this.getId() }
|
||||||
|
|
||||||
deprecated override Cfg::NameNode getAFlowNode() { result = super.getAFlowNode() }
|
deprecated override NameNode getAFlowNode() { result = super.getAFlowNode() }
|
||||||
|
|
||||||
override predicate isArtificial() {
|
override predicate isArtificial() {
|
||||||
/* Artificial variable names in comprehensions all start with "." */
|
/* Artificial variable names in comprehensions all start with "." */
|
||||||
@@ -588,7 +587,7 @@ abstract class NameConstant extends Name, ImmutableLiteral {
|
|||||||
|
|
||||||
override predicate isConstant() { any() }
|
override predicate isConstant() { any() }
|
||||||
|
|
||||||
deprecated override Cfg::NameConstantNode getAFlowNode() { result = Name.super.getAFlowNode() }
|
deprecated override NameConstantNode getAFlowNode() { result = Name.super.getAFlowNode() }
|
||||||
|
|
||||||
override predicate isArtificial() { none() }
|
override predicate isArtificial() { none() }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ overlay[local]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
import python
|
import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A function, independent of defaults and binding.
|
* A function, independent of defaults and binding.
|
||||||
@@ -158,12 +157,12 @@ class Function extends Function_, Scope, AstNode {
|
|||||||
* DEPRECATED: bind a `Return` node explicitly instead, e.g.
|
* DEPRECATED: bind a `Return` node explicitly instead, e.g.
|
||||||
* `exists(Return ret | ret.getScope() = this and n.getNode() = ret.getValue())`.
|
* `exists(Return ret | ret.getScope() = this and n.getNode() = ret.getValue())`.
|
||||||
* This API is being phased out together with `AstNode.getAFlowNode()` to
|
* This API is being phased out together with `AstNode.getAFlowNode()` to
|
||||||
* untangle the AST and CFG hierarchies.
|
* untangle the AST and CFG hierarchies in preparation for migrating the
|
||||||
|
* dataflow library off the legacy CFG.
|
||||||
*
|
*
|
||||||
* Gets a control flow node for a return value of this function, from the
|
* Gets a control flow node for a return value of this function.
|
||||||
* new (shared) CFG.
|
|
||||||
*/
|
*/
|
||||||
deprecated Cfg::ControlFlowNode getAReturnValueFlowNode() {
|
deprecated ControlFlowNode getAReturnValueFlowNode() {
|
||||||
exists(Return ret |
|
exists(Return ret |
|
||||||
ret.getScope() = this and
|
ret.getScope() = this and
|
||||||
ret.getValue() = result.getNode()
|
ret.getValue() = result.getNode()
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ module;
|
|||||||
import python
|
import python
|
||||||
private import semmle.python.types.Builtins
|
private import semmle.python.types.Builtins
|
||||||
private import semmle.python.internal.CachedStages
|
private import semmle.python.internal.CachedStages
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An alias in an import statement, the `mod as name` part of `import mod as name`. May be artificial;
|
* An alias in an import statement, the `mod as name` part of `import mod as name`. May be artificial;
|
||||||
@@ -164,7 +163,7 @@ class ImportMember extends ImportMember_ {
|
|||||||
result = this.getModule().(ImportExpr).getImportedModuleName() + "." + this.getName()
|
result = this.getModule().(ImportExpr).getImportedModuleName() + "." + this.getName()
|
||||||
}
|
}
|
||||||
|
|
||||||
deprecated override Cfg::ImportMemberNode getAFlowNode() { result = super.getAFlowNode() }
|
deprecated override ImportMemberNode getAFlowNode() { result = super.getAFlowNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An import statement */
|
/** An import statement */
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,11 @@
|
|||||||
/** Provides commonly used BarrierGuards. */
|
/** Provides commonly used BarrierGuards. */
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
|
|
||||||
private predicate constCompare(DataFlow::GuardNode g, Cfg::ControlFlowNode node, boolean branch) {
|
private predicate constCompare(DataFlow::GuardNode g, ControlFlowNode node, boolean branch) {
|
||||||
exists(Cfg::CompareNode cn | cn = g |
|
exists(CompareNode cn | cn = g |
|
||||||
exists(ImmutableLiteral const, Cmpop op, Cfg::ControlFlowNode c |
|
exists(ImmutableLiteral const, Cmpop op, ControlFlowNode c |
|
||||||
c.getNode() = const and
|
c.getNode() = const and
|
||||||
(
|
(
|
||||||
op = any(Eq eq) and branch = true
|
op = any(Eq eq) and branch = true
|
||||||
@@ -19,7 +18,7 @@ private predicate constCompare(DataFlow::GuardNode g, Cfg::ControlFlowNode node,
|
|||||||
cn.operands(node, op, c)
|
cn.operands(node, op, c)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(NameConstant const, Cmpop op, Cfg::ControlFlowNode c |
|
exists(NameConstant const, Cmpop op, ControlFlowNode c |
|
||||||
c.getNode() = const and
|
c.getNode() = const and
|
||||||
(
|
(
|
||||||
op = any(Is is_) and branch = true
|
op = any(Is is_) and branch = true
|
||||||
@@ -32,12 +31,12 @@ private predicate constCompare(DataFlow::GuardNode g, Cfg::ControlFlowNode node,
|
|||||||
cn.operands(node, op, c)
|
cn.operands(node, op, c)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(Cfg::IterableNode const_iterable, Cmpop op |
|
exists(IterableNode const_iterable, Cmpop op |
|
||||||
op = any(In in_) and branch = true
|
op = any(In in_) and branch = true
|
||||||
or
|
or
|
||||||
op = any(NotIn ni) and branch = false
|
op = any(NotIn ni) and branch = false
|
||||||
|
|
|
|
||||||
forall(Cfg::ControlFlowNode elem | elem = const_iterable.getAnElement() |
|
forall(ControlFlowNode elem | elem = const_iterable.getAnElement() |
|
||||||
elem.getNode() instanceof ImmutableLiteral
|
elem.getNode() instanceof ImmutableLiteral
|
||||||
) and
|
) and
|
||||||
cn.operands(node, op, const_iterable)
|
cn.operands(node, op, const_iterable)
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
// Need to import `semmle.python.Frameworks` since frameworks can extend `SensitiveDataSource::Range`
|
// Need to import `semmle.python.Frameworks` since frameworks can extend `SensitiveDataSource::Range`
|
||||||
private import semmle.python.Frameworks
|
private import semmle.python.Frameworks
|
||||||
@@ -106,7 +105,7 @@ private module SensitiveDataModeling {
|
|||||||
or
|
or
|
||||||
// to cover functions that we don't have the definition for, and where the
|
// to cover functions that we don't have the definition for, and where the
|
||||||
// reference to the function has not already been marked as being sensitive
|
// reference to the function has not already been marked as being sensitive
|
||||||
this.getFunction().asCfgNode().(Cfg::NameNode).getId() = sensitiveString(classification)
|
this.getFunction().asCfgNode().(NameNode).getId() = sensitiveString(classification)
|
||||||
}
|
}
|
||||||
|
|
||||||
override SensitiveDataClassification getClassification() { result = classification }
|
override SensitiveDataClassification getClassification() { result = classification }
|
||||||
@@ -252,12 +251,12 @@ private module SensitiveDataModeling {
|
|||||||
SensitiveDataClassification classification;
|
SensitiveDataClassification classification;
|
||||||
|
|
||||||
SensitiveVariableAssignment() {
|
SensitiveVariableAssignment() {
|
||||||
exists(Cfg::DefinitionNode def |
|
exists(DefinitionNode def |
|
||||||
def.(Cfg::NameNode).getId() = sensitiveString(classification) and
|
def.(NameNode).getId() = sensitiveString(classification) and
|
||||||
(
|
(
|
||||||
this.asCfgNode() = def.getValue()
|
this.asCfgNode() = def.getValue()
|
||||||
or
|
or
|
||||||
this.asCfgNode() = def.getValue().(Cfg::ForNode).getSequence()
|
this.asCfgNode() = def.getValue().(ForNode).getSequence()
|
||||||
) and
|
) and
|
||||||
not this.asExpr() instanceof FunctionExpr and
|
not this.asExpr() instanceof FunctionExpr and
|
||||||
not this.asExpr() instanceof ClassExpr
|
not this.asExpr() instanceof ClassExpr
|
||||||
@@ -294,7 +293,7 @@ private module SensitiveDataModeling {
|
|||||||
SensitiveDataClassification classification;
|
SensitiveDataClassification classification;
|
||||||
|
|
||||||
SensitiveSubscript() {
|
SensitiveSubscript() {
|
||||||
this.asCfgNode().(Cfg::SubscriptNode).getIndex() =
|
this.asCfgNode().(SubscriptNode).getIndex() =
|
||||||
sensitiveLookupStringConst(classification).asCfgNode()
|
sensitiveLookupStringConst(classification).asCfgNode()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ overlay[local]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
import DataFlowUtil
|
import DataFlowUtil
|
||||||
import DataFlowPublic
|
import DataFlowPublic
|
||||||
private import DataFlowPrivate
|
private import DataFlowPrivate
|
||||||
@@ -84,9 +83,9 @@ abstract class AttrWrite extends AttrRef {
|
|||||||
* ```python
|
* ```python
|
||||||
* object.attr = value
|
* object.attr = value
|
||||||
* ```
|
* ```
|
||||||
* Also gives access to the `value` being written, by extending `Cfg::DefinitionNode`.
|
* Also gives access to the `value` being written, by extending `DefinitionNode`.
|
||||||
*/
|
*/
|
||||||
private class AttributeAssignmentNode extends Cfg::DefinitionNode, Cfg::AttrNode { }
|
private class AttributeAssignmentNode extends DefinitionNode, AttrNode { }
|
||||||
|
|
||||||
/** A simple attribute assignment: `object.attr = value`. */
|
/** A simple attribute assignment: `object.attr = value`. */
|
||||||
private class AttributeAssignmentAsAttrWrite extends AttrWrite, CfgNode {
|
private class AttributeAssignmentAsAttrWrite extends AttrWrite, CfgNode {
|
||||||
@@ -132,13 +131,13 @@ private class GlobalAttributeAssignmentAsAttrWrite extends AttrWrite, CfgNode {
|
|||||||
override string getAttributeName() { result = node.getName() }
|
override string getAttributeName() { result = node.getName() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Represents `Cfg::CallNode`s that may refer to calls to built-in functions or classes. */
|
/** Represents `CallNode`s that may refer to calls to built-in functions or classes. */
|
||||||
private class BuiltInCallNode extends Cfg::CallNode {
|
private class BuiltInCallNode extends CallNode {
|
||||||
string name;
|
string name;
|
||||||
|
|
||||||
BuiltInCallNode() {
|
BuiltInCallNode() {
|
||||||
// TODO disallow instances where the name of the built-in may refer to an in-scope variable of that name.
|
// TODO disallow instances where the name of the built-in may refer to an in-scope variable of that name.
|
||||||
exists(Cfg::NameNode id |
|
exists(NameNode id |
|
||||||
name = Builtins::getBuiltinName() and
|
name = Builtins::getBuiltinName() and
|
||||||
this.getFunction() = id and
|
this.getFunction() = id and
|
||||||
id.getId() = name and
|
id.getId() = name and
|
||||||
@@ -146,7 +145,7 @@ private class BuiltInCallNode extends Cfg::CallNode {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the name of the built-in function that is called at this `Cfg::CallNode` */
|
/** Gets the name of the built-in function that is called at this `CallNode` */
|
||||||
string getBuiltinName() { result = name }
|
string getBuiltinName() { result = name }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,20 +157,20 @@ private class BuiltinAttrCallNode extends BuiltInCallNode {
|
|||||||
BuiltinAttrCallNode() { name in ["setattr", "getattr", "hasattr", "delattr"] }
|
BuiltinAttrCallNode() { name in ["setattr", "getattr", "hasattr", "delattr"] }
|
||||||
|
|
||||||
/** Gets the control flow node for object on which the attribute is accessed. */
|
/** Gets the control flow node for object on which the attribute is accessed. */
|
||||||
Cfg::ControlFlowNode getObject() { result in [this.getArg(0), this.getArgByName("object")] }
|
ControlFlowNode getObject() { result in [this.getArg(0), this.getArgByName("object")] }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the control flow node for the value that is being written to the attribute.
|
* Gets the control flow node for the value that is being written to the attribute.
|
||||||
* Only relevant for `setattr` calls.
|
* Only relevant for `setattr` calls.
|
||||||
*/
|
*/
|
||||||
Cfg::ControlFlowNode getValue() {
|
ControlFlowNode getValue() {
|
||||||
// only valid for `setattr`
|
// only valid for `setattr`
|
||||||
name = "setattr" and
|
name = "setattr" and
|
||||||
result in [this.getArg(2), this.getArgByName("value")]
|
result in [this.getArg(2), this.getArgByName("value")]
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the control flow node that defines the name of the attribute being accessed. */
|
/** Gets the control flow node that defines the name of the attribute being accessed. */
|
||||||
Cfg::ControlFlowNode getName() { result in [this.getArg(1), this.getArgByName("name")] }
|
ControlFlowNode getName() { result in [this.getArg(1), this.getArgByName("name")] }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Represents calls to the built-in `setattr`. */
|
/** Represents calls to the built-in `setattr`. */
|
||||||
@@ -206,10 +205,10 @@ private class SetAttrCallAsAttrWrite extends AttrWrite, CfgNode {
|
|||||||
* attr = value
|
* attr = value
|
||||||
* ...
|
* ...
|
||||||
* ```
|
* ```
|
||||||
* Instances of this class correspond to the `Cfg::NameNode` for `attr`, and also gives access to `value` by
|
* Instances of this class correspond to the `NameNode` for `attr`, and also gives access to `value` by
|
||||||
* virtue of being a `Cfg::DefinitionNode`.
|
* virtue of being a `DefinitionNode`.
|
||||||
*/
|
*/
|
||||||
private class ClassAttributeAssignmentNode extends Cfg::DefinitionNode, Cfg::NameNode {
|
private class ClassAttributeAssignmentNode extends DefinitionNode, NameNode {
|
||||||
ClassAttributeAssignmentNode() { this.getScope() = any(ClassExpr c).getInnerScope() }
|
ClassAttributeAssignmentNode() { this.getScope() = any(ClassExpr c).getInnerScope() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,7 +248,7 @@ abstract class AttrRead extends AttrRef, Node, LocalSourceNode {
|
|||||||
|
|
||||||
/** A simple attribute read, e.g. `object.attr` */
|
/** A simple attribute read, e.g. `object.attr` */
|
||||||
private class AttributeReadAsAttrRead extends AttrRead, CfgNode {
|
private class AttributeReadAsAttrRead extends AttrRead, CfgNode {
|
||||||
override Cfg::AttrNode node;
|
override AttrNode node;
|
||||||
|
|
||||||
AttributeReadAsAttrRead() { node.isLoad() }
|
AttributeReadAsAttrRead() { node.isLoad() }
|
||||||
|
|
||||||
@@ -286,7 +285,7 @@ private class GetAttrCallAsAttrRead extends AttrRead, CfgNode {
|
|||||||
* is treated as if it is a read of the attribute `module.attr`, even if `module` is not imported directly.
|
* is treated as if it is a read of the attribute `module.attr`, even if `module` is not imported directly.
|
||||||
*/
|
*/
|
||||||
private class ModuleAttributeImportAsAttrRead extends AttrRead, CfgNode {
|
private class ModuleAttributeImportAsAttrRead extends AttrRead, CfgNode {
|
||||||
override Cfg::ImportMemberNode node;
|
override ImportMemberNode node;
|
||||||
|
|
||||||
override Node getObject() { result.asCfgNode() = node.getModule(_) }
|
override Node getObject() { result.asCfgNode() = node.getModule(_) }
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ overlay[local]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.dataflow.new.internal.ImportStar
|
private import semmle.python.dataflow.new.internal.ImportStar
|
||||||
|
|
||||||
@@ -68,7 +67,7 @@ module Builtins {
|
|||||||
DataFlow::CfgNode likelyBuiltin(string name) {
|
DataFlow::CfgNode likelyBuiltin(string name) {
|
||||||
exists(Module m |
|
exists(Module m |
|
||||||
result.getNode() =
|
result.getNode() =
|
||||||
any(Cfg::NameNode n |
|
any(NameNode n |
|
||||||
possible_builtin_accessed_in_module(n, name, m) and
|
possible_builtin_accessed_in_module(n, name, m) and
|
||||||
not possible_builtin_defined_in_module(name, m)
|
not possible_builtin_defined_in_module(name, m)
|
||||||
)
|
)
|
||||||
@@ -88,7 +87,7 @@ module Builtins {
|
|||||||
* Holds if `n` is an access of a global variable called `name` (which is also the name of a
|
* Holds if `n` is an access of a global variable called `name` (which is also the name of a
|
||||||
* built-in) inside the module `m`.
|
* built-in) inside the module `m`.
|
||||||
*/
|
*/
|
||||||
private predicate possible_builtin_accessed_in_module(Cfg::NameNode n, string name, Module m) {
|
private predicate possible_builtin_accessed_in_module(NameNode n, string name, Module m) {
|
||||||
n.isGlobal() and
|
n.isGlobal() and
|
||||||
n.isLoad() and
|
n.isLoad() and
|
||||||
name = n.getId() and
|
name = n.getId() and
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
* what callable this call might end up targeting.
|
* what callable this call might end up targeting.
|
||||||
*
|
*
|
||||||
* Specifically this means that we cannot use type-backtrackers from the function of a
|
* Specifically this means that we cannot use type-backtrackers from the function of a
|
||||||
* `Cfg::CallNode`, since there is no `Cfg::CallNode` to backtrack from for `func` in the example
|
* `CallNode`, since there is no `CallNode` to backtrack from for `func` in the example
|
||||||
* above.
|
* above.
|
||||||
*
|
*
|
||||||
* Note: This hasn't been 100% realized yet, so we don't currently expose a predicate to
|
* Note: This hasn't been 100% realized yet, so we don't currently expose a predicate to
|
||||||
@@ -35,7 +35,6 @@ overlay[local?]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import DataFlowPublic
|
private import DataFlowPublic
|
||||||
private import DataFlowPrivate
|
private import DataFlowPrivate
|
||||||
private import FlowSummaryImpl as FlowSummaryImpl
|
private import FlowSummaryImpl as FlowSummaryImpl
|
||||||
@@ -163,7 +162,7 @@ newtype TArgumentPosition =
|
|||||||
*/
|
*/
|
||||||
TLambdaSelfArgumentPosition() or
|
TLambdaSelfArgumentPosition() or
|
||||||
TPositionalArgumentPosition(int index) {
|
TPositionalArgumentPosition(int index) {
|
||||||
exists(any(Cfg::CallNode c).getArg(index))
|
exists(any(CallNode c).getArg(index))
|
||||||
or
|
or
|
||||||
// since synthetic calls within a summarized callable could use a unique argument
|
// since synthetic calls within a summarized callable could use a unique argument
|
||||||
// position, we need to ensure we make these available (these are specified as
|
// position, we need to ensure we make these available (these are specified as
|
||||||
@@ -175,7 +174,7 @@ newtype TArgumentPosition =
|
|||||||
index = 0
|
index = 0
|
||||||
} or
|
} or
|
||||||
TKeywordArgumentPosition(string name) {
|
TKeywordArgumentPosition(string name) {
|
||||||
exists(any(Cfg::CallNode c).getArgByName(name))
|
exists(any(CallNode c).getArgByName(name))
|
||||||
or
|
or
|
||||||
// see comment for TPositionalArgumentPosition
|
// see comment for TPositionalArgumentPosition
|
||||||
FlowSummaryImpl::ParsePositions::isParsedKeywordParameterPosition(_, name)
|
FlowSummaryImpl::ParsePositions::isParsedKeywordParameterPosition(_, name)
|
||||||
@@ -298,12 +297,10 @@ predicate hasPropertyDecorator(Function func) {
|
|||||||
*/
|
*/
|
||||||
overlay[local]
|
overlay[local]
|
||||||
predicate hasContextmanagerDecorator(Function func) {
|
predicate hasContextmanagerDecorator(Function func) {
|
||||||
exists(Cfg::ControlFlowNode contextmanager |
|
exists(ControlFlowNode contextmanager |
|
||||||
contextmanager.(Cfg::NameNode).getId() = "contextmanager" and
|
contextmanager.(NameNode).getId() = "contextmanager" and contextmanager.(NameNode).isGlobal()
|
||||||
contextmanager.(Cfg::NameNode).isGlobal()
|
|
||||||
or
|
or
|
||||||
contextmanager.(Cfg::AttrNode).getObject("contextmanager").(Cfg::NameNode).getId() =
|
contextmanager.(AttrNode).getObject("contextmanager").(NameNode).getId() = "contextlib"
|
||||||
"contextlib"
|
|
||||||
|
|
|
|
||||||
func.getADecorator() = contextmanager.getNode()
|
func.getADecorator() = contextmanager.getNode()
|
||||||
)
|
)
|
||||||
@@ -319,10 +316,10 @@ predicate hasContextmanagerDecorator(Function func) {
|
|||||||
*/
|
*/
|
||||||
overlay[local]
|
overlay[local]
|
||||||
private predicate hasOverloadDecorator(Function func) {
|
private predicate hasOverloadDecorator(Function func) {
|
||||||
exists(Cfg::ControlFlowNode overload |
|
exists(ControlFlowNode overload |
|
||||||
overload.(Cfg::NameNode).getId() = "overload" and overload.(Cfg::NameNode).isGlobal()
|
overload.(NameNode).getId() = "overload" and overload.(NameNode).isGlobal()
|
||||||
or
|
or
|
||||||
overload.(Cfg::AttrNode).getObject("overload").(Cfg::NameNode).isGlobal()
|
overload.(AttrNode).getObject("overload").(NameNode).isGlobal()
|
||||||
|
|
|
|
||||||
func.getADecorator() = overload.getNode()
|
func.getADecorator() = overload.getNode()
|
||||||
)
|
)
|
||||||
@@ -541,7 +538,7 @@ class LibraryCallableValue extends DataFlowCallable, TLibraryCallable {
|
|||||||
// =============================================================================
|
// =============================================================================
|
||||||
/** Gets a call to `type`. */
|
/** Gets a call to `type`. */
|
||||||
private CallCfgNode getTypeCall() {
|
private CallCfgNode getTypeCall() {
|
||||||
exists(Cfg::NameNode id | id.getId() = "type" and id.isGlobal() |
|
exists(NameNode id | id.getId() = "type" and id.isGlobal() |
|
||||||
result.getFunction().asCfgNode() = id
|
result.getFunction().asCfgNode() = id
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -553,7 +550,7 @@ private CallCfgNode getSuperCall() {
|
|||||||
// link below), but otherwise only 2 edgecases. Overall it seems ok to ignore this complexity.
|
// link below), but otherwise only 2 edgecases. Overall it seems ok to ignore this complexity.
|
||||||
//
|
//
|
||||||
// https://github.com/python/cpython/blob/18b1782192f85bd26db89f5bc850f8bee4247c1a/Lib/unittest/mock.py#L48-L50
|
// https://github.com/python/cpython/blob/18b1782192f85bd26db89f5bc850f8bee4247c1a/Lib/unittest/mock.py#L48-L50
|
||||||
exists(Cfg::NameNode id | id.getId() = "super" and id.isGlobal() |
|
exists(NameNode id | id.getId() = "super" and id.isGlobal() |
|
||||||
result.getFunction().asCfgNode() = id
|
result.getFunction().asCfgNode() = id
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1039,7 +1036,7 @@ private module MethodCalls {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate directCall(
|
private predicate directCall(
|
||||||
Cfg::CallNode call, Function target, string functionName, Class cls, AttrRead attr, Node self
|
CallNode call, Function target, string functionName, Class cls, AttrRead attr, Node self
|
||||||
) {
|
) {
|
||||||
target = findFunctionAccordingToMroKnownStartingClass(cls, functionName) and
|
target = findFunctionAccordingToMroKnownStartingClass(cls, functionName) and
|
||||||
directCall_join(call, functionName, cls, attr, self)
|
directCall_join(call, functionName, cls, attr, self)
|
||||||
@@ -1048,7 +1045,7 @@ private module MethodCalls {
|
|||||||
/** Extracted to give good join order */
|
/** Extracted to give good join order */
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate directCall_join(
|
private predicate directCall_join(
|
||||||
Cfg::CallNode call, string functionName, Class cls, AttrRead attr, Node self
|
CallNode call, string functionName, Class cls, AttrRead attr, Node self
|
||||||
) {
|
) {
|
||||||
call.getFunction() = attrReadTracker(attr).asCfgNode() and
|
call.getFunction() = attrReadTracker(attr).asCfgNode() and
|
||||||
attr.accesses(self, functionName) and
|
attr.accesses(self, functionName) and
|
||||||
@@ -1065,7 +1062,7 @@ private module MethodCalls {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate callWithinMethodImplicitSelfOrCls(
|
private predicate callWithinMethodImplicitSelfOrCls(
|
||||||
Cfg::CallNode call, Function target, string functionName, Class classWithMethod, AttrRead attr,
|
CallNode call, Function target, string functionName, Class classWithMethod, AttrRead attr,
|
||||||
Node self
|
Node self
|
||||||
) {
|
) {
|
||||||
target = findFunctionAccordingToMro(getADirectSubclass*(classWithMethod), functionName) and
|
target = findFunctionAccordingToMro(getADirectSubclass*(classWithMethod), functionName) and
|
||||||
@@ -1075,7 +1072,7 @@ private module MethodCalls {
|
|||||||
/** Extracted to give good join order */
|
/** Extracted to give good join order */
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate callWithinMethodImplicitSelfOrCls_join(
|
private predicate callWithinMethodImplicitSelfOrCls_join(
|
||||||
Cfg::CallNode call, string functionName, Class classWithMethod, AttrRead attr, Node self
|
CallNode call, string functionName, Class classWithMethod, AttrRead attr, Node self
|
||||||
) {
|
) {
|
||||||
call.getFunction() = attrReadTracker(attr).asCfgNode() and
|
call.getFunction() = attrReadTracker(attr).asCfgNode() and
|
||||||
attr.accesses(self, functionName) and
|
attr.accesses(self, functionName) and
|
||||||
@@ -1087,7 +1084,7 @@ private module MethodCalls {
|
|||||||
* resolve the call to a known target (since the only super class might be the
|
* resolve the call to a known target (since the only super class might be the
|
||||||
* builtin `object`, so we never have the implementation of `__new__` in the DB).
|
* builtin `object`, so we never have the implementation of `__new__` in the DB).
|
||||||
*/
|
*/
|
||||||
predicate fromSuperNewCall(Cfg::CallNode call, Class classUsedInSuper, AttrRead attr, Node self) {
|
predicate fromSuperNewCall(CallNode call, Class classUsedInSuper, AttrRead attr, Node self) {
|
||||||
fromSuper_join(call, "__new__", classUsedInSuper, attr, self) and
|
fromSuper_join(call, "__new__", classUsedInSuper, attr, self) and
|
||||||
self in [classTracker(_), clsArgumentTracker(_)]
|
self in [classTracker(_), clsArgumentTracker(_)]
|
||||||
}
|
}
|
||||||
@@ -1109,7 +1106,7 @@ private module MethodCalls {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate fromSuper(
|
predicate fromSuper(
|
||||||
Cfg::CallNode call, Function target, string functionName, Class classUsedInSuper, AttrRead attr,
|
CallNode call, Function target, string functionName, Class classUsedInSuper, AttrRead attr,
|
||||||
Node self
|
Node self
|
||||||
) {
|
) {
|
||||||
target = findFunctionAccordingToMro(getNextClassInMro(classUsedInSuper), functionName) and
|
target = findFunctionAccordingToMro(getNextClassInMro(classUsedInSuper), functionName) and
|
||||||
@@ -1119,7 +1116,7 @@ private module MethodCalls {
|
|||||||
/** Extracted to give good join order */
|
/** Extracted to give good join order */
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fromSuper_join(
|
private predicate fromSuper_join(
|
||||||
Cfg::CallNode call, string functionName, Class classUsedInSuper, AttrRead attr, Node self
|
CallNode call, string functionName, Class classUsedInSuper, AttrRead attr, Node self
|
||||||
) {
|
) {
|
||||||
call.getFunction() = attrReadTracker(attr).asCfgNode() and
|
call.getFunction() = attrReadTracker(attr).asCfgNode() and
|
||||||
(
|
(
|
||||||
@@ -1138,7 +1135,7 @@ private module MethodCalls {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate resolveMethodCall(Cfg::CallNode call, Function target, CallType type, Node self) {
|
predicate resolveMethodCall(CallNode call, Function target, CallType type, Node self) {
|
||||||
(
|
(
|
||||||
directCall(call, target, _, _, _, self)
|
directCall(call, target, _, _, _, self)
|
||||||
or
|
or
|
||||||
@@ -1185,7 +1182,7 @@ import MethodCalls
|
|||||||
* NOTE: We have this predicate mostly to be able to compare with old point-to
|
* NOTE: We have this predicate mostly to be able to compare with old point-to
|
||||||
* call-graph resolution. So it could be removed in the future.
|
* call-graph resolution. So it could be removed in the future.
|
||||||
*/
|
*/
|
||||||
predicate resolveClassCall(Cfg::CallNode call, Class cls) {
|
predicate resolveClassCall(CallNode call, Class cls) {
|
||||||
call.getFunction() = classTracker(cls).asCfgNode()
|
call.getFunction() = classTracker(cls).asCfgNode()
|
||||||
or
|
or
|
||||||
// `cls()` inside a classmethod (which also contains `type(self)()` inside a method)
|
// `cls()` inside a classmethod (which also contains `type(self)()` inside a method)
|
||||||
@@ -1215,7 +1212,7 @@ Function invokedFunctionFromClassConstruction(Class cls, string funcName) {
|
|||||||
*
|
*
|
||||||
* See https://docs.python.org/3/reference/datamodel.html#object.__call__
|
* See https://docs.python.org/3/reference/datamodel.html#object.__call__
|
||||||
*/
|
*/
|
||||||
predicate resolveClassInstanceCall(Cfg::CallNode call, Function target, Node self) {
|
predicate resolveClassInstanceCall(CallNode call, Function target, Node self) {
|
||||||
exists(Class cls |
|
exists(Class cls |
|
||||||
call.getFunction() = classInstanceTracker(cls).asCfgNode() and
|
call.getFunction() = classInstanceTracker(cls).asCfgNode() and
|
||||||
target = findFunctionAccordingToMroKnownStartingClass(cls, "__call__")
|
target = findFunctionAccordingToMroKnownStartingClass(cls, "__call__")
|
||||||
@@ -1234,7 +1231,7 @@ predicate resolveClassInstanceCall(Cfg::CallNode call, Function target, Node sel
|
|||||||
* Holds if `call` is a call to the `target`, with call-type `type`.
|
* Holds if `call` is a call to the `target`, with call-type `type`.
|
||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
predicate resolveCall(Cfg::CallNode call, Function target, CallType type) {
|
predicate resolveCall(CallNode call, Function target, CallType type) {
|
||||||
Stages::DataFlow::ref() and
|
Stages::DataFlow::ref() and
|
||||||
(
|
(
|
||||||
type instanceof CallTypePlainFunction and
|
type instanceof CallTypePlainFunction and
|
||||||
@@ -1259,11 +1256,11 @@ predicate resolveCall(Cfg::CallNode call, Function target, CallType type) {
|
|||||||
// =============================================================================
|
// =============================================================================
|
||||||
/**
|
/**
|
||||||
* Holds if the argument of `call` at position `apos` is `arg`. This is just a helper
|
* Holds if the argument of `call` at position `apos` is `arg`. This is just a helper
|
||||||
* predicate that maps ArgumentPositions to the arguments of the underlying `Cfg::CallNode`.
|
* predicate that maps ArgumentPositions to the arguments of the underlying `CallNode`.
|
||||||
*/
|
*/
|
||||||
overlay[local]
|
overlay[local]
|
||||||
cached
|
cached
|
||||||
predicate normalCallArg(Cfg::CallNode call, Node arg, ArgumentPosition apos) {
|
predicate normalCallArg(CallNode call, Node arg, ArgumentPosition apos) {
|
||||||
exists(int index |
|
exists(int index |
|
||||||
apos.isPositional(index) and
|
apos.isPositional(index) and
|
||||||
arg.asCfgNode() = call.getArg(index)
|
arg.asCfgNode() = call.getArg(index)
|
||||||
@@ -1278,7 +1275,7 @@ predicate normalCallArg(Cfg::CallNode call, Node arg, ArgumentPosition apos) {
|
|||||||
exists(int index |
|
exists(int index |
|
||||||
apos.isStarArgs(index) and
|
apos.isStarArgs(index) and
|
||||||
arg.asCfgNode() = call.getStarArg() and
|
arg.asCfgNode() = call.getStarArg() and
|
||||||
// since `Cfg::CallNode.getArg` doesn't include `*args`, we need to drop to the AST level
|
// since `CallNode.getArg` doesn't include `*args`, we need to drop to the AST level
|
||||||
// to get the index. Notice that we only use the AST for getting the index, so we
|
// to get the index. Notice that we only use the AST for getting the index, so we
|
||||||
// don't need to check for dominance in regards to splitting.
|
// don't need to check for dominance in regards to splitting.
|
||||||
call.getStarArg().getNode() = call.getNode().getPositionalArg(index).(Starred).getValue()
|
call.getStarArg().getNode() = call.getNode().getPositionalArg(index).(Starred).getValue()
|
||||||
@@ -1352,9 +1349,7 @@ predicate normalCallArg(Cfg::CallNode call, Node arg, ArgumentPosition apos) {
|
|||||||
* translated into `l.clear()`, and we can still have use-use flow.
|
* translated into `l.clear()`, and we can still have use-use flow.
|
||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
predicate getCallArg(
|
predicate getCallArg(CallNode call, Function target, CallType type, Node arg, ArgumentPosition apos) {
|
||||||
Cfg::CallNode call, Function target, CallType type, Node arg, ArgumentPosition apos
|
|
||||||
) {
|
|
||||||
Stages::DataFlow::ref() and
|
Stages::DataFlow::ref() and
|
||||||
resolveCall(call, target, type) and
|
resolveCall(call, target, type) and
|
||||||
(
|
(
|
||||||
@@ -1447,12 +1442,10 @@ private predicate sameEnclosingCallable(Node node1, Node node2) {
|
|||||||
// DataFlowCall
|
// DataFlowCall
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
newtype TDataFlowCall =
|
newtype TDataFlowCall =
|
||||||
TNormalCall(Cfg::CallNode call, Function target, CallType type) {
|
TNormalCall(CallNode call, Function target, CallType type) { resolveCall(call, target, type) } or
|
||||||
call.injects(_) and resolveCall(call, target, type)
|
|
||||||
} or
|
|
||||||
/** A call to the generated function inside a comprehension */
|
/** A call to the generated function inside a comprehension */
|
||||||
TComprehensionCall(Comp c) or
|
TComprehensionCall(Comp c) or
|
||||||
TPotentialLibraryCall(Cfg::CallNode call) { call.injects(_) } or
|
TPotentialLibraryCall(CallNode call) or
|
||||||
/** A synthesized call inside a summarized callable */
|
/** A synthesized call inside a summarized callable */
|
||||||
TSummaryCall(
|
TSummaryCall(
|
||||||
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
|
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
|
||||||
@@ -1472,7 +1465,7 @@ abstract class DataFlowCall extends TDataFlowCall {
|
|||||||
abstract ArgumentNode getArgument(ArgumentPosition apos);
|
abstract ArgumentNode getArgument(ArgumentPosition apos);
|
||||||
|
|
||||||
/** Get the control flow node representing this call, if any. */
|
/** Get the control flow node representing this call, if any. */
|
||||||
abstract Cfg::ControlFlowNode getNode();
|
abstract ControlFlowNode getNode();
|
||||||
|
|
||||||
/** Gets the enclosing callable of this call. */
|
/** Gets the enclosing callable of this call. */
|
||||||
DataFlowCallable getEnclosingCallable() { result = getCallableScope(this.getScope()) }
|
DataFlowCallable getEnclosingCallable() { result = getCallableScope(this.getScope()) }
|
||||||
@@ -1503,28 +1496,28 @@ abstract class ExtractedDataFlowCall extends DataFlowCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A resolved call in source code with an underlying `Cfg::CallNode`.
|
* A resolved call in source code with an underlying `CallNode`.
|
||||||
*
|
*
|
||||||
* This is considered normal, compared with special calls such as `obj[0]` calling the
|
* This is considered normal, compared with special calls such as `obj[0]` calling the
|
||||||
* `__getitem__` method on the object. However, this also includes calls that go to the
|
* `__getitem__` method on the object. However, this also includes calls that go to the
|
||||||
* `__call__` special method.
|
* `__call__` special method.
|
||||||
*/
|
*/
|
||||||
class NormalCall extends ExtractedDataFlowCall, TNormalCall {
|
class NormalCall extends ExtractedDataFlowCall, TNormalCall {
|
||||||
Cfg::CallNode call;
|
CallNode call;
|
||||||
Function target;
|
Function target;
|
||||||
CallType type;
|
CallType type;
|
||||||
|
|
||||||
NormalCall() { this = TNormalCall(call, target, type) }
|
NormalCall() { this = TNormalCall(call, target, type) }
|
||||||
|
|
||||||
override string toString() {
|
override string toString() {
|
||||||
// note: if we used toString directly on the Cfg::CallNode we would get
|
// note: if we used toString directly on the CallNode we would get
|
||||||
// `Cfg::ControlFlowNode for func()`
|
// `ControlFlowNode for func()`
|
||||||
// but the `Cfg::ControlFlowNode` part is just clutter, so we go directly to the AST node
|
// but the `ControlFlowNode` part is just clutter, so we go directly to the AST node
|
||||||
// instead.
|
// instead.
|
||||||
result = call.getNode().toString()
|
result = call.getNode().toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
override Cfg::ControlFlowNode getNode() { result = call }
|
override ControlFlowNode getNode() { result = call }
|
||||||
|
|
||||||
override Scope getScope() { result = call.getScope() }
|
override Scope getScope() { result = call.getScope() }
|
||||||
|
|
||||||
@@ -1552,7 +1545,7 @@ class ComprehensionCall extends ExtractedDataFlowCall, TComprehensionCall {
|
|||||||
|
|
||||||
override string toString() { result = "comprehension call" }
|
override string toString() { result = "comprehension call" }
|
||||||
|
|
||||||
override Cfg::ControlFlowNode getNode() { result.getNode() = c }
|
override ControlFlowNode getNode() { result.getNode() = c }
|
||||||
|
|
||||||
override Scope getScope() { result = c.getScope() }
|
override Scope getScope() { result = c.getScope() }
|
||||||
|
|
||||||
@@ -1575,14 +1568,14 @@ class ComprehensionCall extends ExtractedDataFlowCall, TComprehensionCall {
|
|||||||
* in this class.
|
* in this class.
|
||||||
*/
|
*/
|
||||||
class PotentialLibraryCall extends ExtractedDataFlowCall, TPotentialLibraryCall {
|
class PotentialLibraryCall extends ExtractedDataFlowCall, TPotentialLibraryCall {
|
||||||
Cfg::CallNode call;
|
CallNode call;
|
||||||
|
|
||||||
PotentialLibraryCall() { this = TPotentialLibraryCall(call) }
|
PotentialLibraryCall() { this = TPotentialLibraryCall(call) }
|
||||||
|
|
||||||
override string toString() {
|
override string toString() {
|
||||||
// note: if we used toString directly on the Cfg::CallNode we would get
|
// note: if we used toString directly on the CallNode we would get
|
||||||
// `Cfg::ControlFlowNode for func()`
|
// `ControlFlowNode for func()`
|
||||||
// but the `Cfg::ControlFlowNode` part is just clutter, so we go directly to the AST node
|
// but the `ControlFlowNode` part is just clutter, so we go directly to the AST node
|
||||||
// instead.
|
// instead.
|
||||||
result = call.getNode().toString()
|
result = call.getNode().toString()
|
||||||
}
|
}
|
||||||
@@ -1599,10 +1592,10 @@ class PotentialLibraryCall extends ExtractedDataFlowCall, TPotentialLibraryCall
|
|||||||
// potential self argument, from `foo.bar()` -- note that this could also just be a
|
// potential self argument, from `foo.bar()` -- note that this could also just be a
|
||||||
// module reference, but we really don't have a good way of knowing :|
|
// module reference, but we really don't have a good way of knowing :|
|
||||||
apos.isSelf() and
|
apos.isSelf() and
|
||||||
result.asCfgNode() = call.getFunction().(Cfg::AttrNode).getObject()
|
result.asCfgNode() = call.getFunction().(AttrNode).getObject()
|
||||||
}
|
}
|
||||||
|
|
||||||
override Cfg::ControlFlowNode getNode() { result = call }
|
override ControlFlowNode getNode() { result = call }
|
||||||
|
|
||||||
override Scope getScope() { result = call.getScope() }
|
override Scope getScope() { result = call.getScope() }
|
||||||
}
|
}
|
||||||
@@ -1634,7 +1627,7 @@ class SummaryCall extends DataFlowCall, TSummaryCall {
|
|||||||
|
|
||||||
override ArgumentNode getArgument(ArgumentPosition apos) { none() }
|
override ArgumentNode getArgument(ArgumentPosition apos) { none() }
|
||||||
|
|
||||||
override Cfg::ControlFlowNode getNode() { none() }
|
override ControlFlowNode getNode() { none() }
|
||||||
|
|
||||||
override string toString() { result = "[summary] call to " + receiver + " in " + c }
|
override string toString() { result = "[summary] call to " + receiver + " in " + c }
|
||||||
|
|
||||||
@@ -1776,12 +1769,12 @@ private class SummaryPostUpdateNode extends FlowSummaryNode, PostUpdateNodeImpl
|
|||||||
* This is used for tracking flow through captured variables.
|
* This is used for tracking flow through captured variables.
|
||||||
*/
|
*/
|
||||||
class SynthCapturedVariablesArgumentNode extends Node, TSynthCapturedVariablesArgumentNode {
|
class SynthCapturedVariablesArgumentNode extends Node, TSynthCapturedVariablesArgumentNode {
|
||||||
Cfg::ControlFlowNode callable;
|
ControlFlowNode callable;
|
||||||
|
|
||||||
SynthCapturedVariablesArgumentNode() { this = TSynthCapturedVariablesArgumentNode(callable) }
|
SynthCapturedVariablesArgumentNode() { this = TSynthCapturedVariablesArgumentNode(callable) }
|
||||||
|
|
||||||
/** Gets the `Cfg::CallNode` corresponding to this captured variables argument node. */
|
/** Gets the `CallNode` corresponding to this captured variables argument node. */
|
||||||
Cfg::CallNode getCallNode() { result.getFunction() = callable }
|
CallNode getCallNode() { result.getFunction() = callable }
|
||||||
|
|
||||||
/** Gets the `CfgNode` that corresponds to this synthetic node. */
|
/** Gets the `CfgNode` that corresponds to this synthetic node. */
|
||||||
CfgNode getUnderlyingNode() { result.asCfgNode() = callable }
|
CfgNode getUnderlyingNode() { result.asCfgNode() = callable }
|
||||||
@@ -1799,7 +1792,7 @@ class CapturedVariablesArgumentNodeAsArgumentNode extends ArgumentNode,
|
|||||||
{
|
{
|
||||||
overlay[global]
|
overlay[global]
|
||||||
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
||||||
exists(Cfg::CallNode callNode | callNode = this.getCallNode() |
|
exists(CallNode callNode | callNode = this.getCallNode() |
|
||||||
callNode = call.getNode() and
|
callNode = call.getNode() and
|
||||||
exists(Function target | resolveCall(callNode, target, _) |
|
exists(Function target | resolveCall(callNode, target, _) |
|
||||||
target = any(VariableCapture::CapturedVariable v).getACapturingScope()
|
target = any(VariableCapture::CapturedVariable v).getACapturingScope()
|
||||||
@@ -1813,7 +1806,7 @@ class CapturedVariablesArgumentNodeAsArgumentNode extends ArgumentNode,
|
|||||||
class SynthCapturedVariablesArgumentPostUpdateNode extends PostUpdateNodeImpl,
|
class SynthCapturedVariablesArgumentPostUpdateNode extends PostUpdateNodeImpl,
|
||||||
TSynthCapturedVariablesArgumentPostUpdateNode
|
TSynthCapturedVariablesArgumentPostUpdateNode
|
||||||
{
|
{
|
||||||
Cfg::ControlFlowNode callable;
|
ControlFlowNode callable;
|
||||||
|
|
||||||
SynthCapturedVariablesArgumentPostUpdateNode() {
|
SynthCapturedVariablesArgumentPostUpdateNode() {
|
||||||
this = TSynthCapturedVariablesArgumentPostUpdateNode(callable)
|
this = TSynthCapturedVariablesArgumentPostUpdateNode(callable)
|
||||||
|
|||||||
@@ -2,9 +2,8 @@ overlay[local?]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import DataFlowPublic
|
private import DataFlowPublic
|
||||||
private import semmle.python.dataflow.new.internal.SsaImpl as SsaImpl
|
private import semmle.python.essa.SsaCompute
|
||||||
private import semmle.python.dataflow.new.internal.ImportResolution
|
private import semmle.python.dataflow.new.internal.ImportResolution
|
||||||
private import FlowSummaryImpl as FlowSummaryImpl
|
private import FlowSummaryImpl as FlowSummaryImpl
|
||||||
private import semmle.python.frameworks.data.ModelsAsData
|
private import semmle.python.frameworks.data.ModelsAsData
|
||||||
@@ -44,28 +43,13 @@ predicate isArgumentNode(ArgumentNode arg, DataFlowCall c, ArgumentPosition pos)
|
|||||||
// Nodes
|
// Nodes
|
||||||
//--------
|
//--------
|
||||||
overlay[local]
|
overlay[local]
|
||||||
predicate isExpressionNode(Cfg::ControlFlowNode node) {
|
predicate isExpressionNode(ControlFlowNode node) { node.getNode() instanceof Expr }
|
||||||
// Restrict to the `injects` representative so the dataflow layer creates
|
|
||||||
// exactly one `TCfgNode` per AST expression.
|
|
||||||
node.injects(_) and
|
|
||||||
(
|
|
||||||
node.getNode() instanceof Expr
|
|
||||||
or
|
|
||||||
// `Cfg::ForNode` wraps a `For` statement's iter position, but
|
|
||||||
// overrides `.getNode()` to return the `Py::For` statement (for
|
|
||||||
// legacy parity). The underlying AST is still an `Expr` (the iter
|
|
||||||
// expression); we want a dataflow node here so that for-loop
|
|
||||||
// content reads (`for y in l`) have a source expression node to
|
|
||||||
// read content from.
|
|
||||||
node instanceof Cfg::ForNode
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// SyntheticPreUpdateNode
|
// SyntheticPreUpdateNode
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
class SyntheticPreUpdateNode extends Node, TSyntheticPreUpdateNode {
|
class SyntheticPreUpdateNode extends Node, TSyntheticPreUpdateNode {
|
||||||
Cfg::CallNode node;
|
CallNode node;
|
||||||
|
|
||||||
SyntheticPreUpdateNode() { this = TSyntheticPreUpdateNode(node) }
|
SyntheticPreUpdateNode() { this = TSyntheticPreUpdateNode(node) }
|
||||||
|
|
||||||
@@ -167,7 +151,7 @@ predicate synthStarArgsElementParameterNodeStoreStep(
|
|||||||
* been passed in a `**kwargs` argument.
|
* been passed in a `**kwargs` argument.
|
||||||
*/
|
*/
|
||||||
class SynthDictSplatArgumentNode extends Node, TSynthDictSplatArgumentNode {
|
class SynthDictSplatArgumentNode extends Node, TSynthDictSplatArgumentNode {
|
||||||
Cfg::CallNode node;
|
CallNode node;
|
||||||
|
|
||||||
SynthDictSplatArgumentNode() { this = TSynthDictSplatArgumentNode(node) }
|
SynthDictSplatArgumentNode() { this = TSynthDictSplatArgumentNode(node) }
|
||||||
|
|
||||||
@@ -181,7 +165,7 @@ class SynthDictSplatArgumentNode extends Node, TSynthDictSplatArgumentNode {
|
|||||||
private predicate synthDictSplatArgumentNodeStoreStep(
|
private predicate synthDictSplatArgumentNodeStoreStep(
|
||||||
ArgumentNode nodeFrom, DictionaryElementContent c, SynthDictSplatArgumentNode nodeTo
|
ArgumentNode nodeFrom, DictionaryElementContent c, SynthDictSplatArgumentNode nodeTo
|
||||||
) {
|
) {
|
||||||
exists(string name, Cfg::CallNode call, ArgumentPosition keywordPos |
|
exists(string name, CallNode call, ArgumentPosition keywordPos |
|
||||||
nodeTo = TSynthDictSplatArgumentNode(call) and
|
nodeTo = TSynthDictSplatArgumentNode(call) and
|
||||||
getCallArg(call, _, _, nodeFrom, keywordPos) and
|
getCallArg(call, _, _, nodeFrom, keywordPos) and
|
||||||
keywordPos.isKeyword(name) and
|
keywordPos.isKeyword(name) and
|
||||||
@@ -305,7 +289,7 @@ abstract class PostUpdateNodeImpl extends Node {
|
|||||||
* Synthetic post-update nodes for synthetic nodes need to be listed one by one.
|
* Synthetic post-update nodes for synthetic nodes need to be listed one by one.
|
||||||
*/
|
*/
|
||||||
class SyntheticPostUpdateNode extends PostUpdateNodeImpl, TSyntheticPostUpdateNode {
|
class SyntheticPostUpdateNode extends PostUpdateNodeImpl, TSyntheticPostUpdateNode {
|
||||||
Cfg::ControlFlowNode node;
|
ControlFlowNode node;
|
||||||
|
|
||||||
SyntheticPostUpdateNode() { this = TSyntheticPostUpdateNode(node) }
|
SyntheticPostUpdateNode() { this = TSyntheticPostUpdateNode(node) }
|
||||||
|
|
||||||
@@ -349,42 +333,16 @@ module LocalFlow {
|
|||||||
// `x = f(42)`
|
// `x = f(42)`
|
||||||
// nodeFrom is `f(42)`
|
// nodeFrom is `f(42)`
|
||||||
// nodeTo is `x`
|
// nodeTo is `x`
|
||||||
//
|
exists(AssignmentDefinition def |
|
||||||
// We use the CFG-level `DefinitionNode.getValue()` directly rather
|
|
||||||
// than going through SSA, because the new SSA library prunes write
|
|
||||||
// definitions that have no subsequent read in the same scope (e.g.
|
|
||||||
// a module-level `def f():` whose `f` is only read inside other
|
|
||||||
// functions). The CFG-level link is unconditional.
|
|
||||||
//
|
|
||||||
// The Name-target restriction mirrors legacy ESSA's
|
|
||||||
// `SsaDefinitions::assignment_definition`, which required
|
|
||||||
// `defn.(NameNode).defines(v)`. Subscript and attribute writes
|
|
||||||
// (`x[i] = 42`, `obj.attr = 42`) are intentionally excluded — their
|
|
||||||
// value flow is handled by the content-flow / `AttrWrite` machinery,
|
|
||||||
// not by a local-flow step *into* the Subscript/Attribute expression.
|
|
||||||
// Excluding them is essential for keeping augmented-assignment
|
|
||||||
// targets (`x[i] += 42`) classifiable as `LocalSourceNode` on the
|
|
||||||
// read side: the single canonical CFG node is both a load and a
|
|
||||||
// store, and any incoming local-flow step would disqualify it from
|
|
||||||
// being a local source.
|
|
||||||
exists(Cfg::DefinitionNode def |
|
|
||||||
nodeFrom.(CfgNode).getNode() = def.getValue() and
|
nodeFrom.(CfgNode).getNode() = def.getValue() and
|
||||||
nodeTo.(CfgNode).getNode() = def and
|
nodeTo.(CfgNode).getNode() = def.getDefiningNode()
|
||||||
def instanceof Cfg::NameNode and
|
|
||||||
// Parameter defaults are evaluated in the enclosing scope, while the
|
|
||||||
// parameter itself lives in the function's scope. The cross-scope
|
|
||||||
// edge is provided by `runtimeJumpStep` instead.
|
|
||||||
not exists(Py::Parameter param | def.getNode() = param.asName())
|
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// With definition
|
// With definition
|
||||||
// `with f(42) as x:`
|
// `with f(42) as x:`
|
||||||
// nodeFrom is `f(42)`
|
// nodeFrom is `f(42)`
|
||||||
// nodeTo is `x`
|
// nodeTo is `x`
|
||||||
exists(
|
exists(With with, ControlFlowNode contextManager, WithDefinition withDef, ControlFlowNode var |
|
||||||
With with, Cfg::ControlFlowNode contextManager, SsaImpl::WithDefinition withDef,
|
|
||||||
Cfg::ControlFlowNode var
|
|
||||||
|
|
|
||||||
var = withDef.getDefiningNode()
|
var = withDef.getDefiningNode()
|
||||||
|
|
|
|
||||||
nodeFrom.(CfgNode).getNode() = contextManager and
|
nodeFrom.(CfgNode).getNode() = contextManager and
|
||||||
@@ -403,13 +361,13 @@ module LocalFlow {
|
|||||||
|
|
||||||
predicate expressionFlowStep(Node nodeFrom, Node nodeTo) {
|
predicate expressionFlowStep(Node nodeFrom, Node nodeTo) {
|
||||||
// If expressions
|
// If expressions
|
||||||
nodeFrom.asCfgNode() = nodeTo.asCfgNode().(Cfg::IfExprNode).getAnOperand()
|
nodeFrom.asCfgNode() = nodeTo.asCfgNode().(IfExprNode).getAnOperand()
|
||||||
or
|
or
|
||||||
// Assignment expressions
|
// Assignment expressions
|
||||||
nodeFrom.asCfgNode() = nodeTo.asCfgNode().(Cfg::AssignmentExprNode).getValue()
|
nodeFrom.asCfgNode() = nodeTo.asCfgNode().(AssignmentExprNode).getValue()
|
||||||
or
|
or
|
||||||
// boolean inline expressions such as `x or y` or `x and y`
|
// boolean inline expressions such as `x or y` or `x and y`
|
||||||
nodeFrom.asCfgNode() = nodeTo.asCfgNode().(Cfg::BoolExprNode).getAnOperand()
|
nodeFrom.asCfgNode() = nodeTo.asCfgNode().(BoolExprNode).getAnOperand()
|
||||||
or
|
or
|
||||||
// Flow inside an unpacking assignment
|
// Flow inside an unpacking assignment
|
||||||
iterableUnpackingFlowStep(nodeFrom, nodeTo)
|
iterableUnpackingFlowStep(nodeFrom, nodeTo)
|
||||||
@@ -418,25 +376,12 @@ module LocalFlow {
|
|||||||
matchFlowStep(nodeFrom, nodeTo)
|
matchFlowStep(nodeFrom, nodeTo)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate useToNextUse(Cfg::NameNode nodeFrom, Cfg::NameNode nodeTo) {
|
predicate useToNextUse(NameNode nodeFrom, NameNode nodeTo) {
|
||||||
// The SSA-level adjacent-use predicate works on specific CFG variants
|
AdjacentUses::adjacentUseUse(nodeFrom, nodeTo)
|
||||||
// (e.g. boolean-outcome `[true]`/`[false]` or emptiness `[empty]`/`[non-empty]`
|
|
||||||
// splits of the same AST node), but dataflow values are insensitive to
|
|
||||||
// those splits — there is at most one `CfgNode` per AST. Project both
|
|
||||||
// ends through `.getNode()` so all variants contribute their use-use
|
|
||||||
// edges to the canonical pair.
|
|
||||||
exists(Cfg::NameNode fromVariant, Cfg::NameNode toVariant |
|
|
||||||
SsaImpl::AdjacentUses::adjacentUseUse(fromVariant, toVariant) and
|
|
||||||
fromVariant.getNode() = nodeFrom.getNode() and
|
|
||||||
toVariant.getNode() = nodeTo.getNode()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate defToFirstUse(SsaImpl::EssaVariable var, Cfg::NameNode nodeTo) {
|
predicate defToFirstUse(EssaVariable var, NameNode nodeTo) {
|
||||||
exists(Cfg::NameNode toVariant |
|
AdjacentUses::firstUse(var.getDefinition(), nodeTo)
|
||||||
SsaImpl::AdjacentUses::firstUse(var.getDefinition(), toVariant) and
|
|
||||||
toVariant.getNode() = nodeTo.getNode()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate useUseFlowStep(Node nodeFrom, Node nodeTo) {
|
predicate useUseFlowStep(Node nodeFrom, Node nodeTo) {
|
||||||
@@ -445,13 +390,12 @@ module LocalFlow {
|
|||||||
// `x = f(y)`
|
// `x = f(y)`
|
||||||
// nodeFrom is `y` on first line
|
// nodeFrom is `y` on first line
|
||||||
// nodeTo is `y` on second line
|
// nodeTo is `y` on second line
|
||||||
exists(SsaImpl::EssaDefinition def, Cfg::NameNode toVariant |
|
exists(EssaDefinition def |
|
||||||
nodeFrom.(CfgNode).getNode() = def.(SsaImpl::EssaNodeDefinition).getDefiningNode()
|
nodeFrom.(CfgNode).getNode() = def.(EssaNodeDefinition).getDefiningNode()
|
||||||
or
|
or
|
||||||
nodeFrom.(ScopeEntryDefinitionNode).getDefinition() = def
|
nodeFrom.(ScopeEntryDefinitionNode).getDefinition() = def
|
||||||
|
|
|
|
||||||
SsaImpl::AdjacentUses::firstUse(def, toVariant) and
|
AdjacentUses::firstUse(def, nodeTo.(CfgNode).getNode())
|
||||||
toVariant.getNode() = nodeTo.(CfgNode).getNode().getNode()
|
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// Next use after use
|
// Next use after use
|
||||||
@@ -613,9 +557,9 @@ predicate runtimeJumpStep(Node nodeFrom, Node nodeTo) {
|
|||||||
// a parameter with a default value, since the parameter will be in the scope of the
|
// a parameter with a default value, since the parameter will be in the scope of the
|
||||||
// function, while the default value itself will be in the scope that _defines_ the
|
// function, while the default value itself will be in the scope that _defines_ the
|
||||||
// function.
|
// function.
|
||||||
exists(SsaImpl::ParameterDefinition param |
|
exists(ParameterDefinition param |
|
||||||
// note: we go to the _control-flow node_ of the parameter, and not the ESSA node of the parameter, since for type-tracking, the ESSA node is not a LocalSourceNode, so we would get in trouble.
|
// note: we go to the _control-flow node_ of the parameter, and not the ESSA node of the parameter, since for type-tracking, the ESSA node is not a LocalSourceNode, so we would get in trouble.
|
||||||
nodeFrom.asCfgNode().getNode() = param.getParameter().(Parameter).getDefault() and
|
nodeFrom.asCfgNode() = param.getDefault() and
|
||||||
nodeTo.asCfgNode() = param.getDefiningNode()
|
nodeTo.asCfgNode() = param.getDefiningNode()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -719,7 +663,7 @@ predicate neverSkipInPathGraph(Node n) {
|
|||||||
// ```
|
// ```
|
||||||
// we would end up saying that the path MUST not skip the x in `y = x`, which is just
|
// we would end up saying that the path MUST not skip the x in `y = x`, which is just
|
||||||
// annoying and doesn't help the path explanation become clearer.
|
// annoying and doesn't help the path explanation become clearer.
|
||||||
n.asCfgNode() = any(SsaImpl::EssaNodeDefinition def).getDefiningNode()
|
n.asCfgNode() = any(EssaNodeDefinition def).getDefiningNode()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -930,7 +874,7 @@ predicate listStoreStep(CfgNode nodeFrom, ListElementContent c, CfgNode nodeTo)
|
|||||||
// nodeFrom is `42`, cfg node
|
// nodeFrom is `42`, cfg node
|
||||||
// nodeTo is the list, `[..., 42, ...]`, cfg node
|
// nodeTo is the list, `[..., 42, ...]`, cfg node
|
||||||
// c denotes element of list
|
// c denotes element of list
|
||||||
nodeTo.getNode().(Cfg::ListNode).getAnElement() = nodeFrom.getNode() and
|
nodeTo.getNode().(ListNode).getAnElement() = nodeFrom.getNode() and
|
||||||
not nodeTo.getNode() instanceof UnpackingAssignmentSequenceTarget and
|
not nodeTo.getNode() instanceof UnpackingAssignmentSequenceTarget and
|
||||||
// Suppress unused variable warning
|
// Suppress unused variable warning
|
||||||
c = c
|
c = c
|
||||||
@@ -943,7 +887,7 @@ predicate setStoreStep(CfgNode nodeFrom, SetElementContent c, CfgNode nodeTo) {
|
|||||||
// nodeFrom is `42`, cfg node
|
// nodeFrom is `42`, cfg node
|
||||||
// nodeTo is the set, `{..., 42, ...}`, cfg node
|
// nodeTo is the set, `{..., 42, ...}`, cfg node
|
||||||
// c denotes element of list
|
// c denotes element of list
|
||||||
nodeTo.getNode().(Cfg::SetNode).getAnElement() = nodeFrom.getNode() and
|
nodeTo.getNode().(SetNode).getAnElement() = nodeFrom.getNode() and
|
||||||
// Suppress unused variable warning
|
// Suppress unused variable warning
|
||||||
c = c
|
c = c
|
||||||
}
|
}
|
||||||
@@ -956,7 +900,7 @@ predicate tupleStoreStep(CfgNode nodeFrom, TupleElementContent c, CfgNode nodeTo
|
|||||||
// nodeTo is the tuple, `(..., 42, ...)`, cfg node
|
// nodeTo is the tuple, `(..., 42, ...)`, cfg node
|
||||||
// c denotes element of tuple and index of nodeFrom
|
// c denotes element of tuple and index of nodeFrom
|
||||||
exists(int n |
|
exists(int n |
|
||||||
nodeTo.getNode().(Cfg::TupleNode).getElement(n) = nodeFrom.getNode() and
|
nodeTo.getNode().(TupleNode).getElement(n) = nodeFrom.getNode() and
|
||||||
not nodeTo.getNode() instanceof UnpackingAssignmentSequenceTarget and
|
not nodeTo.getNode() instanceof UnpackingAssignmentSequenceTarget and
|
||||||
c.getIndex() = n
|
c.getIndex() = n
|
||||||
)
|
)
|
||||||
@@ -970,7 +914,7 @@ predicate dictStoreStep(CfgNode nodeFrom, DictionaryElementContent c, Node nodeT
|
|||||||
// nodeTo is the dict, `{..., "key" = 42, ...}`, cfg node
|
// nodeTo is the dict, `{..., "key" = 42, ...}`, cfg node
|
||||||
// c denotes element of dictionary and the key `"key"`
|
// c denotes element of dictionary and the key `"key"`
|
||||||
exists(KeyValuePair item |
|
exists(KeyValuePair item |
|
||||||
item = nodeTo.asCfgNode().(Cfg::DictNode).getNode().(Dict).getAnItem() and
|
item = nodeTo.asCfgNode().(DictNode).getNode().(Dict).getAnItem() and
|
||||||
nodeFrom.getNode().getNode() = item.getValue() and
|
nodeFrom.getNode().getNode() = item.getValue() and
|
||||||
c.getKey() = item.getKey().(StringLiteral).getS()
|
c.getKey() = item.getKey().(StringLiteral).getS()
|
||||||
)
|
)
|
||||||
@@ -985,9 +929,9 @@ predicate dictStoreStep(CfgNode nodeFrom, DictionaryElementContent c, Node nodeT
|
|||||||
private predicate moreDictStoreSteps(CfgNode nodeFrom, DictionaryElementContent c, Node nodeTo) {
|
private predicate moreDictStoreSteps(CfgNode nodeFrom, DictionaryElementContent c, Node nodeTo) {
|
||||||
// NOTE: It's important to add logic to the newtype definition of
|
// NOTE: It's important to add logic to the newtype definition of
|
||||||
// DictionaryElementContent if you add new cases here.
|
// DictionaryElementContent if you add new cases here.
|
||||||
exists(Cfg::SubscriptNode subscript |
|
exists(SubscriptNode subscript |
|
||||||
nodeTo.(PostUpdateNode).getPreUpdateNode().asCfgNode() = subscript.getObject() and
|
nodeTo.(PostUpdateNode).getPreUpdateNode().asCfgNode() = subscript.getObject() and
|
||||||
nodeFrom.asCfgNode() = subscript.(Cfg::DefinitionNode).getValue() and
|
nodeFrom.asCfgNode() = subscript.(DefinitionNode).getValue() and
|
||||||
c.getKey() = subscript.getIndex().getNode().(StringLiteral).getText()
|
c.getKey() = subscript.getIndex().getNode().(StringLiteral).getText()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -1000,8 +944,8 @@ private predicate moreDictStoreSteps(CfgNode nodeFrom, DictionaryElementContent
|
|||||||
}
|
}
|
||||||
|
|
||||||
predicate dictClearStep(Node node, DictionaryElementContent c) {
|
predicate dictClearStep(Node node, DictionaryElementContent c) {
|
||||||
exists(Cfg::SubscriptNode subscript |
|
exists(SubscriptNode subscript |
|
||||||
subscript instanceof Cfg::DefinitionNode and
|
subscript instanceof DefinitionNode and
|
||||||
node.asCfgNode() = subscript.getObject() and
|
node.asCfgNode() = subscript.getObject() and
|
||||||
c.getKey() = subscript.getIndex().getNode().(StringLiteral).getText()
|
c.getKey() = subscript.getIndex().getNode().(StringLiteral).getText()
|
||||||
)
|
)
|
||||||
@@ -1080,7 +1024,7 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {
|
|||||||
// nodeFrom is `l`, cfg node
|
// nodeFrom is `l`, cfg node
|
||||||
// nodeTo is `l[3]`, cfg node
|
// nodeTo is `l[3]`, cfg node
|
||||||
// c is compatible with 3
|
// c is compatible with 3
|
||||||
nodeFrom.getNode() = nodeTo.getNode().(Cfg::SubscriptNode).getObject() and
|
nodeFrom.getNode() = nodeTo.getNode().(SubscriptNode).getObject() and
|
||||||
(
|
(
|
||||||
c instanceof ListElementContent
|
c instanceof ListElementContent
|
||||||
or
|
or
|
||||||
@@ -1089,10 +1033,10 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {
|
|||||||
c instanceof DictionaryElementAnyContent
|
c instanceof DictionaryElementAnyContent
|
||||||
or
|
or
|
||||||
c.(TupleElementContent).getIndex() =
|
c.(TupleElementContent).getIndex() =
|
||||||
nodeTo.getNode().(Cfg::SubscriptNode).getIndex().getNode().(IntegerLiteral).getValue()
|
nodeTo.getNode().(SubscriptNode).getIndex().getNode().(IntegerLiteral).getValue()
|
||||||
or
|
or
|
||||||
c.(DictionaryElementContent).getKey() =
|
c.(DictionaryElementContent).getKey() =
|
||||||
nodeTo.getNode().(Cfg::SubscriptNode).getIndex().getNode().(StringLiteral).getS()
|
nodeTo.getNode().(SubscriptNode).getIndex().getNode().(StringLiteral).getS()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1147,7 +1091,7 @@ module Conversions {
|
|||||||
|
|
||||||
predicate formatReadStep(Node nodeFrom, ContentSet c, Node nodeTo) {
|
predicate formatReadStep(Node nodeFrom, ContentSet c, Node nodeTo) {
|
||||||
// % formatting
|
// % formatting
|
||||||
exists(Cfg::BinaryExprNode fmt | fmt = nodeTo.asCfgNode() |
|
exists(BinaryExprNode fmt | fmt = nodeTo.asCfgNode() |
|
||||||
fmt.getOp() instanceof Mod and
|
fmt.getOp() instanceof Mod and
|
||||||
fmt.getRight() = nodeFrom.asCfgNode()
|
fmt.getRight() = nodeFrom.asCfgNode()
|
||||||
) and
|
) and
|
||||||
|
|||||||
@@ -5,14 +5,11 @@ overlay[local]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.controlflow.internal.AstNodeImpl as CfgImpl
|
|
||||||
private import codeql.controlflow.SuccessorType
|
|
||||||
private import DataFlowPrivate
|
private import DataFlowPrivate
|
||||||
import semmle.python.dataflow.new.TypeTracking
|
import semmle.python.dataflow.new.TypeTracking
|
||||||
import Attributes
|
import Attributes
|
||||||
import LocalSources
|
import LocalSources
|
||||||
private import semmle.python.dataflow.new.internal.SsaImpl as SsaImpl
|
private import semmle.python.essa.SsaCompute
|
||||||
private import semmle.python.dataflow.new.internal.ImportStar
|
private import semmle.python.dataflow.new.internal.ImportStar
|
||||||
private import semmle.python.frameworks.data.ModelsAsData
|
private import semmle.python.frameworks.data.ModelsAsData
|
||||||
private import FlowSummaryImpl as FlowSummaryImpl
|
private import FlowSummaryImpl as FlowSummaryImpl
|
||||||
@@ -30,18 +27,16 @@ private import semmle.python.frameworks.data.ModelsAsData
|
|||||||
overlay[local]
|
overlay[local]
|
||||||
newtype TNode =
|
newtype TNode =
|
||||||
/** A node corresponding to a control flow node. */
|
/** A node corresponding to a control flow node. */
|
||||||
TCfgNode(Cfg::ControlFlowNode node) {
|
TCfgNode(ControlFlowNode node) {
|
||||||
isExpressionNode(node)
|
isExpressionNode(node)
|
||||||
or
|
or
|
||||||
node.injects(_) and node.getNode() instanceof Pattern
|
node.getNode() instanceof Pattern
|
||||||
} or
|
} or
|
||||||
/**
|
/**
|
||||||
* A node corresponding to a scope entry definition. That is, the value of a variable
|
* A node corresponding to a scope entry definition. That is, the value of a variable
|
||||||
* as it enters a scope.
|
* as it enters a scope.
|
||||||
*/
|
*/
|
||||||
TScopeEntryDefinitionNode(SsaImpl::ScopeEntryDefinition def) {
|
TScopeEntryDefinitionNode(ScopeEntryDefinition def) { not def.getScope() instanceof Module } or
|
||||||
not def.getScope() instanceof Module
|
|
||||||
} or
|
|
||||||
/**
|
/**
|
||||||
* A synthetic node representing the value of an object before a state change.
|
* A synthetic node representing the value of an object before a state change.
|
||||||
*
|
*
|
||||||
@@ -52,15 +47,13 @@ newtype TNode =
|
|||||||
// NOTE: since we can't rely on the call graph, but we want to have synthetic
|
// NOTE: since we can't rely on the call graph, but we want to have synthetic
|
||||||
// pre-update nodes for class calls, we end up getting synthetic pre-update nodes for
|
// pre-update nodes for class calls, we end up getting synthetic pre-update nodes for
|
||||||
// ALL calls :|
|
// ALL calls :|
|
||||||
TSyntheticPreUpdateNode(Cfg::CallNode call) { call.injects(_) } or
|
TSyntheticPreUpdateNode(CallNode call) or
|
||||||
/**
|
/**
|
||||||
* A synthetic node representing the value of an object after a state change.
|
* A synthetic node representing the value of an object after a state change.
|
||||||
* See QLDoc for `PostUpdateNode`.
|
* See QLDoc for `PostUpdateNode`.
|
||||||
*/
|
*/
|
||||||
TSyntheticPostUpdateNode(Cfg::ControlFlowNode node) {
|
TSyntheticPostUpdateNode(ControlFlowNode node) {
|
||||||
node.injects(_) and
|
exists(CallNode call |
|
||||||
(
|
|
||||||
exists(Cfg::CallNode call |
|
|
||||||
node = call.getArg(_)
|
node = call.getArg(_)
|
||||||
or
|
or
|
||||||
node = call.getArgByName(_)
|
node = call.getArgByName(_)
|
||||||
@@ -69,12 +62,12 @@ newtype TNode =
|
|||||||
node = call.getFunction()
|
node = call.getFunction()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
node = any(Cfg::AttrNode a).getObject()
|
node = any(AttrNode a).getObject()
|
||||||
or
|
or
|
||||||
node = any(Cfg::SubscriptNode s).getObject()
|
node = any(SubscriptNode s).getObject()
|
||||||
or
|
or
|
||||||
// self parameter when used implicitly in `super()`
|
// self parameter when used implicitly in `super()`
|
||||||
exists(Class cls, Function func, SsaImpl::ParameterDefinition def |
|
exists(Class cls, Function func, ParameterDefinition def |
|
||||||
func = cls.getAMethod() and
|
func = cls.getAMethod() and
|
||||||
not isStaticmethod(func) and
|
not isStaticmethod(func) and
|
||||||
// this matches what we do in ExtractedParameterNode
|
// this matches what we do in ExtractedParameterNode
|
||||||
@@ -84,7 +77,6 @@ newtype TNode =
|
|||||||
or
|
or
|
||||||
// the iterable argument to the implicit comprehension function
|
// the iterable argument to the implicit comprehension function
|
||||||
node.getNode() = any(Comp c).getIterable()
|
node.getNode() = any(Comp c).getIterable()
|
||||||
)
|
|
||||||
} or
|
} or
|
||||||
/** A node representing a global (module-level) variable in a specific module. */
|
/** A node representing a global (module-level) variable in a specific module. */
|
||||||
TModuleVariableNode(Module m, GlobalVariable v) { v.getScope() = m } or
|
TModuleVariableNode(Module m, GlobalVariable v) { v.getScope() = m } or
|
||||||
@@ -120,9 +112,7 @@ newtype TNode =
|
|||||||
exists(ParameterPosition ppos | ppos.isStarArgs(_) | exists(callable.getParameter(ppos)))
|
exists(ParameterPosition ppos | ppos.isStarArgs(_) | exists(callable.getParameter(ppos)))
|
||||||
} or
|
} or
|
||||||
/** A synthetic node to capture keyword arguments that are passed to a `**kwargs` parameter. */
|
/** A synthetic node to capture keyword arguments that are passed to a `**kwargs` parameter. */
|
||||||
TSynthDictSplatArgumentNode(Cfg::CallNode call) {
|
TSynthDictSplatArgumentNode(CallNode call) { exists(call.getArgByName(_)) } or
|
||||||
call.injects(_) and exists(call.getArgByName(_))
|
|
||||||
} or
|
|
||||||
/** A synthetic node to allow flow to keyword parameters from a `**kwargs` argument. */
|
/** A synthetic node to allow flow to keyword parameters from a `**kwargs` argument. */
|
||||||
TSynthDictSplatParameterNode(DataFlowCallable callable) {
|
TSynthDictSplatParameterNode(DataFlowCallable callable) {
|
||||||
exists(ParameterPosition ppos | ppos.isKeyword(_) | exists(callable.getParameter(ppos)))
|
exists(ParameterPosition ppos | ppos.isKeyword(_) | exists(callable.getParameter(ppos)))
|
||||||
@@ -138,15 +128,15 @@ newtype TNode =
|
|||||||
* A synthetic node representing the values of the variables captured
|
* A synthetic node representing the values of the variables captured
|
||||||
* by the callable being called.
|
* by the callable being called.
|
||||||
*/
|
*/
|
||||||
TSynthCapturedVariablesArgumentNode(Cfg::ControlFlowNode callable) {
|
TSynthCapturedVariablesArgumentNode(ControlFlowNode callable) {
|
||||||
callable.injects(_) and callable = any(Cfg::CallNode c).getFunction()
|
callable = any(CallNode c).getFunction()
|
||||||
} or
|
} or
|
||||||
/**
|
/**
|
||||||
* A synthetic node representing the values of the variables captured
|
* A synthetic node representing the values of the variables captured
|
||||||
* by the callable being called, after the output has been computed.
|
* by the callable being called, after the output has been computed.
|
||||||
*/
|
*/
|
||||||
TSynthCapturedVariablesArgumentPostUpdateNode(Cfg::ControlFlowNode callable) {
|
TSynthCapturedVariablesArgumentPostUpdateNode(ControlFlowNode callable) {
|
||||||
callable.injects(_) and callable = any(Cfg::CallNode c).getFunction()
|
callable = any(CallNode c).getFunction()
|
||||||
} or
|
} or
|
||||||
/** A synthetic node representing the values of variables captured by a comprehension. */
|
/** A synthetic node representing the values of variables captured by a comprehension. */
|
||||||
TSynthCompCapturedVariablesArgumentNode(Comp comp) {
|
TSynthCompCapturedVariablesArgumentNode(Comp comp) {
|
||||||
@@ -204,7 +194,7 @@ class Node extends TNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the control-flow node corresponding to this node, if any. */
|
/** Gets the control-flow node corresponding to this node, if any. */
|
||||||
Cfg::ControlFlowNode asCfgNode() { none() }
|
ControlFlowNode asCfgNode() { none() }
|
||||||
|
|
||||||
/** Gets the expression corresponding to this node, if any. */
|
/** Gets the expression corresponding to this node, if any. */
|
||||||
Expr asExpr() { none() }
|
Expr asExpr() { none() }
|
||||||
@@ -217,14 +207,14 @@ class Node extends TNode {
|
|||||||
|
|
||||||
/** A data-flow node corresponding to a control-flow node. */
|
/** A data-flow node corresponding to a control-flow node. */
|
||||||
class CfgNode extends Node, TCfgNode {
|
class CfgNode extends Node, TCfgNode {
|
||||||
Cfg::ControlFlowNode node;
|
ControlFlowNode node;
|
||||||
|
|
||||||
CfgNode() { this = TCfgNode(node) }
|
CfgNode() { this = TCfgNode(node) }
|
||||||
|
|
||||||
/** Gets the `Cfg::ControlFlowNode` represented by this data-flow node. */
|
/** Gets the `ControlFlowNode` represented by this data-flow node. */
|
||||||
Cfg::ControlFlowNode getNode() { result = node }
|
ControlFlowNode getNode() { result = node }
|
||||||
|
|
||||||
override Cfg::ControlFlowNode asCfgNode() { result = node }
|
override ControlFlowNode asCfgNode() { result = node }
|
||||||
|
|
||||||
/** Gets a textual representation of this element. */
|
/** Gets a textual representation of this element. */
|
||||||
override string toString() { result = node.toString() }
|
override string toString() { result = node.toString() }
|
||||||
@@ -234,9 +224,9 @@ class CfgNode extends Node, TCfgNode {
|
|||||||
override Location getLocation() { result = node.getLocation() }
|
override Location getLocation() { result = node.getLocation() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A data-flow node corresponding to a `Cfg::CallNode` in the control-flow graph. */
|
/** A data-flow node corresponding to a `CallNode` in the control-flow graph. */
|
||||||
class CallCfgNode extends CfgNode, LocalSourceNode {
|
class CallCfgNode extends CfgNode, LocalSourceNode {
|
||||||
override Cfg::CallNode node;
|
override CallNode node;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the data-flow node for the function component of the call corresponding to this data-flow
|
* Gets the data-flow node for the function component of the call corresponding to this data-flow
|
||||||
@@ -317,15 +307,15 @@ ExprNode exprNode(DataFlowExpr e) { result.getNode().getNode() = e }
|
|||||||
* as it enters a scope.
|
* as it enters a scope.
|
||||||
*/
|
*/
|
||||||
class ScopeEntryDefinitionNode extends Node, TScopeEntryDefinitionNode {
|
class ScopeEntryDefinitionNode extends Node, TScopeEntryDefinitionNode {
|
||||||
SsaImpl::ScopeEntryDefinition def;
|
ScopeEntryDefinition def;
|
||||||
|
|
||||||
ScopeEntryDefinitionNode() { this = TScopeEntryDefinitionNode(def) }
|
ScopeEntryDefinitionNode() { this = TScopeEntryDefinitionNode(def) }
|
||||||
|
|
||||||
/** Gets the `SsaImpl::ScopeEntryDefinition` associated with this node. */
|
/** Gets the `ScopeEntryDefinition` associated with this node. */
|
||||||
SsaImpl::ScopeEntryDefinition getDefinition() { result = def }
|
ScopeEntryDefinition getDefinition() { result = def }
|
||||||
|
|
||||||
/** Gets the source variable represented by this node. */
|
/** Gets the source variable represented by this node. */
|
||||||
SsaImpl::SsaSourceVariable getVariable() { result = def.getSourceVariable() }
|
SsaSourceVariable getVariable() { result = def.getSourceVariable() }
|
||||||
|
|
||||||
override Location getLocation() { result = def.getLocation() }
|
override Location getLocation() { result = def.getLocation() }
|
||||||
|
|
||||||
@@ -347,7 +337,7 @@ class ParameterNode extends Node instanceof ParameterNodeImpl {
|
|||||||
/** A parameter node found in the source code (not in a summary). */
|
/** A parameter node found in the source code (not in a summary). */
|
||||||
class ExtractedParameterNode extends ParameterNodeImpl, CfgNode {
|
class ExtractedParameterNode extends ParameterNodeImpl, CfgNode {
|
||||||
//, LocalSourceNode {
|
//, LocalSourceNode {
|
||||||
SsaImpl::ParameterDefinition def;
|
ParameterDefinition def;
|
||||||
|
|
||||||
ExtractedParameterNode() { node = def.getDefiningNode() }
|
ExtractedParameterNode() { node = def.getDefiningNode() }
|
||||||
|
|
||||||
@@ -378,10 +368,10 @@ Node getCallArgApproximation() {
|
|||||||
exists(Class c | result.asExpr() = c.getAMethod().getArg(0))
|
exists(Class c | result.asExpr() = c.getAMethod().getArg(0))
|
||||||
or
|
or
|
||||||
// the object part of an attribute expression (which might be a bound method)
|
// the object part of an attribute expression (which might be a bound method)
|
||||||
result.asCfgNode() = any(Cfg::AttrNode a).getObject()
|
result.asCfgNode() = any(AttrNode a).getObject()
|
||||||
or
|
or
|
||||||
// the function part of any call
|
// the function part of any call
|
||||||
result.asCfgNode() = any(Cfg::CallNode c).getFunction()
|
result.asCfgNode() = any(CallNode c).getFunction()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the extracted argument nodes that do not rely on `getCallArg`. */
|
/** Gets the extracted argument nodes that do not rely on `getCallArg`. */
|
||||||
@@ -390,7 +380,7 @@ private Node implicitArgumentNode() {
|
|||||||
normalCallArg(_, result, _)
|
normalCallArg(_, result, _)
|
||||||
or
|
or
|
||||||
// and self arguments
|
// and self arguments
|
||||||
result.asCfgNode() = any(Cfg::CallNode c).getFunction().(Cfg::AttrNode).getObject()
|
result.asCfgNode() = any(CallNode c).getFunction().(AttrNode).getObject()
|
||||||
or
|
or
|
||||||
// for comprehensions, we allow the synthetic `iterable` argument
|
// for comprehensions, we allow the synthetic `iterable` argument
|
||||||
result.asExpr() = any(Comp c).getIterable()
|
result.asExpr() = any(Comp c).getIterable()
|
||||||
@@ -499,20 +489,17 @@ class ModuleVariableNode extends Node, TModuleVariableNode {
|
|||||||
not result.getScope() = mod
|
not result.getScope() = mod
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a CFG node that corresponds to an assignment of this global variable. */
|
/** Gets an `EssaNode` that corresponds to an assignment of this global variable. */
|
||||||
Node getAWrite() {
|
Node getAWrite() {
|
||||||
exists(Cfg::NameNode n |
|
any(EssaNodeDefinition def).definedBy(var, result.asCfgNode().(DefinitionNode))
|
||||||
n.defines(var) and
|
|
||||||
result.asCfgNode() = n
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the possible values of the variable at the end of import time */
|
/** Gets the possible values of the variable at the end of import time */
|
||||||
CfgNode getADefiningWrite() {
|
CfgNode getADefiningWrite() {
|
||||||
exists(SsaImpl::EssaVariable def |
|
exists(SsaVariable def |
|
||||||
def = any(SsaImpl::EssaVariable ssa_var).getAnUltimateDefinition() and
|
def = any(SsaVariable ssa_var).getAnUltimateDefinition() and
|
||||||
def.getDefinition().(SsaImpl::EssaNodeDefinition).getDefiningNode() = result.asCfgNode() and
|
def.getDefinition() = result.asCfgNode() and
|
||||||
def.getSourceVariable().getVariable() = var
|
def.getVariable() = var
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,7 +516,7 @@ private ModuleVariableNode import_star_read(Node n) {
|
|||||||
overlay[global]
|
overlay[global]
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate resolved_import_star_module(Module m, string name, Node n) {
|
private predicate resolved_import_star_module(Module m, string name, Node n) {
|
||||||
exists(Cfg::NameNode nn | nn = n.asCfgNode() |
|
exists(NameNode nn | nn = n.asCfgNode() |
|
||||||
ImportStar::importStarResolvesTo(pragma[only_bind_into](nn), m) and
|
ImportStar::importStarResolvesTo(pragma[only_bind_into](nn), m) and
|
||||||
nn.getId() = name
|
nn.getId() = name
|
||||||
)
|
)
|
||||||
@@ -587,88 +574,88 @@ class StarPatternElementNode extends Node, TStarPatternElementNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A node that participates in a conditional split: a CFG node whose
|
* Gets a node that controls whether other nodes are evaluated.
|
||||||
* evaluation outcome (true/false) is used to choose between two
|
|
||||||
* successor basic blocks. In the shared CFG, branching is detected
|
|
||||||
* via typed successor edges (boolean successor types) on the unique
|
|
||||||
* `injects` node for each AST expression.
|
|
||||||
*
|
*
|
||||||
* Users typically obtain a `GuardNode` by casting from a more specific
|
* In the base case, this is the last node of `conditionBlock`, and `flipped` is `false`.
|
||||||
* Cfg type: `g.(Cfg::CallNode)` for a call-based check, etc.
|
* This definition accounts for (short circuting) `and`- and `or`-expressions, as the structure
|
||||||
|
* of basic blocks will reflect their semantics.
|
||||||
|
*
|
||||||
|
* However, in the program
|
||||||
|
* ```python
|
||||||
|
* if not is_safe(path):
|
||||||
|
* return
|
||||||
|
* ```
|
||||||
|
* the last node in the `ConditionBlock` is `not is_safe(path)`.
|
||||||
|
*
|
||||||
|
* We would like to consider also `is_safe(path)` a guard node, albeit with `flipped` being `true`.
|
||||||
|
* Thus we recurse through `not`-expressions.
|
||||||
*/
|
*/
|
||||||
class GuardNode extends Cfg::ControlFlowNode {
|
ControlFlowNode guardNode(ConditionBlock conditionBlock, boolean flipped) {
|
||||||
GuardNode() {
|
// Base case: the last node truly does determine which successor is chosen
|
||||||
// This node has boolean successor edges (directly or via wrapping).
|
result = conditionBlock.getLastNode() and
|
||||||
outcomeOfGuard(this, _, _)
|
flipped = false
|
||||||
}
|
or
|
||||||
|
// Recursive cases:
|
||||||
/** Holds if this guard controls block `b` upon evaluating to `branch`. */
|
// if a guard node is a `not`-expression,
|
||||||
predicate controlsBlock(Cfg::BasicBlock b, boolean branch) {
|
// the operand is also a guard node, but with inverted polarity.
|
||||||
exists(CfgImpl::BasicBlock outcomeBB |
|
exists(UnaryExprNode notNode |
|
||||||
outcomeOfGuard(this, outcomeBB, branch) and
|
result = notNode.getOperand() and
|
||||||
outcomeBB.dominates(b)
|
notNode.getNode().getOp() instanceof Not
|
||||||
|
|
|
||||||
|
notNode = guardNode(conditionBlock, flipped.booleanNot())
|
||||||
|
)
|
||||||
|
or
|
||||||
|
// if a guard node is compared to a boolean literal,
|
||||||
|
// the other operand is also a guard node,
|
||||||
|
// but with polarity depending on the literal (and on the comparison).
|
||||||
|
exists(CompareNode cmpNode, Cmpop op, ControlFlowNode b, boolean should_flip |
|
||||||
|
(
|
||||||
|
cmpNode.operands(result, op, b) or
|
||||||
|
cmpNode.operands(b, op, result)
|
||||||
|
) and
|
||||||
|
not result.getNode() instanceof BooleanLiteral and
|
||||||
|
(
|
||||||
|
// comparing to the boolean
|
||||||
|
(op instanceof Eq or op instanceof Is) and
|
||||||
|
// we should flip if the value compared against, here the value of `b`, is false
|
||||||
|
should_flip = b.getNode().(BooleanLiteral).booleanValue().booleanNot()
|
||||||
|
or
|
||||||
|
// comparing to the negation of the boolean
|
||||||
|
(op instanceof NotEq or op instanceof IsNot) and
|
||||||
|
// again, we should flip if the value compared against, here the value of `not b`, is false.
|
||||||
|
// That is, if the value of `b` is true.
|
||||||
|
should_flip = b.getNode().(BooleanLiteral).booleanValue()
|
||||||
)
|
)
|
||||||
}
|
|
|
||||||
|
// we flip `flipped` according to `should_flip` via the formula `flipped xor should_flip`.
|
||||||
|
flipped in [true, false] and
|
||||||
|
cmpNode = guardNode(conditionBlock, flipped.booleanXor(should_flip))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if `outcomeBB` is the basic block entered when `guard` evaluates
|
* A node that controls whether other nodes are evaluated.
|
||||||
* to `branch`.
|
|
||||||
*
|
*
|
||||||
* For a direct guard `if g:`, the outcome BB starts at the after-value
|
* The field `flipped` allows us to match `GuardNode`s underneath
|
||||||
* node for the matching branch. For wrapped guards like `not g` or
|
* `not`-expressions and still choose the appropriate branch.
|
||||||
* `g == True`, we follow those wrappers up the AST to find the
|
|
||||||
* outermost expression that actually branches, with an appropriate
|
|
||||||
* polarity transform.
|
|
||||||
*/
|
*/
|
||||||
private predicate outcomeOfGuard(
|
class GuardNode extends ControlFlowNode {
|
||||||
Cfg::ControlFlowNode guard, CfgImpl::BasicBlock outcomeBB, boolean branch
|
ConditionBlock conditionBlock;
|
||||||
) {
|
boolean flipped;
|
||||||
// Base case: the guard has boolean successor edges.
|
|
||||||
// Only the canonical representative (injects) can act as a guard base.
|
GuardNode() { this = guardNode(conditionBlock, flipped) }
|
||||||
guard.injects(_) and
|
|
||||||
exists(BooleanSuccessor t |
|
/** Holds if this guard controls block `b` upon evaluating to `branch`. */
|
||||||
t.getValue() = branch and
|
predicate controlsBlock(BasicBlock b, boolean branch) {
|
||||||
outcomeBB = guard.(CfgImpl::ControlFlowNode).getASuccessor(t).getBasicBlock()
|
branch in [true, false] and
|
||||||
)
|
conditionBlock.controls(b, branch.booleanXor(flipped))
|
||||||
or
|
}
|
||||||
// Recursive: `not guard` — same outcome split as `guard`, flipped.
|
|
||||||
exists(Cfg::UnaryExprNode notNode, boolean notBranch |
|
|
||||||
notNode.injects(_) and
|
|
||||||
notNode.getOperand().getNode() = guard.getNode() and
|
|
||||||
notNode.getNode().getOp() instanceof Not and
|
|
||||||
outcomeOfGuard(notNode, outcomeBB, notBranch) and
|
|
||||||
branch = notBranch.booleanNot()
|
|
||||||
)
|
|
||||||
or
|
|
||||||
// Recursive: comparisons against a boolean literal.
|
|
||||||
exists(
|
|
||||||
Cfg::CompareNode cmpNode, Cmpop op, Cfg::ControlFlowNode otherOperand,
|
|
||||||
Cfg::ControlFlowNode guardOperand, boolean polarity, boolean cmpBranch
|
|
||||||
|
|
|
||||||
cmpNode.injects(_) and
|
|
||||||
guardOperand.getNode() = guard.getNode() and
|
|
||||||
(
|
|
||||||
cmpNode.operands(guardOperand, op, otherOperand) or
|
|
||||||
cmpNode.operands(otherOperand, op, guardOperand)
|
|
||||||
) and
|
|
||||||
not guard.getNode() instanceof BooleanLiteral and
|
|
||||||
(
|
|
||||||
(op instanceof Eq or op instanceof Is) and
|
|
||||||
polarity = otherOperand.getNode().(BooleanLiteral).booleanValue()
|
|
||||||
or
|
|
||||||
(op instanceof NotEq or op instanceof IsNot) and
|
|
||||||
polarity = otherOperand.getNode().(BooleanLiteral).booleanValue().booleanNot()
|
|
||||||
) and
|
|
||||||
outcomeOfGuard(cmpNode, outcomeBB, cmpBranch) and
|
|
||||||
branch = cmpBranch.booleanXor(polarity.booleanNot())
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if the guard `g` validates `node` upon evaluating to `branch`.
|
* Holds if the guard `g` validates `node` upon evaluating to `branch`.
|
||||||
*/
|
*/
|
||||||
signature predicate guardChecksSig(GuardNode g, Cfg::ControlFlowNode node, boolean branch);
|
signature predicate guardChecksSig(GuardNode g, ControlFlowNode node, boolean branch);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a set of barrier nodes for a guard that validates a node.
|
* Provides a set of barrier nodes for a guard that validates a node.
|
||||||
@@ -683,9 +670,7 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
|
|||||||
result = ParameterizedBarrierGuard<Unit, extendedGuardChecks/4>::getABarrierNode(_)
|
result = ParameterizedBarrierGuard<Unit, extendedGuardChecks/4>::getABarrierNode(_)
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate extendedGuardChecks(
|
private predicate extendedGuardChecks(GuardNode g, ControlFlowNode node, boolean branch, Unit u) {
|
||||||
GuardNode g, Cfg::ControlFlowNode node, boolean branch, Unit u
|
|
||||||
) {
|
|
||||||
guardChecks(g, node, branch) and
|
guardChecks(g, node, branch) and
|
||||||
u = u
|
u = u
|
||||||
}
|
}
|
||||||
@@ -695,7 +680,7 @@ bindingset[this]
|
|||||||
private signature class ParamSig;
|
private signature class ParamSig;
|
||||||
|
|
||||||
private module WithParam<ParamSig P> {
|
private module WithParam<ParamSig P> {
|
||||||
signature predicate guardChecksSig(GuardNode g, Cfg::ControlFlowNode node, boolean branch, P param);
|
signature predicate guardChecksSig(GuardNode g, ControlFlowNode node, boolean branch, P param);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -708,16 +693,10 @@ module ParameterizedBarrierGuard<ParamSig P, WithParam<P>::guardChecksSig/4 guar
|
|||||||
/** Gets a node that is safely guarded by the given guard check with parameter `param`. */
|
/** Gets a node that is safely guarded by the given guard check with parameter `param`. */
|
||||||
overlay[global]
|
overlay[global]
|
||||||
ExprNode getABarrierNode(P param) {
|
ExprNode getABarrierNode(P param) {
|
||||||
exists(GuardNode g, SsaImpl::EssaDefinition def, Cfg::ControlFlowNode node, boolean branch |
|
exists(GuardNode g, EssaDefinition def, ControlFlowNode node, boolean branch |
|
||||||
SsaImpl::AdjacentUses::useOfDef(def, node) and
|
AdjacentUses::useOfDef(def, node) and
|
||||||
guardChecks(g, node, branch, param) and
|
guardChecks(g, node, branch, param) and
|
||||||
SsaImpl::AdjacentUses::useOfDef(def, result.asCfgNode()) and
|
AdjacentUses::useOfDef(def, result.asCfgNode()) and
|
||||||
// The protected use must be a different SSA position than the test
|
|
||||||
// position itself: `controlsBlock` is reflexive on dominance, and
|
|
||||||
// the test expression is an SSA-use position on the def-use chain.
|
|
||||||
// Without this guard, the test position would be returned as a
|
|
||||||
// barrier and block flow before it can reach genuine branch uses.
|
|
||||||
node != result.asCfgNode() and
|
|
||||||
g.controlsBlock(result.asCfgNode().getBasicBlock(), branch)
|
g.controlsBlock(result.asCfgNode().getBasicBlock(), branch)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -733,7 +712,7 @@ module ExternalBarrierGuard {
|
|||||||
private import semmle.python.ApiGraphs
|
private import semmle.python.ApiGraphs
|
||||||
|
|
||||||
overlay[global]
|
overlay[global]
|
||||||
private predicate guardCheck(GuardNode g, Cfg::ControlFlowNode node, boolean branch, string kind) {
|
private predicate guardCheck(GuardNode g, ControlFlowNode node, boolean branch, string kind) {
|
||||||
exists(API::CallNode call, API::Node parameter |
|
exists(API::CallNode call, API::Node parameter |
|
||||||
parameter = call.getAParameter() and
|
parameter = call.getAParameter() and
|
||||||
parameter = ModelOutput::getABarrierGuardNode(kind, branch)
|
parameter = ModelOutput::getABarrierGuardNode(kind, branch)
|
||||||
@@ -769,10 +748,10 @@ newtype TContent =
|
|||||||
TSetElementContent() or
|
TSetElementContent() or
|
||||||
/** An element of a tuple at a specific index. */
|
/** An element of a tuple at a specific index. */
|
||||||
TTupleElementContent(int index) {
|
TTupleElementContent(int index) {
|
||||||
exists(any(Cfg::TupleNode tn).getElement(index))
|
exists(any(TupleNode tn).getElement(index))
|
||||||
or
|
or
|
||||||
// Arguments can overflow and end up in the starred parameter tuple.
|
// Arguments can overflow and end up in the starred parameter tuple.
|
||||||
exists(any(Cfg::CallNode cn).getArg(index))
|
exists(any(CallNode cn).getArg(index))
|
||||||
or
|
or
|
||||||
// since flow summaries might use tuples, we ensure that we at least have valid
|
// since flow summaries might use tuples, we ensure that we at least have valid
|
||||||
// TTupleElementContent for the 0..7 (7 was picked to match `small_tuple` in
|
// TTupleElementContent for the 0..7 (7 was picked to match `small_tuple` in
|
||||||
@@ -789,14 +768,10 @@ newtype TContent =
|
|||||||
or
|
or
|
||||||
// d["key"] = ...
|
// d["key"] = ...
|
||||||
key =
|
key =
|
||||||
any(Cfg::SubscriptNode sub |
|
any(SubscriptNode sub | sub.isStore() | sub.getIndex().getNode().(StringLiteral).getText())
|
||||||
sub.isStore()
|
|
||||||
|
|
|
||||||
sub.getIndex().getNode().(StringLiteral).getText()
|
|
||||||
)
|
|
||||||
or
|
or
|
||||||
// d.setdefault("key", ...)
|
// d.setdefault("key", ...)
|
||||||
exists(Cfg::CallNode call | call.getFunction().(Cfg::AttrNode).getName() = "setdefault" |
|
exists(CallNode call | call.getFunction().(AttrNode).getName() = "setdefault" |
|
||||||
key = call.getArg(0).getNode().(StringLiteral).getText()
|
key = call.getArg(0).getNode().(StringLiteral).getText()
|
||||||
)
|
)
|
||||||
} or
|
} or
|
||||||
|
|||||||
@@ -5,18 +5,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.internal.SsaImpl as SsaImpl
|
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.dataflow.new.internal.ImportStar
|
private import semmle.python.dataflow.new.internal.ImportStar
|
||||||
private import semmle.python.dataflow.new.TypeTracking
|
private import semmle.python.dataflow.new.TypeTracking
|
||||||
private import semmle.python.dataflow.new.internal.DataFlowPrivate
|
private import semmle.python.dataflow.new.internal.DataFlowPrivate
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if the name of `var` refers to a submodule of a package and `init` is
|
* Holds if `init` is a package's `__init__.py` and `var` is a global variable in
|
||||||
* the `__init__` module of that package. Locally inlined replacement for the
|
* `init` whose name matches a submodule of the package.
|
||||||
* legacy `SsaSource::init_module_submodule_defn` so that this module has no
|
*
|
||||||
* direct dependency on `semmle.python.essa.SsaDefinitions`.
|
* Inlined from `SsaSource::init_module_submodule_defn` to avoid pulling
|
||||||
|
* `semmle.python.essa.SsaDefinitions` into the new dataflow stack.
|
||||||
*/
|
*/
|
||||||
private predicate initModuleSubmoduleDefn(GlobalVariable var, Module init) {
|
private predicate initModuleSubmoduleDefn(GlobalVariable var, Module init) {
|
||||||
init.isPackageInit() and
|
init.isPackageInit() and
|
||||||
@@ -82,19 +81,13 @@ module ImportResolution {
|
|||||||
* Holds if there is an ESSA step from `defFrom` to `defTo`, which should be allowed
|
* Holds if there is an ESSA step from `defFrom` to `defTo`, which should be allowed
|
||||||
* for import resolution.
|
* for import resolution.
|
||||||
*/
|
*/
|
||||||
private predicate allowedEssaImportStep(
|
private predicate allowedEssaImportStep(EssaDefinition defFrom, EssaDefinition defTo) {
|
||||||
SsaImpl::EssaDefinition defFrom, SsaImpl::EssaDefinition defTo
|
|
||||||
) {
|
|
||||||
// to handle definitions guarded by if-then-else
|
// to handle definitions guarded by if-then-else
|
||||||
defFrom = defTo.(SsaImpl::PhiFunction).getAnInput()
|
defFrom = defTo.(PhiFunction).getAnInput()
|
||||||
or
|
or
|
||||||
// to handle uncertain writes such as `from X import *`, which create an
|
// refined variable
|
||||||
// uncertain SSA definition for every name in the importing scope. The
|
// example: https://github.com/nvbn/thefuck/blob/ceeaeab94b5df5a4fe9d94d61e4f6b0bbea96378/thefuck/utils.py#L25-L45
|
||||||
// immediately preceding definition is still potentially the value of the
|
defFrom = defTo.(EssaNodeRefinement).getInput().getDefinition()
|
||||||
// module export.
|
|
||||||
SsaImpl::Ssa::uncertainWriteDefinitionInput(defTo, defFrom)
|
|
||||||
// Note: legacy ESSA refinement-step (e.g. for `foo.bar = X`) is
|
|
||||||
// not modelled in the new SSA beyond the cases handled above.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -111,32 +104,30 @@ module ImportResolution {
|
|||||||
// Definitions made inside `m` itself
|
// Definitions made inside `m` itself
|
||||||
//
|
//
|
||||||
// for code such as `foo = ...; foo.bar = ...` there will be TWO
|
// for code such as `foo = ...; foo.bar = ...` there will be TWO
|
||||||
// SsaImpl::EssaDefinition/SsaImpl::EssaVariable. One for `foo = ...` (SsaImpl::AssignmentDefinition) and one
|
// EssaDefinition/EssaVariable. One for `foo = ...` (AssignmentDefinition) and one
|
||||||
// for `foo.bar = ...`. The one for `foo.bar = ...` (EssaNodeRefinement). The
|
// for `foo.bar = ...`. The one for `foo.bar = ...` (EssaNodeRefinement). The
|
||||||
// EssaNodeRefinement is the one that will reach the end of the module (normal
|
// EssaNodeRefinement is the one that will reach the end of the module (normal
|
||||||
// exit).
|
// exit).
|
||||||
//
|
//
|
||||||
// However, we cannot just use the EssaNodeRefinement as the `val`, because the
|
// However, we cannot just use the EssaNodeRefinement as the `val`, because the
|
||||||
// normal data-flow depends on use-use flow, and use-use flow targets CFG nodes not
|
// normal data-flow depends on use-use flow, and use-use flow targets CFG nodes not
|
||||||
// EssaNodes. So we need to go back from the SsaImpl::EssaDefinition/SsaImpl::EssaVariable that
|
// EssaNodes. So we need to go back from the EssaDefinition/EssaVariable that
|
||||||
// reaches the end of the module, to the first definition of the variable, and then
|
// reaches the end of the module, to the first definition of the variable, and then
|
||||||
// track forwards using use-use flow to find a suitable CFG node that has flow into
|
// track forwards using use-use flow to find a suitable CFG node that has flow into
|
||||||
// it from use-use flow.
|
// it from use-use flow.
|
||||||
exists(SsaImpl::EssaVariable lastUseVar, SsaImpl::EssaVariable firstDef |
|
exists(EssaVariable lastUseVar, EssaVariable firstDef |
|
||||||
lastUseVar.getName() = name and
|
lastUseVar.getName() = name and
|
||||||
// we ignore special variable $ introduced by our analysis (not used for anything)
|
// we ignore special variable $ introduced by our analysis (not used for anything)
|
||||||
// we ignore special variable * introduced by `from <pkg> import *` -- TODO: understand why we even have this?
|
// we ignore special variable * introduced by `from <pkg> import *` -- TODO: understand why we even have this?
|
||||||
not name in ["$", "*"] and
|
not name in ["$", "*"] and
|
||||||
exists(Cfg::ControlFlowNode exit |
|
lastUseVar.getAUse() = m.getANormalExit() and
|
||||||
exit.isNormalExit() and exit.getScope() = m and lastUseVar.getAUse() = exit
|
|
||||||
) and
|
|
||||||
allowedEssaImportStep*(firstDef, lastUseVar) and
|
allowedEssaImportStep*(firstDef, lastUseVar) and
|
||||||
not allowedEssaImportStep(_, firstDef)
|
not allowedEssaImportStep(_, firstDef)
|
||||||
|
|
|
|
||||||
not LocalFlow::defToFirstUse(firstDef, _) and
|
not LocalFlow::defToFirstUse(firstDef, _) and
|
||||||
val.asCfgNode() = firstDef.getDefinition().(SsaImpl::EssaNodeDefinition).getDefiningNode()
|
val.asCfgNode() = firstDef.getDefinition().(EssaNodeDefinition).getDefiningNode()
|
||||||
or
|
or
|
||||||
exists(Cfg::ControlFlowNode mid, Cfg::ControlFlowNode end |
|
exists(ControlFlowNode mid, ControlFlowNode end |
|
||||||
LocalFlow::defToFirstUse(firstDef, mid) and
|
LocalFlow::defToFirstUse(firstDef, mid) and
|
||||||
LocalFlow::useToNextUse*(mid, end) and
|
LocalFlow::useToNextUse*(mid, end) and
|
||||||
not LocalFlow::useToNextUse(end, _) and
|
not LocalFlow::useToNextUse(end, _) and
|
||||||
@@ -164,9 +155,9 @@ module ImportResolution {
|
|||||||
* handles simple cases where we can statically tell that this is the case.
|
* handles simple cases where we can statically tell that this is the case.
|
||||||
*/
|
*/
|
||||||
private predicate all_mentions_name(Module m, string name) {
|
private predicate all_mentions_name(Module m, string name) {
|
||||||
exists(Cfg::DefinitionNode def, Cfg::SequenceNode n |
|
exists(DefinitionNode def, SequenceNode n |
|
||||||
def.getValue() = n and
|
def.getValue() = n and
|
||||||
def.(Cfg::NameNode).getId() = "__all__" and
|
def.(NameNode).getId() = "__all__" and
|
||||||
def.getScope() = m and
|
def.getScope() = m and
|
||||||
any(StringLiteral s | s.getText() = name) = n.getAnElement().getNode()
|
any(StringLiteral s | s.getText() = name) = n.getAnElement().getNode()
|
||||||
)
|
)
|
||||||
@@ -179,20 +170,18 @@ module ImportResolution {
|
|||||||
*/
|
*/
|
||||||
private predicate no_or_complicated_all(Module m) {
|
private predicate no_or_complicated_all(Module m) {
|
||||||
// No mention of `__all__` in the module
|
// No mention of `__all__` in the module
|
||||||
not exists(Cfg::DefinitionNode def |
|
not exists(DefinitionNode def | def.getScope() = m and def.(NameNode).getId() = "__all__")
|
||||||
def.getScope() = m and def.(Cfg::NameNode).getId() = "__all__"
|
|
||||||
)
|
|
||||||
or
|
or
|
||||||
// `__all__` is set to a non-sequence value
|
// `__all__` is set to a non-sequence value
|
||||||
exists(Cfg::DefinitionNode def |
|
exists(DefinitionNode def |
|
||||||
def.(Cfg::NameNode).getId() = "__all__" and
|
def.(NameNode).getId() = "__all__" and
|
||||||
def.getScope() = m and
|
def.getScope() = m and
|
||||||
not def.getValue() instanceof Cfg::SequenceNode
|
not def.getValue() instanceof SequenceNode
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// `__all__` is used in some way that doesn't involve storing a value in it. This usually means
|
// `__all__` is used in some way that doesn't involve storing a value in it. This usually means
|
||||||
// it is being mutated through `append` or `extend`, which we don't handle.
|
// it is being mutated through `append` or `extend`, which we don't handle.
|
||||||
exists(Cfg::NameNode n | n.getId() = "__all__" and n.getScope() = m and n.isLoad())
|
exists(NameNode n | n.getId() = "__all__" and n.getScope() = m and n.isLoad())
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate potential_module_export(Module m, string name) {
|
private predicate potential_module_export(Module m, string name) {
|
||||||
@@ -200,7 +189,7 @@ module ImportResolution {
|
|||||||
or
|
or
|
||||||
no_or_complicated_all(m) and
|
no_or_complicated_all(m) and
|
||||||
(
|
(
|
||||||
exists(Cfg::NameNode n | n.getId() = name and n.getScope() = m and name.charAt(0) != "_")
|
exists(NameNode n | n.getId() = name and n.getScope() = m and name.charAt(0) != "_")
|
||||||
or
|
or
|
||||||
exists(Alias a | a.getAsname().(Name).getId() = name and a.getValue().getScope() = m)
|
exists(Alias a | a.getAsname().(Name).getId() = name and a.getValue().getScope() = m)
|
||||||
)
|
)
|
||||||
@@ -230,12 +219,12 @@ module ImportResolution {
|
|||||||
|
|
||||||
/** Gets a module that may have been added to `sys.modules`. */
|
/** Gets a module that may have been added to `sys.modules`. */
|
||||||
private Module sys_modules_module_with_name(string name) {
|
private Module sys_modules_module_with_name(string name) {
|
||||||
exists(Cfg::ControlFlowNode n, DataFlow::Node mod |
|
exists(ControlFlowNode n, DataFlow::Node mod |
|
||||||
exists(Cfg::SubscriptNode sub |
|
exists(SubscriptNode sub |
|
||||||
sub.getObject() = sys_modules_reference().asCfgNode() and
|
sub.getObject() = sys_modules_reference().asCfgNode() and
|
||||||
sub.getIndex() = n and
|
sub.getIndex() = n and
|
||||||
n.getNode().(StringLiteral).getText() = name and
|
n.getNode().(StringLiteral).getText() = name and
|
||||||
sub.(Cfg::DefinitionNode).getValue() = mod.asCfgNode() and
|
sub.(DefinitionNode).getValue() = mod.asCfgNode() and
|
||||||
mod = getModuleReference(result)
|
mod = getModuleReference(result)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -347,11 +336,11 @@ module ImportResolution {
|
|||||||
// name as a submodule, we always consider that this attribute _could_ be a
|
// name as a submodule, we always consider that this attribute _could_ be a
|
||||||
// reference to the submodule, even if we don't know that the submodule has been
|
// reference to the submodule, even if we don't know that the submodule has been
|
||||||
// imported yet.
|
// imported yet.
|
||||||
exists(string submodule, Module package, SsaImpl::EssaVariable var |
|
exists(string submodule, Module package, EssaVariable var |
|
||||||
submodule = var.getName() and
|
submodule = var.getName() and
|
||||||
initModuleSubmoduleDefn(var.getSourceVariable().getVariable(), package) and
|
initModuleSubmoduleDefn(var.getSourceVariable(), package) and
|
||||||
m = getModuleFromName(package.getPackageName() + "." + submodule) and
|
m = getModuleFromName(package.getPackageName() + "." + submodule) and
|
||||||
result.asCfgNode() = var.getDefinition().(SsaImpl::EssaNodeDefinition).getDefiningNode()
|
result.asCfgNode() = var.getDefinition().(EssaNodeDefinition).getDefiningNode()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ overlay[local]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.internal.Builtins
|
private import semmle.python.dataflow.new.internal.Builtins
|
||||||
private import semmle.python.dataflow.new.internal.ImportResolution
|
private import semmle.python.dataflow.new.internal.ImportResolution
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
@@ -16,7 +15,7 @@ module ImportStar {
|
|||||||
*/
|
*/
|
||||||
overlay[local]
|
overlay[local]
|
||||||
cached
|
cached
|
||||||
predicate namePossiblyDefinedInImportStar(Cfg::NameNode n, string name, Scope s) {
|
predicate namePossiblyDefinedInImportStar(NameNode n, string name, Scope s) {
|
||||||
n.isLoad() and
|
n.isLoad() and
|
||||||
name = n.getId() and
|
name = n.getId() and
|
||||||
s = n.getScope().getEnclosingScope*() and
|
s = n.getScope().getEnclosingScope*() and
|
||||||
@@ -53,7 +52,7 @@ module ImportStar {
|
|||||||
/** Holds if a global variable called `name` is assigned a value in the module `m`. */
|
/** Holds if a global variable called `name` is assigned a value in the module `m`. */
|
||||||
cached
|
cached
|
||||||
predicate globalNameDefinedInModule(string name, Module m) {
|
predicate globalNameDefinedInModule(string name, Module m) {
|
||||||
exists(Cfg::NameNode n |
|
exists(NameNode n |
|
||||||
not exists(LocalVariable v | n.defines(v)) and
|
not exists(LocalVariable v | n.defines(v)) and
|
||||||
n.isStore() and
|
n.isStore() and
|
||||||
name = n.getId() and
|
name = n.getId() and
|
||||||
@@ -67,7 +66,7 @@ module ImportStar {
|
|||||||
*/
|
*/
|
||||||
overlay[global]
|
overlay[global]
|
||||||
cached
|
cached
|
||||||
predicate importStarResolvesTo(Cfg::NameNode n, Module m) {
|
predicate importStarResolvesTo(NameNode n, Module m) {
|
||||||
m = getStarImported+(n.getEnclosingModule()) and
|
m = getStarImported+(n.getEnclosingModule()) and
|
||||||
globalNameDefinedInModule(n.getId(), m) and
|
globalNameDefinedInModule(n.getId(), m) and
|
||||||
not isDefinedLocally(n.getNode())
|
not isDefinedLocally(n.getNode())
|
||||||
@@ -100,7 +99,7 @@ module ImportStar {
|
|||||||
*/
|
*/
|
||||||
overlay[local]
|
overlay[local]
|
||||||
cached
|
cached
|
||||||
Cfg::ControlFlowNode potentialImportStarBase(Scope s) {
|
ControlFlowNode potentialImportStarBase(Scope s) {
|
||||||
result = any(Cfg::ImportStarNode n | n.getScope() = s).getModule()
|
result = any(ImportStarNode n | n.getScope() = s).getModule()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,8 +170,6 @@ overlay[local]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.internal.SsaImpl as SsaImpl
|
|
||||||
private import DataFlowPublic
|
private import DataFlowPublic
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -180,7 +178,7 @@ private import DataFlowPublic
|
|||||||
* This class abstracts away the differing representations of comprehensions and
|
* This class abstracts away the differing representations of comprehensions and
|
||||||
* for statements.
|
* for statements.
|
||||||
*/
|
*/
|
||||||
class ForTarget extends Cfg::ControlFlowNode {
|
class ForTarget extends ControlFlowNode {
|
||||||
Expr source;
|
Expr source;
|
||||||
|
|
||||||
ForTarget() {
|
ForTarget() {
|
||||||
@@ -200,7 +198,7 @@ class ForTarget extends Cfg::ControlFlowNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** The LHS of an assignment, it also records the assigned value. */
|
/** The LHS of an assignment, it also records the assigned value. */
|
||||||
class AssignmentTarget extends Cfg::ControlFlowNode {
|
class AssignmentTarget extends ControlFlowNode {
|
||||||
Expr value;
|
Expr value;
|
||||||
|
|
||||||
AssignmentTarget() {
|
AssignmentTarget() {
|
||||||
@@ -211,7 +209,7 @@ class AssignmentTarget extends Cfg::ControlFlowNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** A direct (or top-level) target of an unpacking assignment. */
|
/** A direct (or top-level) target of an unpacking assignment. */
|
||||||
class UnpackingAssignmentDirectTarget extends Cfg::ControlFlowNode instanceof Cfg::SequenceNode {
|
class UnpackingAssignmentDirectTarget extends ControlFlowNode instanceof SequenceNode {
|
||||||
Expr value;
|
Expr value;
|
||||||
|
|
||||||
UnpackingAssignmentDirectTarget() {
|
UnpackingAssignmentDirectTarget() {
|
||||||
@@ -224,7 +222,7 @@ class UnpackingAssignmentDirectTarget extends Cfg::ControlFlowNode instanceof Cf
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** A (possibly recursive) target of an unpacking assignment. */
|
/** A (possibly recursive) target of an unpacking assignment. */
|
||||||
class UnpackingAssignmentTarget extends Cfg::ControlFlowNode {
|
class UnpackingAssignmentTarget extends ControlFlowNode {
|
||||||
UnpackingAssignmentTarget() {
|
UnpackingAssignmentTarget() {
|
||||||
this instanceof UnpackingAssignmentDirectTarget
|
this instanceof UnpackingAssignmentDirectTarget
|
||||||
or
|
or
|
||||||
@@ -233,11 +231,10 @@ class UnpackingAssignmentTarget extends Cfg::ControlFlowNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** A (possibly recursive) target of an unpacking assignment which is also a sequence. */
|
/** A (possibly recursive) target of an unpacking assignment which is also a sequence. */
|
||||||
class UnpackingAssignmentSequenceTarget extends UnpackingAssignmentTarget instanceof Cfg::SequenceNode
|
class UnpackingAssignmentSequenceTarget extends UnpackingAssignmentTarget instanceof SequenceNode {
|
||||||
{
|
ControlFlowNode getElement(int i) { result = super.getElement(i) }
|
||||||
Cfg::ControlFlowNode getElement(int i) { result = super.getElement(i) }
|
|
||||||
|
|
||||||
Cfg::ControlFlowNode getAnElement() { result = this.getElement(_) }
|
ControlFlowNode getAnElement() { result = this.getElement(_) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -258,7 +255,7 @@ predicate iterableUnpackingAssignmentFlowStep(Node nodeFrom, Node nodeTo) {
|
|||||||
predicate iterableUnpackingForReadStep(CfgNode nodeFrom, Content c, Node nodeTo) {
|
predicate iterableUnpackingForReadStep(CfgNode nodeFrom, Content c, Node nodeTo) {
|
||||||
exists(ForTarget target |
|
exists(ForTarget target |
|
||||||
nodeFrom.getNode().getNode() = target.getSource() and
|
nodeFrom.getNode().getNode() = target.getSource() and
|
||||||
target instanceof Cfg::SequenceNode and
|
target instanceof SequenceNode and
|
||||||
nodeTo = TIterableSequenceNode(target)
|
nodeTo = TIterableSequenceNode(target)
|
||||||
) and
|
) and
|
||||||
(
|
(
|
||||||
@@ -326,11 +323,11 @@ predicate iterableUnpackingConvertingStoreStep(Node nodeFrom, Content c, Node no
|
|||||||
*/
|
*/
|
||||||
predicate iterableUnpackingElementReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
predicate iterableUnpackingElementReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||||
exists(
|
exists(
|
||||||
UnpackingAssignmentSequenceTarget target, int index, Cfg::ControlFlowNode element, int starIndex
|
UnpackingAssignmentSequenceTarget target, int index, ControlFlowNode element, int starIndex
|
||||||
|
|
|
|
||||||
target.getElement(starIndex) instanceof Cfg::StarredNode
|
target.getElement(starIndex) instanceof StarredNode
|
||||||
or
|
or
|
||||||
not exists(target.getAnElement().(Cfg::StarredNode)) and
|
not exists(target.getAnElement().(StarredNode)) and
|
||||||
starIndex = -1
|
starIndex = -1
|
||||||
|
|
|
|
||||||
nodeFrom.(CfgNode).getNode() = target and
|
nodeFrom.(CfgNode).getNode() = target and
|
||||||
@@ -345,18 +342,18 @@ predicate iterableUnpackingElementReadStep(Node nodeFrom, Content c, Node nodeTo
|
|||||||
else c.(TupleElementContent).getIndex() >= index - 1
|
else c.(TupleElementContent).getIndex() >= index - 1
|
||||||
) and
|
) and
|
||||||
(
|
(
|
||||||
if element instanceof Cfg::SequenceNode
|
if element instanceof SequenceNode
|
||||||
then
|
then
|
||||||
// Step 5b
|
// Step 5b
|
||||||
nodeTo = TIterableSequenceNode(element)
|
nodeTo = TIterableSequenceNode(element)
|
||||||
else
|
else
|
||||||
if element instanceof Cfg::StarredNode
|
if element instanceof StarredNode
|
||||||
then
|
then
|
||||||
// Step 5c
|
// Step 5c
|
||||||
nodeTo = TIterableElementNode(element)
|
nodeTo = TIterableElementNode(element)
|
||||||
else
|
else
|
||||||
// Step 5a
|
// Step 5a
|
||||||
exists(SsaImpl::MultiAssignmentDefinition mad | element = mad.getDefiningNode() |
|
exists(MultiAssignmentDefinition mad | element = mad.getDefiningNode() |
|
||||||
nodeTo.(CfgNode).getNode() = element
|
nodeTo.(CfgNode).getNode() = element
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -369,7 +366,7 @@ predicate iterableUnpackingElementReadStep(Node nodeFrom, Content c, Node nodeTo
|
|||||||
* content type `ListElementContent`.
|
* content type `ListElementContent`.
|
||||||
*/
|
*/
|
||||||
predicate iterableUnpackingStarredElementStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
predicate iterableUnpackingStarredElementStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||||
exists(Cfg::ControlFlowNode starred, SsaImpl::MultiAssignmentDefinition mad |
|
exists(ControlFlowNode starred, MultiAssignmentDefinition mad |
|
||||||
starred.getNode() instanceof Starred and
|
starred.getNode() instanceof Starred and
|
||||||
starred = mad.getDefiningNode()
|
starred = mad.getDefiningNode()
|
||||||
|
|
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ overlay[local]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
import DataFlowPublic
|
import DataFlowPublic
|
||||||
private import DataFlowPrivate
|
private import DataFlowPrivate
|
||||||
private import semmle.python.internal.CachedStages
|
private import semmle.python.internal.CachedStages
|
||||||
@@ -315,7 +314,7 @@ private module Cached {
|
|||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
predicate subscript(LocalSourceNode node, CfgNode subscript, CfgNode index) {
|
predicate subscript(LocalSourceNode node, CfgNode subscript, CfgNode index) {
|
||||||
exists(CfgNode seq, Cfg::SubscriptNode subscriptNode | subscriptNode = subscript.getNode() |
|
exists(CfgNode seq, SubscriptNode subscriptNode | subscriptNode = subscript.getNode() |
|
||||||
node.flowsTo(seq) and
|
node.flowsTo(seq) and
|
||||||
seq.getNode() = subscriptNode.getObject() and
|
seq.getNode() = subscriptNode.getObject() and
|
||||||
index.getNode() = subscriptNode.getIndex()
|
index.getNode() = subscriptNode.getIndex()
|
||||||
|
|||||||
@@ -91,7 +91,9 @@ predicate matchAsFlowStep(Node nodeFrom, Node nodeTo) {
|
|||||||
or
|
or
|
||||||
// the interior pattern flows to the alias
|
// the interior pattern flows to the alias
|
||||||
nodeFrom.(CfgNode).getNode().getNode() = subject.getPattern() and
|
nodeFrom.(CfgNode).getNode().getNode() = subject.getPattern() and
|
||||||
nodeTo.(CfgNode).getNode().getNode() = alias
|
exists(PatternAliasDefinition pad | pad.getDefiningNode().getNode() = alias |
|
||||||
|
nodeTo.(CfgNode).getNode() = pad.getDefiningNode()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,9 +124,11 @@ predicate matchLiteralFlowStep(Node nodeFrom, Node nodeTo) {
|
|||||||
* syntax (toplevel): `case var:`
|
* syntax (toplevel): `case var:`
|
||||||
*/
|
*/
|
||||||
predicate matchCaptureFlowStep(Node nodeFrom, Node nodeTo) {
|
predicate matchCaptureFlowStep(Node nodeFrom, Node nodeTo) {
|
||||||
exists(MatchCapturePattern capture |
|
exists(MatchCapturePattern capture, Name var | capture.getVariable() = var |
|
||||||
nodeFrom.(CfgNode).getNode().getNode() = capture and
|
nodeFrom.(CfgNode).getNode().getNode() = capture and
|
||||||
nodeTo.(CfgNode).getNode().getNode() = capture.getVariable()
|
exists(PatternCaptureDefinition pcd | pcd.getDefiningNode().getNode() = var |
|
||||||
|
nodeTo.(CfgNode).getNode() = pcd.getDefiningNode()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,548 +0,0 @@
|
|||||||
/**
|
|
||||||
* Provides the Python SSA implementation built on the new (shared) CFG.
|
|
||||||
*
|
|
||||||
* Mirrors the Java SSA adapter at
|
|
||||||
* `java/ql/lib/semmle/code/java/dataflow/internal/SsaImpl.qll`:
|
|
||||||
* an `InputSig` is defined in terms of positional `(BasicBlock, int)`
|
|
||||||
* variable references, and the shared
|
|
||||||
* `codeql.ssa.Ssa::Make<Location, Cfg, Input>` module is then
|
|
||||||
* instantiated.
|
|
||||||
*
|
|
||||||
* `SourceVariable` is the AST-level `Py::Variable`. Variable references
|
|
||||||
* are looked up via the CFG facade's `NameNode.defines`/`uses`/`deletes`
|
|
||||||
* predicates, which themselves are one-line bridges to AST-level
|
|
||||||
* `Name.defines`/`uses`/`deletes`.
|
|
||||||
*
|
|
||||||
* Implicit-entry definitions are inserted for:
|
|
||||||
* - non-local / global / builtin variables that are read in the scope
|
|
||||||
* but never assigned (no enclosing CFG node defines them),
|
|
||||||
* - captured variables (variables defined in an enclosing scope that
|
|
||||||
* are read inside the scope), and
|
|
||||||
* - parameters, but only if the corresponding parameter name is *not*
|
|
||||||
* itself a CFG node. With the C#-style parameter wiring already
|
|
||||||
* installed in `AstNodeImpl.qll`, parameter names *are* CFG nodes,
|
|
||||||
* so the regular `variableWrite` path handles them — no `i = -1`
|
|
||||||
* entry is needed for ordinary parameters.
|
|
||||||
*/
|
|
||||||
overlay[local?]
|
|
||||||
module;
|
|
||||||
|
|
||||||
private import python as Py
|
|
||||||
private import semmle.python.controlflow.internal.AstNodeImpl as CfgImpl
|
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import codeql.ssa.Ssa as SsaImplCommon
|
|
||||||
private import codeql.controlflow.BasicBlock as BB
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adapts the Python `Cfg` facade to the shared SSA library's `CfgSig`.
|
|
||||||
* All members are inherited from `Cfg::ControlFlowNode` and
|
|
||||||
* `Cfg::BasicBlock`.
|
|
||||||
*/
|
|
||||||
private module CfgForSsa implements BB::CfgSig<Py::Location> {
|
|
||||||
class ControlFlowNode = CfgImpl::ControlFlowNode;
|
|
||||||
|
|
||||||
class BasicBlock = CfgImpl::BasicBlock;
|
|
||||||
|
|
||||||
class EntryBasicBlock = CfgImpl::Cfg::EntryBasicBlock;
|
|
||||||
|
|
||||||
predicate dominatingEdge = CfgImpl::Cfg::dominatingEdge/2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A source variable for SSA, wrapping a Python AST `Variable`.
|
|
||||||
*
|
|
||||||
* We only track variables that are read at least once in their scope —
|
|
||||||
* tracking write-only variables would be unnecessary work — *except*
|
|
||||||
* for module-scope globals, where the "read" can be external (e.g.
|
|
||||||
* `import mymodule; mymodule.x`). Such globals are tracked
|
|
||||||
* unconditionally so that import-resolution can find their defining
|
|
||||||
* write.
|
|
||||||
*/
|
|
||||||
private newtype TSsaSourceVariable =
|
|
||||||
TPyVar(Py::Variable v) {
|
|
||||||
// Has a use somewhere — read-relevant for SSA.
|
|
||||||
exists(Cfg::NameNode n | n.uses(v))
|
|
||||||
or
|
|
||||||
// Or has a deletion (treated as a write that destroys the value).
|
|
||||||
exists(Cfg::NameNode n | n.deletes(v))
|
|
||||||
or
|
|
||||||
// Or is a module-scope global written in this module — must be
|
|
||||||
// tracked even if never read locally, because importers may read
|
|
||||||
// it as an attribute on the module object.
|
|
||||||
v.getScope() instanceof Py::Module and
|
|
||||||
exists(Cfg::NameNode n | n.defines(v))
|
|
||||||
or
|
|
||||||
// Or is a parameter — parameters must always have a
|
|
||||||
// `ParameterDefinition` for dataflow argument-routing to work,
|
|
||||||
// even if the parameter is never read in its scope. Mirrors
|
|
||||||
// legacy ESSA's `ParameterDefinition` (which fired for every
|
|
||||||
// parameter binding regardless of liveness).
|
|
||||||
exists(Py::Parameter p | p.asName() = v.getAStore())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A source variable for SSA, wrapping a Python AST `Variable`.
|
|
||||||
*/
|
|
||||||
class SsaSourceVariable extends TSsaSourceVariable {
|
|
||||||
/** Gets the underlying Python AST variable. */
|
|
||||||
Py::Variable getVariable() { this = TPyVar(result) }
|
|
||||||
|
|
||||||
/** Gets the (textual) name of this variable. */
|
|
||||||
string getName() { result = this.getVariable().getId() }
|
|
||||||
|
|
||||||
/** Gets a textual representation of this source variable. */
|
|
||||||
string toString() { result = this.getVariable().toString() }
|
|
||||||
|
|
||||||
/** Gets the location of this source variable. */
|
|
||||||
Py::Location getLocation() { result = this.getVariable().getScope().getLocation() }
|
|
||||||
|
|
||||||
/** Gets the scope in which this variable lives. */
|
|
||||||
Py::Scope getScope() { result = this.getVariable().getScope() }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a use of this variable as it appears in the source — a `NameNode`
|
|
||||||
* that loads or deletes the variable. Mirrors legacy
|
|
||||||
* `SsaSourceVariable.getASourceUse()`.
|
|
||||||
*/
|
|
||||||
Cfg::ControlFlowNode getASourceUse() {
|
|
||||||
exists(Cfg::NameNode n | result = n |
|
|
||||||
n.uses(this.getVariable()) or n.deletes(this.getVariable())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an implicit use of this variable. The new SSA does not have
|
|
||||||
* implicit-use refinements, but we keep this for API parity — every
|
|
||||||
* normal-exit of the variable's scope counts as a sink, ensuring
|
|
||||||
* variables stay live to scope exit for taint-tracking.
|
|
||||||
*/
|
|
||||||
Cfg::ControlFlowNode getAnImplicitUse() {
|
|
||||||
result.isNormalExit() and result.getScope() = this.getScope()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a use of this variable — either an explicit source use or an
|
|
||||||
* implicit use at scope exit. Mirrors legacy `SsaSourceVariable.getAUse()`.
|
|
||||||
*/
|
|
||||||
Cfg::ControlFlowNode getAUse() {
|
|
||||||
result = this.getASourceUse() or result = this.getAnImplicitUse()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `v` is a non-local read in scope `s`, in the sense that `s`
|
|
||||||
* uses `v` but does not write it within `s`. This includes globals,
|
|
||||||
* builtins, and variables captured from an enclosing function scope.
|
|
||||||
*
|
|
||||||
* The `Py::Variable` `v` lives in some defining scope (the module for
|
|
||||||
* globals, an outer function for closures, etc.); the reading scope
|
|
||||||
* `s` is the scope where the use of `v` occurs.
|
|
||||||
*/
|
|
||||||
private predicate nonLocalReadIn(Py::Variable v, Py::Scope s) {
|
|
||||||
exists(Cfg::NameNode n |
|
|
||||||
n.uses(v) and
|
|
||||||
n.getScope() = s and
|
|
||||||
not exists(Cfg::NameNode def | def.defines(v) and def.getScope() = s)
|
|
||||||
) and
|
|
||||||
// Match legacy ESSA: only create entry defs for variables that have
|
|
||||||
// at least one defining store somewhere — otherwise the entry def
|
|
||||||
// represents "nothing reaches here", which is the default anyway and
|
|
||||||
// introduces no useful flow. (Legacy's `ModuleVariable` required a
|
|
||||||
// store; this is the closure-aware generalisation.)
|
|
||||||
exists(Cfg::NameNode store | store.defines(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `bb` is the entry basic block of a scope where `v` should
|
|
||||||
* have an implicit entry definition. This covers:
|
|
||||||
* - non-local / global / builtin variables read in `s`, and
|
|
||||||
* - captured variables (defined in an enclosing scope but read in `s`).
|
|
||||||
*
|
|
||||||
* Each reading scope gets its own entry def, so a closure variable can
|
|
||||||
* have multiple entry defs across all functions/methods that read it.
|
|
||||||
*
|
|
||||||
* Parameters are *not* included: their bound `Name` is itself a CFG
|
|
||||||
* node (per the C#-style parameter wiring), so `variableWrite` fires at
|
|
||||||
* the parameter's natural CFG index.
|
|
||||||
*/
|
|
||||||
private predicate hasEntryDefIn(SsaSourceVariable v, CfgImpl::BasicBlock bb) {
|
|
||||||
exists(Py::Scope s |
|
|
||||||
nonLocalReadIn(v.getVariable(), s) and
|
|
||||||
bb = entryBlock(s)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the entry basic block of scope `s`, where implicit entry
|
|
||||||
* definitions are placed (at synthetic index `-1`).
|
|
||||||
*/
|
|
||||||
private CfgImpl::BasicBlock entryBlock(Py::Scope s) {
|
|
||||||
exists(CfgImpl::ControlFlowNode entry |
|
|
||||||
entry instanceof CfgImpl::ControlFlow::EntryNode and
|
|
||||||
entry.getEnclosingCallable().asScope() = s and
|
|
||||||
result = entry.getBasicBlock()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The SSA `InputSig` for Python. References are positional
|
|
||||||
* `(BasicBlock, int)` pairs into the new CFG.
|
|
||||||
*/
|
|
||||||
private module SsaImplInput implements SsaImplCommon::InputSig<Py::Location, CfgImpl::BasicBlock> {
|
|
||||||
class SourceVariable = SsaSourceVariable;
|
|
||||||
|
|
||||||
predicate variableWrite(CfgImpl::BasicBlock bb, int i, SourceVariable v, boolean certain) {
|
|
||||||
// Explicit binding at a CFG node — includes assignments,
|
|
||||||
// parameter Names (wired in via the C# pattern), exception-handler
|
|
||||||
// `as`-bindings, import aliases, and match-pattern captures.
|
|
||||||
exists(Cfg::NameNode n |
|
|
||||||
bb.getNode(i) = n and
|
|
||||||
n.defines(v.getVariable()) and
|
|
||||||
certain = true
|
|
||||||
)
|
|
||||||
or
|
|
||||||
// `del x` — removes the binding. Modelled as a certain write that
|
|
||||||
// makes any subsequent read invalid.
|
|
||||||
exists(Cfg::NameNode n |
|
|
||||||
bb.getNode(i) = n and
|
|
||||||
n.deletes(v.getVariable()) and
|
|
||||||
certain = true
|
|
||||||
)
|
|
||||||
or
|
|
||||||
// Implicit entry definition for non-local / captured / global /
|
|
||||||
// builtin variables read in some scope. Each reading scope's entry
|
|
||||||
// block gets one such write, allowing closures: e.g. when `x` is a
|
|
||||||
// parameter of an outer function and read inside a nested
|
|
||||||
// function, both scopes get entry defs for `x`.
|
|
||||||
hasEntryDefIn(v, bb) and
|
|
||||||
i = -1 and
|
|
||||||
certain = true
|
|
||||||
or
|
|
||||||
// `from X import *` — possibly rebinds every name in the importing
|
|
||||||
// scope. Modelled as an uncertain write at the import-star's CFG
|
|
||||||
// position for every variable that lives in (or is referenced
|
|
||||||
// from) the same scope as the import-star. Mirrors legacy ESSA's
|
|
||||||
// `ImportStarRefinement` (see `essa/SsaDefinitions.qll`'s
|
|
||||||
// `import_star_refinement` predicate). The write is uncertain so
|
|
||||||
// that prior definitions of the variable remain available — the
|
|
||||||
// shared-SSA `SsaUncertainWrite` merges the new value with the
|
|
||||||
// immediately preceding definition.
|
|
||||||
exists(Cfg::ImportStarNode imp |
|
|
||||||
imp.injects(_) and
|
|
||||||
bb.getNode(i) = imp and
|
|
||||||
certain = false and
|
|
||||||
(
|
|
||||||
v.getVariable().getScope() = imp.getScope()
|
|
||||||
or
|
|
||||||
// Variable is defined in some other scope but referenced in
|
|
||||||
// the same scope as the import-star (matches legacy clause 2:
|
|
||||||
// `other.uses(v) and def.getScope() = other.getScope()`).
|
|
||||||
exists(Cfg::NameNode other |
|
|
||||||
other.uses(v.getVariable()) and
|
|
||||||
imp.getScope() = other.getScope()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
predicate variableRead(CfgImpl::BasicBlock bb, int i, SourceVariable v, boolean certain) {
|
|
||||||
// Explicit source use — a `Name` load or a `del x` of the variable.
|
|
||||||
exists(Cfg::NameNode n |
|
|
||||||
bb.getNode(i) = n and
|
|
||||||
n.uses(v.getVariable()) and
|
|
||||||
certain = true
|
|
||||||
)
|
|
||||||
or
|
|
||||||
// Synthetic use at the normal exit of the variable's defining scope.
|
|
||||||
// This keeps every variable live to scope exit so that callers (e.g.
|
|
||||||
// `module_export` in ImportResolution.qll, or taint-tracking pass-through
|
|
||||||
// through unread locals) can ask "which definition reaches end of
|
|
||||||
// scope?". Mirrors legacy ESSA's `SsaSourceVariable.getAUse()` which
|
|
||||||
// included `getScope().getANormalExit()`.
|
|
||||||
exists(Cfg::ControlFlowNode exit |
|
|
||||||
exit.isNormalExit() and
|
|
||||||
exit.getScope() = v.getVariable().getScope() and
|
|
||||||
bb.getNode(i) = exit and
|
|
||||||
certain = true
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The shared SSA instantiation for Python.
|
|
||||||
*
|
|
||||||
* Members:
|
|
||||||
* - `Definition` — the union of explicit, uncertain, and phi definitions
|
|
||||||
* - `WriteDefinition`, `UncertainWriteDefinition`, `PhiNode`
|
|
||||||
* - the standard SSA predicates (`getAUse`, `getAnUltimateDefinition`, ...).
|
|
||||||
*/
|
|
||||||
module Ssa = SsaImplCommon::Make<Py::Location, CfgForSsa, SsaImplInput>;
|
|
||||||
|
|
||||||
final class Definition = Ssa::Definition;
|
|
||||||
|
|
||||||
final class WriteDefinition = Ssa::WriteDefinition;
|
|
||||||
|
|
||||||
final class UncertainWriteDefinition = Ssa::UncertainWriteDefinition;
|
|
||||||
|
|
||||||
final class PhiNode = Ssa::PhiNode;
|
|
||||||
|
|
||||||
// ===========================================================================
|
|
||||||
// ESSA-shaped adapter layer
|
|
||||||
//
|
|
||||||
// The dataflow library (`python/ql/lib/semmle/python/dataflow/new/`) and
|
|
||||||
// related modules (`ApiGraphs.qll`, etc.) consume the legacy ESSA API
|
|
||||||
// (`EssaVariable`, `EssaDefinition`, `AssignmentDefinition`,
|
|
||||||
// `ScopeEntryDefinition`, `ParameterDefinition`, `WithDefinition`,
|
|
||||||
// `PhiFunction`, plus the `AdjacentUses` module). To migrate them off
|
|
||||||
// the legacy CFG, we expose the same API surface on top of the
|
|
||||||
// shared SSA built above.
|
|
||||||
//
|
|
||||||
// This adapter is intentionally narrow: it covers only the predicates
|
|
||||||
// that new dataflow consumes. The richer legacy ESSA — refinement
|
|
||||||
// nodes, attribute refinements, edge refinements — stays available
|
|
||||||
// via `semmle.python.essa.Essa` for points-to / legacy code.
|
|
||||||
// ===========================================================================
|
|
||||||
/**
|
|
||||||
* Gets the CFG node at which a write definition's binding takes place.
|
|
||||||
*
|
|
||||||
* For ordinary writes (assignment, deletion, parameter) this is the
|
|
||||||
* canonical CFG node of the bound Name. For implicit entry definitions
|
|
||||||
* (synthesised at position `-1` of a scope's entry BB) this is the
|
|
||||||
* scope's entry node.
|
|
||||||
*/
|
|
||||||
private Cfg::ControlFlowNode writeDefNode(Ssa::WriteDefinition def) {
|
|
||||||
exists(CfgImpl::BasicBlock bb, int i | def.definesAt(_, bb, i) |
|
|
||||||
i >= 0 and result = bb.getNode(i)
|
|
||||||
or
|
|
||||||
i = -1 and result = bb.getNode(0)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A write definition whose binding has a corresponding CFG node — i.e.
|
|
||||||
* everything that's not a phi node. Mirrors legacy ESSA's
|
|
||||||
* `EssaNodeDefinition`.
|
|
||||||
*/
|
|
||||||
class EssaNodeDefinition extends Ssa::WriteDefinition {
|
|
||||||
/** Gets the CFG node where this definition's binding takes place. */
|
|
||||||
Cfg::ControlFlowNode getDefiningNode() { result = writeDefNode(this) }
|
|
||||||
|
|
||||||
/** Gets the variable defined here (legacy name). */
|
|
||||||
SsaSourceVariable getVariable() { result = this.getSourceVariable() }
|
|
||||||
|
|
||||||
/** Gets the enclosing scope. */
|
|
||||||
Py::Scope getScope() {
|
|
||||||
exists(Cfg::ControlFlowNode n | n = this.getDefiningNode() | result = n.getScope())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if this definition defines source variable `v` at CFG node
|
|
||||||
* `defNode`. Flatter form of `getSourceVariable()` +
|
|
||||||
* `getDefiningNode()`, matching legacy ESSA's `definedBy`.
|
|
||||||
*/
|
|
||||||
predicate definedBy(SsaSourceVariable v, Cfg::ControlFlowNode defNode) {
|
|
||||||
v = this.getSourceVariable() and defNode = this.getDefiningNode()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An assignment definition: any binding where the value being assigned
|
|
||||||
* is statically known via `Cfg::DefinitionNode.getValue()`. Includes
|
|
||||||
* plain assignments, walrus, annotated assignments, augmented
|
|
||||||
* assignments, import aliases (`import x` / `from m import x [as y]`),
|
|
||||||
* `with ... as x`, and for-target bindings (where `getValue()` returns
|
|
||||||
* the iter expression's CFG node). Excludes parameter bindings —
|
|
||||||
* those are modelled by `ParameterDefinition`.
|
|
||||||
*/
|
|
||||||
class AssignmentDefinition extends EssaNodeDefinition {
|
|
||||||
AssignmentDefinition() {
|
|
||||||
exists(Cfg::NameNode n | n = this.getDefiningNode() |
|
|
||||||
exists(n.(Cfg::DefinitionNode).getValue()) and
|
|
||||||
not n.(Cfg::ControlFlowNode).isParameter()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets the CFG node for the value being assigned, if statically known. */
|
|
||||||
Cfg::ControlFlowNode getValue() {
|
|
||||||
result = this.getDefiningNode().(Cfg::DefinitionNode).getValue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A parameter definition — the binding of a parameter name in a
|
|
||||||
* function's scope.
|
|
||||||
*/
|
|
||||||
class ParameterDefinition extends EssaNodeDefinition {
|
|
||||||
ParameterDefinition() { this.getDefiningNode().isParameter() }
|
|
||||||
|
|
||||||
/** Gets the AST `Parameter` (a `Py::Name` in param context). */
|
|
||||||
Py::Name getParameter() { result = this.getDefiningNode().getNode() }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A definition introduced by a `with ... as x:` clause.
|
|
||||||
*/
|
|
||||||
class WithDefinition extends EssaNodeDefinition {
|
|
||||||
WithDefinition() {
|
|
||||||
exists(Cfg::NameNode n, Py::With w |
|
|
||||||
n = this.getDefiningNode() and
|
|
||||||
w.getOptionalVars() = n.getNode()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An assignment where the LHS is a tuple/list and the RHS is unpacked:
|
|
||||||
* `a, b = (1, 2)` or `a, *rest = xs`. The SSA def lives at the inner
|
|
||||||
* `Name` CFG node, but for IterableUnpacking integration we expose
|
|
||||||
* the enclosing `StarredNode` as the `getDefiningNode()` for `*rest`
|
|
||||||
* patterns — mirroring legacy ESSA's `multi_assignment_definition`,
|
|
||||||
* which placed the def at the StarredNode CFG node.
|
|
||||||
*/
|
|
||||||
class MultiAssignmentDefinition extends EssaNodeDefinition {
|
|
||||||
MultiAssignmentDefinition() {
|
|
||||||
exists(Cfg::NameNode n | n = super.getDefiningNode() |
|
|
||||||
exists(Py::Assign a, Py::Expr lhs |
|
|
||||||
a.getATarget() = lhs and
|
|
||||||
(lhs instanceof Py::Tuple or lhs instanceof Py::List) and
|
|
||||||
lhs.getASubExpression+() = n.getNode()
|
|
||||||
)
|
|
||||||
or
|
|
||||||
// For-loop with tuple/list target: `for a, b in xs:` —
|
|
||||||
// tuple-unpacking semantics applies to the for-target.
|
|
||||||
exists(Py::For f, Py::Expr lhs |
|
|
||||||
f.getTarget() = lhs and
|
|
||||||
(lhs instanceof Py::Tuple or lhs instanceof Py::List) and
|
|
||||||
lhs.getASubExpression+() = n.getNode()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override Cfg::ControlFlowNode getDefiningNode() {
|
|
||||||
// Default: the underlying `Name` CFG node (where the SSA def lives).
|
|
||||||
not exists(Cfg::StarredNode s |
|
|
||||||
s.getNode().(Py::Starred).getValue() = super.getDefiningNode().getNode()
|
|
||||||
) and
|
|
||||||
result = super.getDefiningNode()
|
|
||||||
or
|
|
||||||
// Exception: for `*rest`, expose the enclosing `Starred` CFG node
|
|
||||||
// so that `IterableUnpacking::iterableUnpackingStarredElementStoreStep`
|
|
||||||
// can attach the rest-list to it.
|
|
||||||
exists(Cfg::StarredNode s |
|
|
||||||
s.getNode().(Py::Starred).getValue() = super.getDefiningNode().getNode()
|
|
||||||
|
|
|
||||||
result = s
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An implicit entry definition for a non-local / captured / global /
|
|
||||||
* builtin variable read in a scope but not defined there.
|
|
||||||
*
|
|
||||||
* Inherits from `EssaNodeDefinition` and exposes the scope's entry node
|
|
||||||
* as its defining node (matching legacy ESSA semantics).
|
|
||||||
*/
|
|
||||||
class ScopeEntryDefinition extends EssaNodeDefinition {
|
|
||||||
ScopeEntryDefinition() {
|
|
||||||
exists(CfgImpl::BasicBlock bb |
|
|
||||||
this.definesAt(_, bb, -1) and
|
|
||||||
bb instanceof CfgImpl::Cfg::EntryBasicBlock
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets the enclosing scope (the scope whose entry block this def is in). */
|
|
||||||
override Py::Scope getScope() {
|
|
||||||
exists(CfgImpl::BasicBlock bb |
|
|
||||||
this.definesAt(_, bb, -1) and
|
|
||||||
result = bb.getNode(0).(Cfg::ControlFlowNode).getScope()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A phi node (alias matching legacy naming). */
|
|
||||||
class PhiFunction extends PhiNode {
|
|
||||||
/**
|
|
||||||
* Gets an input to this phi function (a definition that flows into
|
|
||||||
* the phi from one of its predecessor blocks). Mirrors legacy
|
|
||||||
* ESSA's `PhiFunction.getAnInput()`.
|
|
||||||
*/
|
|
||||||
Ssa::Definition getAnInput() { Ssa::phiHasInputFromBlock(this, result, _) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Base class for all ESSA definitions (legacy-shaped). */
|
|
||||||
class EssaDefinition = Ssa::Definition;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An adapter representing a single SSA-defined "variable" — wrapping
|
|
||||||
* one `Ssa::Definition`. Mirrors legacy `EssaVariable` API.
|
|
||||||
*/
|
|
||||||
class EssaVariable extends Ssa::Definition {
|
|
||||||
/** Gets the underlying SSA definition (legacy name). */
|
|
||||||
Ssa::Definition getDefinition() { result = this }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a CFG node where this definition is used. Includes regular
|
|
||||||
* `Name` reads as well as the synthetic scope-exit "use" registered
|
|
||||||
* via `SsaImplInput::variableRead` — mirrors legacy ESSA's
|
|
||||||
* `EssaVariable.getAUse()` which inherited the synthetic exit-use
|
|
||||||
* from `SsaSourceVariable`.
|
|
||||||
*/
|
|
||||||
Cfg::ControlFlowNode getAUse() {
|
|
||||||
exists(CfgImpl::BasicBlock bb, int i |
|
|
||||||
Ssa::ssaDefReachesRead(this.getSourceVariable(), this, bb, i) and
|
|
||||||
bb.getNode(i) = result
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets the (textual) name of the underlying variable. */
|
|
||||||
string getName() { result = this.getSourceVariable().getVariable().getId() }
|
|
||||||
|
|
||||||
/** Gets the scope in which this variable lives. */
|
|
||||||
Py::Scope getScope() { result = this.getSourceVariable().getVariable().getScope() }
|
|
||||||
|
|
||||||
/** Gets an ultimate non-phi ancestor of this definition. */
|
|
||||||
EssaVariable getAnUltimateDefinition() {
|
|
||||||
if this instanceof PhiNode
|
|
||||||
then
|
|
||||||
exists(Ssa::Definition input |
|
|
||||||
Ssa::phiHasInputFromBlock(this, input, _) and
|
|
||||||
result = input.(EssaVariable).getAnUltimateDefinition()
|
|
||||||
)
|
|
||||||
else result = this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adjacent use-use and def-use relations exposed by the shared SSA
|
|
||||||
* library. Provides the same interface as legacy
|
|
||||||
* `semmle.python.essa.SsaCompute::AdjacentUses`.
|
|
||||||
*/
|
|
||||||
module AdjacentUses {
|
|
||||||
/** Holds if `nodeFrom` and `nodeTo` are adjacent uses of the same SSA variable. */
|
|
||||||
predicate adjacentUseUse(Cfg::NameNode nodeFrom, Cfg::NameNode nodeTo) {
|
|
||||||
exists(SsaSourceVariable v, CfgImpl::BasicBlock bb1, int i1, CfgImpl::BasicBlock bb2, int i2 |
|
|
||||||
Ssa::adjacentUseUse(bb1, i1, bb2, i2, v, _) and
|
|
||||||
nodeFrom = bb1.getNode(i1) and
|
|
||||||
nodeTo = bb2.getNode(i2)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Holds if `use` is a first use of definition `def`. */
|
|
||||||
predicate firstUse(Ssa::Definition def, Cfg::NameNode use) {
|
|
||||||
exists(CfgImpl::BasicBlock bb, int i |
|
|
||||||
Ssa::firstUse(def, bb, i, _) and
|
|
||||||
use = bb.getNode(i)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `use` is any reachable use of definition `def`. Combines
|
|
||||||
* `firstUse` with transitive use-use adjacency.
|
|
||||||
*/
|
|
||||||
predicate useOfDef(Ssa::Definition def, Cfg::NameNode use) {
|
|
||||||
firstUse(def, use)
|
|
||||||
or
|
|
||||||
exists(Cfg::NameNode mid | useOfDef(def, mid) and adjacentUseUse(mid, use))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.internal.SsaImpl as SsaImpl
|
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
|
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
|
||||||
private import FlowSummaryImpl as FlowSummaryImpl
|
private import FlowSummaryImpl as FlowSummaryImpl
|
||||||
@@ -99,7 +97,7 @@ import Cached
|
|||||||
* and isn't a big problem in practice.
|
* and isn't a big problem in practice.
|
||||||
*/
|
*/
|
||||||
predicate concatStep(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeTo) {
|
predicate concatStep(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeTo) {
|
||||||
exists(Cfg::BinaryExprNode add | add = nodeTo.getNode() |
|
exists(BinaryExprNode add | add = nodeTo.getNode() |
|
||||||
add.getOp() instanceof Add and add.getAnOperand() = nodeFrom.getNode()
|
add.getOp() instanceof Add and add.getAnOperand() = nodeFrom.getNode()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -108,7 +106,7 @@ predicate concatStep(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeTo) {
|
|||||||
* Holds if taint can flow from `nodeFrom` to `nodeTo` with a step related to subscripting.
|
* Holds if taint can flow from `nodeFrom` to `nodeTo` with a step related to subscripting.
|
||||||
*/
|
*/
|
||||||
predicate subscriptStep(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeTo) {
|
predicate subscriptStep(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeTo) {
|
||||||
nodeTo.getNode().(Cfg::SubscriptNode).getObject() = nodeFrom.getNode()
|
nodeTo.getNode().(SubscriptNode).getObject() = nodeFrom.getNode()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -124,15 +122,15 @@ predicate stringManipulation(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeT
|
|||||||
(
|
(
|
||||||
call = API::builtin(["str", "bytes", "unicode"]).getACall()
|
call = API::builtin(["str", "bytes", "unicode"]).getACall()
|
||||||
or
|
or
|
||||||
call.getFunction().asCfgNode().(Cfg::NameNode).getId() in ["str", "bytes", "unicode"]
|
call.getFunction().asCfgNode().(NameNode).getId() in ["str", "bytes", "unicode"]
|
||||||
) and
|
) and
|
||||||
nodeFrom in [call.getArg(0), call.getArgByName("object")]
|
nodeFrom in [call.getArg(0), call.getArgByName("object")]
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// String methods. Note that this doesn't recognize `meth = "foo".upper; meth()`
|
// String methods. Note that this doesn't recognize `meth = "foo".upper; meth()`
|
||||||
exists(Cfg::CallNode call, string method_name, Cfg::ControlFlowNode object |
|
exists(CallNode call, string method_name, ControlFlowNode object |
|
||||||
call = nodeTo.getNode() and
|
call = nodeTo.getNode() and
|
||||||
object = call.getFunction().(Cfg::AttrNode).getObject(method_name)
|
object = call.getFunction().(AttrNode).getObject(method_name)
|
||||||
|
|
|
|
||||||
nodeFrom.getNode() = object and
|
nodeFrom.getNode() = object and
|
||||||
method_name in [
|
method_name in [
|
||||||
@@ -158,7 +156,7 @@ predicate stringManipulation(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeT
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
// % formatting
|
// % formatting
|
||||||
exists(Cfg::BinaryExprNode fmt | fmt = nodeTo.getNode() |
|
exists(BinaryExprNode fmt | fmt = nodeTo.getNode() |
|
||||||
fmt.getOp() instanceof Mod and
|
fmt.getOp() instanceof Mod and
|
||||||
(
|
(
|
||||||
fmt.getLeft() = nodeFrom.getNode()
|
fmt.getLeft() = nodeFrom.getNode()
|
||||||
@@ -168,7 +166,7 @@ predicate stringManipulation(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeT
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
// string multiplication -- `"foo" * 10`
|
// string multiplication -- `"foo" * 10`
|
||||||
exists(Cfg::BinaryExprNode mult | mult = nodeTo.getNode() |
|
exists(BinaryExprNode mult | mult = nodeTo.getNode() |
|
||||||
mult.getOp() instanceof Mult and
|
mult.getOp() instanceof Mult and
|
||||||
mult.getLeft() = nodeFrom.getNode()
|
mult.getLeft() = nodeFrom.getNode()
|
||||||
)
|
)
|
||||||
@@ -215,8 +213,8 @@ predicate awaitStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
|||||||
* the variable `f` is tainted if the result of `open("foo")` is tainted.
|
* the variable `f` is tainted if the result of `open("foo")` is tainted.
|
||||||
*/
|
*/
|
||||||
predicate asyncWithStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
predicate asyncWithStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||||
exists(With with, Cfg::ControlFlowNode contextManager, Cfg::ControlFlowNode var |
|
exists(With with, ControlFlowNode contextManager, ControlFlowNode var |
|
||||||
var = any(SsaImpl::WithDefinition wd).getDefiningNode()
|
var = any(WithDefinition wd).getDefiningNode()
|
||||||
|
|
|
|
||||||
nodeFrom.(DataFlow::CfgNode).getNode() = contextManager and
|
nodeFrom.(DataFlow::CfgNode).getNode() = contextManager and
|
||||||
nodeTo.(DataFlow::CfgNode).getNode() = var and
|
nodeTo.(DataFlow::CfgNode).getNode() = var and
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ import codeql.util.Unit
|
|||||||
import codeql.typetracking.TypeTracking as Shared
|
import codeql.typetracking.TypeTracking as Shared
|
||||||
import codeql.typetracking.internal.TypeTrackingImpl as SharedImpl
|
import codeql.typetracking.internal.TypeTrackingImpl as SharedImpl
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.internal.SsaImpl as SsaImpl
|
|
||||||
private import semmle.python.internal.CachedStages
|
private import semmle.python.internal.CachedStages
|
||||||
private import semmle.python.dataflow.new.internal.DataFlowPublic as DataFlowPublic
|
private import semmle.python.dataflow.new.internal.DataFlowPublic as DataFlowPublic
|
||||||
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
|
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
|
||||||
@@ -164,7 +162,7 @@ module TypeTrackingInput implements Shared::TypeTrackingInput<Location> {
|
|||||||
// ignore the flow steps from the synthetic sequence node to the real sequence node,
|
// ignore the flow steps from the synthetic sequence node to the real sequence node,
|
||||||
// since we only support one level of content in type-trackers, and the nested
|
// since we only support one level of content in type-trackers, and the nested
|
||||||
// structure requires two levels at least to be useful.
|
// structure requires two levels at least to be useful.
|
||||||
not exists(Cfg::SequenceNode outer |
|
not exists(SequenceNode outer |
|
||||||
outer.getAnElement() = nodeTo.asCfgNode() and
|
outer.getAnElement() = nodeTo.asCfgNode() and
|
||||||
IterableUnpacking::iterableUnpackingTupleFlowStep(nodeFrom, nodeTo)
|
IterableUnpacking::iterableUnpackingTupleFlowStep(nodeFrom, nodeTo)
|
||||||
)
|
)
|
||||||
@@ -269,7 +267,7 @@ module TypeTrackingInput implements Shared::TypeTrackingInput<Location> {
|
|||||||
// Since we only support one level of content in type-trackers we don't actually
|
// Since we only support one level of content in type-trackers we don't actually
|
||||||
// support `(aa, ab), (ba, bb) = ...`. Therefore we exclude the read-step from `(aa,
|
// support `(aa, ab), (ba, bb) = ...`. Therefore we exclude the read-step from `(aa,
|
||||||
// ab)` to `aa` (since it is not needed).
|
// ab)` to `aa` (since it is not needed).
|
||||||
not exists(Cfg::SequenceNode outer |
|
not exists(SequenceNode outer |
|
||||||
outer.getAnElement() = nodeFrom.asCfgNode() and
|
outer.getAnElement() = nodeFrom.asCfgNode() and
|
||||||
IterableUnpacking::iterableUnpackingTupleFlowStep(_, nodeFrom)
|
IterableUnpacking::iterableUnpackingTupleFlowStep(_, nodeFrom)
|
||||||
) and
|
) and
|
||||||
@@ -279,7 +277,7 @@ module TypeTrackingInput implements Shared::TypeTrackingInput<Location> {
|
|||||||
IterableUnpacking::iterableUnpackingForReadStep(_, _, seq) and
|
IterableUnpacking::iterableUnpackingForReadStep(_, _, seq) and
|
||||||
IterableUnpacking::iterableUnpackingConvertingReadStep(seq, _, elem) and
|
IterableUnpacking::iterableUnpackingConvertingReadStep(seq, _, elem) and
|
||||||
IterableUnpacking::iterableUnpackingConvertingStoreStep(elem, _, nodeFrom) and
|
IterableUnpacking::iterableUnpackingConvertingStoreStep(elem, _, nodeFrom) and
|
||||||
nodeFrom.asCfgNode() instanceof Cfg::SequenceNode
|
nodeFrom.asCfgNode() instanceof SequenceNode
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
TypeTrackerSummaryFlow::basicLoadStep(nodeFrom, nodeTo, DataFlowPublic::singleton(content))
|
TypeTrackerSummaryFlow::basicLoadStep(nodeFrom, nodeTo, DataFlowPublic::singleton(content))
|
||||||
@@ -317,15 +315,13 @@ module TypeTrackingInput implements Shared::TypeTrackingInput<Location> {
|
|||||||
//
|
//
|
||||||
// nodeFrom is `expr`
|
// nodeFrom is `expr`
|
||||||
// nodeTo is entry node for `f`
|
// nodeTo is entry node for `f`
|
||||||
exists(
|
exists(ScopeEntryDefinition e, SsaSourceVariable var, DefinitionNode def |
|
||||||
SsaImpl::ScopeEntryDefinition e, SsaImpl::SsaSourceVariable var, Cfg::DefinitionNode def
|
|
||||||
|
|
|
||||||
e.getSourceVariable() = var and
|
e.getSourceVariable() = var and
|
||||||
def.getNode() = var.getVariable().getAStore()
|
var.hasDefiningNode(def)
|
||||||
|
|
|
|
||||||
nodeTo.(DataFlowPublic::ScopeEntryDefinitionNode).getDefinition() = e and
|
nodeTo.(DataFlowPublic::ScopeEntryDefinitionNode).getDefinition() = e and
|
||||||
nodeFrom.asCfgNode() = def and
|
nodeFrom.asCfgNode() = def and
|
||||||
var.getVariable().getScope().getScope*() = nodeFrom.getScope()
|
var.getScope().getScope*() = nodeFrom.getScope()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,6 @@ overlay[local]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.controlflow.internal.AstNodeImpl as CfgImpl
|
|
||||||
private import semmle.python.dataflow.new.internal.SsaImpl as SsaImpl
|
|
||||||
private import DataFlowPublic
|
private import DataFlowPublic
|
||||||
private import semmle.python.dataflow.new.internal.DataFlowPrivate
|
private import semmle.python.dataflow.new.internal.DataFlowPrivate
|
||||||
private import codeql.dataflow.VariableCapture as Shared
|
private import codeql.dataflow.VariableCapture as Shared
|
||||||
@@ -17,10 +14,10 @@ private import codeql.dataflow.VariableCapture as Shared
|
|||||||
// The first is the main implementation, the second is a performance motivated restriction.
|
// The first is the main implementation, the second is a performance motivated restriction.
|
||||||
// The restriction is to clear any `CapturedVariableContent` before writing a new one
|
// The restriction is to clear any `CapturedVariableContent` before writing a new one
|
||||||
// to avoid long access paths (see the link for a nice explanation).
|
// to avoid long access paths (see the link for a nice explanation).
|
||||||
private module CaptureInput implements Shared::InputSig<Location, CfgImpl::BasicBlock> {
|
private module CaptureInput implements Shared::InputSig<Location, Cfg::BasicBlock> {
|
||||||
private import python as PY
|
private import python as PY
|
||||||
|
|
||||||
additional class ExprCfgNode extends Cfg::ControlFlowNode {
|
additional class ExprCfgNode extends ControlFlowNode {
|
||||||
ExprCfgNode() { isExpressionNode(this) }
|
ExprCfgNode() { isExpressionNode(this) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,9 +25,7 @@ private module CaptureInput implements Shared::InputSig<Location, CfgImpl::Basic
|
|||||||
predicate isConstructor() { none() }
|
predicate isConstructor() { none() }
|
||||||
}
|
}
|
||||||
|
|
||||||
Callable basicBlockGetEnclosingCallable(CfgImpl::BasicBlock bb) {
|
Callable basicBlockGetEnclosingCallable(Cfg::BasicBlock bb) { result = bb.getScope() }
|
||||||
result = bb.getEnclosingCallable().asScope()
|
|
||||||
}
|
|
||||||
|
|
||||||
class CapturedVariable extends LocalVariable {
|
class CapturedVariable extends LocalVariable {
|
||||||
Function f;
|
Function f;
|
||||||
@@ -56,23 +51,21 @@ private module CaptureInput implements Shared::InputSig<Location, CfgImpl::Basic
|
|||||||
class CapturedParameter extends CapturedVariable {
|
class CapturedParameter extends CapturedVariable {
|
||||||
CapturedParameter() { this.isParameter() }
|
CapturedParameter() { this.isParameter() }
|
||||||
|
|
||||||
Cfg::ControlFlowNode getCfgNode() { result.getNode().(Parameter) = this.getAnAccess() }
|
ControlFlowNode getCfgNode() { result.getNode().(Parameter) = this.getAnAccess() }
|
||||||
}
|
}
|
||||||
|
|
||||||
class Expr extends ExprCfgNode {
|
class Expr extends ExprCfgNode {
|
||||||
predicate hasCfgNode(CfgImpl::BasicBlock bb, int i) { this = bb.getNode(i) }
|
predicate hasCfgNode(Cfg::BasicBlock bb, int i) { this = bb.getNode(i) }
|
||||||
}
|
}
|
||||||
|
|
||||||
class VariableWrite extends Cfg::ControlFlowNode {
|
class VariableWrite extends ControlFlowNode {
|
||||||
CapturedVariable v;
|
CapturedVariable v;
|
||||||
|
|
||||||
VariableWrite() {
|
VariableWrite() { exists(DefinitionNode d | d.getNode() = v.getAStore() | this = d.getValue()) }
|
||||||
exists(Cfg::DefinitionNode d | d.getNode() = v.getAStore() | this = d.getValue())
|
|
||||||
}
|
|
||||||
|
|
||||||
CapturedVariable getVariable() { result = v }
|
CapturedVariable getVariable() { result = v }
|
||||||
|
|
||||||
predicate hasCfgNode(CfgImpl::BasicBlock bb, int i) { this = bb.getNode(i) }
|
predicate hasCfgNode(Cfg::BasicBlock bb, int i) { this = bb.getNode(i) }
|
||||||
}
|
}
|
||||||
|
|
||||||
class VariableRead extends Expr {
|
class VariableRead extends Expr {
|
||||||
@@ -87,14 +80,9 @@ private module CaptureInput implements Shared::InputSig<Location, CfgImpl::Basic
|
|||||||
// TODO: Other languages have an extra case here looking like
|
// TODO: Other languages have an extra case here looking like
|
||||||
// simpleAstFlowStep(nodeFrom, nodeTo)
|
// simpleAstFlowStep(nodeFrom, nodeTo)
|
||||||
// we should investigate the potential benefit of adding that.
|
// we should investigate the potential benefit of adding that.
|
||||||
exists(SsaImpl::EssaVariable def |
|
exists(SsaVariable def |
|
||||||
def.getAUse() = nodeTo and
|
def.getAUse() = nodeTo and
|
||||||
def.getAnUltimateDefinition()
|
def.getAnUltimateDefinition().getDefinition().(DefinitionNode).getValue() = nodeFrom
|
||||||
.getDefinition()
|
|
||||||
.(SsaImpl::EssaNodeDefinition)
|
|
||||||
.getDefiningNode()
|
|
||||||
.(Cfg::DefinitionNode)
|
|
||||||
.getValue() = nodeFrom
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +107,7 @@ class CapturedVariable = CaptureInput::CapturedVariable;
|
|||||||
|
|
||||||
class ClosureExpr = CaptureInput::ClosureExpr;
|
class ClosureExpr = CaptureInput::ClosureExpr;
|
||||||
|
|
||||||
module Flow = Shared::Flow<Location, Cfg::CfgSigImpl, CaptureInput>;
|
module Flow = Shared::Flow<Location, Cfg, CaptureInput>;
|
||||||
|
|
||||||
private Flow::ClosureNode asClosureNode(Node n) {
|
private Flow::ClosureNode asClosureNode(Node n) {
|
||||||
result = n.(SynthCaptureNode).getSynthesizedCaptureNode()
|
result = n.(SynthCaptureNode).getSynthesizedCaptureNode()
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.Concepts
|
private import semmle.python.Concepts
|
||||||
private import semmle.python.ApiGraphs
|
private import semmle.python.ApiGraphs
|
||||||
private import semmle.python.dataflow.new.RemoteFlowSources
|
private import semmle.python.dataflow.new.RemoteFlowSources
|
||||||
@@ -158,9 +157,9 @@ module Bottle {
|
|||||||
DataFlow::Node value;
|
DataFlow::Node value;
|
||||||
|
|
||||||
HeaderWriteSubscript() {
|
HeaderWriteSubscript() {
|
||||||
exists(Cfg::SubscriptNode subscript |
|
exists(SubscriptNode subscript |
|
||||||
this.asCfgNode() = subscript and
|
this.asCfgNode() = subscript and
|
||||||
value.asCfgNode() = subscript.(Cfg::DefinitionNode).getValue() and
|
value.asCfgNode() = subscript.(DefinitionNode).getValue() and
|
||||||
name.asCfgNode() = subscript.getIndex() and
|
name.asCfgNode() = subscript.getIndex() and
|
||||||
subscript.getObject() = headers().asSource().asCfgNode()
|
subscript.getObject() = headers().asSource().asCfgNode()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.dataflow.new.RemoteFlowSources
|
private import semmle.python.dataflow.new.RemoteFlowSources
|
||||||
private import semmle.python.dataflow.new.TaintTracking
|
private import semmle.python.dataflow.new.TaintTracking
|
||||||
@@ -1306,7 +1305,7 @@ module PrivateDjango {
|
|||||||
dict.(DataFlow::MethodCallNode).calls(files, "dict")
|
dict.(DataFlow::MethodCallNode).calls(files, "dict")
|
||||||
)
|
)
|
||||||
|
|
|
|
||||||
this.asCfgNode().(Cfg::SubscriptNode).getObject() = dict.asCfgNode()
|
this.asCfgNode().(SubscriptNode).getObject() = dict.asCfgNode()
|
||||||
or
|
or
|
||||||
this.(DataFlow::MethodCallNode).calls(dict, "get")
|
this.(DataFlow::MethodCallNode).calls(dict, "get")
|
||||||
)
|
)
|
||||||
@@ -1315,7 +1314,7 @@ module PrivateDjango {
|
|||||||
exists(DataFlow::AttrRead files, DataFlow::MethodCallNode getlistCall |
|
exists(DataFlow::AttrRead files, DataFlow::MethodCallNode getlistCall |
|
||||||
files.accesses(instance(), "FILES") and
|
files.accesses(instance(), "FILES") and
|
||||||
getlistCall.calls(files, "getlist") and
|
getlistCall.calls(files, "getlist") and
|
||||||
this.asCfgNode().(Cfg::SubscriptNode).getObject() = getlistCall.asCfgNode()
|
this.asCfgNode().(SubscriptNode).getObject() = getlistCall.asCfgNode()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2217,7 +2216,7 @@ module PrivateDjango {
|
|||||||
DataFlow::Node value;
|
DataFlow::Node value;
|
||||||
|
|
||||||
DjangoResponseCookieSubscriptWrite() {
|
DjangoResponseCookieSubscriptWrite() {
|
||||||
exists(Cfg::SubscriptNode subscript, DataFlow::AttrRead cookieLookup |
|
exists(SubscriptNode subscript, DataFlow::AttrRead cookieLookup |
|
||||||
// To give `this` a value, we need to choose between either LHS or RHS,
|
// To give `this` a value, we need to choose between either LHS or RHS,
|
||||||
// and just go with the LHS
|
// and just go with the LHS
|
||||||
this.asCfgNode() = subscript
|
this.asCfgNode() = subscript
|
||||||
@@ -2229,7 +2228,7 @@ module PrivateDjango {
|
|||||||
|
|
|
|
||||||
cookieLookup.flowsTo(subscriptObj)
|
cookieLookup.flowsTo(subscriptObj)
|
||||||
) and
|
) and
|
||||||
value.asCfgNode() = subscript.(Cfg::DefinitionNode).getValue() and
|
value.asCfgNode() = subscript.(DefinitionNode).getValue() and
|
||||||
index.asCfgNode() = subscript.getIndex()
|
index.asCfgNode() = subscript.getIndex()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -2250,7 +2249,7 @@ module PrivateDjango {
|
|||||||
DataFlow::Node value;
|
DataFlow::Node value;
|
||||||
|
|
||||||
DjangoResponseHeaderSubscriptWrite() {
|
DjangoResponseHeaderSubscriptWrite() {
|
||||||
exists(Cfg::SubscriptNode subscript, DataFlow::AttrRead headerLookup |
|
exists(SubscriptNode subscript, DataFlow::AttrRead headerLookup |
|
||||||
// To give `this` a value, we need to choose between either LHS or RHS,
|
// To give `this` a value, we need to choose between either LHS or RHS,
|
||||||
// and just go with the LHS
|
// and just go with the LHS
|
||||||
this.asCfgNode() = subscript
|
this.asCfgNode() = subscript
|
||||||
@@ -2262,7 +2261,7 @@ module PrivateDjango {
|
|||||||
|
|
|
|
||||||
headerLookup.flowsTo(subscriptObj)
|
headerLookup.flowsTo(subscriptObj)
|
||||||
) and
|
) and
|
||||||
value.asCfgNode() = subscript.(Cfg::DefinitionNode).getValue() and
|
value.asCfgNode() = subscript.(DefinitionNode).getValue() and
|
||||||
index.asCfgNode() = subscript.getIndex()
|
index.asCfgNode() = subscript.getIndex()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -2285,14 +2284,14 @@ module PrivateDjango {
|
|||||||
DataFlow::Node value;
|
DataFlow::Node value;
|
||||||
|
|
||||||
DjangoResponseSubscriptWrite() {
|
DjangoResponseSubscriptWrite() {
|
||||||
exists(Cfg::SubscriptNode subscript |
|
exists(SubscriptNode subscript |
|
||||||
// To give `this` a value, we need to choose between either LHS or RHS,
|
// To give `this` a value, we need to choose between either LHS or RHS,
|
||||||
// and just go with the LHS
|
// and just go with the LHS
|
||||||
this.asCfgNode() = subscript
|
this.asCfgNode() = subscript
|
||||||
|
|
|
|
||||||
subscript.getObject() =
|
subscript.getObject() =
|
||||||
DjangoImpl::DjangoHttp::Response::HttpResponse::instance().asCfgNode() and
|
DjangoImpl::DjangoHttp::Response::HttpResponse::instance().asCfgNode() and
|
||||||
value.asCfgNode() = subscript.(Cfg::DefinitionNode).getValue() and
|
value.asCfgNode() = subscript.(DefinitionNode).getValue() and
|
||||||
index.asCfgNode() = subscript.getIndex()
|
index.asCfgNode() = subscript.getIndex()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -2427,7 +2426,7 @@ module PrivateDjango {
|
|||||||
/** Gets a reference to the result of calling the `as_view` classmethod of this class. */
|
/** Gets a reference to the result of calling the `as_view` classmethod of this class. */
|
||||||
private DataFlow::TypeTrackingNode asViewResult(DataFlow::TypeTracker t) {
|
private DataFlow::TypeTrackingNode asViewResult(DataFlow::TypeTracker t) {
|
||||||
t.start() and
|
t.start() and
|
||||||
result.asCfgNode().(Cfg::CallNode).getFunction() = this.asViewRef().asCfgNode()
|
result.asCfgNode().(CallNode).getFunction() = this.asViewRef().asCfgNode()
|
||||||
or
|
or
|
||||||
exists(DataFlow::TypeTracker t2 | result = this.asViewResult(t2).track(t2, t))
|
exists(DataFlow::TypeTracker t2 | result = this.asViewResult(t2).track(t2, t))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.dataflow.new.RemoteFlowSources
|
private import semmle.python.dataflow.new.RemoteFlowSources
|
||||||
private import semmle.python.dataflow.new.TaintTracking
|
private import semmle.python.dataflow.new.TaintTracking
|
||||||
@@ -442,7 +441,7 @@ module FastApi {
|
|||||||
DataFlow::Node value;
|
DataFlow::Node value;
|
||||||
|
|
||||||
HeaderSubscriptWrite() {
|
HeaderSubscriptWrite() {
|
||||||
exists(Cfg::SubscriptNode subscript, DataFlow::AttrRead headerLookup |
|
exists(SubscriptNode subscript, DataFlow::AttrRead headerLookup |
|
||||||
// To give `this` a value, we need to choose between either LHS or RHS,
|
// To give `this` a value, we need to choose between either LHS or RHS,
|
||||||
// and just go with the LHS
|
// and just go with the LHS
|
||||||
this.asCfgNode() = subscript
|
this.asCfgNode() = subscript
|
||||||
@@ -451,7 +450,7 @@ module FastApi {
|
|||||||
exists(DataFlow::Node subscriptObj | subscriptObj.asCfgNode() = subscript.getObject() |
|
exists(DataFlow::Node subscriptObj | subscriptObj.asCfgNode() = subscript.getObject() |
|
||||||
headerLookup.flowsTo(subscriptObj)
|
headerLookup.flowsTo(subscriptObj)
|
||||||
) and
|
) and
|
||||||
value.asCfgNode() = subscript.(Cfg::DefinitionNode).getValue() and
|
value.asCfgNode() = subscript.(DefinitionNode).getValue() and
|
||||||
index.asCfgNode() = subscript.getIndex()
|
index.asCfgNode() = subscript.getIndex()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import python
|
import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
import semmle.python.dataflow.new.RemoteFlowSources
|
import semmle.python.dataflow.new.RemoteFlowSources
|
||||||
import semmle.python.dataflow.new.TaintTracking
|
import semmle.python.dataflow.new.TaintTracking
|
||||||
import semmle.python.ApiGraphs
|
import semmle.python.ApiGraphs
|
||||||
@@ -52,9 +51,9 @@ module Gradio {
|
|||||||
// limit only to lists of parameters given to `inputs`.
|
// limit only to lists of parameters given to `inputs`.
|
||||||
(
|
(
|
||||||
(
|
(
|
||||||
call.getKeywordParameter("inputs").asSink().asCfgNode() instanceof Cfg::ListNode
|
call.getKeywordParameter("inputs").asSink().asCfgNode() instanceof ListNode
|
||||||
or
|
or
|
||||||
call.getParameter(1).asSink().asCfgNode() instanceof Cfg::ListNode
|
call.getParameter(1).asSink().asCfgNode() instanceof ListNode
|
||||||
) and
|
) and
|
||||||
(
|
(
|
||||||
this = call.getKeywordParameter("inputs").getASubscript().getAValueReachingSink()
|
this = call.getKeywordParameter("inputs").getASubscript().getAValueReachingSink()
|
||||||
@@ -76,8 +75,8 @@ module Gradio {
|
|||||||
exists(GradioInput call |
|
exists(GradioInput call |
|
||||||
this = call.getParameter(0, "fn").getParameter(_).asSource() and
|
this = call.getParameter(0, "fn").getParameter(_).asSource() and
|
||||||
// exclude lists of parameters given to `inputs`
|
// exclude lists of parameters given to `inputs`
|
||||||
not call.getKeywordParameter("inputs").asSink().asCfgNode() instanceof Cfg::ListNode and
|
not call.getKeywordParameter("inputs").asSink().asCfgNode() instanceof ListNode and
|
||||||
not call.getParameter(1).asSink().asCfgNode() instanceof Cfg::ListNode
|
not call.getParameter(1).asSink().asCfgNode() instanceof ListNode
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,16 +105,16 @@ module Gradio {
|
|||||||
// handle cases where there are multiple arguments passed as a list to `inputs`
|
// handle cases where there are multiple arguments passed as a list to `inputs`
|
||||||
(
|
(
|
||||||
(
|
(
|
||||||
node.getKeywordParameter("inputs").asSink().asCfgNode() instanceof Cfg::ListNode
|
node.getKeywordParameter("inputs").asSink().asCfgNode() instanceof ListNode
|
||||||
or
|
or
|
||||||
node.getParameter(1).asSink().asCfgNode() instanceof Cfg::ListNode
|
node.getParameter(1).asSink().asCfgNode() instanceof ListNode
|
||||||
) and
|
) and
|
||||||
exists(int i | nodeTo = node.getParameter(0, "fn").getParameter(i).asSource() |
|
exists(int i | nodeTo = node.getParameter(0, "fn").getParameter(i).asSource() |
|
||||||
nodeFrom.asCfgNode() =
|
nodeFrom.asCfgNode() =
|
||||||
node.getKeywordParameter("inputs").asSink().asCfgNode().(Cfg::ListNode).getElement(i)
|
node.getKeywordParameter("inputs").asSink().asCfgNode().(ListNode).getElement(i)
|
||||||
or
|
or
|
||||||
nodeFrom.asCfgNode() =
|
nodeFrom.asCfgNode() =
|
||||||
node.getParameter(1).asSink().asCfgNode().(Cfg::ListNode).getElement(i)
|
node.getParameter(1).asSink().asCfgNode().(ListNode).getElement(i)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.dataflow.new.TaintTracking
|
private import semmle.python.dataflow.new.TaintTracking
|
||||||
private import semmle.python.Concepts
|
private import semmle.python.Concepts
|
||||||
@@ -47,7 +46,7 @@ module MarkupSafeModel {
|
|||||||
|
|
||||||
/** A direct instantiation of `markupsafe.Markup`. */
|
/** A direct instantiation of `markupsafe.Markup`. */
|
||||||
private class ClassInstantiation extends InstanceSource, DataFlow::CallCfgNode {
|
private class ClassInstantiation extends InstanceSource, DataFlow::CallCfgNode {
|
||||||
override Cfg::CallNode node;
|
override CallNode node;
|
||||||
|
|
||||||
ClassInstantiation() { this = classRef().getACall() }
|
ClassInstantiation() { this = classRef().getACall() }
|
||||||
}
|
}
|
||||||
@@ -65,7 +64,7 @@ module MarkupSafeModel {
|
|||||||
|
|
||||||
/** A string concatenation with a `markupsafe.Markup` involved. */
|
/** A string concatenation with a `markupsafe.Markup` involved. */
|
||||||
class StringConcat extends Markup::InstanceSource, DataFlow::CfgNode {
|
class StringConcat extends Markup::InstanceSource, DataFlow::CfgNode {
|
||||||
override Cfg::BinaryExprNode node;
|
override BinaryExprNode node;
|
||||||
|
|
||||||
StringConcat() {
|
StringConcat() {
|
||||||
node.getOp() instanceof Add and
|
node.getOp() instanceof Add and
|
||||||
@@ -80,7 +79,7 @@ module MarkupSafeModel {
|
|||||||
|
|
||||||
/** A %-style string format with `markupsafe.Markup` as the format string. */
|
/** A %-style string format with `markupsafe.Markup` as the format string. */
|
||||||
class PercentStringFormat extends Markup::InstanceSource, DataFlow::CfgNode {
|
class PercentStringFormat extends Markup::InstanceSource, DataFlow::CfgNode {
|
||||||
override Cfg::BinaryExprNode node;
|
override BinaryExprNode node;
|
||||||
|
|
||||||
PercentStringFormat() {
|
PercentStringFormat() {
|
||||||
node.getOp() instanceof Mod and
|
node.getOp() instanceof Mod and
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.Concepts
|
private import semmle.python.Concepts
|
||||||
private import semmle.python.ApiGraphs
|
private import semmle.python.ApiGraphs
|
||||||
private import semmle.python.frameworks.data.ModelsAsData
|
private import semmle.python.frameworks.data.ModelsAsData
|
||||||
@@ -57,7 +56,7 @@ module Pycurl {
|
|||||||
{
|
{
|
||||||
OutgoingRequestCall() {
|
OutgoingRequestCall() {
|
||||||
this = setopt().getACall() and
|
this = setopt().getACall() and
|
||||||
this.getArg(0).asCfgNode().(Cfg::AttrNode).getName() = "URL"
|
this.getArg(0).asCfgNode().(AttrNode).getName() = "URL"
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getAUrlPart() {
|
override DataFlow::Node getAUrlPart() {
|
||||||
@@ -82,7 +81,7 @@ module Pycurl {
|
|||||||
private class CurlSslCall extends Http::Client::Request::Range instanceof DataFlow::CallCfgNode {
|
private class CurlSslCall extends Http::Client::Request::Range instanceof DataFlow::CallCfgNode {
|
||||||
CurlSslCall() {
|
CurlSslCall() {
|
||||||
this = setopt().getACall() and
|
this = setopt().getACall() and
|
||||||
this.getArg(0).asCfgNode().(Cfg::AttrNode).getName() = ["SSL_VERIFYPEER", "SSL_VERIFYHOST"]
|
this.getArg(0).asCfgNode().(AttrNode).getName() = ["SSL_VERIFYPEER", "SSL_VERIFYHOST"]
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getAUrlPart() { none() }
|
override DataFlow::Node getAUrlPart() { none() }
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.dataflow.new.TaintTracking
|
private import semmle.python.dataflow.new.TaintTracking
|
||||||
private import semmle.python.Concepts
|
private import semmle.python.Concepts
|
||||||
@@ -94,7 +93,7 @@ module Pydantic {
|
|||||||
// be a Pydantic model. So `model[0]` will be an overapproximation, but should not
|
// be a Pydantic model. So `model[0]` will be an overapproximation, but should not
|
||||||
// really cause problems (since we don't expect real code to contain such accesses)
|
// really cause problems (since we don't expect real code to contain such accesses)
|
||||||
nodeFrom = instance() and
|
nodeFrom = instance() and
|
||||||
nodeTo.asCfgNode().(Cfg::SubscriptNode).getObject() = nodeFrom.asCfgNode()
|
nodeTo.asCfgNode().(SubscriptNode).getObject() = nodeFrom.asCfgNode()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ overlay[local?]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.dataflow.new.TaintTracking
|
private import semmle.python.dataflow.new.TaintTracking
|
||||||
private import semmle.python.dataflow.new.RemoteFlowSources
|
private import semmle.python.dataflow.new.RemoteFlowSources
|
||||||
@@ -1247,7 +1246,7 @@ module StdlibPrivate {
|
|||||||
/** An additional taint step for calls to `os.path.join` */
|
/** An additional taint step for calls to `os.path.join` */
|
||||||
private class OsPathJoinCallAdditionalTaintStep extends TaintTracking::AdditionalTaintStep {
|
private class OsPathJoinCallAdditionalTaintStep extends TaintTracking::AdditionalTaintStep {
|
||||||
override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||||
exists(Cfg::CallNode call |
|
exists(CallNode call |
|
||||||
nodeTo.asCfgNode() = call and
|
nodeTo.asCfgNode() = call and
|
||||||
call = OS::OsPath::join().getACall().asCfgNode() and
|
call = OS::OsPath::join().getACall().asCfgNode() and
|
||||||
call.getAnArg() = nodeFrom.asCfgNode()
|
call.getAnArg() = nodeFrom.asCfgNode()
|
||||||
@@ -1318,13 +1317,13 @@ module StdlibPrivate {
|
|||||||
// run, so if we're able to, we only mark the first element as the command
|
// run, so if we're able to, we only mark the first element as the command
|
||||||
// (and not the arguments to the command).
|
// (and not the arguments to the command).
|
||||||
//
|
//
|
||||||
result.asCfgNode() = arg_args.asCfgNode().(Cfg::SequenceNode).getElement(0)
|
result.asCfgNode() = arg_args.asCfgNode().(SequenceNode).getElement(0)
|
||||||
or
|
or
|
||||||
// Either the "args" argument is not a sequence (which is valid) or we where
|
// Either the "args" argument is not a sequence (which is valid) or we where
|
||||||
// just not able to figure it out. Simply mark the "args" argument as the
|
// just not able to figure it out. Simply mark the "args" argument as the
|
||||||
// command.
|
// command.
|
||||||
//
|
//
|
||||||
not arg_args.asCfgNode() instanceof Cfg::SequenceNode and
|
not arg_args.asCfgNode() instanceof SequenceNode and
|
||||||
result = arg_args
|
result = arg_args
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1543,7 +1542,7 @@ module StdlibPrivate {
|
|||||||
* See https://docs.python.org/3/library/functions.html#eval
|
* See https://docs.python.org/3/library/functions.html#eval
|
||||||
*/
|
*/
|
||||||
private class BuiltinsEvalCall extends CodeExecution::Range, DataFlow::CallCfgNode {
|
private class BuiltinsEvalCall extends CodeExecution::Range, DataFlow::CallCfgNode {
|
||||||
override Cfg::CallNode node;
|
override CallNode node;
|
||||||
|
|
||||||
BuiltinsEvalCall() { this = API::builtin("eval").getACall() }
|
BuiltinsEvalCall() { this = API::builtin("eval").getACall() }
|
||||||
|
|
||||||
@@ -1924,7 +1923,7 @@ module StdlibPrivate {
|
|||||||
nodeFrom = instance().getAValueReachableFromSource() and
|
nodeFrom = instance().getAValueReachableFromSource() and
|
||||||
nodeTo = [getvalueRef(), getfirstRef(), getlistRef()].getAValueReachableFromSource()
|
nodeTo = [getvalueRef(), getfirstRef(), getlistRef()].getAValueReachableFromSource()
|
||||||
or
|
or
|
||||||
nodeFrom.asCfgNode() = nodeTo.asCfgNode().(Cfg::CallNode).getFunction() and
|
nodeFrom.asCfgNode() = nodeTo.asCfgNode().(CallNode).getFunction() and
|
||||||
(
|
(
|
||||||
nodeFrom = getvalueRef().getAValueReachableFromSource() and
|
nodeFrom = getvalueRef().getAValueReachableFromSource() and
|
||||||
nodeTo = getvalueResult().asSource()
|
nodeTo = getvalueResult().asSource()
|
||||||
@@ -1940,7 +1939,7 @@ module StdlibPrivate {
|
|||||||
nodeFrom in [
|
nodeFrom in [
|
||||||
instance().getAValueReachableFromSource(), fieldList().getAValueReachableFromSource()
|
instance().getAValueReachableFromSource(), fieldList().getAValueReachableFromSource()
|
||||||
] and
|
] and
|
||||||
nodeTo.asCfgNode().(Cfg::SubscriptNode).getObject() = nodeFrom.asCfgNode()
|
nodeTo.asCfgNode().(SubscriptNode).getObject() = nodeFrom.asCfgNode()
|
||||||
or
|
or
|
||||||
// Attributes on Field
|
// Attributes on Field
|
||||||
nodeFrom = field().getAValueReachableFromSource() and
|
nodeFrom = field().getAValueReachableFromSource() and
|
||||||
@@ -2255,8 +2254,8 @@ module StdlibPrivate {
|
|||||||
DataFlow::CfgNode
|
DataFlow::CfgNode
|
||||||
{
|
{
|
||||||
WsgirefSimpleServerApplicationReturn() {
|
WsgirefSimpleServerApplicationReturn() {
|
||||||
exists(Return ret |
|
exists(WsgirefSimpleServerApplication requestHandler, Return ret |
|
||||||
ret.getScope() = any(WsgirefSimpleServerApplication requestHandler) and
|
ret.getScope() = requestHandler and
|
||||||
node.getNode() = ret.getValue()
|
node.getNode() = ret.getValue()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -2339,9 +2338,9 @@ module StdlibPrivate {
|
|||||||
DataFlow::Node value;
|
DataFlow::Node value;
|
||||||
|
|
||||||
HeaderWriteSubscript() {
|
HeaderWriteSubscript() {
|
||||||
exists(Cfg::SubscriptNode subscript |
|
exists(SubscriptNode subscript |
|
||||||
this.asCfgNode() = subscript and
|
this.asCfgNode() = subscript and
|
||||||
value.asCfgNode() = subscript.(Cfg::DefinitionNode).getValue() and
|
value.asCfgNode() = subscript.(DefinitionNode).getValue() and
|
||||||
name.asCfgNode() = subscript.getIndex() and
|
name.asCfgNode() = subscript.getIndex() and
|
||||||
subscript.getObject() = instance().asCfgNode()
|
subscript.getObject() = instance().asCfgNode()
|
||||||
)
|
)
|
||||||
@@ -2683,7 +2682,7 @@ module StdlibPrivate {
|
|||||||
or
|
or
|
||||||
// Data injection
|
// Data injection
|
||||||
// Special handling of the `/` operator
|
// Special handling of the `/` operator
|
||||||
exists(Cfg::BinaryExprNode slash, DataFlow::Node pathOperand, DataFlow::TypeTracker t2 |
|
exists(BinaryExprNode slash, DataFlow::Node pathOperand, DataFlow::TypeTracker t2 |
|
||||||
slash.getOp() instanceof Div and
|
slash.getOp() instanceof Div and
|
||||||
pathOperand.asCfgNode() = slash.getAnOperand() and
|
pathOperand.asCfgNode() = slash.getAnOperand() and
|
||||||
pathlibPath(t2).flowsTo(pathOperand) and
|
pathlibPath(t2).flowsTo(pathOperand) and
|
||||||
@@ -2808,7 +2807,7 @@ module StdlibPrivate {
|
|||||||
pathlibPath().flowsTo(nodeTo) and
|
pathlibPath().flowsTo(nodeTo) and
|
||||||
(
|
(
|
||||||
// Special handling of the `/` operator
|
// Special handling of the `/` operator
|
||||||
exists(Cfg::BinaryExprNode slash, DataFlow::Node pathOperand |
|
exists(BinaryExprNode slash, DataFlow::Node pathOperand |
|
||||||
slash.getOp() instanceof Div and
|
slash.getOp() instanceof Div and
|
||||||
pathOperand.asCfgNode() = slash.getAnOperand() and
|
pathOperand.asCfgNode() = slash.getAnOperand() and
|
||||||
pathlibPath().flowsTo(pathOperand)
|
pathlibPath().flowsTo(pathOperand)
|
||||||
@@ -4606,9 +4605,9 @@ module StdlibPrivate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||||
exists(Cfg::CallNode c, string name, Cfg::ControlFlowNode n, DataFlow::AttributeContent ac |
|
exists(CallNode c, string name, ControlFlowNode n, DataFlow::AttributeContent ac |
|
||||||
c.getFunction().(Cfg::NameNode).getId() = "replace" or
|
c.getFunction().(NameNode).getId() = "replace" or
|
||||||
c.getFunction().(Cfg::AttrNode).getName() = "replace"
|
c.getFunction().(AttrNode).getName() = "replace"
|
||||||
|
|
|
|
||||||
n = c.getArgByName(name) and
|
n = c.getArgByName(name) and
|
||||||
ac.getAttribute() = name and
|
ac.getAttribute() = name and
|
||||||
@@ -5172,10 +5171,10 @@ module StdlibPrivate {
|
|||||||
* See https://docs.python.org/3.9/library/stdtypes.html#str.startswith
|
* See https://docs.python.org/3.9/library/stdtypes.html#str.startswith
|
||||||
*/
|
*/
|
||||||
private class StartswithCall extends Path::SafeAccessCheck::Range {
|
private class StartswithCall extends Path::SafeAccessCheck::Range {
|
||||||
StartswithCall() { this.(Cfg::CallNode).getFunction().(Cfg::AttrNode).getName() = "startswith" }
|
StartswithCall() { this.(CallNode).getFunction().(AttrNode).getName() = "startswith" }
|
||||||
|
|
||||||
override predicate checks(Cfg::ControlFlowNode node, boolean branch) {
|
override predicate checks(ControlFlowNode node, boolean branch) {
|
||||||
node = this.(Cfg::CallNode).getFunction().(Cfg::AttrNode).getObject() and
|
node = this.(CallNode).getFunction().(AttrNode).getObject() and
|
||||||
branch = true
|
branch = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.Concepts
|
private import semmle.python.Concepts
|
||||||
private import semmle.python.ApiGraphs
|
private import semmle.python.ApiGraphs
|
||||||
private import semmle.python.security.dataflow.UrlRedirectCustomizations
|
private import semmle.python.security.dataflow.UrlRedirectCustomizations
|
||||||
@@ -92,7 +91,7 @@ private module Urllib {
|
|||||||
* A read of the `netloc` attribute of a parsed URL as returned by `urllib.parse.urlparse`,
|
* A read of the `netloc` attribute of a parsed URL as returned by `urllib.parse.urlparse`,
|
||||||
* which is being checked in a way that is relevant for URL redirection vulnerabilities.
|
* which is being checked in a way that is relevant for URL redirection vulnerabilities.
|
||||||
*/
|
*/
|
||||||
private predicate netlocCheck(DataFlow::GuardNode g, Cfg::ControlFlowNode node, boolean branch) {
|
private predicate netlocCheck(DataFlow::GuardNode g, ControlFlowNode node, boolean branch) {
|
||||||
exists(DataFlow::CallCfgNode urlParseCall, DataFlow::AttrRead netlocRead |
|
exists(DataFlow::CallCfgNode urlParseCall, DataFlow::AttrRead netlocRead |
|
||||||
urlParseCall = getUrlParseCall() and
|
urlParseCall = getUrlParseCall() and
|
||||||
netlocRead = urlParseCall.getAnAttributeRead("netloc") and
|
netlocRead = urlParseCall.getAnAttributeRead("netloc") and
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.dataflow.new.RemoteFlowSources
|
private import semmle.python.dataflow.new.RemoteFlowSources
|
||||||
private import semmle.python.dataflow.new.TaintTracking
|
private import semmle.python.dataflow.new.TaintTracking
|
||||||
@@ -73,9 +72,9 @@ module Tornado {
|
|||||||
DataFlow::Node value;
|
DataFlow::Node value;
|
||||||
|
|
||||||
TornadoHeaderSubscriptWrite() {
|
TornadoHeaderSubscriptWrite() {
|
||||||
exists(Cfg::SubscriptNode subscript |
|
exists(SubscriptNode subscript |
|
||||||
subscript.getObject() = instance().asCfgNode() and
|
subscript.getObject() = instance().asCfgNode() and
|
||||||
value.asCfgNode() = subscript.(Cfg::DefinitionNode).getValue() and
|
value.asCfgNode() = subscript.(DefinitionNode).getValue() and
|
||||||
index.asCfgNode() = subscript.getIndex() and
|
index.asCfgNode() = subscript.getIndex() and
|
||||||
this.asCfgNode() = subscript
|
this.asCfgNode() = subscript
|
||||||
)
|
)
|
||||||
@@ -423,7 +422,7 @@ module Tornado {
|
|||||||
// be able to do something more structured for providing modeling of the members
|
// be able to do something more structured for providing modeling of the members
|
||||||
// of a container-object.
|
// of a container-object.
|
||||||
exists(DataFlow::AttrRead files | files.accesses(instance(), "cookies") |
|
exists(DataFlow::AttrRead files | files.accesses(instance(), "cookies") |
|
||||||
this.asCfgNode().(Cfg::SubscriptNode).getObject() = files.asCfgNode()
|
this.asCfgNode().(SubscriptNode).getObject() = files.asCfgNode()
|
||||||
or
|
or
|
||||||
this.(DataFlow::MethodCallNode).calls(files, "get")
|
this.(DataFlow::MethodCallNode).calls(files, "get")
|
||||||
)
|
)
|
||||||
@@ -480,20 +479,20 @@ module Tornado {
|
|||||||
// routing
|
// routing
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** Gets a sequence that defines a number of route rules */
|
/** Gets a sequence that defines a number of route rules */
|
||||||
Cfg::SequenceNode routeSetupRuleList() {
|
SequenceNode routeSetupRuleList() {
|
||||||
exists(Cfg::CallNode call |
|
exists(CallNode call |
|
||||||
call = any(TornadoModule::Web::Application::ClassInstantiation c).asCfgNode()
|
call = any(TornadoModule::Web::Application::ClassInstantiation c).asCfgNode()
|
||||||
|
|
|
|
||||||
result in [call.getArg(0), call.getArgByName("handlers")]
|
result in [call.getArg(0), call.getArgByName("handlers")]
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(Cfg::CallNode call |
|
exists(CallNode call |
|
||||||
call.getFunction() = TornadoModule::Web::Application::add_handlers().asCfgNode()
|
call.getFunction() = TornadoModule::Web::Application::add_handlers().asCfgNode()
|
||||||
|
|
|
|
||||||
result in [call.getArg(1), call.getArgByName("host_handlers")]
|
result in [call.getArg(1), call.getArgByName("host_handlers")]
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
result = routeSetupRuleList().getElement(_).(Cfg::TupleNode).getElement(1)
|
result = routeSetupRuleList().getElement(_).(TupleNode).getElement(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A tornado route setup. */
|
/** A tornado route setup. */
|
||||||
@@ -516,12 +515,12 @@ module Tornado {
|
|||||||
|
|
||||||
/** A route setup using a tuple. */
|
/** A route setup using a tuple. */
|
||||||
private class TornadoTupleRouteSetup extends TornadoRouteSetup, DataFlow::CfgNode {
|
private class TornadoTupleRouteSetup extends TornadoRouteSetup, DataFlow::CfgNode {
|
||||||
override Cfg::TupleNode node;
|
override TupleNode node;
|
||||||
|
|
||||||
TornadoTupleRouteSetup() {
|
TornadoTupleRouteSetup() {
|
||||||
node = routeSetupRuleList().getElement(_) and
|
node = routeSetupRuleList().getElement(_) and
|
||||||
count(node.getElement(_)) = 2 and
|
count(node.getElement(_)) = 2 and
|
||||||
not node.getElement(1) instanceof Cfg::SequenceNode
|
not node.getElement(1) instanceof SequenceNode
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getUrlPatternArg() { result.asCfgNode() = node.getElement(0) }
|
override DataFlow::Node getUrlPatternArg() { result.asCfgNode() = node.getElement(0) }
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.dataflow.new.TaintTracking
|
private import semmle.python.dataflow.new.TaintTracking
|
||||||
private import semmle.python.ApiGraphs
|
private import semmle.python.ApiGraphs
|
||||||
@@ -222,9 +221,9 @@ module Werkzeug {
|
|||||||
DataFlow::Node value;
|
DataFlow::Node value;
|
||||||
|
|
||||||
HeaderWriteSubscript() {
|
HeaderWriteSubscript() {
|
||||||
exists(Cfg::SubscriptNode subscript |
|
exists(SubscriptNode subscript |
|
||||||
this.asCfgNode() = subscript and
|
this.asCfgNode() = subscript and
|
||||||
value.asCfgNode() = subscript.(Cfg::DefinitionNode).getValue() and
|
value.asCfgNode() = subscript.(DefinitionNode).getValue() and
|
||||||
name.asCfgNode() = subscript.getIndex() and
|
name.asCfgNode() = subscript.getIndex() and
|
||||||
subscript.getObject() = instance().asCfgNode()
|
subscript.getObject() = instance().asCfgNode()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.Concepts
|
private import semmle.python.Concepts
|
||||||
private import semmle.python.ApiGraphs
|
private import semmle.python.ApiGraphs
|
||||||
@@ -29,7 +28,7 @@ private module Yaml {
|
|||||||
* See https://pyyaml.org/wiki/PyYAMLDocumentation (you will have to scroll down).
|
* See https://pyyaml.org/wiki/PyYAMLDocumentation (you will have to scroll down).
|
||||||
*/
|
*/
|
||||||
private class YamlLoadCall extends Decoding::Range, DataFlow::CallCfgNode {
|
private class YamlLoadCall extends Decoding::Range, DataFlow::CallCfgNode {
|
||||||
override Cfg::CallNode node;
|
override CallNode node;
|
||||||
string func_name;
|
string func_name;
|
||||||
|
|
||||||
YamlLoadCall() {
|
YamlLoadCall() {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.dataflow.new.TaintTracking
|
private import semmle.python.dataflow.new.TaintTracking
|
||||||
private import semmle.python.Concepts
|
private import semmle.python.Concepts
|
||||||
@@ -112,7 +111,7 @@ module Yarl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate yarlUrlIsAbsoluteCall(
|
private predicate yarlUrlIsAbsoluteCall(
|
||||||
DataFlow::GuardNode g, Cfg::ControlFlowNode node, boolean branch
|
DataFlow::GuardNode g, ControlFlowNode node, boolean branch
|
||||||
) {
|
) {
|
||||||
exists(ClassInstantiation instance, DataFlow::MethodCallNode call |
|
exists(ClassInstantiation instance, DataFlow::MethodCallNode call |
|
||||||
call.calls(instance, "is_absolute") and
|
call.calls(instance, "is_absolute") and
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ private import semmle.python.dataflow.new.internal.ImportResolution
|
|||||||
private import semmle.python.ApiGraphs
|
private import semmle.python.ApiGraphs
|
||||||
private import semmle.python.filters.Tests
|
private import semmle.python.filters.Tests
|
||||||
private import semmle.python.Module
|
private import semmle.python.Module
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
|
|
||||||
// very much inspired by the draft at https://github.com/github/codeql/pull/5632
|
// very much inspired by the draft at https://github.com/github/codeql/pull/5632
|
||||||
module NotExposed {
|
module NotExposed {
|
||||||
@@ -207,7 +206,7 @@ module NotExposed {
|
|||||||
string relevantName, Location loc
|
string relevantName, Location loc
|
||||||
) {
|
) {
|
||||||
loc = mod.getLocation() and
|
loc = mod.getLocation() and
|
||||||
exists(API::Node relevantClass, Cfg::ControlFlowNode value |
|
exists(API::Node relevantClass, ControlFlowNode value |
|
||||||
relevantClass = newOrExistingModeling(spec).getASubclass*() and
|
relevantClass = newOrExistingModeling(spec).getASubclass*() and
|
||||||
ImportResolution::module_export(mod, relevantName, def) and
|
ImportResolution::module_export(mod, relevantName, def) and
|
||||||
value = relevantClass.getAValueReachableFromSource().asCfgNode() and
|
value = relevantClass.getAValueReachableFromSource().asCfgNode() and
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import python
|
import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.Concepts as Concepts
|
private import semmle.python.Concepts as Concepts
|
||||||
private import semmle.python.regex
|
private import semmle.python.regex
|
||||||
@@ -79,7 +78,7 @@ private module FindRegexMode {
|
|||||||
t.start() and
|
t.start() and
|
||||||
exists(API::Node flag | flag_name = canonical_name(flag) and result = flag.asSource())
|
exists(API::Node flag | flag_name = canonical_name(flag) and result = flag.asSource())
|
||||||
or
|
or
|
||||||
exists(Cfg::BinaryExprNode binop, DataFlow::Node operand |
|
exists(BinaryExprNode binop, DataFlow::Node operand |
|
||||||
operand.getALocalSource() = re_flag_tracker(flag_name, t.continue()) and
|
operand.getALocalSource() = re_flag_tracker(flag_name, t.continue()) and
|
||||||
operand.asCfgNode() = binop.getAnOperand() and
|
operand.asCfgNode() = binop.getAnOperand() and
|
||||||
(binop.getOp() instanceof BitOr or binop.getOp() instanceof Add) and
|
(binop.getOp() instanceof BitOr or binop.getOp() instanceof Add) and
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
import python
|
import python
|
||||||
import semmle.python.dataflow.new.DataFlow
|
import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.ApiGraphs
|
private import semmle.python.ApiGraphs
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* INTERNAL: Do not use.
|
* INTERNAL: Do not use.
|
||||||
@@ -30,7 +29,7 @@ private class TracebackFunctionCall extends ExceptionInfo, DataFlow::CallCfgNode
|
|||||||
private class CaughtException extends ExceptionInfo {
|
private class CaughtException extends ExceptionInfo {
|
||||||
CaughtException() {
|
CaughtException() {
|
||||||
this.asExpr() = any(ExceptStmt s).getName() and
|
this.asExpr() = any(ExceptStmt s).getName() and
|
||||||
this.asCfgNode().(Cfg::NameNode).defines(_)
|
this.asCfgNode() = any(EssaNodeDefinition def).getDefiningNode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ private import semmle.python.dataflow.new.RemoteFlowSources
|
|||||||
private import semmle.python.dataflow.new.BarrierGuards
|
private import semmle.python.dataflow.new.BarrierGuards
|
||||||
private import semmle.python.ApiGraphs
|
private import semmle.python.ApiGraphs
|
||||||
private import semmle.python.frameworks.data.internal.ApiGraphModels
|
private import semmle.python.frameworks.data.internal.ApiGraphModels
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides default sources, sinks and sanitizers for detecting
|
* Provides default sources, sinks and sanitizers for detecting
|
||||||
@@ -96,7 +95,7 @@ module ServerSideRequestForgery {
|
|||||||
class StringConstructionAsFullUrlControlSanitizer extends FullUrlControlSanitizer {
|
class StringConstructionAsFullUrlControlSanitizer extends FullUrlControlSanitizer {
|
||||||
StringConstructionAsFullUrlControlSanitizer() {
|
StringConstructionAsFullUrlControlSanitizer() {
|
||||||
// string concat
|
// string concat
|
||||||
exists(Cfg::BinaryExprNode add |
|
exists(BinaryExprNode add |
|
||||||
add.getOp() instanceof Add and
|
add.getOp() instanceof Add and
|
||||||
add.getRight() = this.asCfgNode() and
|
add.getRight() = this.asCfgNode() and
|
||||||
not add.getLeft().getNode().(StringLiteral).getText().toLowerCase() in [
|
not add.getLeft().getNode().(StringLiteral).getText().toLowerCase() in [
|
||||||
@@ -105,7 +104,7 @@ module ServerSideRequestForgery {
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
// % formatting
|
// % formatting
|
||||||
exists(Cfg::BinaryExprNode fmt |
|
exists(BinaryExprNode fmt |
|
||||||
fmt.getOp() instanceof Mod and
|
fmt.getOp() instanceof Mod and
|
||||||
fmt.getRight() = this.asCfgNode() and
|
fmt.getRight() = this.asCfgNode() and
|
||||||
// detecting %-formatting is not super easy, so we simplify it to only handle
|
// detecting %-formatting is not super easy, so we simplify it to only handle
|
||||||
@@ -156,9 +155,7 @@ module ServerSideRequestForgery {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate stringRestriction(
|
private predicate stringRestriction(DataFlow::GuardNode g, ControlFlowNode node, boolean branch) {
|
||||||
DataFlow::GuardNode g, Cfg::ControlFlowNode node, boolean branch
|
|
||||||
) {
|
|
||||||
exists(DataFlow::MethodCallNode call, DataFlow::Node strNode |
|
exists(DataFlow::MethodCallNode call, DataFlow::Node strNode |
|
||||||
call.asCfgNode() = g and strNode.asCfgNode() = node
|
call.asCfgNode() = g and strNode.asCfgNode() = node
|
||||||
|
|
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ private import semmle.python.dataflow.new.DataFlow
|
|||||||
private import semmle.python.Concepts
|
private import semmle.python.Concepts
|
||||||
private import semmle.python.dataflow.new.BarrierGuards
|
private import semmle.python.dataflow.new.BarrierGuards
|
||||||
private import semmle.python.ApiGraphs
|
private import semmle.python.ApiGraphs
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides default sources, sinks and sanitizers for detecting
|
* Provides default sources, sinks and sanitizers for detecting
|
||||||
@@ -140,8 +139,8 @@ module TarSlip {
|
|||||||
* where `<check_path>` is any function matching `"%path"`.
|
* where `<check_path>` is any function matching `"%path"`.
|
||||||
* `info` is assumed to be a `TarInfo` instance.
|
* `info` is assumed to be a `TarInfo` instance.
|
||||||
*/
|
*/
|
||||||
predicate tarFileInfoSanitizer(DataFlow::GuardNode g, Cfg::ControlFlowNode tarInfo, boolean branch) {
|
predicate tarFileInfoSanitizer(DataFlow::GuardNode g, ControlFlowNode tarInfo, boolean branch) {
|
||||||
exists(Cfg::CallNode call, Cfg::AttrNode attr |
|
exists(CallNode call, AttrNode attr |
|
||||||
g = call and
|
g = call and
|
||||||
// We must test the name of the tar info object.
|
// We must test the name of the tar info object.
|
||||||
attr = call.getAnArg() and
|
attr = call.getAnArg() and
|
||||||
@@ -149,9 +148,9 @@ module TarSlip {
|
|||||||
attr.getObject() = tarInfo
|
attr.getObject() = tarInfo
|
||||||
|
|
|
|
||||||
// The assumption that any test that matches %path is a sanitizer might be too broad.
|
// The assumption that any test that matches %path is a sanitizer might be too broad.
|
||||||
call.getAChild*().(Cfg::AttrNode).getName().matches("%path")
|
call.getAChild*().(AttrNode).getName().matches("%path")
|
||||||
or
|
or
|
||||||
call.getAChild*().(Cfg::NameNode).getId().matches("%path")
|
call.getAChild*().(NameNode).getId().matches("%path")
|
||||||
) and
|
) and
|
||||||
branch = false
|
branch = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.Concepts
|
private import semmle.python.Concepts
|
||||||
private import semmle.python.ApiGraphs
|
private import semmle.python.ApiGraphs
|
||||||
@@ -112,7 +111,7 @@ module UrlRedirect {
|
|||||||
// Url redirection is a problem only if the user controls the prefix of the URL.
|
// Url redirection is a problem only if the user controls the prefix of the URL.
|
||||||
// TODO: This is a copy of the taint-sanitizer from the old points-to query, which doesn't
|
// TODO: This is a copy of the taint-sanitizer from the old points-to query, which doesn't
|
||||||
// cover formatting.
|
// cover formatting.
|
||||||
exists(Cfg::BinaryExprNode string_concat | string_concat.getOp() instanceof Add |
|
exists(BinaryExprNode string_concat | string_concat.getOp() instanceof Add |
|
||||||
string_concat.getRight() = this.asCfgNode()
|
string_concat.getRight() = this.asCfgNode()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import python
|
import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
import semmle.python.dataflow.new.DataFlow
|
import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.dataflow.new.internal.DataFlowPrivate
|
private import semmle.python.dataflow.new.internal.DataFlowPrivate
|
||||||
import FlowTest
|
import FlowTest
|
||||||
@@ -24,7 +23,7 @@ import MakeTest<MakeTestSig<MaximalFlowTest>>
|
|||||||
module MaximalFlowsConfig implements DataFlow::ConfigSig {
|
module MaximalFlowsConfig implements DataFlow::ConfigSig {
|
||||||
predicate isSource(DataFlow::Node node) {
|
predicate isSource(DataFlow::Node node) {
|
||||||
exists(node.getLocation().getFile().getRelativePath()) and
|
exists(node.getLocation().getFile().getRelativePath()) and
|
||||||
not node.asCfgNode() instanceof Cfg::CallNode and
|
not node.asCfgNode() instanceof CallNode and
|
||||||
not node.asCfgNode().getNode() instanceof Return and
|
not node.asCfgNode().getNode() instanceof Return and
|
||||||
not node instanceof DataFlow::ParameterNode and
|
not node instanceof DataFlow::ParameterNode and
|
||||||
not node instanceof DataFlow::PostUpdateNode and
|
not node instanceof DataFlow::PostUpdateNode and
|
||||||
@@ -35,9 +34,9 @@ module MaximalFlowsConfig implements DataFlow::ConfigSig {
|
|||||||
|
|
||||||
predicate isSink(DataFlow::Node node) {
|
predicate isSink(DataFlow::Node node) {
|
||||||
exists(node.getLocation().getFile().getRelativePath()) and
|
exists(node.getLocation().getFile().getRelativePath()) and
|
||||||
not any(Cfg::CallNode c).getArg(_) = node.asCfgNode() and
|
not any(CallNode c).getArg(_) = node.asCfgNode() and
|
||||||
not isArgumentNode(node, _, _) and
|
not isArgumentNode(node, _, _) and
|
||||||
not node.asCfgNode().(Cfg::NameNode).getId().matches("SINK%") and
|
not node.asCfgNode().(NameNode).getId().matches("SINK%") and
|
||||||
not DataFlow::localFlowStep(node, _)
|
not DataFlow::localFlowStep(node, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import python
|
import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
import utils.test.dataflow.FlowTest
|
import utils.test.dataflow.FlowTest
|
||||||
import utils.test.dataflow.testConfig
|
import utils.test.dataflow.testConfig
|
||||||
private import semmle.python.dataflow.new.internal.PrintNode
|
private import semmle.python.dataflow.new.internal.PrintNode
|
||||||
@@ -20,7 +19,7 @@ query predicate missingAnnotationOnSink(Location location, string error, string
|
|||||||
TestConfig::isSink(sink) and
|
TestConfig::isSink(sink) and
|
||||||
// note: we only care about `SINK` and not `SINK_F`, so we have to reconstruct manually.
|
// note: we only care about `SINK` and not `SINK_F`, so we have to reconstruct manually.
|
||||||
exists(DataFlow::CallCfgNode call |
|
exists(DataFlow::CallCfgNode call |
|
||||||
call.getFunction().asCfgNode().(Cfg::NameNode).getId() = "SINK" and
|
call.getFunction().asCfgNode().(NameNode).getId() = "SINK" and
|
||||||
(sink = call.getArg(_) or sink = call.getArgByName(_))
|
(sink = call.getArg(_) or sink = call.getArgByName(_))
|
||||||
) and
|
) and
|
||||||
location = sink.getLocation() and
|
location = sink.getLocation() and
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import python
|
import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
import utils.test.dataflow.FlowTest
|
import utils.test.dataflow.FlowTest
|
||||||
import utils.test.dataflow.testTaintConfig
|
import utils.test.dataflow.testTaintConfig
|
||||||
private import semmle.python.dataflow.new.internal.PrintNode
|
private import semmle.python.dataflow.new.internal.PrintNode
|
||||||
@@ -19,7 +18,7 @@ query predicate missingAnnotationOnSink(Location location, string error, string
|
|||||||
exists(DataFlow::Node sink |
|
exists(DataFlow::Node sink |
|
||||||
exists(DataFlow::CallCfgNode call |
|
exists(DataFlow::CallCfgNode call |
|
||||||
// note: we only care about `SINK` and not `SINK_F`, so we have to reconstruct manually.
|
// note: we only care about `SINK` and not `SINK_F`, so we have to reconstruct manually.
|
||||||
call.getFunction().asCfgNode().(Cfg::NameNode).getId() = "SINK" and
|
call.getFunction().asCfgNode().(NameNode).getId() = "SINK" and
|
||||||
(sink = call.getArg(_) or sink = call.getArgByName(_))
|
(sink = call.getArg(_) or sink = call.getArgByName(_))
|
||||||
) and
|
) and
|
||||||
location = sink.getLocation() and
|
location = sink.getLocation() and
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import python
|
import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
import semmle.python.dataflow.new.DataFlow
|
import semmle.python.dataflow.new.DataFlow
|
||||||
import utils.test.InlineExpectationsTest
|
import utils.test.InlineExpectationsTest
|
||||||
private import semmle.python.dataflow.new.internal.PrintNode
|
private import semmle.python.dataflow.new.internal.PrintNode
|
||||||
@@ -50,7 +49,7 @@ private string fromValue(DataFlow::Node fromNode) {
|
|||||||
|
|
||||||
pragma[inline]
|
pragma[inline]
|
||||||
private string fromFunc(DataFlow::ArgumentNode fromNode) {
|
private string fromFunc(DataFlow::ArgumentNode fromNode) {
|
||||||
result = fromNode.getCall().getNode().(Cfg::CallNode).getFunction().getNode().(Name).getId()
|
result = fromNode.getCall().getNode().(CallNode).getFunction().getNode().(Name).getId()
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[inline]
|
pragma[inline]
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
import python
|
import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.dataflow.new.internal.PrintNode
|
private import semmle.python.dataflow.new.internal.PrintNode
|
||||||
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
|
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
|
||||||
private import semmle.python.ApiGraphs
|
private import semmle.python.ApiGraphs
|
||||||
import utils.test.InlineExpectationsTest
|
import utils.test.InlineExpectationsTest
|
||||||
|
|
||||||
signature module UnresolvedCallExpectationsSig {
|
signature module UnresolvedCallExpectationsSig {
|
||||||
predicate unresolvedCall(Cfg::CallNode call);
|
predicate unresolvedCall(CallNode call);
|
||||||
}
|
}
|
||||||
|
|
||||||
module DefaultUnresolvedCallExpectations implements UnresolvedCallExpectationsSig {
|
module DefaultUnresolvedCallExpectations implements UnresolvedCallExpectationsSig {
|
||||||
predicate unresolvedCall(Cfg::CallNode call) {
|
predicate unresolvedCall(CallNode call) {
|
||||||
not exists(DataFlowPrivate::DataFlowCall dfc |
|
not exists(DataFlowPrivate::DataFlowCall dfc |
|
||||||
exists(dfc.getCallable()) and dfc.getNode() = call
|
exists(dfc.getCallable()) and dfc.getNode() = call
|
||||||
) and
|
) and
|
||||||
@@ -25,7 +24,7 @@ module MakeUnresolvedCallExpectations<UnresolvedCallExpectationsSig Impl> {
|
|||||||
|
|
||||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||||
exists(location.getFile().getRelativePath()) and
|
exists(location.getFile().getRelativePath()) and
|
||||||
exists(Cfg::CallNode call | Impl::unresolvedCall(call) and call.injects(_) |
|
exists(CallNode call | Impl::unresolvedCall(call) |
|
||||||
location = call.getLocation() and
|
location = call.getLocation() and
|
||||||
tag = "unresolved_call" and
|
tag = "unresolved_call" and
|
||||||
value = prettyExpr(call.getNode()) and
|
value = prettyExpr(call.getNode()) and
|
||||||
|
|||||||
@@ -21,12 +21,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
import semmle.python.dataflow.new.DataFlow
|
import semmle.python.dataflow.new.DataFlow
|
||||||
|
|
||||||
module TestConfig implements DataFlow::ConfigSig {
|
module TestConfig implements DataFlow::ConfigSig {
|
||||||
predicate isSource(DataFlow::Node node) {
|
predicate isSource(DataFlow::Node node) {
|
||||||
node.(DataFlow::CfgNode).getNode().(Cfg::NameNode).getId() = "SOURCE"
|
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "SOURCE"
|
||||||
or
|
or
|
||||||
node.(DataFlow::CfgNode).getNode().getNode().(StringLiteral).getS() = "source"
|
node.(DataFlow::CfgNode).getNode().getNode().(StringLiteral).getS() = "source"
|
||||||
or
|
or
|
||||||
@@ -38,7 +37,7 @@ module TestConfig implements DataFlow::ConfigSig {
|
|||||||
|
|
||||||
predicate isSink(DataFlow::Node node) {
|
predicate isSink(DataFlow::Node node) {
|
||||||
exists(DataFlow::CallCfgNode call |
|
exists(DataFlow::CallCfgNode call |
|
||||||
call.getFunction().asCfgNode().(Cfg::NameNode).getId() in ["SINK", "SINK_F"] and
|
call.getFunction().asCfgNode().(NameNode).getId() in ["SINK", "SINK_F"] and
|
||||||
(node = call.getArg(_) or node = call.getArgByName(_)) and
|
(node = call.getArg(_) or node = call.getArgByName(_)) and
|
||||||
not node = call.getArgByName("not_present_at_runtime")
|
not node = call.getArgByName("not_present_at_runtime")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,13 +21,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
import semmle.python.dataflow.new.DataFlow
|
import semmle.python.dataflow.new.DataFlow
|
||||||
import semmle.python.dataflow.new.TaintTracking
|
import semmle.python.dataflow.new.TaintTracking
|
||||||
|
|
||||||
module TestConfig implements DataFlow::ConfigSig {
|
module TestConfig implements DataFlow::ConfigSig {
|
||||||
predicate isSource(DataFlow::Node node) {
|
predicate isSource(DataFlow::Node node) {
|
||||||
node.(DataFlow::CfgNode).getNode().(Cfg::NameNode).getId() = "SOURCE"
|
node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "SOURCE"
|
||||||
or
|
or
|
||||||
node.(DataFlow::CfgNode).getNode().getNode().(StringLiteral).getS() = "source"
|
node.(DataFlow::CfgNode).getNode().getNode().(StringLiteral).getS() = "source"
|
||||||
or
|
or
|
||||||
@@ -38,8 +37,8 @@ module TestConfig implements DataFlow::ConfigSig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
predicate isSink(DataFlow::Node node) {
|
predicate isSink(DataFlow::Node node) {
|
||||||
exists(Cfg::CallNode call |
|
exists(CallNode call |
|
||||||
call.getFunction().(Cfg::NameNode).getId() in ["SINK", "SINK_F"] and
|
call.getFunction().(NameNode).getId() in ["SINK", "SINK_F"] and
|
||||||
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
|
node.(DataFlow::CfgNode).getNode() = call.getAnArg()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,6 @@
|
|||||||
|
|
||||||
import python
|
import python
|
||||||
private import semmle.python.ApiGraphs
|
private import semmle.python.ApiGraphs
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
private import semmle.python.Flow as Flow
|
|
||||||
|
|
||||||
API::Node iter() { result = API::builtin("iter") }
|
API::Node iter() { result = API::builtin("iter") }
|
||||||
|
|
||||||
@@ -21,17 +19,17 @@ API::Node next() { result = API::builtin("next") }
|
|||||||
|
|
||||||
API::Node stopIteration() { result = API::builtin("StopIteration") }
|
API::Node stopIteration() { result = API::builtin("StopIteration") }
|
||||||
|
|
||||||
predicate call_to_iter(Flow::CallNode call, EssaVariable sequence) {
|
predicate call_to_iter(CallNode call, EssaVariable sequence) {
|
||||||
call.getNode() = iter().getACall().asCfgNode().(Cfg::CallNode).getNode() and
|
call = iter().getACall().asCfgNode() and
|
||||||
call.getArg(0) = sequence.getAUse()
|
call.getArg(0) = sequence.getAUse()
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate call_to_next(Flow::CallNode call, Flow::ControlFlowNode iter) {
|
predicate call_to_next(CallNode call, ControlFlowNode iter) {
|
||||||
call.getNode() = next().getACall().asCfgNode().(Cfg::CallNode).getNode() and
|
call = next().getACall().asCfgNode() and
|
||||||
call.getArg(0) = iter
|
call.getArg(0) = iter
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate call_to_next_has_default(Flow::CallNode call) {
|
predicate call_to_next_has_default(CallNode call) {
|
||||||
exists(call.getArg(1)) or exists(call.getArgByName("default"))
|
exists(call.getArg(1)) or exists(call.getArgByName("default"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,14 +49,14 @@ predicate iter_not_exhausted(EssaVariable iterator) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate stop_iteration_handled(Flow::CallNode call) {
|
predicate stop_iteration_handled(CallNode call) {
|
||||||
exists(Try t |
|
exists(Try t |
|
||||||
t.containsInScope(call.getNode()) and
|
t.containsInScope(call.getNode()) and
|
||||||
t.getAHandler().getType() = stopIteration().getAValueReachableFromSource().asExpr()
|
t.getAHandler().getType() = stopIteration().getAValueReachableFromSource().asExpr()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
from Flow::CallNode call
|
from CallNode call
|
||||||
where
|
where
|
||||||
call_to_next(call, _) and
|
call_to_next(call, _) and
|
||||||
not call_to_next_has_default(call) and
|
not call_to_next_has_default(call) and
|
||||||
|
|||||||
@@ -11,9 +11,8 @@
|
|||||||
|
|
||||||
import python
|
import python
|
||||||
private import semmle.python.ApiGraphs
|
private import semmle.python.ApiGraphs
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
|
|
||||||
from Cfg::CallNode call
|
from CallNode call
|
||||||
where
|
where
|
||||||
major_version() = 2 and
|
major_version() = 2 and
|
||||||
call = API::builtin("apply").getACall().asCfgNode()
|
call = API::builtin("apply").getACall().asCfgNode()
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
import python
|
import python
|
||||||
import semmle.python.dataflow.new.DataFlow
|
import semmle.python.dataflow.new.DataFlow
|
||||||
import semmle.python.dataflow.new.internal.DataFlowDispatch
|
import semmle.python.dataflow.new.internal.DataFlowDispatch
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
import codeql.util.Option
|
import codeql.util.Option
|
||||||
|
|
||||||
/** Holds if `base` is overridden by `sub` */
|
/** Holds if `base` is overridden by `sub` */
|
||||||
@@ -144,7 +143,7 @@ predicate ignore(Function f) {
|
|||||||
|
|
||||||
/** Gets a function that `call` may resolve to. */
|
/** Gets a function that `call` may resolve to. */
|
||||||
Function resolveCall(Call call) {
|
Function resolveCall(Call call) {
|
||||||
exists(DataFlowCall dfc | call = dfc.getNode().(Cfg::CallNode).getNode() |
|
exists(DataFlowCall dfc | call = dfc.getNode().(CallNode).getNode() |
|
||||||
result = viableCallable(dfc).(DataFlowFunction).getScope()
|
result = viableCallable(dfc).(DataFlowFunction).getScope()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import python
|
|||||||
import semmle.python.dataflow.new.internal.DataFlowDispatch
|
import semmle.python.dataflow.new.internal.DataFlowDispatch
|
||||||
import semmle.python.ApiGraphs
|
import semmle.python.ApiGraphs
|
||||||
private import semmle.python.dataflow.new.internal.ReExposedInstance
|
private import semmle.python.dataflow.new.internal.ReExposedInstance
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
|
|
||||||
/** A CFG node where a file is opened. */
|
/** A CFG node where a file is opened. */
|
||||||
abstract class FileOpenSource extends DataFlow::CfgNode { }
|
abstract class FileOpenSource extends DataFlow::CfgNode { }
|
||||||
@@ -82,14 +81,12 @@ abstract class FileClose extends DataFlow::CfgNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate bbSuccessor(Cfg::BasicBlock src, Cfg::BasicBlock sink) {
|
private predicate bbSuccessor(BasicBlock src, BasicBlock sink) { sink = src.getASuccessor() }
|
||||||
sink = src.getASuccessor()
|
|
||||||
}
|
|
||||||
|
|
||||||
private predicate bbReachableStrict(Cfg::BasicBlock src, Cfg::BasicBlock sink) =
|
private predicate bbReachableStrict(BasicBlock src, BasicBlock sink) =
|
||||||
fastTC(bbSuccessor/2)(src, sink)
|
fastTC(bbSuccessor/2)(src, sink)
|
||||||
|
|
||||||
private predicate bbReachableRefl(Cfg::BasicBlock src, Cfg::BasicBlock sink) {
|
private predicate bbReachableRefl(BasicBlock src, BasicBlock sink) {
|
||||||
bbReachableStrict(src, sink) or src = sink
|
bbReachableStrict(src, sink) or src = sink
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ private import semmle.python.dataflow.new.RemoteFlowSources
|
|||||||
private import semmle.python.ApiGraphs
|
private import semmle.python.ApiGraphs
|
||||||
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
|
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
|
||||||
private import semmle.python.dataflow.new.internal.TaintTrackingPrivate as TaintTrackingPrivate
|
private import semmle.python.dataflow.new.internal.TaintTrackingPrivate as TaintTrackingPrivate
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An external API that is considered "safe" from a security perspective.
|
* An external API that is considered "safe" from a security perspective.
|
||||||
@@ -72,7 +71,7 @@ string apiNodeToStringRepr(API::Node node) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate resolvedCall(Cfg::CallNode call) {
|
predicate resolvedCall(CallNode call) {
|
||||||
DataFlowPrivate::resolveCall(call, _, _) or
|
DataFlowPrivate::resolveCall(call, _, _) or
|
||||||
DataFlowPrivate::resolveClassCall(call, _)
|
DataFlowPrivate::resolveClassCall(call, _)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
import python
|
import python
|
||||||
import semmle.python.dataflow.new.DataFlow
|
import semmle.python.dataflow.new.DataFlow
|
||||||
import semmle.python.ApiGraphs
|
import semmle.python.ApiGraphs
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Jinja 2 Docs:
|
* Jinja 2 Docs:
|
||||||
@@ -37,8 +36,8 @@ private API::Node jinja2EnvironmentOrTemplate() {
|
|||||||
from API::CallNode call
|
from API::CallNode call
|
||||||
where
|
where
|
||||||
call = jinja2EnvironmentOrTemplate().getACall() and
|
call = jinja2EnvironmentOrTemplate().getACall() and
|
||||||
not exists(call.asCfgNode().(Cfg::CallNode).getNode().getStarargs()) and
|
not exists(call.asCfgNode().(CallNode).getNode().getStarargs()) and
|
||||||
not exists(call.asCfgNode().(Cfg::CallNode).getNode().getKwargs()) and
|
not exists(call.asCfgNode().(CallNode).getNode().getKwargs()) and
|
||||||
(
|
(
|
||||||
not exists(call.getArgByName("autoescape"))
|
not exists(call.getArgByName("autoescape"))
|
||||||
or
|
or
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.ApiGraphs
|
private import semmle.python.ApiGraphs
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
import TlsLibraryModel
|
import TlsLibraryModel
|
||||||
|
|
||||||
class PyOpenSslContextCreation extends ContextCreation, DataFlow::CallCfgNode {
|
class PyOpenSslContextCreation extends ContextCreation, DataFlow::CallCfgNode {
|
||||||
@@ -38,10 +37,10 @@ class ConnectionCall extends ConnectionCreation, DataFlow::CallCfgNode {
|
|||||||
// This cannot be used to unrestrict,
|
// This cannot be used to unrestrict,
|
||||||
// see https://www.pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_options
|
// see https://www.pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_options
|
||||||
class SetOptionsCall extends ProtocolRestriction, DataFlow::CallCfgNode {
|
class SetOptionsCall extends ProtocolRestriction, DataFlow::CallCfgNode {
|
||||||
SetOptionsCall() { node.getFunction().(Cfg::AttrNode).getName() = "set_options" }
|
SetOptionsCall() { node.getFunction().(AttrNode).getName() = "set_options" }
|
||||||
|
|
||||||
override DataFlow::CfgNode getContext() {
|
override DataFlow::CfgNode getContext() {
|
||||||
result.getNode() = node.getFunction().(Cfg::AttrNode).getObject()
|
result.getNode() = node.getFunction().(AttrNode).getObject()
|
||||||
}
|
}
|
||||||
|
|
||||||
override ProtocolVersion getRestriction() {
|
override ProtocolVersion getRestriction() {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.ApiGraphs
|
private import semmle.python.ApiGraphs
|
||||||
private import semmle.python.controlflow.internal.Cfg as Cfg
|
|
||||||
import TlsLibraryModel
|
import TlsLibraryModel
|
||||||
|
|
||||||
class SslContextCreation extends ContextCreation, DataFlow::CallCfgNode {
|
class SslContextCreation extends ContextCreation, DataFlow::CallCfgNode {
|
||||||
@@ -54,7 +53,7 @@ class OptionsAugOr extends ProtocolRestriction, DataFlow::CfgNode {
|
|||||||
ProtocolVersion restriction;
|
ProtocolVersion restriction;
|
||||||
|
|
||||||
OptionsAugOr() {
|
OptionsAugOr() {
|
||||||
exists(AugAssign aa, Cfg::AttrNode attr, Expr flag |
|
exists(AugAssign aa, AttrNode attr, Expr flag |
|
||||||
aa.getOperation().getOp() instanceof BitOr and
|
aa.getOperation().getOp() instanceof BitOr and
|
||||||
aa.getTarget() = attr.getNode() and
|
aa.getTarget() = attr.getNode() and
|
||||||
attr.getName() = "options" and
|
attr.getName() = "options" and
|
||||||
@@ -81,7 +80,7 @@ class OptionsAugAndNot extends ProtocolUnrestriction, DataFlow::CfgNode {
|
|||||||
ProtocolVersion restriction;
|
ProtocolVersion restriction;
|
||||||
|
|
||||||
OptionsAugAndNot() {
|
OptionsAugAndNot() {
|
||||||
exists(AugAssign aa, Cfg::AttrNode attr, Expr flag, UnaryExpr notFlag |
|
exists(AugAssign aa, AttrNode attr, Expr flag, UnaryExpr notFlag |
|
||||||
aa.getOperation().getOp() instanceof BitAnd and
|
aa.getOperation().getOp() instanceof BitAnd and
|
||||||
aa.getTarget() = attr.getNode() and
|
aa.getTarget() = attr.getNode() and
|
||||||
attr.getName() = "options" and
|
attr.getName() = "options" and
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user